diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml index 77b598ad3c..f02f99e9b5 100644 --- a/.rubocop_manual_todo.yml +++ b/.rubocop_manual_todo.yml @@ -33,7 +33,6 @@ Layout/LineLength: - app/controllers/admin/inventory_items_controller.rb - app/controllers/admin/manager_invitations_controller.rb - app/controllers/admin/product_import_controller.rb - - app/controllers/admin/proxy_orders_controller.rb - app/controllers/admin/schedules_controller.rb - app/controllers/admin/subscriptions_controller.rb - app/controllers/admin/variant_overrides_controller.rb @@ -89,7 +88,6 @@ Layout/LineLength: - app/models/spree/tax_rate_decorator.rb - app/models/spree/taxon_decorator.rb - app/models/spree/user.rb - - app/models/spree/variant_decorator.rb - app/models/subscription.rb - app/models/variant_override.rb - app/models/variant_override_set.rb @@ -98,7 +96,6 @@ Layout/LineLength: - app/services/embedded_page_service.rb - app/services/order_cycle_form.rb - app/services/order_factory.rb - - app/services/subscriptions_count.rb - app/services/variants_stock_levels.rb - engines/web/app/helpers/web/cookies_policy_helper.rb - lib/discourse/single_sign_on.rb @@ -158,7 +155,6 @@ Layout/LineLength: - spec/controllers/spree/admin/orders/customer_details_controller_spec.rb - spec/controllers/spree/admin/orders_controller_spec.rb - spec/controllers/spree/admin/payment_methods_controller_spec.rb - - spec/controllers/spree/admin/payments_controller_spec.rb - spec/controllers/spree/admin/products_controller_spec.rb - spec/controllers/spree/admin/reports_controller_spec.rb - spec/controllers/spree/admin/variants_controller_spec.rb @@ -183,7 +179,6 @@ Layout/LineLength: - spec/features/admin/image_settings_spec.rb - spec/features/admin/multilingual_spec.rb - spec/features/admin/order_cycles_spec.rb - - spec/features/admin/orders_spec.rb - spec/features/admin/overview_spec.rb - spec/features/admin/payment_method_spec.rb - spec/features/admin/product_import_spec.rb @@ -239,10 +234,7 @@ Layout/LineLength: - spec/lib/open_food_network/packing_report_spec.rb - spec/lib/open_food_network/permissions_spec.rb - spec/lib/open_food_network/products_and_inventory_report_spec.rb - - spec/lib/open_food_network/proxy_order_syncer_spec.rb - spec/lib/open_food_network/scope_variant_to_hub_spec.rb - - spec/lib/open_food_network/subscription_payment_updater_spec.rb - - spec/lib/open_food_network/subscription_summarizer_spec.rb - spec/lib/open_food_network/tag_rule_applicator_spec.rb - spec/lib/open_food_network/users_and_enterprises_report_spec.rb - spec/lib/open_food_network/xero_invoices_report_spec.rb @@ -317,10 +309,6 @@ Layout/LineLength: - 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 - - spec/services/subscription_form_spec.rb - - spec/services/subscription_validator_spec.rb - - spec/services/subscription_variants_service_spec.rb - spec/spec_helper.rb - spec/support/cancan_helper.rb - spec/support/delayed_job_helper.rb @@ -386,7 +374,6 @@ Metrics/AbcSize: - app/helpers/spree/admin/base_helper.rb - app/helpers/spree/admin/zones_helper.rb - app/helpers/spree/orders_helper.rb - - app/mailers/producer_mailer.rb - app/models/calculator/flat_percent_per_item.rb - app/models/column_preference.rb - app/models/enterprise.rb @@ -411,7 +398,7 @@ Metrics/AbcSize: - app/services/cart_service.rb - app/services/create_order_cycle.rb - app/services/order_syncer.rb - - app/services/subscription_validator.rb + - engines/order_management/app/services/order_management/subscriptions/validator.rb - lib/active_merchant/billing/gateways/stripe_decorator.rb - lib/active_merchant/billing/gateways/stripe_payment_intents.rb - lib/discourse/single_sign_on.rb @@ -477,7 +464,6 @@ Metrics/BlockLength: - spec/factories/shipping_method_factory.rb - spec/factories/subscription_factory.rb - spec/factories/variant_factory.rb - - spec/features/admin/orders_spec.rb - spec/features/consumer/shopping/embedded_shopfronts_spec.rb - spec/lib/open_food_network/group_buy_report_spec.rb - spec/models/tag_rule/discount_order_spec.rb @@ -583,7 +569,6 @@ Metrics/MethodLength: - app/helpers/spree/admin/navigation_helper.rb - app/helpers/spree/admin/base_helper.rb - app/jobs/subscription_placement_job.rb - - app/mailers/producer_mailer.rb - app/models/column_preference.rb - app/models/enterprise.rb - app/models/enterprise_relationship.rb @@ -686,6 +671,12 @@ Metrics/ModuleLength: - app/helpers/injection_helper.rb - app/helpers/spree/admin/navigation_helper.rb - app/helpers/spree/admin/base_helper.rb + - engines/order_management/spec/services/order_management/subscriptions/estimator_spec.rb + - engines/order_management/spec/services/order_management/subscriptions/form_spec.rb + - engines/order_management/spec/services/order_management/subscriptions/proxy_order_syncer_spec.rb + - engines/order_management/spec/services/order_management/subscriptions/summarizer_spec.rb + - engines/order_management/spec/services/order_management/subscriptions/validator_spec.rb + - engines/order_management/spec/services/order_management/subscriptions/variants_list_spec.rb - lib/open_food_network/column_preference_defaults.rb - spec/controllers/admin/enterprises_controller_spec.rb - spec/controllers/admin/order_cycles_controller_spec.rb @@ -701,9 +692,7 @@ Metrics/ModuleLength: - spec/lib/open_food_network/order_grouper_spec.rb - spec/lib/open_food_network/permissions_spec.rb - spec/lib/open_food_network/products_and_inventory_report_spec.rb - - spec/lib/open_food_network/proxy_order_syncer_spec.rb - spec/lib/open_food_network/scope_variant_to_hub_spec.rb - - spec/lib/open_food_network/subscription_payment_updater_spec.rb - spec/lib/open_food_network/tag_rule_applicator_spec.rb - spec/lib/open_food_network/users_and_enterprises_report_spec.rb - spec/models/spree/ability_spec.rb diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 479f96c533..1c482dbc82 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -107,7 +107,6 @@ Lint/DuplicateHashKey: Lint/DuplicateMethods: Exclude: - 'lib/discourse/single_sign_on.rb' - - 'lib/open_food_network/subscription_summary.rb' # Offense count: 10 Lint/IneffectiveAccessModifier: @@ -209,7 +208,7 @@ Naming/MemoizedInstanceVariableName: Naming/MethodParameterName: Exclude: - 'app/helpers/spree/base_helper_decorator.rb' - - 'app/services/subscription_validator.rb' + - 'engines/order_management/app/services/order_management/subscriptions/validator.rb' - 'lib/open_food_network/reports/bulk_coop_report.rb' - 'lib/open_food_network/xero_invoices_report.rb' - 'spec/lib/open_food_network/reports/report_spec.rb' @@ -224,7 +223,6 @@ Naming/MethodParameterName: Naming/PredicateName: Exclude: - 'spec/**/*' - - 'app/mailers/producer_mailer.rb' - 'app/models/enterprise.rb' - 'app/models/enterprise_relationship.rb' - 'app/models/order_cycle.rb' @@ -861,7 +859,6 @@ Style/FrozenStringLiteralComment: - 'app/jobs/subscription_placement_job.rb' - 'app/jobs/welcome_enterprise_job.rb' - 'app/mailers/enterprise_mailer.rb' - - 'app/mailers/producer_mailer.rb' - 'app/mailers/spree/base_mailer_decorator.rb' - 'app/mailers/spree/order_mailer_decorator.rb' - 'app/mailers/spree/user_mailer.rb' @@ -1078,11 +1075,6 @@ Style/FrozenStringLiteralComment: - 'app/services/reset_order_service.rb' - 'app/services/restart_checkout.rb' - 'app/services/search_orders.rb' - - 'app/services/subscription_estimator.rb' - - 'app/services/subscription_form.rb' - - 'app/services/subscription_validator.rb' - - 'app/services/subscription_variants_service.rb' - - 'app/services/subscriptions_count.rb' - 'app/services/tax_rate_finder.rb' - 'app/services/upload_sanitizer.rb' - 'app/services/variant_deleter.rb' @@ -1090,7 +1082,6 @@ Style/FrozenStringLiteralComment: - 'app/validators/date_time_string_validator.rb' - 'app/validators/distributors_validator.rb' - 'app/validators/integer_array_validator.rb' - - 'app/views/spree/admin/taxons/search.rabl' - 'config.ru' - 'engines/order_management/app/controllers/order_management/application_controller.rb' - 'engines/order_management/app/services/order_management/reports/enterprise_fee_summary/authorizer.rb' @@ -1121,6 +1112,7 @@ Style/FrozenStringLiteralComment: - 'engines/order_management/lib/order_management/engine.rb' - 'engines/order_management/lib/order_management/version.rb' - 'engines/order_management/order_management.gemspec' + - 'engines/order_management/spec/performance/order_management/subscriptions/proxy_order_syncer_spec.rb' - 'engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/authorizer_spec.rb' - 'engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/parameters_spec.rb' - 'engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/permissions_spec.rb' @@ -1177,7 +1169,6 @@ Style/FrozenStringLiteralComment: - 'lib/open_food_network/products_and_inventory_report.rb' - 'lib/open_food_network/products_and_inventory_report_base.rb' - 'lib/open_food_network/property_merge.rb' - - 'lib/open_food_network/proxy_order_syncer.rb' - 'lib/open_food_network/rack_request_blocker.rb' - 'lib/open_food_network/referer_parser.rb' - 'lib/open_food_network/reports/bulk_coop_allocation_report.rb' @@ -1194,8 +1185,6 @@ Style/FrozenStringLiteralComment: - 'lib/open_food_network/scope_variants_for_search.rb' - 'lib/open_food_network/spree_api_key_loader.rb' - 'lib/open_food_network/subscription_payment_updater.rb' - - 'lib/open_food_network/subscription_summarizer.rb' - - 'lib/open_food_network/subscription_summary.rb' - 'lib/open_food_network/tag_rule_applicator.rb' - 'lib/open_food_network/user_balance_calculator.rb' - 'lib/open_food_network/users_and_enterprises_report.rb' @@ -1435,7 +1424,6 @@ Style/FrozenStringLiteralComment: - 'spec/lib/open_food_network/permissions_spec.rb' - 'spec/lib/open_food_network/products_and_inventory_report_spec.rb' - 'spec/lib/open_food_network/property_merge_spec.rb' - - 'spec/lib/open_food_network/proxy_order_syncer_spec.rb' - 'spec/lib/open_food_network/referer_parser_spec.rb' - 'spec/lib/open_food_network/reports/report_spec.rb' - 'spec/lib/open_food_network/reports/row_spec.rb' @@ -1444,8 +1432,6 @@ Style/FrozenStringLiteralComment: - 'spec/lib/open_food_network/scope_variant_to_hub_spec.rb' - 'spec/lib/open_food_network/scope_variants_to_search_spec.rb' - 'spec/lib/open_food_network/subscription_payment_updater_spec.rb' - - 'spec/lib/open_food_network/subscription_summarizer_spec.rb' - - 'spec/lib/open_food_network/subscription_summary_spec.rb' - 'spec/lib/open_food_network/tag_rule_applicator_spec.rb' - 'spec/lib/open_food_network/user_balance_calculator_spec.rb' - 'spec/lib/open_food_network/users_and_enterprises_report_spec.rb' @@ -1529,7 +1515,6 @@ Style/FrozenStringLiteralComment: - 'spec/models/variant_override_spec.rb' - 'spec/performance/injection_helper_spec.rb' - 'spec/performance/orders_controller_spec.rb' - - 'spec/performance/proxy_order_syncer_spec.rb' - 'spec/performance/shop_controller_spec.rb' - 'spec/requests/checkout/failed_checkout_spec.rb' - 'spec/requests/checkout/paypal_spec.rb' @@ -1581,11 +1566,6 @@ Style/FrozenStringLiteralComment: - 'spec/services/reset_order_service_spec.rb' - 'spec/services/restart_checkout_spec.rb' - 'spec/services/search_orders_spec.rb' - - 'spec/services/subscription_estimator_spec.rb' - - 'spec/services/subscription_form_spec.rb' - - 'spec/services/subscription_validator_spec.rb' - - 'spec/services/subscription_variants_service_spec.rb' - - 'spec/services/subscriptions_count_spec.rb' - 'spec/services/tax_rate_finder_spec.rb' - 'spec/services/upload_sanitizer_spec.rb' - 'spec/services/variants_stock_levels_spec.rb' @@ -1778,7 +1758,6 @@ Style/Send: - 'spec/lib/open_food_network/products_and_inventory_report_spec.rb' - 'spec/lib/open_food_network/sales_tax_report_spec.rb' - 'spec/lib/open_food_network/subscription_payment_updater_spec.rb' - - 'spec/lib/open_food_network/subscription_summarizer_spec.rb' - 'spec/lib/open_food_network/tag_rule_applicator_spec.rb' - 'spec/lib/open_food_network/xero_invoices_report_spec.rb' - 'spec/lib/stripe/webhook_handler_spec.rb' diff --git a/DOCKER.md b/DOCKER.md index 994f582fde..3df0f7d345 100644 --- a/DOCKER.md +++ b/DOCKER.md @@ -35,13 +35,20 @@ Download the Docker images and build the containers: $ docker-compose build ``` -Run the app with all the required containers: +Setup the database and seed it with sample data: +```sh +$ docker-compose run web bundle exec rake db:reset +$ docker-compose run web bundle exec rake db:test:prepare +$ docker-compose run web bundle exec rake ofn:sample_data +``` + +Finally, run the app with all the required containers: ```sh $ docker-compose up ``` -This command will setup the database and seed it with sample data. The default admin user is 'ofn@example.com' with 'ofn123' password. +The default admin user is 'ofn@example.com' with 'ofn123' password. Check the app in the browser at `http://localhost:3000`. You will then get the trace of the containers in the terminal. You can stop the containers using Ctrl-C in the terminal. diff --git a/Dockerfile b/Dockerfile index fa7718f2ee..93caceecc1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ ENV BUNDLE_PATH /bundles WORKDIR /usr/src/app COPY .ruby-version . -# Rbenv & Ruby part +# Install Rbenv & Ruby RUN git clone https://github.com/rbenv/rbenv.git ${RBENV_ROOT} && \ git clone https://github.com/rbenv/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build && \ ${RBENV_ROOT}/plugins/ruby-build/install.sh && \ @@ -21,7 +21,7 @@ RUN git clone https://github.com/rbenv/rbenv.git ${RBENV_ROOT} && \ rbenv global $(cat .ruby-version) && \ gem install bundler --version=1.17.2 -# Postgres +# Install Postgres RUN sh -c "echo 'deb https://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main' > /etc/apt/sources.list.d/pgdg.list" && \ wget --quiet -O - https://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | apt-key add - && \ apt-get update && \ @@ -38,4 +38,6 @@ RUN wget https://chromedriver.storage.googleapis.com/2.41/chromedriver_linux64.z unzip chromedriver_linux64.zip -d /usr/bin && \ chmod u+x /usr/bin/chromedriver +# Copy code and install app dependencies COPY . /usr/src/app/ +RUN bundle install diff --git a/GETTING_STARTED.md b/GETTING_STARTED.md index c372d152d7..84b38663aa 100644 --- a/GETTING_STARTED.md +++ b/GETTING_STARTED.md @@ -118,7 +118,7 @@ $ createdb open_food_network_test --owner=ofn If these commands succeed, you should be able to [continue the setup process](#get-it-running). [developer-wiki]: https://github.com/openfoodfoundation/openfoodnetwork/wiki -[sierra]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup%3A-macOS-%28Sierra%2C-HighSierra-and-Mojave%29 +[sierra]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup%3A-macOS-%28Sierra%2C-HighSierra%2C-Mojave-and-Catalina%29 [el-capitan]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup:-OS-X-(El-Capitan) [ubuntu]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup:-Ubuntu [wiki]: https://github.com/openfoodfoundation/openfoodnetwork/wiki diff --git a/Gemfile b/Gemfile index 5a13e1ff50..e3621237fc 100644 --- a/Gemfile +++ b/Gemfile @@ -9,7 +9,6 @@ gem 'rails-i18n', '~> 4.0' gem 'rails_safe_tasks', '~> 1.0' gem "activerecord-import" -gem 'nokogiri', '~> 1.6.8.1' gem "catalog", path: "./engines/catalog" gem "order_management", path: "./engines/order_management" @@ -44,10 +43,6 @@ gem 'daemons' gem 'delayed_job_active_record' gem 'delayed_job_web' -# Fix bug in simple_form preventing collection_check_boxes usage within form_for block -# When merged, revert to upstream gem -# gem 'simple_form', github: 'RohanM/simple_form' - # Spree's default pagination gem (locked to the current version used by Spree) # We use it's methods in OFN code as well, so this is a direct dependency gem 'kaminari', '~> 0.14.1' @@ -58,7 +53,6 @@ gem 'aws-sdk' gem 'bugsnag' gem 'db2fog' gem 'haml' -gem 'rabl' gem 'redcarpet' gem 'sass' gem 'sass-rails' @@ -101,7 +95,7 @@ gem 'test-unit', '~> 3.3' gem 'coffee-rails', '~> 4.0.0' gem 'compass-rails' -gem 'mini_racer', '0.2.9' +gem 'mini_racer', '0.2.10' gem 'uglifier', '>= 1.0.3' @@ -120,16 +114,17 @@ gem 'ofn-qz', github: 'openfoodfoundation/ofn-qz', branch: 'ofn-rails-4' group :production, :staging do gem 'ddtrace' + gem 'unicorn-worker-killer' end group :test, :development do # Pretty printed test output gem 'atomic' gem 'awesome_print' - gem 'capybara', '>= 2.18.0' # 3.0 requires nokogiri 1.8 + gem 'capybara', '>= 2.18.0' # 3.0 requires rack 1.6 that only works with Rails 4.2 gem 'database_cleaner', require: false gem "factory_bot_rails", '4.10.0', require: false - gem 'fuubar', '~> 2.4.1' + gem 'fuubar', '~> 2.5.0' gem 'json_spec', '~> 1.1.4' gem 'knapsack' gem 'letter_opener', '>= 1.4.1' diff --git a/Gemfile.lock b/Gemfile.lock index 4ea04c16c5..f984accedf 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -31,7 +31,6 @@ GIT awesome_nested_set (~> 3.0.0.rc.1) aws-sdk (= 1.11.1) cancan (~> 1.6.10) - deface (>= 1.0.0.rc3) ffaker (~> 1.16) highline (= 1.6.18) httparty (~> 0.11) @@ -169,7 +168,6 @@ GEM coffee-script-source execjs coffee-script-source (1.12.2) - colorize (0.8.1) combine_pdf (1.0.16) ruby-rc4 (>= 0.1.5) compass (1.0.3) @@ -200,14 +198,9 @@ GEM activerecord (>= 3.2.0, < 5.0) fog (~> 1.0) rails (>= 3.2.0, < 5.0) - ddtrace (0.34.0) + ddtrace (0.34.2) msgpack debugger-linecache (1.2.0) - deface (1.0.2) - colorize (>= 0.5.8) - nokogiri (~> 1.6.0) - polyglot - rails (>= 3.1) delayed_job (4.1.8) activesupport (>= 3.0, < 6.1) delayed_job_active_record (4.1.4) @@ -406,6 +399,8 @@ GEM rspec-core (~> 3.0) ruby-progressbar (~> 1.4) geocoder (1.5.2) + get_process_mem (0.2.5) + ffi (~> 1.0) gmaps4rails (2.1.2) haml (5.1.2) temple (>= 0.8.0) @@ -452,9 +447,9 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2019.1009) mini_mime (1.0.2) - mini_portile2 (2.1.0) - mini_racer (0.2.9) - libv8 (>= 6.9.411) + mini_portile2 (2.4.0) + mini_racer (0.2.10) + libv8 (> 7.3) minitest (4.7.5) momentjs-rails (2.20.1) railties (>= 3.1) @@ -465,15 +460,15 @@ GEM multi_xml (0.6.0) multipart-post (2.1.1) newrelic_rpm (3.18.1.330) - nokogiri (1.6.8.1) - mini_portile2 (~> 2.1.0) + nokogiri (1.10.9) + mini_portile2 (~> 2.4.0) oauth2 (1.4.4) faraday (>= 0.8, < 2.0) jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) rack (>= 1.2, < 3) - oj (3.10.5) + oj (3.10.6) optimist (3.0.0) orm_adapter (0.5.0) paper_trail (5.2.3) @@ -488,7 +483,7 @@ GEM parallel (1.19.1) paranoia (2.4.2) activerecord (>= 4.0, < 6.1) - parser (2.7.0.5) + parser (2.7.1.0) ast (~> 2.4.0) paypal-sdk-core (0.2.10) multi_json (~> 1.0) @@ -594,7 +589,7 @@ GEM rexml ruby-progressbar (~> 1.7) unicode-display_width (>= 1.4.0, < 2.0) - rubocop-rails (2.5.0) + rubocop-rails (2.5.2) activesupport rack (>= 1.1) rubocop (>= 0.72.0) @@ -660,6 +655,9 @@ GEM unicorn-rails (2.2.1) rack unicorn + unicorn-worker-killer (0.4.4) + get_process_mem (~> 0) + unicorn (>= 4, < 6) uuidtools (2.1.5) warden (1.2.7) rack (>= 1.0) @@ -739,10 +737,9 @@ DEPENDENCIES kaminari (~> 0.14.1) knapsack letter_opener (>= 1.4.1) - mini_racer (= 0.2.9) + mini_racer (= 0.2.10) momentjs-rails newrelic_rpm (~> 3.0) - nokogiri (~> 1.6.8.1) oauth2 (~> 1.4.4) ofn-qz! oj @@ -751,7 +748,6 @@ DEPENDENCIES paperclip (~> 3.4.1) pg (~> 0.21.0) pry-byebug (>= 3.4.3) - rabl rack-mini-profiler (< 3.0.0) rack-rewrite rack-ssl @@ -784,6 +780,7 @@ DEPENDENCIES uglifier (>= 1.0.3) unicorn unicorn-rails + unicorn-worker-killer web! webdrivers webmock diff --git a/app/assets/javascripts/admin/index_utils/services/paged_fetcher.js.coffee b/app/assets/javascripts/admin/index_utils/services/paged_fetcher.js.coffee index 82487996ae..96836ef9cc 100644 --- a/app/assets/javascripts/admin/index_utils/services/paged_fetcher.js.coffee +++ b/app/assets/javascripts/admin/index_utils/services/paged_fetcher.js.coffee @@ -2,19 +2,24 @@ angular.module("admin.indexUtils").factory "PagedFetcher", (dataFetcher) -> new class PagedFetcher # Given a URL like http://example.com/foo?page=::page::&per_page=20 # And the response includes an attribute pages with the number of pages to fetch - # Fetch each page async, and call the processData callback with the resulting data - fetch: (url, processData, onLastPageComplete) -> - dataFetcher(@urlForPage(url, 1)).then (data) => - processData data + # Fetch each page async, and call the pageCallback callback with the resulting data + # Developer note: this class should not be re-used! + page: 1 + last_page: 1 - if data.pages > 1 - for page in [2..data.pages] - lastPromise = dataFetcher(@urlForPage(url, page)).then (data) -> - processData data - onLastPageComplete && lastPromise.then onLastPageComplete - return - else - onLastPageComplete && onLastPageComplete() + fetch: (url, pageCallback) -> + @fetchPages(url, @page, pageCallback) urlForPage: (url, page) -> url.replace("::page::", page) + + fetchPages: (url, page, pageCallback) -> + dataFetcher(@urlForPage(url, page)).then (data) => + @page++ + @last_page = data.pages + + pageCallback(data) if pageCallback + + if @page <= @last_page + @fetchPages(url, @page, pageCallback) + diff --git a/app/assets/javascripts/admin/orders/controllers/orders_controller.js.coffee b/app/assets/javascripts/admin/orders/controllers/orders_controller.js.coffee index d4d86b7ddb..e98fcccb2a 100644 --- a/app/assets/javascripts/admin/orders/controllers/orders_controller.js.coffee +++ b/app/assets/javascripts/admin/orders/controllers/orders_controller.js.coffee @@ -67,7 +67,7 @@ angular.module("admin.orders").controller "ordersCtrl", ($scope, $timeout, Reque return unless sort && sort.predicate != "" $scope.sorting = sort.getSortingExpr() - $scope.fetchProducts() + $scope.fetchResults() , true $scope.capturePayment = (order) -> diff --git a/app/assets/javascripts/admin/variant_overrides/controllers/variant_overrides_controller.js.coffee b/app/assets/javascripts/admin/variant_overrides/controllers/variant_overrides_controller.js.coffee index c37ba72071..b890d2ffd5 100644 --- a/app/assets/javascripts/admin/variant_overrides/controllers/variant_overrides_controller.js.coffee +++ b/app/assets/javascripts/admin/variant_overrides/controllers/variant_overrides_controller.js.coffee @@ -43,12 +43,11 @@ angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl", $scope.fetchProducts = -> url = "/api/products/overridable?page=::page::;per_page=100" - PagedFetcher.fetch url, (data) => $scope.addProducts data.products + PagedFetcher.fetch url, $scope.addProducts - - $scope.addProducts = (products) -> - $scope.products = $scope.products.concat products - VariantOverrides.ensureDataFor hubs, products + $scope.addProducts = (data) -> + $scope.products = $scope.products.concat data.products + VariantOverrides.ensureDataFor hubs, data.products $scope.displayDirty = -> if DirtyVariantOverrides.count() > 0 diff --git a/app/assets/javascripts/darkswarm/controllers/enterprises_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/enterprises_controller.js.coffee index 4f85093df5..0bc5c3a460 100644 --- a/app/assets/javascripts/darkswarm/controllers/enterprises_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/enterprises_controller.js.coffee @@ -9,8 +9,13 @@ Darkswarm.controller "EnterprisesCtrl", ($scope, $rootScope, $timeout, $location $scope.show_closed = false $scope.filtersActive = false $scope.distanceMatchesShown = false + $scope.closed_shops_loading = false + $scope.closed_shops_loaded = false $scope.$watch "query", (query)-> + $scope.resetSearch(query) + + $scope.resetSearch = (query) -> Enterprises.flagMatching query Search.search query $rootScope.$broadcast 'enterprisesChanged' @@ -19,6 +24,7 @@ Darkswarm.controller "EnterprisesCtrl", ($scope, $rootScope, $timeout, $location $timeout -> Enterprises.calculateDistance query, $scope.firstNameMatch() $rootScope.$broadcast 'enterprisesChanged' + $scope.closed_shops_loading = false $timeout -> if $location.search()['show_closed']? @@ -73,6 +79,12 @@ Darkswarm.controller "EnterprisesCtrl", ($scope, $rootScope, $timeout, $location undefined $scope.showClosedShops = -> + unless $scope.closed_shops_loaded + $scope.closed_shops_loading = true + $scope.closed_shops_loaded = true + Enterprises.loadClosedEnterprises().then -> + $scope.resetSearch($scope.query) + $scope.show_closed = true $location.search('show_closed', '1') diff --git a/app/assets/javascripts/darkswarm/controllers/hub_node_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/hub_node_controller.js.coffee index 8b0a1159e6..f96d2d454f 100644 --- a/app/assets/javascripts/darkswarm/controllers/hub_node_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/hub_node_controller.js.coffee @@ -24,7 +24,7 @@ Darkswarm.controller "HubNodeCtrl", ($scope, HashNavigation, CurrentHub, $http, $scope.shopfront_loading = true $scope.toggle_tab(event) - $http.get("/api/enterprises/" + $scope.hub.id + "/shopfront") + $http.get("/api/shops/" + $scope.hub.id) .success (data) -> $scope.shopfront_loading = false $scope.hub = data diff --git a/app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee index 0cacb566d5..3aa5045bee 100644 --- a/app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/producer_node_controller.js.coffee @@ -24,7 +24,7 @@ Darkswarm.controller "ProducerNodeCtrl", ($scope, HashNavigation, $anchorScroll, $scope.shopfront_loading = true $scope.toggle_tab(event) - $http.get("/api/enterprises/" + $scope.producer.id + "/shopfront") + $http.get("/api/shops/" + $scope.producer.id) .success (data) -> $scope.shopfront_loading = false $scope.producer = data diff --git a/app/assets/javascripts/darkswarm/services/checkout.js.coffee b/app/assets/javascripts/darkswarm/services/checkout.js.coffee index 83cf018365..f0da646ebe 100644 --- a/app/assets/javascripts/darkswarm/services/checkout.js.coffee +++ b/app/assets/javascripts/darkswarm/services/checkout.js.coffee @@ -14,15 +14,28 @@ Darkswarm.factory 'Checkout', ($injector, CurrentOrder, ShippingMethods, StripeE submit: => Loading.message = t 'submitting_order' - $http.put('/checkout.json', {order: @preprocess()}).success (data, status)=> - Navigation.go data.path - .error (response, status)=> - if response.path - Navigation.go response.path - else - Loading.clear() - @errors = response.errors - RailsFlashLoader.loadFlash(response.flash) + $http.put('/checkout.json', {order: @preprocess()}) + .then (response) => + Navigation.go response.data.path + .catch (response) => + try + @handle_checkout_error_response(response) + catch error + @loadFlash(error: t("checkout.failed")) # inform the user about the unexpected error + throw error # generate a BugsnagJS alert + + handle_checkout_error_response: (response) => + if response.data.path + Navigation.go response.data.path + else + throw response unless response.data.flash + + @errors = response.data.errors + @loadFlash(response.data.flash) + + loadFlash: (flash) => + Loading.clear() + RailsFlashLoader.loadFlash(flash) # Rails wants our Spree::Address data to be provided with _attributes preprocess: -> diff --git a/app/assets/javascripts/darkswarm/services/enterprise_modal.js.coffee b/app/assets/javascripts/darkswarm/services/enterprise_modal.js.coffee index 19361fe508..37dafef776 100644 --- a/app/assets/javascripts/darkswarm/services/enterprise_modal.js.coffee +++ b/app/assets/javascripts/darkswarm/services/enterprise_modal.js.coffee @@ -5,7 +5,7 @@ Darkswarm.factory "EnterpriseModal", ($modal, $rootScope, $http)-> scope = $rootScope.$new(true) # Spawn an isolate to contain the enterprise scope.embedded_layout = window.location.search.indexOf("embedded_shopfront=true") != -1 - $http.get("/api/enterprises/" + enterprise.id + "/shopfront").success (data) -> + $http.get("/api/shops/" + enterprise.id).success (data) -> scope.enterprise = data $modal.open(templateUrl: "enterprise_modal.html", scope: scope) .error (data) -> diff --git a/app/assets/javascripts/darkswarm/services/enterprises.js.coffee b/app/assets/javascripts/darkswarm/services/enterprises.js.coffee index b7b43ca040..46e50cb574 100644 --- a/app/assets/javascripts/darkswarm/services/enterprises.js.coffee +++ b/app/assets/javascripts/darkswarm/services/enterprises.js.coffee @@ -1,27 +1,30 @@ -Darkswarm.factory 'Enterprises', (enterprises, CurrentHub, Taxons, Dereferencer, Matcher, Geo, $rootScope) -> +Darkswarm.factory 'Enterprises', (enterprises, ShopsResource, CurrentHub, Taxons, Dereferencer, Matcher, Geo, $rootScope) -> new class Enterprises + enterprises: [] enterprises_by_id: {} constructor: -> # Populate Enterprises.enterprises from json in page. - @enterprises = enterprises + @initEnterprises(enterprises) + initEnterprises: (enterprises) -> # Map enterprises to id/object pairs for lookup. for enterprise in enterprises + @enterprises.push enterprise @enterprises_by_id[enterprise.id] = enterprise # Replace enterprise and taxons ids with actual objects. - @dereferenceEnterprises() + @dereferenceEnterprises(enterprises) @producers = @enterprises.filter (enterprise)-> enterprise.category in ["producer_hub", "producer_shop", "producer"] @hubs = @enterprises.filter (enterprise)-> enterprise.category in ["hub", "hub_profile", "producer_hub", "producer_shop"] - dereferenceEnterprises: -> + dereferenceEnterprises: (enteprises) -> if CurrentHub.hub?.id CurrentHub.hub = @enterprises_by_id[CurrentHub.hub.id] - for enterprise in @enterprises + for enterprise in enterprises @dereferenceEnterprise enterprise dereferenceEnterprise: (enterprise) -> @@ -42,6 +45,12 @@ Darkswarm.factory 'Enterprises', (enterprises, CurrentHub, Taxons, Dereferencer, for enterprise in new_enterprises @enterprises_by_id[enterprise.id] = enterprise + loadClosedEnterprises: -> + request = ShopsResource.closed_shops {}, (data) => + @initEnterprises(data) + + request.$promise + flagMatching: (query) -> for enterprise in @enterprises enterprise.matches_name_query = if query? && query.length > 0 diff --git a/app/assets/javascripts/darkswarm/services/order_cycle.js.coffee b/app/assets/javascripts/darkswarm/services/order_cycle.js.coffee index 0c5176328b..c3f9a0a48f 100644 --- a/app/assets/javascripts/darkswarm/services/order_cycle.js.coffee +++ b/app/assets/javascripts/darkswarm/services/order_cycle.js.coffee @@ -1,6 +1,6 @@ Darkswarm.factory 'OrderCycle', ($resource, orderCycleData) -> class OrderCycle - @order_cycle = orderCycleData # Object or {} due to RABL + @order_cycle = orderCycleData # Object or {} @push_order_cycle: (callback) -> new $resource("/shop/order_cycle").save {order_cycle_id: @order_cycle.order_cycle_id}, (order_data)-> OrderCycle.order_cycle.orders_close_at = order_data.orders_close_at diff --git a/app/assets/javascripts/darkswarm/services/shops_resource.js.coffee b/app/assets/javascripts/darkswarm/services/shops_resource.js.coffee new file mode 100644 index 0000000000..2726b25496 --- /dev/null +++ b/app/assets/javascripts/darkswarm/services/shops_resource.js.coffee @@ -0,0 +1,7 @@ +Darkswarm.factory 'ShopsResource', ($resource) -> + $resource('/api/shops/:id.json', {}, { + 'closed_shops': + method: 'GET' + isArray: true + url: '/api/shops/closed_shops.json' + }) diff --git a/app/assets/javascripts/templates/admin/columns_dropdown.html.haml b/app/assets/javascripts/templates/admin/columns_dropdown.html.haml index 37398b200a..cae123bbcf 100644 --- a/app/assets/javascripts/templates/admin/columns_dropdown.html.haml +++ b/app/assets/javascripts/templates/admin/columns_dropdown.html.haml @@ -8,4 +8,4 @@ %hr %div.menu_item.text-center %input.fullwidth.orange{ type: "button", ng: { value: "saved() ? 'Saved': 'Saving'", show: "saved() || saving", disabled: "saved()" } } - %input.fullwidth.red{ type: "button", value: 'Save As Default', ng: { show: "!saved() && !saving", click: "saveColumnPreferences(action)"} } + %input.fullwidth.red{ type: "button", :value => t('admin.column_save_as_default').html_safe, ng: { show: "!saved() && !saving", click: "saveColumnPreferences(action)"} } diff --git a/app/assets/stylesheets/darkswarm/_shop-inputs.css.scss b/app/assets/stylesheets/darkswarm/_shop-inputs.css.scss index 55f3309477..3cf5d6e497 100644 --- a/app/assets/stylesheets/darkswarm/_shop-inputs.css.scss +++ b/app/assets/stylesheets/darkswarm/_shop-inputs.css.scss @@ -9,6 +9,9 @@ input#search { @include medium-input(rgba(0, 0, 0, 0.3), #777, $clr-brick); + + // avoid zoom on iphone, see issue #4535 + font-size: 1rem; } // ordering diff --git a/app/assets/stylesheets/darkswarm/branding.css.scss b/app/assets/stylesheets/darkswarm/branding.css.scss index b8ab72349c..ca75eaa227 100644 --- a/app/assets/stylesheets/darkswarm/branding.css.scss +++ b/app/assets/stylesheets/darkswarm/branding.css.scss @@ -54,6 +54,7 @@ $teal-400: #4cb5c5; $teal-500: #0096ad; $orange-400: #ff9466; +$orange-450: #f4704c; $orange-500: #f27052; $orange-600: #d7583a; diff --git a/app/assets/stylesheets/darkswarm/hubs.css.scss b/app/assets/stylesheets/darkswarm/hubs.css.scss index 9845ce9ad8..253266eba4 100644 --- a/app/assets/stylesheets/darkswarm/hubs.css.scss +++ b/app/assets/stylesheets/darkswarm/hubs.css.scss @@ -14,5 +14,10 @@ .more-controls { text-align: center; + + .spinner { + height: 2.25em; + margin-right: 0.5em; + } } } diff --git a/app/assets/stylesheets/darkswarm/shopping-cart.css.scss b/app/assets/stylesheets/darkswarm/shopping-cart.css.scss index 9a1a2efe8d..bd4a5019c8 100644 --- a/app/assets/stylesheets/darkswarm/shopping-cart.css.scss +++ b/app/assets/stylesheets/darkswarm/shopping-cart.css.scss @@ -115,3 +115,14 @@ height: 36px; } } + +.links { + .button { + padding: 1.125rem 0 1.1875rem; + width: 210px; + + @media all and (max-width: 480px) { + width: 100%; + } + } +} diff --git a/app/assets/stylesheets/darkswarm/ui.css.scss b/app/assets/stylesheets/darkswarm/ui.css.scss index 6dc4d95d3b..4a50c4a1a0 100644 --- a/app/assets/stylesheets/darkswarm/ui.css.scss +++ b/app/assets/stylesheets/darkswarm/ui.css.scss @@ -64,13 +64,13 @@ .button.primary, button.primary { font-family: $body-font; - background: $clr-brick; + background: $orange-450; color: white; } .button.primary:hover, .button.primary:active, .button.primary:focus, button.primary:hover, button.primary:active, button.primary:focus { - background: $clr-brick-bright; - text-shadow: 0 1px 0 $clr-brick; + background: $orange-400; + text-shadow: 0 1px 0 $orange-450; } button.success, .button.success { diff --git a/app/controllers/admin/customers_controller.rb b/app/controllers/admin/customers_controller.rb index d4cf9b15fe..667c62aad0 100644 --- a/app/controllers/admin/customers_controller.rb +++ b/app/controllers/admin/customers_controller.rb @@ -17,8 +17,9 @@ module Admin respond_to do |format| format.html format.json do - tag_rule_mapping = TagRule.mapping_for(Enterprise.where(id: params[:enterprise_id])) - render_as_json @collection, tag_rule_mapping: tag_rule_mapping + render_as_json @collection, + tag_rule_mapping: tag_rule_mapping, + customer_tags: customer_tags_by_id end end end @@ -64,8 +65,13 @@ module Admin def collection return Customer.where("1=0") unless json_request? && params[:enterprise_id].present? - enterprise = Enterprise.managed_by(spree_current_user).find_by(id: params[:enterprise_id]) - Customer.of(enterprise) + Customer.of(managed_enterprise_id). + includes(:bill_address, :ship_address, user: :credit_cards) + end + + def managed_enterprise_id + @managed_enterprise_id ||= Enterprise.managed_by(spree_current_user). + select('enterprises.id').find_by(id: params[:enterprise_id]) end def load_managed_shops @@ -93,5 +99,28 @@ module Admin def permitted_resource_params customer_params end + + def tag_rule_mapping + TagRule.mapping_for(Enterprise.where(id: managed_enterprise_id)) + end + + # Fetches tags for all customers of the enterprise and returns a hash indexed by customer_id + def customer_tags_by_id + customer_tags = ::ActsAsTaggableOn::Tag. + joins(:taggings). + includes(:taggings). + where(taggings: + { taggable_type: 'Customer', + taggable_id: Customer.of(managed_enterprise_id), + context: 'tags' }) + + customer_tags.each_with_object({}) do |tag, indexed_hash| + tag.taggings.each do |tagging| + customer_id = tagging.taggable_id + indexed_hash[customer_id] ||= [] + indexed_hash[customer_id] << tag.name + end + end + end end end diff --git a/app/controllers/admin/order_cycles_controller.rb b/app/controllers/admin/order_cycles_controller.rb index 19c2240d25..d66e7eefd2 100644 --- a/app/controllers/admin/order_cycles_controller.rb +++ b/app/controllers/admin/order_cycles_controller.rb @@ -16,7 +16,7 @@ module Admin render_as_json @collection, ams_prefix: params[:ams_prefix], current_user: spree_current_user, - subscriptions_count: SubscriptionsCount.new(@collection) + subscriptions_count: OrderManagement::Subscriptions::Count.new(@collection) end end end @@ -74,7 +74,7 @@ module Admin render_as_json @order_cycles, ams_prefix: 'index', current_user: spree_current_user, - subscriptions_count: SubscriptionsCount.new(@collection) + subscriptions_count: OrderManagement::Subscriptions::Count.new(@collection) else order_cycle = order_cycle_set.collection.find{ |oc| oc.errors.present? } render json: { errors: order_cycle.errors.full_messages }, status: :unprocessable_entity diff --git a/app/controllers/admin/proxy_orders_controller.rb b/app/controllers/admin/proxy_orders_controller.rb index b6d0140845..8e92f307f4 100644 --- a/app/controllers/admin/proxy_orders_controller.rb +++ b/app/controllers/admin/proxy_orders_controller.rb @@ -9,25 +9,19 @@ module Admin def cancel if @proxy_order.cancel - respond_with(@proxy_order) do |format| - format.json { render_as_json @proxy_order } - end + render_as_json @proxy_order else - respond_with(@proxy_order) do |format| - format.json { render json: { errors: [t('admin.proxy_orders.cancel.could_not_cancel_the_order')] }, status: :unprocessable_entity } - end + render json: { errors: [t('admin.proxy_orders.cancel.could_not_cancel_the_order')] }, + status: :unprocessable_entity end end def resume if @proxy_order.resume - respond_with(@proxy_order) do |format| - format.json { render_as_json @proxy_order } - end + render_as_json @proxy_order else - respond_with(@proxy_order) do |format| - format.json { render json: { errors: [t('admin.proxy_orders.resume.could_not_resume_the_order')] }, status: :unprocessable_entity } - end + render json: { errors: [t('admin.proxy_orders.resume.could_not_resume_the_order')] }, + status: :unprocessable_entity end end end diff --git a/app/controllers/admin/schedules_controller.rb b/app/controllers/admin/schedules_controller.rb index 8c8392372e..44ccb48d64 100644 --- a/app/controllers/admin/schedules_controller.rb +++ b/app/controllers/admin/schedules_controller.rb @@ -1,5 +1,5 @@ require 'open_food_network/permissions' -require 'open_food_network/proxy_order_syncer' +require 'order_management/subscriptions/proxy_order_syncer' module Admin class SchedulesController < ResourceController @@ -90,7 +90,7 @@ module Admin return unless removed_ids.any? || new_ids.any? subscriptions = Subscription.where(schedule_id: @schedule) - syncer = OpenFoodNetwork::ProxyOrderSyncer.new(subscriptions) + syncer = OrderManagement::Subscriptions::ProxyOrderSyncer.new(subscriptions) syncer.sync! end diff --git a/app/controllers/admin/subscription_line_items_controller.rb b/app/controllers/admin/subscription_line_items_controller.rb index 27ec3611a1..c52cca1c3b 100644 --- a/app/controllers/admin/subscription_line_items_controller.rb +++ b/app/controllers/admin/subscription_line_items_controller.rb @@ -56,7 +56,7 @@ module Admin end def variant_if_eligible(variant_id) - SubscriptionVariantsService.eligible_variants(@shop).find_by(id: variant_id) + OrderManagement::Subscriptions::VariantsList.eligible_variants(@shop).find_by(id: variant_id) end def subscription_line_item_params diff --git a/app/controllers/admin/subscriptions_controller.rb b/app/controllers/admin/subscriptions_controller.rb index 4561ef3a79..11163b6830 100644 --- a/app/controllers/admin/subscriptions_controller.rb +++ b/app/controllers/admin/subscriptions_controller.rb @@ -1,5 +1,4 @@ require 'open_food_network/permissions' -require 'open_food_network/proxy_order_syncer' module Admin class SubscriptionsController < ResourceController @@ -65,7 +64,7 @@ module Admin private def save_form_and_render(render_issues = true) - form = SubscriptionForm.new(@subscription, subscription_params) + form = OrderManagement::Subscriptions::Form.new(@subscription, subscription_params) unless form.save render json: { errors: form.json_errors }, status: :unprocessable_entity return diff --git a/app/controllers/admin/variant_overrides_controller.rb b/app/controllers/admin/variant_overrides_controller.rb index 3530b3648f..07894a9498 100644 --- a/app/controllers/admin/variant_overrides_controller.rb +++ b/app/controllers/admin/variant_overrides_controller.rb @@ -74,10 +74,10 @@ module Admin def collection @variant_overrides = VariantOverride. - includes(:variant). + includes(variant: :product). for_hubs(params[:hub_id] || @hubs). - references(:variant) - @variant_overrides.select { |vo| vo.variant.present? } + references(:variant). + select { |vo| vo.variant.present? } end def collection_actions diff --git a/app/controllers/api/enterprises_controller.rb b/app/controllers/api/enterprises_controller.rb index 7c545e5181..b4456c5ae4 100644 --- a/app/controllers/api/enterprises_controller.rb +++ b/app/controllers/api/enterprises_controller.rb @@ -5,7 +5,6 @@ module Api before_filter :override_sells, only: [:create, :update] before_filter :override_visible, only: [:create, :update] respond_to :json - skip_authorization_check only: [:shopfront] def create authorize! :create, Enterprise @@ -46,12 +45,6 @@ module Api end end - def shopfront - enterprise = Enterprise.find_by(id: params[:id]) - - render text: Api::EnterpriseShopfrontSerializer.new(enterprise).to_json, status: :ok - end - private def override_owner diff --git a/app/controllers/api/products_controller.rb b/app/controllers/api/products_controller.rb index e346112326..49246bc624 100644 --- a/app/controllers/api/products_controller.rb +++ b/app/controllers/api/products_controller.rb @@ -69,12 +69,12 @@ module Api end def overridable - producers = OpenFoodNetwork::Permissions.new(current_api_user). - variant_override_producers.by_name + producer_ids = OpenFoodNetwork::Permissions.new(current_api_user). + variant_override_producers.by_name.select('enterprises.id') - @products = paged_products_for_producers producers + @products = paged_products_for_producers producer_ids - render_paged_products @products + render_paged_products @products, ::Api::Admin::ProductSimpleSerializer end # POST /api/products/:product_id/clone @@ -118,19 +118,20 @@ module Api ] end - def paged_products_for_producers(producers) + def paged_products_for_producers(producer_ids) Spree::Product.where(nil). merge(product_scope). - where(supplier_id: producers). + includes(variants: [:product, :default_price, :stock_items]). + where(supplier_id: producer_ids). by_producer.by_name. ransack(params[:q]).result. page(params[:page]).per(params[:per_page]) end - def render_paged_products(products) + def render_paged_products(products, product_serializer = ::Api::Admin::ProductSerializer) serializer = ActiveModel::ArraySerializer.new( products, - each_serializer: ::Api::Admin::ProductSerializer + each_serializer: product_serializer ) render text: { diff --git a/app/controllers/api/shops_controller.rb b/app/controllers/api/shops_controller.rb new file mode 100644 index 0000000000..66740c5cbd --- /dev/null +++ b/app/controllers/api/shops_controller.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +module Api + class ShopsController < BaseController + respond_to :json + skip_authorization_check only: [:show, :closed_shops] + + def show + enterprise = Enterprise.find_by_id(params[:id]) + + render text: Api::EnterpriseShopfrontSerializer.new(enterprise).to_json, status: :ok + end + + def closed_shops + @active_distributor_ids = [] + @earliest_closing_times = [] + + serialized_closed_shops = ActiveModel::ArraySerializer.new( + ShopsListService.new.closed_shops, + each_serializer: Api::EnterpriseSerializer, + data: OpenFoodNetwork::EnterpriseInjectionData.new + ) + + render json: serialized_closed_shops + end + end +end diff --git a/app/controllers/base_controller.rb b/app/controllers/base_controller.rb index dab3eb6752..fdbe51634d 100644 --- a/app/controllers/base_controller.rb +++ b/app/controllers/base_controller.rb @@ -14,10 +14,6 @@ class BaseController < ApplicationController helper 'spree/base' - # Spree::Core::ControllerHelpers declares helper_method get_taxonomies, so we need to - # include Spree::ProductsHelper so that method is available on the controller - include Spree::ProductsHelper - before_filter :set_locale before_filter :check_order_cycle_expiry diff --git a/app/controllers/checkout_controller.rb b/app/controllers/checkout_controller.rb index d09574cdcf..b4fcc732f0 100644 --- a/app/controllers/checkout_controller.rb +++ b/app/controllers/checkout_controller.rb @@ -133,13 +133,6 @@ class CheckoutController < Spree::StoreController @order.ship_address = finder.ship_address end - def before_delivery - return if params[:order].present? - - packages = @order.shipments.map(&:to_package) - @differentiator = Spree::Stock::Differentiator.new(@order, packages) - end - def before_payment current_order.payments.destroy_all if request.put? end @@ -153,10 +146,12 @@ class CheckoutController < Spree::StoreController end def valid_payment_intent_provided? - params["payment_intent"]&.starts_with?("pi_") && - @order.state == "payment" && - @order.payments.last.state == "pending" && - @order.payments.last.response_code == params["payment_intent"] + return false unless params["payment_intent"]&.starts_with?("pi_") + + last_payment = OrderPaymentFinder.new(@order).last_payment + @order.state == "payment" && + last_payment&.state == "pending" && + last_payment&.response_code == params["payment_intent"] end def handle_redirect_from_stripe diff --git a/app/controllers/shops_controller.rb b/app/controllers/shops_controller.rb index d4f350b47f..b57c6f5063 100644 --- a/app/controllers/shops_controller.rb +++ b/app/controllers/shops_controller.rb @@ -4,13 +4,6 @@ class ShopsController < BaseController before_filter :enable_embedded_shopfront def index - @enterprises = Enterprise - .activated - .visible - .is_distributor - .includes(address: [:state, :country]) - .includes(:properties) - .includes(supplied_products: :properties) - .all + @enterprises = ShopsListService.new.open_shops end end diff --git a/app/controllers/spree/admin/payments_controller.rb b/app/controllers/spree/admin/payments_controller.rb index 7627e5c6a2..676e148c6e 100644 --- a/app/controllers/spree/admin/payments_controller.rb +++ b/app/controllers/spree/admin/payments_controller.rb @@ -29,6 +29,8 @@ module Spree return end + authorize_stripe_sca_payment + if @order.completed? @payment.process! flash[:success] = flash_message_for(@payment, :successfully_created) @@ -93,7 +95,7 @@ module Spree available(:back_end). select{ |pm| pm.has_distributor? @order.distributor } - @payment_method = if @payment && @payment.payment_method + @payment_method = if @payment&.payment_method @payment.payment_method else @payment_methods.first @@ -124,6 +126,13 @@ module Spree def load_payment @payment = Payment.find(params[:id]) end + + def authorize_stripe_sca_payment + return unless @payment.payment_method.class == Spree::Gateway::StripeSCA + + @payment.authorize! + raise Spree::Core::GatewayError, I18n.t('authorization_failure') unless @payment.pending? + end end end end diff --git a/app/controllers/spree/admin/reports/enterprise_fee_summaries_controller.rb b/app/controllers/spree/admin/reports/enterprise_fee_summaries_controller.rb deleted file mode 100644 index e6b750b904..0000000000 --- a/app/controllers/spree/admin/reports/enterprise_fee_summaries_controller.rb +++ /dev/null @@ -1,66 +0,0 @@ -module Spree - module Admin - module Reports - class EnterpriseFeeSummariesController < BaseController - before_filter :load_report_parameters - before_filter :load_permissions - - def new; end - - def create - return respond_to_invalid_parameters unless @report_parameters.valid? - - @report_parameters.authorize!(@permissions) - - @report = report_klass::ReportService.new(@permissions, @report_parameters) - renderer.render(self) - rescue ::Reports::Authorizer::ParameterNotAllowedError => e - flash[:error] = e.message - render_report_form - end - - private - - def respond_to_invalid_parameters - flash[:error] = I18n.t("invalid_filter_parameters", scope: i18n_scope) - render_report_form - end - - def i18n_scope - "order_management.reports.enterprise_fee_summary" - end - - def render_report_form - render action: :new - end - - def report_klass - OrderManagement::Reports::EnterpriseFeeSummary - end - - def load_report_parameters - @report_parameters = report_klass::Parameters.new(params[:report] || {}) - end - - def load_permissions - @permissions = report_klass::Permissions.new(spree_current_user) - end - - def report_renderer_klass - case params[:report_format] - when "csv" - report_klass::Renderers::CsvRenderer - when nil, "", "html" - report_klass::Renderers::HtmlRenderer - else - raise Reports::UnsupportedReportFormatException - end - end - - def renderer - @renderer ||= report_renderer_klass.new(@report) - end - end - end - end -end diff --git a/app/controllers/spree/admin/reports_controller.rb b/app/controllers/spree/admin/reports_controller.rb index 78381a9d63..633ca8c8de 100644 --- a/app/controllers/spree/admin/reports_controller.rb +++ b/app/controllers/spree/admin/reports_controller.rb @@ -298,11 +298,20 @@ module Spree end def url_for_report(report) - public_send("#{report}_admin_reports_url".to_sym) + if report_in_order_management_engine?(report) + main_app.public_send("new_order_management_reports_#{report}_url".to_sym) + else + public_send("#{report}_admin_reports_url".to_sym) + end rescue NoMethodError url_for([:new, :admin, :reports, report.to_s.singularize]) end + # List of reports that have been moved to the Order Management engine + def report_in_order_management_engine?(report) + report == :enterprise_fee_summary + end + def timestamp Time.zone.now.strftime("%Y%m%d") end diff --git a/app/controllers/spree/admin/taxons_controller.rb b/app/controllers/spree/admin/taxons_controller.rb index 739b2df31a..fab6eaeb12 100644 --- a/app/controllers/spree/admin/taxons_controller.rb +++ b/app/controllers/spree/admin/taxons_controller.rb @@ -3,14 +3,6 @@ module Spree class TaxonsController < Spree::Admin::BaseController respond_to :html, :json, :js - def search - @taxons = if params[:ids] - Spree::Taxon.where(id: params[:ids].split(',')) - else - Spree::Taxon.limit(20).search(name_cont: params[:q]).result - end - end - def create @taxonomy = Taxonomy.find(params[:taxonomy_id]) @taxon = @taxonomy.taxons.build(params[:taxon]) diff --git a/app/helpers/order_helper.rb b/app/helpers/order_helper.rb new file mode 100644 index 0000000000..157ee212bb --- /dev/null +++ b/app/helpers/order_helper.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module OrderHelper + def last_payment_method(order) + OrderPaymentFinder.new(order).last_payment&.payment_method + end +end diff --git a/app/helpers/spree/products_helper.rb b/app/helpers/spree/products_helper.rb new file mode 100644 index 0000000000..9e367fb010 --- /dev/null +++ b/app/helpers/spree/products_helper.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module Spree + module ProductsHelper + def product_has_variant_unit_option_type?(product) + product.option_types.any? { |option_type| variant_unit_option_type? option_type } + end + + def variant_unit_option_type?(option_type) + Spree::Product.all_variant_unit_option_types.include? option_type + end + end +end diff --git a/app/helpers/spree/products_helper_decorator.rb b/app/helpers/spree/products_helper_decorator.rb deleted file mode 100644 index ac31d260b9..0000000000 --- a/app/helpers/spree/products_helper_decorator.rb +++ /dev/null @@ -1,23 +0,0 @@ -module Spree - ProductsHelper.class_eval do - # Return the price of the variant, overriding sprees price diff capability. - # This will allways return the variant price as if the show_variant_full_price is set. - def variant_price_diff(variant) - "(#{Spree::Money.new(variant.price)})" - end - - def product_has_variant_unit_option_type?(product) - product.option_types.any? { |option_type| variant_unit_option_type? option_type } - end - - def variant_unit_option_type?(option_type) - Spree::Product.all_variant_unit_option_types.include? option_type - end - - def product_variant_unit_options - [[I18n.t(:weight), 'weight'], - [I18n.t(:volume), 'volume'], - [I18n.t(:items), 'items']] - end - end -end diff --git a/app/jobs/subscription_confirm_job.rb b/app/jobs/subscription_confirm_job.rb index be7f589cfc..748257a340 100644 --- a/app/jobs/subscription_confirm_job.rb +++ b/app/jobs/subscription_confirm_job.rb @@ -1,17 +1,9 @@ -require 'open_food_network/subscription_payment_updater' -require 'open_food_network/subscription_summarizer' +require 'order_management/subscriptions/summarizer' +# Confirms orders of unconfirmed proxy orders in recently closed Order Cycles class SubscriptionConfirmJob def perform - ids = proxy_orders.pluck(:id) - proxy_orders.update_all(confirmed_at: Time.zone.now) - ProxyOrder.where(id: ids).each do |proxy_order| - Rails.logger.info "Confirming Order for Proxy Order #{proxy_order.id}" - @order = proxy_order.order - process! - end - - send_confirmation_summary_emails + confirm_proxy_orders! end private @@ -20,10 +12,26 @@ class SubscriptionConfirmJob delegate :record_and_log_error, :send_confirmation_summary_emails, to: :summarizer def summarizer - @summarizer ||= OpenFoodNetwork::SubscriptionSummarizer.new + @summarizer ||= OrderManagement::Subscriptions::Summarizer.new end - def proxy_orders + def confirm_proxy_orders! + # Fetch all unconfirmed proxy orders + unconfirmed_proxy_orders_ids = unconfirmed_proxy_orders.pluck(:id) + + # Mark these proxy orders as confirmed + unconfirmed_proxy_orders.update_all(confirmed_at: Time.zone.now) + + # Confirm these proxy orders + ProxyOrder.where(id: unconfirmed_proxy_orders_ids).each do |proxy_order| + Rails.logger.info "Confirming Order for Proxy Order #{proxy_order.id}" + confirm_order!(proxy_order.order) + end + + send_confirmation_summary_emails + end + + def unconfirmed_proxy_orders ProxyOrder.not_canceled.where('confirmed_at IS NULL AND placed_at IS NOT NULL') .joins(:order_cycle).merge(recently_closed_order_cycles) .joins(:order).merge(Spree::Order.complete.not_state('canceled')) @@ -33,30 +41,55 @@ class SubscriptionConfirmJob OrderCycle.closed.where('order_cycles.orders_close_at BETWEEN (?) AND (?) OR order_cycles.updated_at BETWEEN (?) AND (?)', 1.hour.ago, Time.zone.now, 1.hour.ago, Time.zone.now) end - def process! - record_order(@order) - update_payment! if @order.payment_required? - return send_failed_payment_email if @order.errors.present? + # It sets up payments, processes payments and sends confirmation emails + def confirm_order!(order) + record_order(order) - @order.process_payments! if @order.payment_required? - return send_failed_payment_email if @order.errors.present? - - send_confirm_email + if process_payment!(order) + send_confirmation_email(order) + else + send_failed_payment_email(order) + end end - def update_payment! - OpenFoodNetwork::SubscriptionPaymentUpdater.new(@order).update! + def process_payment!(order) + return false if order.errors.present? + return true unless order.payment_required? + + setup_payment!(order) + return false if order.errors.any? + + authorize_payment!(order) + return false if order.errors.any? + + order.process_payments! + return false if order.errors.any? + + true end - def send_confirm_email - @order.update! - record_success(@order) - SubscriptionMailer.confirmation_email(@order).deliver + def setup_payment!(order) + OrderManagement::Subscriptions::PaymentSetup.new(order).call! + return if order.errors.any? + + OrderManagement::Subscriptions::StripePaymentSetup.new(order).call! end - def send_failed_payment_email - @order.update! - record_and_log_error(:failed_payment, @order) - SubscriptionMailer.failed_payment_email(@order).deliver + def authorize_payment!(order) + return if order.subscription.payment_method.class != Spree::Gateway::StripeSCA + + OrderManagement::Subscriptions::StripeScaPaymentAuthorize.new(order).call! + end + + def send_confirmation_email(order) + order.update! + record_success(order) + SubscriptionMailer.confirmation_email(order).deliver + end + + def send_failed_payment_email(order) + order.update! + record_and_log_error(:failed_payment, order) + SubscriptionMailer.failed_payment_email(order).deliver end end diff --git a/app/jobs/subscription_placement_job.rb b/app/jobs/subscription_placement_job.rb index ecaa9208ef..44a4a27c75 100644 --- a/app/jobs/subscription_placement_job.rb +++ b/app/jobs/subscription_placement_job.rb @@ -1,4 +1,4 @@ -require 'open_food_network/subscription_summarizer' +require 'order_management/subscriptions/summarizer' class SubscriptionPlacementJob def perform @@ -17,7 +17,7 @@ class SubscriptionPlacementJob delegate :record_and_log_error, :send_placement_summary_emails, to: :summarizer def summarizer - @summarizer ||= OpenFoodNetwork::SubscriptionSummarizer.new + @summarizer ||= OrderManagement::Subscriptions::Summarizer.new end def proxy_orders diff --git a/app/mailers/producer_mailer.rb b/app/mailers/producer_mailer.rb index 959cdf3537..48f3c6a34d 100644 --- a/app/mailers/producer_mailer.rb +++ b/app/mailers/producer_mailer.rb @@ -1,41 +1,58 @@ +# frozen_string_literal: true + class ProducerMailer < Spree::BaseMailer include I18nHelper def order_cycle_report(producer, order_cycle) @producer = producer - @coordinator = order_cycle.coordinator @order_cycle = order_cycle - line_items = line_items_from(@order_cycle, @producer) - @grouped_line_items = line_items.group_by(&:product_and_full_name) - @receival_instructions = @order_cycle.receival_instructions_for @producer - @total = total_from_line_items(line_items) - @tax_total = tax_total_from_line_items(line_items) - I18n.with_locale valid_locale(@producer.owner) do - order_cycle_subject = I18n.t('producer_mailer.order_cycle.subject', producer: producer.name) - subject = "[#{Spree::Config.site_name}] #{order_cycle_subject}" + with_unscoped_products_and_variants do + load_data - return unless has_orders?(order_cycle, producer) + I18n.with_locale(owner_locale) do + return unless orders?(order_cycle, producer) - mail( - to: @producer.contact.email, - from: from_address, - subject: subject, - reply_to: @coordinator.contact.email, - cc: @coordinator.contact.email - ) + mail( + to: @producer.contact.email, + from: from_address, + subject: subject, + reply_to: @coordinator.contact.email, + cc: @coordinator.contact.email + ) + end end end private - def has_orders?(order_cycle, producer) + def owner_locale + valid_locale(@producer.owner) + end + + def load_data + @coordinator = @order_cycle.coordinator + + line_items = line_items_from(@order_cycle, @producer) + + @grouped_line_items = line_items.group_by(&:product_and_full_name) + @receival_instructions = @order_cycle.receival_instructions_for(@producer) + @total = total_from_line_items(line_items) + @tax_total = tax_total_from_line_items(line_items) + end + + def subject + order_cycle_subject = I18n.t('producer_mailer.order_cycle.subject', producer: @producer.name) + "[#{Spree::Config.site_name}] #{order_cycle_subject}" + end + + def orders?(order_cycle, producer) line_items_from(order_cycle, producer).any? end def line_items_from(order_cycle, producer) - Spree::LineItem. - includes(variant: { option_values: :option_type }). + @line_items ||= Spree::LineItem. + includes(:option_values, variant: [:product, { option_values: :option_type }]). from_order_cycle(order_cycle). sorted_by_name_and_unit_value. merge(Spree::Product.in_supplier(producer)). @@ -49,4 +66,22 @@ class ProducerMailer < Spree::BaseMailer def tax_total_from_line_items(line_items) Spree::Money.new line_items.sum(&:included_tax) end + + # This hack makes ActiveRecord skip the default_scope (deleted_at IS NULL) + # when eager loading associations. Further details: + # https://github.com/rails/rails/issues/11036 + def with_unscoped_products_and_variants + variant_default_scopes = Spree::Variant.default_scopes + product_default_scopes = Spree::Product.default_scopes + + Spree::Variant.default_scopes = [] + Spree::Product.default_scopes = [] + + return_value = yield + + Spree::Variant.default_scopes = variant_default_scopes + Spree::Product.default_scopes = product_default_scopes + + return_value + end end diff --git a/app/mailers/spree/order_mailer_decorator.rb b/app/mailers/spree/order_mailer_decorator.rb index bffc26ee46..fbf17013b8 100644 --- a/app/mailers/spree/order_mailer_decorator.rb +++ b/app/mailers/spree/order_mailer_decorator.rb @@ -2,6 +2,7 @@ Spree::OrderMailer.class_eval do helper HtmlHelper helper CheckoutHelper helper SpreeCurrencyHelper + helper OrderHelper include I18nHelper def cancel_email(order_or_order_id, resend = false) diff --git a/app/mailers/subscription_mailer.rb b/app/mailers/subscription_mailer.rb index e2216c01c9..0267e24ef4 100644 --- a/app/mailers/subscription_mailer.rb +++ b/app/mailers/subscription_mailer.rb @@ -1,6 +1,7 @@ class SubscriptionMailer < Spree::BaseMailer helper CheckoutHelper helper ShopMailHelper + helper OrderHelper include I18nHelper def confirmation_email(order) diff --git a/app/models/order_cycle.rb b/app/models/order_cycle.rb index 57f7ebeabc..b320550caf 100644 --- a/app/models/order_cycle.rb +++ b/app/models/order_cycle.rb @@ -17,7 +17,7 @@ class OrderCycle < ActiveRecord::Base has_many :distributors, -> { uniq }, source: :receiver, through: :cached_outgoing_exchanges has_and_belongs_to_many :schedules, join_table: 'order_cycle_schedules' - has_paper_trail meta: { custom_data: :schedule_ids } + has_paper_trail meta: { custom_data: proc { |order_cycle| order_cycle.schedule_ids.to_s } } attr_accessor :incoming_exchanges, :outgoing_exchanges diff --git a/app/models/producer_property.rb b/app/models/producer_property.rb index f29b682def..75f3d98f17 100644 --- a/app/models/producer_property.rb +++ b/app/models/producer_property.rb @@ -4,18 +4,6 @@ class ProducerProperty < ActiveRecord::Base default_scope { order("#{table_name}.position") } - scope :ever_sold_by, ->(shop) { - joins(producer: { supplied_products: { variants: { exchanges: :order_cycle } } }). - merge(Exchange.outgoing). - merge(Exchange.to_enterprise(shop)). - select('DISTINCT producer_properties.*') - } - - scope :currently_sold_by, ->(shop) { - ever_sold_by(shop). - merge(OrderCycle.active) - } - def property_name property.name if property end diff --git a/app/models/schedule.rb b/app/models/schedule.rb index d4957f935e..4f5e84768f 100644 --- a/app/models/schedule.rb +++ b/app/models/schedule.rb @@ -1,7 +1,7 @@ class Schedule < ActiveRecord::Base - has_paper_trail meta: { custom_data: :order_cycle_ids } - has_and_belongs_to_many :order_cycles, join_table: 'order_cycle_schedules' + has_paper_trail meta: { custom_data: proc { |schedule| schedule.order_cycle_ids.to_s } } + has_many :coordinators, -> { uniq }, through: :order_cycles validates :order_cycles, presence: true diff --git a/app/models/spree/calculator/price_sack_decorator.rb b/app/models/spree/calculator/price_sack_decorator.rb index 41aeabf330..b474f77861 100644 --- a/app/models/spree/calculator/price_sack_decorator.rb +++ b/app/models/spree/calculator/price_sack_decorator.rb @@ -17,9 +17,9 @@ module Spree order_amount = line_items_for(object).map { |x| x.price * x.quantity }.sum if order_amount < min - cost = preferred_normal_amount.to_i + cost = preferred_normal_amount.to_f elsif order_amount >= min - cost = preferred_discount_amount.to_i + cost = preferred_discount_amount.to_f end cost diff --git a/app/models/spree/money_decorator.rb b/app/models/spree/money_decorator.rb deleted file mode 100644 index ae4ca7e497..0000000000 --- a/app/models/spree/money_decorator.rb +++ /dev/null @@ -1,6 +0,0 @@ -Spree::Money.class_eval do - # return the currency symbol (on it's own) for the current default currency - def self.currency_symbol - Money.new(0, Spree::Config[:currency]).symbol - end -end diff --git a/app/models/spree/property.rb b/app/models/spree/property.rb index f9f3415bbc..18f2497786 100644 --- a/app/models/spree/property.rb +++ b/app/models/spree/property.rb @@ -2,9 +2,14 @@ module Spree class Property < ActiveRecord::Base has_many :product_properties, dependent: :destroy has_many :products, through: :product_properties + has_many :producer_properties validates :name, :presentation, presence: true scope :sorted, -> { order(:name) } + + def property + self + end end end diff --git a/app/models/spree/property_decorator.rb b/app/models/spree/property_decorator.rb deleted file mode 100644 index aeeb607af9..0000000000 --- a/app/models/spree/property_decorator.rb +++ /dev/null @@ -1,27 +0,0 @@ -module Spree - Property.class_eval do - has_many :producer_properties - - scope :applied_by, ->(enterprise) { - select('DISTINCT spree_properties.*'). - joins(:product_properties). - where('spree_product_properties.product_id IN (?)', enterprise.supplied_product_ids) - } - - scope :ever_sold_by, ->(shop) { - joins(products: { variants: { exchanges: :order_cycle } }). - merge(Exchange.outgoing). - merge(Exchange.to_enterprise(shop)). - select('DISTINCT spree_properties.*') - } - - scope :currently_sold_by, ->(shop) { - ever_sold_by(shop). - merge(OrderCycle.active) - } - - def property - self - end - end -end diff --git a/app/models/spree/stock/quantifier.rb b/app/models/spree/stock/quantifier.rb new file mode 100644 index 0000000000..8c437dc580 --- /dev/null +++ b/app/models/spree/stock/quantifier.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module Spree + module Stock + class Quantifier + attr_reader :stock_items + + def initialize(variant) + @variant = variant + @stock_items = fetch_stock_items + end + + def total_on_hand + stock_items.sum(&:count_on_hand) + end + + def backorderable? + stock_items.any?(&:backorderable) + end + + def can_supply?(required) + total_on_hand >= required || backorderable? + end + + private + + def fetch_stock_items + # Don't re-fetch associated stock items from the DB if we've already eager-loaded them + return @variant.stock_items.to_a if @variant.stock_items.loaded? + + Spree::StockItem.joins(:stock_location). + where(:variant_id => @variant, Spree::StockLocation.table_name => { active: true }) + end + end + end +end diff --git a/app/models/spree/user.rb b/app/models/spree/user.rb index 814ba38a6c..80b3adc8b8 100644 --- a/app/models/spree/user.rb +++ b/app/models/spree/user.rb @@ -104,7 +104,12 @@ module Spree end def default_card - credit_cards.where(is_default: true).first + # Don't re-fetch associated cards from the DB if they're already eager-loaded + if credit_cards.loaded? + credit_cards.to_a.find(&:is_default) + else + credit_cards.where(is_default: true).first + end end # Checks whether the specified user is a superadmin, with full control of the diff --git a/app/models/spree/variant_decorator.rb b/app/models/spree/variant_decorator.rb index 4e1e8e1a21..96853a28f2 100644 --- a/app/models/spree/variant_decorator.rb +++ b/app/models/spree/variant_decorator.rb @@ -52,13 +52,23 @@ Spree::Variant.class_eval do } scope :visible_for, lambda { |enterprise| - joins(:inventory_items).where('inventory_items.enterprise_id = (?) AND inventory_items.visible = (?)', enterprise, true) + joins(:inventory_items). + where( + 'inventory_items.enterprise_id = (?) AND inventory_items.visible = (?)', + enterprise, + true + ) } scope :not_hidden_for, lambda { |enterprise| return where("1=0") if enterprise.blank? - joins("LEFT OUTER JOIN (SELECT * from inventory_items WHERE enterprise_id = #{sanitize enterprise.andand.id}) AS o_inventory_items ON o_inventory_items.variant_id = spree_variants.id") + joins(" + LEFT OUTER JOIN (SELECT * + FROM inventory_items + WHERE enterprise_id = #{sanitize enterprise.andand.id}) + AS o_inventory_items + ON o_inventory_items.variant_id = spree_variants.id") .where("o_inventory_items.id IS NULL OR o_inventory_items.visible = (?)", true) } @@ -67,7 +77,8 @@ Spree::Variant.class_eval do scope :stockable_by, lambda { |enterprise| return where("1=0") if enterprise.blank? - joins(:product).where(spree_products: { id: Spree::Product.stockable_by(enterprise).pluck(:id) }) + joins(:product). + where(spree_products: { id: Spree::Product.stockable_by(enterprise).pluck(:id) }) } # Define sope as class method to allow chaining with other scopes filtering id. @@ -84,7 +95,19 @@ Spree::Variant.class_eval do ] end - # We override in_stock? to avoid depending on the non-overridable method Spree::Stock::Quantifier.can_supply? + def self.active(currency = nil) + # "where(id:" is necessary so that the returned relation has no includes + # The relation without includes will not be readonly and allow updates on it + where("spree_variants.id in (?)", joins(:prices). + where(deleted_at: nil). + where('spree_prices.currency' => + currency || Spree::Config[:currency]). + where('spree_prices.amount IS NOT NULL'). + select("spree_variants.id")) + end + + # We override in_stock? to avoid depending + # on the non-overridable method Spree::Stock::Quantifier.can_supply? # VariantStock implements can_supply? itself which depends on overridable methods def in_stock?(quantity = 1) can_supply?(quantity) diff --git a/app/models/variant_override_set.rb b/app/models/variant_override_set.rb index c64b4cdc32..d380df4144 100644 --- a/app/models/variant_override_set.rb +++ b/app/models/variant_override_set.rb @@ -15,8 +15,10 @@ class VariantOverrideSet < ModelSet tag_list.empty? end + # Override of ModelSet method to allow us to check presence of a tag_list (which is not an attribute) + # This method will delete VariantOverrides that have no values (see deletable? above) + # If the user sets all values to nil in the UI the VO will be deleted from the DB def collection_to_delete - # Override of ModelSet method to allow us to check presence of a tag_list (which is not an attribute) deleted = [] collection.delete_if { |e| deleted << e if @delete_if.andand.call(e.attributes, e.tag_list) } deleted diff --git a/app/serializers/api/admin/customer_serializer.rb b/app/serializers/api/admin/customer_serializer.rb index 070e7927da..7648104600 100644 --- a/app/serializers/api/admin/customer_serializer.rb +++ b/app/serializers/api/admin/customer_serializer.rb @@ -6,7 +6,7 @@ class Api::Admin::CustomerSerializer < ActiveModel::Serializer has_one :bill_address, serializer: Api::AddressSerializer def tag_list - object.tag_list.join(",") + customer_tag_list.join(",") end def name @@ -14,7 +14,7 @@ class Api::Admin::CustomerSerializer < ActiveModel::Serializer end def tags - object.tag_list.map do |tag| + customer_tag_list.map do |tag| tag_rule_map = options[:tag_rule_mapping].andand[tag] tag_rule_map || { text: tag, rules: nil } end @@ -25,4 +25,12 @@ class Api::Admin::CustomerSerializer < ActiveModel::Serializer object.user.default_card.present? end + + private + + def customer_tag_list + return object.tag_list unless options[:customer_tags] + + options[:customer_tags].andand[object.id] || [] + end end diff --git a/app/serializers/api/admin/product_simple_serializer.rb b/app/serializers/api/admin/product_simple_serializer.rb new file mode 100644 index 0000000000..6b968ab8d3 --- /dev/null +++ b/app/serializers/api/admin/product_simple_serializer.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module Api + module Admin + class ProductSimpleSerializer < ActiveModel::Serializer + attributes :id, :name, :producer_id + + has_many :variants, key: :variants, serializer: Api::Admin::VariantSimpleSerializer + + def producer_id + object.supplier_id + end + end + end +end diff --git a/app/serializers/api/admin/subscription_line_item_serializer.rb b/app/serializers/api/admin/subscription_line_item_serializer.rb index 34bc00c6c0..f1411e040f 100644 --- a/app/serializers/api/admin/subscription_line_item_serializer.rb +++ b/app/serializers/api/admin/subscription_line_item_serializer.rb @@ -13,9 +13,9 @@ module Api end def in_open_and_upcoming_order_cycles - SubscriptionVariantsService.in_open_and_upcoming_order_cycles?(option_or_assigned_shop, - option_or_assigned_schedule, - object.variant) + OrderManagement::Subscriptions::VariantsList.in_open_and_upcoming_order_cycles?(option_or_assigned_shop, + option_or_assigned_schedule, + object.variant) end private diff --git a/app/serializers/api/admin/variant_simple_serializer.rb b/app/serializers/api/admin/variant_simple_serializer.rb new file mode 100644 index 0000000000..d94421321f --- /dev/null +++ b/app/serializers/api/admin/variant_simple_serializer.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +module Api + module Admin + class VariantSimpleSerializer < ActiveModel::Serializer + attributes :id, :name, :import_date, + :options_text, :unit_value, :unit_description, :unit_to_display, + :display_as, :display_name, :name_to_display, + :price, :on_demand, :on_hand + + has_many :variant_overrides + + def name + if object.full_name.present? + "#{object.name} - #{object.full_name}" + else + object.name + end + end + + def on_hand + return 0 if object.on_hand.nil? + + object.on_hand + end + + def price + object.price.nil? ? 0.to_f : object.price + end + end + end +end diff --git a/app/serializers/api/cached_enterprise_serializer.rb b/app/serializers/api/cached_enterprise_serializer.rb index 05677720db..8a6726e503 100644 --- a/app/serializers/api/cached_enterprise_serializer.rb +++ b/app/serializers/api/cached_enterprise_serializer.rb @@ -73,12 +73,16 @@ module Api # This results in 3 queries per enterprise def distributed_properties + return [] unless active + (distributed_product_properties + distributed_producer_properties).uniq do |property_object| property_object.property.presentation end end def distributed_product_properties + return [] unless active + properties = Spree::Property .joins(products: { variants: { exchanges: :order_cycle } }) .merge(Exchange.outgoing) @@ -91,6 +95,8 @@ module Api end def distributed_producer_properties + return [] unless active + properties = Spree::Property .joins( producer_properties: { diff --git a/app/services/checkout/stripe_redirect.rb b/app/services/checkout/stripe_redirect.rb index 40feebfde8..e7c40a4b9e 100644 --- a/app/services/checkout/stripe_redirect.rb +++ b/app/services/checkout/stripe_redirect.rb @@ -12,11 +12,8 @@ module Checkout def path return unless stripe_payment_method? - payment = @order.pending_payments.last - return unless payment&.checkout? - - payment.authorize! - raise unless payment.pending? + payment = OrderManagement::Subscriptions::StripeScaPaymentAuthorize.new(@order).call! + raise if @order.errors.any? field_with_url(payment) if url?(field_with_url(payment)) end diff --git a/app/services/order_cycle_form.rb b/app/services/order_cycle_form.rb index fa397aed44..f83b2c57e2 100644 --- a/app/services/order_cycle_form.rb +++ b/app/services/order_cycle_form.rb @@ -1,6 +1,6 @@ require 'open_food_network/permissions' -require 'open_food_network/proxy_order_syncer' require 'open_food_network/order_cycle_form_applicator' +require 'order_management/subscriptions/proxy_order_syncer' class OrderCycleForm def initialize(order_cycle, order_cycle_params, user) @@ -58,7 +58,7 @@ class OrderCycleForm return unless schedule_ids? return unless schedule_sync_required? - OpenFoodNetwork::ProxyOrderSyncer.new(subscriptions_to_sync).sync! + OrderManagement::Subscriptions::ProxyOrderSyncer.new(subscriptions_to_sync).sync! end def schedule_sync_required? diff --git a/app/services/order_payment_finder.rb b/app/services/order_payment_finder.rb index c28d0e139a..54b19654a3 100644 --- a/app/services/order_payment_finder.rb +++ b/app/services/order_payment_finder.rb @@ -1,14 +1,28 @@ # frozen_string_literal: true -module OrderPaymentFinder - def self.last_payment_method(order) - # `max_by` avoids additional database queries when payments are loaded - # already. There is usually only one payment and this shouldn't cause - # any overhead compared to `order(:created_at).last`. Using `last` - # without order is not deterministic. - # - # We are not using `updated_at` because all payments are touched when the - # order is updated and then all payments have the same `updated_at` value. - order.payments.max_by(&:created_at)&.payment_method +class OrderPaymentFinder + def initialize(order) + @order = order + end + + def last_payment + last(@order.payments) + end + + def last_pending_payment + last(@order.pending_payments) + end + + private + + # `max_by` avoids additional database queries when payments are loaded + # already. There is usually only one payment and this shouldn't cause + # any overhead compared to `order(:created_at).last`. Using `last` + # without order is not deterministic. + # + # We are not using `updated_at` because all payments are touched when the + # order is updated and then all payments have the same `updated_at` value. + def last(payments) + payments.max_by(&:created_at) end end diff --git a/app/services/products_renderer.rb b/app/services/products_renderer.rb index bfa7f4eaa5..72d61b50b1 100644 --- a/app/services/products_renderer.rb +++ b/app/services/products_renderer.rb @@ -40,7 +40,7 @@ class ProductsRenderer end def product_scoper - OpenFoodNetwork::ScopeProductToHub.new(distributor) + @product_scoper ||= OpenFoodNetwork::ScopeProductToHub.new(distributor) end def enterprise_fee_calculator diff --git a/app/services/shops_list_service.rb b/app/services/shops_list_service.rb new file mode 100644 index 0000000000..030010bea1 --- /dev/null +++ b/app/services/shops_list_service.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class ShopsListService + def open_shops + shops_list.ready_for_checkout.all + end + + def closed_shops + shops_list.not_ready_for_checkout.all + end + + private + + def shops_list + Enterprise + .activated + .visible + .is_distributor + .includes(address: [:state, :country]) + .includes(:properties) + .includes(supplied_products: :properties) + end +end diff --git a/app/services/subscription_estimator.rb b/app/services/subscription_estimator.rb deleted file mode 100644 index 6e4d7b0938..0000000000 --- a/app/services/subscription_estimator.rb +++ /dev/null @@ -1,63 +0,0 @@ -require 'open_food_network/scope_variant_to_hub' - -# Responsible for estimating prices and fees for subscriptions -# Used by SubscriptionForm as part of the create/update process -# The values calculated here are intended to be persisted in the db - -class SubscriptionEstimator - def initialize(subscription) - @subscription = subscription - end - - def estimate! - assign_price_estimates - assign_fee_estimates - end - - private - - attr_accessor :subscription - - delegate :subscription_line_items, :shipping_method, :payment_method, :shop, to: :subscription - - def assign_price_estimates - subscription_line_items.each do |item| - item.price_estimate = - price_estimate_for(item.variant, item.price_estimate_was) - end - end - - def price_estimate_for(variant, fallback) - return fallback unless fee_calculator && variant - - scoper.scope(variant) - fees = fee_calculator.indexed_fees_for(variant) - (variant.price + fees).to_d - end - - def fee_calculator - return @fee_calculator unless @fee_calculator.nil? - - next_oc = subscription.schedule.andand.current_or_next_order_cycle - return nil unless shop && next_oc - - @fee_calculator = OpenFoodNetwork::EnterpriseFeeCalculator.new(shop, next_oc) - end - - def scoper - OpenFoodNetwork::ScopeVariantToHub.new(shop) - end - - def assign_fee_estimates - subscription.shipping_fee_estimate = shipping_fee_estimate - subscription.payment_fee_estimate = payment_fee_estimate - end - - def shipping_fee_estimate - shipping_method.calculator.compute(subscription) - end - - def payment_fee_estimate - payment_method.calculator.compute(subscription) - end -end diff --git a/app/services/subscription_form.rb b/app/services/subscription_form.rb deleted file mode 100644 index 0458467fb5..0000000000 --- a/app/services/subscription_form.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'open_food_network/proxy_order_syncer' - -class SubscriptionForm - attr_accessor :subscription, :subscription_params, :order_update_issues, :validator, :order_syncer, :estimator - - delegate :json_errors, :valid?, to: :validator - delegate :order_update_issues, to: :order_syncer - - def initialize(subscription, subscription_params = {}) - @subscription = subscription - @subscription_params = subscription_params - @estimator = SubscriptionEstimator.new(subscription) - @validator = SubscriptionValidator.new(subscription) - @order_syncer = OrderSyncer.new(subscription) - end - - def save - subscription.assign_attributes(subscription_params) - return false unless valid? - - subscription.transaction do - estimator.estimate! - proxy_order_syncer.sync! - order_syncer.sync! - subscription.save! - end - end - - private - - def proxy_order_syncer - OpenFoodNetwork::ProxyOrderSyncer.new(subscription) - end -end diff --git a/app/services/subscription_validator.rb b/app/services/subscription_validator.rb deleted file mode 100644 index 4cce8a3af3..0000000000 --- a/app/services/subscription_validator.rb +++ /dev/null @@ -1,127 +0,0 @@ -# Encapsulation of all of the validation logic required for subscriptions -# Public interface consists of #valid? method provided by ActiveModel::Validations -# and #json_errors which compiles a serializable hash of errors - -class SubscriptionValidator - include ActiveModel::Naming - include ActiveModel::Conversion - include ActiveModel::Validations - - attr_reader :subscription - - validates :shop, :customer, :schedule, :shipping_method, :payment_method, presence: true - validates :bill_address, :ship_address, :begins_at, presence: true - validate :shipping_method_allowed? - validate :payment_method_allowed? - validate :payment_method_type_allowed? - validate :ends_at_after_begins_at? - validate :customer_allowed? - validate :schedule_allowed? - validate :credit_card_ok? - validate :subscription_line_items_present? - validate :requested_variants_available? - - delegate :shop, :customer, :schedule, :shipping_method, :payment_method, to: :subscription - delegate :bill_address, :ship_address, :begins_at, :ends_at, to: :subscription - delegate :subscription_line_items, to: :subscription - - def initialize(subscription) - @subscription = subscription - end - - def json_errors - errors.messages.each_with_object({}) do |(k, v), errors| - errors[k] = v.map { |msg| build_msg_from(k, msg) } - end - end - - private - - def shipping_method_allowed? - return unless shipping_method - return if shipping_method.distributors.include?(shop) - - errors.add(:shipping_method, :not_available_to_shop, shop: shop.name) - end - - def payment_method_allowed? - return unless payment_method - return if payment_method.distributors.include?(shop) - - errors.add(:payment_method, :not_available_to_shop, shop: shop.name) - end - - def payment_method_type_allowed? - return unless payment_method - return if Subscription::ALLOWED_PAYMENT_METHOD_TYPES.include? payment_method.type - - errors.add(:payment_method, :invalid_type) - end - - def ends_at_after_begins_at? - # Only validates ends_at if it is present - return if begins_at.blank? || ends_at.blank? - return if ends_at > begins_at - - errors.add(:ends_at, :after_begins_at) - end - - def customer_allowed? - return unless customer - return if customer.enterprise == shop - - errors.add(:customer, :does_not_belong_to_shop, shop: shop.name) - end - - def schedule_allowed? - return unless schedule - return if schedule.coordinators.include?(shop) - - errors.add(:schedule, :not_coordinated_by_shop, shop: shop.name) - end - - def credit_card_ok? - return unless customer && payment_method - return unless stripe_payment_method?(payment_method) - return errors.add(:payment_method, :charges_not_allowed) unless customer.allow_charges - return if customer.user.andand.default_card.present? - - errors.add(:payment_method, :no_default_card) - end - - def stripe_payment_method?(payment_method) - payment_method.type == "Spree::Gateway::StripeConnect" || - payment_method.type == "Spree::Gateway::StripeSCA" - end - - def subscription_line_items_present? - return if subscription_line_items.reject(&:marked_for_destruction?).any? - - errors.add(:subscription_line_items, :at_least_one_product) - end - - def requested_variants_available? - subscription_line_items.each { |sli| verify_availability_of(sli.variant) } - end - - def verify_availability_of(variant) - return if available_variant_ids.include? variant.id - - name = "#{variant.product.name} - #{variant.full_name}" - errors.add(:subscription_line_items, :not_available, name: name) - end - - def available_variant_ids - return @available_variant_ids if @available_variant_ids.present? - - subscription_variant_ids = subscription_line_items.map(&:variant_id) - @available_variant_ids = SubscriptionVariantsService.eligible_variants(shop) - .where(id: subscription_variant_ids).pluck(:id) - end - - def build_msg_from(k, msg) - return msg[1..-1] if msg.starts_with?("^") - - errors.full_message(k, msg) - end -end diff --git a/app/services/subscription_variants_service.rb b/app/services/subscription_variants_service.rb deleted file mode 100644 index fbdef71e56..0000000000 --- a/app/services/subscription_variants_service.rb +++ /dev/null @@ -1,39 +0,0 @@ -class SubscriptionVariantsService - # Includes the following variants: - # - Variants of permitted producers - # - Variants of hub - # - Variants that are in outgoing exchanges where the hub is receiver - def self.eligible_variants(distributor) - variant_conditions = ["spree_products.supplier_id IN (?)", permitted_producer_ids(distributor)] - exchange_variant_ids = outgoing_exchange_variant_ids(distributor) - if exchange_variant_ids.present? - variant_conditions[0] << " OR spree_variants.id IN (?)" - variant_conditions << exchange_variant_ids - end - - Spree::Variant.joins(:product).where(is_master: false).where(*variant_conditions) - end - - def self.in_open_and_upcoming_order_cycles?(distributor, schedule, variant) - scope = ExchangeVariant.joins(exchange: { order_cycle: :schedules }) - .where(variant_id: variant, exchanges: { incoming: false, receiver_id: distributor }) - .merge(OrderCycle.not_closed) - scope = scope.where(schedules: { id: schedule }) - scope.any? - end - - def self.permitted_producer_ids(distributor) - other_permitted_producer_ids = EnterpriseRelationship.joins(:parent) - .permitting(distributor.id).with_permission(:add_to_order_cycle) - .merge(Enterprise.is_primary_producer) - .pluck(:parent_id) - - other_permitted_producer_ids | [distributor.id] - end - - def self.outgoing_exchange_variant_ids(distributor) - ExchangeVariant.select("DISTINCT exchange_variants.variant_id").joins(:exchange) - .where(exchanges: { incoming: false, receiver_id: distributor.id }) - .pluck(:variant_id) - end -end diff --git a/app/services/subscriptions_count.rb b/app/services/subscriptions_count.rb deleted file mode 100644 index ee1126c0d2..0000000000 --- a/app/services/subscriptions_count.rb +++ /dev/null @@ -1,20 +0,0 @@ -class SubscriptionsCount - def initialize(order_cycles) - @order_cycles = order_cycles - end - - def for(order_cycle_id) - active[order_cycle_id] || 0 - end - - private - - attr_accessor :order_cycles - - def active - return @active unless @active.nil? - return @active = [] if order_cycles.blank? - - @active ||= ProxyOrder.not_canceled.group(:order_cycle_id).where(order_cycle_id: order_cycles).count - end -end diff --git a/app/services/variant_overrides_indexed.rb b/app/services/variant_overrides_indexed.rb new file mode 100644 index 0000000000..2c2ead6e44 --- /dev/null +++ b/app/services/variant_overrides_indexed.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +# Produces mappings of variant overrides by distributor id and variant id +# The primary use case for data structured in this way is for injection into +# the initializer of the OpenFoodNetwork::ScopeVariantToHub class + +class VariantOverridesIndexed + def initialize(variant_ids, distributor_ids) + @variant_ids = variant_ids + @distributor_ids = distributor_ids + end + + def indexed + scoped_variant_overrides.each_with_object(hash_of_hashes) do |variant_override, indexed| + indexed[variant_override.hub_id][variant_override.variant] = variant_override + end + end + + private + + attr_reader :variant_ids, :distributor_ids + + def scoped_variant_overrides + VariantOverride + .joins(:variant) + .preload(:variant) + .where( + hub_id: distributor_ids, + variant_id: variant_ids, + ) + end + + def hash_of_hashes + Hash.new { |hash, key| hash[key] = {} } + end +end diff --git a/app/services/variants_stock_levels.rb b/app/services/variants_stock_levels.rb index 73f6e68278..f06002db19 100644 --- a/app/services/variants_stock_levels.rb +++ b/app/services/variants_stock_levels.rb @@ -8,10 +8,13 @@ class VariantsStockLevels variant_stock_levels = variant_stock_levels(order.line_items) order_variant_ids = variant_stock_levels.keys - missing_variant_ids = requested_variant_ids - order_variant_ids - missing_variant_ids.each do |variant_id| - variant = scoped_variant(order.distributor, Spree::Variant.find(variant_id)) - variant_stock_levels[variant_id] = { quantity: 0, max_quantity: 0, on_hand: variant.on_hand, on_demand: variant.on_demand } + missing_variants = Spree::Variant.includes(:stock_items). + where(id: (requested_variant_ids - order_variant_ids)) + + missing_variants.each do |missing_variant| + variant = scoped_variant(order.distributor, missing_variant) + variant_stock_levels[variant.id] = + { quantity: 0, max_quantity: 0, on_hand: variant.on_hand, on_demand: variant.on_demand } end variant_stock_levels diff --git a/app/views/admin/enterprise_relationships/_enterprise_relationship.html.haml b/app/views/admin/enterprise_relationships/_enterprise_relationship.html.haml index c1c6ccbc4b..c6f630ba48 100644 --- a/app/views/admin/enterprise_relationships/_enterprise_relationship.html.haml +++ b/app/views/admin/enterprise_relationships/_enterprise_relationship.html.haml @@ -6,6 +6,7 @@ %td %ul %li{"ng-repeat" => "permission in enterprise_relationship.permissions"} - to {{ EnterpriseRelationships.permission_presentation(permission.name) }} + = t 'admin_enterprise_relationships_to' + {{ EnterpriseRelationships.permission_presentation(permission.name) }} %td.actions %a.delete-enterprise-relationship.icon-trash.no-text{'ng-click' => 'delete(enterprise_relationship)'} diff --git a/app/views/admin/enterprise_relationships/_form.html.haml b/app/views/admin/enterprise_relationships/_form.html.haml index 958ce53074..e79da0b144 100644 --- a/app/views/admin/enterprise_relationships/_form.html.haml +++ b/app/views/admin/enterprise_relationships/_form.html.haml @@ -13,7 +13,8 @@ %div{"ng-repeat" => "permission in EnterpriseRelationships.all_permissions"} %label %input{type: "checkbox", "ng-model" => "permissions[permission]"} - to {{ EnterpriseRelationships.permission_presentation(permission) }} + = t 'admin_enterprise_relationships_to' + {{ EnterpriseRelationships.permission_presentation(permission) }} %td.actions %input{type: "button", value: t(:admin_enterprise_relationships_button_create), "ng-click" => "create()"} .errors {{ EnterpriseRelationships.create_errors }} diff --git a/app/views/checkout/_summary.html.haml b/app/views/checkout/_summary.html.haml index 0ca86fcb2e..fa3bd6f4ed 100644 --- a/app/views/checkout/_summary.html.haml +++ b/app/views/checkout/_summary.html.haml @@ -31,5 +31,4 @@ //= f.submit "Purchase", class: "button", "ofn-focus" => "accordion['payment']" %a.button.secondary{href: main_app.cart_url} - %i.ofn-i_008-caret-left = t :checkout_back_to_cart diff --git a/app/views/shops/_hubs.html.haml b/app/views/shops/_hubs.html.haml index 3d83d28923..6c05561da0 100644 --- a/app/views/shops/_hubs.html.haml +++ b/app/views/shops/_hubs.html.haml @@ -26,8 +26,11 @@ %a{href: "", "ng-click" => "showDistanceMatches()"} = t :hubs_distance_filter, location: "{{ nameMatchesFiltered[0].name }}" .more-controls - %a.button{href: "", ng: {click: "showClosedShops()", show: "!show_closed"}} - = t '.show_closed_shops' - %a.button{href: "", ng: {click: "hideClosedShops()", show: "show_closed"}} - = t '.hide_closed_shops' + %img.spinner.text-center{ng: {show: "closed_shops_loading"}, src: "/assets/spinning-circles.svg" } + %span{ng: {if: "!show_closed", cloak: true}} + %a.button{href: "", ng: {click: "showClosedShops()"}} + = t '.show_closed_shops' + %span{ng: {if: "show_closed", cloak: true}} + %a.button{href: "", ng: {click: "hideClosedShops()"}} + = t '.hide_closed_shops' %a.button{href: main_app.map_path}= t '.show_on_map' diff --git a/app/views/spree/admin/orders/_shipment_manifest.html.haml b/app/views/spree/admin/orders/_shipment_manifest.html.haml index 8651ee3188..611cf4a5d7 100644 --- a/app/views/spree/admin/orders/_shipment_manifest.html.haml +++ b/app/views/spree/admin/orders/_shipment_manifest.html.haml @@ -1,5 +1,6 @@ - shipment.manifest.each do |item| - line_item = order.find_line_item_by_variant(item.variant) + - break if line_item.blank? %tr.stock-item{ "data-item-quantity" => "#{item.quantity}" } %td.item-image diff --git a/app/views/spree/admin/products/_display_as.html.haml b/app/views/spree/admin/products/_display_as.html.haml index 04af12bdce..95636694c3 100644 --- a/app/views/spree/admin/products/_display_as.html.haml +++ b/app/views/spree/admin/products/_display_as.html.haml @@ -1,4 +1,5 @@ .three.columns.omega{ "ng-if" => "product.variant_unit_with_scale != 'items'" } = f.field_container :display_as do = f.label :product_display_as, t('.display_as') + %span.required * %input#product_display_as.fullwidth{name: "product[display_as]", placeholder: "{{ placeholder_text }}", type: "text"} diff --git a/app/views/spree/admin/products/_form.html.haml b/app/views/spree/admin/products/_form.html.haml index cbc7718325..616f7977f3 100644 --- a/app/views/spree/admin/products/_form.html.haml +++ b/app/views/spree/admin/products/_form.html.haml @@ -16,11 +16,6 @@ = sanitize(@product.description) = f.error_message_on :description - = f.field_container :taxons do - = f.label :taxon_ids, t(:taxons) - %br - = f.hidden_field :taxon_ids, :value => @product.taxon_ids.join(',') - .right.four.columns.omega .variant_units_form{ 'ng-app' => 'admin.products', 'ng-controller' => 'editUnitsCtrl' } diff --git a/app/views/spree/admin/products/new.html.haml b/app/views/spree/admin/products/new.html.haml index 6b3259c5e4..34665fbdcb 100644 --- a/app/views/spree/admin/products/new.html.haml +++ b/app/views/spree/admin/products/new.html.haml @@ -38,6 +38,7 @@ .three.columns.omega{ 'ng-show' => "product.variant_unit_with_scale == 'items'" } = f.field_container :unit_name do = f.label :product_variant_unit_name, t(".unit_name") + %span.required * %input.fullwidth{ id: 'product_variant_unit_name','ng-model' => 'product.variant_unit_name', :name => 'product[variant_unit_name]', :placeholder => t('admin.products.unit_name_placeholder'), :type => 'text' } .twelve.columns.alpha .six.columns.alpha diff --git a/app/views/spree/admin/taxons/search.rabl b/app/views/spree/admin/taxons/search.rabl deleted file mode 100644 index 5214337d12..0000000000 --- a/app/views/spree/admin/taxons/search.rabl +++ /dev/null @@ -1,4 +0,0 @@ -object false -child(@taxons => :taxons) do - attributes :name, :pretty_name, :id -end diff --git a/app/views/spree/order_mailer/_payment.html.haml b/app/views/spree/order_mailer/_payment.html.haml index 60fc1056f4..85ad234cda 100644 --- a/app/views/spree/order_mailer/_payment.html.haml +++ b/app/views/spree/order_mailer/_payment.html.haml @@ -8,7 +8,7 @@ = t :email_payment_summary %h4 = t :email_payment_method - %strong= OrderPaymentFinder.last_payment_method(@order)&.name + %strong= last_payment_method(@order)&.name %p - %em= OrderPaymentFinder.last_payment_method(@order)&.description + %em= last_payment_method(@order)&.description %p   diff --git a/app/views/spree/orders/form/_cart_links.html.haml b/app/views/spree/orders/form/_cart_links.html.haml index d787b9c50f..8da012cd78 100644 --- a/app/views/spree/orders/form/_cart_links.html.haml +++ b/app/views/spree/orders/form/_cart_links.html.haml @@ -1,9 +1,5 @@ .row.links{'data-hook' => "cart_buttons"} - .columns.large-8{"data-hook" => ""} - %a.button.large.secondary{href: current_shop_products_path} - %i.ofn-i_008-caret-left - = t :orders_edit_continue - .columns.large-4.text-right - %a#checkout-link.button.large.primary{href: main_app.checkout_path} - = t :orders_edit_checkout - %i.ofn-i_007-caret-right + %a.button.large.secondary{href: current_shop_products_path} + = t :orders_edit_continue + %a#checkout-link.button.large.primary.right{href: main_app.checkout_path} + = t :orders_edit_checkout diff --git a/app/views/spree/orders/form/_update_buttons.html.haml b/app/views/spree/orders/form/_update_buttons.html.haml index 22ede28e57..5757d1742f 100644 --- a/app/views/spree/orders/form/_update_buttons.html.haml +++ b/app/views/spree/orders/form/_update_buttons.html.haml @@ -3,11 +3,9 @@ - if current_order.nil? || current_order.distributor.nil? || current_order.distributor == @order.distributor - if current_order&.line_items.present? = link_to main_app.cart_path, :class => "button expand" do - %i.ofn-i_008-caret-left = t(:order_back_to_cart) - else = link_to "#{main_app.enterprise_shop_path(@order.distributor)}#/shop", class: "button expand" do - %i.ofn-i_008-caret-left = t(:order_back_to_store) - else   diff --git a/app/views/spree/shared/_order_details.html.haml b/app/views/spree/shared/_order_details.html.haml index 22c8ccdf8f..f4861d8148 100644 --- a/app/views/spree/shared/_order_details.html.haml +++ b/app/views/spree/shared/_order_details.html.haml @@ -13,9 +13,9 @@ .pad .text-big = t :order_payment - %strong= OrderPaymentFinder.last_payment_method(order)&.name + %strong= last_payment_method(order)&.name %p.text-small.text-skinny.pre-line - %em= OrderPaymentFinder.last_payment_method(order)&.description + %em= last_payment_method(order)&.description .order-summary.text-small %strong diff --git a/app/views/spree/users/_open_orders.html.haml b/app/views/spree/users/_open_orders.html.haml index ed5e43b9b5..2b8578a658 100644 --- a/app/views/spree/users/_open_orders.html.haml +++ b/app/views/spree/users/_open_orders.html.haml @@ -13,7 +13,8 @@ %tr.order-row %td.order1 %a{"ng-href" => "{{::order.path}}", "ng-bind" => "::order.number"} - %td.order2{"ng-bind" => "::Orders.shopsByID[order.shop_id].name"} + %td.order2 + %a{"ng-href" => "{{::Orders.shopsByID[order.shop_id].hash}}#{main_app.shop_path}", "ng-bind" => "::Orders.shopsByID[order.shop_id].name"} %td.order3.show-for-large-up{"ng-bind" => "::order.changes_allowed_until"} %td.order4.show-for-large-up{"ng-bind" => "::order.item_count"} %td.order5.text-right{"ng-class" => "{'credit' : order.total < 0, 'debit' : order.total > 0, 'paid' : order.total == 0}","ng-bind" => "::order.total | localizeCurrency"} diff --git a/app/views/spree/users/_past_orders.html.haml b/app/views/spree/users/_past_orders.html.haml index 2abf5a273e..4ded53858d 100644 --- a/app/views/spree/users/_past_orders.html.haml +++ b/app/views/spree/users/_past_orders.html.haml @@ -13,7 +13,8 @@ %tr.order-row %td.order1 %a{"ng-href" => "{{::order.path}}", "ng-bind" => "::order.number"} - %td.order2{"ng-bind" => "::Orders.shopsByID[order.shop_id].name"} + %td.order2 + %a{"ng-href" => "{{::Orders.shopsByID[order.shop_id].hash}}#{main_app.shop_path}", "ng-bind" => "::Orders.shopsByID[order.shop_id].name"} %td.order3.show-for-large-up{"ng-bind" => "::order.completed_at"} %td.order4.show-for-large-up{"ng-bind" => "::order.item_count"} %td.order5.text-right{"ng-class" => "{'debit': order.payment_state != 'paid', 'credit': order.payment_state == 'paid'}","ng-bind" => "::order.total | localizeCurrency"} diff --git a/config.ru b/config.ru index 45a4379990..e2d03deb47 100644 --- a/config.ru +++ b/config.ru @@ -1,4 +1,17 @@ # This file is used by Rack-based servers to start the application. +if ENV.fetch('KILL_UNICORNS', false) && ['production', 'staging'].include?(ENV['RAILS_ENV']) + # Gracefully restart individual unicorn workers if they have: + # - performed between 25000 and 30000 requests + # - grown in memory usage to between 700 and 850 MB + require 'unicorn/worker_killer' + use Unicorn::WorkerKiller::MaxRequests, + ENV.fetch('UWK_REQS_MIN', 25_000).to_i, + ENV.fetch('UWK_REQS_MAX', 30_000).to_i + use Unicorn::WorkerKiller::Oom, + ( ENV.fetch('UWK_MEM_MIN', 700).to_i * (1024**2) ), + ( ENV.fetch('UWK_MEM_MAX', 850).to_i * (1024**2) ) +end + require ::File.expand_path('../config/environment', __FILE__) run Openfoodnetwork::Application diff --git a/config/database.yml b/config/database.yml index 99ed20078d..20c6760868 100644 --- a/config/database.yml +++ b/config/database.yml @@ -1,7 +1,7 @@ defaults: &defaults adapter: postgresql encoding: unicode - pool: 5 + pool: <%= ENV.fetch('OFN_DB_POOL', 5) %> host: <%= ENV.fetch('OFN_DB_HOST', 'localhost') %> username: <%= ENV.fetch('OFN_DB_USERNAME', 'ofn') %> password: <%= ENV.fetch('OFN_DB_PASSWORD', 'f00d') %> diff --git a/config/initializers/datadog.rb b/config/initializers/datadog.rb index eb82b340ff..c1265c7802 100644 --- a/config/initializers/datadog.rb +++ b/config/initializers/datadog.rb @@ -4,5 +4,6 @@ if ENV['DATADOG_RAILS_APM'] c.use :delayed_job, service_name: 'delayed_job' c.use :dalli, service_name: 'memcached' c.analytics_enabled = true + c.runtime_metrics_enabled = true end end diff --git a/config/locales/ar.yml b/config/locales/ar.yml index b7c5a59b6c..d364366dff 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -55,7 +55,7 @@ ar: messages: inclusion: "غير مدرجة في القائمة" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^ الرجاء إضافة منتج واحد على الأقل" @@ -2725,6 +2725,8 @@ ar: location: "الموقع" count_on_hand: "الاعتماد على المتوفر" quantity: "الكمية" + on_demand: "على الطلب" + on_hand: "متوفر" package_from: "التعبئة من" item_description: "وصف السلعة" price: "السعر" diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 35a2a9657a..2ffb83cecc 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -31,6 +31,10 @@ ca: taken: "Ja hi ha un compte per a aquest correu electrònic. Si us plau, inicia sessió o restableix la contrasenya." spree/order: no_card: No hi ha targetes de crèdit autoritzades disponibles per carregar + spree/credit_card: + attributes: + base: + card_expired: "Ha expirat" order_cycle: attributes: orders_close_at: @@ -55,7 +59,7 @@ ca: messages: inclusion: "no està inclòs a la llista" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Afegiu com a mínim un producte" @@ -665,9 +669,9 @@ ca: primary_producer: Productora principal? primary_producer_tip: Selecciona "Productora" si ets productora principal d'aliments. producer: Productora - any: Cap - none: No productora - own: Propi + any: Qualsevol + none: Cap + own: Propis sells: Ven sells_tip: "Cap: l'organització no ven als clients directament.
Propietari: l'organització ven productes propis als clients.
Qualsevol: l'organització pot vendre productes propis o d'altres empreses.
" visible_in_search: Visible a la cerca? @@ -1452,13 +1456,13 @@ ca: email_payment_summary: Resum del pagament email_payment_method: "Pagament a través de:" email_so_placement_intro_html: "Tens una nova comanda amb %{distributor} " - email_so_placement_details_html: "Aquests són els detalls de la comanda de %{distributor} :" + email_so_placement_details_html: "Aquests són els detalls de la comanda de %{distributor} :" email_so_placement_changes: "Malauradament, no tots els productes que has demanat estaven disponibles. Les quantitats originals que has sol·licitat apareixen ratllades a sota." email_so_payment_success_intro_html: "S'ha processat un pagament automàtic per a la vostra comanda des de %{distributor} ." email_so_placement_explainer_html: "Aquesta comanda s'ha creat automàticament per tu." - email_so_edit_true_html: "Potd fer canvis fins que les comandes es tanquin el %{orders_close_at}." + email_so_edit_true_html: "Pots fer canvis fins que les comandes es tanquin el %{orders_close_at}." email_so_edit_false_html: "Pots veure detalls d'aquesta comanda en qualsevol moment." - email_so_contact_distributor_html: "Si tens alguna pregunta pots contactar amb %{distributor} a través d'%{email}." + email_so_contact_distributor_html: "Si tens alguna pregunta pots contactar amb %{distributor} a través d'%{email}." email_so_contact_distributor_to_change_order_html: "Aquesta comanda s'ha creat automàticament per a vostè. Podeu fer canvis fins que les comandes es tanquin a %{orders_close_at} contactant a %{distributor} a través d'%{email}." email_so_confirmation_intro_html: "La teva comanda amb %{distributor} ja està confirmada" email_so_confirmation_explainer_html: "Vas realitzar aquesta comanda automàticament i ara s'ha finalitzat." @@ -2762,6 +2766,8 @@ ca: location: "Ubicació" count_on_hand: "Compte disponible" quantity: "Quantitat" + on_demand: "Sota demanda" + on_hand: "Disponibles" package_from: "perfil de" item_description: "Descripció de l'article" price: "Preu" diff --git a/config/locales/de_DE.yml b/config/locales/de_DE.yml index bfdacc350e..95764417ea 100644 --- a/config/locales/de_DE.yml +++ b/config/locales/de_DE.yml @@ -59,7 +59,7 @@ de_DE: messages: inclusion: "ist in der Liste nicht enthalten" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^ Bitte fügen Sie mindestens ein Produkt hinzu" @@ -2765,6 +2765,8 @@ de_DE: location: "Ort" count_on_hand: "Zählen Sie zur Hand" quantity: "Menge" + on_demand: "Unbegrenzt" + on_hand: "Verfügbar" package_from: "Paket von" item_description: "Artikelbeschreibung" price: "Preis" diff --git a/config/locales/en.yml b/config/locales/en.yml index 039cc3c8eb..07a8a849c2 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -80,7 +80,7 @@ en: messages: inclusion: "is not included in the list" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Please add at least one product" @@ -362,6 +362,7 @@ en: choose: "Choose..." please_select: Please select... + column_save_as_default: Save As Default columns: Columns actions: Actions viewing: "Viewing: %{current_view_name}" @@ -2053,6 +2054,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using admin_enterprise_relationships_permits: "permits" admin_enterprise_relationships_seach_placeholder: "Search" admin_enterprise_relationships_button_create: "Create" + admin_enterprise_relationships_to: "to" admin_enterprise_groups: "Enterprise Groups" admin_enterprise_groups_name: "Name" admin_enterprise_groups_owner: "Owner" @@ -2828,6 +2830,14 @@ See the %{link} to find out more about %{sitename}'s features and to start using order_management: reports: + enterprise_fee_summaries: + filters: + date_range: "Date Range" + report_format_csv: "Download as CSV" + generate_report: "Generate Report" + report: + none: "None" + select_and_search: "Select filters and click on GENERATE REPORT to access your data." enterprise_fee_summary: date_end_before_start_error: "must be after start" parameter_not_allowed_error: "You are not authorized to use one or more selected filters for this report." @@ -2910,6 +2920,8 @@ See the %{link} to find out more about %{sitename}'s features and to start using location: "Location" count_on_hand: "Count On Hand" quantity: "Quantity" + on_demand: "On Demand" + on_hand: "On Hand" package_from: "package from" item_description: "Item Description" price: "Price" @@ -3331,14 +3343,6 @@ See the %{link} to find out more about %{sitename}'s features and to start using bulk_coop_allocation: 'Bulk Co-op - Allocation' bulk_coop_packing_sheets: 'Bulk Co-op - Packing Sheets' bulk_coop_customer_payments: 'Bulk Co-op - Customer Payments' - enterprise_fee_summaries: - filters: - date_range: "Date Range" - report_format_csv: "Download as CSV" - generate_report: "Generate Report" - report: - none: "None" - select_and_search: "Select filters and click on GENERATE REPORT to access your data." users: index: listing_users: "Listing Users" @@ -3384,6 +3388,9 @@ See the %{link} to find out more about %{sitename}'s features and to start using producer_name: "Producer" unit: "Unit" general_settings: + shared: + sortable_header: + name: "Name" edit: legal_settings: "Legal Settings" cookies_consent_banner_toggle: "Display cookies consent banner" diff --git a/config/locales/en_AU.yml b/config/locales/en_AU.yml index ecc81b40ce..47288e5a5e 100644 --- a/config/locales/en_AU.yml +++ b/config/locales/en_AU.yml @@ -53,7 +53,7 @@ en_AU: payment_method_ids: "Payment Methods" errors: models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Please add at least one product" @@ -2676,6 +2676,8 @@ en_AU: location: "Location" count_on_hand: "Count On Hand" quantity: "Quantity" + on_demand: "On Demand" + on_hand: "On Hand" package_from: "package from" item_description: "Item Description" price: "Price" diff --git a/config/locales/en_BE.yml b/config/locales/en_BE.yml index 7f6c05a7c3..5be45d93e5 100644 --- a/config/locales/en_BE.yml +++ b/config/locales/en_BE.yml @@ -53,7 +53,7 @@ en_BE: payment_method_ids: "Payment Methods" errors: models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Please add at least one product" @@ -2632,6 +2632,8 @@ en_BE: location: "Location" count_on_hand: "Count On Hand" quantity: "Quantity" + on_demand: "On Demand" + on_hand: "On Hand" package_from: "package from" item_description: "Item Description" price: "Price" diff --git a/config/locales/en_CA.yml b/config/locales/en_CA.yml index 193b756e57..9e522830cd 100644 --- a/config/locales/en_CA.yml +++ b/config/locales/en_CA.yml @@ -55,7 +55,7 @@ en_CA: messages: inclusion: "is not included in the list" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Please add at least one product" @@ -2754,6 +2754,8 @@ en_CA: location: "Location" count_on_hand: "Count On Hand" quantity: "Quantity" + on_demand: "On Demand" + on_hand: "On Hand" package_from: "package from" item_description: "Item Description" price: "Price" diff --git a/config/locales/en_DE.yml b/config/locales/en_DE.yml index 8c81c87986..711d8e4b30 100644 --- a/config/locales/en_DE.yml +++ b/config/locales/en_DE.yml @@ -53,7 +53,7 @@ en_DE: payment_method_ids: "Payment Methods" errors: models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Please add at least one product" @@ -2644,6 +2644,8 @@ en_DE: location: "Location" count_on_hand: "Count On Hand" quantity: "Quantity" + on_demand: "On Demand" + on_hand: "On Hand" package_from: "package from" item_description: "Item Description" price: "Price" diff --git a/config/locales/en_FR.yml b/config/locales/en_FR.yml index 5665f4422b..c242e06622 100644 --- a/config/locales/en_FR.yml +++ b/config/locales/en_FR.yml @@ -59,7 +59,7 @@ en_FR: messages: inclusion: "is not included in the list" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Please add at least one product" @@ -1919,6 +1919,7 @@ en_FR: admin_enterprise_relationships_permits: "permits" admin_enterprise_relationships_seach_placeholder: "Search" admin_enterprise_relationships_button_create: "Create" + admin_enterprise_relationships_to: "to" admin_enterprise_groups: "Enterprise Groups" admin_enterprise_groups_name: "Name" admin_enterprise_groups_owner: "Owner" @@ -2760,6 +2761,8 @@ en_FR: location: "Location" count_on_hand: "Count On Hand" quantity: "Quantity" + on_demand: "On Demand" + on_hand: "On Hand" package_from: "package from" item_description: "Item Description" price: "Price" diff --git a/config/locales/en_GB.yml b/config/locales/en_GB.yml index dfa17eb46e..3f69dae27f 100644 --- a/config/locales/en_GB.yml +++ b/config/locales/en_GB.yml @@ -31,6 +31,10 @@ en_GB: taken: "There's already an account for this email. Please login or reset your password." spree/order: no_card: There are no authorised credit cards available to charge + spree/credit_card: + attributes: + base: + card_expired: "has expired" order_cycle: attributes: orders_close_at: @@ -55,7 +59,7 @@ en_GB: messages: inclusion: "is not included in the list" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Please add at least one product" @@ -2762,6 +2766,8 @@ en_GB: location: "Location" count_on_hand: "Count In Stock" quantity: "Quantity" + on_demand: "Unlimited" + on_hand: "In Stock" package_from: "package from" item_description: "Item Description" price: "Price" diff --git a/config/locales/en_NZ.yml b/config/locales/en_NZ.yml index 15ad362a51..e54cc75239 100644 --- a/config/locales/en_NZ.yml +++ b/config/locales/en_NZ.yml @@ -31,6 +31,10 @@ en_NZ: taken: "There's already an account for this email. Please login or reset your password." spree/order: no_card: There are no authorised credit cards available to charge + spree/credit_card: + attributes: + base: + card_expired: "has expired" order_cycle: attributes: orders_close_at: @@ -55,7 +59,7 @@ en_NZ: messages: inclusion: "is not included in the list" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Please add at least one product" @@ -867,6 +871,7 @@ en_NZ: distributor: "Distributor" products: "Products" tags: "Tags" + delivery_details: "Delivery Details" fees: "Fees" previous: "Previous" save: "Save" @@ -2755,6 +2760,8 @@ en_NZ: location: "Location" count_on_hand: "Count On Hand" quantity: "Quantity" + on_demand: "On Demand" + on_hand: "On Hand" package_from: "package from" item_description: "Item Description" price: "Price" diff --git a/config/locales/en_PH.yml b/config/locales/en_PH.yml new file mode 100644 index 0000000000..3d07dac662 --- /dev/null +++ b/config/locales/en_PH.yml @@ -0,0 +1,3375 @@ +en_PH: + language_name: "English" + activerecord: + attributes: + enterprise_fee: + fee_type: Fee Type + spree/order: + payment_state: Payment State + shipment_state: Shipment State + completed_at: Completed At + number: Number + state: State + email: Customer E-Mail + spree/payment: + amount: Amount + spree/product: + primary_taxon: "Product Category" + supplier: "Supplier" + shipping_category_id: "Shipping Category" + variant_unit: "Variant Unit" + variant_unit_name: "Variant Unit Name" + spree/credit_card: + base: "Credit Card" + order_cycle: + orders_close_at: Close date + errors: + models: + spree/user: + attributes: + email: + taken: "There's already an account for this email. Please login or reset your password." + spree/order: + no_card: There are no authorised credit cards available to charge + spree/credit_card: + attributes: + base: + card_expired: "has expired" + order_cycle: + attributes: + orders_close_at: + after_orders_open_at: must be after open date + variant_override: + count_on_hand: + using_producer_stock_settings_but_count_on_hand_set: "must be blank because using producer stock settings" + on_demand_but_count_on_hand_set: "must be blank if on demand" + limited_stock_but_no_count_on_hand: "must be specified because forcing limited stock" + activemodel: + attributes: + order_management/reports/enterprise_fee_summary/parameters: + start_at: "Start" + end_at: "End" + distributor_ids: "Hubs" + producer_ids: "Producers" + order_cycle_ids: "Order Cycles" + enterprise_fee_ids: "Fees Names" + shipping_method_ids: "Shipping Methods" + payment_method_ids: "Payment Methods" + errors: + messages: + inclusion: "is not included in the list" + models: + order_management/subscriptions/validator: + attributes: + subscription_line_items: + at_least_one_product: "^Please add at least one product" + not_available: "^%{name} is not available from the selected schedule" + ends_at: + after_begins_at: "must be after begins at" + customer: + does_not_belong_to_shop: "does not belong to %{shop}" + schedule: + not_coordinated_by_shop: "is not coordinated by %{shop}" + payment_method: + not_available_to_shop: "is not available to %{shop}" + invalid_type: "must be a Cash or Stripe method" + charges_not_allowed: "^Credit card charges are not allowed by this customer" + no_default_card: "^No default card available for this customer" + shipping_method: + not_available_to_shop: "is not available to %{shop}" + devise: + confirmations: + send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes." + failed_to_send: "An error occurred whilst sending your confirmation email." + resend_confirmation_email: "Resend confirmation email." + confirmed: "Thanks for confirming your email! You can now log in." + not_confirmed: "Your email address could not be confirmed. Perhaps you have already completed this step?" + user_confirmations: + spree_user: + send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes." + confirmation_sent: "Email confirmation sent" + confirmation_not_sent: "Error sending confirmation email" + user_registrations: + spree_user: + signed_up_but_unconfirmed: "A message with a confirmation link has been sent to your email address. Please open the link to activate your account." + unknown_error: "Something went wrong while creating your account. Check your email address and try again." + failure: + invalid: | + Invalid email or password. + Were you a guest last time? Perhaps you need to create an account or reset your password. + unconfirmed: "You have to confirm your account before continuing." + already_registered: "This email address is already registered. Please log in to continue, or go back and use another email address." + success: + logged_in_succesfully: "Logged in successfully" + user_passwords: + spree_user: + updated_not_active: "Your password has been reset, but your email has not been confirmed yet." + updated: "Your password was changed successfully. You are now signed in." + send_instructions: "You will receive an email with instructions about how to confirm your account in a few minutes." + models: + order_cycle: + cloned_order_cycle_name: "COPY OF %{order_cycle}" + validators: + date_time_string_validator: + not_string_error: "must be a string" + invalid_format_error: "must be valid" + integer_array_validator: + not_array_error: "must be an array" + invalid_element_error: "must contain only valid integers" + enterprise_mailer: + confirmation_instructions: + subject: "Please confirm the email address for %{enterprise}" + welcome: + subject: "%{enterprise} is now on %{sitename}" + email_welcome: "Welcome" + email_registered: "is now part of" + email_userguide_html: "The User Guide with detailed support for setting up your Producer or Hub is here: %{link}" + 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}" + join_community: "Join the community" + invite_manager: + subject: "%{enterprise} has invited you to be a manager" + producer_mailer: + order_cycle: + subject: "Order cycle report for %{producer}" + shipment_mailer: + shipped_email: + dear_customer: "Dear Customer," + instructions: "Your order has been shipped" + shipment_summary: "Shipment Summary" + subject: "Shipment Notification" + thanks: "Thank you for your business." + track_information: "Tracking Information: %{tracking}" + track_link: "Tracking Link: %{url}" + subscription_mailer: + placement_summary_email: + subject: A summary of recently placed subscription orders + greeting: "Hi %{name}," + intro: "Below is a summary of the subscription orders that have just been placed for %{shop}." + confirmation_summary_email: + subject: A summary of recently confirmed subscription orders + greeting: "Hi %{name}," + intro: "Below is a summary of the subscription orders that have just been finalised for %{shop}." + summary_overview: + total: A total of %{count} subscriptions were marked for automatic processing. + success_zero: Of these, none were processed successfully. + success_some: Of these, %{count} were processed successfully. + success_all: All were processed successfully. + issues: Details of the issues encountered are provided below. + summary_detail: + no_message_provided: No error message provided + changes: + title: Insufficient Stock (%{count} orders) + explainer: These orders were processed but insufficient stock was available for some requested items + empty: + title: No Stock (%{count} orders) + explainer: These orders were unable to be processed because no stock was available for any requested items + complete: + title: Already Processed (%{count} orders) + explainer: These orders were already marked as complete, and were therefore left untouched + processing: + title: Error Encountered (%{count} orders) + explainer: Automatic processing of these orders failed due to an error. The error has been listed where possible. + failed_payment: + title: Failed Payment (%{count} orders) + explainer: Automatic processing of payment for these orders failed due to an error. The error has been listed where possible. + other: + title: Other Failure (%{count} orders) + explainer: Automatic processing of these orders failed for an unknown reason. This should not occur, please contact us if you are seeing this. + home: "OFN" + title: Open Food Network + welcome_to: 'Welcome to ' + site_meta_description: "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…" + search_by_name: Search by name or city... + producers_join: Philippine producers are now welcome to join the Open Food Network. + charges_sales_tax: Charges VAT? + print_invoice: "Print Invoice" + print_ticket: "Print Ticket" + select_ticket_printer: "Select printer for tickets" + send_invoice: "Send Invoice" + resend_confirmation: "Resend Confirmation" + view_order: "View Order" + edit_order: "Edit Order" + ship_order: "Ship Order" + cancel_order: "Cancel Order" + confirm_send_invoice: "An invoice for this order will be sent to the customer. Are you sure you want to continue?" + confirm_resend_order_confirmation: "Are you sure you want to resend the order confirmation email?" + must_have_valid_business_number: "%{enterprise_name} must have a valid TIN before invoices can be sent." + invoice: "Invoice" + more: "More" + say_no: "No" + say_yes: "Yes" + ongoing: Ongoing + bill_address: Billing Address + ship_address: Shipping Address + sort_order_cycles_on_shopfront_by: "Sort Order Cycles On Shopfront By" + required_fields: Required fields are denoted with an asterisk + select_continue: Select and Continue + remove: Remove + or: or + collapse_all: Collapse all + expand_all: Expand all + loading: Loading... + show_more: Show more + show_all: Show all + show_all_with_more: "Show All (%{num} More)" + cancel: Cancel + edit: Edit + clone: Clone + distributors: Distributors + bulk_order_management: Bulk Order Management + enterprises: Enterprises + enterprise_groups: Groups + reports: Reports + variant_overrides: Inventory + import: Import + spree_products: Spree Products + all: All + current: Current + available: Available + dashboard: Dashboard + undefined: undefined + unused: unused + admin_and_handling: Admin & Handling + profile: Profile + supplier_only: Supplier Only + has_shopfront: Has Shopfront + weight: Weight + volume: Volume + items: Items + summary: Summary + detailed: Detailed + updated: Updated + 'yes': "Yes" + 'no': "No" + y: 'Y' + n: 'N' + powered_by: Powered by + blocked_cookies_alert: "Your browser may be blocking cookies needed to use this shopfront. Click below to allow cookies and reload the page." + allow_cookies: "Allow Cookies" + notes: Notes + error: Error + processing_payment: "Processing payment..." + no_pending_payments: "No pending payments" + invalid_payment_state: "Invalid payment state" + filter_results: Filter Results + quantity: Quantity + pick_up: Pick up + copy: Copy + change_my_password: "Change my password" + update_password: "Update password" + password_confirmation: Password Confirmation + reset_password_token: Reset password token + expired: has expired, please request a new one + back_to_payments_list: "Back to Payments List" + maestro_or_solo_cards: "Maestro/Solo cards" + backordered: "Backordered" + on hand: "On Hand" + ship: "Ship" + actions: + create_and_add_another: "Create and Add Another" + create: "Create" + cancel: "Cancel" + save: "Save" + edit: "Edit" + update: "Update" + delete: "Delete" + admin: + begins_at: Begins At + begins_on: Begins On + customer: Customer + date: Date + email: Email + ends_at: Ends At + ends_on: Ends On + name: Name + on_hand: On Hand + on_demand: On Demand + on_demand?: On Demand? + order_cycle: Order Cycle + payment: Payment + payment_method: Payment Method + phone: Phone + price: Price + producer: Producer + image: Image + product: Product + quantity: Quantity + schedule: Schedule + shipping: Shipping + shipping_method: Shipping Method + shop: Shop + sku: SKU + status_state: State + tags: Tags + variant: Variant + weight: Weight + volume: Volume + items: Items + select_all: Select all + quick_search: Quick Search + clear_all: Clear All + start_date: "Start Date" + end_date: "End Date" + form_invalid: "Form contains missing or invalid fields" + clear_filters: Clear Filters + clear: Clear + save: Save + cancel: Cancel + back: Back + show_more: Show more + show_n_more: Show %{num} more + choose: "Choose..." + please_select: Please select... + columns: Columns + actions: Actions + viewing: "Viewing: %{current_view_name}" + description: Description + whats_this: What's this? + tag_has_rules: "Existing rules for this tag: %{num}" + has_one_rule: "has one rule" + has_n_rules: "has %{num} rules" + unsaved_confirm_leave: "There are unsaved changed on this page. Continue without saving?" + unsaved_changes: "You have unsaved changes" + shopfront_settings: + embedded_shopfront_settings: "Embedded Shopfront Settings" + enable_embedded_shopfronts: "Enable Embedded Shopfronts" + embedded_shopfronts_whitelist: "External Domains Whitelist" + number_localization: + number_localization_settings: "Number Localization Settings" + enable_localized_number: "Use the international thousand/decimal separator logic" + invoice_settings: + edit: + title: "Invoice Settings" + enable_invoices?: "Enable Invoices?" + invoice_style2?: "Use the alternative invoice model that includes total tax breakdown per rate and tax rate info per item (not yet suitable for countries displaying prices excluding tax)" + enable_receipt_printing?: "Show options for printing receipts using thermal printers in order dropdown?" + stripe_connect_settings: + edit: + title: "Stripe Connect" + settings: "Settings" + stripe_connect_enabled: Enable shops to accept payments using Stripe Connect? + no_api_key_msg: No Stripe account exists for this enterprise. + configuration_explanation_html: For detailed instructions on configuring the Stripe Connect integration, please consult this guide. + status: Status + ok: Ok + instance_secret_key: Instance Secret Key + account_id: Account ID + business_name: Business Name + charges_enabled: Charges Enabled + charges_enabled_warning: "Warning: Charges are not enabled for your account" + auth_fail_error: The API key you provided is invalid + empty_api_key_error_html: No Stripe API key has been provided. To set your API key, please follow these instructions + matomo_settings: + edit: + title: "Matomo Settings" + matomo_url: "Matomo URL" + matomo_site_id: "Matomo Site ID" + info_html: "Matomo is a Web and Mobile Analytics. You can either host Matomo on-premises or use a cloud-hosted service. See matomo.org for more information." + config_instructions_html: "Here you can configure the OFN Matomo integration. The Matomo URL below should point to the Matomo instance where the user tracking information will be sent to; if it is left empty, Matomo user tracking will be disabled. The Site ID field is not mandatory but useful if you are tracking more than one website on a single Matomo instance; it can be found on the Matomo instance console." + customers: + index: + new_customer: "New Customer" + code: Code + duplicate_code: "This code is used already." + bill_address: "Billing Address" + ship_address: "Shipping Address" + update_address_success: 'Address updated successfully.' + update_address_error: 'Sorry! Please input all of the required fields!' + edit_bill_address: 'Edit Billing Address' + edit_ship_address: 'Edit Shipping Address' + required_fileds: 'Required fields are denoted with an asterisk ' + select_country: 'Select Country' + select_state: 'Select Province' + edit: 'Edit' + update_address: 'Update Address' + confirm_delete: 'Sure to delete?' + search_by_email: "Search by email/code..." + guest_label: 'Guest checkout' + destroy: + has_associated_orders: 'Delete failed: customer has associated orders with his shop' + contents: + edit: + title: Content + header: Header + home_page: Home page + producer_signup_page: Producer signup page + hub_signup_page: Hub signup page + group_signup_page: Group signup page + main_links: Main Menu Links + footer_and_external_links: Footer and External Links + your_content: Your content + user_guide: User Guide + enterprise_fees: + index: + title: "Enterprise Fees" + enterprise: "Enterprise" + fee_type: "Fee Type" + name: "Name" + tax_category: "Tax Category" + calculator: "Calculator" + calculator_values: "Calculator Values" + search: "Search" + name_placeholder: "e.g. packing fee" + enterprise_groups: + index: + new_button: New Enterprise Group + enterprise_roles: + form: + manages: manages + enterprise_role: + manages: manages + products: + unit_name_placeholder: 'eg. bunches' + index: + unit: Unit + display_as: Display As + category: Category + tax_category: Tax Category + inherits_properties?: Inherits Properties? + available_on: Available On + av_on: "Av. On" + import_date: Imported + upload_an_image: Upload an image + seo: + product_search_keywords: "Product Search Keywords" + product_search_tip: "Type words to help search your products in the shops. Use space to separate each keyword." + SEO_keywords: "SEO Keywords" + seo_tip: "Type words to help search your products in the web. Use space to separate each keyword." + search: "Search" + properties: + property_name: "Property Name" + inherited_property: "Inherited Property" + variants: + infinity: "Infinity" + to_order_tip: "Items made to order do not have a set stock level, such as loaves of bread made fresh to order." + back_to_products_list: "Back to products list" + editing_product: "Editing Product" + tabs: + product_details: "Product Details" + group_buy_options: "Group Buy Options" + images: "Images" + variants: "Variants" + product_properties: "Product Properties" + product_import: + title: Product Import + file_not_found: File not found or could not be opened + no_data: No data found in spreadsheet + confirm_reset: "This will set stock level to zero on all products for this \n enterprise that are not present in the uploaded file" + model: + no_file: "error: no file uploaded" + could_not_process: "could not process file: invalid filetype" + incorrect_value: incorrect value + conditional_blank: can't be blank if unit_type is blank + no_product: did not match any products in the database + not_found: not found in database + not_updatable: cannot be updated on existing products via product import + blank: can't be blank + products_no_permission: you do not have permission to manage products for this enterprise + inventory_no_permission: you do not have permission to create inventory for this producer + none_saved: did not save any products successfully + line_number: "Line %{number}:" + encoding_error: "Please check the language setting of your source file and ensure it is saved with UTF-8 encoding" + unexpected_error: "Product Import encountered an unexpected error whilst opening the file: %{error_message}" + index: + notice: "Notice" + beta_notice: "This feature is still in beta: you may experience some errors while using it. Please don't hesitate to contact support." + select_file: Select a spreadsheet to upload + spreadsheet: Spreadsheet + choose_import_type: Select import type + import_into: Import type + product_list: Product list + inventories: Inventories + import: Import + upload: Upload + csv_templates: CSV Templates + product_list_template: Download Product List template + inventory_template: Download Inventory template + category_values: Available Category Values + product_categories: Product Categories + tax_categories: Tax Categories + shipping_categories: Shipping Categories + import: + review: Review + import: Import + save: Save + results: Results + save_imported: Save imported products + no_valid_entries: No valid entries found + none_to_save: There are no entries that can be saved + some_invalid_entries: Imported file contains invalid entries + fix_before_import: Please fix these errors and try importing the file again + save_valid?: Save valid entries for now and discard the others? + no_errors: No errors detected! + save_all_imported?: Save all imported products? + options_and_defaults: Import options and defaults + no_permission: you do not have permission to manage this enterprise + not_found: enterprise could not be found in database + no_name: No name + blank_enterprise: some products do not have an enterprise defined + reset_absent?: Reset absent products + reset_absent_tip: Set stock to zero for all exiting products not present in the file + overwrite_all: Overwrite all + overwrite_empty: Overwrite if empty + default_stock: Set stock level + default_tax_cat: Set tax category + default_shipping_cat: Set shipping category + default_available_date: Set available date + validation_overview: Import validation overview + entries_found: Entries found in imported file + entries_with_errors: Items contain errors and will not be imported + products_to_create: Products will be created + products_to_update: Products will be updated + inventory_to_create: Inventory items will be created + inventory_to_update: Inventory items will be updated + products_to_reset: Existing products will have their stock reset to zero + inventory_to_reset: Existing inventory items will have their stock reset to zero + line: Line + item_line: Item line + import_review: + not_updatable_tip: "The following fields cannot be updated via bulk import for existing products:" + fields_ignored: These fields will be ignored when the imported products are saved. + entries_table: + not_updatable: This field is not updatable via bulk import on existing products + save_results: + final_results: Import final results + products_created: Products created + products_updated: Products updated + inventory_created: Inventory items created + inventory_updated: Inventory items updated + products_reset: Products had stock level reset to zero + inventory_reset: Inventory items had stock level reset to zero + all_saved: "All items saved successfully" + some_saved: "items saved successfully" + save_errors: Save errors + import_again: Upload Another File + view_products: Go To Products Page + view_inventory: Go To Inventory Page + variant_overrides: + loading_flash: + loading_inventory: LOADING INVENTORY + index: + title: Inventory + description: Use this page to manage inventories for your enterprises. Any product details set here will override those set on the 'Products' page + enable_reset?: Enable Stock Reset? + default_stock: "Default stock" + inherit?: Inherit? + add: Add + hide: Hide + import_date: Imported + select_a_shop: Select A Shop + review_now: Review Now + new_products_alert_message: There are %{new_product_count} new products available to add to your inventory. + currently_empty: Your inventory is currently empty + no_matching_products: No matching products found in your inventory + no_hidden_products: No products have been hidden from this inventory + no_matching_hidden_products: No hidden products match your search criteria + no_new_products: No new products are available to add to this inventory + no_matching_new_products: No new products match your search criteria + inventory_powertip: This is your inventory of products. To add products to your inventory, select 'New Products' from the Viewing dropdown. + hidden_powertip: These products have been hidden from your inventory and will not be available to add to your shop. You can click 'Add' to add a product to you inventory. + new_powertip: These products are available to be added to your inventory. Click 'Add' to add a product to your inventory, or 'Hide' to hide it from view. You can always change your mind later! + controls: + back_to_my_inventory: Back to my inventory + orders: + invoice_email_sent: 'Invoice email has been sent' + order_email_resent: 'Order email has been resent' + bulk_management: + tip: "Use this page to alter product quantities across multiple orders. Products may also be removed from orders entirely, if required." + shared: "Shared Resource?" + order_no: "Order No." + order_date: "Completed at" + max: "Max" + product_unit: "Product: Unit" + weight_volume: "Weight/Volume" + ask: "Ask?" + page_title: "Bulk Order Management" + actions_delete: "Delete Selected" + loading: "Loading orders" + no_results: "No orders found." + group_buy_unit_size: "Group Buy Unit Size" + total_qtt_ordered: "Total Quantity Ordered" + max_qtt_ordered: "Max Quantity Ordered" + current_fulfilled_units: "Current Fulfilled Units" + max_fulfilled_units: "Max Fulfilled Units" + order_error: "Some errors must be resolved before you can update orders.\nAny fields with red borders contain errors." + variants_without_unit_value: "WARNING: Some variants do not have a unit value" + select_variant: "Select a variant" + enterprise: + select_outgoing_oc_products_from: Select outgoing OC products from + enterprises: + index: + title: Enterprises + new_enterprise: New Enterprise + producer?: "Producer?" + package: Package + status: Status + manage: Manage + form: + about_us: + desc_short: Short Description + desc_short_placeholder: Tell us about your enterprise in one or two sentences + desc_long: About Us + desc_long_placeholder: Tell customers about yourself. This information appears on your public profile. + business_details: + abn: TIN + abn_placeholder: eg. 99 123 456 789 + acn: Branch TIN + acn_placeholder: eg. 123 456 789 + display_invoice_logo: Display logo in invoices + invoice_text: Add customized text at the end of invoices + contact: + name: Name + name_placeholder: eg. Gustav Plum + email_address: Public Email Address + email_address_placeholder: eg. inquiries@fresh-food.com + email_address_tip: "This email address will be displayed in your public profile" + phone: Phone + phone_placeholder: eg. 98 7654 3210 + website: Website + website_placeholder: eg. www.truffles.com + enterprise_fees: + name: Name + fee_type: Fee Type + manage_fees: Manage Enterprise Fees + no_fees_yet: You don't have any enterprise fees yet. + create_button: Create One Now + images: + logo: Logo + promo_image_placeholder: 'This image is displayed in "About Us"' + promo_image_note1: 'PLEASE NOTE:' + promo_image_note2: Any promo image uploaded here will be cropped to 1200 x 260. + promo_image_note3: The promo image is displayed at the top of an enterprise's profile page and pop-ups. + inventory_settings: + text1: You may opt to manage stock levels and prices in via your + inventory: inventory + text2: > + If you are using the inventory tool, you can select whether new products + added by your suppliers need to be added to your inventory before they + can be stocked. If you are not using your inventory to manage your products + you should select the 'recommended' option below: + preferred_product_selection_from_inventory_only_yes: New products can be put into my shopfront (recommended) + preferred_product_selection_from_inventory_only_no: New products must be added to my inventory before they can be put into my shopfront + payment_methods: + name: Name + applies: Applies? + manage: Manage Payment Methods + no_method_yet: You don't have any payment methods yet. + create_button: Create New Payment Method + create_one_button: Create One Now + primary_details: + name: Name + name_placeholder: eg. Professor Plum's Biodynamic Truffles + groups: Groups + 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. + producer: Producer + any: Any + none: None + own: Own + sells: Sells + sells_tip: "None - enterprise does not sell to customers directly.
Own - Enterprise sells own products to customers.
Any - Enterprise can sell own or other enterprises products.
" + visible_in_search: Visible in search? + visible_in_search_tip: Determines whether this enterprise will be visible to customers when searching the site. + visible: Visible + not_visible: Not visible + permalink: Permalink (no spaces) + permalink_tip: "This permalink is used to create the url to your shop: %{link}your-shop-name/shop" + link_to_front: Link to shop front + link_to_front_tip: A direct link to your shopfront on the Open Food Network. + ofn_uid: OFN UID + ofn_uid_tip: The unique id used to identify the enterprise on Open Food Network. + shipping_methods: + name: Name + applies: Applies? + manage: Manage Shipping Methods + create_button: Create New Shipping Method + create_one_button: Create One Now + no_method_yet: You don't have any shipping methods yet. + shop_preferences: + shopfront_requires_login: "Publicly visible shopfront?" + shopfront_requires_login_tip: "Choose whether customers must login to view the shopfront or if it's visible to everybody." + shopfront_requires_login_false: "Public" + shopfront_requires_login_true: "Visible to registered customers only" + recommend_require_login: "We recommend to require users to login when orders can be changed." + allow_guest_orders: "Guest orders" + allow_guest_orders_tip: "Allow checkout as guest or require a registered user." + allow_guest_orders_false: "Require login to order" + allow_guest_orders_true: "Allow guest checkout" + allow_order_changes: "Change orders" + allow_order_changes_tip: "Allow customers to change their order as long the order cycle is open." + allow_order_changes_false: "Placed orders cannot be changed / cancelled" + allow_order_changes_true: "Customers can change / cancel orders while order cycle is open" + enable_subscriptions: "Subscriptions" + enable_subscriptions_tip: "Enable subscriptions functionality?" + enable_subscriptions_false: "Disabled" + enable_subscriptions_true: "Enabled" + shopfront_message: "Shopfront Message" + shopfront_message_placeholder: > + An optional message to welcome customers and explain how to shop with + you. If text is entered here it will be displayed in a home tab when + customers first arrive at your shopfront. + shopfront_message_link_tooltip: "Insert / edit link" + shopfront_message_link_prompt: "Please enter a URL to insert" + shopfront_closed_message: "Shopfront Closed Message" + shopfront_closed_message_placeholder: > + A message which provides a more detailed explanation about why your + shop is closed and/or when customers can expect it to open again. This + is displayed on your shop only when you have no active order cycles + (ie. shop is closed). + shopfront_category_ordering: "Shopfront Category Ordering" + open_date: "Open Date" + close_date: "Close Date" + social: + twitter_placeholder: "e.g. @OFNPhilippines" + instagram_placeholder: "e.g. OFNPhilippines" + facebook_placeholder: "eg. www.facebook.com/PageNameHere" + linkedin_placeholder: "eg. www.linkedin.com/in/YourNameHere" + stripe_connect: + connect_with_stripe: "Connect with Stripe" + stripe_connect_intro: "To accept payments using credit card, you will need to connect your stripe account to the Open Food Network. Use the button to the right to get started." + stripe_account_connected: "Stripe account connected." + disconnect: "Disconnect account" + confirm_modal: + title: Connect with Stripe + part1: Stripe is a payment processing service that allows shops on the OFN to accept credit card payments from customers. + part2: To use this feature, you must connect your Stripe account to the OFN. Clicking 'I Agree' below will redirect to you the Stripe website where you can connect an existing Stripe account, or create a new one if you don't already have one. + part3: This will allow the Open Food Network to accept credit card payments from customers on your behalf. Please note that you will need to maintain your own Stripe account, pay the fees Stripe charges and handle any chargebacks and customer service yourself. + i_agree: I Agree + cancel: Cancel + tag_rules: + default_rules: + by_default: By Default + no_rules_yet: No default rules apply yet + add_new_button: '+ Add A New Default Rule' + no_tags_yet: No tags apply to this enterprise yet + no_rules_yet: No rules apply to this tag yet + for_customers_tagged: 'For customers tagged:' + add_new_rule: '+ Add A New Rule' + add_new_tag: '+ Add A New Tag' + users: + email_confirmation_notice_html: "Email confirmation is pending. We've sent a confirmation email to %{email}." + resend: Resend + owner: 'Owner' + contact: "Contact" + contact_tip: "The manager who will receive enterprise emails for orders and notifications. Must have a confirmed email adress." + owner_tip: The primary user responsible for this enterprise. + notifications: Notifications + notifications_tip: Notifications about orders will be send to this email address. + notifications_placeholder: eg. gustav@truffles.com + notifications_note: 'Note: A new email address may need to be confirmed prior to use' + managers: Managers + managers_tip: The other users with permission to manage this enterprise. + invite_manager: "Invite Manager" + invite_manager_tip: "Invite an unregistered user to sign up and become a manager of this enterprise." + add_unregistered_user: "Add an unregistered user" + email_confirmed: "Email confirmed" + email_not_confirmed: "Email not confirmed" + actions: + edit_profile: Settings + properties: Properties + payment_methods: Payment Methods + payment_methods_tip: This enterprise has no payment methods + shipping_methods: Shipping Methods + shipping_methods_tip: This enterprise has shipping methods + enterprise_fees: Enterprise Fees + enterprise_fees_tip: This enterprise has no fees + admin_index: + name: Name + role: Role + sells: Sells + visible: Visible? + owner: Owner + producer: Producer + change_type_form: + producer_profile: Producer Profile + connect_ofn: Connect through OFN + 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 + 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_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. + 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. + choose_option: Please choose one of the options above. + change_now: Change now + enterprise_user_index: + loading_enterprises: LOADING ENTERPRISES + no_enterprises_found: No enterprises found. + search_placeholder: Search By Name + manage: Manage + manage_link: Settings + producer?: "Producer?" + package: "Package" + status: "Status" + new_form: + owner: Owner + owner_tip: The primary user responsible for this enterprise. + i_am_producer: I am a Producer + contact_name: Contact Name + edit: + editing: 'Settings:' + back_link: Back to enterprises list + new: + title: New Enterprise + back_link: Back to enterprises list + remove_logo: + remove: "Remove Image" + removed_successfully: "Logo removed successfully" + immediate_removal_warning: "The logo will be removed immediately after you confirm." + remove_promo_image: + remove: "Remove Image" + removed_successfully: "Promo image removed successfully" + immediate_removal_warning: "The promo image will be removed immediately after you confirm." + welcome: + welcome_title: Welcome to the Open Food Network! + welcome_text: You have successfully created a + next_step: Next step + choose_starting_point: 'Choose your package:' + profile: 'Profile' + producer_profile: 'Producer Profile' + invite_manager: + user_already_exists: "User already exists" + error: "Something went wrong" + order_cycles: + loading_flash: + loading_order_cycles: LOADING ORDER CYCLES + loading: LOADING... + new: + create: "Create" + cancel: "Cancel" + back_to_list: "Back To List" + edit: + advanced_settings: "Advanced Settings" + save: "Save" + save_and_next: "Save and Next" + next: "Next" + cancel: "Cancel" + back_to_list: "Back To List" + save_and_back_to_list: "Save and Back to List" + choose_products_from: "Choose Products From:" + incoming: + save: "Save" + save_and_next: "Save and Next" + next: "Next" + cancel: "Cancel" + back_to_list: "Back To List" + outgoing: + outgoing: "Outgoing" + distributor: "Distributor" + products: "Products" + tags: "Tags" + delivery_details: "Delivery Details" + fees: "Fees" + previous: "Previous" + save: "Save" + save_and_back_to_list: "Save and Back to List" + cancel: "Cancel" + back_to_list: "Back To List" + wizard_progress: + edit: "1. General Settings" + incoming: "2. Incoming Products" + outgoing: "3. Outgoing Products" + exchange_form: + pickup_time_tip: When orders from this OC will be ready for the customer + pickup_instructions_placeholder: "Pick-up instructions" + pickup_instructions_tip: These instructions are shown to customers after they complete an order + pickup_time_placeholder: "Ready for (ie. Date / Time)" + receival_instructions_placeholder: "Receival instructions" + add_fee: 'Add fee' + remove: 'Remove' + selected: 'selected' + add_exchange_form: + add_supplier: 'Add supplier' + add_distributor: 'Add distributor' + advanced_settings: + title: Advanced Settings + choose_product_tip: You can restrict products incoming and outgoing to only %{inventory}'s inventory. + preferred_product_selection_from_coordinator_inventory_only_here: Coordinator's Inventory Only + preferred_product_selection_from_coordinator_inventory_only_all: All Available Products + save_reload: Save and Reload Page + coordinator_fees: + add: Add coordinator fee + filters: + search_by_order_cycle_name: "Search by Order Cycle name..." + involving: "Involving" + any_enterprise: "Any Enterprise" + any_schedule: "Any Schedule" + form: + general_settings: "General Settings" + incoming: Incoming + supplier: Supplier + receival_details: Receival details + fees: Fees + outgoing: Outgoing + distributor: Distributor + products: Products + tags: Tags + add_a_tag: Add a tag + delivery_details: Pickup / Delivery details + index: + schedule: Schedule + schedules: Schedules + new_schedule: New Schedule + name_and_timing_form: + name: Name + orders_open: Orders open at + coordinator: Coordinator + orders_close: Orders close + row: + suppliers: suppliers + distributors: distributors + variants: variants + simple_form: + ready_for: Ready for + ready_for_placeholder: Date / time + customer_instructions: Customer instructions + customer_instructions_placeholder: Pick-up or delivery notes + products: Products + fees: Fees + destroy_errors: + orders_present: That order cycle has been selected by a customer and cannot be deleted. To prevent customers from accessing it, please close it instead. + schedule_present: That order cycle is linked to a schedule and cannot be deleted. Please unlink or delete the schedule first. + bulk_update: + no_data: Hm, something went wrong. No order cycle data found. + date_warning: + msg: This order cycle is linked to %{n} open subscription orders. Changing this date now will not affect any orders which have already been placed, but should be avoided if possible. Are you sure you want to proceed? + cancel: Cancel + proceed: Proceed + producer_properties: + index: + title: Producer Properties + proxy_orders: + cancel: + could_not_cancel_the_order: Could not cancel the order + resume: + could_not_resume_the_order: Could not resume the order + shared: + user_guide_link: + user_guide: User Guide + enterprises_hubs_tabs: + has_no_payment_methods: "%{enterprise} has no payment methods" + has_no_shipping_methods: "%{enterprise} has no shipping methods" + has_no_enterprise_fees: "%{enterprise} has no enterprise fees" + enterprise_issues: + create_new: Create New + resend_email: Resend Email + has_no_payment_methods: "%{enterprise} currently has no payment methods" + has_no_shipping_methods: "%{enterprise} currently has no shipping methods" + email_confirmation: "Email confirmation is pending. We've sent a confirmation email to %{email}." + not_visible: "%{enterprise} is not visible and so cannot be found on the map or in searches" + reports: + hidden: HIDDEN + unitsize: UNITSIZE + total: TOTAL + total_items: TOTAL ITEMS + supplier_totals: Order Cycle Supplier Totals + supplier_totals_by_distributor: Order Cycle Supplier Totals by Distributor + totals_by_supplier: Order Cycle Distributor Totals by Supplier + customer_totals: Order Cycle Customer Totals + all_products: All products + inventory: Inventory (on hand) + lettuce_share: LettuceShare + mailing_list: Mailing List + addresses: Addresses + payment_methods: Payment Methods Report + delivery: Delivery Report + tax_types: Tax Types + tax_rates: Tax Rates + pack_by_customer: Pack By Customer + pack_by_supplier: Pack By Supplier + orders_and_distributors: + name: Orders And Distributors + description: Orders with distributor details + bulk_coop: + name: Bulk Co-Op + description: Reports for Bulk Co-Op orders + payments: + name: Payment Reports + description: Reports for Payments + orders_and_fulfillment: + name: Orders & Fulfillment Reports + customers: + name: Customers + products_and_inventory: + name: Products & Inventory + users_and_enterprises: + name: Users & Enterprises + description: Enterprise Ownership & Status + order_cycle_management: + name: Order Cycle Management + sales_tax: + name: Sales Tax + xero_invoices: + name: Xero Invoices + description: Invoices for import into Xero + packing: + name: Packing Reports + enterprise_fee_summary: + name: "Enterprise Fee Summary" + description: "Summary of Enterprise Fees collected" + subscriptions: + subscriptions: Subscriptions + new: New Subscription + create: Create Subscription + edit: Edit Subscription + table: + edit_subscription: Edit Subscription + pause_subscription: Pause Subscription + unpause_subscription: Unpause Subscription + cancel_subscription: Cancel Subscription + filters: + query_placeholder: "Search by email..." + setup_explanation: + just_a_few_more_steps: 'Just a few more steps before you can begin:' + enable_subscriptions: "Enable subscriptions for at least one of your shops" + enable_subscriptions_step_1_html: 1. Go to the %{enterprises_link} page, find your shop, and click "Manage" + enable_subscriptions_step_2: 2. Under "Shop Preferences", enable the Subscriptions option + set_up_shipping_and_payment_methods_html: Set up %{shipping_link} and %{payment_link} methods + set_up_shipping_and_payment_methods_note_html: Note that only Cash and Stripe payment methods may
be used with subscriptions + ensure_at_least_one_customer_html: Ensure that at least one %{customer_link} exists + create_at_least_one_schedule: Create at least one Schedule + create_at_least_one_schedule_step_1_html: 1. Go to the on the %{order_cycles_link} page + create_at_least_one_schedule_step_2: 2. Create an order cycle if you have not already done so + create_at_least_one_schedule_step_3: 3. Click '+ New Schedule', and fill out the form + once_you_are_done_you_can_html: Once you are done, you can %{reload_this_page_link} + reload_this_page: reload this page + steps: + details: 1. Basic Details + address: 2. Address + products: 3. Add Products + review: 4. Review & Save + subscription_line_items: + this_is_an_estimate: | + The displayed prices are only an estimate and calculated at the time the subscription is changed. + If you change prices or fees, orders will be updated, but the subscription will still display the old values. + not_in_open_and_upcoming_order_cycles_warning: "There are no open or upcoming order cycles for this product." + autocomplete: + name_or_sku: "NAME OR SKU" + quantity: "Quantity" + add: "Add" + details: + details: Details + invalid_error: Oops! Please fill in all of the required fields... + allowed_payment_method_types_tip: Only Cash and Stripe payment methods may be used at the moment + credit_card: Credit Card + charges_not_allowed: Charges are not allowed by this customer + no_default_card: Customer has no cards available to charge + card_ok: Customer has a card available to charge + begins_at_placeholder: "Select a Date" + ends_at_placeholder: "Optional" + loading_flash: + loading: LOADING SUBSCRIPTIONS + review: + details: Details + address: Address + products: Products + no_open_or_upcoming_order_cycle: "No Upcoming Order Cycle" + products_panel: + save: "SAVE" + saving: "SAVING" + saved: "SAVED" + product_already_in_order: This product has already been added to the order. Please edit the quantity directly. + stock: + insufficient_stock: "Insufficient stock available" + out_of_stock: "Out of Stock" + orders: + number: Number + confirm_edit: Are you sure you want to edit this order? Doing so may make it more difficult to automatically sync changes to the subscription in the future. + confirm_cancel_msg: "Are you sure you want to cancel this subscription? This action cannot be undone." + cancel_failure_msg: "Sorry, cancellation failed!" + confirm_pause_msg: "Are you sure you want to pause this subscription?" + pause_failure_msg: "Sorry, pausing failed!" + confirm_unpause_msg: "If you have an open Order Cycle in this subscription's schedule, an order will be created for this customer. Are you sure you want to unpause this subscription?" + unpause_failure_msg: "Sorry, unpausing failed!" + confirm_cancel_open_orders_msg: "Some orders for this subscription are currently open. The customer has already been notified that the order will be placed. Would you like to cancel these order(s) or keep them?" + resume_canceled_orders_msg: "Some orders for this subscription can be resumed right now. You can resume them from the orders dropdown." + yes_cancel_them: Cancel them + no_keep_them: Keep them + yes_i_am_sure: Yes, I'm sure + order_update_issues_msg: Some orders could not be automatically updated, this is most likely because they have been manually edited. Please review the issues listed below and make any adjustments to individual orders if required. + no_results: + no_subscriptions: No subscriptions yet... + why_dont_you_add_one: Why don't you add one? :) + no_matching_subscriptions: No matching subscriptions found + schedules: + destroy: + associated_subscriptions_error: This schedule cannot be deleted because it has associated subscriptions + controllers: + enterprises: + stripe_connect_cancelled: "Connection to Stripe has been cancelled" + stripe_connect_success: "Stripe account connected successfully" + stripe_connect_fail: Sorry, the connection of your Stripe account failed + stripe_connect_settings: + resource: Stripe Connect configuration + api: + enterprise_logo: + 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" + message_html: "You have an order for this order cycle already. Check the %{cart} to see the items you ordered before. You can also cancel items as long as the order cycle is open." + failed: "The checkout failed. Please let us know so that we can process your order." + shops: + hubs: + show_closed_shops: "Show closed shops" + hide_closed_shops: "Hide closed shops" + show_on_map: "Show all on the map" + shared: + menu: + cart: + cart: "Cart" + signed_in: + profile: "Profile" + mobile_menu: + cart: "Cart" + joyride: + checkout: "Checkout now" + already_ordered_products: "Already ordered in this order cycle" + register_call: + selling_on_ofn: "Interested in getting on the Open Food Network?" + register: "Register here" + footer: + 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" + footer_contact_email: "Email us" + footer_nav_headline: "Navigate" + footer_join_headline: "Join us" + footer_join_body: "Create a listing, shop or group directory on the Open Food Network." + footer_join_cta: "Tell me more!" + footer_legal_call: "Read our" + footer_legal_tos: "Terms and conditions" + footer_legal_visit: "Find us on" + footer_legal_text_html: "Open Food Network is a free and open source software platform. Our content is licensed with %{content_license} and our code with %{code_license}." + footer_data_text_with_privacy_policy_html: "We take good care of your data. See our %{privacy_policy} and %{cookies_policy}" + footer_data_text_without_privacy_policy_html: "We take good care of your data. See our %{cookies_policy}" + footer_data_privacy_policy: "privacy policy" + footer_data_cookies_policy: "cookies policy" + shop: + messages: + login: "login" + signup: "signup" + contact: "contact" + require_customer_login: "Only approved customers can access this shop." + require_login_html: "If you're already an approved customer, %{login} or %{signup} to proceed. Want to start shopping here? Please %{contact} %{enterprise} and ask about joining." + require_customer_html: "If you'd like to start shopping here, please %{contact} %{enterprise} to ask about joining." + card_could_not_be_updated: Card could not be updated + card_could_not_be_saved: card could not be saved + spree_gateway_error_flash_for_checkout: "There was a problem with your payment information: %{error}" + invoice_billing_address: "Billing address:" + invoice_column_tax: "VAT" + invoice_column_price: "Price" + invoice_column_item: "Item" + invoice_column_qty: "Qty" + invoice_column_unit_price_with_taxes: "Unit price (Incl. tax)" + invoice_column_unit_price_without_taxes: "Unit price (Excl. tax)" + invoice_column_price_with_taxes: "Total price (Incl. tax)" + invoice_column_price_without_taxes: "Total price (Excl. tax)" + invoice_column_tax_rate: "Tax rate" + invoice_tax_total: "VAT Total:" + tax_invoice: "TAX INVOICE" + tax_total: "Total tax (%{rate}):" + total_excl_tax: "Total (Excl. tax):" + total_incl_tax: "Total (Incl. tax):" + abn: "TIN:" + acn: "Branch TIN:" + invoice_issued_on: "Invoice issued on:" + order_number: "Invoice number:" + date_of_transaction: "Date of transaction:" + ticket_column_qty: "Qty" + ticket_column_item: "Item" + ticket_column_unit_price: "Unit Price" + ticket_column_total_price: "Total Price" + menu_1_title: "Shops" + menu_1_url: "/shops" + menu_2_title: "Map" + menu_2_url: "/map" + menu_3_title: "Producers" + menu_3_url: "/producers" + menu_4_title: "Fees" + menu_4_url: "/sell" + menu_5_title: "About" + menu_5_url: "https://www.openfoodnetwork.org/about-us/" + menu_6_title: "Connect" + menu_6_url: "https://www.openfoodnetwork.org/contact/" + menu_7_title: "Learn" + menu_7_url: "https://www.openfoodnetwork.org/resources/" + logo: "Logo (640x130)" + logo_mobile: "Mobile logo (75x26)" + logo_mobile_svg: "Mobile logo (SVG)" + home_hero: "Hero image" + home_show_stats: "Show statistics" + footer_logo: "Logo (220x76)" + footer_facebook_url: "Facebook URL" + footer_twitter_url: "Twitter URL" + footer_instagram_url: "Instagram URL" + footer_linkedin_url: "LinkedIn URL" + footer_googleplus_url: "Google Plus URL" + footer_pinterest_url: "Pinterest URL" + footer_email: "Email" + footer_links_md: "Links" + footer_about_url: "About URL" + user_guide_link: "User Guide Link" + name: Name + first_name: First Name + last_name: Last Name + email: Email + phone: Phone + next: Next + address: Address + address_placeholder: e.g. 123 Kapayapaan St. + address2: Address (contd.) + city: City + city_placeholder: e.g. Mandaluyong + postcode: Postcode + postcode_placeholder: e.g. 1555 + suburb: City + state: Province + country: Country + unauthorized: Unauthorized + terms_of_service: "Terms of service" + on_demand: On demand + none: None + not_allowed: Not allowed + no_shipping: no shipping methods + no_payment: no payment methods + no_shipping_or_payment: no shipping or payment methods + unconfirmed: unconfirmed + days: days + authorization_failure: "Authorization Failure" + label_shop: "Shop" + label_shops: "Shops" + label_map: "Map" + label_producer: "Producer" + label_producers: "Producers" + label_groups: "Groups" + label_about: "About" + label_connect: "Connect" + label_learn: "Learn" + label_blog: "Blog" + label_support: "Support" + label_shopping: "Shopping" + label_login: "Login" + label_logout: "Logout" + label_signup: "Sign up" + label_administration: "Administration" + label_admin: "Admin" + label_account: "Account" + label_more: "Show more" + label_less: "Show less" + label_notices: "Notices" + cart_items: "items" + cart_headline: "Your shopping cart" + total: "Total" + cart_updating: "Updating cart..." + cart_empty: "Cart empty" + cart_edit: "Edit your cart" + card_number: Card Number + card_securitycode: "Security Code" + card_expiry_date: Expiry Date + card_masked_digit: "X" + card_expiry_abbreviation: "Exp" + new_credit_card: "New credit card" + my_credit_cards: My credit cards + add_new_credit_card: Add new credit card + saved_cards: Saved cards + add_a_card: Add a Card + add_card: Add Card + you_have_no_saved_cards: You haven't saved any cards yet + saving_credit_card: Saving credit card... + card_has_been_removed: "Your card has been removed (number: %{number})" + card_could_not_be_removed: Sorry, the card could not be removed + invalid_credit_card: "Invalid credit card" + ie_warning_headline: "Your browser is out of date :-(" + ie_warning_text: "For the best Open Food Network experience, we strongly recommend upgrading your browser:" + ie_warning_chrome: Download Chrome + ie_warning_firefox: Download Firefox + ie_warning_ie: Upgrade Internet Explorer + ie_warning_other: "Can't upgrade your browser? Try Open Food Network on your smartphone :-)" + legal: + 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_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." + essential_cookies_note: "Most cookies only contain a unique identifier, but no other data, so your email address and password for instance are never contained in them and never exposed." + cookie_domain: "Set By:" + cookie_session_desc: "Used to allow the website to remember users between page visits, for example, remember items in your cart." + cookie_consent_desc: "Used to maintain status of user consent to store cookies" + cookie_remember_me_desc: "Used if the user has requested the website to remember him. This cookie is automatically deleted after 12 days. If as a user you want that cookie to be deleted, you only need to logout. If you don’t want that cookie to be installed on your computer you shouldn’t check the “remember me” checkbox when logging in." + cookie_openstreemap_desc: "Used by our friendly open source mapping provider (OpenStreetMap) to ensure that it does not receive too many requests during a given time period, to prevent abuse of their services." + cookie_stripe_desc: "Data collected by our payment processor Stripe for fraud detection https://stripe.com/cookies-policy/legal. Not all shops use Stripe as a payment method but it is a good practice to prevent fraud to apply it to all pages. Stripe probably build a picture of which of our pages usually interact with their API and then flag anything unusual. So setting the Stripe cookie has a broader function than simply the provision of a payment method to a user. Removing it could affect the security of the service itself. You can learn more about Stripe and read its privacy policy at https://stripe.com/privacy." + statistics_cookies: "Statistics Cookies" + statistics_cookies_desc: "The following are not strictly necessary, but help to provide you with the best user experience by allowing us to analyse user behaviour, identify which features you use most, or don’t use, understand user experience issues, etc." + statistics_cookies_analytics_desc_html: "To collect and analyse platform usage data, we use Google Analytics, as it was the default service connected with Spree (the e-commerce open source software that we built on) but our vision is to switch to Matomo (ex Piwik, open source analytics tool that is GDPR compliant and protects your privacy) as soon as we can." + statistics_cookies_matomo_desc_html: "To collect and analyse platform usage data, we use Matomo (ex Piwik), an open source analytics tool that is GDPR compliant and protects your privacy." + statistics_cookies_matomo_optout: "Do you want to opt-out of Matomo analytics? We don’t collect any personal data, and Matomo helps us to improve our service, but we respect your choice :-)" + cookie_analytics_utma_desc: "Used to distinguish users and sessions. The cookie is created when the javascript library executes and no existing __utma cookies exists. The cookie is updated every time data is sent to Google Analytics." + cookie_analytics_utmt_desc: "Used to throttle request rate." + cookie_analytics_utmb_desc: "Used to determine new sessions/visits. The cookie is created when the javascript library executes and no existing __utmb cookies exists. The cookie is updated every time data is sent to Google Analytics." + cookie_analytics_utmc_desc: "Not used in ga.js. Set for interoperability with urchin.js. Historically, this cookie operated in conjunction with the __utmb cookie to determine whether the user was in a new session/visit." + cookie_analytics_utmz_desc: "Stores the traffic source or campaign that explains how the user reached your site. The cookie is created when the javascript library executes and is updated every time data is sent to Google Analytics." + cookie_matomo_basics_desc: "Matomo first party cookies to collect statistics." + cookie_matomo_heatmap_desc: "Matomo Heatmap & Session Recording cookie." + cookie_matomo_ignore_desc: "Cookie used to exclude user from being tracked." + disabling_cookies_header: "Warning on disabling cookies" + disabling_cookies_desc: "As a user you can always allow, block or delete Open Food Network’s or any other website cookies whenever you want to through your browser’s setting control. Each browser has a different operative. Here are the links:" + disabling_cookies_firefox_link: "https://support.mozilla.org/en-US/kb/enable-and-disable-cookies-website-preferences" + disabling_cookies_chrome_link: "https://support.google.com/chrome/answer/95647" + disabling_cookies_ie_link: "https://support.microsoft.com/en-us/help/17442/windows-internet-explorer-delete-manage-cookies" + disabling_cookies_safari_link: "https://www.apple.com/legal/privacy/en-ww/cookies/" + disabling_cookies_note: "But be aware that if you delete or modify the essential cookies used by Open Food Network, the website won’t work, you will not be able to add anything to your cart neither to checkout for instance." + 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_policy_link_desc: "If you want to learn more, check our" + cookies_policy_link: "cookies policy" + cookies_accept_button: "Accept Cookies" + home_shop: Shop Now + 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_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_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_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_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_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." + 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" + checkout_title: Checkout + checkout_now: Checkout now + checkout_order_ready: Order ready for + checkout_hide: Hide + checkout_expand: Expand + checkout_headline: "Ok, ready to checkout?" + checkout_as_guest: "Checkout as guest" + checkout_details: "Your details" + checkout_billing: "Billing info" + checkout_default_bill_address: "Save as default billing address" + checkout_shipping: Shipping info + checkout_default_ship_address: "Save as default shipping address" + checkout_method_free: Free + checkout_address_same: Shipping address same as billing address? + checkout_ready_for: "Ready for:" + checkout_instructions: "Any comments or special instructions?" + checkout_payment: Payment + checkout_send: Place order now + checkout_your_order: Your order + checkout_cart_total: Cart total + checkout_shipping_price: Shipping + checkout_total_price: Total + checkout_back_to_cart: "Back to Cart" + cost_currency: "Cost Currency" + order_paid: PAID + order_not_paid: NOT PAID + order_total: Total order + order_payment: "Paying via:" + order_billing_address: Billing address + order_delivery_on: Delivery on + order_delivery_address: Delivery address + order_delivery_time: Delivery time + order_special_instructions: "Your notes:" + order_pickup_time: Ready for collection + order_pickup_instructions: Collection Instructions + order_produce: Produce + order_total_price: Total + order_includes_tax: (includes tax) + order_payment_paypal_successful: Your payment via PayPal has been processed successfully. + order_hub_info: Hub Info + order_back_to_store: Back To Store + order_back_to_cart: Back To Cart + bom_tip: "Use this page to alter product quantities across multiple orders. Products may also be removed from orders entirely, if required." + unsaved_changes_warning: "Unsaved changes exist and will be lost if you continue." + unsaved_changes_error: "Fields with red borders contain errors." + products: "Products" + products_in: "in %{oc}" + products_at: "at %{distributor}" + products_elsewhere: "Products found elsewhere" + email_confirmed: "Thank you for confirming your email address." + email_confirmation_activate_account: "Before we can activate your new account, we need to confirm your email address." + email_confirmation_greeting: "Hi, %{contact}!" + email_confirmation_profile_created: "A profile for %{name} has been successfully created! To activate your Profile we need to confirm this email address." + email_confirmation_click_link: "Please click the link below to confirm your email and to continue setting up your profile." + email_confirmation_link_label: "Confirm this email address »" + email_confirmation_help_html: "After confirming your email you can access your administration account for this enterprise. See the %{link} to find out more about %{sitename}'s features and to start using your profile or online store." + email_confirmation_notice_unexpected: "You received this message because you signed up on %{sitename}, or were invited to sign up by someone you probably know. If you don't understand why you are receiving this email, please write to %{contact}." + email_social: "Connect with Us:" + email_contact: "Email us:" + email_signoff: "Cheers," + email_signature: "%{sitename} Team" + email_confirm_customer_greeting: "Hi %{name}," + email_confirm_customer_intro_html: "Thanks for shopping at %{distributor}!" + email_confirm_customer_number_html: "Order confirmation #%{number}" + email_confirm_customer_details_html: "Here are your order details from %{distributor}:" + email_confirm_customer_signoff: "Kind regards," + email_confirm_shop_greeting: "Hi %{name}," + email_confirm_shop_order_html: "Well done! You have a new order for %{distributor}!" + email_confirm_shop_number_html: "Order confirmation #%{number}" + email_order_summary_item: "Item" + email_order_summary_quantity: "Qty" + email_order_summary_sku: "SKU" + email_order_summary_price: "Price" + email_order_summary_subtotal: "Subtotal:" + email_order_summary_total: "Total:" + email_order_summary_includes_tax: "(includes tax):" + email_payment_paid: PAID + email_payment_not_paid: NOT PAID + email_payment_summary: Payment summary + email_payment_method: "Paying via:" + email_so_placement_intro_html: "You have a new order with %{distributor}" + email_so_placement_details_html: "Here are the details of your order for %{distributor}:" + email_so_placement_changes: "Unfortunately, not all products that you requested were available. The original quantities that you requested appear crossed-out below." + email_so_payment_success_intro_html: "An automatic payment has been processed for your order from %{distributor}." + email_so_placement_explainer_html: "This order was automatically created for you." + email_so_edit_true_html: "You can make changes until orders close on %{orders_close_at}." + email_so_edit_false_html: "You can view details of this order at any time." + email_so_contact_distributor_html: "If you have any questions you can contact %{distributor} via %{email}." + email_so_contact_distributor_to_change_order_html: "This order was automatically created for you. You can make changes until orders close on %{orders_close_at} by contacting %{distributor} via %{email}." + email_so_confirmation_intro_html: "Your order with %{distributor} is now confirmed" + email_so_confirmation_explainer_html: "This order was automatically placed for you, and it has now been finalised." + email_so_confirmation_details_html: "Here's everything you need to know about your order from %{distributor}:" + email_so_empty_intro_html: "We tried to place a new order with %{distributor}, but had some problems..." + email_so_empty_explainer_html: "Unfortunately, none of products that you ordered were available, so no order has been placed. The original quantities that you requested appear crossed-out below." + email_so_empty_details_html: "Here are the details of the unplaced order for %{distributor}:" + email_so_failed_payment_intro_html: "We tried to process a payment, but had some problems..." + email_so_failed_payment_explainer_html: "The payment for your subscription with %{distributor} failed because of a problem with your credit card. %{distributor} has been notified of this failed payment." + email_so_failed_payment_details_html: "Here are the details of the failure provided by the payment gateway:" + email_shipping_delivery_details: Delivery details + email_shipping_delivery_time: "Delivery on:" + email_shipping_delivery_address: "Delivery address:" + email_shipping_collection_details: Collection details + email_shipping_collection_time: "Ready for collection:" + email_shipping_collection_instructions: "Collection instructions:" + email_special_instructions: "Your notes:" + email_signup_greeting: Hello! + 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_help_html: "We welcome all your questions and feedback; you can use the Send Feedback button on the site or email us at %{email}" + invite_email: + greeting: "Hello!" + invited_to_manage: "You have been invited to manage %{enterprise} on %{instance}." + confirm_your_email: "You should have received or will soon receive an email with a confirmation link. You won’t be able to access %{enterprise}'s profile until you have confirmed your email." + set_a_password: "You will then be prompted to set a password before you are able to administer the enterprise." + mistakenly_sent: "Not sure why you have received this email? Please contact %{owner_email} for more information." + producer_mail_greeting: "Dear" + producer_mail_text_before: "We now have all the consumer orders for the next food drop." + producer_mail_order_text: "Here is a summary of the orders for your products:" + producer_mail_delivery_instructions: "Stock pickup/delivery instructions:" + producer_mail_signoff: "Thanks and best wishes" + shopping_oc_closed: Orders are closed + shopping_oc_closed_description: "Please wait until the next cycle opens (or contact us directly to see if we can accept any late orders)" + shopping_oc_last_closed: "The last cycle closed %{distance_of_time} ago" + shopping_oc_next_open: "The next cycle opens in %{distance_of_time}" + shopping_oc_select: "Select..." + shopping_tabs_home: "Home" + shopping_tabs_shop: "Shop" + shopping_tabs_about: "About" + shopping_tabs_contact: "Contact" + shopping_contact_address: "Address" + shopping_contact_web: "Contact" + shopping_contact_social: "Follow" + shopping_groups_part_of: "is part of:" + shopping_producers_of_hub: "%{hub}'s producers:" + enterprises_next_closing: "Next order closing" + enterprises_ready_for: "Ready for" + enterprises_choose: "Choose when you want your order:" + maps_open: "Open" + maps_closed: "Closed" + hubs_buy: "Shop for:" + hubs_shopping_here: "Shopping here" + hubs_orders_closed: "Orders closed" + hubs_profile_only: "Profile only" + hubs_delivery_options: "Delivery options" + hubs_pickup: "Pickup" + hubs_delivery: "Delivery" + hubs_producers: "Our producers" + hubs_filter_by: "Filter by" + hubs_filter_type: "Type" + hubs_filter_delivery: "Delivery" + hubs_filter_property: "Property" + hubs_matches: "Did you mean?" + hubs_intro: Shop in your local area + hubs_distance: Closest to + hubs_distance_filter: "Show me shops near %{location}" + shop_changeable_orders_alert_html: + one: Your order with %{shop} / %{order} is open for review. You can make changes until %{oc_close}. + other: You have %{count} orders with %{shop} currently open for review. You can make changes until %{oc_close}. + orders_changeable_orders_alert_html: This order has been confirmed, but you can make changes until %{oc_close}. + products_clear_all: Clear all + products_showing: "Showing:" + products_or: "OR" + products_with: with + products_search: "Search by product or producer" + products_loading: "Loading products..." + products_updating_cart: "Updating cart..." + products_cart_empty: "Cart empty" + products_edit_cart: "Edit your cart" + products_from: from + products_change: "No changes to save." + products_update_error: "Saving failed with the following error(s):" + products_update_error_msg: "Saving failed." + products_update_error_data: "Save failed due to invalid data:" + products_changes_saved: "Changes saved." + search_no_results_html: "Sorry, no results found for %{query}. Try another search?" + components_profiles_popover: "Profiles do not have a shopfront on the Open Food Network, but may have their own physical or online shop elsewhere" + components_profiles_show: "Show profiles" + components_filters_nofilters: "No filters" + components_filters_clearfilters: "Clear all filters" + groups_title: Groups + groups_headline: Groups / regions + groups_text: "Every producer is unique. Every business has something different to offer. Our groups are collectives of producers, hubs and distributors who share something in common like location, farmers market or philosophy. This makes your shopping experience easier. So explore our groups and have the curating done for you." + groups_search: "Search name or keyword" + groups_no_groups: "No groups found" + groups_about: "About Us" + groups_producers: "Our producers" + groups_hubs: "Our hubs" + groups_contact_web: Contact + groups_contact_social: Follow + groups_contact_address: Address + groups_contact_email: Email us + groups_contact_website: Visit our website + groups_contact_facebook: Follow us on Facebook + groups_signup_title: Sign up as a group + groups_signup_headline: Groups sign up + groups_signup_intro: "We're an amazing platform for collaborative marketing, the easiest way for your members and stakeholders to reach new markets. We're non-profit, affordable, and simple." + groups_signup_email: Email us + groups_signup_motivation1: We transform food systems fairly. + 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_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 + groups_signup_studies: Case Studies + groups_signup_contact: Ready to discuss? + 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_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_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_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." + producers_about: About us + producers_buy: Shop for + producers_contact: Contact + producers_contact_phone: Call + producers_contact_social: Follow + producers_buy_at_html: "Shop for %{enterprise} products at:" + producers_filter: Filter by + producers_filter_type: Type + producers_filter_property: Property + 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_send: Join now + 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_detail: Here's the detail. + products_item: Item + products_description: Description + products_variant: Variant + products_quantity: Quantity + products_available: Available? + products_producer: "Producer" + products_price: "Price" + name_or_sku: "NAME OR SKU" + register_title: Register + sell_title: "Register" + sell_headline: "Get on the Open Food Network!" + sell_motivation: "Showcase your beautiful food." + 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_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 PHP 5,000 of monthly sales. If you sell more, you can choose your community contribution between 1.5% and 3% of sales. 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_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_pricing: Enterprise Accounts + shops_signup_stories: Stories from our hubs. + shops_signup_help: We're ready to help. + shops_signup_help_text: You need a better return. You need new buyers and logistics partners. You need your story told across wholesale, retail, and the kitchen table. + shops_signup_detail: Here's the detail. + orders: Orders + orders_fees: Fees... + orders_edit_title: Shopping Cart + orders_edit_headline: Your shopping cart + orders_edit_time: Order ready for + orders_edit_continue: Continue shopping + orders_edit_checkout: Checkout + orders_form_empty_cart: "Empty cart" + orders_form_subtotal: Produce subtotal + orders_form_admin: Admin & Handling + orders_form_total: Total + orders_oc_expired_headline: Orders have closed for this order cycle + orders_oc_expired_text: "Sorry, orders for this order cycle closed %{time} ago! Please contact your hub directly to see if they can accept late orders." + orders_oc_expired_text_others_html: "Sorry, orders for this order cycle closed %{time} ago! Please contact your hub directly to see if they can accept late orders %{link}." + orders_oc_expired_text_link: "or see the other order cycles available at this hub" + orders_oc_expired_email: "Email:" + orders_oc_expired_phone: "Phone:" + orders_show_title: Order Confirmation + orders_show_time: Order ready on + orders_show_order_number: "Order #%{number}" + orders_show_cancelled: Cancelled + orders_show_confirmed: Confirmed + orders_your_order_has_been_cancelled: "Your order has been cancelled" + orders_could_not_cancel: "Sorry, the order could not be cancelled" + orders_cannot_remove_the_final_item: "Cannot remove the final item from an order, please cancel the order instead." + orders_bought_items_notice: + one: "An additional item is already confirmed for this order cycle" + other: "%{count} additional items already confirmed for this order cycle" + orders_bought_edit_button: Edit confirmed items + orders_bought_already_confirmed: "* already confirmed" + orders_confirm_cancel: Are you sure you want to cancel this order? + order_processed_successfully: "Your order has been processed successfully" + products_cart_distributor_choice: "Distributor for your order:" + products_cart_distributor_change: "Your distributor for this order will be changed to %{name} if you add this product to your cart." + products_cart_distributor_is: "Your distributor for this order is %{name}." + products_distributor_error: "Please complete your order at %{link} before shopping with another distributor." + products_oc: "Order cycle for your order:" + products_oc_change: "Your order cycle for this order will be changed to %{name} if you add this product to your cart." + products_oc_is: "Your order cycle for this order is %{name}." + products_oc_error: "Please complete your order from %{link} before shopping in a different order cycle." + products_oc_current: "your current order cycle" + products_max_quantity: Max quantity + products_distributor: Distributor + products_distributor_info: When you select a distributor for your order, their address and pickup times will be displayed here. + password: Password + remember_me: Remember Me + are_you_sure: "Are you sure?" + orders_open: Orders open + closing: "Closing " + going_back_to_home_page: "Taking you back to the home page" + creating: Creating + updating: Updating + failed_to_create_enterprise: "Failed to create your enterprise." + failed_to_create_enterprise_unknown: "Failed to create your enterprise.\nPlease ensure all fields are completely filled out." + failed_to_update_enterprise_unknown: "Failed to update your enterprise.\nPlease ensure all fields are completely filled out." + enterprise_confirm_delete_message: "This will also delete the %{product} that this enterprise supplies. Are you sure you want to continue?" + order_not_saved_yet: "Your order hasn't been saved yet. Give us a few seconds to finish!" + filter_by: "Filter by" + hide_filters: "Hide filters" + one_filter_applied: "1 filter applied" + x_filters_applied: " filters applied" + submitting_order: "Submitting your order: please wait" + confirm_hub_change: "Are you sure? This will change your selected hub and remove any items in your shopping cart." + confirm_oc_change: "Are you sure? This will change your selected order cycle and remove any items in your shopping cart." + location_placeholder: "Type in a location..." + error_required: "can't be blank" + error_number: "must be number" + error_email: "must be email address" + error_not_found_in_database: "%{name} not found in database" + error_not_primary_producer: "%{name} is not enabled as a producer" + error_no_permission_for_enterprise: "\"%{name}\": you do not have permission to manage products for this enterprise" + item_handling_fees: "Item Handling Fees (included in item totals)" + january: "January" + february: "February" + march: "March" + april: "April" + may: "May" + june: "June" + july: "July" + august: "August" + september: "September" + october: "October" + november: "November" + december: "December" + email_not_found: "Email address not found" + email_unconfirmed: "You must confirm your email address before you can reset your password." + email_required: "You must provide an email address" + logging_in: "Hold on a moment, we're logging you in" + signup_email: "Your email" + choose_password: "Choose a password" + confirm_password: "Confirm password" + action_signup: "Sign up now" + forgot_password: "Forgot Password?" + password_reset_sent: "An email with instructions on resetting your password has been sent!" + reset_password: "Reset password" + update_and_recalculate_fees: "Update And Recalculate Fees" + registration: + steps: + introduction: + registration_greeting: "Hi there!" + registration_intro: "You can now create a profile for your Producer or Hub" + registration_checklist: "What do I need?" + registration_time: "5-10 minutes" + registration_enterprise_address: "Enterprise address" + registration_contact_details: "Primary contact details" + registration_logo: "Your logo image" + registration_promo_image: "Landscape image for your profile" + registration_about_us: "'About Us' text" + registration_outcome_headline: "What do I get?" + registration_outcome1_html: "Your profile helps people find and contact you on the Open Food Network." + registration_outcome2: "Use this space to tell the story of your enterprise, to help drive connections to your social and online presence." + registration_outcome3: "It's also the first step towards trading on the Open Food Network, or opening an online store." + registration_action: "Let's get started!" + details: + title: "Details" + headline: "Let's Get Started" + enterprise: "Woot! First need to know a little bit about your enterprise:" + producer: "Woot! First we need to know a little bit about your farm:" + enterprise_name_field: "Enterprise Name:" + producer_name_field: "Farm Name:" + producer_name_field_placeholder: "e.g. Jose's Awesome Farm" + producer_name_field_error: "Please choose a unique name for your enterprise" + address1_field: "Address line 1:" + address1_field_placeholder: "e.g. 123 Kapayapaan St." + address1_field_error: "Please enter an address" + address2_field: "Address line 2:" + suburb_field: "City:" + suburb_field_placeholder: "e.g. Tobias Fornier" + suburb_field_error: "Please enter a city/municipality" + postcode_field: "Postcode:" + postcode_field_placeholder: "e.g. 5716" + postcode_field_error: "Postcode required" + state_field: "Province:" + state_field_error: "Province required" + country_field: "Country:" + country_field_error: "Please select a country" + contact: + title: "Contact" + who_is_managing_enterprise: "Who is responsible for managing %{enterprise}?" + contact_field: "Primary Contact" + contact_field_placeholder: "Contact Name" + contact_field_required: "You need to enter a primary contact." + phone_field: "Phone number" + phone_field_placeholder: "eg. (03) 1234 5678" + type: + title: "Type" + headline: "Last step to add %{enterprise}!" + question: "Are you a producer?" + 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." + create_profile: "Create Profile" + about: + title: "About" + headline: "Nice one!" + message: "Now let's flesh out the details about" + success: "Success! %{enterprise} added to the Open Food Network" + registration_exit_message: "If you exit this wizard at any stage, you can continue to create your profile by going to the admin interface." + enterprise_description: "Short Description" + enterprise_description_placeholder: "A short sentence describing your enterprise" + enterprise_long_desc: "Long Description" + enterprise_long_desc_placeholder: "This is your opportunity to tell the story of your enterprise - what makes you different and wonderful? We'd suggest keeping your description to under 600 characters or 150 words." + enterprise_long_desc_length: "%{num} characters / up to 600 recommended" + enterprise_abn: "TIN" + enterprise_abn_placeholder: "eg. 99 123 456 789" + enterprise_acn: "Branch TIN" + enterprise_acn_placeholder: "eg. 123 456 789" + enterprise_tax_required: "You need to make a selection." + images: + title: "Images" + headline: "Thanks!" + description: "Let's upload some pretty pictures so your profile looks great! :)" + uploading: "Uploading..." + continue: "Continue" + back: "Back" + logo: + select_logo: "Step 1. Select Logo Image" + logo_tip: "Tip: Square images will work best, preferably at least 300×300px" + logo_label: "Choose a logo image" + logo_drag: "Drag and drop your logo here" + review_logo: "Step 2. Review Your Logo" + review_logo_tip: "Tip: for best results, your logo should fill the available space" + logo_placeholder: "Your logo will appear here for review once uploaded" + promo: + select_promo_image: "Step 3. Select Promo Image" + promo_image_tip: "Tip: Shown as a banner, preferred size is 1200×260px" + promo_image_label: "Choose a promo image" + promo_image_drag: "Drag and drop your promo here" + review_promo_image: "Step 4. Review Your Promo Banner" + review_promo_image_tip: "Tip: for best results, your promo image should fill the available space" + promo_image_placeholder: "Your logo will appear here for review once uploaded" + social: + title: "Social" + enterprise_final_step: "Final step!" + enterprise_social_text: "How can people find %{enterprise} online?" + website: "Website" + website_placeholder: "e.g. www.openfoodnetwork.ph" + facebook: "Facebook" + facebook_placeholder: "eg. www.facebook.com/PageNameHere" + linkedin: "LinkedIn" + linkedin_placeholder: "eg. www.linkedin.com/YourNameHere" + twitter: "Twitter" + twitter_placeholder: "e.g. @OFNPhilippines" + instagram: "Instagram" + instagram_placeholder: "eg. @OFNPhilippines" + limit_reached: + headline: "Oh no!" + message: "You have reached the limit!" + text: "You have reached the limit for the number of enterprises you are allowed to own on the" + action: "Return to the homepage" + 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." + action: "Go to Enterprise Dashboard" + back: "Back" + continue: "Continue" + action_or: "OR" + enterprise_limit: Enterprise Limit + shipping_method_destroy_error: "That shipping method cannot be deleted as it is referenced by an order: %{number}." + fees: "Fees" + item_cost: "Item cost" + bulk: "Bulk" + shop_variant_quantity_min: "min" + shop_variant_quantity_max: "max" + follow: "Follow" + shop_for_products_html: "Shop for %{enterprise} products at:" + change_shop: "Change shop to:" + shop_at: "Shop now at:" + price_breakdown: "Full price breakdown" + admin_fee: "Admin fee" + sales_fee: "Sales fee" + packing_fee: "Packing fee" + transport_fee: "Transport fee" + fundraising_fee: "Fundraising fee" + price_graph: "Price graph" + included_tax: "Included tax" + balance: "Balance" + transaction: "Transaction" + transaction_date: "Date" + payment_state: "Payment status" + shipping_state: "Shipping status" + value: "Value" + balance_due: "Balance due" + credit: "Credit" + Paid: "Paid" + Ready: "Ready" + ok: OK + not_visible: not visible + you_have_no_orders_yet: "You have no orders yet" + show_only_complete_orders: "Only show complete orders" + successfully_created: '%{resource} has been successfully created!' + successfully_removed: '%{resource} has been successfully removed!' + successfully_updated: '%{resource} has been successfully updated!' + running_balance: "Running balance" + outstanding_balance: "Outstanding balance" + admin_enterprise_relationships: "Enterprise Permissions" + admin_enterprise_relationships_everything: "Everything" + admin_enterprise_relationships_permits: "permits" + admin_enterprise_relationships_seach_placeholder: "Search" + admin_enterprise_relationships_button_create: "Create" + admin_enterprise_groups: "Enterprise Groups" + admin_enterprise_groups_name: "Name" + admin_enterprise_groups_owner: "Owner" + admin_enterprise_groups_on_front_page: "On front page ?" + admin_enterprise_groups_enterprise: "Enterprises" + admin_enterprise_groups_data_powertip: "The primary user responsible for this group." + admin_enterprise_groups_data_powertip_logo: "This is the logo for the group" + admin_enterprise_groups_data_powertip_promo_image: "This image is displayed at the top of the Group profile" + admin_enterprise_groups_contact: "Contact" + admin_enterprise_groups_contact_phone_placeholder: "eg. 98 7654 3210" + admin_enterprise_groups_contact_address1_placeholder: "123 Kapayapaan St." + admin_enterprise_groups_contact_city: "City" + admin_enterprise_groups_contact_city_placeholder: "e.g. Mandaluyong" + admin_enterprise_groups_contact_zipcode: "Postcode" + admin_enterprise_groups_contact_zipcode_placeholder: "e.g. 1555" + admin_enterprise_groups_contact_state_id: "Province" + admin_enterprise_groups_contact_country_id: "Country" + admin_enterprise_groups_web: "Web Resources" + admin_enterprise_groups_web_twitter: "e.g. @OFNPhilippines" + admin_enterprise_groups_web_website_placeholder: "eg. www.truffles.com" + admin_order_cycles: "Admin Order Cycles" + open: "Open" + close: "Close" + create: "Create" + search: "Search" + supplier: "Supplier" + product_name: "Product Name" + product_description: "Product Description" + units: "Unit Size" + coordinator: "Coordinator" + distributor: "Distributor" + enterprise_fees: "Enterprise Fees" + process_my_order: "Process My Order" + delivery_instructions: Delivery Instructions + delivery_method: Delivery Method + fee_type: "Fee Type" + tax_category: "Tax Category" + calculator: "Calculator" + calculator_values: "Calculator values" + calculator_settings_warning: "If you are changing the calculator type, you must save first before you can edit the calculator settings" + flat_percent_per_item: "Flat Percent (per item)" + flat_rate_per_item: "Flat Rate (per item)" + flat_rate_per_order: "Flat Rate (per order)" + flexible_rate: "Flexible Rate" + price_sack: "Price Sack" + new_order_cycles: "New Order Cycles" + new_order_cycle: "New Order Cycle" + select_a_coordinator_for_your_order_cycle: "Select a coordinator for your order cycle" + notify_producers: 'Notify producers' + edit_order_cycle: "Edit Order Cycle" + roles: "Roles" + update: "Update" + delete: Delete + add_producer_property: "Add producer property" + in_progress: "In Progress" + started_at: "Started at" + queued: "Queued" + scheduled_for: "Scheduled for" + customers: "Customers" + please_select_hub: "Please select a Hub" + loading_customers: "Loading Customers" + no_customers_found: "No customers found" + go: "Go" + hub: "Hub" + producer: "Producer" + product: "Product" + price: "Price" + on_hand: "On hand" + review: "Review" + save_changes: "Save Changes" + order_saved: "Order Saved" + no_products: No Products + spree_admin_overview_enterprises_header: "My Enterprises" + spree_admin_overview_enterprises_footer: "MANAGE MY ENTERPRISES" + spree_admin_enterprises_hubs_name: "Name" + spree_admin_enterprises_create_new: "CREATE NEW" + spree_admin_enterprises_shipping_methods: "Shipping Methods" + spree_admin_enterprises_fees: "Enterprise Fees" + spree_admin_enterprises_none_create_a_new_enterprise: "CREATE A NEW ENTERPRISE" + spree_admin_enterprises_none_text: "You don't have any enterprises yet" + spree_admin_enterprises_tabs_hubs: "HUBS" + spree_admin_enterprises_producers_manage_products: "MANAGE PRODUCTS" + spree_admin_enterprises_create_new_product: "CREATE A NEW PRODUCT" + spree_admin_single_enterprise_alert_mail_confirmation: "Please confirm the email address for" + spree_admin_single_enterprise_alert_mail_sent: "We've sent an email to" + spree_admin_overview_action_required: "Action Required" + spree_admin_overview_check_your_inbox: "Please check your inbox for further instructions. Thanks!" + spree_admin_unit_value: Unit Value + spree_admin_unit_description: Unit Description + spree_admin_variant_unit: Variant unit + spree_admin_variant_unit_scale: Variant unit scale + spree_admin_supplier: Supplier + spree_admin_product_category: Product Category + spree_admin_variant_unit_name: Variant unit name + unit_name: "Unit name" + change_package: "Change Package" + spree_admin_single_enterprise_hint: "Hint: To allow people to find you, turn on your visibility under" + spree_admin_eg_pickup_from_school: "eg. 'Pick-up from Primary School'" + spree_admin_eg_collect_your_order: "eg. 'Please collect your order from 123 Kapayapaan St., Tobias Fornier, Antique 5716'" + spree_classification_primary_taxon_error: "Taxon %{taxon} is the primary taxon of %{product} and cannot be deleted" + spree_order_availability_error: "Distributor or order cycle cannot supply the products in your cart" + spree_order_populator_error: "That distributor or order cycle can't supply all the products in your cart. Please choose another." + spree_order_populator_availability_error: "That product is not available from the chosen distributor or order cycle." + spree_distributors_error: "At least one hub must be selected" + spree_user_enterprise_limit_error: "^%{email} is not permitted to own any more enterprises (limit is %{enterprise_limit})." + spree_variant_product_error: must have at least one variant + your_profil_live: "Your profile live" + on_ofn_map: "on the Open Food Network map" + see: "See" + live: "live" + manage: "Manage" + resend: "Resend" + add_and_manage_products: "Add & manage products" + add_and_manage_order_cycles: "Add & manage order cycles" + manage_order_cycles: "Manage order cycles" + manage_products: "Manage products" + edit_profile_details: "Edit profile details" + edit_profile_details_etc: "Change your profile description, images, etc." + order_cycle: "Order Cycle" + order_cycles: "Order Cycles" + enterprise_relationships: "Enterprise permissions" + remove_tax: "Remove tax" + first_name_begins_with: "First name begins with" + last_name_begins_with: "Last name begins with" + enterprise_tos_link: "Enterprise Terms of Service link" + enterprise_tos_message: "We want to work with people that share our aims and values. As such we ask new enterprises to agree to our " + enterprise_tos_link_text: "Terms of Service." + enterprise_tos_agree: "I agree to the above Terms of Service" + tax_settings: "Tax Settings" + products_require_tax_category: "products require tax category" + admin_shared_address_1: "Address" + admin_shared_address_2: "Address (cont.)" + admin_share_city: "City" + admin_share_zipcode: "Postcode" + admin_share_country: "Country" + admin_share_state: "Province" + hub_sidebar_hubs: "Hubs" + hub_sidebar_none_available: "None Available" + hub_sidebar_manage: "Manage" + hub_sidebar_at_least: "At least one hub must be selected" + hub_sidebar_blue: "blue" + hub_sidebar_red: "red" + report_customers_distributor: "Distributor" + report_customers_supplier: "Supplier" + report_customers_cycle: "Order Cycle" + report_customers_type: "Report Type" + report_customers_csv: "Download as csv" + report_producers: "Producers: " + report_type: "Report Type: " + report_hubs: "Hubs: " + report_payment: "Payment Methods: " + report_distributor: "Distributor: " + report_payment_by: 'Payments By Type' + report_itemised_payment: 'Itemised Payment Totals' + report_payment_totals: 'Payment Totals' + report_all: 'all' + report_order_cycle: "Order Cycle: " + report_enterprises: "Enterprises: " + report_users: "Users: " + report_tax_rates: Tax rates + report_tax_types: Tax types + report_header_order_cycle: Order Cycle + report_header_user: User + report_header_email: Email + report_header_status: Status + report_header_comments: Comments + report_header_first_name: First Name + report_header_last_name: Last Name + report_header_phone: Phone + report_header_suburb: City + report_header_address: Address + report_header_billing_address: Billing Address + report_header_relationship: Relationship + report_header_hub: Hub + report_header_hub_address: Hub Address + report_header_to_hub: To Hub + report_header_hub_code: Hub Code + report_header_code: Code + report_header_paid: Paid? + report_header_delivery: Delivery? + report_header_shipping: Shipping + report_header_shipping_method: Shipping Method + report_header_shipping_instructions: Shipping instructions + report_header_ship_street: Ship Street + report_header_ship_street_2: Ship Street 2 + report_header_ship_city: Ship City + report_header_ship_postcode: Ship Postcode + report_header_ship_state: Ship State + 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 Postcode + report_header_billing_state: Billing State + report_header_incoming_transport: Incoming Transport + report_header_special_instructions: Special Instructions + report_header_order_number: Order number + report_header_date: Date + report_header_confirmation_date: Confirmation Date + report_header_tags: Tags + report_header_items: Items + report_header_items_total: "Items total %{currency_symbol}" + report_header_taxable_items_total: "Taxable Items Total (%{currency_symbol})" + report_header_sales_tax: "Sales Tax (%{currency_symbol})" + report_header_delivery_charge: "Delivery Charge (%{currency_symbol})" + report_header_tax_on_delivery: "Tax on Delivery (%{currency_symbol})" + report_header_tax_on_fees: "Tax on Fees (%{currency_symbol})" + report_header_total_tax: "Total Tax (%{currency_symbol})" + report_header_enterprise: Enterprise + report_header_customer: Customer + report_header_customer_code: Customer Code + report_header_product: Product + report_header_product_properties: Product Properties + report_header_quantity: Quantity + report_header_max_quantity: Max Quantity + report_header_variant: Variant + report_header_variant_value: Variant Value + report_header_variant_unit: Variant Unit + report_header_total_available: Total available + report_header_unallocated: Unallocated + report_header_max_quantity_excess: Max Quantity Excess + report_header_taxons: Taxons + report_header_supplier: Supplier + report_header_producer: Producer + report_header_producer_suburb: Producer City + report_header_unit: Unit + report_header_group_buy_unit_quantity: Group Buy Unit Quantity + report_header_cost: Cost + report_header_shipping_cost: Shipping Cost + report_header_curr_cost_per_unit: Curr. Cost per Unit + report_header_total_shipping_cost: Total Shipping Cost + report_header_payment_method: Payment Method + report_header_sells: Sells + report_header_visible: Visible + report_header_price: Price + report_header_unit_size: Unit Size + report_header_distributor: Distributor + report_header_distributor_address: Distributor address + report_header_distributor_city: Distributor city + report_header_distributor_postcode: Distributor postcode + report_header_delivery_address: Delivery Address + report_header_delivery_postcode: Delivery Postcode + report_header_bulk_unit_size: Bulk Unit Size + report_header_weight: Weight + report_header_sum_total: Sum Total + report_header_date_of_order: Date of Order + report_header_amount_owing: Amount Owing + report_header_amount_paid: Amount Paid + report_header_units_required: Units Required + report_header_remainder: Remainder + report_header_order_date: Order date + report_header_order_id: Order Id + report_header_item_name: Item name + report_header_temp_controlled_items: Temp Controlled Items? + report_header_customer_name: Customer Name + report_header_customer_email: Customer Email + report_header_customer_phone: Customer Phone + report_header_customer_city: Customer City + report_header_payment_state: Payment State + report_header_payment_type: Payment Type + report_header_item_price: "Item (%{currency})" + report_header_item_fees_price: "Item + Fees (%{currency})" + report_header_admin_handling_fees: "Admin & Handling (%{currency})" + report_header_ship_price: "Ship (%{currency})" + report_header_pay_fee_price: "Pay fee (%{currency})" + report_header_total_price: "Total (%{currency})" + report_header_product_total_price: "Product Total (%{currency})" + report_header_shipping_total_price: "Shipping Total (%{currency})" + report_header_outstanding_balance_price: "Outstanding Balance (%{currency})" + report_header_eft_price: "EFT (%{currency})" + report_header_paypal_price: "PayPal (%{currency})" + report_header_sku: SKU + report_header_amount: Amount + report_header_balance: Balance + report_header_total_cost: "Total Cost" + report_header_total_ordered: Total Ordered + report_header_total_max: Total Max + report_header_total_units: Total Units + report_header_sum_max_total: "Sum Max Total" + report_header_total_excl_vat: "Total excl. tax (%{currency_symbol})" + report_header_total_incl_vat: "Total incl. tax (%{currency_symbol})" + report_header_temp_controlled: TempControlled? + report_header_is_producer: Producer? + report_header_not_confirmed: Not Confirmed + report_header_gst_on_income: VAT on Income + report_header_gst_free_income: VAT Free Income + report_header_total_untaxable_produce: Total untaxable produce (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) + report_header_delivery_shipping_cost: Delivery Shipping Cost (tax inclusive) + report_header_transaction_fee: Transaction Fee (no tax) + report_header_total_untaxable_admin: Total untaxable admin adjustments (no tax) + report_header_total_taxable_admin: Total taxable admin adjustments (tax inclusive) + initial_invoice_number: "Initial invoice number:" + invoice_date: "Invoice date:" + due_date: "Due date:" + account_code: "Account code:" + equals: "Equals" + contains: "contains" + discount: "Discount" + filter_products: "Filter Products" + delete_product_variant: "The last variant cannot be deleted!" + progress: "progress" + saving: "Saving.." + success: "success" + failure: "failure" + unsaved_changes_confirmation: "Unsaved changes will be lost. Continue anyway?" + one_product_unsaved: "Changes to one product remain unsaved." + products_unsaved: "Changes to %{n} products remain unsaved." + is_already_manager: "is already a manager!" + no_change_to_save: " No change to save" + user_invited: "%{email} has been invited to manage this enterprise" + add_manager: "Add an existing user" + users: "Users" + about: "About" + images: "Images" + web: "Web" + primary_details: "Primary Details" + adrdress: "Address" + contact: "Contact" + social: "Social" + business_details: "Business Details" + properties: "Properties" + shipping: "Shipping" + shipping_methods: "Shipping Methods" + payment_methods: "Payment Methods" + payment_method_fee: "Transaction fee" + payment_processing_failed: "Payment could not be processed, please check the details you entered" + payment_method_not_supported: "That payment method is unsupported. Please choose another one." + payment_updated: "Payment Updated" + inventory_settings: "Inventory Settings" + tag_rules: "Tag Rules" + shop_preferences: "Shop Preferences" + enterprise_fee_whole_order: Whole order + enterprise_fee_by: "%{type} fee by %{role} %{enterprise_name}" + validation_msg_relationship_already_established: "^That relationship is already established." + validation_msg_at_least_one_hub: "^At least one hub must be selected" + validation_msg_tax_category_cant_be_blank: "^Tax Category can't be blank" + validation_msg_is_associated_with_an_exising_customer: "is associated with an existing customer" + content_configuration_pricing_table: "(TODO: Pricing table)" + content_configuration_case_studies: "(TODO: Case studies)" + content_configuration_detail: "(TODO: Detail)" + enterprise_name_error: "has already been taken. If this is your enterprise and you would like to claim ownership, or if you would like to trade with this enterprise please contact the current manager of this profile at %{email}." + enterprise_owner_error: "^%{email} is not permitted to own any more enterprises (limit is %{enterprise_limit})." + enterprise_role_uniqueness_error: "^That role is already present." + inventory_item_visibility_error: must be true or false + product_importer_file_error: "error: no file uploaded" + product_importer_spreadsheet_error: "could not process file: invalid filetype" + product_importer_products_save_error: did not save any products successfully + product_import_file_not_found_notice: 'File not found or could not be opened' + product_import_no_data_in_spreadsheet_notice: 'No data found in spreadsheet' + order_choosing_hub_notice: Your hub has been selected. + order_cycle_selecting_notice: Your order cycle has been selected. + adjustments_tax_rate_error: "^Please check that the tax rate for this adjustment is correct." + active_distributors_not_ready_for_checkout_message_singular: >- + The hub %{distributor_names} is listed in an active order cycle, but does not + have valid shipping and payment methods. Until you set these up, customers will + not be able to shop at this hub. + active_distributors_not_ready_for_checkout_message_plural: >- + The hubs %{distributor_names} are listed in an active order cycle, but do not + have valid shipping and payment methods. Until you set these up, customers will + not be able to shop at these hubs. + enterprise_fees_update_notice: Your enterprise fees have been updated. + enterprise_register_package_error: "Please select a package" + enterprise_register_error: "Could not complete registration for %{enterprise}" + enterprise_register_success_notice: "Congratulations! Registration for %{enterprise} is complete!" + enterprise_bulk_update_success_notice: "Enterprises updated successfully" + enterprise_bulk_update_error: 'Update failed' + enterprise_shop_show_error: "The shop you are looking for doesn't exist or is inactive on OFN. Please check other shops." + order_cycles_create_notice: 'Your order cycle has been created.' + order_cycles_update_notice: 'Your order cycle has been updated.' + order_cycles_bulk_update_notice: 'Order cycles have been updated.' + order_cycles_clone_notice: "Your order cycle %{name} has been cloned." + order_cycles_email_to_producers_notice: 'Emails to be sent to producers have been queued for sending.' + order_cycles_no_permission_to_coordinate_error: "None of your enterprises have permission to coordinate an order cycle" + order_cycles_no_permission_to_create_error: "You don't have permission to create an order cycle coordinated by that enterprise" + back_to_orders_list: "Back to order list" + no_orders_found: "No Orders Found" + order_information: "Order Information" + date_completed: "Date Completed" + amount: "Amount" + state_names: + ready: Ready + pending: Pending + shipped: Shipped + js: + saving: 'Saving...' + changes_saved: 'Changes saved.' + save_changes_first: Save changes first. + all_changes_saved: All changes saved + unsaved_changes: You have unsaved changes + all_changes_saved_successfully: All changes saved successfully + oh_no: "Oh no! I was unable to save your changes." + unauthorized: "You are unauthorised to access this page." + error: Error + unavailable: Unavailable + profile: Profile + hub: Hub + shop: Shop + choose: Choose + resolve_errors: Please resolve the following errors + more_items: "+ %{count} More" + default_card_updated: Default Card Updated + admin: + enterprise_limit_reached: "You have reached the standard limit of enterprises per account. Write to %{contact_email} if you need to increase it." + modals: + got_it: Got it + close: "Close" + invite: "Invite" + invite_title: "Invite an unregistered user" + tag_rule_help: + title: Tag Rules + overview: Overview + overview_text: > + Tag rules provide a way to describe which items are visible or otherwise + to which customers. Items can be Shipping Methods, Payment Methods, + Products and Order Cycles. + by_default_rules: "'By Default...' Rules" + by_default_rules_text: > + Default rules allow you to hide items so that they are not visible by + default. This behaviour can then be overriden by non-default rules for + customers with particular tags. + customer_tagged_rules: "'Customers Tagged...' Rules" + customer_tagged_rules_text: > + By creating rules related to a specific customer tag, you can override + the default behaviour (whether it be to show or to hide items) for customers + with the specified tag. + panels: + save: SAVE + saved: SAVED + saving: SAVING + enterprise_package: + hub_profile: Hub Profile + hub_profile_cost: "COST: ALWAYS FREE" + hub_profile_text1: > + 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. + 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 + 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. + hub_shop_text3: > + If you also want to sell your own products, you will need to switch + this enterprise to be a producer. + choose_package: Please Choose a Package + choose_package_text1: > + Your enterprise will not be fully activated until a package is selected + from the options on the left. + choose_package_text2: > + Click on an option to see more detailed information about each package, + and hit the red SAVE button when you are done! + profile_only: Profile Only + profile_only_cost: "COST: ALWAYS FREE" + profile_only_text1: > + 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. + profile_only_text3: > + Add your products to Open Food Network, allowing hubs to stock your + products in their stores. + producer_shop: Producer Shop + producer_shop_text1: > + 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'. + 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 + 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_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 + 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. + 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 + Network. + non_producer: Non-producer + non_producer_text1: > + Non-producers do not produce any food 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 + 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 + enterprise_status: + status_title: "%{name} is set up and ready to go!" + severity: Severity + description: Description + resolve: Resolve + exchange_products: + load_more_variants: "Load More Variants" + load_all_variants: "Load All Variants" + select_all_variants: "Select All %{total_number_of_variants} Variants" + variants_loaded: "%{num_of_variants_loaded} of %{total_number_of_variants} Variants Loaded" + loading_variants: "Loading Variants" + tag_rules: + shipping_method_tagged_top: "Shipping methods tagged" + shipping_method_tagged_bottom: "are:" + payment_method_tagged_top: "Payment methods tagged" + payment_method_tagged_bottom: "are:" + order_cycle_tagged_top: "Order Cycles tagged" + order_cycle_tagged_bottom: "are:" + inventory_tagged_top: "Inventory variants tagged" + inventory_tagged_bottom: "are:" + new_tag_rule_dialog: + select_rule_type: "Select a rule type:" + add_rule: "Add Rule" + enterprise_fees: + inherit_from_product: "Inherit From Product" + orders: + index: + per_page: "%{results} per page" + view_file: "View File" + compiling_invoices: "Compiling Invoices" + bulk_invoice_created: "Bulk Invoice created" + bulk_invoice_failed: "Failed to create Bulk Invoice" + please_wait: "Please wait until the PDF is ready before closing this modal." + order_state: + address: "address" + adjustments: "adjustments" + awaiting_return: "awaiting return" + canceled: "cancelled" + cart: "cart" + complete: "complete" + confirm: "confirm" + delivery: "delivery" + paused: "paused" + payment: "payment" + pending: "pending" + resumed: "resumed" + returned: "returned" + skrill: "skrill" + shipment_states: + backorder: "backorder" + partial: "partial" + pending: "pending" + ready: "ready" + shipped: "shipped" + canceled: "cancelled" + payment_states: + balance_due: "balance due" + completed: "completed" + checkout: "checkout" + credit_owed: "credit owed" + failed: "failed" + paid: "paid" + pending: "pending" + processing: "processing" + void: "void" + invalid: "invalid" + resend_user_email_confirmation: + resend: "Resend" + sending: "Resend..." + done: "Resend done ✓" + failed: "Resend failed ✗" + order_cycles: + schedules: + adding_a_new_schedule: "Adding A New Schedule" + updating_a_schedule: "Updating A Schedule" + create_schedule: "Create Schedule" + update_schedule: "Update Schedule" + delete_schedule: "Delete Schedule" + schedule_name_placeholder: "Schedule Name" + created_schedule: "Created schedule" + updated_schedule: "Updated schedule" + deleted_schedule: "Deleted schedule" + name_required_error: "Please enter a name for this schedule" + no_order_cycles_error: "Please select at least one order cycle (drag and drop)" + available: "Available" + selected: "Selected" + customers: + index: + add_customer: "Add Customer" + add_a_new_customer_for: "Add a new customer for %{shop_name}" + 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" + out_of_stock: + reduced_stock_available: Reduced stock available + out_of_stock_text: > + While you've been shopping, the stock levels for one or more of the products + in your cart have reduced. Here's what's changed: + now_out_of_stock: is now out of stock. + only_n_remainging: "now only has %{num} remaining." + variants: + on_demand: + 'yes': "On demand" + variant_overrides: + on_demand: + use_producer_settings: "Use producer stock settings" + 'yes': "Yes" + 'no': "No" + inventory_products: "Inventory Products" + hidden_products: "Hidden Products" + new_products: "New Products" + reset_stock_levels: Reset Stock Levels To Defaults + changes_to: Changes to + one_override: one override + overrides: overrides + remain_unsaved: remain unsaved. + no_changes_to_save: No changes to save.' + no_authorisation: "I couldn't get authorisation to save those changes, so they remain unsaved." + some_trouble: "I had some trouble saving: %{errors}" + changing_on_hand_stock: Changing on hand stock levels... + stock_reset: Stocks reset to defaults. + tag_rules: + show_hide_variants: 'Show or Hide variants in my shopfront' + show_hide_shipping: 'Show or Hide shipping methods at checkout' + show_hide_payment: 'Show or Hide payment methods at checkout' + show_hide_order_cycles: 'Show or Hide order cycles in my shopfront' + visible: VISIBLE + not_visible: NOT VISIBLE + services: + unsaved_changes_message: Unsaved changes currently exist, save now or ignore? + save: SAVE + ignore: IGNORE + add_to_order_cycle: "add to order cycle" + manage_products: "manage products" + edit_profile: "edit profile" + add_products_to_inventory: "add products to inventory" + resources: + could_not_delete_customer: 'Could not delete customer' + product_import: + confirmation: | + This will set stock level to zero on all products for this + enterprise that are not present in the uploaded file. + order_cycles: + create_failure: "Failed to create order cycle" + update_success: 'Your order cycle has been updated.' + update_failure: "Failed to update order cycle" + no_distributors: There are no distributors in this order cycle. This order cycle will not be visible to customers until you add one. Would you like to continue saving this order cycle?' + enterprises: + producer: "Producer" + non_producer: "Non-Producer" + customers: + select_shop: 'Please select a shop first' + could_not_create: Sorry! Could not create + subscriptions: + closes: closes + closed: closed + close_date_not_set: Close date not set + spree: + users: + order: "Order" + registration: + welcome_to_ofn: "Welcome to the Open Food Network!" + signup_or_login: "Start By Signing Up (or logging in)" + have_an_account: "Already have an account?" + action_login: "Log in now." + inflections: + each: + one: "each" + other: "each" + bunch: + one: "bunch" + other: "bunches" + pack: + one: "pack" + other: "packs" + box: + one: "box" + other: "boxes" + bottle: + one: "bottle" + other: "bottles" + jar: + one: "jar" + other: "jars" + head: + one: "head" + other: "heads" + bag: + one: "bag" + other: "bags" + loaf: + one: "loaf" + other: "loaves" + single: + one: "single" + other: "singles" + tub: + one: "tub" + other: "tubs" + punnet: + one: "punnet" + other: "punnets" + packet: + one: "packet" + other: "packets" + item: + one: "item" + other: "items" + dozen: + one: "dozen" + other: "dozens" + unit: + one: "unit" + other: "units" + serve: + one: "serve" + other: "serves" + tray: + one: "tray" + other: "trays" + piece: + one: "piece" + other: "pieces" + pot: + one: "pot" + other: "pots" + bundle: + one: "bundle" + other: "bundles" + flask: + one: "flask" + other: "flasks" + basket: + one: "basket" + other: "baskets" + sack: + one: "sack" + other: "sacks" + producers: + signup: + start_free_profile: "Start with a free profile, and expand when you're ready!" + order_management: + reports: + enterprise_fee_summary: + date_end_before_start_error: "must be after start" + parameter_not_allowed_error: "You are not authorized to use one or more selected filters for this report." + fee_calculated_on_transfer_through_all: "All" + fee_calculated_on_transfer_through_entire_orders: "Entire Orders through %{distributor}" + tax_category_various: "Various" + fee_type: + payment_method: "Payment Transaction" + shipping_method: "Shipment" + fee_placements: + supplier: "Incoming" + distributor: "Outgoing" + coordinator: "Coordinator" + tax_category_name: + shipping_instance_rate: "Platform Rate" + formats: + csv: + header: + fee_type: "Fee Type" + enterprise_name: "Enterprise Owner" + fee_name: "Fee Name" + customer_name: "Customer" + fee_placement: "Fee Placement" + fee_calculated_on_transfer_through_name: "Fee Calc on Transfer Through" + tax_category_name: "Tax Category" + total_amount: "$$ SUM" + html: + header: + fee_type: "Fee Type" + enterprise_name: "Enterprise Owner" + fee_name: "Fee Name" + customer_name: "Customer" + fee_placement: "Fee Placement" + fee_calculated_on_transfer_through_name: "Fee Calc on Transfer Through" + tax_category_name: "Tax Category" + total_amount: "$$ SUM" + invalid_filter_parameters: "The filters you selected for this report are invalid." + order: "Order" + distribution: "Distribution" + order_details: "Order Details" + customer_details: "Customer Details" + adjustments: "Adjustments" + payments: "Payments" + payment: "Payment" + payment_method: "Payment Method" + shipment: "Shipment" + shipment_inc_vat: "Shipment including VAT" + shipping_tax_rate: "Shipping Tax Rate" + category: "Category" + delivery: "Delivery" + temperature_controlled: "Temperature Controlled" + new_product: "New Product" + administration: "Administration" + logged_in_as: "Logged in as" + account: "Account" + logout: "Logout" + date_range: "Date Range" + status: "status" + new: "New" + start: "Start" + end: "End" + stop: "Stop" + first: "First" + previous: "Previous" + last: "Last" + spree: + your_order_is_empty_add_product: "Your order is empty, please search for and add a product above" + add_product: "Add Product" + name_or_sku: "Name or SKU (enter at least first 4 characters of product name)" + resend: Resend + back_to_orders_list: Back To Orders List + return_authorizations: Return Authorizations + cannot_create_returns: Cannot create returns as this order has no shipped units. + select_stock: "Select stock" + location: "Location" + count_on_hand: "Count On Hand" + quantity: "Quantity" + on_demand: "On Demand" + on_hand: "On Hand" + package_from: "package from" + item_description: "Item Description" + price: "Price" + total: "Total" + edit: "Edit" + split: "Split" + delete: "Delete" + cannot_set_shipping_method_without_address: "Cannot set shipping method until customer details are provided." + no_tracking_present: "No tracking details provided." + order_total: "Order Total" + customer_details: "Customer Details" + customer_search: "Customer Search" + choose_a_customer: "Choose a customer" + account: "Account" + billing_address: "Billing Address" + shipping_address: "Shipping Address" + first_name: "First name" + last_name: "Last name" + street_address: "Street Address" + street_address_2: "Street Address (cont'd)" + city: "City" + zip: "ZIP" + country: "Country" + state: "Province" + phone: "Phone" + update: "Update" + use_billing_address: "Use Billing Address" + adjustments: "Adjustments" + continue: "Continue" + fill_in_customer_info: "Please fill in customer info" + new_payment: "New Payment" + capture: "Capture" + void: "Void" + configurations: "Configurations" + general_settings: "General Settings" + site_name: "Site Name" + site_url: "Site URL" + default_seo_title: "Default Seo Title" + default_meta_description: "Default Meta Description" + default_meta_keywords: "Default Meta Keywords" + security_settings: "Security Settings" + 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" + currency_decimal_mark: "Currency decimal mark" + currency_settings: "Currency Settings" + currency_symbol_position: Put "currency symbol before or after currency amount?" + currency_thousands_separator: "Currency thousands separator" + hide_cents: "Hide cents" + display_currency: "Display currency" + choose_currency: "Choose Currency" + mail_method_settings: "Mail Method Settings" + general: "General" + enable_mail_delivery: "Enable Mail Delivery" + send_mails_as: "Send Mails As" + smtp_send_all_emails_as_from_following_address: "Send all mails as from the following address." + send_copy_of_all_mails_to: "Send Copy of All Mails To" + smtp_send_copy_to_this_addresses: "Sends a copy of all outgoing mails to this address. For multiple addresses, separate with commas." + intercept_email_address: "Intercept Email Address" + intercept_email_instructions: "Override email recipient and replace with this address." + smtp: "SMTP" + smtp_domain: "SMTP Domain" + smtp_mail_host: "SMTP Mail Host" + smtp_port: "SMTP Port" + secure_connection_type: "Secure Connection Type" + smtp_authentication_type: "SMTP Authentication Type" + smtp_username: "SMTP Username" + smtp_password: "SMTP Password" + image_settings: "Image Settings" + image_settings_warning: "You will need to regenerate thumbnails if you update the paperclip styles. Use rake paperclip:refresh:thumbnails CLASS=Spree::Image to do this." + attachment_default_style: Attachments Style + attachment_default_url: "Attachments Default URL" + attachment_path: "Attachments Path" + attachment_styles: "Paperclip Styles" + attachment_url: "Attachments URL" + add_new_style: "Add New Style" + image_settings_updated: "Image Settings successfully updated." + tax_categories: "Tax Categories" + listing_tax_categories: "Listing Tax Categories" + back_to_tax_categories_list: "Back To Tax Categories List" + tax rate: "Tax Rates" + new_tax_rate: "New Tax Rate" + tax_category: "Tax Category" + rate: "Rate" + tax_rate_amount_explanation: "Tax rates are a decimal amount to aid in calculations, (i.e. if the tax rate is 5% then enter 0.05)" + included_in_price: "Included in Price" + show_rate_in_label: "Show rate in label" + back_to_tax_rates_list: "Back to Tax Rates List" + tax_settings: "Tax Settings" + zones: "Zones" + new_zone: "New Zone" + default_tax: "Default Tax" + default_tax_zone: "Default Tax Zone" + country_based: "Country Based" + state_based: "Province Based" + countries: "Countries" + listing_countries: "Listing Countries" + iso_name: "ISO Name" + states_required: "Provinces Required" + editing_country: "Editing Country" + back_to_countries_list: "Back to Countries List" + states: "Provinces" + abbreviation: "Abbreviation" + new_state: "New Province" + payment_methods: "Payment Methods" + new_payment_method: "New Payment Method" + provider: "Provider" + taxonomies: "Taxonomies" + new_taxonomy: "New Category" + back_to_taxonomies_list: "Back to Taxonomies List" + shipping_methods: "Shipping Methods" + shipping_categories: "Shipping Categories" + new_shipping_category: "New Shipping Category" + back_to_shipping_categories: "Back To Shipping Categories" + analytics_trackers: "Analytics Trackers" + no_trackers_found: "No Trackers Found" + new_tracker: "New Tracker" + add_one: "Add One" + google_analytics_id: "Analytics ID" + back_to_trackers_list: "Back to Trackers List" + name: "Name" + description: "Description" + type: "Type" + default: "default" + calculator: "Calculator" + zone: "Zone" + display: "Display" + environment: "Environment" + active: "Active" + nore: "More" + no_results: "No results" + create: "Create" + loading: "Loading" + flat_percent: "Flat Percent" + per_kg: "Per Kg" + amount: "Amount" + currency: "Currency" + first_item: "First Item Cost" + additional_item: "Additional Item Cost" + max_items: "Max Items" + minimal_amount: "Minimal Amount" + normal_amount: "Normal Amount" + discount_amount: "Discount Amount" + no_images_found: "No Images Found" + new_image: "New Image" + filename: "Filename" + alt_text: "Alternative Text" + thumbnail: "Thumbnail" + back_to_images_list: "Back To Images List" + email: Email + account_updated: "Account updated!" + email_updated: "The account will be updated once the new email is confirmed." + my_account: "My account" + date: "Date" + time: "Time" + inventory_error_flash_for_insufficient_quantity: "An item in your cart has become unavailable." + inventory: Inventory + zipcode: Postcode + weight: Weight (per kg) + error_user_destroy_with_orders: "Users with completed orders may not be deleted" + cannot_create_payment_without_payment_methods: "You cannot create a payment for an order without any payment methods defined." + please_define_payment_methods: "Please define some payment methods first." + options: "Options" + actions: + update: "Update" + errors: + messages: + blank: "can't be blank" + layouts: + admin: + header: + store: Store + admin: + tab: + dashboard: "Dashboard" + orders: "Orders" + bulk_order_management: "Bulk Order Management" + subscriptions: "Subscriptions" + products: "Products" + option_types: "Option Types" + properties: "Properties" + variant_overrides: "Inventory" + reports: "Reports" + configuration: "Configuration" + users: "Users" + roles: "Roles" + order_cycles: "Order Cycles" + enterprises: "Enterprises" + enterprise_relationships: "Permissions" + customers: "Customers" + groups: "Groups" + product_properties: + index: + inherits_properties_checkbox_hint: "Inherit properties from %{supplier}? (unless overridden above)" + add_product_properties: "Add Product Properties" + select_from_prototype: "Select From Prototype" + properties: + index: + properties: "Properties" + new_property: "New Property" + name: "Name" + presentation: "Presentation" + new: + new_property: "New Property" + edit: + editing_property: "Editing Property" + back_to_properties_list: "Back To Properties List" + form: + name: "Name" + presentation: "Presentation" + return_authorizations: + index: + new_return_authorization: "New Return Authorization" + return_authorizations: "Return Authorizations" + back_to_orders_list: "Back To Orders List" + rma_number: "RMA Number" + status: "Status" + amount: "Amount" + cannot_create_returns: "Cannot create returns as this order has no shipped units." + continue: "Continue" + new: + new_return_authorization: "New Return Authorization" + back_to_return_authorizations_list: "Back To Return Authorization List" + continue: "Continue" + edit: + receive: "receive" + are_you_sure: "Are you sure?" + return_authorization: "Return Authorization" + form: + product: "Product" + quantity_shipped: "Quantity Shipped" + quantity_returned: "Quantity Returned" + return_quantity: "Return Quantity" + amount: "Amount" + rma_value: "RMA Value" + reason: "Reason" + stock_location: "Stock Location" + states: + authorized: "Authorized" + received: "Received" + canceled: "Canceled" + orders: + index: + listing_orders: "Listing Orders" + new_order: "New Order" + capture: "Capture" + ship: "Ship" + edit: "Edit" + order_not_updated: "The order could not be updated" + note: "Note" + first: "First" + last: "Last" + previous: "Previous" + next: "Next" + loading: "Loading" + no_orders_found: "No Orders Found" + results_found: "%{number} Results found." + viewing: "Viewing %{start} to %{end}." + print_invoices: "Print Invoices" + sortable_header: + payment_state: "Payment State" + shipment_state: "Shipment State" + completed_at: "Completed At" + number: "Number" + state: "State" + email: "Customer E-Mail" + invoice: + issued_on: "Issued on" + tax_invoice: "TAX INVOICE" + code: "Code" + from: "From" + to: "Bill to" + shipping: "Shipping" + form: + distribution_fields: + title: "Distribution" + distributor: "Distributor:" + order_cycle: "Order cycle:" + line_item_adjustments: "Line Item Adjustments" + order_adjustments: "Order Adjustments" + order_total: "Order Total" + overview: + enterprises_header: + ofn_with_tip: Enterprises are Producers and/or Hubs and are the basic unit of organisation within the Open Food Network. + products: + active_products: + zero: "You don't have any active products." + one: "You have one active product" + other: "You have %{count} active products" + order_cycles: + order_cycles: "Order Cycles" + order_cycles_tip: "Order cycles determine when and where your products are available to customers." + you_have_active: + zero: "You don't have any active order cycles." + one: "You have one active order cycle." + other: "You have %{count} active order cycles." + manage_order_cycles: "MANAGE ORDER CYCLES" + shipping_methods: + index: + shipping_methods: "Shipping Methods" + new_shipping_method: "New Shipping Method" + name: "Name" + products_distributor: "Distributor" + zone: "Zone" + calculator: "Calculator" + display: "Display" + both: "Both" + front_end: "Front End" + back_end: "Back End" + no_shipping_methods_found: "No shipping methods found" + new: + new_shipping_method: "New Shipping Method" + back_to_shipping_methods_list: "Back To Shipping Methods List" + edit: + editing_shipping_method: "Editing Shipping Method" + new: "New" + back_to_shipping_methods_list: "Back To Shipping Methods List" + form: + categories: "Categories" + zones: "Zones" + both: "Both" + front_end: "Front End" + back_end: "Back End" + payment_methods: + new: + new_payment_method: "New Payment Method" + back_to_payment_methods_list: "Back To Payment Methods List" + edit: + editing_payment_method: "Editing Payment Method" + back_to_payment_methods_list: "Back To Payment Methods List" + stripe_connect: + enterprise_select_placeholder: Choose... + loading_account_information_msg: Loading account information from stripe, please wait... + stripe_disabled_msg: Stripe payments have been disabled by the system administrator. + request_failed_msg: Sorry. Something went wrong when trying to verify account details with Stripe... + account_missing_msg: No Stripe account exists for this enterprise. + connect_one: Connect One + access_revoked_msg: Access to this Stripe account has been revoked, please reconnect your account. + status: Status + connected: Connected + account_id: Account ID + business_name: Business Name + charges_enabled: Charges Enabled + payments: + source_forms: + stripe: + error_saving_payment: Error saving payment + submitting_payment: Submitting payment... + products: + image_upload_error: "The product image was not recognised. Please upload an image in PNG or JPG format." + new: + title: "New Product" + new_product: "New Product" + supplier: "Supplier" + product_name: "Product Name" + units: "Unit Size" + value: "Value" + unit_name: "Unit name" + price: "Price" + on_hand: "On Hand" + on_demand: "On Demand" + product_description: "Product Description" + image: "Image" + or: "or" + unit_name_placeholder: 'eg. bunches' + index: + header: + title: Bulk Edit Products + indicators: + title: LOADING PRODUCTS + no_products: "No products yet. Why don't you add some?" + no_results: "Sorry, no results match" + products_head: + name: Name + unit: Unit + display_as: Display As + category: Category + tax_category: Tax Category + inherits_properties?: Inherits Properties? + available_on: Available On + av_on: "Av. On" + import_date: "Import Date" + products_variant: + variant_has_n_overrides: "This variant has %{n} override(s)" + new_variant: "New variant" + product_name: Product Name + primary_taxon_form: + product_category: Product Category + group_buy_form: + group_buy: "Group Buy?" + bulk_unit_size: Bulk unit size + display_as: + display_as: Display As + reports: + table: + select_and_search: "Select filters and click on %{option} to access your data." + bulk_coop: + bulk_coop_supplier_report: 'Bulk Co-op - Totals by Supplier' + bulk_coop_allocation: 'Bulk Co-op - Allocation' + bulk_coop_packing_sheets: 'Bulk Co-op - Packing Sheets' + bulk_coop_customer_payments: 'Bulk Co-op - Customer Payments' + enterprise_fee_summaries: + filters: + date_range: "Date Range" + report_format_csv: "Download as CSV" + generate_report: "Generate Report" + report: + none: "None" + select_and_search: "Select filters and click on GENERATE REPORT to access your data." + users: + index: + listing_users: "Listing Users" + new_user: "New User" + user: "User" + enterprise_limit: "Enterprise Limit" + search: "Search" + email: "Email" + edit: + editing_user: "Editing User" + back_to_users_list: "Back To Users List" + general_settings: "General Settings" + form: + email: "Email" + roles: "Roles" + enterprise_limit: "Enterprise Limit" + confirm_password: "Confirm Password" + password: "Password" + email_confirmation: + confirmation_pending: "Email confirmation is pending. We've sent a confirmation email to %{address}." + variants: + index: + sku: "SKU" + price: "Price" + options: "Options" + no_results: "No results" + to_add_variants_you_must_first_define: "To add variants, you must first define" + option_types: "Option Types" + option_values: "Option Values" + and: "and" + new_variant: "New Variant" + show_active: "Show Active" + show_deleted: "Show Deleted" + new: + new_variant: "New Variant" + form: + cost_price: "Cost Price" + sku: "SKU" + price: "Price" + display_as: "Display As" + display_name: "Display Name" + autocomplete: + producer_name: "Producer" + unit: "Unit" + general_settings: + edit: + legal_settings: "Legal Settings" + cookies_consent_banner_toggle: "Display cookies consent banner" + privacy_policy_url: "Privacy Policy URL" + enterprises_require_tos: "Enterprises must accept Terms of Service" + cookies_policy_matomo_section: "Display Matomo section on cookies policy page" + cookies_policy_ga_section: "Display Google Analytics section on cookies policy page" + footer_tos_url: "Terms of Service URL" + checkout: + payment: + stripe: + choose_one: Choose one + enter_new_card: Enter details for a new card + used_saved_card: "Use a saved card:" + or_enter_new_card: "Or, enter details for a new card:" + remember_this_card: Remember this card? + stripe_sca: + choose_one: Choose one + enter_new_card: Enter details for a new card + used_saved_card: "Use a saved card:" + or_enter_new_card: "Or, enter details for a new card:" + remember_this_card: Remember this card? + date_picker: + format: '%Y-%m-%d' + js_format: 'yy-mm-dd' + orders: + error_flash_for_unavailable_items: "An item in your cart has become unavailable." + edit: + login_to_view_order: "Please log in to view your order." + bought: + item: "Already ordered in this order cycle" + line_item: + insufficient_stock: "Insufficient stock available, only %{on_hand} remaining" + out_of_stock: "Out of Stock" + unavailable_item: "Currently unavailable" + shipment_states: + backorder: backorder + partial: partial + pending: pending + ready: ready + shipped: shipped + payment_states: + balance_due: balance due + completed: completed + checkout: checkout + credit_owed: credit owed + failed: failed + paid: paid + pending: pending + processing: processing + void: void + invalid: invalid + order_mailer: + cancel_email: + customer_greeting: "Hi %{name}!" + instructions: "Your order has been CANCELED. Please retain this cancellation information for your records." + order_summary_canceled: "Order Summary [CANCELED]" + subject: "Cancellation of Order" + confirm_email: + subject: "Order Confirmation" + invoice_email: + hi: "Hi %{name}" + invoice_attached_text: Please find attached an invoice for your recent order from + order_state: + address: address + adjustments: adjustments + awaiting_return: awaiting return + canceled: cancelled + cart: cart + complete: complete + confirm: confirm + delivery: delivery + paused: paused + payment: payment + pending: pending + resumed: resumed + returned: returned + skrill: skrill + subscription_state: + active: active + pending: pending + ended: ended + paused: paused + canceled: cancelled + user_mailer: + reset_password_instructions: + request_sent_text: | + A request to reset your password has been made. + If you did not make this request, simply ignore this email. + link_text: > + If you did make this request just click the link below: + issue_text: | + If the above URL does not work try copying and pasting it into your browser. + If you continue to have problems please feel free to contact us. + confirmation_instructions: + subject: Please confirm your OFN account + users: + form: + account_settings: Account Settings + show: + tabs: + orders: Orders + cards: Credit Cards + transactions: Transactions + settings: Account Settings + unconfirmed_email: "Pending email confirmation for: %{unconfirmed_email}. Your email address will be updated once the new email is confirmed." + orders: + open_orders: Open Orders + past_orders: Past Orders + transactions: + transaction_history: Transaction History + open_orders: + order: Order + shop: Shop + changes_allowed_until: Changes Allowed Until + items: Items + total: Total + edit: Edit + cancel: Cancel + closed: Closed + until: Until + past_orders: + order: Order + shop: Shop + completed_at: Completed At + items: Items + total: Total + paid?: Paid? + view: View + saved_cards: + default?: Default? + delete?: Delete? + cards: + authorised_shops: Authorised Shops + authorised_shops_popover: This is the list of shops which are permitted to charge your default credit card for any subscriptions (ie. repeating orders) you may have. Your card details will be kept secure and will not be shared with shop owners. You will always be notified when you are charged. + saved_cards_popover: This is the list of cards you have opted to save for later use. Your 'default' will be selected automatically when you checkout an order, and can be charged by any shops you have allowed to do so (see right). + authorised_shops: + shop_name: "Shop Name" + allow_charges?: "Allow Charges?" + localized_number: + invalid_format: has an invalid format. Please enter a number. + api: + invalid_api_key: "Invalid API key (%{key}) specified." + unauthorized: "You are not authorized to perform that action." + invalid_resource: "Invalid resource. Please fix errors and try again." + resource_not_found: "The resource you were looking for could not be found." + access: "API Access" + key: "Key" + clear_key: "Clear key" + regenerate_key: "Regenerate Key" + no_key: "No key" + generate_key: "Generate API key" + key_generated: "Key generated" + key_cleared: "Key cleared" + shipment: + cannot_ready: "Cannot ready shipment." + invalid_taxonomy_id: "Invalid category ID." diff --git a/config/locales/en_US.yml b/config/locales/en_US.yml index 1e04a29f90..507653ccb5 100644 --- a/config/locales/en_US.yml +++ b/config/locales/en_US.yml @@ -55,7 +55,7 @@ en_US: messages: inclusion: "is not included in the list" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Please add at least one product" @@ -2753,6 +2753,8 @@ en_US: location: "Location" count_on_hand: "Count On Hand" quantity: "Quantity" + on_demand: "On Demand" + on_hand: "On Hand" package_from: "package from" item_description: "Item Description" price: "Price" diff --git a/config/locales/en_ZA.yml b/config/locales/en_ZA.yml index 71e4279ab3..bcc0f2e080 100644 --- a/config/locales/en_ZA.yml +++ b/config/locales/en_ZA.yml @@ -53,7 +53,7 @@ en_ZA: payment_method_ids: "Payment Methods" errors: models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Please add at least one product" @@ -2645,6 +2645,8 @@ en_ZA: location: "Location" count_on_hand: "Count On Hand" quantity: "Quantity" + on_demand: "Unlimited" + on_hand: "In Stock" package_from: "package from" item_description: "Item Description" price: "Price" diff --git a/config/locales/es.yml b/config/locales/es.yml index ab12b1328f..d287fba960 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -31,6 +31,10 @@ es: taken: "Ya existe una cuenta con este email. Inicie sesión o restablezca tu contraseña." spree/order: no_card: No hay tarjetas de crédito autorizadas disponibles para cargar + spree/credit_card: + attributes: + base: + card_expired: "ha expirado" order_cycle: attributes: orders_close_at: @@ -52,8 +56,10 @@ es: shipping_method_ids: "Métodos de envío" payment_method_ids: "Métodos de Pago" errors: + messages: + inclusion: "no está incluido en la lista" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Por favor agrega al menos un producto" @@ -246,6 +252,8 @@ es: notes: Notas error: Error processing_payment: "Procesando el pago..." + no_pending_payments: "No tiene pagos pendientes" + invalid_payment_state: "Estado de pago no válido" filter_results: Filtrar resultados quantity: Cantidad pick_up: Recogida @@ -438,9 +446,12 @@ es: infinity: "infinito" to_order_tip: "Los artículos hechos según demanda no tienen un nivel de stock, como por ejemplo panes hechos según demanda." back_to_products_list: "Volver a la lista de productos" + editing_product: "Editando producto" tabs: + product_details: "Detalles del Producto" group_buy_options: "Opciones de compra grupales" images: "Imágenes" + variants: "variaciones" product_properties: "Propiedades del producto" product_import: title: Importación de productos @@ -699,6 +710,11 @@ es: enable_subscriptions_false: "Deshabilitado" enable_subscriptions_true: "Habilitado" shopfront_message: "Mensaje de la Tienda" + shopfront_message_placeholder: > + Mensaje de bienvenida opcional para compradores, explica como comprar + en el sitio. si el texto se agrega en este campo, va a ser mostrado + en la pestaña de inicio cuando los clientes ingresen por primera vez + a la tienda. shopfront_message_link_tooltip: "Insertar / editar enlace" shopfront_message_link_prompt: "Por favor introduzca una URL para insertar" shopfront_closed_message: "Mensaje de tienda cerrada" @@ -836,25 +852,38 @@ es: new: create: "Crear" cancel: "Cancelar" + back_to_list: "Regresar a la lista" edit: advanced_settings: "Configuración Avanzada" save: "Guardar" + save_and_next: "Salvar y continuar" next: "Siguiente" cancel: "Cancelar" + back_to_list: "Regresar a la lista" + save_and_back_to_list: "Salvar y volver a lista" choose_products_from: "Escoger Productos desde:" incoming: save: "Guardar" + save_and_next: "Salvar y continuar" next: "Siguiente" cancel: "Cancelar" + back_to_list: "Regresar a la lista" outgoing: outgoing: "Saliente" distributor: "Distribuidora" products: "Productos" tags: "Tags" + delivery_details: "Detalles de entrega" fees: "Comisiones" previous: "Anterior" save: "Guardar" + save_and_back_to_list: "Salvar y volver a lista" cancel: "Cancelar" + back_to_list: "Regresar a la lista" + wizard_progress: + edit: "1. Configuración general" + incoming: "2. Productos entrantes" + outgoing: "3. Productos salientes" exchange_form: pickup_time_tip: Cuando los pedidos de este ciclo de pedido estarán listos para la consumidora pickup_instructions_placeholder: "Instrucciones de recogida" @@ -1092,10 +1121,13 @@ es: destroy_attachment_does_not_exist: "El logotipo no existe" enterprise_promo_image: destroy_attachment_does_not_exist: "La imagen promocional no existe" + orders: + failed_to_update: "Error al actualizar pedido" checkout: already_ordered: cart: "carrito" message_html: "Ya realizó un pedido para este ciclo de pedido. Compruebe el %{cart}para ver los artículos que pidió. También puede cancelar artículos mientras el ciclo de pedido siga abierto." + failed: "La finalización de compra falló, por favor comunicate con nosotros para procesar la orden." shops: hubs: show_closed_shops: "Mostrar tiendas cerradas" @@ -1266,6 +1298,7 @@ es: saving_credit_card: Guardando tarjeta de crédito... card_has_been_removed: "Su tarjeta ha sido eliminada (número: %{number})" card_could_not_be_removed: Lo sentimos, la tarjeta no se pudo quitar + invalid_credit_card: "Tarjeta de crédito inválida" ie_warning_headline: "Su navegador está desactualizado :-(" ie_warning_text: "Para la mejor esperiencia de Open Food Network, recomendamos actualizar su navegador:" ie_warning_chrome: Descargar Chrome @@ -1467,6 +1500,7 @@ es: shopping_oc_closed_description: "Por favor espere hasta que el próximo ciclo abra (o contactanos de forma directa para ver si podemos aceptar algunos pedidos tardíos)" shopping_oc_last_closed: "El último ciclo cerró hace %{distance_of_time}" shopping_oc_next_open: "El próximo ciclo abrirá en %{distance_of_time}" + shopping_oc_select: "Seleccionar" shopping_tabs_home: "Inicio" shopping_tabs_shop: "Tienda" shopping_tabs_about: "Acerca de" @@ -1840,6 +1874,7 @@ es: headline: "¡Terminado!" thanks: "Gracias por llenar los detalles de %{enterprise}." login: "Puede cambiar o actualizar su negocio en cualquier etapa iniciando sesión en Open Food Network y yendo a Admin." + action: "Ir al Panel de Organización" back: "Atrás" continue: "Continuar" action_or: "Ó" @@ -1925,6 +1960,7 @@ es: tax_category: "Categoría del impuesto" calculator: "Calculadora" calculator_values: "Calculadora de valores" + calculator_settings_warning: "Si está cambiando el tipo de calculadora, debe de salvar primero antes de editar las configuraciones de la calculadora" flat_percent_per_item: "Porcentaje fijo (por artículo)" flat_rate_per_item: "Tarifa plana (por artículo)" flat_rate_per_order: "Tarifa plana (por pedido)" @@ -2255,6 +2291,7 @@ es: enterprise_register_success_notice: "¡Felicidades! ¡Se ha completado el registro de %{enterprise}!" enterprise_bulk_update_success_notice: "Organizaciones actualizadas con éxito" enterprise_bulk_update_error: 'Error en la actualización' + enterprise_shop_show_error: "La tienda que busca no existe o esta inactiva en OFN. por favor visita otras tiendas." order_cycles_create_notice: 'Se ha creado el ciclo de pedido.' order_cycles_update_notice: 'Se ha actualizado su ciclo de pedido.' order_cycles_bulk_update_notice: 'Los ciclos de pedido han sido actualizados.' @@ -2410,6 +2447,12 @@ es: severity: Gravedad description: Descripción resolve: Resolver + exchange_products: + load_more_variants: "Cargar mas variantes" + load_all_variants: "cargar todas las variantes" + select_all_variants: "Seleccionar todo" + variants_loaded: "%{num_of_variants_loaded} de %{total_number_of_variants} variantes cargadas" + loading_variants: "Cargando variantes" tag_rules: shipping_method_tagged_top: "Métodos de envío etiquetados" shipping_method_tagged_bottom: "son:" @@ -2492,6 +2535,7 @@ es: customer_placeholder: "customer@example.org" valid_email_error: "Introduce un email válido" subscriptions: + error_saving: "Error al salvar suscripción " new: please_select_a_shop: "Por favor seleccione una tienda" insufficient_stock: "Stock insuficiente disponible, solo quedan %{on_hand}" @@ -2567,6 +2611,79 @@ es: signup_or_login: "Empieza registrándose (o iniciando sesión)" have_an_account: "¿Ya tiene una cuenta?" action_login: "Inicie sesión ahora." + inflections: + each: + one: "each" + other: "cada" + bunch: + one: "manojo" + other: "manojos" + pack: + one: "paquete" + other: "paquetes" + box: + one: "caja" + other: "cajas" + bottle: + one: "botella" + other: "botellas" + jar: + one: "frasco" + other: "frascos" + head: + one: "cabeza" + other: "cabezas" + bag: + one: "bolsa" + other: "bolsas" + loaf: + one: "hogaza" + other: "hogazas" + single: + one: "single" + other: "individuales" + tub: + one: "tub" + other: "recipientes" + punnet: + one: "canastilla" + other: "canastillas" + packet: + one: "paquete" + other: "paquetes" + item: + one: "elemento" + other: "elementos" + dozen: + one: "docena" + other: "docenas" + unit: + one: "unidad" + other: "unidades" + serve: + one: "serve" + other: "porción" + tray: + one: "bandeja" + other: "bandejas" + piece: + one: "pieza" + other: "piezas" + pot: + one: "maceta" + other: "contenedores" + bundle: + one: "haz" + other: "paquetes" + flask: + one: "flask" + other: "frascos" + basket: + one: "canasta" + other: "canastas" + sack: + one: "sacos" + other: "sacos" producers: signup: start_free_profile: "Empieze con un perfil gratuito, y amplíelo cuando esté preparado!" @@ -2649,6 +2766,8 @@ es: location: "Ubicación" count_on_hand: "Cuenta de disponibilidad" quantity: "Cantidad" + on_demand: "Bajo demanda" + on_hand: "Disponibles" package_from: "perfil de" item_description: "Descripción del artículo" price: "Precio" @@ -2792,6 +2911,12 @@ es: minimal_amount: "Cantidad mínima" normal_amount: "Cantidad normal" discount_amount: "Importe de descuento" + no_images_found: "No se encontraron imágenes " + new_image: "Nueva Imagen" + filename: "Nombre de archivo" + alt_text: "Texto Alternativo" + thumbnail: "Miniatura" + back_to_images_list: "Volver a lista de imágenes " email: Email account_updated: "Cuenta actualizada!" email_updated: "La cuenta se actualizará una vez que se confirme el nuevo correo electrónico." @@ -2803,6 +2928,9 @@ es: zipcode: Código Postal weight: Peso (en kg) error_user_destroy_with_orders: "Los usuarios con pedidos completados no pueden ser eliminados" + cannot_create_payment_without_payment_methods: "No se puede crear un pago para una orden sin un medio de pago definido" + please_define_payment_methods: "por favor definir métodos de pago" + options: "Opciones" actions: update: "Actualizar" errors: @@ -2834,27 +2962,53 @@ es: product_properties: index: inherits_properties_checkbox_hint: "¿Heredar propiedades desde %{supplier}? (a menos que sea anulado arriba)" + add_product_properties: "Agregar Propiedades del producto" + select_from_prototype: "seleccionar de prototipo" properties: index: properties: "Propiedades" + new_property: "Nueva propiedad" name: "Nombre" + presentation: "presentación" + new: + new_property: "Nueva propiedad" + edit: + editing_property: "Editar Propiedad" + back_to_properties_list: "volver a lista de propiedades" form: name: "Nombre" + presentation: "presentación" return_authorizations: index: + new_return_authorization: "Nueva autorización de devolución" return_authorizations: "Autorizaciones de devolución" back_to_orders_list: "Volver a la lista de pedidos" + rma_number: "número RMA" status: "Estado" amount: "Cantidad" cannot_create_returns: "No se pueden crear devoluciones ya que este pedido no tiene unidades enviadas." continue: "Continuar" new: + new_return_authorization: "Nueva autorización de devolución" + back_to_return_authorizations_list: "Back To Return Authorization List" continue: "Continuar" edit: + receive: "recibir" are_you_sure: "¿Está seguro?" + return_authorization: "volver a autorización" form: product: "Producto" + quantity_shipped: "cantidad enviada" + quantity_returned: "Cantidad devuelta" + return_quantity: "cantidad a devolver" amount: "Cantidad" + rma_value: "Valor RMA" + reason: "razón" + stock_location: "localización de inventario" + states: + authorized: "autorizado" + received: "recibido" + canceled: "cancelado" orders: index: listing_orders: "Pedidos de listado" @@ -2862,6 +3016,7 @@ es: capture: "Captura" ship: "Envío" edit: "Editar" + order_not_updated: "El pedido no se pudo actualizar" note: "Nota" first: "primero" last: "Último" @@ -2884,6 +3039,8 @@ es: tax_invoice: "FACTURA DE IMPUESTOS" code: "Código" from: "De" + to: "Facturar a" + shipping: "envío" form: distribution_fields: title: "Distribución" @@ -3044,12 +3201,23 @@ es: index: sku: "SKU" price: "Precio" + options: "Opciones" no_results: "No hay resultados" + to_add_variants_you_must_first_define: "para agregar variantes, se debe primero definir" option_types: "Tipos de opciones" + option_values: "valores de opción" + and: "y" + new_variant: "Nueva Variante" + show_active: "mostrar activo" + show_deleted: "Mostrar eliminados" + new: + new_variant: "Nueva Variante" form: + cost_price: "Precio de costo" sku: "SKU" price: "Precio" display_as: "Mostrar como" + display_name: "Nombre para mostrar" autocomplete: producer_name: "Productora" unit: "Unidad" @@ -3195,3 +3363,19 @@ es: allow_charges?: "¿Permitir cargos?" localized_number: invalid_format: tiene un formato invalido. Por favor introduzca un numero. + api: + invalid_api_key: "La llave de API especificada (%{key}) es inválida." + unauthorized: "No tiene autorización para realizar esta acción." + invalid_resource: "Recurso inválido. Por favor corrija los errores e intente nuevamente." + resource_not_found: "El recurso que buscaba no puede ser encontrado." + access: "acceso al API" + key: "Llave" + clear_key: "valor vacío" + regenerate_key: "Regenerar llave" + no_key: "sin valor" + generate_key: "Generar llave de API" + key_generated: "Llave generada" + key_cleared: "valor borrado" + shipment: + cannot_ready: "No se puede completar envío" + invalid_taxonomy_id: "El identificador de taxonomía es inválido." diff --git a/config/locales/es_CR.yml b/config/locales/es_CR.yml new file mode 100644 index 0000000000..151ed7be42 --- /dev/null +++ b/config/locales/es_CR.yml @@ -0,0 +1,3382 @@ +es_CR: + language_name: "Español" + activerecord: + attributes: + enterprise_fee: + fee_type: Tipo de Comisión + spree/order: + payment_state: Estado del pago + shipment_state: Estado del envío + completed_at: Completado en + number: Número + state: Provincia + email: Correo electrónico del cliente + spree/payment: + amount: Cantidad + spree/product: + primary_taxon: "Categoría del producto" + supplier: "Proveedor" + shipping_category_id: "Categoría de envío" + variant_unit: "Unidad Variante" + variant_unit_name: "Nombre de la unidad de la variante" + spree/credit_card: + base: "Tarjeta de crédito" + order_cycle: + orders_close_at: Fecha de cierre + errors: + models: + spree/user: + attributes: + email: + taken: "Ya existe una cuenta con este correo electrónico. Inicie sesión o restablezca tu contraseña." + spree/order: + no_card: No hay tarjetas de crédito autorizadas disponibles para realizar el cobro + spree/credit_card: + attributes: + base: + card_expired: "ha expirado" + order_cycle: + attributes: + orders_close_at: + after_orders_open_at: debe ser después de la fecha de apertura + variant_override: + count_on_hand: + using_producer_stock_settings_but_count_on_hand_set: "debe estar en blanco porque está usando la configuración de inventario del productor" + on_demand_but_count_on_hand_set: "debe estar en blanco si es bajo demanda" + limited_stock_but_no_count_on_hand: "debe estar especificado porque se ha definido un inventario limitado" + activemodel: + attributes: + order_management/reports/enterprise_fee_summary/parameters: + start_at: "Inicio" + end_at: "Final" + distributor_ids: "Centros de acopio" + producer_ids: "Productoras" + order_cycle_ids: "Ciclos de Pedido" + enterprise_fee_ids: "Nombres de las comisiones" + shipping_method_ids: "Métodos de envío" + payment_method_ids: "Métodos de pago" + errors: + messages: + inclusion: "no está incluido en la lista" + models: + order_management/subscriptions/validator: + attributes: + subscription_line_items: + at_least_one_product: "^Por favor, agregue al menos un producto" + not_available: "^%{name} no está disponible en el horario seleccionado" + ends_at: + after_begins_at: "debe ser después del inicio en" + customer: + does_not_belong_to_shop: "no pertenece a %{shop}" + schedule: + not_coordinated_by_shop: "no es coordinado por %{shop}" + payment_method: + not_available_to_shop: "no está disponible para %{shop}" + invalid_type: "El método debe ser en efectivo o Stripe" + charges_not_allowed: "^Los cargos de la tarjeta de crédito no están permitidos para este cliente" + no_default_card: "^No hay una tarjeta predeterminada disponible para este cliente" + shipping_method: + not_available_to_shop: "no está disponible para %{shop}" + devise: + confirmations: + send_instructions: "En unos minutos recibirá un correo electrónico con instrucciones sobre cómo confirmar su cuenta." + failed_to_send: "Se produjo un error al enviar su correo electrónico de confirmación." + resend_confirmation_email: "Reenviar el correo electrónico de confirmación." + confirmed: "¡Gracias por confirmar su correo electrónico! Ahora puede iniciar sesión." + not_confirmed: "Su dirección de correo electrónico no pudo ser confirmada. -¿Tal vez ya realizó este paso?" + user_confirmations: + spree_user: + send_instructions: "Recibirá un correo electrónico con instrucciones sobre cómo confirmar su cuenta dentro de unos minutos." + confirmation_sent: "Se ha enviado un correo electrónico de confirmación" + confirmation_not_sent: "Error al enviar el correo electrónico de confirmación." + user_registrations: + spree_user: + signed_up_but_unconfirmed: "Se ha enviado un mensaje con un enlace de confirmación a su dirección de correo electrónico. Abra el enlace para activar su cuenta." + unknown_error: "Algo salió mal al crear su cuenta. Compruebe su dirección de correo electrónico y vuelva a intentarlo." + failure: + invalid: | + Correo o contraseña inválidos. + ¿Ha sido invitada? Tal vez necesite crear una cuenta nueva o recuperar su contraseña. + unconfirmed: "Debe confirmar su cuenta antes de continuar." + already_registered: "Esta dirección de correo electrónico ya está registrada. Inicie sesión para continuar, o vuelva atrás y use otra dirección de correo electrónico." + success: + logged_in_succesfully: "Sesión iniciada con éxito" + user_passwords: + spree_user: + updated_not_active: "Su contraseña ha sido restablecida, pero su correo electrónico aún no ha sido confirmado." + updated: "Su contraseña ha sido cambiada con éxito. Ya tienes la sesión iniciada." + send_instructions: "Recibirá un correo electrónico con instrucciones sobre cómo confirmar su cuenta en unos minutos." + models: + order_cycle: + cloned_order_cycle_name: "COPIA DE %{order_cycle}" + validators: + date_time_string_validator: + not_string_error: "debe ser una cadena" + invalid_format_error: "debe ser válido" + integer_array_validator: + not_array_error: "debe ser una lista" + invalid_element_error: "debe contener solo enteros válidos" + enterprise_mailer: + confirmation_instructions: + subject: "Por favor, confirma la dirección de correo electrónico de %{enterprise}" + welcome: + subject: "%{enterprise} está ahora en %{sitename}" + email_welcome: "Bienvenido" + email_registered: "ahora es parte de" + email_userguide_html: "La Guía de Usuario con soporte detallado para configurar su Productora o Grupo de Consumo está aquí: %{link}" + userguide: "Guía de usuario de Open Food Network (LaFeriaCR)" + email_admin_html: "Puede administrar su cuenta iniciando sesión en %{link} o haciendo clic en el engranaje arriba a la derecha de la página de inicio, y seleccionando Administración." + admin_panel: "Panel de administración" + email_community_html: "También tenemos un foro en línea para la discusión comunitaria relacionada con el software OFN y los retos únicos del funcionamiento de una organización de alimentación. Lo invitamos a unirse. Estamos evolucionando constantemente y su aporte en este foro le dará forma a lo que pase luego. %{link}" + join_community: "Unirse a la comunidad" + invite_manager: + subject: "%{enterprise} te ha invitado a ser administrador" + producer_mailer: + order_cycle: + subject: "Reporte de Ciclo de Pedido para %{producer}" + shipment_mailer: + shipped_email: + dear_customer: "Estimado cliente," + instructions: "Su pedido ha sido enviado" + shipment_summary: "Resumen de envío" + subject: "Notificación de envío" + thanks: "Gracias por su negocio." + track_information: "Información de seguimiento: %{tracking}" + track_link: "Enlace de seguimiento: %{url}" + subscription_mailer: + placement_summary_email: + subject: Un resumen los pedidos de suscripción recientes + greeting: "Hola %{name}," + intro: "A continuación se muestra un resumen de los pedidos de suscripción que acaban de realizarse en %{shop}." + confirmation_summary_email: + subject: Un resumen de los pedidos de suscripción confirmados recientemente + greeting: "Hola %{name}," + intro: "A continuación se muestra un resumen de los pedidos de suscripción que acaban de finalizar para %{shop}." + summary_overview: + total: Se marcaron un total de %{count} suscripciones para ser procesadas automáticamente. + success_zero: De estos, ninguno fue procesado. + success_some: De estos, %{count} se procesaron con éxito. + success_all: Todos fueron procesados ​​con éxito. + issues: Los detalles de los problemas encontrados se mostrarán a continuación. + summary_detail: + no_message_provided: No hay mensajes de error + changes: + title: Inventario insuficiente (%{count} pedidos) + explainer: Estos pedidos se procesaron pero no había suficiente inventario disponible para algunos artículos solicitados. + empty: + title: Sin inventario (%{count} pedidos) + explainer: Estas órdenes no se pudieron procesar porque no había inventario disponibles para los artículos solicitados + complete: + title: Ya procesado (%{count} pedidos) + explainer: Estas órdenes ya estaban marcadas como completas y, por lo tanto, no se modificaron + processing: + title: Error encontrado (%{count} pedidos) + explainer: El procesamiento automático de estas órdenes falló debido a un error. El error será mostrado en los casos en que sea posible. + failed_payment: + title: Error en el pago (%{count} pedidos) + explainer: El procesamiento automático del pago de estos pedidos falló debido a un error. El error ha sido listado donde ha sido posible. + other: + title: Otros fallos (%{count} pedidos) + explainer: El procesamiento automático de estas órdenes falló por un motivo desconocido. Esto no debería ocurrir, contáctanos si estás viendo esto. + home: "OFN" + title: Open Food Network + welcome_to: 'Bienvenido a ' + site_meta_description: "Nosotros empezamos desde abajo. Con granjeros y productores listos para contar sus historias con orgullo y autenticidad. Con distribuidores listos para conectar gente con productos de forma justa y honesta. Con compradores que creen que mejores decisiones de compras semanales pueden..." + search_by_name: Buscar por nombre o cantón... + producers_join: Los productores costarricenses son bienvenidos a unirse ahora a Open Food Network (LaFeriaCR). + charges_sales_tax: ¿Cargos de IVA? + print_invoice: "Imprimir factura" + print_ticket: "Imprimir Ticket" + select_ticket_printer: "Seleccionar impresora para los tickets" + send_invoice: "Enviar factura" + resend_confirmation: "Reenviar confirmación" + view_order: "Ver pedido" + edit_order: "Editar pedido" + ship_order: "Enviar pedido" + cancel_order: "Cancelar pedido" + confirm_send_invoice: "Al cliente se enviará una factura por este pedido. ¿Desea continuar?" + confirm_resend_order_confirmation: "¿Estás seguro que quieres reenviar el correo de confirmación del pedido?" + must_have_valid_business_number: "%{enterprise_name} debe tener un NIF válido antes de que las facturas se puedan enviar." + invoice: "Factura" + more: "Más" + say_no: "No" + say_yes: "Si" + ongoing: En marcha + bill_address: Dirección de facturación + ship_address: Dirección de envío + sort_order_cycles_on_shopfront_by: "Ordenar Ciclos de Pedidos en Tienda por" + required_fields: Los campos obligatorios se indican con un asterisco + select_continue: Seleccione y Continue + remove: Eliminar + or: o + collapse_all: Contraer todos + expand_all: Expandir todos + loading: Cargando... + show_more: Mostrar más + show_all: Mostrar todos + show_all_with_more: "Mostrar todo (%{num} Más)" + cancel: Cancelar + edit: Editar + clone: Duplicar + distributors: Distribuidores + bulk_order_management: Gestión de pedidos en volumen + enterprises: Organizaciones + enterprise_groups: Grupos + reports: Reportes + variant_overrides: Inventario + import: Importar + spree_products: Productos de temporada + all: Todos + current: Actual + available: Disponible + dashboard: Panel de inicio + undefined: indefinido + unused: no utilizado + admin_and_handling: Administración y Manejo + profile: Perfil + supplier_only: Sólo proveedor + has_shopfront: Tiene puesto de tienda + weight: Peso + volume: Volumen + items: Elementos + summary: Resumen + detailed: Detallado + updated: Actualizado + 'yes': "Sí" + 'no': "No" + y: 'S' + n: 'N' + powered_by: Impulsado por + blocked_cookies_alert: "Es posible que su navegador esté bloqueando las cookies necesarias para utilizar esta tienda. Haga clic a continuación para permitir las cookies y vuelva a cargar la página." + allow_cookies: "Permitir cookies" + notes: Notas + error: Error + processing_payment: "Procesando el pago..." + no_pending_payments: "No tiene pagos pendientes" + invalid_payment_state: "Estado de pago no válido" + filter_results: Filtrar resultados + quantity: Cantidad + pick_up: Recoger + copy: Copia + change_my_password: "Cambiar mi contraseña" + update_password: "Actualizar contraseña" + password_confirmation: Confirmación de contraseña + reset_password_token: token de restablecimiento de contraseña + expired: ha expirado, por favor solicite una nueva + back_to_payments_list: "Volver a la lista de pagos" + maestro_or_solo_cards: "Solo tarjetas MasterCard" + backordered: "Pedido pendiente" + on hand: "Disponibles" + ship: "Envío" + actions: + create_and_add_another: "Crear y agregar otro" + create: "Crear" + cancel: "Cancelar" + save: "Guardar" + edit: "Editar" + update: "Actualizar" + delete: "Borrar" + admin: + begins_at: Empieza en + begins_on: Comienza en + customer: Cliente + date: Fecha + email: Email + ends_at: Termina en + ends_on: Finaliza en + name: Nombre + on_hand: Disponibles + on_demand: Bajo demanda + on_demand?: Bajo demanda? + order_cycle: Ciclo de Pedido + payment: Pago + payment_method: Método de pago + phone: Teléfono + price: Precio + producer: Productor + image: Imagen + product: Producto + quantity: Cantidad + schedule: Programación + shipping: Envío + shipping_method: Método de envío + shop: Tienda + sku: número de referencia + status_state: Provincia + tags: Etiquetas + variant: Variedad + weight: Peso + volume: Volumen + items: Artículos + select_all: Seleccionar todo + quick_search: Búsqueda rápida + clear_all: Limpiar todo + start_date: "Fecha de inicio" + end_date: "Fecha de finalización" + form_invalid: "El formulario contiene campos vacíos o inválidos" + clear_filters: Limpiar filtros + clear: Limpiar + save: Guardar + cancel: Cancelar + back: Atrás + show_more: Mostrar más + show_n_more: Mostrar %{num} más + choose: "Escoger..." + please_select: Por favor selecciona ... + columns: Columnas + actions: Acciones + viewing: "Viendo: %{current_view_name}" + description: Descripción + whats_this: ¿Qué es esto? + tag_has_rules: "Reglas existentes para esta etiqueta: %{num}" + has_one_rule: "Tiene una regla" + has_n_rules: "Tiene %{num} reglas" + unsaved_confirm_leave: "Hay cambios sin guardar en esta página ¿Desea continuar?" + unsaved_changes: "Tiene cambios sin guardar" + shopfront_settings: + embedded_shopfront_settings: "Configuración de la tienda integrada" + enable_embedded_shopfronts: "Habilitar tiendas integradas" + embedded_shopfronts_whitelist: "Lista de dominios externos permitidos" + number_localization: + number_localization_settings: "Configuración de ubicación de número" + enable_localized_number: "Usar la logica internacional separador miles/decimales" + invoice_settings: + edit: + title: "Configuración de factura" + enable_invoices?: "Habilitar facturas?" + invoice_style2?: "Utiliza el modelo de factura alternativo que incluye el desglose fiscal total por tipo de interés y tasa de impuestos por artículo (todavía no es adecuado para países que muestran los precios sin impuestos)" + enable_receipt_printing?: "¿Mostrar opciones para imprimir recibos usando impresoras térmicas en el desplegable del pedido?" + stripe_connect_settings: + edit: + title: "Stripe Connect" + settings: "Configuración" + stripe_connect_enabled: ¿Permitir a las tiendas aceptar pagos mediante Stripe Connect? + no_api_key_msg: No existe una cuenta Stripe para esta organización. + configuration_explanation_html: Para obtener instrucciones detalladas sobre cómo configurar la integración con Stripe Connect, consulte esta guía . + status: Estado + ok: Ok + instance_secret_key: Clave secreta de instancia + account_id: ID de cuenta + business_name: Nombre de la organización + charges_enabled: Cargos habilitados + charges_enabled_warning: "Advertencia: los cargos no están habilitados para su cuenta" + auth_fail_error: La clave API que proporcionó no es válida. + empty_api_key_error_html: No se ha proporcionado ninguna clave API Stripe. Para configurar su clave API, siga estas instrucciones + matomo_settings: + edit: + title: "Configuración de Matomo" + matomo_url: "URL de Matomo" + matomo_site_id: "ID de sitio de Matomo" + info_html: "Matomo es un analizador web y móvil. Puede alojar Matomo en sus servidores o utilizar un servicio alojado en la nube. Consulte matomo.org para obtener más información." + config_instructions_html: "Aquí puede configurar la integración de OFN Matomo. La siguiente URL de Matomo debe apuntar a la instancia de Matomo a la que se enviará la información de seguimiento del usuario; si se deja vacío, el seguimiento del usuario Matomo se desactivará. El campo ID del sitio no es obligatorio, pero es útil si está rastreando más de un sitio web en una sola instancia de Matomo; se puede encontrar en la consola de la instancia de Matomo." + customers: + index: + new_customer: "Nuevo cliente" + code: Código + duplicate_code: "Este código ya ha sido utilizado." + bill_address: "Dirección de facturación" + ship_address: "Dirección de envío" + update_address_success: 'Dirección actualizada correctamente.' + update_address_error: 'Introduce todos los campos requeridos' + edit_bill_address: 'Editar la dirección de facturación' + edit_ship_address: 'Editar dirección de envío' + required_fileds: 'Los campos obligatorios se indican con un asterisco' + select_country: 'Selecciona país' + select_state: 'Selecciona provincia' + edit: 'Editar' + update_address: 'Actualizar dirección' + confirm_delete: '¿Confirmas que quieres borrar?' + search_by_email: "Buscar por correo electrónico/código" + guest_label: 'Hacer pedido como invitado' + destroy: + has_associated_orders: 'Error al eliminar: el cliente tiene pedidos asociados a su tienda.' + contents: + edit: + title: Contenido + header: Encabezado + home_page: Página principal + producer_signup_page: Página de registro del productor + hub_signup_page: Página para registro del Hub + group_signup_page: Página de registro de grupo + main_links: Enlaces al menú principal + footer_and_external_links: Pie de página y enlaces externos + your_content: Tu contenido + user_guide: Manual de usuario + enterprise_fees: + index: + title: "Comisiones de la organización" + enterprise: "Organización" + fee_type: "Tipo de Comisión" + name: "Nombre" + tax_category: "Categoría del impuesto" + calculator: "Calculadora" + calculator_values: "Valores de la calculadora" + search: "Buscar" + name_placeholder: "por ejemplo, comision de embalaje" + enterprise_groups: + index: + new_button: Nuevo grupo de organización + enterprise_roles: + form: + manages: Administra + enterprise_role: + manages: Administra + products: + unit_name_placeholder: 'ej. racimos' + index: + unit: Unidad + display_as: Mostrar como + category: Categoría + tax_category: Categoría de impuestos + inherits_properties?: ¿Hereda propiedades? + available_on: Disponible en + av_on: "Disp. en" + import_date: Importado + upload_an_image: Subir una imágen + seo: + product_search_keywords: "Palabras clave de búsqueda de productos" + product_search_tip: "Escriba palabras para ayudar a buscar sus productos en las tiendas. Use un espacio para separar cada palabra clave." + SEO_keywords: "Palabras clave de SEO" + seo_tip: "Escriba palabras para ayudar a buscar sus productos en la web. Use un espacio para separar cada palabra clave." + search: "Buscar" + properties: + property_name: "Nombre de la propiedad" + inherited_property: "Propiedad heredada" + variants: + infinity: "infinito" + to_order_tip: "Los artículos hechos según el pedido no tienen un nivel fijado de inventario, como por ejemplo panes hechos según demanda." + back_to_products_list: "Volver a la lista de productos" + editing_product: "Editando producto" + tabs: + product_details: "Detalles del producto" + group_buy_options: "Opciones de compra grupales" + images: "Imágenes" + variants: "Variante" + product_properties: "Propiedades del producto" + product_import: + title: Importe de producto + file_not_found: Archivo no encontrado o no se pudo abrir + no_data: No se encontraron datos en la hoja de cálculo + confirm_reset: "Esto establecerá el nivel de inventario a cero en todos los productos para esta\n organizacion que no están presentes en el archivo cargado" + model: + no_file: "Error: no se ha subido ningún archivo" + could_not_process: "No se pudo procesar el archivo: tipo de archivo inválido" + incorrect_value: valor incorrecto + conditional_blank: no puede estar en blanco si unit_type está en blanco + no_product: no coincide con ningún producto en la base de datos + not_found: no encontrado en la base de datos + not_updatable: No se puede actualizar sobre productos existentes a través de la importación de productos + blank: no puede estar en blanco + products_no_permission: no tienes permiso para administrar productos para esta organización + inventory_no_permission: no tienes permiso para crear inventario para este productor + none_saved: no se guardó ningún producto con éxito + line_number: "Línea %{number}:" + encoding_error: "Verifique la configuración de idioma de su archivo fuente y asegúrese de que esté guardado con la codificación UTF-8" + unexpected_error: "La importación de productos encontró un error inesperado al abrir el archivo: %{error_message}" + index: + notice: "Aviso" + beta_notice: "Esta funcionalidad aún está en versión beta: puede experimentar algunos errores mientras la usa. Por favor no dude en ponerse en contacto con nosotros." + select_file: Selecciona una hoja de cálculo para subir + spreadsheet: Hoja de cálculo + choose_import_type: Seleccionar tipo de importación + import_into: Tipo de importación + product_list: Lista de productos + inventories: Inventarios + import: Importar + upload: Subir + csv_templates: Plantillas CSV + product_list_template: Descargar la plantilla de lista de productos + inventory_template: Descargar plantilla de inventario + category_values: Valores de categoría disponibles + product_categories: Categorías de producto + tax_categories: Categorías de impuestos + shipping_categories: Categorías de envío + import: + review: Revisión + import: Importar + save: Guardar + results: Resultados + save_imported: Guardar productos importados + no_valid_entries: No se encontraron entradas válidas + none_to_save: No hay entradas que se puedan guardar + some_invalid_entries: El archivo importado contiene entradas no válidas + fix_before_import: Corrija estos errores e intente importar el archivo nuevamente + save_valid?: ¿Guardar entradas válidas por ahora y descartar las demás? + no_errors: ¡No se detectaron errores! + save_all_imported?: ¿Guardar todos los productos importados? + options_and_defaults: Opciones de importación y valores predeterminados + no_permission: no tienes permiso para administrar esta organización + not_found: no se pudo encontrar la organización en la base de datos + no_name: Sin nombre + blank_enterprise: algunos productos no tienen una organización definida. + reset_absent?: Restablecer productos ausentes + reset_absent_tip: Establezca el inventario en cero para todos los productos existentes que no estén presentes en el archivo. + overwrite_all: Sobrescribir todo + overwrite_empty: Sobrescribir si está vacío + default_stock: Establecer nivel de inventario + default_tax_cat: Establecer categoría de impuestos + default_shipping_cat: Establecer categoría de envío + default_available_date: Establecer fecha disponible + validation_overview: Resumen de validación de importación + entries_found: Entradas encontradas en el archivo importado + entries_with_errors: Los artículos contienen errores y no se importarán + products_to_create: Los productos se crearán + products_to_update: Los productos se actualizarán + inventory_to_create: Se crearán Artículos de inventario + inventory_to_update: Los artículos de inventario se actualizarán + products_to_reset: Los productos existentes tendrán su inventario restablecido a cero + inventory_to_reset: Los artículos de inventario existentes tendrán su stock restablecido a cero + line: Línea + item_line: Línea del artículo + import_review: + not_updatable_tip: "Los siguientes campos no se pueden actualizar mediante la importación masiva de productos existentes:" + fields_ignored: Estos campos se ignorarán cuando se guarden los productos importados. + entries_table: + not_updatable: Este campo no es actualizable mediante importación masiva en productos existentes + save_results: + final_results: Importar resultados finales + products_created: Productos creados + products_updated: Productos actualizados + inventory_created: Artículos de inventario creados + inventory_updated: Artículos de inventario actualizados + products_reset: Los productos tenían nivel de inventario restablecido a cero + inventory_reset: Los artículos de inventario tenían el nivel de este restablecido a cero + all_saved: "Todos los artículos guardados con éxito" + some_saved: "Artículos guardados con éxito" + save_errors: Guardar errores + import_again: Subir otro archivo + view_products: Ir a la página de productos + view_inventory: Ir a la página de inventario + variant_overrides: + loading_flash: + loading_inventory: CARGANDO INVENTARIO + index: + title: Inventario + description: Utilice esta página para administrar inventarios para sus organizaciones. Todos los detalles del producto establecidos aquí anularán los establecidos en la página de 'Productos' + enable_reset?: ¿Activar Reset del Stock? + default_stock: "Inventario predeterminado" + inherit?: ¿Heredado? + add: Añadir + hide: Ocultar + import_date: Importado + select_a_shop: Selecciona una Tienda + review_now: Revisar ahora + new_products_alert_message: Hay %{new_product_count} nuevos productos disponibles para añadir a tu inventario. + currently_empty: Tu inventario está vacio + no_matching_products: No se encuentran productos que concuerden en tu inventario + no_hidden_products: No hay productos ocultados de tu inventario + no_matching_hidden_products: No se encuentran productos ocultos que concuerden + no_new_products: No hay nuevos productos disponibles para añadir a este inventario + no_matching_new_products: No hay nuevos productos que concuerden + inventory_powertip: Este es tu inventario de productos. Para añadir productos a tu inventario, selecciona "Nuevos Productos" en el menú desplegable. + hidden_powertip: Estos productos han sido ocultados de tu inventario y no están disponibles para añadir a tu tienda. Puedes hacer click en "Añadir" para añadir un producto a tu inventario. + new_powertip: Estos productos están disponibles para añadirlos a tu inventario. Haz clic en "Añadir" para añadir un producto a tu inventario o "Ocultar" para ocultarlo de la vista. Siempre puedes cambiar de idea! + controls: + back_to_my_inventory: Volver a mi inventario + orders: + invoice_email_sent: 'Se ha enviado correo electrónico con la factura.' + order_email_resent: 'El correo electrónico del pedido se ha reenviado' + bulk_management: + tip: "Usa esta página para alterar la cantidad del producto en varios pedidos a la vez. Los productos pueden ser eliminados de los pedidos si es necesario. " + shared: "¿Recurso compartido?" + order_no: "Pedido Nº" + order_date: "Completado en" + max: "Max" + product_unit: "Producto: Unidad" + weight_volume: "Peso/Volumen" + ask: "¿Pregunta?" + page_title: "Gestor de Multiples Pedidos" + actions_delete: "Borrar Seleccionados" + loading: "Cargando pedidos" + no_results: "No se encuentran pedidos." + group_buy_unit_size: "Unidad de Magnitud del Grupo de Consumo" + total_qtt_ordered: "Cantidad total del Pedido" + max_qtt_ordered: "Cantidad máxima del Pedido" + current_fulfilled_units: "Unidades Completadas" + max_fulfilled_units: "Max Unidades Completadas" + order_error: "Algunos errores deberán ser resueltos antes de que puedas actualizar los pedidos.\nTodos los campos con borde rojo contienen errores." + variants_without_unit_value: "CUIDADO: Algunas variedades no tienen un valor unitario " + select_variant: "Seleccione una variante" + enterprise: + select_outgoing_oc_products_from: Selecciona los productos OC que salgan de + enterprises: + index: + title: Organizaciones + new_enterprise: Nueva Organización + producer?: "Productora?" + package: Perfil + status: Estado + manage: Gestionar + form: + about_us: + desc_short: Descripción corta + desc_short_placeholder: Háblanos sobre tu organización en una o dos frases + desc_long: Sobre nosotras + desc_long_placeholder: Explica a las consumidoras quién eres. Esta información aparecerá en tu perfil público. + business_details: + abn: NIF + abn_placeholder: ej. 99 123 456 789 + acn: ACN + acn_placeholder: ej. 123 456 789 + display_invoice_logo: Mostrar logo en facturas + invoice_text: Añadir texto personalizado al final de las facturas + contact: + name: Nombre + name_placeholder: ej. Gustav Plum + email_address: Dirección de correo electrónico público + email_address_placeholder: p.ej. consultas@lacesta.com + email_address_tip: "Esta dirección de correo electrónico se mostrará en su perfil público" + phone: Teléfono + phone_placeholder: ej. 98 7654 3210 + website: Website + website_placeholder: ej. www.truffles.com + enterprise_fees: + name: Nombre + fee_type: Tipo de Comisión + manage_fees: Gestiona las comisiones de la Organización + no_fees_yet: No tienes comisiones para la organización. + create_button: Crear una ahora + images: + logo: Logo + promo_image_placeholder: 'Esta imagen aparece en "Sobre nosotras"' + promo_image_note1: 'ATENCIÓN:' + promo_image_note2: La imagen será recortada a 1200 x 260. + promo_image_note3: La imagen se mostrará en la parte superior del perfil de la organización y en pop-ups. + inventory_settings: + text1: Puedes optar por administrar los niveles de stock y los precios a través de tu + inventory: inventario + text2: > + Si estás utilizando la herramienta de inventario, puedes seleccionar + si los nuevos productos añadidos por las proveedoras deben añadirse + antes al inventario de ser almacenados. Si no estás utilizando tu inventario + para administrar tus productos, debes seleccionar la opción 'recomendada' + a continuación: + preferred_product_selection_from_inventory_only_yes: Los nuevos productos se pueden publicar en la tienda (recomendado) + preferred_product_selection_from_inventory_only_no: Los nuevos productos se deben agregar al inventario antes de que puedan ser puestos en la tienda + payment_methods: + name: Nombre + applies: ¿Aplicar? + manage: Gestionar los métodos de pago + no_method_yet: Todavía no tienes ningún método de pago. + create_button: Crear un nuevo método de pago + create_one_button: Crear una ahora + primary_details: + name: Nombre + name_placeholder: ej. Professor Plum's Biodynamic Truffles + groups: Grupos + groups_tip: Seleccione cualquier grupo o región de la que sea miembro. Esto ayudará a los clientes a encontrar su organización. + groups_placeholder: Comience a escribir para buscar los grupos disponibles ... + primary_producer: Productora Principal? + primary_producer_tip: Seleciona "Productora" si eres la principal productora. + producer: Productora + any: Cualquiera + none: Ninguno + own: Propio + sells: Vende + sells_tip: "Ninguno - La organización no vende directamente a los consumidores.
Popios - La organización vende sus propios productos a los consumidores.
Cualquiera - La organización vende sus propios productos o de otros.
" + visible_in_search: ¿Visible en la búsqueda? + visible_in_search_tip: Determina qué organizaciones son visibles para los consumidores cuando buscan en el site. + visible: Visible + not_visible: No visible + permalink: Permalink (sin espacios) + permalink_tip: "Se usa para crear la URL de tu tienda: %{link}nombre-de-tu-tienda/shop" + link_to_front: Link a la tienda + link_to_front_tip: Enlace directo a tu tienda en Open Food Networks + ofn_uid: UID de OFN + ofn_uid_tip: La identificación única utilizada para identificar la organización en Open Food Network. + shipping_methods: + name: Nombre + applies: ¿Aplicar? + manage: Gestionar métodos de envío + create_button: Crear nuevo método de envío + create_one_button: Crear una ahora + no_method_yet: Todavía no tienes ningún método de envío. + shop_preferences: + shopfront_requires_login: "¿Quieres que la tienda sea visible y pública?" + shopfront_requires_login_tip: "Elije si los clientes deben iniciar sesión para ver la tienda o si es visible para todos." + shopfront_requires_login_false: "Pública" + shopfront_requires_login_true: "Visible solo para consumidores registrados" + recommend_require_login: "Recomendamos requerir a los usuarios que accedan cuando sus pedidos puedan cambiar." + allow_guest_orders: "Pedidos de invitados" + allow_guest_orders_tip: "Permitir pedidos como invitado o solo como usuarios registrados." + allow_guest_orders_false: "Se necesita hacer login para realizar un pedido" + allow_guest_orders_true: "Permitir pedidos a invitados" + allow_order_changes: "Cambiar pedidos" + allow_order_changes_tip: "Permitir a los clientes cambiar sus pedidos mientras que el ciclo de pedido siga abierto." + allow_order_changes_false: "Los pedidos efectuados no pueden ser cambiados / cancelados" + allow_order_changes_true: "Los clientes pueden cambiar / cancelar pedidos mientras el ciclo de pedido está abierto" + enable_subscriptions: "Suscripciones" + enable_subscriptions_tip: "¿Habilitar la funcionalidad de suscripciones?" + enable_subscriptions_false: "Deshabilitado" + enable_subscriptions_true: "Habilitado" + shopfront_message: "Mensaje de la Tienda" + shopfront_message_placeholder: > + Mensaje de bienvenida opcional para compradores, explica como comprar + en el sitio. si el texto se agrega en este campo, va a ser mostrado + en la pestaña de inicio cuando los clientes ingresen por primera vez + a la tienda. + shopfront_message_link_tooltip: "Insertar / editar enlace" + shopfront_message_link_prompt: "Por favor introduzca una URL para insertar" + shopfront_closed_message: "Mensaje de tienda cerrada" + shopfront_closed_message_placeholder: > + Un mensaje que proporciona una explicación más detallada sobre por qué + tu tienda está cerrada y/o cuándo se abrirá de nuevo. Esto se muestra + en tu tienda sólo cuando no tienes ciclos de pedidos activos (p.e. la + tienda está cerrada). + shopfront_category_ordering: "Orden de las categorías de la tienda" + open_date: "Fecha de Inicio" + close_date: "Fecha de Finalización" + social: + twitter_placeholder: "ej: the_prof" + instagram_placeholder: "p.ej. @mi_huerta" + facebook_placeholder: "eg. www.facebook.com/NombreDePáginaAquí" + linkedin_placeholder: "p.ej. www.linkedin.com/in/YourNameHere" + stripe_connect: + connect_with_stripe: "Conectar con Stripe" + stripe_connect_intro: "Para aceptar pagos con tarjeta de crédito, necesitarás conectar tu cuenta Stripe con Open Food Network. Usa el botón a la derecha para comenzar." + stripe_account_connected: "Cuenta de Stripe conectada." + disconnect: "Desconectar cuenta" + confirm_modal: + title: Conectar con Stripe + part1: Stripe es un servicio de pagos que permite a las tiendas aceptar pagos con tarjeta de crédito de las consumidoras. + part2: Para usar esta función, debes conectar su cuenta Stripe con OFN. Al hacer clic en 'Acepto' a continuación, se redireccionará al sitio web de Stripe donde puede conectar una cuenta de Stripe existente o crear una nueva si aún no la tiene. + part3: Esto permitirá que Open Food Network acepte pagos con tarjeta de crédito de los clientes en su nombre. Tenga en cuenta que deberá mantener su propia cuenta de Stripe, pagar las tarifas de Stripe y gestionar los reembolsos y el servicio al cliente por usted mismo. + i_agree: Estoy de acuerdo + cancel: Cancelar + tag_rules: + default_rules: + by_default: Por Defecto + no_rules_yet: No hay reglas por defecto aplicadas + add_new_button: '+ Añadir una nueva regla por defecto' + no_tags_yet: No hay etiquetas para esta organización + no_rules_yet: Todavía no se aplican reglas a esta etiqueta + for_customers_tagged: 'Para los consumidores etiquetados:' + add_new_rule: '+ Añadir una nueva regla' + add_new_tag: '+ Añadir una nueva etiqueta' + users: + email_confirmation_notice_html: "Falta la confirmación del email. Te hemos enviado un correo de confirmación a %{email}." + resend: Reenviar + owner: 'Propietaria' + contact: "Contacto" + contact_tip: "El administrador que recibirá los correos electrónicos de la empresa para pedidos y notificaciones. Debe tener una dirección de correo electrónico confirmada." + owner_tip: La principal usaría responsable para esta organización. + notifications: Notificaciones + notifications_tip: Las Notificaciones sobre los pedidos se enviarán a esta dirección de correo. + notifications_placeholder: ej. gustav@truffles.com + notifications_note: 'Nota: Una nueva dirección de correo debe ser confirmada. ' + managers: Gestoras + managers_tip: Otras usuarias con permiso para gestionar esta organización. + invite_manager: "Invitar administrador" + invite_manager_tip: "Invite a un usuario no registrado a registrarse y convertirse en administrador de esta organización." + add_unregistered_user: "Agregar un usuario no registrado" + email_confirmed: "Correo electrónico confirmado" + email_not_confirmed: "Correo electrónico no confirmado" + actions: + edit_profile: Configuración + properties: Propiedades + payment_methods: Métodos de pago + payment_methods_tip: Esta organización no tiene métodos de pago + shipping_methods: Métodos de envío + shipping_methods_tip: Esta organización tiene métodos de envío + enterprise_fees: Comisiones de la Organización + enterprise_fees_tip: Esta organización no tiene comisiones + admin_index: + name: Nombre + role: Rol + sells: Vende + visible: ¿Visible? + owner: Propietario + producer: Productor + change_type_form: + producer_profile: Perfil del productor + connect_ofn: Conectar a través de OFN + always_free: SIEMPRE GRATIS + producer_description_text: Añade tus productos a Open Food Network, permitiendo a los Grupos de Consumo vender tus productos. + producer_shop: Tienda de productor + sell_your_produce: Vende tu propia producción + producer_shop_description_text: Venda sus productos directamente a los clientes a través de su propia tienda. + producer_shop_description_text2: Una tienda de productor es para vender sus productos solamente, si quiere vender productos de otros productores, seleccione "Hub de Productor" + producer_hub: Hub de productor + producer_hub_text: Vende tu propia producción y la de otros + producer_hub_description_text: Su organización es la columna vertebral de un sistema de consumo local. Agregue productos suyos o de otras organizaciones y véndalo a través de su tienda en Open Food Network (LaFeriaCR). + profile: Solo perfil + get_listing: Obtener un listado + profile_description_text: La gente podrá encontrarlo y ponerse en contacto con usted en Open Food Network (LaFeriaCR). Su organización será visible en el mapa y se podrá buscar en los listados. + hub_shop: Tienda del Hub + hub_shop_text: Vender la producción de otros + hub_shop_description_text: Su organización es la columna vertebral de un sistema de consumo local. Agregue productos de otras organizaciones y véndalo a través de su tienda en Open Food Network (LaFeriaCR). + choose_option: Por favor, elija una de las opciones anteriores. + change_now: Cambiar + enterprise_user_index: + loading_enterprises: CARGANDO ORGANIZACIONES + no_enterprises_found: No se encuentran organizaciones. + search_placeholder: Buscar por nombre + manage: Administrar + manage_link: Configuración + producer?: "¿Productor?" + package: "Perfil" + status: "Estado" + new_form: + owner: Propietario + owner_tip: El usuario principal responsable para esta organización. + i_am_producer: Soy un productor + contact_name: Nombre de contacto + edit: + editing: 'Configuración:' + back_link: Volver a la lista de organizaciones + new: + title: Nueva Organización + back_link: Volver a la lista de organizaciones + remove_logo: + remove: "Eliminar la imágen" + removed_successfully: "Logotipo eliminado con éxito" + immediate_removal_warning: "El logotipo se eliminará inmediatamente después de confirmar." + remove_promo_image: + remove: "Eliminar la imagen" + removed_successfully: "Imágen promocional eliminada con éxito" + immediate_removal_warning: "La imágen promocional se eliminará inmediatamente después de confirmar." + welcome: + welcome_title: ¡Bienvenido a Open Food Network (LaFeriaCR)! + welcome_text: Ha creado correctamente un + next_step: Siguiente paso + choose_starting_point: 'Seleccione su perfil:' + profile: 'Perfil' + producer_profile: 'Perfil de Productor' + invite_manager: + user_already_exists: "El usuario ya existe" + error: "Algo salió mal" + order_cycles: + loading_flash: + loading_order_cycles: Cargando ciclos de pedido + loading: CARGANDO... + new: + create: "Crear" + cancel: "Cancelar" + back_to_list: "Regresar a la lista" + edit: + advanced_settings: "Configuración avanzada" + save: "Guardar" + save_and_next: "Guardar y continuar" + next: "Siguiente" + cancel: "Cancelar" + back_to_list: "Regresar a la lista" + save_and_back_to_list: "Guardar y volver a lista" + choose_products_from: "Escoger productos desde:" + incoming: + save: "Guardar" + save_and_next: "Guardar y continuar" + next: "Siguiente" + cancel: "Cancelar" + back_to_list: "Regresar a la lista" + outgoing: + outgoing: "Saliente" + distributor: "Distribuidor" + products: "Productos" + tags: "Etiquetas" + delivery_details: "Detalles de entrega" + fees: "Comisiones" + previous: "Anterior" + save: "Guardar" + save_and_back_to_list: "Guardar y volver a lista" + cancel: "Cancelar" + back_to_list: "Regresar a la lista" + wizard_progress: + edit: "1. Configuración general" + incoming: "2. Productos entrantes" + outgoing: "3. Productos salientes" + exchange_form: + pickup_time_tip: Cuándo estarán listos los pedidos de este ciclo de pedido para los clientes + pickup_instructions_placeholder: "Instrucciones de recogida" + pickup_instructions_tip: Estas instrucciones se muestran a los clientes después de completar un pedido. + pickup_time_placeholder: "Listo para ( Fecha / Hora)" + receival_instructions_placeholder: "Instrucciones de recepción" + add_fee: 'Añadir comisión' + remove: 'Eliminar' + selected: 'seleccionado' + add_exchange_form: + add_supplier: 'Añadir proveedor' + add_distributor: 'Añadir distribuidor' + advanced_settings: + title: Configuración avanzada + choose_product_tip: Puede restringir los productos entrantes y salientes a solo el inventario de %{inventory}. + preferred_product_selection_from_coordinator_inventory_only_here: Solo el inventario del coordinador + preferred_product_selection_from_coordinator_inventory_only_all: Todos los productos disponibles + save_reload: Guardar y recargar la página + coordinator_fees: + add: Añadir comisión para el coordinador + filters: + search_by_order_cycle_name: "Buscar por nombre del Ciclo de Pedido..." + involving: "Involucrando" + any_enterprise: "Cualquier organización" + any_schedule: "Cualquier programación" + form: + general_settings: "Configuración general" + incoming: Entrante + supplier: Proveedor + receival_details: Detalles de la recepción + fees: Comisiones + outgoing: Saliente + distributor: Distribuidor + products: Productos + tags: Etiquetas + add_a_tag: Añade una etiqueta + delivery_details: Detalles de Recogida / Entrega + index: + schedule: Programación + schedules: Programación + new_schedule: Nueva programación + name_and_timing_form: + name: Nombre + orders_open: Pedidos abiertos a + coordinator: Coordinador + orders_close: Cierre de pedidos + row: + suppliers: proveedores + distributors: distribuidores + variants: variedades + simple_form: + ready_for: Listo para + ready_for_placeholder: Fecha / hora + customer_instructions: Instrucciones del cliente + customer_instructions_placeholder: Notas de la recogida o entrega + products: Productos + fees: Comisiones + destroy_errors: + orders_present: Ese ciclo de pedido ha sido seleccionado por un cliente y no puede ser eliminado. Para evitar que los clientes accedan a él, ciérrelo. + schedule_present: Ese ciclo de pedido está vinculado a una programación y no puede ser eliminado. Desvincula o elimina la programación primero. + bulk_update: + no_data: Hm, algo salió mal. No se encontraron datos de ciclo de pedido. + date_warning: + msg: Este ciclo de pedido está vinculado a %{n}pedidos de suscripción abiertos. Cambiar esta fecha ahora no afectará ningun pedido que ya se haya realizado pero se debe evitar si es posible. ¿Estás seguro que deseas continuar? + cancel: Cancelar + proceed: Proceder + producer_properties: + index: + title: Propiedades del productor + proxy_orders: + cancel: + could_not_cancel_the_order: No se pudo cancelar la orden + resume: + could_not_resume_the_order: No se pudo reanudar el pedido + shared: + user_guide_link: + user_guide: Manual de usuario + enterprises_hubs_tabs: + has_no_payment_methods: "%{enterprise} no tiene métodos de pago" + has_no_shipping_methods: "%{enterprise} no tiene ningún método de envío" + has_no_enterprise_fees: "%{enterprise} no tiene comisiones de organización" + enterprise_issues: + create_new: Crear nuevo + resend_email: Reenviar correo electrónico + has_no_payment_methods: "%{enterprise} actualmente no tiene métodos de pago" + has_no_shipping_methods: "%{enterprise} no tiene actualmente métodos de envío" + email_confirmation: "La confirmación de correo electrónico está pendiente. Hemos enviado un correo electrónico de confirmación a %{email}." + not_visible: "%{enterprise} no es visible y no se puede encontrar en el mapa o en búsquedas" + reports: + hidden: OCULTO + unitsize: TAMAÑO DE LA UNIDAD + total: TOTAL + total_items: ARTÍCULOS TOTALES + supplier_totals: Totales de proveedores del Ciclo de Pedido + supplier_totals_by_distributor: Totales de proveedores por Distribuidor del Ciclo de pedidos + totals_by_supplier: Totales del distribuidor por proveedor del Ciclos de Pedido  + customer_totals: Totales de clientes del Ciclo de Pedido + all_products: Todos los productos + inventory: Inventario (disponible) + lettuce_share: LettuceShare + mailing_list: Lista de correo + addresses: Direcciones + payment_methods: Reporte de los métodos de pago + delivery: Reporte de entrega + tax_types: Tipos de impuestos + tax_rates: Tarifas de impuesto + pack_by_customer: Paquete por cliente + pack_by_supplier: Pack por proveedor + orders_and_distributors: + name: Pedidos y distribuidores + description: Pedidos con detalles de distribuidor + bulk_coop: + name: Bulk Co-Op + description: Reporte para pedidos de Bulk Co-Op + payments: + name: Reportes de pago + description: Reportes de pagos + orders_and_fulfillment: + name: Reportes de Pedidos y Repartos + customers: + name: Clientes + products_and_inventory: + name: Productos e inventario + users_and_enterprises: + name: Usuarios y organizaciones + description: Posesión y estado de la organización + order_cycle_management: + name: Gestión del Ciclo de Pedido + sales_tax: + name: Impuesto de venta + xero_invoices: + name: Facturas Xero + description: Facturas para la importación en Xero + packing: + name: Reportes de empaquetado + enterprise_fee_summary: + name: "Resumen de las comisiones de la organización" + description: "Resumen de las comisiones de la organización recolectadas" + subscriptions: + subscriptions: Suscripciones + new: Nueva suscripción + create: Crear suscripción + edit: Editar suscripción + table: + edit_subscription: Editar suscripción + pause_subscription: Pausar suscripción + unpause_subscription: Reanudar suscripción + cancel_subscription: Cancelar suscripción + filters: + query_placeholder: "Buscar por correo electrónico ..." + setup_explanation: + just_a_few_more_steps: 'Solo unos pocos pasos más antes de que pueda comenzar:' + enable_subscriptions: "Habilita suscripciones para al menos una de sus tiendas" + enable_subscriptions_step_1_html: 1. Ir a la página %{enterprises_link}, encuentre su tienda y haga clic en "Administrar" + enable_subscriptions_step_2: 2. En "Preferencias de la tienda", habilite la opción Suscripciones + set_up_shipping_and_payment_methods_html: Configurar los métodos %{shipping_link} y %{payment_link} + set_up_shipping_and_payment_methods_note_html: Tenga en cuenta que solo se pueden usar
métodos de pago en efectivo y Stripe con las suscripciones + ensure_at_least_one_customer_html: Asegúrese de que exista al menos un %{customer_link} + create_at_least_one_schedule: Crear al menos una programación + create_at_least_one_schedule_step_1_html: 1. Ir a la página %{order_cycles_link} + create_at_least_one_schedule_step_2: 2. Crea un ciclo de pedido si aún no lo has hecho + create_at_least_one_schedule_step_3: 3. Haga clic en '+ Nueva programación' y complete el formulario + once_you_are_done_you_can_html: Una vez que haya terminado, puede %{reload_this_page_link} + reload_this_page: recarga esta página + steps: + details: 1. Detalles básicos + address: 2. Dirección + products: 3. Agregue productos + review: 4. Revisar y guardar + subscription_line_items: + this_is_an_estimate: | + Los precios mostrados son solo una estimación y se calculan en el momento en que se cambia la suscripción. + Si cambias precios o comisiones, los pedidos se actualizarán pero la suscripción seguirá mostrando los valores anteriores. + not_in_open_and_upcoming_order_cycles_warning: "No hay ciclos de pedidos abiertos o próximos para este producto." + autocomplete: + name_or_sku: "NOMBRE O CÓDIGO SKU" + quantity: "Cantidad" + add: "Añadir" + details: + details: Detalles + invalid_error: Ups! Por favor complete todos los campos requeridos ... + allowed_payment_method_types_tip: Solo se pueden usar métodos de pago en efectivo y Stripe en este momento + credit_card: Tarjeta de crédito + charges_not_allowed: Los cargos no están permitidos para este cliente + no_default_card: El cliente no tiene tarjetas disponibles para el cobro + card_ok: El cliente tiene una tarjeta disponible para cobro + begins_at_placeholder: "Seleccione una fecha" + ends_at_placeholder: "Opcional" + loading_flash: + loading: CARGANDO SUSCRIPCIONES + review: + details: Detalles + address: Dirección + products: Productos + no_open_or_upcoming_order_cycle: "No hay ciclo de pedido próximo" + products_panel: + save: "GUARDAR" + saving: "GUARDANDO" + saved: "GUARDADO" + product_already_in_order: Este producto ya ha sido agregado a la orden. Por favor edite la cantidad directamente. + stock: + insufficient_stock: "Inventario insuficiente" + out_of_stock: "Agotado" + orders: + number: Número + confirm_edit: ¿Seguro que quiere editar esta orden? Si lo hace, puede ser más difícil sincronizar automáticamente los cambios a la suscripción en el futuro. + confirm_cancel_msg: "¿Seguro que quieres cancelar esta suscripción? Esta acción no se puede deshacer." + cancel_failure_msg: "Lo sentimos ¡la cancelación falló!" + confirm_pause_msg: "¿Seguro que quieres pausar esta suscripción?" + pause_failure_msg: "Lo sentimos ¡pausar falló!" + confirm_unpause_msg: "Si tiene un ciclo de pedido abierto en el horario de esta suscripción, se creará un pedido para este cliente. ¿Estás seguro de que deseas anular la pausa de esta suscripción?" + unpause_failure_msg: "Lo sentimos ¡no se pudo reanudar!" + confirm_cancel_open_orders_msg: "Algunos pedidos de esta suscripción están actualmente abiertos. El cliente ya ha sido notificado de que se realizará el pedido. ¿Desea cancelar estos pedidos o conservarlos?" + resume_canceled_orders_msg: "Algunos pedidos de esta suscripción se pueden reanudar en este momento. Puede reanudarlos desde el menú desplegable de pedidos." + yes_cancel_them: Cancelarlos + no_keep_them: Guárdalos + yes_i_am_sure: Sí estoy seguro + order_update_issues_msg: Algunas órdenes no se pudieron actualizar automáticamente, esto es más probable porque se han editado manualmente. Revise los problemas que se detallan a continuación y realice los ajustes a los pedidos individuales si es necesario. + no_results: + no_subscriptions: Aún no hay suscripciones ... + why_dont_you_add_one: ¿Por qué no agrega una? :) + no_matching_subscriptions: No se encontraron suscripciones coincidentes + schedules: + destroy: + associated_subscriptions_error: Este horario no se puede eliminar porque tiene suscripciones asociadas + controllers: + enterprises: + stripe_connect_cancelled: "Se ha cancelado la conexión a Stripe" + stripe_connect_success: "La cuenta Stripe se ha conectado correctamente" + stripe_connect_fail: Lo sentimos, la conexión de su cuenta Stripe ha fallado + stripe_connect_settings: + resource: Configuración de Stripe Connect + api: + enterprise_logo: + destroy_attachment_does_not_exist: "El logotipo no existe" + enterprise_promo_image: + destroy_attachment_does_not_exist: "La imágen promocional no existe" + orders: + failed_to_update: "Error al actualizar pedido" + checkout: + already_ordered: + cart: "carrito" + message_html: "Ya realizó un pedido para este ciclo de pedido. Compruebe el %{cart}para ver los artículos que pidió. También puede cancelar artículos mientras el ciclo de pedido siga abierto." + failed: "La finalización de compra falló, por favor comunicate con nosotros para procesar la orden." + shops: + hubs: + show_closed_shops: "Mostrar tiendas cerradas" + hide_closed_shops: "Ocultar tiendas cerradas" + show_on_map: "Ver todos en el mapa" + shared: + menu: + cart: + cart: "Carrito" + signed_in: + profile: "Perfil" + mobile_menu: + cart: "Carrito" + joyride: + checkout: "Validar el carrito ahora" + already_ordered_products: "Pedido en este ciclo de pedido" + register_call: + selling_on_ofn: "¿Tiene interés sobre entrar en Open Food Network (LaFeriaCR)?" + register: "Regístrarse aquí" + footer: + footer_secure: "Seguro y de confianza." + footer_secure_text: "Open Food Network (LaFeriaCR) 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" + footer_contact_email: "Envíenos un correo electrónico" + footer_nav_headline: "Navegar" + footer_join_headline: "Unirse" + footer_join_body: "Crea un listado, una tienda o un directorio en Open Food Network (LaFeriaCR)." + footer_join_cta: "¡Cuénteme más!" + footer_legal_call: "Leer nuestros" + footer_legal_tos: "Términos y condiciones" + footer_legal_visit: "Encuéntrenos en" + footer_legal_text_html: "Open Food Network (LaFeriaCR) es una plataforma libre y de código abierto. Nuestro contenido tiene una licencia %{content_license} y nuestro código %{code_license}." + footer_data_text_with_privacy_policy_html: "Cuidamos bien sus datos. Consulte nuestra %{privacy_policy} y %{cookies_policy}" + footer_data_text_without_privacy_policy_html: "Cuidamos bien sus datos. Consulte nuestra %{cookies_policy}" + footer_data_privacy_policy: "política de privacidad" + footer_data_cookies_policy: "política de cookies" + shop: + messages: + login: "Ingresar" + signup: "Registrarse" + contact: "contactar" + require_customer_login: "Sólo los clientes aprobados pueden acceder a esta tienda." + require_login_html: "Si ya es un cliente aprobado, %{login} o %{signup} para continuar. ¿Quiere empezar a comprar aquí? Por favor, %{contact} %{enterprise} y pregunte acerca de participar." + require_customer_html: "Si desea comenzar a comprar aquí, por favor %{contact} %{enterprise} para preguntar acerca de incorporación." + card_could_not_be_updated: La tarjeta no se pudo actualizar + card_could_not_be_saved: la tarjeta no se pudo guardar + spree_gateway_error_flash_for_checkout: "Hubo un problema con su información de pago: %{error}" + invoice_billing_address: "Dirección de facturación:" + invoice_column_tax: "Impuesto sobre bienes y servicios" + invoice_column_price: "Precio" + invoice_column_item: "Artículo" + invoice_column_qty: "Cantidad" + invoice_column_unit_price_with_taxes: "Precio unidad (impuestos incl.)" + invoice_column_unit_price_without_taxes: "Precio unidad (sin impuestos)" + invoice_column_price_with_taxes: "Precio total (impuestos incl.)" + invoice_column_price_without_taxes: "Precio total (sin impuestos)" + invoice_column_tax_rate: "Tarifa de impuestos" + invoice_tax_total: "Total IVA:" + tax_invoice: "FACTURA DE IMPUESTOS" + tax_total: "Total impuestos (%{rate}):" + total_excl_tax: "Total (sin impuestos):" + total_incl_tax: "Total (Impuestos incl.)" + abn: "NIF:" + acn: "ACN:" + invoice_issued_on: "Factura emitida el:" + order_number: "Número de factura:" + date_of_transaction: "Fecha de la transacción:" + ticket_column_qty: "Cantidad" + ticket_column_item: "Artículo" + ticket_column_unit_price: "Precio por unidad" + ticket_column_total_price: "Precio total" + menu_1_title: "Tiendas" + menu_1_url: "/shops" + menu_2_title: "Mapa" + menu_2_url: "/map" + menu_3_title: "Productoras" + menu_3_url: "/producers" + menu_4_title: "Grupos" + menu_4_url: "/groups" + menu_5_title: "Acerca de" + menu_5_url: "https://laferia.cr/" + menu_6_title: "Conectar" + menu_6_url: " " + menu_7_title: "Aprender" + menu_7_url: " " + logo: "Logo (640x130)" + logo_mobile: "Logo para móvil (75x26)" + logo_mobile_svg: "Logo para móvil (SVG)" + home_hero: "Hero image" + home_show_stats: "Mostrar estadísticas" + footer_logo: "Logo (220x76)" + footer_facebook_url: "URL de Facebook" + footer_twitter_url: "URL de Twitter" + footer_instagram_url: "URL de Instagram" + footer_linkedin_url: "URL de LinkedIn" + footer_googleplus_url: "URL de Google Plus" + footer_pinterest_url: "URL de Pinterest" + footer_email: "Correo electrónico" + footer_links_md: "Enlaces" + footer_about_url: "URL acerca de" + user_guide_link: "Enlace de la guía de usuario" + name: Nombre + first_name: Nombre + last_name: Apellido + email: Correo electrónico + phone: Teléfono + next: Siguiente + address: Dirección + address_placeholder: ej. Calle 7 de Plaza Alta + address2: Dirección (continuación) + city: Ciudad + city_placeholder: ej. Alajuela + postcode: Código postal + postcode_placeholder: ej. 20307 + suburb: Barrio + state: Provincia + country: País + unauthorized: No autorizado + terms_of_service: "Términos de servicio" + on_demand: Bajo demanda + none: Ninguno + not_allowed: No permitido + no_shipping: Sin métodos de envío + no_payment: Sin métodos de pago + no_shipping_or_payment: sin envío ni métodos de pago + unconfirmed: sin confirmar + days: dias + authorization_failure: "Fallo de autorización" + label_shop: "Tienda" + label_shops: "Tiendas" + label_map: "Mapa" + label_producer: "Productor" + label_producers: "Productores" + label_groups: "Grupos" + label_about: "Acerca de" + label_connect: "Conectar" + label_learn: "Aprender" + label_blog: "Blog" + label_support: "Soporte" + label_shopping: "Tienda" + label_login: "Iniciar sesión" + label_logout: "Cerrar sesión" + label_signup: "Registrarse" + label_administration: "Administración" + label_admin: "Admin" + label_account: "Cuenta" + label_more: "Mostrar más" + label_less: "Mostrar menos" + label_notices: "Noticias" + cart_items: "Elementos" + cart_headline: "Su carrito de compras" + total: "Total" + cart_updating: "Actualizando el carrito..." + cart_empty: "Carrito vacío" + cart_edit: "Editar carrito" + card_number: Número de tarjeta + card_securitycode: "Código de seguridad" + card_expiry_date: Fecha de expiración + card_masked_digit: "X" + card_expiry_abbreviation: "Exp" + new_credit_card: "Nueva tarjeta de crédito" + my_credit_cards: Mis tarjetas de crédito + add_new_credit_card: Añadir nueva tarjeta de crédito + saved_cards: Tarjetas de crédito guardadas + add_a_card: Añade una tarjeta + add_card: Añadir tarjeta + you_have_no_saved_cards: Aún no has guardado ninguna tarjeta. + saving_credit_card: Guardando tarjeta de crédito... + card_has_been_removed: "Su tarjeta ha sido eliminada (número: %{number})" + card_could_not_be_removed: Lo sentimos, la tarjeta no se pudo eliminar + invalid_credit_card: "Tarjeta de crédito inválida" + ie_warning_headline: "Su navegador está desactualizado :-(" + ie_warning_text: "Para una mejor experiencia utilizando La Feria, le recomendamos actualizar su navegador:" + ie_warning_chrome: Descargar Chrome + ie_warning_firefox: Descargar Firefox + ie_warning_ie: Actualizar Internet Explorer + ie_warning_other: "¿No puede actualizar su navegador? Pruebe usar Open Food Network (LaFeriaCR) en su teléfono :-)" + legal: + cookies_policy: + header: "Cómo utilizamos las cookies" + desc_part_1: "Las cookies son archivos de texto muy pequeños que se almacenan en tu computadora cuando visitas algunos sitios web." + desc_part_2: "En OFN somos respetuosos con tu privacidad. Utilizamos solo las cookies que son necesarias para ofrecerte el servicio de compraventa de alimentos en línea. No vendemos ninguno de tus datos. Es posible que en el futuro te propongamos que compartas alguno de tus datos para crear nuevos servicios comunes que podrían ser útiles para el ecosistema (como los servicios logísticos para sistemas alimentarios cortos), pero aún no hemos llegado a ese punto y no lo haremos sin tu autorización :-)" + desc_part_3: "Usamos cookies principalmente para recordar quién eres si 'inicias sesión' o para poder recordar los artículos que colocas en tu carrito, incluso si no has iniciado sesión. Si continúas navegando en el sitio web sin hacer clic en \"Aceptar cookies\" suponemos que nos das tu consentimiento para almacenar las cookies que son esenciales para el funcionamiento del sitio web. ¡Aquí está la lista de cookies que usamos!" + essential_cookies: "Cookies esenciales" + essential_cookies_desc: "Las siguientes cookies son estrictamente necesarias para el funcionamiento de nuestro sitio web." + essential_cookies_note: "La mayoría de las cookies solo contienen un identificador único, pero no otros datos, por lo que su dirección de correo electrónico y contraseña, por ejemplo, nunca se incluyen ni se exponen." + cookie_domain: "Establecido por:" + cookie_session_desc: "Se usa para permitir que el sitio web recuerde a los usuarios entre las visitas a la página, por ejemplo, recordar los artículos en tu carrito." + cookie_consent_desc: "Se usa para mantener el estado del consentimiento del usuario para almacenar cookies" + cookie_remember_me_desc: "Se usa si el usuario ha solicitado que el sitio web lo recuerde. Esta cookie se elimina automáticamente después de 12 días. Si como usuario deseas que se elimine esa cookie, solo necesitas desconectarte. Si no deseas que la cookie se instale en tu computadora no debes marcar la casilla \"recordarme\" al iniciar sesión." + cookie_openstreemap_desc: "Utilizado por nuestro amigo proveedor de mapeo de código abierto (OpenStreetMap) para garantizar que no recibas demasiadas solicitudes durante un período de tiempo determinado, para evitar el abuso de sus servicios." + cookie_stripe_desc: "Datos recopilados por nuestro procesador de pagos Stripe para detectar fraudes https://stripe.com/cookies-policy/legal. No todas las tiendas usan Stripe como método de pago pero es una buena práctica evitar fraude aplicarlo a todas las páginas. Stripe probablemente crea una imagen de cuáles de nuestras páginas generalmente interactúan con su API y luego marca cualquier cosa inusual. Por lo tanto configurar la cookie Stripe tiene una función más amplia que la simple provisión de un método de pago a un usuario. Eliminarla podría afectar la seguridad del servicio en sí. Puede obtener más información acerca de Stripe y leer su política de privacidad en https://stripe.com/privacy." + statistics_cookies: "Cookies de estadísticas" + statistics_cookies_desc: "Las siguientes no son estrictamente necesarias, pero ayudan a proporcionarle una mejor experiencia de usuario al permitirnos analizar el comportamiento del usuario, identificar qué funciones usa más o no, comprender los problemas de la experiencia del usuario, etc." + statistics_cookies_analytics_desc_html: "Para recopilar y analizar los datos de uso de la plataforma utilizamos Google Analytics, ya que era el servicio predeterminado conectado con Spree (el software de código abierto de comercio electrónico que utilizamos) pero nuestra visión es cambiar a Matomo (ex Piwik, herramienta analítica de código abierto que cumple con GDPR y protege su privacidad) tan pronto como podamos." + statistics_cookies_matomo_desc_html: "Para recopilar y analizar los datos de uso de la plataforma, utilizamos Matomo (ex Piwik), una herramienta analítica de código abierto que cumple con GDPR y protege tu privacidad" + statistics_cookies_matomo_optout: "¿Deseas excluirte de Matomo Analytics? No recopilamos ningún dato personal y Matomo nos ayuda a mejorar nuestro servicio, pero respetamos tu elección :-)" + cookie_analytics_utma_desc: "Se usa para distinguir usuarios y sesiones. La cookie se crea cuando la biblioteca javascript se ejecuta y no existe ninguna cookie __utma existente. La cookie se actualiza cada vez que se envían datos a Google Analytics." + cookie_analytics_utmt_desc: "Se usa para acelerar la tasa de solicitud." + cookie_analytics_utmb_desc: "Se utiliza para determinar nuevas sesiones / visitas. La cookie se crea cuando la librería javascript se ejecuta y no existe ninguna cookie __utmb existente. La cookie se actualiza cada vez que los datos se envían a Google Analytics." + cookie_analytics_utmc_desc: "No utilizado en ga.js. Establecer para la interoperabilidad con urchin.js. Históricamente, esta cookie funcionó junto con la cookie __utmb para determinar si el usuario estaba en una nueva sesión / visita." + cookie_analytics_utmz_desc: "Almacena la fuente de tráfico o la campaña que explica cómo el usuario llegó a su sitio. La cookie se crea cuando se ejecuta la librería javascript y se actualiza cada vez que se envían datos a Google Analytics." + cookie_matomo_basics_desc: "Matomo cookies de origen para recopilar estadísticas." + cookie_matomo_heatmap_desc: "Matomo Heatmap y sesión de grabación de cookies." + cookie_matomo_ignore_desc: "Cookie utilizada para excluir al usuario de ser rastreado." + disabling_cookies_header: "Advertencia sobre la desactivación de cookies" + disabling_cookies_desc: "Como usuario, siempre puede permitir, bloquear o eliminar las cookies de Open Food Network o cualquier otra página web cuando lo desee a través del control de configuración de su navegador. Cada navegador tiene una operativa diferente. Aquí están los enlaces:" + disabling_cookies_firefox_link: "https://support.mozilla.org/es/kb/habilitar-y-deshabilitar-cookies-sitios-web-rastrear-preferencias" + disabling_cookies_chrome_link: "https://support.google.com/chrome/answer/95647" + disabling_cookies_ie_link: "https://support.microsoft.com/es-es/help/17442/windows-internet-explorer-delete-manage-cookies" + disabling_cookies_safari_link: "https://www.apple.com/legal/privacy/es/cookies/" + disabling_cookies_note: "Pero tenga en cuenta que si elimina o modifica las cookies esenciales utilizadas por Open Food Network, el sitio web no funcionará, no podrá agregar nada a su carrito ni realizar pedidos, por ejemplo." + cookies_banner: + cookies_usage: "Este sitio utiliza cookies para que su navegación sea fluida y segura, y para ayudarnos a comprender cómo lo usa para mejorar las funciones que ofrecemos." + cookies_definition: "Las cookies son archivos de texto muy pequeños que se almacenan en tu ordenador cuando visitas algunos sitios web." + cookies_desc: "Utilizamos solo las cookies que son necesarias para ofrecerle el servicio de venta / compra de alimentos en línea. No vendemos ninguno de sus datos. Utilizamos cookies principalmente para recordar quién es usted si 'inicia sesión' en el servicio, o para poder recordar los artículos que puso en su carrito, incluso si no ha iniciado sesión. Si continúa navegando en el sitio web sin hacer clic en \"Aceptar cookies\", asumimos que nos da su consentimiento para almacenar las cookies que son esenciales para el funcionamiento del sitio web." + cookies_policy_link_desc: "Si desea obtener más información, consulte nuestro" + cookies_policy_link: "política de cookies" + cookies_accept_button: "Aceptar cookies" + home_shop: Comprar ahora + brandstory_headline: "Consume con valores." + brandstory_intro: "A veces la mejor forma de arreglar el sistema es empezar uno nuevo…" + brandstory_part1: "Nosotros empezamos desde abajo. Con granjeros y productoras listas para contar sus historias con orgullo y autenticidad. Con distribuidoras listas para conectar gente con productos de forma justa y honesta. Con compradores que creen que mejores decisiones de compras semanales pueden seriamente cambiar el mundo." + brandstory_part2: "Luego necesitamos una forma de hacerlo real. Una forma de empoderar a todos los que producen, venden y compran comida. Una forma de contar todas las historias, de manejar todas las logísticas. Una forma de convertir transacción en transformación todos los días." + brandstory_part3: "Entonces contruímos un mercado que nivela el campo de juego. Es transparente, de forma que crea relaciones reales. Es de código abierto, de forma que todos son los dueños." + brandstory_part4: "Funciona en cualquier lugar. Lo cambia todo." + brandstory_part5_strong: "Le llamamos Open Food Network." + brandstory_part6: "Todos amamos la comida. Ahora podemos amar nuestro sistema de comida también." + learn_body: "Explora modelos, historias y recursos para ayudarte a desarrollar tu organización. Encuentra formación, eventos y otras oportunidades para aprender de tus compañeros." + learn_cta: "Inspírate" + connect_body: "Busca en nuestros directorios de productoras, grupos u otras organizaciones. Haz una lista de tu organización en OFN para que los consumidores puedan encontrarte. Únete a la comunidad para obtener consejos y resolver problemas juntos." + connect_cta: "Explorar" + system_headline: "Compras - aquí está cómo funcionan." + system_step1: "1. Buscar" + system_step1_text: "Busque comida local y de temporada en nuestras tiendas diversas e independientes. Busque por cantón y categoría de comida o si prefiere entrega o recoger." + system_step2: "2. Comprar" + system_step2_text: "Transforme su consumo con comida local y asequible de diversos productores ¡Conoce las historias detrás de su comida y la gente que la hace!" + system_step3: "3. Recogida" + system_step3_text: "Visite su productor para crear un vínculo más directo con los productores y sus vecinos, también puedes comprar directamente a algunos productores. Compre su comida de una manera tan diversa como la naturaleza." + cta_headline: "Compras que hacen el mundo un mejor lugar." + cta_label: "Estoy listo" + stats_headline: "Entre todos creamos un nuevo sistema de producción, distribución y consumo." + stats_producers: "productores" + stats_shops: "tiendas" + stats_shoppers: "consumidores" + stats_orders: "pedidos" + checkout_title: Validar el carrito + checkout_now: Validar el carrito ahora + checkout_order_ready: Pedido preparado para + checkout_hide: Esconder + checkout_expand: Expandir + checkout_headline: "Está bien, ¿listo para realizar el pedido?" + checkout_as_guest: "Hacer pedido como invitado" + checkout_details: "Sus detalles" + checkout_billing: "Información de cobro" + checkout_default_bill_address: "Guardar como dirección de facturación por defecto" + checkout_shipping: Información de envío + checkout_default_ship_address: "Guardar como dirección de envío por defecto" + checkout_method_free: Gratis + checkout_address_same: ¿Dirección de entrega igual a la dirección de cobro? + checkout_ready_for: "Listo para:" + checkout_instructions: "¿Algún comentario o intrucciones especiales?" + checkout_payment: Pago + checkout_send: Realizar pedido ahora + checkout_your_order: Su pedido + checkout_cart_total: Total del carrito + checkout_shipping_price: Envío + checkout_total_price: Total + checkout_back_to_cart: "De vuelta al carrito" + cost_currency: "Moneda" + order_paid: PAGADO + order_not_paid: NO PAGADO + order_total: Pedido total + order_payment: "Pagando con:" + order_billing_address: Dirección de cobro + order_delivery_on: Entregar en + order_delivery_address: Dirección de entrega + order_delivery_time: Tiempo de entrega + order_special_instructions: "Sus notas:" + order_pickup_time: Listo para la recolección + order_pickup_instructions: Instrucciones de recolección + order_produce: Productos + order_total_price: Total + order_includes_tax: (incluye impuesto) + order_payment_paypal_successful: Su pago a través de PayPal ha sido procesado con éxito. + order_hub_info: Información del centro de acopio + order_back_to_store: Volver a la Tienda + order_back_to_cart: Volver al Carrito + bom_tip: "Use esta página para alterar la cantidad del producto en varios pedidos a la vez. Los productos pueden ser eliminados de los pedidos si es necesario. " + unsaved_changes_warning: "Hay cambios no guardados, se perderán si continúa." + unsaved_changes_error: "Los campos con bordes rojos contienen errores." + products: "Productos" + products_in: "en %{oc}" + products_at: "en %{distributor}" + products_elsewhere: "Productos encontrados en otros lugares" + email_confirmed: "Gracias por confirmar la dirección de correo electrónico." + email_confirmation_activate_account: "Antes de que podamos activar su nueva cuenta, necesitamos confirmar su dirección de correo electrónico." + email_confirmation_greeting: "Hola, %{contact}!" + email_confirmation_profile_created: "¡Se creó un un perfil para %{name} con éxito! Para activar su Perfil necesitamos que confirme esta dirección de correo." + email_confirmation_click_link: "Por favor haga clic en el enlace de abajo para confirmar el correo electrónico y continuar configurando su perfil." + email_confirmation_link_label: "Confirmar este correo electrónico »" + email_confirmation_help_html: "Después de confirmar el correo electrónico puede acceder a su cuenta de administración para esta organización. Visite %{link} para encontrar más información sobre las características de %{sitename} y empiece a usar su perfil o tienda en línea." + email_confirmation_notice_unexpected: "Recibe este mensaje porque se ha registrado en %{sitename} o ha sido invitado a inscribirse por alguien que probablemente conozca. Si no entiende por qué está recibiendo este correo electrónico, escriba a %{contact}." + email_social: "Conecte con nosotros:" + email_contact: "Envíenos un correo electrónico:" + email_signoff: "Saludos," + email_signature: "El equipo de %{sitename}" + email_confirm_customer_greeting: "Hola %{name}," + email_confirm_customer_intro_html: "¡Gracias por comprar en %{distributor}!" + email_confirm_customer_number_html: "Confirmación del pedido #%{number}" + email_confirm_customer_details_html: "Aquí están los detalles de su pedido de %{distributor}:" + email_confirm_customer_signoff: "Saludos cordiales," + email_confirm_shop_greeting: "Hola %{name}," + email_confirm_shop_order_html: "¡Bien! ¡Tiene un nuevo pedido en %{distributor}!" + email_confirm_shop_number_html: "Confirmación del pedido #%{number}" + email_order_summary_item: "Artículo" + email_order_summary_quantity: "Cantidad" + email_order_summary_sku: "SKU" + email_order_summary_price: "Precio" + email_order_summary_subtotal: "Subtotal:" + email_order_summary_total: "Total:" + email_order_summary_includes_tax: "(incluye impuestos):" + email_payment_paid: PAGADO + email_payment_not_paid: NO PAGADO + email_payment_summary: Resumen de pago + email_payment_method: "Pagando con:" + email_so_placement_intro_html: "Tiene un nuevo pedido con %{distributor} " + email_so_placement_details_html: "Aquí están los detalles de su pedido para %{distributor} :" + email_so_placement_changes: "Desafortunadamente, no todos los productos que solicitó estaban disponibles. Las cantidades originales que solicitó aparecen tachadas a continuación." + email_so_payment_success_intro_html: "Se ha procesado un pago automático para su pedido desde %{distributor} ." + email_so_placement_explainer_html: "Esta orden se creó automáticamente para usted." + email_so_edit_true_html: "Puede realizar cambios hasta que los pedidos se cierren en %{orders_close_at}." + email_so_edit_false_html: "Puede ver detalles de este pedido en cualquier momento." + email_so_contact_distributor_html: "Si tiene alguna pregunta, puede contactar a %{distributor} a través de %{email}." + email_so_contact_distributor_to_change_order_html: "Has creado este pedido automáticamente. Puedes realizar cambios hasta que los pedidos se cierren en %{orders_close_at} contactando a %{distributor} a través de %{email}." + email_so_confirmation_intro_html: "Su pedido con %{distributor} ahora está confirmado" + email_so_confirmation_explainer_html: "Este pedido fue colocado automáticamente para usted, y ahora ha sido finalizado." + email_so_confirmation_details_html: "Aquí encontrará todo lo que necesita saber sobre su pedido en %{distributor} :" + email_so_empty_intro_html: "Intentamos realizar un nuevo pedido con %{distributor} , pero tuvimos algunos problemas ..." + email_so_empty_explainer_html: "Lamentablemente, ninguno de los productos que ordenó estaba disponible, por lo que no se realizó ningún pedido. Las cantidades originales que solicitó aparecen tachadas a continuación." + email_so_empty_details_html: "Aquí están los detalles del pedido no realizado para %{distributor} :" + email_so_failed_payment_intro_html: "Intentamos procesar un pago, pero tuvimos algunos problemas ..." + email_so_failed_payment_explainer_html: "El pago de su suscripción con %{distributor} ha fallado debido a un problema con su tarjeta de crédito. %{distributor} ha recibido notificación de este pago fallido." + email_so_failed_payment_details_html: "Aquí están los detalles del fallo proporcionados por la plataforma de pago:" + email_shipping_delivery_details: Detalles de entrega + email_shipping_delivery_time: "Entregar en:" + email_shipping_delivery_address: "Dirección de entrega:" + email_shipping_collection_details: Detalles de recolección + email_shipping_collection_time: "Listo para la recolección:" + email_shipping_collection_instructions: "Instrucciones de recolección:" + email_special_instructions: "Sus notas:" + email_signup_greeting: ¡Hola! + email_signup_welcome: "¡Bienvenido a %{sitename}!" + email_signup_confirmed_email: "Gracias por confirmar su correo electrónico." + email_signup_shop_html: "Ahora puedes iniciar sesión en %{link}." + email_signup_text: "Gracias por unirse a la red. Si es un comprador, ¡esperamos presentarle a muchos agricultores, grupos de consumo y comida deliciosa! Si es un productor o forma parte de una organización de alimentos, estamos emocionados de que forme parte de la red." + email_signup_help_html: "Agradecemos todas tus preguntas y retroalimentación; puedes usar el botón de Enviar retroalimenación en el sitio o escribir un correo electrónico a %{email}" + invite_email: + greeting: "¡Hola!" + invited_to_manage: "Ha sido invitado a administrar %{enterprise} en %{instance}." + confirm_your_email: "Debería haber recibido o recibirá pronto un correo electrónico con un enlace de confirmación. No podrá acceder al perfil de %{enterprise} hasta que haya confirmado su correo electrónico." + set_a_password: "Luego se le pedirá que establezca una contraseña antes de poder administrar la organización." + mistakenly_sent: "¿No está seguro de por qué ha recibido este correo electrónico? Por favor, póngase en contacto con %{owner_email} para más información." + producer_mail_greeting: "Estimada" + producer_mail_text_before: "Ahora tenemos todas los pedidos de las consumidoras para la siguiente ronda." + producer_mail_order_text: "Se muestra un resumen de los pedidos de tus productos:" + producer_mail_delivery_instructions: "Instrucciones de recogida/entrega de inventario:" + producer_mail_signoff: "Gracias y hasta pronto" + shopping_oc_closed: Los pedidos están cerrados + shopping_oc_closed_description: "Por favor espere hasta que el próximo ciclo abra (o contactanos de forma directa para ver si podemos aceptar algunos pedidos tardíos)" + shopping_oc_last_closed: "El último ciclo cerró hace %{distance_of_time}" + shopping_oc_next_open: "El próximo ciclo abrirá en %{distance_of_time}" + shopping_oc_select: "Seleccionar" + shopping_tabs_home: "Inicio" + shopping_tabs_shop: "Tienda" + shopping_tabs_about: "Acerca de" + shopping_tabs_contact: "Contacto" + shopping_contact_address: "Dirección" + shopping_contact_web: "Contacto" + shopping_contact_social: "Seguir" + shopping_groups_part_of: "es parte de:" + shopping_producers_of_hub: "productores de %{hub}:" + enterprises_next_closing: "Los pedidos se cerrarán" + enterprises_ready_for: "Listo para" + enterprises_choose: "Hay más de un ciclo abierto. Escoge en cuál quieres realizar el pedido:" + maps_open: "Abierto" + maps_closed: "Cerrado" + hubs_buy: "Comprar:" + hubs_shopping_here: "Comprando aquí" + hubs_orders_closed: "Pedidos cerrados" + hubs_profile_only: "Solo perfil" + hubs_delivery_options: "Opciones de entrega" + hubs_pickup: "Recoger" + hubs_delivery: "Entrega" + hubs_producers: "Nuestros productores" + hubs_filter_by: "Filtrar por" + hubs_filter_type: "Tipo" + hubs_filter_delivery: "Entrega" + hubs_filter_property: "Propiedad" + hubs_matches: "¿Quiso decir?" + hubs_intro: Compra en tu localidad + hubs_distance: Más cercano a + hubs_distance_filter: "Muéstrame tiendas cerca de %{location}" + shop_changeable_orders_alert_html: + one: Su pedido con %{shop} / %{order} está abierto para revisión. Puede realizar cambios hasta %{oc_close}. + other: 'Usted tiene %{count} pedidos con %{shop} actualmente abiertos para revisión. Puede realizar cambios hasta %{oc_close}. ' + orders_changeable_orders_alert_html: Este pedido ha sido confirmado, pero puede realizar cambios hasta %{oc_close}. + products_clear_all: Limpiar todo + products_showing: "Mostrando:" + products_or: "Ó" + products_with: con + products_search: "Buscar por producto o productor" + products_loading: "Cargando productos..." + products_updating_cart: "Actualizando su carrito..." + products_cart_empty: "Carrito vacío" + products_edit_cart: "Editar su carrito" + products_from: desde + products_change: "No hay cambios para guardar." + products_update_error: "No se ha podido guardar por los siguientes errores:" + products_update_error_msg: "No se ha podido guardar." + products_update_error_data: "Error al guardar datos no válidos:" + products_changes_saved: "Cambios guardados." + search_no_results_html: "Lo sentimos, no hay resultados para %{query}. ¿Intentar otra búsqueda?" + components_profiles_popover: "Los perfiles no tienen una tienda en Open Food Network, pero pueden tener su propia tienda física o en línea en otro lugar" + components_profiles_show: "Mostrar perfiles" + components_filters_nofilters: "Sin filtros" + components_filters_clearfilters: "Limpiar todos los filtros" + groups_title: Grupos + groups_headline: Grupos / regiones + groups_text: "Cada productor es único. Cada organización tiene algo diferente que ofrecer. Nuestros grupos son colectivos de productores, centros de acopio y distribuidores que comparten valores agroecológicos. Esto hace que su experiencia de compra sea más fácil." + groups_search: "Buscar nombre o palabra clave" + groups_no_groups: "No se encontraron grupos" + groups_about: "Acerca de nosotros" + groups_producers: "Nuestros productores" + groups_hubs: "Nuestros Grupos de Consumo" + groups_contact_web: Contacto + groups_contact_social: Seguir + groups_contact_address: Dirección + groups_contact_email: Envíenos un correo electrónico + groups_contact_website: Visite nuestro sitio web + groups_contact_facebook: Síganos en Facebook + groups_signup_title: Registrarse como un grupo + groups_signup_headline: Registro de grupos + groups_signup_intro: "Somos una asombrosa plataforma de mercadeo colaborativo, la forma más sencilla para que sus miembros e interesados encuentren nuevos mercados. No tenemos fines de lucro, somos asequibles y simples." + groups_signup_email: Envíenos un correo electrónico + groups_signup_motivation1: Nosotros transformamos sistemas de comida de forma justa. + groups_signup_motivation2: Es por lo que salimos de la cama cada día. Somos una organización sin fines de lucro global, basada en código de fuente abierta. Jugamos de forma justa. Siempre puede confiar en nosotros. + groups_signup_motivation3: Sabemos que tiene grandes ideas, y queremos ayudar. Compartiremos nuestro conocimiento, redes y recursos. Sabemos que el aislamiento no crea cambio, entonces nos asociaremos con usted. + groups_signup_motivation4: Nos reunimos con usted en donde esté. + groups_signup_motivation5: Quizás eres un grupo de consumo, productora o distribuidora u otra organización. + groups_signup_motivation6: Cualquiera que sea su rol en el movimiento de comida local, estamos listos para ayudar. De cualquier forma en que se pregunte cómo se vería Open Food Network o qué está haciendo en su parte del mundo, empecemos la conversación. + groups_signup_motivation7: Hacemos que los movimientos alimenticios tengan más sentido. + groups_signup_motivation8: Necesita activar y habilitar sus redes. Le ofrecemos una plataforma para conversación y acción. Necesita involucramiento real. Le ayudaremos a alcanzar todos los actores, todos los interesados, todos los sectores. + groups_signup_motivation9: Necesita recursos. Le brindaremos todas nuestras experiencias para portar. Necesita cooperación. Lo conectaremos mejor a una red global de pares. + groups_signup_pricing: Cuenta de grupo + groups_signup_studies: Casos de estudio + groups_signup_contact: ¿Listo para discutir? + groups_signup_contact_text: "Póngase en conta para descubrir qué puede hacer OFN por usted:" + groups_signup_detail: "Aquí está el detalle." + login_invalid: "Correo electrónico o contraseña inválidos" + modal_hubs: "Hubs" + modal_hubs_abstract: ¡Nuestros Grupos de Consumo son el punto de contacto entre usted y la gente que hace su comida! + modal_hubs_content1: Puede buscar un grupo de consumo conveniente por ubicación o nombre. Algunos grupos de consumo tienen múltiples puntos en loa que puede recoger las compras, y algunos también brindan opciones de entrega a domicilio. Cada Grupo de Consumo es un punto de venta con operaciones de negocio y logística independientes, entonces puede esperar diferencias entre Grupos de Consumo. + modal_hubs_content2: Sólo puedes comprar en un grupo de consumo a la vez. + modal_groups: "Grupos / Regiones" + modal_groups_content1: Estas son las organizaciones y relaciones entre grupos de consumo que conforman el Open Food Network. + modal_groups_content2: Algunos grupos están organizados por ubicación, otros por afinidades no geográficas. + modal_how: "Cómo funciona" + modal_how_shop: Comprar en Open Food Network + modal_how_shop_explained: ¡Buscar un grupo de consumo cerca de ti para empezar a comprar! Puedes expandir cada grupo de consumo para ver qué tipos de productos están disponibles, y hacer clic para empezar a comprar. (Sólo puedes comprar en un grupo de consumo a la vez.) + modal_how_pickup: Recogida, entrega y gastos de envío + modal_how_pickup_explained: Algunos grupos de consumo hacen entregas hasta su puerta, mientras otros requieren que recojas las compras. Puedes ver que opciones están disponibles en su página de inicio, y seleccionar cuál te gustaría en las páginas de compras y revisión. Las entregas costarán más, y el precio cambia entre grupos de consumo. Cada grupo es un punto de venta con operaciones y logística independientes, las diferencias son normales y deseables. + modal_how_more: Aprender más + modal_how_more_explained: "Si quieres saber más acerca de Open Food Network, cómo trabajamos y nos organizamos, visita:" + modal_producers: "Productores" + modal_producers_explained: "Nuestras productoras hacen todos los deliciosos alimentos que puedes comprar en Open Food Network." + producers_about: Acerca de nosotros + producers_buy: Comprar para + producers_contact: Contacto + producers_contact_phone: Llamar + producers_contact_social: Seguir + producers_buy_at_html: "Comprar productos de %{enterprise} en:" + producers_filter: Filtrar por + producers_filter_type: Tipo + producers_filter_property: Propiedad + producers_title: Productores + producers_headline: Encuentra productoras locales + producers_signup_title: Registrarse como productora + producers_signup_headline: Productoras de alimentos, empoderadas. + producers_signup_motivation: Venda sus alimentos y cuente sus historias en distintos nuevos mercados. Ahorre tiempo y dinero en costos administrativos. Apoyamos la innovación sin el riesgo. Hemos nivelado el campo de juego. + producers_signup_send: Únase ahora + producers_signup_enterprise: Cuentas de organización + producers_signup_studies: Historias de nuestros productores. + producers_signup_cta_headline: ¡Únase ahora! + producers_signup_cta_action: Únase ahora + producers_signup_detail: Aquí esta el detalle. + products_item: Artículo + products_description: Descripción + products_variant: Variante + products_quantity: Cantidad + products_available: ¿Disponible? + products_producer: "Productora" + products_price: "Precio" + name_or_sku: "NOMBRE O CÓDIGO SKU" + register_title: Registro + sell_title: "Registro" + sell_headline: "¡Consíguelo en Open Food Network!" + sell_motivation: "Muestra tus preciosos alimentos." + sell_producers: "Productoras" + sell_hubs: "Hubs" + sell_groups: "Grupos" + sell_producers_detail: "Crea tu perfil en OFN en cuestión de minutos. En cualquier momento puedes actualizar tu perfil a una tienda en línea y vender tus productos directamente a los consumidores." + sell_hubs_detail: "Crea un perfil para tu organización en OFN. En cualquier momento puedes actualizar tu perfil a una tienda de varias productoras." + sell_groups_detail: "Crea un directorio personalizado de organizaciones (productoras u otras organizaciones) para tu región o para tu organización." + sell_user_guide: "Descubre mucho más en la guía de usuario." + sell_listing_price: "Listado en la OFN es gratis. Abrir y administrar una tienda en OFN es gratis hasta $ 500 en ventas mensuales. Si vende más, puede elegir la contribución de su comunidad entre el 1% y el 3% de las ventas. Para obtener más detalles sobre los precios, visite la sección Plataforma de software a través del enlace Acerca de en el menú superior." + sell_embed: "También podemos incrustar una tienda OFN en tu propia web personalizada o crear un sitio web de la red local a medida para su región." + sell_ask_services: "Pregúntanos sobre los servicios de OFN" + shops_title: Tiendas + shops_headline: Compras, transformadas. + shops_text: Los alimentos crecen en ciclos, los agricultores cosechan en ciclos, y nosotros pedimos la comida en ciclos. Si encuentras un ciclo de pedido cerrado, vuelve a visitarlo pronto. + shops_signup_title: Registrarse como un grupo de consumo + shops_signup_headline: Grupos de Consumo, sin límites. + shops_signup_motivation: Cualquiera que sea su modelo, lo apoyamos. De cualquier forma que cambie, estamos con usted. Somos una organización sin findes de lucro, independiente, y de código abierto. Somos los socios de software con los que ha soñado. + shops_signup_action: Únase ahora + shops_signup_pricing: Cuentas de organización + shops_signup_stories: Historias de nuestros grupos de consumo. + shops_signup_help: Estamos listos para ayudar. + shops_signup_help_text: Usted necesita un mejor retorno. Usted necesita nuevos compradores y socios de logística. Usted necesita que su historia sea contada a través de ventas al por mayor, al detalle y en la mesa de la cocina. + shops_signup_detail: Aquí está el detalle. + orders: Pedidos + orders_fees: Comisiones... + orders_edit_title: Carrito de compras + orders_edit_headline: Su carrito de compras + orders_edit_time: Pedido listo para + orders_edit_continue: Continuar comprando + orders_edit_checkout: Validar + orders_form_empty_cart: "Vaciar carrito" + orders_form_subtotal: Subtotal de productos + orders_form_admin: Administrar y Gestionar + orders_form_total: Total + orders_oc_expired_headline: Los pedidos están cerrados para este ciclo + orders_oc_expired_text: "Lo sentimos, ¡los pedidos para este ciclo cerraron hace %{time}! Contacta con tu grupo de consumo directamente para ver si pueden aceptar pedidos tardíos." + orders_oc_expired_text_others_html: "Lo sentimos, ¡los pedidos para este ciclo cerraron hace %{time}! Contacta con tu grupo de consumo directamente para ver si pueden aceptar pedidos tardíos %{link}." + orders_oc_expired_text_link: "o visitar otros ciclos de pedidos disponibles en este grupo de consumo" + orders_oc_expired_email: "Correo electrónico:" + orders_oc_expired_phone: "Teléfono:" + orders_show_title: Confirmación del pedido + orders_show_time: Pedido listo en + orders_show_order_number: "Pedido #%{number}" + orders_show_cancelled: Cancelado + orders_show_confirmed: Confirmado + orders_your_order_has_been_cancelled: "Su pedido ha sido cancelado" + orders_could_not_cancel: "Lo sentimos, no se pudo cancelar el pedido" + orders_cannot_remove_the_final_item: "No se puede quitar el último artículo de un pedido, en su lugar, por favor cancele el pedido." + orders_bought_items_notice: + one: "Un elemento adicional ya está confirmado para este ciclo de pedido" + other: "%{count} artículos adicionales ya confirmados para este ciclo de pedido" + orders_bought_edit_button: Editar artículos confirmados + orders_bought_already_confirmed: "* ya confirmados" + orders_confirm_cancel: Seguro que desea cancelar este pedido? + order_processed_successfully: "Su pedido ha sido procesado con éxito." + products_cart_distributor_choice: "Distribuidora para tu pedido:" + products_cart_distributor_change: "Su distribuidora para este pedido se cambiará a %{name} si agregas este producto al carrito." + products_cart_distributor_is: "Tu distribuidora para este pedido es %{name}." + products_distributor_error: "Completa tu pedido en %{link} antes de comprar con otra distribuidora." + products_oc: "Ciclo de pedido para tu pedido:" + products_oc_change: "Tu ciclo de pedido para este pedido será cambiado a %{name} si agregas este producto al carrito." + products_oc_is: "Tu ciclo de pedido para este pedido es %{name}." + products_oc_error: "Completa este pedido de %{link} antes de comprar en un ciclo de pedido diferente." + products_oc_current: "tu ciclo de de pedido actual" + products_max_quantity: Cantidad máxima + products_distributor: Distribuidor + products_distributor_info: Cuando selecciones una distribuidora para tu pedido, tu dirección y tiempo de recolección se mostrarán aquí. + password: Contraseña + remember_me: Recordarme + are_you_sure: "¿Está seguro?" + orders_open: Pedidos abiertos + closing: "Cerrando " + going_back_to_home_page: "Le estamos llevando de vuelta a la página de inicio" + creating: Creando + updating: Actualizando + failed_to_create_enterprise: "Error al crear tu organización." + failed_to_create_enterprise_unknown: "Error al crear tu organización.\nAsegúrate de haber rellenado todos los campos." + failed_to_update_enterprise_unknown: "Error al actualizar tu organización.\nAsegúrate de haber rellenado todos los campos." + enterprise_confirm_delete_message: "Esto también eliminará el %{product} que suministra esta organización. ¿Estás seguro de que quieres continuar?" + order_not_saved_yet: "Su orden aun no ha sido guardada. ¡Denos unos cuantos segundos para terminar!" + filter_by: "Fitrar por" + hide_filters: "Esconder filtros" + one_filter_applied: "1 filtro aplicado" + x_filters_applied: "filtros aplicados" + submitting_order: "Enviando su orden: espere" + confirm_hub_change: "¿Está seguro? Esto cambiará tu grupo de consumo seleccionado y eliminará cualquier artículo en tu carrito de la compra." + confirm_oc_change: "¿Está seguro? Esto cambiará su ciclo de orden seleccionado y eliminará cualquier artículo en su carrito de compras." + location_placeholder: "Escriba una ubicación..." + error_required: "no puede estar vacío" + error_number: "debe ser un número" + error_email: "debe ser una dirección de correo electrónico" + error_not_found_in_database: "%{name} no se encuentra en la base de datos" + error_not_primary_producer: "%{name} no está habilitado como productora" + error_no_permission_for_enterprise: "\"%{name}\": no tiene permiso para administrar productos para esta organización" + item_handling_fees: "Comisiones de manejo de artículos (incluída en el total de artículos)" + january: "Enero" + february: "Febrero" + march: "Marzo" + april: "Abril" + may: "Mayo" + june: "Junio" + july: "Julio" + august: "Agosto" + september: "Setiembre" + october: "Octubre" + november: "Noviembre" + december: "Diciembre" + email_not_found: "Dirección de correo electrónico no encontrada" + email_unconfirmed: "Debe confirmar su dirección de correo electrónico antes de poder restablecer su contraseña." + email_required: "Debe brindar una dirección de correo electrónico" + logging_in: "Espere un momento, le vamos a iniciar una sesión" + signup_email: "Su correo electrónico" + choose_password: "Elige una contraseña" + confirm_password: "Confirmar contraseña" + action_signup: "Registrarse ahora" + forgot_password: "¿Se le olvidó su contraseña?" + password_reset_sent: "¡Le enviamos un correo electrónico con instrucciones para restaurar la contraseña!" + reset_password: "Restablecer contraseña" + update_and_recalculate_fees: "Actualizar y recalcular comisiones" + registration: + steps: + introduction: + registration_greeting: "¡Hola!" + registration_intro: "Ahora puedes crear un perfil para tu Productora o Grupo de Consumo" + registration_checklist: "¿Qué necesito?" + registration_time: "5-10 minutos" + registration_enterprise_address: "Dirección de la organización" + registration_contact_details: "Detalles de contacto principal" + registration_logo: "Su imagen de logo" + registration_promo_image: "Imagen en formato apaisado para su perfil" + registration_about_us: "Texto 'Acerca de nosotras'" + registration_outcome_headline: "¿Para qué sirve?" + registration_outcome1_html: "Su perfil le ayuda a las personas a encontrarle y contactarle en la Open Food Network." + registration_outcome2: "Use este espacio para contar la historia de tu organización, para ayudar a impulsar las conexiones a tu presencia social y en línea." + registration_outcome3: "También es el primer paso para empezar en Open Food Network, o abrir una tienda online." + registration_action: "¡Empecemos!" + details: + title: "Detalles" + headline: "Empecemos" + enterprise: "Ei! Primero necesitamos saber un poco sobre tu organización:" + producer: "Primero necesitamos saber un poco sobre tu productora:" + enterprise_name_field: "Nombre de la organización:" + producer_name_field: "Nombre de la productora:" + producer_name_field_placeholder: "p.ej. La impresionante granja de Charlie" + producer_name_field_error: "Elija un nombre único para su organización." + address1_field: "Dirección Línea 1:" + address1_field_placeholder: "p.ej. Passeig Sant Joan" + address1_field_error: "Introduce una dirección" + address2_field: "Dirección línea 2:" + suburb_field: "Barrio:" + suburb_field_placeholder: "e.g. Gràcia" + suburb_field_error: "Introduce un barrio" + postcode_field: "Código postal:" + postcode_field_placeholder: "p.ej. 08025" + postcode_field_error: "Requiere un código postal" + state_field: "Región:" + state_field_error: "Región requerida" + country_field: "País:" + country_field_error: "Por favor selecciona un país" + contact: + title: "Contacto" + who_is_managing_enterprise: "¿Quién es responsable de administrar %{enterprise}?" + contact_field: "Contacto principal" + contact_field_placeholder: "Nombre de contacto" + contact_field_required: "Debes introducir un contacto principal." + phone_field: "Número de teléfono" + phone_field_placeholder: "p.ej. 93 250 16 45" + type: + title: "Tipo" + headline: "Último paso para añadir %{enterprise}!" + question: "¿Eres una productora?" + yes_producer: "Si soy una productora" + no_producer: "No, no soy una productora" + producer_field_error: "Por favor elige uno. ¿Eres una productora?" + yes_producer_help: "Las productoras hacen cosas deliciosas para comer y/o beber. Eres una productora si lo cultivas, lo haces crecer, lo preparas, lo horneas, lo fermentas, lo ordeñas, ..." + no_producer_help: "Si no eres una productora, probablemente conozcas a alguien que venda o distribuya comida. También podrías convertirte en un grupo de consumo u otro tipo de organización." + create_profile: "Crear Perfil" + about: + title: "Acerca de" + headline: "¡Seguimos!" + message: "Ahora vamos a profundizar en los detalles acerca de" + success: "¡Éxito! %{enterprise} agregado a Open Food Network" + registration_exit_message: "Si sales de este asistente en cualquier etapa puedes continuar creando tu perfil yendo a la interfaz de administración." + enterprise_description: "Descripción corta" + enterprise_description_placeholder: "Una frase corta que describa tu organización" + enterprise_long_desc: "Descripción larga" + enterprise_long_desc_placeholder: "Esta es tu oportunidad de contar la historia de tu organización - ¿qué la hace diferente? Sugerimos mantener la descripción en menos de 600 caracteres o 150 palabras." + enterprise_long_desc_length: "%{num} caracteres / recomentdamos hasta 600" + enterprise_abn: "NIF" + enterprise_abn_placeholder: "ej. 99 123 456 789" + enterprise_acn: "ACN" + enterprise_acn_placeholder: "ej. 123 456 789" + enterprise_tax_required: "Necesita seleccionar algo." + images: + title: "Imágenes" + headline: "¡Ya casi lo tenemos!" + description: "¡Sube algunas fotografías así el perfil se verá mucho mejor! :)" + uploading: "Subiendo..." + continue: "Continuar" + back: "Atrás" + logo: + select_logo: "Paso 1. Seleccione una imagen de logotipo" + logo_tip: "Consejo: Imágenes cuadradas funcionan mejor, de preferencia por lo menos de 300×300px" + logo_label: "Escoja una imagen de logo" + logo_drag: "Arrastre y suelte su logo aquí" + review_logo: "Paso 2. Revise su logo" + review_logo_tip: "Consejo: para mejores resultados, su logo debería llenar el espacio disponible" + logo_placeholder: "El logo aparecerá aquí para ser revisado cuando se haya subido" + promo: + select_promo_image: "Paso 3. Seleccione una imagen promocional" + promo_image_tip: "Consejo: Se muestra como una pancarta, el tamaño preferido es 1200×260px" + promo_image_label: "Escoja una imagen promocional" + promo_image_drag: "Arrastre y suelte su imagen promocional aquí" + review_promo_image: "Paso 4. Revise su pancarta promocional" + review_promo_image_tip: "Consejo: para mejores resultados, su imagen promocional debería llenar el espacio disponible" + promo_image_placeholder: "El logo aparecerá aquí para ser revisado cuando se haya subido" + social: + title: "Social" + enterprise_final_step: "¡Paso final!" + enterprise_social_text: "¿Cómo puede la gente encontrar a %{enterprise} en línea?" + website: "Sitio web" + website_placeholder: "eg. openfoodnetwork.org.au" + facebook: "Facebook" + facebook_placeholder: "eg. www.facebook.com/NombreDePáginaAquí" + linkedin: "LinkedIn" + linkedin_placeholder: "eg. www.linkedin.com/SuNombreAquí" + twitter: "Twitter" + twitter_placeholder: "usuario_de_twitter" + instagram: "Instagram" + instagram_placeholder: "usuario_de_instagram" + limit_reached: + headline: "¡Ay no!" + message: "¡Ha alcanzado el límite!" + text: "Has alcanzado el límite de organizaciones de las que puedes gestionar en " + action: "Regresar a la página de inicio" + finished: + headline: "¡Terminado!" + thanks: "Gracias por llenar los detalles de %{enterprise}." + login: "Puede cambiar o actualizar su negocio en cualquier etapa iniciando sesión en Open Food Network y yendo a Admin." + action: "Ir al Panel de Organización" + back: "Atrás" + continue: "Continuar" + action_or: "Ó" + enterprise_limit: Límite de la Organización + shipping_method_destroy_error: "Ese método de envío no puede ser eliminado ya que se hace referencia en un pedido: %{number}." + fees: "Comisiones" + item_cost: "Costo del artículo" + bulk: "Agrupar" + shop_variant_quantity_min: "mínimo" + shop_variant_quantity_max: "máximo" + follow: "Seguir" + shop_for_products_html: "Comprar productos de %{enterprise} en:" + change_shop: "Cambiar de tienda:" + shop_at: "Comprar en:" + price_breakdown: "Desglose de precios completo" + admin_fee: "Comisión de administración" + sales_fee: "Comisión de ventas" + packing_fee: "Comisión de empaquetado" + transport_fee: "Comisión de transporte" + fundraising_fee: "Comisión para recaptación de fondos" + price_graph: "Gráfico de precios" + included_tax: "Impuesto incluido" + balance: "Saldo" + transaction: "Transacción" + transaction_date: "Fecha" + payment_state: "Estado de pago" + shipping_state: "Estado del envío" + value: "Valor" + balance_due: "Saldo debido" + credit: "Crédito" + Paid: "Pagado" + Ready: "Listo" + ok: OK + not_visible: no visible + you_have_no_orders_yet: "No tienes pedidos todavía" + show_only_complete_orders: "Mostrar solo pedidos completados" + successfully_created: '%{resource} se ha creado exitosamente!' + successfully_removed: '%{resource} ha sido eliminado exitosamente!' + successfully_updated: '%{resource} ha sido actualizado exitosamente!' + running_balance: "Saldo actual" + outstanding_balance: "Saldo extraordinario" + admin_enterprise_relationships: "Permisos de la organización" + admin_enterprise_relationships_everything: "Marcar todos" + admin_enterprise_relationships_permits: "Permite" + admin_enterprise_relationships_seach_placeholder: "Buscar" + admin_enterprise_relationships_button_create: "Crear" + admin_enterprise_relationships_to: "para" + admin_enterprise_groups: "Grupos de organizaciones" + admin_enterprise_groups_name: "Nombre" + admin_enterprise_groups_owner: "Propietaria" + admin_enterprise_groups_on_front_page: "¿En la página principal?" + admin_enterprise_groups_enterprise: "Organizaciones" + admin_enterprise_groups_data_powertip: "El principal usuario responsable de este grupo." + admin_enterprise_groups_data_powertip_logo: "Este es el logo del grupo" + admin_enterprise_groups_data_powertip_promo_image: "Esta imagen se mostrará en la cabecera del perfil del Grupo" + admin_enterprise_groups_contact: "Contacto" + admin_enterprise_groups_contact_phone_placeholder: "ej. 98 7654 3210" + admin_enterprise_groups_contact_address1_placeholder: "ej. Carrer Torrent de l'Olla" + admin_enterprise_groups_contact_city: "Barrio" + admin_enterprise_groups_contact_city_placeholder: "ej. Barcelona" + admin_enterprise_groups_contact_zipcode: "Código Postal" + admin_enterprise_groups_contact_zipcode_placeholder: "ej. 08025" + admin_enterprise_groups_contact_state_id: "Provincia" + admin_enterprise_groups_contact_country_id: "País" + admin_enterprise_groups_web: "Recursos Web" + admin_enterprise_groups_web_twitter: "ej: the_prof" + admin_enterprise_groups_web_website_placeholder: "ej. www.truffles.com" + admin_order_cycles: "Ciclos de Pedidos del Admin" + open: "Abierta" + close: "Cerrar" + create: "Crear" + search: "Buscar" + supplier: "Proveedora" + product_name: "nombre del producto" + product_description: "Descripción del producto" + units: "Unidad de medida" + coordinator: "Coordinadora" + distributor: "Distribuidor" + enterprise_fees: "Comisiones de la Organización" + process_my_order: "Procesar mi pedido" + delivery_instructions: Instrucciones de Entrega + delivery_method: Método de entrega + fee_type: "Tipo de Comisión" + tax_category: "Categoría del impuesto" + calculator: "Calculadora" + calculator_values: "Calculadora de valores" + calculator_settings_warning: "Si está cambiando el tipo de calculadora, debe de salvar primero antes de editar las configuraciones de la calculadora" + flat_percent_per_item: "Porcentaje fijo (por artículo)" + flat_rate_per_item: "Tarifa plana (por artículo)" + flat_rate_per_order: "Tarifa plana (por pedido)" + flexible_rate: "Tarifa flexible" + price_sack: "Precio saco" + new_order_cycles: "Nuevos Ciclos de Pedidos" + new_order_cycle: "Nuevo Ciclo de Pedido" + select_a_coordinator_for_your_order_cycle: "Selecciona un coordinador para vuestro ciclo de pedido" + notify_producers: 'Notificar a las productoras' + edit_order_cycle: "Editar Ciclo de Pedido" + roles: "Roles" + update: "Actualizar" + delete: Borrar + add_producer_property: "Añadir propiedad de productora" + in_progress: "En Proceso" + started_at: "Empezó el" + queued: "En Cola" + scheduled_for: "Planificado para" + customers: "Consumidores" + please_select_hub: "Selecciona un Grupo" + loading_customers: "Cargando Consumidores" + no_customers_found: "No se encuentran consumidores" + go: "Ir" + hub: "Grupo de Consumo" + producer: "Productora" + product: "Producto" + price: "Precio" + on_hand: "Disponibles" + review: "Revisión" + save_changes: "Guardar Cambios" + order_saved: "Pedido Guardado" + no_products: No hay productos + spree_admin_overview_enterprises_header: "Mis Organizaciones" + spree_admin_overview_enterprises_footer: "GESTIONAR MIS ORGANIZACIONES" + spree_admin_enterprises_hubs_name: "Nombre" + spree_admin_enterprises_create_new: "CREAR NUEVA" + spree_admin_enterprises_shipping_methods: "Métodos de envío" + spree_admin_enterprises_fees: "Comisiones de la Organización" + spree_admin_enterprises_none_create_a_new_enterprise: "CREAR NUEVA ORGANIZACIÓN" + spree_admin_enterprises_none_text: "No tienes ninguna organización" + spree_admin_enterprises_tabs_hubs: "HUBS" + spree_admin_enterprises_producers_manage_products: "GESTIONAR PRODUCTOS" + spree_admin_enterprises_create_new_product: "CREAR UN NUEVO PRODUCTO" + spree_admin_single_enterprise_alert_mail_confirmation: "Confirma la dirección de email para" + spree_admin_single_enterprise_alert_mail_sent: "Te hemos enviado un mail a" + spree_admin_overview_action_required: "Acción Requerida" + spree_admin_overview_check_your_inbox: "Revisa tu bandeja de entrada para las siguientes instrucciones. Gracias!" + spree_admin_unit_value: Valor unidad + spree_admin_unit_description: Descripción de la unidad + spree_admin_variant_unit: Variante + spree_admin_variant_unit_scale: Escala de unidad + spree_admin_supplier: Proveedora + spree_admin_product_category: categoría del producto + spree_admin_variant_unit_name: Nombre de la variante + unit_name: "Nombre de la unidad" + change_package: "Cambiar Perfil" + spree_admin_single_enterprise_hint: "Sugerencia: Para permitir que la gente te encuentre, activa tu visibilidad" + spree_admin_eg_pickup_from_school: "p.ej. 'Recogida en la Cooperativa'" + spree_admin_eg_collect_your_order: "p.ej. 'Por favor recoge tu pedido en la Calle del Hormiguero nº3'" + spree_classification_primary_taxon_error: "La clasificación %{taxon} es la clasificación primaria de %{product} y no puede ser eliminada" + spree_order_availability_error: "El Distribuidor o el Ciclo de Pedido no pueden suministrar los productos en su carrito" + spree_order_populator_error: "Este Distribuidor o Ciclo de Pedido no puede suministrar todos los productos en tu carrito. Por favor, elige otro." + spree_order_populator_availability_error: "Este producto no está disponible por el distribuidor o Ciclo de Pedido elegido." + spree_distributors_error: "Se debe seleccionar al menos un Grupo" + spree_user_enterprise_limit_error: "^ %{email} no está autorizado a tener más organizaciones (el límite es %{enterprise_limit})." + spree_variant_product_error: Debes tener al menos una variante + your_profil_live: "Tu perfil online" + on_ofn_map: "en el mapa Open Food Network" + see: "Ver" + live: "En directo" + manage: "Gestionar" + resend: "Reenviar" + add_and_manage_products: "Añadir y gestionar productos" + add_and_manage_order_cycles: "Añadir y gestionar ciclos de pedidos" + manage_order_cycles: "Gestionar ciclos de pedidos" + manage_products: "Gestionar productos" + edit_profile_details: "Editar detalles del perfil" + edit_profile_details_etc: "Cambia tu descripción, imágenes, etc." + order_cycle: "Ciclo de Pedido" + order_cycles: "Ciclos de Pedidos" + enterprise_relationships: "Permisos de la organización" + remove_tax: "Eliminar impuesto" + first_name_begins_with: "El nombre comienza con" + last_name_begins_with: "El apellido comienza con" + enterprise_tos_link: "Enlace a los Términos del Servicio de la Organización" + enterprise_tos_message: "Queremos trabajar con personas que compartan nuestros objetivos y valores. Por ello, pedimos a las nuevas organizaciones que acepten" + enterprise_tos_link_text: "Términos del Servicio." + enterprise_tos_agree: "Estoy de acuerdo con los Términos del Servicio" + tax_settings: "Configuración de Impuestos" + products_require_tax_category: "Los productos requieren categoría de impuesto" + admin_shared_address_1: "Dirección" + admin_shared_address_2: "Dirección (cont.)" + admin_share_city: "Ciudad" + admin_share_zipcode: "Código Postal" + admin_share_country: "País" + admin_share_state: "Provincia" + hub_sidebar_hubs: "Hubs" + hub_sidebar_none_available: "Ninguno Disponible" + hub_sidebar_manage: "Gestionar" + hub_sidebar_at_least: "Al menos un grupo debe ser seleccionado" + hub_sidebar_blue: "azul" + hub_sidebar_red: "rojo" + report_customers_distributor: "Distribuidor" + report_customers_supplier: "Proveedora" + report_customers_cycle: "Ciclo de Pedido" + report_customers_type: "Tipo de Reporte" + report_customers_csv: "Descargar como CSV" + report_producers: "Productoras:" + report_type: "Tipo de Reporte:" + report_hubs: "Hubs: " + report_payment: "Métodos de Pago:" + report_distributor: "Distribuidora:" + report_payment_by: 'Pagos por Tipo' + report_itemised_payment: 'Pagos Totales Detallados' + report_payment_totals: 'Pagos Totales' + report_all: 'Todo' + report_order_cycle: "Ciclo de Pedido:" + report_enterprises: "Organizaciones:" + report_users: "Usuarias:" + report_tax_rates: Porcentajes de los Impuestos + report_tax_types: Tipos de Impuestos + report_header_order_cycle: Ciclo de Pedido + report_header_user: Usuaria + report_header_email: Email + report_header_status: Estado + report_header_comments: Comentarios + report_header_first_name: Nombre + report_header_last_name: Apellido + report_header_phone: Teléfono + report_header_suburb: Barrio + report_header_address: Dirección + report_header_billing_address: Dirección de Facturación + report_header_relationship: Relación + report_header_hub: Grupo + report_header_hub_address: Dirección del Grupo + report_header_to_hub: Al Grupo + report_header_hub_code: Código de Grupo + report_header_code: Código + report_header_paid: ¿Pagado? + report_header_delivery: ¿Entregado? + report_header_shipping: Envío + report_header_shipping_method: Método de envío + report_header_shipping_instructions: Instrucciones de envío + report_header_ship_street: Calle de envío + report_header_ship_street_2: Calle de envío 2 + report_header_ship_city: Ciudad de envío + report_header_ship_postcode: Código postal de envío + report_header_ship_state: Provincia de envío + report_header_billing_street: Calle de facturación + report_header_billing_street_2: Calle de facturación 2 + report_header_billing_street_3: Calle de facturación 3 + report_header_billing_street_4: Calle de facturación 4 + report_header_billing_city: Ciudad de facturación + report_header_billing_postcode: Código postal de facturación + report_header_billing_state: Provincia de facturación + report_header_incoming_transport: Transporte entrante + report_header_special_instructions: instrucciones especiales + report_header_order_number: Número de pedido + report_header_date: Fecha + report_header_confirmation_date: Fecha de confirmación + report_header_tags: Tags + report_header_items: Artículos + report_header_items_total: "Artículos en total %{currency_symbol}" + report_header_taxable_items_total: "Artículos con Impuestos en Total (%{currency_symbol})" + report_header_sales_tax: "Impuesto sobre las Ventas (%{currency_symbol})" + report_header_delivery_charge: "Gastos de Envío (%{currency_symbol})" + report_header_tax_on_delivery: "Impuestos sobre la entrega (%{currency_symbol})" + report_header_tax_on_fees: "Impuesto sobre las comisiones (%{currency_symbol})" + report_header_total_tax: "Total Impuestos (%{currency_symbol})" + report_header_enterprise: Organización + report_header_customer: Cliente + report_header_customer_code: Código del cliente + report_header_product: Producto + report_header_product_properties: Propiedades del producto + report_header_quantity: Cantidad + report_header_max_quantity: Cantidad máxima + report_header_variant: Variante + report_header_variant_value: Valor de la variante + report_header_variant_unit: Unidad Variante + report_header_total_available: Total disponible + report_header_unallocated: Sin asignar + report_header_max_quantity_excess: Cantidad máxima + report_header_taxons: Clasificación + report_header_supplier: Proveedor + report_header_producer: Productora + report_header_producer_suburb: Barrio Productora + report_header_unit: Unidad + report_header_group_buy_unit_quantity: Agrupar por cantidad unidad + report_header_cost: Coste + report_header_shipping_cost: Coste del envío + report_header_curr_cost_per_unit: Coste por unidad actual + report_header_total_shipping_cost: Coste total del envío + report_header_payment_method: Método de pago + report_header_sells: Vende + report_header_visible: Visible + report_header_price: Precio + report_header_unit_size: Unidad de medida + report_header_distributor: Distribuidora + report_header_distributor_address: Dirección del distribuidor + report_header_distributor_city: Ciudad del distribuidor + report_header_distributor_postcode: Código postal del distribuidor + report_header_delivery_address: Dirección de entrega + report_header_delivery_postcode: Código postal de entrega + report_header_bulk_unit_size: Tamaño de la unidad a granel + report_header_weight: Peso + report_header_sum_total: Suma Total + report_header_date_of_order: Fecha de pedido + report_header_amount_owing: Cantidad adeudada + report_header_amount_paid: Cantidad pagada + report_header_units_required: Unidades requeridas + report_header_remainder: Recordatorio + report_header_order_date: Fecha de pedido + report_header_order_id: ID de Pedido + report_header_item_name: Nombre del artículo + report_header_temp_controlled_items: ¿Artículos de temperatura controlada? + report_header_customer_name: Nombre del cliente + report_header_customer_email: Correo electrónico del cliente + report_header_customer_phone: Teléfono del cliente + report_header_customer_city: Ciudad del cliente + report_header_payment_state: Estado del pago + report_header_payment_type: Tipo de pago + report_header_item_price: "Artículo (%{currency})" + report_header_item_fees_price: "Artículo + Comisiones (%{currency})" + report_header_admin_handling_fees: "Administración y Gestión (%{currency})" + report_header_ship_price: "Envío (%{currency})" + report_header_pay_fee_price: "Comisión de pago (%{currency})" + report_header_total_price: "Total (%{currency})" + report_header_product_total_price: "Producto Total (%{currency})" + report_header_shipping_total_price: "Total envíos (%{currency})" + report_header_outstanding_balance_price: "Saldo pendiente (%{currency})" + report_header_eft_price: "Transferencia (%{currency})" + report_header_paypal_price: "PayPal (%{currency})" + report_header_sku: SKU + report_header_amount: Cantidad + report_header_balance: Saldo + report_header_total_cost: "Coste total" + report_header_total_ordered: Total pedidos + report_header_total_max: Total Max + report_header_total_units: Unidades totales + report_header_sum_max_total: "Suma Máx. Total" + report_header_total_excl_vat: "Total Impuestos excl. (%{currency_symbol})" + report_header_total_incl_vat: "Total Impuestos incl. (%{currency_symbol})" + report_header_temp_controlled: ¿Control de Temperatura? + report_header_is_producer: ¿Productora? + report_header_not_confirmed: No confirmado + report_header_gst_on_income: IVA sobre Ingresos + report_header_gst_free_income: Ingresos sin IVA + report_header_total_untaxable_produce: Total productos sin impuestos + report_header_total_taxable_produce: Total productos con impuestos + report_header_total_untaxable_fees: Total comisiones no imponibles (sin impuestos) + report_header_total_taxable_fees: Total de impuestos imponibles (impuestos incluidos) + report_header_delivery_shipping_cost: Gastos de envío (impuestos incluidos) + report_header_transaction_fee: Comisión por transacción (sin impuestos) + report_header_total_untaxable_admin: Total de ajustes administrativos no tributables (sin impuestos) + report_header_total_taxable_admin: Total de ajustes tributarios de administración (impuestos incluidos) + initial_invoice_number: "Número inicial de Factura:" + invoice_date: "Fecha de la factura:" + due_date: "Fecha de vencimiento:" + account_code: "Código de la Cuenta:" + equals: "Iguales" + contains: "Contiene" + discount: "Descuento" + filter_products: "Filtrar Poductos" + delete_product_variant: "¡La última variedad no puede ser borrada!" + progress: "Progreso" + saving: "Guardando.." + success: "completado" + failure: "fallo" + unsaved_changes_confirmation: "Los cambios no guardados se perderán. ¿Continuar igualmente? " + one_product_unsaved: "Los cambios de un producto aún no se han guardado." + products_unsaved: "Los cambios de %{n} productos aún no se han guardado." + is_already_manager: "¡Ya eres un administrador!" + no_change_to_save: "No hay cambios para guardar" + user_invited: "%{email} ha sido invitado a administrar esta organización" + add_manager: "Agrega un usuario existente" + users: "Usuarias" + about: "Acerca de" + images: "Imagenes" + web: "Web" + primary_details: "Detalles Principales" + adrdress: "Dirección" + contact: "Contacto" + social: "Social" + business_details: "Detalles de la Organización" + properties: "Propiedades" + shipping: "Envío" + shipping_methods: "Métodos de envío" + payment_methods: "Métodos de Pago" + payment_method_fee: "Comisión de Transacción" + payment_processing_failed: "No se pudo procesar el pago, por favor verifique los detalles que introdujo" + payment_method_not_supported: "Ese método de pago no está soportado. Por favor elije otro." + payment_updated: "Pago actualizado" + inventory_settings: "Configuración del Inventario" + tag_rules: "Reglas de las Etiquetas" + shop_preferences: "Configuración de la tienda" + enterprise_fee_whole_order: Pedido completo + enterprise_fee_by: "%{type} comisión por %{role} %{enterprise_name}" + validation_msg_relationship_already_established: "^Esta relación ya existe." + validation_msg_at_least_one_hub: "^Al menos se debe seleccionar un grupo de consumo" + validation_msg_tax_category_cant_be_blank: "^La Categoría del Impuesto no puede estar vacía" + validation_msg_is_associated_with_an_exising_customer: "está asociado con un cliente existente" + content_configuration_pricing_table: "(TODO: tabla de precios)" + content_configuration_case_studies: "(TODO: Casos de Estudio)" + content_configuration_detail: "(TODO: Detalle)" + enterprise_name_error: "ya está en uso. Si esta es su organización y le gustaría reclamar la propiedad, o si desea negociar con esta organización, comuníquese con el gestor actual de este perfil al %{email}." + enterprise_owner_error: "^ %{email} no está autorizado a tener más organizaciones (el límite es %{enterprise_limit})." + enterprise_role_uniqueness_error: "^Este rol ya está presente." + inventory_item_visibility_error: Debe ser verdadero o falso + product_importer_file_error: "error: no se ha subido ningún archivo" + product_importer_spreadsheet_error: "No se pudo procesar el archivo: tipo de archivo inválido" + product_importer_products_save_error: No se guardó ningún producto con éxito + product_import_file_not_found_notice: 'Archivo no encontrado o no se pudo abrir' + product_import_no_data_in_spreadsheet_notice: 'No se encontraron datos en la hoja de cálculo' + order_choosing_hub_notice: Tu Grupo se ha seleccionado. + order_cycle_selecting_notice: Se ha seleccionado el ciclo de pedido. + adjustments_tax_rate_error: "^Comprueba que los impuestos para este ajuste es correcta." + active_distributors_not_ready_for_checkout_message_singular: >- + El Grupo %{distributor_names} aparece en un ciclo de pedido activo, pero no + tiene métodos de envío y pago válidos. Hasta que los configure, los clientes + no podrán comprar en este grupo. + active_distributors_not_ready_for_checkout_message_plural: >- + Los Grupos %{distributor_names} se listan los ciclos de pedido activos, pero + no tienen métodos de envío y pago válidos. Hasta que los configure, los clientes + no podrán comprar en estos concentradores. + enterprise_fees_update_notice: Las comisiones de tu Organización se han actualizado. + enterprise_register_package_error: "Seleccione un paquete" + enterprise_register_error: "No se pudo completar el registro para %{enterprise}" + enterprise_register_success_notice: "¡Felicidades! ¡Se ha completado el registro de %{enterprise}!" + enterprise_bulk_update_success_notice: "Organizaciones actualizadas con éxito" + enterprise_bulk_update_error: 'Error en la actualización' + enterprise_shop_show_error: "La tienda que busca no existe o esta inactiva en OFN. por favor visita otras tiendas." + order_cycles_create_notice: 'Se ha creado el ciclo de pedido.' + order_cycles_update_notice: 'Se ha actualizado su ciclo de pedido.' + order_cycles_bulk_update_notice: 'Los ciclos de pedido han sido actualizados.' + order_cycles_clone_notice: "Su ciclo de pedido %{name} ha sido clonado." + order_cycles_email_to_producers_notice: 'Los correos electrónicos que se enviarán a las productoras se han puesto en cola para enviarlos.' + order_cycles_no_permission_to_coordinate_error: "Ninguna de tus organizaciones tiene permiso para coordinar un ciclo de pedido" + order_cycles_no_permission_to_create_error: "No tienes permiso para crear un ciclo de pedido coordinado por esta empresa." + back_to_orders_list: "Volver a la lista de pedidos" + no_orders_found: "No se encontraron pedidos" + order_information: "información del pedido" + date_completed: "Fecha completada" + amount: "Cantidad" + state_names: + ready: Listo + pending: Pendiente + shipped: Enviado + js: + saving: 'Guardando...' + changes_saved: 'Cambios guardados.' + save_changes_first: Guarda los cambios primero. + all_changes_saved: Todos los cambios guardados + unsaved_changes: Tiene cambios sin guardar + all_changes_saved_successfully: Todos los cambios guardados correctamente + oh_no: "¡Vaya! No se ha podido guardar los cambios." + unauthorized: "No estás autorizado a acceder a esta página." + error: Error + unavailable: No disponible + profile: Perfil + hub: Grupo + shop: Tienda + choose: Escoge + resolve_errors: Resuelve los siguientes errores + more_items: "+ %{count} Más" + default_card_updated: Tarjeta predeterminada actualizada + admin: + enterprise_limit_reached: "Has alcanzado el límite estándar de organizaciones por cuenta. Escriba a %{contact_email} si necesita aumentarlo." + modals: + got_it: Lo entiendo + close: "Cerrar" + invite: "Invitar" + invite_title: "Invitar a un usuario no registrado" + tag_rule_help: + title: Reglas de las etiquetas + overview: Vista general + overview_text: > + Las reglas de etiqueta proporcionan una manera de describir qué elementos + son visibles o no para determinados consumidores. Los artículos pueden + ser métodos de envío, métodos de pago, productos y ciclos de pedido. + by_default_rules: "'Por Defecto...' Reglas" + by_default_rules_text: > + Las reglas predeterminadas permiten ocultar los elementos para que no + estén visibles de forma predeterminada. Este comportamiento puede ser + invalidado por reglas no predeterminadas para consumidores con etiquetas + particulares. + customer_tagged_rules: "Reglas de \"clientes etiquetados ...\"" + customer_tagged_rules_text: > + Al crear reglas relacionadas con una etiqueta de cliente específica, + puede anular el comportamiento predeterminado (ya sea para mostrar u + ocultar elementos) a cliente con dicha etiqueta. + panels: + save: GUARDAR + saved: GUARDADO + saving: GUARDANDO + enterprise_package: + hub_profile: Perfil del Grupo + hub_profile_cost: "COSTE: GRATUITO PARA SIEMPRE" + hub_profile_text1: > + La gente puede encontrarte y ponerse en contacto contigo en Open Food + Network. Tu organización será visible en el mapa y se podrá buscar en + los listados. + hub_profile_text2: > + Tener un perfil y hacer vínculos a través de Open Food Network será + gratis para siempre. + hub_shop: Tienda + hub_shop_text1: > + Tu organización es la columna vertebral de un sistema de consumo local. + Agrega productos de otras organizaciones y véndelo a través de tu tienda + en Open Food Network. + hub_shop_text2: > + Los grupos pueden tener diferentes finalidades, ya sea una cooperativa + de alimentos, un grupo de consumo, un supermercado local, ... + hub_shop_text3: > + Si también quieres vender tus propios productos, tendrás que cambiar + esta organización para ser una productora. + choose_package: Seleccione un Perfil + choose_package_text1: > + Su organización no se activará completamente hasta que seleccione un + perfil de las opciones de la izquierda. + choose_package_text2: > + Haga click en una opción para ver información más detallada acerca de + cada perfil, y pulse el botón rojo GUARDAR cuando hayas terminado. + profile_only: Solo perfil + profile_only_cost: "COSTO: GRATUITO PARA SIEMPRE" + profile_only_text1: >+ + El perfil te hace visible y permite que las personas te puedan contactar. + Es una manera de aportar la máxima transparencia y explicar tu historia. + + profile_only_text2: > + Si prefieres concentrarte en producir alimentos y deseas dejar el trabajo + de venderlo a otras personas, no necesitas una tienda en Open Food Network. + profile_only_text3: > + Añade tus productos a Open Food Network (LaFeriaCR), permitiendo a los + Hubs vender tus productos. + producer_shop: Tienda de productor + producer_shop_text1: > + Vende tus productos directamente a los consumidores con tu tienda en + Open Food Network (LaFeriaCR). + producer_shop_text2: > + Una tienda de productora es para tu producto solamente, si quieres vender + productos de otros productores, selecciona 'Grupo de Productores'. + producer_hub: Grupo de Productoras + producer_hub_text1: > + Tu organización es la columna vertebral de un sistema de consumo local. + Agrega productos tuyos o de otras organizaciones y véndelo a través + de tu tienda en Open Food Network. + producer_hub_text2: > + Los Hubs de Productoras pueden tener diferentes finalidades, ya sea + una cooperativa de alimentos, un grupo de consumo o un supermercado + local. + producer_hub_text3: > + Open Food Network (LaFeriaCR) tiene como objetivo apoyar tantos modelos + de organizaciones como sea posible, queremos aportarte las herramientas + que necesites para poner en marcha tu organización. + get_listing: Obtener un listado + always_free: SIEMPRE GRATIS + sell_produce_others: Vende la producción de otros + sell_own_produce: Vende tu propia producción. + sell_both: Vende tu propia producción y la de otros + enterprise_producer: + producer: Productor + producer_text1: > + Los productores pueden crear cosas deliciosas para comer o beber. Usted + es un productor si cultiva, mejora, fermenta, ordeña o moldea. + producer_text2: > + Los Productores pueden también realizar otras acciones, como agregar + productos de otras organizaciones y venderlos a través de su tienda + en Open Food Network (LaFeriaCR). + non_producer: No-productor + non_producer_text1: > + Los no-productores no producen alimentos por si mismos, lo que significa + que no pueden crear sus propios productos para ofrecerlos a través de + Open Food Network (LaFeriaCR). + non_producer_text2: > + En cambio, los no-productores se especializan en vincular a los productores + con los consumidores finales, ya sea entregando, empaquetando o vendiendo + alimentos. + producer_desc: Productores + producer_example: ej. AGRICULTORES, PRODUCTORES + non_producer_desc: Todas las demás organizaciones + non_producer_example: ej. Grupos de consumo, tiendas cercanas, ... + enterprise_status: + status_title: "¡%{name} está configurado y listo para funcionar!" + severity: Gravedad + description: Descripción + resolve: Resolver + exchange_products: + load_more_variants: "Cargar mas variantes" + load_all_variants: "cargar todas las variantes" + select_all_variants: "Seleccionar todo" + variants_loaded: "%{num_of_variants_loaded} de %{total_number_of_variants} variantes cargadas" + loading_variants: "Cargando variantes" + tag_rules: + shipping_method_tagged_top: "Métodos de envío etiquetados" + shipping_method_tagged_bottom: "son:" + payment_method_tagged_top: "Métodos de pago etiquetados" + payment_method_tagged_bottom: "son:" + order_cycle_tagged_top: "Ciclos de pedido etiquetados" + order_cycle_tagged_bottom: "son:" + inventory_tagged_top: "Variantes de inventario etiquetadas" + inventory_tagged_bottom: "son:" + new_tag_rule_dialog: + select_rule_type: "Selecciona un tipo de regla:" + add_rule: "Añadir regla" + enterprise_fees: + inherit_from_product: "Heredar del producto" + orders: + index: + per_page: "%{results} por página" + view_file: "Ver archivo" + compiling_invoices: "Generando facturas" + bulk_invoice_created: "Factura conjunta creada" + bulk_invoice_failed: "Error al crear la factura conjunta" + please_wait: "Por favor, espere hasta que el PDF esté listo antes de cerrar esta ventana." + order_state: + address: "dirección" + adjustments: "ajustes" + awaiting_return: "esperando devolución" + canceled: "cancelado" + cart: "carrito" + complete: "completar" + confirm: "confirmar" + delivery: "entrega" + paused: "pausado" + payment: "pago" + pending: "pendiente" + resumed: "resumido" + returned: "devuelto" + skrill: "skrill" + shipment_states: + backorder: "orden pendiente" + partial: "parcial" + pending: "pendiente" + ready: "listo" + shipped: "enviado" + canceled: "cancelado" + payment_states: + balance_due: "saldo debido" + completed: "completado" + checkout: "validar" + credit_owed: "crédito debido" + failed: "fallido" + paid: "pagado" + pending: "pendiente" + processing: "procesando" + void: "vacío" + invalid: "inválido" + resend_user_email_confirmation: + resend: "Reenviar" + sending: "Reenviar..." + done: "Reenvío hecho ✓" + failed: "Reenvío fallido ✗" + order_cycles: + schedules: + adding_a_new_schedule: "Agregar una nueva programación" + updating_a_schedule: "Actualización de una programación" + create_schedule: "Crear programación" + update_schedule: "Actualizar programación" + delete_schedule: "Eliminar programación" + schedule_name_placeholder: "Nombre de la programación" + created_schedule: "Programación creada" + updated_schedule: "Programación actualizada" + deleted_schedule: "Programación eliminada" + name_required_error: "Por favor ingrese un nombre para este horario" + no_order_cycles_error: "Seleccione al menos un ciclo de pedido (arrastrar y soltar)" + available: "Disponible" + selected: "Seleccionado" + customers: + index: + add_customer: "Añadir cliente" + add_a_new_customer_for: "Añadir un nuevo cliente para %{shop_name}" + customer_placeholder: "cliente@ejemplo.org" + valid_email_error: "Introduce un correo electrónico válido" + subscriptions: + error_saving: "Error al guardar suscripción " + new: + please_select_a_shop: "Por favor seleccione una tienda" + insufficient_stock: "Inventario insuficiente disponible, solo quedan %{on_hand}" + out_of_stock: + reduced_stock_available: Inventario reducido disponible + out_of_stock_text: > + Mientras usted estaba comprando, los niveles de inventario para uno o más + de los productos de su carrito se han reducido. Aquí está lo que ha cambiado: + now_out_of_stock: está ahora fuera de inventario. + only_n_remainging: "ahora solo hay %{num} restantes." + variants: + on_demand: + 'yes': "Bajo demanda" + variant_overrides: + on_demand: + use_producer_settings: "Utilizar la configuración de inventario del productor." + 'yes': "Sí" + 'no': "No" + inventory_products: "Productos del Inventario" + hidden_products: "Productos ocultos" + new_products: "Nuevos productos" + reset_stock_levels: Restablecer niveles de inventario a valores predeterminados + changes_to: Cambia a + one_override: Una sobreescritura + overrides: sobrescribe + remain_unsaved: permanecen sin guardar. + no_changes_to_save: 'No hay cambios para guardar. ' + no_authorisation: "No se ha podido obtener autorización para guardar estos cambios, por lo que no se guardarán." + some_trouble: "Han habido algunos problemas al guardar: %{errors}" + changing_on_hand_stock: Cambiando los niveles de inventario.. + stock_reset: Restablecer inventario a valores por defecto + tag_rules: + show_hide_variants: 'Mostrar u ocultar variantes en mi tienda' + show_hide_shipping: 'Mostrar u ocultar los métodos de envío al comprar' + show_hide_payment: 'Mostrar u ocultar los métodos de pago al comprar' + show_hide_order_cycles: 'Mostrar u ocultar ciclos de pedido en mi tienda' + visible: VISIBLE + not_visible: NO VISIBLE + services: + unsaved_changes_message: Los cambios no guardados existen todavía, ¿guardar ahora o ignorar? + save: GUARDAR + ignore: IGNORAR + add_to_order_cycle: "Añadir al Ciclo de Pedido" + manage_products: "Gestionar productos" + edit_profile: "Editar perfil" + add_products_to_inventory: "Añadir productos al inventario" + resources: + could_not_delete_customer: 'No se pudo eliminar al cliente' + product_import: + confirmation: | + Esto establecerá el nivel de stock a cero en todos los productos para esta + organización que no están presentes en el archivo subido. + order_cycles: + create_failure: "Error al crear el ciclo de pedido" + update_success: 'Se ha actualizado su ciclo de pedido.' + update_failure: "Error al actualizar el ciclo de pedido" + no_distributors: No hay distribuidores en este ciclo de pedido. Este ciclo de pedido no será visible para las consumidoras hasta que agregues uno. ¿Deseas continuar guardando este ciclo de pedido? ' + enterprises: + producer: "Productor" + non_producer: "No productor" + customers: + select_shop: 'Seleccione primero una tienda' + could_not_create: ¡Lo siento! No se pudo crear + subscriptions: + closes: cierra + closed: cerrado + close_date_not_set: Fecha de cierre no establecida + spree: + users: + order: "Pedido" + registration: + welcome_to_ofn: "¡Bienvenido a Open Food Network (LaFeriaCR)!" + signup_or_login: "Empieza registrándose (o iniciando sesión)" + have_an_account: "¿Ya tiene una cuenta?" + action_login: "Inicie sesión ahora." + inflections: + each: + one: "each" + other: "cada" + bunch: + one: "manojo" + other: "manojos" + pack: + one: "paquete" + other: "paquetes" + box: + one: "caja" + other: "cajas" + bottle: + one: "botella" + other: "botellas" + jar: + one: "frasco" + other: "frascos" + head: + one: "cabeza" + other: "cabezas" + bag: + one: "bolsa" + other: "bolsas" + loaf: + one: "hogaza" + other: "hogazas" + single: + one: "single" + other: "individuales" + tub: + one: "tub" + other: "recipientes" + punnet: + one: "canastilla" + other: "canastillas" + packet: + one: "paquete" + other: "paquetes" + item: + one: "elemento" + other: "elementos" + dozen: + one: "docena" + other: "docenas" + unit: + one: "unidad" + other: "unidades" + serve: + one: "serve" + other: "porción" + tray: + one: "bandeja" + other: "bandejas" + piece: + one: "pieza" + other: "piezas" + pot: + one: "maceta" + other: "contenedores" + bundle: + one: "haz" + other: "paquetes" + flask: + one: "flask" + other: "frascos" + basket: + one: "canasta" + other: "canastas" + sack: + one: "sacos" + other: "sacos" + producers: + signup: + start_free_profile: "¡Empieze con un perfil gratuito, y amplíelo cuando esté preparado!" + order_management: + reports: + enterprise_fee_summary: + date_end_before_start_error: "debe ser después del comienzo" + parameter_not_allowed_error: "Usted no está autorizado a usar uno o más filtros seleccionados para este reporte." + fee_calculated_on_transfer_through_all: "Todos" + fee_calculated_on_transfer_through_entire_orders: "Pedidos completos a través de %{distributor}" + tax_category_various: "Varios" + fee_type: + payment_method: "Transaccion de pago" + shipping_method: "Envío" + fee_placements: + supplier: "Entrante" + distributor: "Saliente" + coordinator: "Coordinadora" + tax_category_name: + shipping_instance_rate: "Tarifa de plataforma" + formats: + csv: + header: + fee_type: "Tipo de Comisión" + enterprise_name: "Propietario de la organización" + fee_name: "Nombre de la comisión" + customer_name: "Cliente" + fee_placement: "Asignación de comisiones" + fee_calculated_on_transfer_through_name: "Cálculo de comisiones a través de transferencias" + tax_category_name: "Categoría de impuestos" + total_amount: "€€ SUM" + html: + header: + fee_type: "Tipo de Comisión" + enterprise_name: "Propietario de la organización" + fee_name: "Nombre de la comisión" + customer_name: "Cliente" + fee_placement: "Asignación de comisiones" + fee_calculated_on_transfer_through_name: "Cálculo de comisiones a través de transferencias" + tax_category_name: "Categoría de impuestos" + total_amount: "€€ SUM" + invalid_filter_parameters: "Los filtros que seleccionó para este reporte no son válidos." + order: "Pedido" + distribution: "Distribución" + order_details: "Detalles del pedido" + customer_details: "Detalles del cliente" + adjustments: "Ajustes" + payments: "Pagos" + payment: "Pago" + payment_method: "Método de pago" + shipment: "Envío" + shipment_inc_vat: "Envío incluido VAT" + shipping_tax_rate: "Impuestos de envío" + category: "Categoría" + delivery: "Entrega" + temperature_controlled: "Control de temperatura" + new_product: "Nuevo producto" + administration: "Administración" + logged_in_as: "Conectado como" + account: "Cuenta" + logout: "Cerrar sesión" + date_range: "Rango de fechas" + status: "estado" + new: "Nuevo" + start: "Inicio" + end: "Final" + stop: "Detener" + first: "Primero" + previous: "Anterior" + last: "Último" + spree: + your_order_is_empty_add_product: "Su pedido está vacío, busque y añada un producto arriba" + add_product: "Añadir Producto" + name_or_sku: "Nombre o código SKU (ingrese al menos los primeros 4 caracteres del nombre del producto)" + resend: Reenviar + back_to_orders_list: Volver a la lista de pedidos + return_authorizations: Autorizaciones de devolución + cannot_create_returns: No se pueden crear devoluciones ya que este pedido no tiene unidades enviadas. + select_stock: "Seleccionar inventario" + location: "Ubicación" + count_on_hand: "Cuenta de disponibilidad" + quantity: "Cantidad" + on_demand: "Bajo demanda" + on_hand: "Disponibles" + package_from: "paquete de" + item_description: "Descripción del artículo" + price: "Precio" + total: "Total" + edit: "Editar" + split: "División" + delete: "Borrar" + cannot_set_shipping_method_without_address: "No se puede establecer el método de envío hasta que se proporcionen los detalles del cliente." + no_tracking_present: "No se han proporcionado detalles de seguimiento." + order_total: "Total del pedido" + customer_details: "Detalles del cliente" + customer_search: "Búsqueda de clientes" + choose_a_customer: "Elija un cliente " + account: "Cuenta" + billing_address: "Dirección de facturación" + shipping_address: "Dirección de envío" + first_name: "Nombre" + last_name: "Apellidos" + street_address: "Dirección" + street_address_2: "Dirección (continuada)" + city: "Ciudad" + zip: "Código postal" + country: "País" + state: "Provincia" + phone: "Teléfono" + update: "Actualizar" + use_billing_address: "Utilice la dirección de facturación" + adjustments: "Ajustes" + continue: "Continuar" + fill_in_customer_info: "Por favor complete la información del cliente" + new_payment: "Nuevo pago" + capture: "Captura" + void: "Vacío" + configurations: "Configuraciones" + general_settings: "Configuración general" + site_name: "Nombre del sitio" + site_url: "URL del sitio" + default_seo_title: "Título Seo predeterminado" + default_meta_description: "Meta Descripción predeterminada" + default_meta_keywords: "Palabras clave Meta predeterminadas" + security_settings: "Configuraciones de seguridad" + allow_ssl_in_development_and_test: "Permitir el uso de SSL en los modos de desarrollo y prueba" + allow_ssl_in_production: "Permitir el uso de SSL modo de producción" + allow_ssl_in_staging: "Permitir que SSL se utilice en modo de staging" + 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? + currency_thousands_separator: "Separador de miles de la moneda" + hide_cents: "Ocultar céntimos" + display_currency: "Mostrar moneda" + choose_currency: "Elegir moneda" + mail_method_settings: "Configuración del método de correo" + general: "General" + enable_mail_delivery: "Habilitar entrega de correo" + send_mails_as: "Enviar correos como" + smtp_send_all_emails_as_from_following_address: "Enviar todos los correos a partir de la siguiente dirección." + send_copy_of_all_mails_to: "Enviar copia de todos los correos a" + smtp_send_copy_to_this_addresses: "Envía una copia de todos los correos salientes a esta dirección. Para direcciones múltiples, sepárelas con comas." + intercept_email_address: "Interceptar la dirección de correo electrónico" + intercept_email_instructions: "Anular destinatario de correo electrónico y reemplazar con esta dirección." + smtp: "SMTP" + smtp_domain: "Dominio SMTP" + smtp_mail_host: "Alojamiento de correo SMTP" + smtp_port: "Puerto SMTP" + secure_connection_type: "Tipo de conexión segura" + smtp_authentication_type: "Tipo de autenticación SMTP" + smtp_username: "Nombre de usuario SMTP" + smtp_password: "Contraseña SMTP" + image_settings: "Ajustes de imágen" + image_settings_warning: "Deberá regenerar las miniaturas si actualiza los estilos de paperclip. Utilize rake paperclip:refresh:thumbnails CLASS=Spree::Image para hacer esto." + attachment_default_style: Estilo de los archivos adjuntos + attachment_default_url: "URL predeterminada de los archivos adjuntos" + attachment_path: "Ruta de los archivos adjuntos" + attachment_styles: "Estilos de clip" + attachment_url: "URL de los archivos adjuntos" + add_new_style: "Añadir nuevo estilo" + image_settings_updated: "Configuración de la imagen se actualizó correctamente." + tax_categories: "Categorías de impuestos" + listing_tax_categories: "Listado de categorías de impuestos" + back_to_tax_categories_list: "Volver a la lista de categorías de impuestos" + tax rate: "Tarifas de impuesto" + new_tax_rate: "Nueva tarifa de impuesto" + tax_category: "Categoría de impuestos" + rate: "Impuesto" + tax_rate_amount_explanation: "Las tarifas de impuestos son una cantidad decimal para ayudar en los cálculos (es decir, si la tasa de impuestos es del 5%, introduzca 0.05)" + included_in_price: "Incluido en el precio" + show_rate_in_label: "Mostrar tarifa en la etiqueta" + back_to_tax_rates_list: "Volver a la lista de tarifas de impuestos" + tax_settings: "Configuración de Impuestos" + zones: "Zonas" + new_zone: "Nueva zona" + default_tax: "Impuesto por defecto" + default_tax_zone: "Zona de impuestos predeterminada" + country_based: "Basado en el país" + state_based: "Basado en la provincia" + countries: "Países" + listing_countries: "Listado de países" + iso_name: "Nombre de ISO" + states_required: "Provincias requeridas" + editing_country: "Editar país" + back_to_countries_list: "Volver a la lista de países" + states: "Provincias" + abbreviation: "Abreviatura" + new_state: "Nueva provincia" + payment_methods: "Métodos de pago" + new_payment_method: "Nuevo método de pago" + provider: "Proveedor" + taxonomies: "Taxonomías" + new_taxonomy: "Nueva taxonomía" + back_to_taxonomies_list: "Volver a la lista de taxonomías" + shipping_methods: "Métodos de envío" + shipping_categories: "Categorías de envío" + new_shipping_category: "Nueva categoría de envío" + back_to_shipping_categories: "Volver a las categorías de envío" + analytics_trackers: "Rastreador de analizador" + no_trackers_found: "No se encontraron rastreadores" + new_tracker: "Nuevo rastreador" + add_one: "Agrega uno" + google_analytics_id: "ID de analizador" + back_to_trackers_list: "Volver a la lista de rastreadores" + name: "Nombre" + description: "Descripción" + type: "Tipo" + default: "por defecto" + calculator: "Calculadora" + zone: "Zona" + display: "Mostrar" + environment: "Ambiente" + active: "Activo" + nore: "Más" + no_results: "No hay resultados" + create: "Crear" + loading: "Cargando" + flat_percent: "Porcentaje plano" + per_kg: "Por kg" + amount: "Cantidad" + currency: "Moneda" + first_item: "Costo del primer artículo" + additional_item: "Costo del artículo adicional" + max_items: "Max. artículos" + minimal_amount: "Cantidad mínima" + normal_amount: "Cantidad normal" + discount_amount: "Cantidad de descuento" + no_images_found: "No se encontraron imágenes " + new_image: "Nueva imágen" + filename: "Nombre de archivo" + alt_text: "Texto alternativo" + thumbnail: "Miniatura" + back_to_images_list: "Volver a la lista de imágenes " + email: Correo electrónico + account_updated: "¡Cuenta actualizada!" + email_updated: "La cuenta se actualizará una vez que se confirme el nuevo correo electrónico." + my_account: "Mi cuenta" + date: "Fecha" + time: "Hora" + inventory_error_flash_for_insufficient_quantity: "Un artículo de su carrito ya no está disponible." + inventory: Inventario + zipcode: Código postal + weight: Peso (en kg) + error_user_destroy_with_orders: "Los usuarios con pedidos completados no pueden ser eliminados" + cannot_create_payment_without_payment_methods: "No se puede crear un pago para una orden sin un método de pago definido." + please_define_payment_methods: "Por favor definir métodos de pago primero." + options: "Opciones" + actions: + update: "Actualizar" + errors: + messages: + blank: "no puede estar en blanco" + layouts: + admin: + header: + store: Tienda + admin: + tab: + dashboard: "Panel de inicio" + orders: "Pedidos" + bulk_order_management: "Gestión de pedidos en bloque" + subscriptions: "Suscripciones" + products: "Productos" + option_types: "Tipos de opciones" + properties: "Propiedades" + variant_overrides: "Inventario" + reports: "Reportes" + configuration: "Configuración" + users: "Usuarios" + roles: "Roles" + order_cycles: "Ciclos de Pedido" + enterprises: "Organizaciones" + enterprise_relationships: "Permisos" + customers: "Cliente" + groups: "Grupos" + product_properties: + index: + inherits_properties_checkbox_hint: "¿Heredar propiedades desde %{supplier}? (a menos que sea anulado arriba)" + add_product_properties: "Agregar propiedades del producto" + select_from_prototype: "Seleccionar de prototipo" + properties: + index: + properties: "Propiedades" + new_property: "Nueva propiedad" + name: "Nombre" + presentation: "Presentación" + new: + new_property: "Nueva propiedad" + edit: + editing_property: "Editar propiedad" + back_to_properties_list: "Volver a lista de propiedades" + form: + name: "Nombre" + presentation: "Presentación" + return_authorizations: + index: + new_return_authorization: "Nueva autorización de devolución" + return_authorizations: "Autorizaciones de devolución" + back_to_orders_list: "Volver a la lista de pedidos" + rma_number: "número RMA" + status: "Estado" + amount: "Cantidad" + cannot_create_returns: "No se pueden crear devoluciones ya que este pedido no tiene unidades enviadas." + continue: "Continuar" + new: + new_return_authorization: "Nueva autorización de devolución" + back_to_return_authorizations_list: "Volver a lista de autorización de devolución" + continue: "Continuar" + edit: + receive: "recibir" + are_you_sure: "¿Está seguro?" + return_authorization: "Autorización de devolución" + form: + product: "Producto" + quantity_shipped: "Cantidad enviada" + quantity_returned: "Cantidad devuelta" + return_quantity: "Cantidad a devolver" + amount: "Cantidad" + rma_value: "Valor RMA" + reason: "Razón" + stock_location: "Ubicación de inventario" + states: + authorized: "Autorizado" + received: "Recibido" + canceled: "Cancelado" + orders: + index: + listing_orders: "Listado de pedidos" + new_order: "Nuevo pedido" + capture: "Captura" + ship: "Envío" + edit: "Editar" + order_not_updated: "El pedido no se pudo actualizar" + note: "Nota" + first: "Primero" + last: "Último" + previous: "Anterior" + next: "Siguiente" + loading: "Cargando" + no_orders_found: "No se encontraron pedidos" + results_found: "%{number} Resultados encontrados." + viewing: "Viendo de %{start}a %{end}." + print_invoices: "Imprimir facturas" + sortable_header: + payment_state: "Estado del pago" + shipment_state: "Estado del envío" + completed_at: "Completado en" + number: "Número" + state: "Provincia" + email: "Correo electrónico del cliente" + invoice: + issued_on: "Emitido el" + tax_invoice: "FACTURA DE IMPUESTOS" + code: "Código" + from: "De" + to: "Facturar a" + shipping: "Envío" + form: + distribution_fields: + title: "Distribución" + distributor: "Distribuidor:" + order_cycle: "Ciclo de pedido:" + line_item_adjustments: "Ajustes de artículo" + order_adjustments: "Ajustes de pedido" + order_total: "Total del pedido" + overview: + enterprises_header: + ofn_with_tip: Las organizaciones son productores y/o grupos y son la unidad básica de organización dentro de Open Food Network. + products: + active_products: + zero: "No tienes ningún producto activo" + one: "Tiene un producto activo." + other: "Tiene %{count} productos activos" + order_cycles: + order_cycles: "Ciclos de Pedido" + order_cycles_tip: "Los ciclos de pedido determinan cuándo y dónde los productos están disponibles para las consumidoras." + you_have_active: + zero: "No tienes ningún ciclo de pedido activo." + one: "Tienes un ciclo de pedido activo." + other: "Tienes %{count} ciclos de pedido activos." + manage_order_cycles: "GESTIONA LOS CICLOS DE PEDIDO" + shipping_methods: + index: + shipping_methods: "Métodos de envío" + new_shipping_method: "Nuevo método de envío" + name: "Nombre" + products_distributor: "Distribuidor" + zone: "Zona" + calculator: "Calculadora" + display: "Mostrar" + both: "Ambos" + front_end: "Front End" + back_end: "Back End" + no_shipping_methods_found: "No se encontraron métodos de envío" + new: + new_shipping_method: "Nuevo método de envío" + back_to_shipping_methods_list: "Volver a la lista de métodos de envío" + edit: + editing_shipping_method: "Edición del método de envío" + new: "Nuevo" + back_to_shipping_methods_list: "Volver a la lista de métodos de envío" + form: + categories: "Categorías" + zones: "Zonas" + both: "Ambos" + front_end: "Front End" + back_end: "Back End" + payment_methods: + new: + new_payment_method: "Nuevo método de pago" + back_to_payment_methods_list: "Volver a la lista de métodos de pago" + edit: + editing_payment_method: "Edición del método de pago" + back_to_payment_methods_list: "Volver a la lista de métodos de pago" + stripe_connect: + enterprise_select_placeholder: Escoge... + loading_account_information_msg: Cargando la información de la cuenta de Stripe, espere un momento ... + stripe_disabled_msg: El administrador del sistema ha deshabilitado los pagos por Stripe. + request_failed_msg: Lo sentimos. Algo salió mal al intentar verificar los detalles de la cuenta con Stripe ... + account_missing_msg: No existe una cuenta Stripe para esta organización. + connect_one: Connect One + access_revoked_msg: El acceso a esta cuenta de Stripe ha sido anulado, por favor, vuelva a conectar su cuenta. + status: Estado + connected: Conectado + account_id: ID de cuenta + business_name: Nombre de la organización + charges_enabled: Cargos habilitados + payments: + source_forms: + stripe: + error_saving_payment: Error al guardar el pago + submitting_payment: Enviando pago... + products: + image_upload_error: "La imágen del producto no fue reconocida. Por favor, cargue una imágen en formato PNG o JPG." + new: + title: "Nuevo producto" + new_product: "Nuevo producto" + supplier: "Proveedor" + product_name: "Nombre del producto" + units: "Unidad de medida" + value: "Valor" + unit_name: "Nombre de la unidad" + price: "Precio" + on_hand: "Disponibles" + on_demand: "Bajo demanda" + product_description: "Descripción del producto" + image: "Imágen" + or: "o" + unit_name_placeholder: 'ej. racimos' + index: + header: + title: Editar productos por volumen + indicators: + title: CARGANDO PRODUCTOS + no_products: "Todavía no hay productos ¿Por qué no añades algunos?" + no_results: "Disculpa, no se han encontrado resultados" + products_head: + name: Nombre + unit: Unidad + display_as: Mostrar como + category: Categoría + tax_category: Categoría de impuestos + inherits_properties?: ¿Hereda propiedades? + available_on: Disponible en + av_on: "Disp. en" + import_date: "Fecha de importación" + products_variant: + variant_has_n_overrides: "Esta variante tiene %{n} override(s)" + new_variant: "Nueva variante" + product_name: Nombre del producto + primary_taxon_form: + product_category: Categoría del producto + group_buy_form: + group_buy: "¿Compra grupal?" + bulk_unit_size: Tamaño de la unidad por volumen + display_as: + display_as: Mostrar como + reports: + table: + select_and_search: "Seleccione filtros y haga clic en %{option} para acceder a sus datos." + bulk_coop: + bulk_coop_supplier_report: 'Bulk Co-op - Totales por Proveedor' + bulk_coop_allocation: 'Bulk Co-op - Asignación' + bulk_coop_packing_sheets: 'Bulk Co-op - Hojas de Empaquetado' + bulk_coop_customer_payments: 'Bulk Co-op - Pagos de clientes' + enterprise_fee_summaries: + filters: + date_range: "Rango de fechas" + report_format_csv: "Descargar como CSV" + generate_report: "Generar reporte" + report: + none: "Ninguno" + select_and_search: "Seleccione los filtros y haga clic en GENERAR REPORTE para acceder a sus datos." + users: + index: + listing_users: "Listando usuarios" + new_user: "Nuevo usuario" + user: "Usuario" + enterprise_limit: "Límite de la organización" + search: "Buscar" + email: "Correo electrónico" + edit: + editing_user: "Editando usuarios" + back_to_users_list: "Volver a la lista de usuarios" + general_settings: "Configuración general" + form: + email: "Correo electrónico" + roles: "Roles" + enterprise_limit: "Límite de la organización" + confirm_password: "Confirmar contraseña" + password: "Contraseña" + email_confirmation: + confirmation_pending: "La confirmación por correo electrónico está pendiente. Hemos enviado un correo electrónico de confirmación a %{address}." + variants: + index: + sku: "SKU" + price: "Precio" + options: "Opciones" + no_results: "No hay resultados" + to_add_variants_you_must_first_define: "Para agregar variantes, usted debe primero definir" + option_types: "Tipos de opciones" + option_values: "Valores de opción" + and: "y" + new_variant: "Nueva Variante" + show_active: "Mostrar activo" + show_deleted: "Mostrar eliminados" + new: + new_variant: "Nueva variante" + form: + cost_price: "Precio de costo" + sku: "SKU" + price: "Precio" + display_as: "Mostrar como" + display_name: "Nombre para mostrar" + autocomplete: + producer_name: "Productor" + unit: "Unidad" + general_settings: + edit: + legal_settings: "Configuraciones legales" + cookies_consent_banner_toggle: "Mostrar el banner de consentimiento de cookies" + privacy_policy_url: "Vínculo con la política de privacidad" + enterprises_require_tos: "Las organizaciones deben aceptar los Términos del Servicio" + cookies_policy_matomo_section: "Mostrar la sección de Matomo en la página de política de cookies" + cookies_policy_ga_section: "Mostrar la sección de Google Analytics en la página de la política de cookies" + footer_tos_url: "URL de términos y servicios" + checkout: + payment: + stripe: + choose_one: Elige uno + enter_new_card: Introduce los detalles para una nueva tarjeta + used_saved_card: "Usa una tarjeta guardada:" + or_enter_new_card: "O introduce los detalles de una nueva tarjeta:" + remember_this_card: ¿Recordar esta tarjeta? + stripe_sca: + choose_one: Elige uno + enter_new_card: Introduce los detalles para una nueva tarjeta + used_saved_card: "Usa una tarjeta guardada:" + or_enter_new_card: "O introduce los detalles de una nueva tarjeta:" + remember_this_card: ¿Recordar esta tarjeta? + date_picker: + format: '%Y-%m-%d' + js_format: 'yy-mm-dd' + orders: + error_flash_for_unavailable_items: "Un artículo de su carrito ya no está disponible." + edit: + login_to_view_order: "Por favor inicie sesión para ver su pedido." + bought: + item: "Pedido en este ciclo de pedido" + line_item: + insufficient_stock: "Inventario insuficiente, solo quedan %{on_hand}" + out_of_stock: "Agotado" + unavailable_item: "Actualmente no disponible" + shipment_states: + backorder: pedido pendiente + partial: parcial + pending: pendiente + ready: listo + shipped: enviado + payment_states: + balance_due: saldo en deuda + completed: completado + checkout: validar + credit_owed: crédito adeudado + failed: fallido + paid: pagado + pending: pendiente + processing: procesando + void: vacío + invalid: inválido + order_mailer: + cancel_email: + customer_greeting: "Hola %{name}!" + instructions: "Su pedido ha sido CANCELADO. Por favor, conserve esta información de cancelación para sus registros." + order_summary_canceled: "Resumen del pedido [CANCELADO]" + subject: "Cancelación del pedido" + confirm_email: + subject: "Confirmación del pedido" + invoice_email: + hi: "Hola %{name}" + invoice_attached_text: Adjunta una factura para su pedido reciente de + order_state: + address: dirección + adjustments: ajustes + awaiting_return: Esperando retorno + canceled: cancelado + cart: carrito + complete: completar + confirm: Confirmar + delivery: Entrega + paused: pausado + payment: pago + pending: pendiente + resumed: resumido + returned: devuelto + skrill: skrill + subscription_state: + active: activo + pending: pendiente + ended: terminado + paused: pausado + canceled: cancelado + user_mailer: + reset_password_instructions: + request_sent_text: | + La solicitud de restablecer su contraseña se ha realizado. + Si usted no lo ha solicitado, ignora este correo electrónico. + link_text: > + Si has solicitado esta acción haz click en el siguiente enlace: + issue_text: | + Si el enlace anterior no funciona pruebe con copiarlo y pegarlo en su navegador. + Si los problemas continúan no dude en contactarnos. + confirmation_instructions: + subject: Por favor, confirma tu cuenta de OFN + users: + form: + account_settings: Configuración de la cuenta + show: + tabs: + orders: Pedidos + cards: Tarjetas de crédito + transactions: Transacciones + settings: Configuración de la cuenta + unconfirmed_email: "Correo electrónico pendiente de confirmación para: %{unconfirmed_email}. Su dirección de correo electrónico se actualizará una vez que se confirme el nuevo correo electrónico." + orders: + open_orders: Pedidos Abiertos + past_orders: Pedidos anteriores + transactions: + transaction_history: Historial de transacciones + open_orders: + order: Pedido + shop: Tienda + changes_allowed_until: Se permiten cambios hasta + items: Artículos + total: Total + edit: Editar + cancel: Cancelar + closed: Cerrado + until: Hasta + past_orders: + order: Pedido + shop: Tienda + completed_at: Completado en + items: Artículos + total: Total + paid?: ¿Pagado? + view: Ver + saved_cards: + default?: ¿Por defecto? + delete?: ¿Borrar? + cards: + authorised_shops: Tiendas autorizadas + authorised_shops_popover: Esta es la lista de tiendas a las que se les permite cobrar a su tarjeta de crédito predeterminada por las suscripciones (como por ejemplo, pedidos repetidos) que pueda tener. Los detalles de su tarjeta se mantendrán seguros y no se compartirán con los propietarios de las tiendas. Siempre se le notificará cuando se le cobra. + saved_cards_popover: Esta es la lista de tarjetas que ha optado por guardar para su uso posterior. Su "valor predeterminado" se seleccionará automáticamente al momento de realizar un pedido, y puede ser cobrado por cualquier tienda que tenga permitido hacerlo (ver a la derecha). + authorised_shops: + shop_name: "Nombre de la tienda" + allow_charges?: "¿Permitir cobros?" + localized_number: + invalid_format: tiene un formato invalido. Por favor introduzca un número. + api: + invalid_api_key: "La llave de API utilizada (%{key}) es inválida." + unauthorized: "No está autorizado para realizar esta acción." + invalid_resource: "Recurso inválido. Por favor corrija los errores e intente nuevamente." + resource_not_found: "El recurso que buscaba no fue encontrado." + access: "Acceso al API" + key: "Llave" + clear_key: "Borrar llave" + regenerate_key: "Regenerar llave" + no_key: "Sin llave" + generate_key: "Generar llave de API" + key_generated: "Llave generada" + key_cleared: "Llave borrada" + shipment: + cannot_ready: "No se puede completar envío" + invalid_taxonomy_id: "El identificador de taxonomía es inválido." diff --git a/config/locales/fil_PH.yml b/config/locales/fil_PH.yml new file mode 100644 index 0000000000..0b3c2d1ce3 --- /dev/null +++ b/config/locales/fil_PH.yml @@ -0,0 +1,3387 @@ +fil_PH: + language_name: "Filipino" + activerecord: + attributes: + enterprise_fee: + fee_type: Uri ng Bayarin + spree/order: + payment_state: Status ng Pagbabayad + shipment_state: status ng kargamento + completed_at: Nakumpleto + number: Bilang + state: Status + email: Email ng Parokyano + spree/payment: + amount: Halaga + spree/product: + primary_taxon: "Kategorya ng Produkto" + supplier: "Supplier" + shipping_category_id: "Kategorya ng Pagpapadala" + variant_unit: "Yunit ng variant" + variant_unit_name: "pangalan ng yunit ng variant" + spree/credit_card: + base: "Credit Card" + order_cycle: + orders_close_at: petsa ng pagsasara + errors: + models: + spree/user: + attributes: + email: + taken: "Mayroon ng account para sa email na ito. Maglog-in o i-reset ang inyong password." + spree/order: + no_card: Walang mga awtorisadong credit card na maaaring i-charge + spree/credit_card: + attributes: + base: + card_expired: "ay nag-expire na" + order_cycle: + attributes: + orders_close_at: + after_orders_open_at: ay dapat pagkatapos ng open date + variant_override: + count_on_hand: + using_producer_stock_settings_but_count_on_hand_set: "ay dapat blanko sapagkat ginagamit ang stock settings ng producer" + on_demand_but_count_on_hand_set: "ay dapat blanko kung on demand" + limited_stock_but_no_count_on_hand: "ay dapat matukoy sapagkat ipipilit ang limitadong stock" + activemodel: + attributes: + order_management/reports/enterprise_fee_summary/parameters: + start_at: "Simula" + end_at: "Hanggang" + distributor_ids: "Hubs" + producer_ids: "Producers" + order_cycle_ids: "Order Cycles" + enterprise_fee_ids: "pangalan ng mga bayarin" + shipping_method_ids: "Mga Paraan ng Pagpapadala" + payment_method_ids: "Mga Paraan ng Pagbabayad" + errors: + messages: + inclusion: "ay hindi kasama sa listahan" + models: + order_management/subscriptions/validator: + attributes: + subscription_line_items: + at_least_one_product: "^Magdagdag ng kahit isang produkto" + not_available: "^%{name} ay hindi magagamit mula sa napiling iskedyul" + ends_at: + after_begins_at: "ay dapat pagkatapos ng nagsisimula sa" + customer: + does_not_belong_to_shop: "ay hindi nabibilang sa%{shop}" + schedule: + not_coordinated_by_shop: "ay hindi coordinated ng%{shop}" + payment_method: + not_available_to_shop: "ay hindi magagamit para sa%{shop}" + invalid_type: "ay dapat pamamaraang Cash o Stripe" + charges_not_allowed: "^ang paniningil gamit ang Credit card ay hindi pinahihintulutan ng Customer na ito" + no_default_card: "^Walang default card na maaaring gamitin para sa customer na ito" + shipping_method: + not_available_to_shop: "ay hindi magagamit para%{shop}" + devise: + confirmations: + send_instructions: "Kayo ay makakatanggap ng email na may panuto kung paano kumpirmahin ang inyong account sa loob ng ilang minuto." + failed_to_send: "May error na nangyari habang pinapadala ang email para sa pagkumpirma ng inyong account." + resend_confirmation_email: "Ipadala muli ang email para sa pagkumpirma ng account" + confirmed: "Salamat sa pagkumpirma ng inyong email! Maaari na kayong maglog-in." + not_confirmed: "Ang inyong email address ay hindi makumpirma. Marahil ay nakumpleto mo na ang hakbang na ito?" + user_confirmations: + spree_user: + send_instructions: "Kayo ay makakatanggap ng email na may panuto kung paano kumpirmahin ang inyong account sa loob ng ilang minuto." + confirmation_sent: "Napadala na ang email para sa pagkumpirma ng account" + confirmation_not_sent: "May error sa pagpapadala ng email para sa pagkumpirma ng account" + user_registrations: + spree_user: + signed_up_but_unconfirmed: "ang mensahe na may nakalakip na confirmation link ay napadala na sa inyong email address. Maaari lamang na buksan ang link para ma-activate ang inyong account." + unknown_error: "may maling nangyari habang ginagawa ang inyong account. I-check ang email address at subukang muli." + failure: + invalid: | + hindi valid ang email o password. + isa ka bang Guest dati? marahil ay kailangang gumawa ng account o i-reset ang inyong password. + unconfirmed: "Kailangang kumpirmahin ang inyong account bago magpatuloy." + already_registered: "Ang email address na ito ay nakarehistro na. Maglog-in upang makapagpatuloy o bumalik at gumamit ng ibang email address." + success: + logged_in_succesfully: "Matagumpay na nakapaglog-in." + user_passwords: + spree_user: + updated_not_active: "ang inyong password ay na-reset na ngunit ang inyong email ay hindi pa nakumpirma." + updated: "Ang password ay matagumpay na napalitan. Ikaw ay nakasign-in na." + send_instructions: "Kayo ay makakatanggap ng email na may panuto kung paano kumpirmahin ang inyong account sa loob ng ilang minuto." + models: + order_cycle: + cloned_order_cycle_name: "KOPYA NG%{order_cycle}" + validators: + date_time_string_validator: + not_string_error: "ay dapat String" + invalid_format_error: "ay dapat valid" + integer_array_validator: + not_array_error: "ay dapat na pagpipilian" + invalid_element_error: "ay dapat naglalaman lamang ng valid na integers" + enterprise_mailer: + confirmation_instructions: + subject: "Pakikumpirma ang email address para sa %{enterprise}" + welcome: + subject: "%{enterprise}ay nasa %{sitename}na ngayon" + email_welcome: "Maligayang pagdating" + email_registered: "ay miyembro na ng" + email_userguide_html: "Narito ang Gabay sa Paggamit na may detalyadong suporta para sa pagset-up ng iyong Producer o Hub: %{link}" + userguide: "Gabay sa Paggamit ng Open Food Network" + email_admin_html: "maaaring pamahalaan ang iyong account sa pamamagitan ng paglog-in sa%{link}o sa pagpindot sa cog sa pinakataas na kanang bahagi ng homepage at pagpili sa Administration." + admin_panel: "Admin Panel" + email_community_html: "Kami ay mayroon ding online forum para sa talakayang pangkomunidad na may kinalaman sa OFN software at sa mga natatanging hamon sa pagpapatakbo ng enterprise ng pagkain. Kayo ay hinihikayat namin na sumali rito. Kami ay patuloy na nagbabago para makapagbigay ng mas mabuting serbisyo, at ang inyong suhestiyon sa forum ay makakatulong para mga susunod na pagbabago.%{link}" + join_community: "Sumali sa Komunidad" + invite_manager: + subject: "%{enterprise}ay inanyayahan kang maging tagapamahala" + producer_mailer: + order_cycle: + subject: "ulat ng order cycle para sa %{producer}" + shipment_mailer: + shipped_email: + dear_customer: "Dear Customer," + instructions: "ang iyong order ay na-ship na " + shipment_summary: "buod ng kargamento" + subject: "notification ukol sa kargamento" + thanks: "Salamat sa inyong pagtangkilik" + track_information: "Impormasyon ukol sa pag-track: %{tracking}" + track_link: "Link ng pag-track:%{url}" + subscription_mailer: + placement_summary_email: + subject: Buod ng mga bagong subsciption orders + greeting: "Magandang araw%{name}," + intro: "Ang nasa ilalim ay buod ng mga subscription orders na na-place para sa %{shop}" + confirmation_summary_email: + subject: Buod ng mga bagong kumpirmadong subscription orders + greeting: "Magandang araw%{name}," + intro: "sa ilalim ay ang buod ng mga subscription order na na-finalize para sa%{shop}." + summary_overview: + total: may kabuuuan na %{count}subscriptions ang minarkahan para sa awtomatikong pagproseso. + success_zero: sa lahat ng ito, walang matagumpay na naproseso + success_some: sa lahat ng ito, %{count}ay matagumpay na naproseso + success_all: Ang lahat ay matagumpay na naproseso + issues: Ang mga detalye ukol sa mga isyu na kinaharap ay mababasa sa baba. + summary_detail: + no_message_provided: Walang dahilan ng error na ibinigay + changes: + title: Hindi Sapat Ang Stock (%{count} orders) + explainer: ang mga order na ito ay naproseso ngunit hindi sapat ang stock para sa ibang ni-request na mga item + empty: + title: Walang Stock (%{count}orders) + explainer: ang mga order na ito ay hindi naproseso sapagkat walang stock ng mga ni-request na item. + complete: + title: Naproseso Na (%{count}na order) + explainer: ang mga order na ito ay namarkahan na kumpleto at hindi na babaguhin + processing: + title: May Error na Kinaharap (%{count}na order) + explainer: ang awtomatikong pagproseso ng mga order na ito ay hindi nagtagumpay dahil sa isang error. ang error ay nailista na upang mabusisi kung saan posibleng nagsimula. + failed_payment: + title: Hindi Nagtagumpay Ang Pagbayad (%{count}na order) + explainer: ang awtomatikong pagproseso ng bayad para sa mga order na ito ay hindi nagtagumpay dahil sa isang error. ang error ay nailista upang mabusisi kung saan posibleng nagsimula. + other: + title: Iba Pang Dahilan ng Error (%{count}na order) + explainer: Hindi naging matagumpay ang awtomatikong pagproseso ng mga order na ito dahil sa hindi maipaliwanag na kadahilanan. Makipag-uganayan sa amin kung nakita ang mensaheng ito. + home: "OFN" + title: Open Food Network + welcome_to: 'Maligayang Pagdating sa' + site_meta_description: "Kami ay nagsimula sa pinakaibaba pataas. Kasama ang mga magsasaka at tagatanim na handang ibahagi at ipagmalaki ang kanilang mga kuwento. May mga tapat at patas na Distributors na handang makipag-usap sa mga gumagawa ng produkto. At mga mamimili na naniniwala na ang mabusising lingguhang pamimili ay..." + search_by_name: Hanapin gamit ang pangalan o lungsod... + producers_join: Ang mga Pilipinong producers ay inaanyayahang naming sumali sa Open Food Network. + charges_sales_tax: Charges GST? + print_invoice: "i-print ang invoice" + print_ticket: "i-print ang ticket" + select_ticket_printer: "pumili ng printer para sa tickets" + send_invoice: "ipadala ang invoice" + resend_confirmation: "ipadala muli ang kumpirmasyon" + view_order: "tignan ang order" + edit_order: "i-edit ang order" + ship_order: "i-ship ang order" + cancel_order: "i-cancel ang order" + confirm_send_invoice: "ang invoice para sa order na ito ay ipapadala sa customer. nais mo bang magpatuloy?" + confirm_resend_order_confirmation: "nais mo bang ipadala muli ang order confirmation email?" + must_have_valid_business_number: "%{enterprise_name}ay dapat may valid na ABN bago makapagpadala ng mga invoice" + invoice: "invoice" + more: "Karagdagang Impormasyon" + say_no: "Hindi" + say_yes: "Oo" + ongoing: Nagaganap + bill_address: Billing Address + ship_address: Address kung saan ipapadala + sort_order_cycles_on_shopfront_by: "Uriin ang mga order cycle sa shopfront gamit ang" + required_fields: ang mga kailangang may sagot ay may nakalagay na asterisk + select_continue: pumili at magpatuloy + remove: Tanggalin + or: o + collapse_all: Itago lahat + expand_all: Ipakita lahat + loading: Naglo-load... + show_more: Ipakita lahat + show_all: Ipakita lahat + show_all_with_more: "Ipakita lahat (%{num}pa)" + cancel: i-cancel + edit: i-edit + clone: Clone + distributors: Mga Distributor + bulk_order_management: Pamamahala sa pangmaramihang order + enterprises: Mga Enterprise + enterprise_groups: Mga grupo + reports: mga ulat + variant_overrides: Imbentaryo + import: i-import + spree_products: mga produktong Spree + all: Lahat + current: kasalukuyan + available: Available + dashboard: Dashboard + undefined: hindi matukoy + unused: Hindi nagamit + admin_and_handling: Admin & Handling + profile: Profile + supplier_only: Supplier Lamang + has_shopfront: May Shopfront + weight: timbang + volume: dami + items: mga item + summary: Buod + detailed: detalyado + updated: na-update + 'yes': "Oo" + 'no': "Hindi" + y: 'Y' + n: 'N' + powered_by: Powered by + blocked_cookies_alert: " ang iyong browser ay maaaring hinaharang ang cookies na kailangan upang magamit ang shopfront na ito. Pindutin sa ibaba upang payagan ang mga cookies at i-reload ang pahina." + allow_cookies: "Payagan ang cookies" + notes: mga tala + error: Error + processing_payment: "Pinoproseso ang bayad..." + no_pending_payments: "walang nakabinbin na mga bayarin" + invalid_payment_state: "hindi valid na status ng pagbabayad" + filter_results: I-filter ang mga resulta + quantity: Dami + pick_up: kunin + copy: Kopyahin + change_my_password: "Palitan ang aking password" + update_password: "i-update ang password" + password_confirmation: Kumpirmasyon ng password + reset_password_token: i-reset ang password token + expired: ay expired na, magrequest ng bago + back_to_payments_list: "ibalik sa listahan ng mga bayad" + maestro_or_solo_cards: "Maestro/Solo cards" + backordered: "na-backorder" + on hand: "on hand" + ship: "ship" + actions: + create_and_add_another: "Gumawa at magdagdag ng isa pa" + create: "gumawa" + cancel: "i-cancel" + save: "i-save" + edit: "i-edit" + update: "i-update" + delete: "Tanggalin" + admin: + begins_at: nagsimula sa + begins_on: nagsisimula sa + customer: Customer + date: Petsa + email: Email + ends_at: nagtatapos sa + ends_on: natapos sa + name: Pangalan + on_hand: on hand + on_demand: on demand + on_demand?: on demand? + order_cycle: Order Cycle + payment: kabayaran + payment_method: Paraan ng pagbayad + phone: Telepono + price: Presyo + producer: Producer + image: larawan + product: Produkto + quantity: Dami + schedule: iskedyul + shipping: pagpapadala + shipping_method: paraan ng pagpapadala + shop: Shop + sku: SKU + status_state: Status + tags: tags + variant: Uri + weight: Timbang + volume: dami + items: mga item + select_all: piliin ang lahat + quick_search: mabilis na paghahanap + clear_all: alisin lahat + start_date: "Petsa na nagsimula" + end_date: "Petsa na natapos" + form_invalid: "ang form ay may nawawala o hindi valid na sagot sa mga patlang" + clear_filters: alisin ang mga filter + clear: alisin + save: i-save + cancel: i-cancel + back: bumalik + show_more: Ipakita lahat + show_n_more: Ipakita%{num}pa + choose: "pumili..." + please_select: pumili + columns: hanay + actions: mga kilos + viewing: "Tinitignan: %{current_view_name}" + description: paglalarawan + whats_this: Ano ito? + tag_has_rules: "mga umiiral na panuntunan para sa tag na ito: %{num}" + has_one_rule: "may isang panuntunan" + has_n_rules: "ay may%{num}na panuntunan" + unsaved_confirm_leave: "may mga hindi naka-save na pagbabago sa pahina na ito. Magpatuloy ng hindi sine-save?" + unsaved_changes: "May mga pagbabago na hindi na-save" + shopfront_settings: + embedded_shopfront_settings: "Embedded Shopfront Settings" + enable_embedded_shopfronts: "Enable Embedded Shopfronts" + embedded_shopfronts_whitelist: "External Domains Whitelist" + number_localization: + number_localization_settings: "Number Localization Settings" + enable_localized_number: "gamitin ang international thousand/decimal separator logic" + invoice_settings: + edit: + title: "settings para sa invoice" + enable_invoices?: "paganahin ang mga invoice?" + invoice_style2?: "gamitin ang alternatibong modelo ng invoice na kinabibilangan ng kabuuang breakdown ng tax bawat rate at impormasyon ng rate ng tax kada item (hindi pa akma para sa mga bansang nagpapakita na presyo na hindi kasama ang tax)" + enable_receipt_printing?: "ipakita ang mga pagpipilian sa pag-print ng mga resibo gamit ang thermal printers sa dropdown ng order." + stripe_connect_settings: + edit: + title: "Stripe Connect" + settings: "settings" + stripe_connect_enabled: paganahin ang pagtanggap ng mga bayad gamit ang Stripe Connect sa mga Shop? + no_api_key_msg: walang Stripe account para sa enterprise na ito + configuration_explanation_html: para sa detalyadong panuto sa pag-configure ng pagsasama ng Stripe Connect, maaari lamang nakumonsulta sa gabay. + status: Status + ok: Ok + instance_secret_key: Instance Secret Key + account_id: Account ID + business_name: Pangalan ng negosyo + charges_enabled: pinagana ang paniningil + charges_enabled_warning: "Babala: Ang paniningil ay hindi pa napapagana sa iyong account" + auth_fail_error: ang API key na inyong binigay ay invalid + empty_api_key_error_html: Walang Stripe API key na naibigay. Upang i-set ang inyong API key, sundinang mga panuto + matomo_settings: + edit: + title: "Matomo Settings" + matomo_url: "Matomo URL" + matomo_site_id: "Matomo Site ID" + info_html: "ang Matomo ay isang Web at Mobile Analytics. Maaari kang mag-host ng Matomo sa mga lugar o gumamit ng mga serbisyong naka-cloud. Tignanmatomo.org para sa karagdagang impormasyon." + config_instructions_html: "Dito ay maaaring ayusin ang pagsasama ng OFN Matomo. ang URL ng Matomo sa ibaba ay ituturo ka sa Matomo kung saan ipapadala ang impormasyon ukol sa pagtatrack ng gumagamit; kung iiwanang blanko, ay hindi gagana ang pag-track ng Matomo. ang paglagay ng SITE ID ay hindi sapilitan ngunit maaaring makatulong kung ikaw ay nagta-track na mahigit sa isang website sa isang pagkakataon; ito ay matatagpuan sa Matomo instance console." + customers: + index: + new_customer: "bagong customer" + code: Code + duplicate_code: "ang code na ito ay nagamit na" + bill_address: "Billing Address" + ship_address: "Address kung saan ipapadala" + update_address_success: 'matagumpay na na-update ang address' + update_address_error: 'pakisagutan lahat ng kailangang impormasyon' + edit_bill_address: 'i-edit ang Billing Address' + edit_ship_address: 'i-edit ang address kung saan ipapadala' + required_fileds: 'ang mga kailangang may sagot ay may nakalagay na asterisk' + select_country: 'Piliin ang bansa' + select_state: 'pumili ng status' + edit: 'i-edit' + update_address: 'i-update ang address' + confirm_delete: 'siguradong tatanggalin?' + search_by_email: "hanapin gamit ang email/code..." + guest_label: 'Guest checkout' + destroy: + has_associated_orders: 'hindi tagumpay ang pagtanggal: ang customer ay may mga iniugnay na order sa kaniyang shop' + contents: + edit: + title: nilalaman + header: Header + home_page: Homepage + producer_signup_page: pahina para sa pagsign-up ng Producer + hub_signup_page: pahina para sa pagsign-up ng Hub + group_signup_page: pahina para sa pagsign-up ng Grupo + main_links: Link para sa pangunahing menu + footer_and_external_links: Footer at panlabas na mga link + your_content: ang iyong nilalaman + user_guide: gabay sa gumagamit + enterprise_fees: + index: + title: "bayad para sa enterprise" + enterprise: "Enterprise" + fee_type: "uri ng bayad" + name: "pangalan" + tax_category: "kategorya ng tax" + calculator: "calculator" + calculator_values: "calculator values" + search: "hanapin" + name_placeholder: "hal. bayad sa pag-iimpake" + enterprise_groups: + index: + new_button: bagong grupo ng enterprise + enterprise_roles: + form: + manages: namamahala + enterprise_role: + manages: namamahala + products: + unit_name_placeholder: 'hal. mga kumpol' + index: + unit: yunit + display_as: ipakita bilang + category: kategorya + tax_category: kategorya ng tax + inherits_properties?: minana ang mga katangian? + available_on: Magagamit Nakabukas + av_on: "Av On" + import_date: na-import + upload_an_image: maglagay ng larawan + seo: + product_search_keywords: "mga keyword sa paghahanap ng produkto" + product_search_tip: "isulat ang mga salita para mahanap ang inyong produkto sa mga shop. gumamit ng laktaw upang paghiwalayin ang bawat keyword." + SEO_keywords: "SEO Keywords" + seo_tip: "isulat ang mga salita para mahanap ang inyong produkto sa web. gumamit ng laktaw upang paghiwalayin ang bawat keyword." + search: "hanapin" + properties: + property_name: "Pangalan ng Pag-aari" + inherited_property: "minanang pag-aari" + variants: + infinity: "walang hanggan" + to_order_tip: "ang mga item na made to order ay walang paraan ng pag-set ng lebel ng stock, tulad ng mga tinapay na ginagawa lamang kapag may order." + back_to_products_list: "bumalik sa listahan ng produkto" + editing_product: "ine-edit ang mga produkto" + tabs: + product_details: "Detalye ng produkto" + group_buy_options: "pagpipilian para sa Grupong pagbili" + images: "larawan" + variants: "mga uri" + product_properties: "mga katangian ng produkto" + product_import: + title: paglipat ng produkto + file_not_found: 'ang file ay hindi mahanap o mabuksan ' + no_data: walang data na mahanap sa spreadsheet + confirm_reset: "ito ay ilalagay ang lebel ng stock ng lahat ng mga produkto sa zero\nmga enterprise na hindi makikita sa nilagay na file." + model: + no_file: "error: walang file na na-upload" + could_not_process: "hindi maproseso ang file: invalid na uri ng file" + incorrect_value: maling halaga + conditional_blank: ay hindi maaaring blanko kung yunit_uri ay blanko + no_product: walang katugmang produkto sa database + not_found: hindi mahanap sa database + not_updatable: ay hindi maaring i-update sa mga umiiral na produkto gamit ang paglilipat ng produkto + blank: hindi maaaring iwanang blanko + products_no_permission: walang permiso na pamahalaan ang mga produkto para sa enterprise na ito + inventory_no_permission: Wala kang permiso na gumawa ng imbentaryo para sa producer na ito + none_saved: hindi matagumpay na na-save ang mga produkto + line_number: "linya%{number}:" + encoding_error: "Paki-check ang language setting ng inyong source file at siguraduhing ito ay naka-save gamit ang UTF-8 encoding" + unexpected_error: "ang paglilipat ng produkto ay may kinaharap na error habang binubuksan ang file: %{error_message}" + index: + notice: "Paalala" + beta_notice: "ang feature na ito ay nasa beta pa: maari kang makaranas ng mga error habang ginagamit ito. huwag mag-atubiling kumontak sa suporta." + select_file: pumili ng spreadsheet na i-a-upload + spreadsheet: spreadsheet + choose_import_type: pumili ng uri ng paglilipat + import_into: uri ng paglilipat + product_list: listahan ng produkto + inventories: mga imbentaryo + import: i-import + upload: i-upload + csv_templates: CSV Templates + product_list_template: i-download ang Product List template + inventory_template: i-download ang Inventory template + category_values: mga available na halaga ng kategorya + product_categories: kategorya ng produkto + tax_categories: kategorya ng tax + shipping_categories: mga kategorya ng pagpapadala + import: + review: suriin + import: i-import + save: i-save + results: Mga Resulta + save_imported: i-save ang inilipat na mga produkto + no_valid_entries: walang nahanap na mga valid na entry + none_to_save: Walang mga entry na maaaring i-save + some_invalid_entries: ang mga nilipat na file ay naglalaman na hindi valid na mga entry + fix_before_import: Ayusin ang error na ito at subukang ilipat muli ang file + save_valid?: i-save ang mga valid na entry at hayaan ang iba? + no_errors: walang error na nakita! + save_all_imported?: i-save lahat ng mga nilipat na produkto? + options_and_defaults: mga pagpipilian sa paglilipat at mga default + no_permission: walang permiso na pamahalaan ang enterprise na ito + not_found: hindi mahanap ang enterprise sa database + no_name: walang pangalan + blank_enterprise: ang ibang mga produkto ay walang tinutukoy na enterprise + reset_absent?: i-reset ang mga nawawalang produkto + reset_absent_tip: i-set sa zero ang mga produkto na hindi makikita sa file + overwrite_all: sulatan lahat + overwrite_empty: sulatan kung walang nakalagay + default_stock: i-set ang lebel ng stock + default_tax_cat: i-set ang kategorya ng tax + default_shipping_cat: i-set ang kategorya ng pagpapadala + default_available_date: i-set ang available na petsa + validation_overview: pagtingin sa pagpapatunay ng paglipat + entries_found: May mga entry na nahanap sa inilipat na file + entries_with_errors: ang mga item ay naglalaman ng error at hindi maililipat + products_to_create: ang mga produkto ay gagawin + products_to_update: ang mga produkto ay i-a-update + inventory_to_create: ang imbentaryo ng mga item ay gagawin + inventory_to_update: ang mga imbentaryong item ay i-a-update + products_to_reset: ang mga produkto na narito ay mare-reset ang stock sa zero + inventory_to_reset: ang imbentaryo ng mga item na narito ay mare-reset ang stock sa zero + line: linya + item_line: linya ng item + import_review: + not_updatable_tip: "ang mga patlang ay hindi ma-update sa pamamagitan ng maramihang paglipat para sa mga produkto:" + fields_ignored: ang mga linya na ito ay hindi mapapansin kapag sinave ang mga nilipat na produkto + entries_table: + not_updatable: ang patlang na ito ay hindi maaaring ma-update sa pamamagitan ng maramihang paglipat ng mga produkto + save_results: + final_results: Ilipat ang pinakahuling mga resulta + products_created: ang mga produkto ay nagawa na + products_updated: inupdate ang mga produkto + inventory_created: ang mga imbentaryo ng item ay nagawa na + inventory_updated: inupdate ang mga inimbentaryong item + products_reset: na-reset sa zero ang lebel ng stock ng mga produkto + inventory_reset: na-reset sa zero ang lebel ng stock ng mga imbentaryo ng item + all_saved: "lahat ng mga item ay matagumpay na na-save" + some_saved: "ang mga item ay matagumpay na na-save" + save_errors: i-save ang mga error + import_again: mag-upload ng isa pang file + view_products: pumunta sa pahina ng mga produkto + view_inventory: pumunta sa pahina ng mga imbentaryo + variant_overrides: + loading_flash: + loading_inventory: NILO-LOAD ANG IMBENTARYO + index: + title: imbentaryo + description: gamitin ang pahina na ito para pamahalaan ang mga imbentaryo ng inyong enterprise. ang kahit anong detalye ng produkto na sinet dito ay mapapalitan ang mga na-set sa pahina ng "Mga Produkto" + enable_reset?: paganahin ang pag-reset ng stock? + default_stock: "Default na Stock" + inherit?: gayahin? + add: idagdag + hide: itago + import_date: na-import + select_a_shop: pumili ng shop + review_now: tignan ngayon + new_products_alert_message: mayroong%{new_product_count}bagong mga produkto na maaaring idagdag sa inyong imbentaryo + currently_empty: ang iyong imbentaryo ay kasalukuyang walang laman + no_matching_products: Walang nahanap na katumbas na produkto sa inyong imbentaryo + no_hidden_products: Walang produkto na nakatago mula sa imbentaryong ito + no_matching_hidden_products: walang nakatagong produkto na tugma sa inyong hinahanap na pamantayan + no_new_products: walang bagong produkto na maaaring idagdag sa inyong imbentaryo + no_matching_new_products: walang bagong mga produkto na tugma sa inyong hinahanap na pamantayan + inventory_powertip: Ito ang imbentaryo ng inyong mga produkto. Upang magdagdag ng produkto sa inyong imbentaryo, piliin ang "Bagong Produkto" sa viewing dropdown. + hidden_powertip: ang mga produktong ito ay nakatago sa inyong imbentaryo at hindi maaaring idagdag sa inyong shop. maaaring pindutin ang "Idagdag" para madagdag ang produkto sa inyong imbentaryo. + new_powertip: ang mga produkto na ito ay maaaring idagdag sa inyong imbentaryo. pindutin ang "idagdag" para magdagdag ng produkto sa inyong imbentaryo, o "itago" para hindi ito makita. Maaari mo itong baguhin sa ibang panahon! + controls: + back_to_my_inventory: bumalik sa aking imbentaryo + orders: + invoice_email_sent: 'ang invoice email ay naipadala na' + order_email_resent: 'ang email ng order ay napadala na muli' + bulk_management: + tip: "gamitin ang pahina na ito para baguhin ang dami ng mga produkto sa maramihang mga order. maaari ding magtanggal ng mga produkto mula sa order kung kinakailangan." + shared: "ibinahaging pinagkuhanan?" + order_no: "Order No." + order_date: "nakumpleto sa" + max: "Labis" + product_unit: "Produkto: Yunit" + weight_volume: "Timbang/Dami" + ask: "itanong?" + page_title: "Pamamahala sa pangmaramihang order" + actions_delete: "burahin ang napili" + loading: "nilo-load ang mga order" + no_results: "walang nahanap na mga order" + group_buy_unit_size: "laki ng yunit para sa maramihang pagbili" + total_qtt_ordered: "Kabuuang dami ng in-order" + max_qtt_ordered: "sagad na dami ng na-order" + current_fulfilled_units: "kasalukuyang tapos na mga yunit" + max_fulfilled_units: "sagad na natapos na yunit" + order_error: "ang ibang error ay dapat munang ayusin bago makapag-update ng mga order.\nang mga patlang na may pulang border ay may mga error." + variants_without_unit_value: "BABALA: Ang ibang variant ay walang halaga ang yunit" + select_variant: "pumili ng variant" + enterprise: + select_outgoing_oc_products_from: pumili ng lumalabas na mga produktong OC mula + enterprises: + index: + title: enterprises + new_enterprise: bagong enterprise + producer?: "Producer?" + package: Package + status: Status + manage: pamahalaan + form: + about_us: + desc_short: maikling paglalarawan + desc_short_placeholder: magsalaysay ukol sa inyong enterprise gamit ang isa hanggang dalawang pangungusap. + desc_long: tungkol sa amin + desc_long_placeholder: magkuwento sa Customer tungkol sa inyong sarili. Ang impormasyon na ito ay makikita at lalabas sa inyong profile. + business_details: + abn: ABN + abn_placeholder: hal. 99 123 456 789 + acn: ACN + acn_placeholder: hal. 123 456 789 + display_invoice_logo: ipakita ang Logo sa mga invoice + invoice_text: magdagdag ng sariling mensahe sa dulo ng bawat invoice + contact: + name: pangalan + name_placeholder: hal. Gustav Plum + email_address: pampublikong email address + email_address_placeholder: hal. inquiries@fresh-food.com + email_address_tip: "ang email address na ito ay makikita sa iyong pampublikong profile" + phone: telepono + phone_placeholder: hal. 98 7654 3210 + website: website + website_placeholder: hal. www.truffles.com + enterprise_fees: + name: pangalan + fee_type: uri ng kabayaran + manage_fees: pamahalaan ang mga bayarin para sa enterprise + no_fees_yet: wala ka pang kahit anong bayaring pang-enterprise + create_button: gumawa ng isa ngayon + images: + logo: Logo + promo_image_placeholder: 'ang larawan na ito ay makikita sa "tungkol sa amin"' + promo_image_note1: 'TANDAAN:' + promo_image_note2: ang kahit anong larawan na ilalagay rito ay maka-crop sa 1200 x 260. + promo_image_note3: ang promo na larawan ay makikita sa taas na pahina ng profile ng enterprise at pop-ups. + inventory_settings: + text1: maaari mong piliin na pamahalaan ang lebel ng mga stock at presyo sa iyong + inventory: imbentaryo + text2: > + kung ikaw ay gumagamit ng tool para sa imbentaryo, piliin na ang mga + bagong produktong dinagdag ng inyong mga supplier ay kailangan munang + idagdag sa inyong imbentaryo bago ito mai-stock. kung hindi ka naman + gumagamit ng imbentaryo para pamahalaan ang inyong produkto, piliin + ang "nirerekomenda" sa pagpipilian sa baba: + preferred_product_selection_from_inventory_only_yes: mga bagong produkto ay maaaring ilagay sa aking shopfront (nirerekomenda) + preferred_product_selection_from_inventory_only_no: ang mga bagong produkto ay dapat idagdag muna sa aking imbentaryo bago mailagay sa aking shopfront. + payment_methods: + name: pangalan + applies: naaangkop? + manage: pamahalaan ang mga paraan ng pagbabayad + no_method_yet: wala ka pang kahit anong paraan ng pagbabayad. + create_button: gumawa ng bagong paraan ng pagbabayad + create_one_button: gumawa ng isa ngayon + primary_details: + name: pangalan + name_placeholder: hal. Professor Plum's Biodynamic Truffles + groups: mga grupo + groups_tip: pumili ng grupo o rehiyon kung saan ka kabilang. makakatulong ito sa mga customer sa paghahanap ng inyong enterprise. + groups_placeholder: magsimulang magsulat para maghanap ng mga grupo... + primary_producer: pangunahing producer + primary_producer_tip: piliin ang "Producer" kung ikaw ay pangunahing producer ng pagkain. + producer: Producer + any: kahit ano + none: wala + own: sarili + sells: nagbebenta + sells_tip: "Wala- ang mga enterprise ay hindi nagbebenta ng direkta sa mga customer
Sarili- ang mga enterprise ay nagbebenta ng sariling mga produkto sa mga customer
Iba- ang enterprise ay maaaring magbenta ng sariling produkto pati na rin ang mga produkto ng enterprise.
" + visible_in_search: makikita sa paghahanap? + visible_in_search_tip: timutukoy kung ang enterprise na ito ay makikita ng mga customer kapag naghahanap sa site. + visible: nakikita + not_visible: hindi nakikita + permalink: Permalink (walang espasyo) + permalink_tip: "ang permalink na ito ay ginamit para gumawa ng url sa inyong shop: %{link}your-shop-name/shop" + link_to_front: Link sa shop front + link_to_front_tip: direktang link sa inyong shopfront sa Open Food Network. + ofn_uid: UID sa OFN + ofn_uid_tip: ang natatanging id na ito ay ginagamit para matukoy ang enterprise sa Open Food Network. + shipping_methods: + name: pangalan + applies: naaangkop? + manage: pamahalaan ang mga paraan ng pagpapadala + create_button: gumawa ng bagong paraan ng pagpapadala + create_one_button: gumawa ng isa ngayon + no_method_yet: wala ka pang inilagay na paraan ng pagpapadala. + shop_preferences: + shopfront_requires_login: "nakikita sa publiko ang shopfront?" + shopfront_requires_login_tip: "pumili kung nais na maglog-in muna ang customer bago makita ang shopfront o nakikita ito ng lahat." + shopfront_requires_login_false: "publiko" + shopfront_requires_login_true: "nakikita lamang ng rehistradong mga customer" + recommend_require_login: "nirerekomenda namin na kailangang maglog-in muna ang Users kapag ang mga order ay maaaring baguhin." + allow_guest_orders: "mga order ng guest" + allow_guest_orders_tip: "payagang mag-checkout bilang guest o kailangang rehistrado ang user." + allow_guest_orders_false: "kailangang maglog-in para makapag-order" + allow_guest_orders_true: "payagan ang guest checkout" + allow_order_changes: "magpalit ng mga order" + allow_order_changes_tip: "payagan ang mga kustomer na palitan ang kanilang order hanggang bukas ang order cycle" + allow_order_changes_false: "ang na-place na mga order ay hindi na maaaring palitan o i-cancel" + allow_order_changes_true: "maaari pang palitan ng customer o i-cancel ang kanilang mga order habang ang order cycle ay bukas pa." + enable_subscriptions: "mga subscription" + enable_subscriptions_tip: "paganahina ng paggamit ng mga subscription?" + enable_subscriptions_false: "huwag paganahin" + enable_subscriptions_true: "paganahin" + shopfront_message: "mensahe sa Shopfront" + shopfront_message_placeholder: > + opsyonal na mensahe para batiin ang mga customers at upang maipaliwanag + kung paano mamili sa iyong shop. kung ang teksto ay ipinasok dito, ito + ay makikita sa home tab kapag ang customer ay nasa loob na ng inyong + shopfront. + shopfront_message_link_tooltip: "ilagay/ i-edit ang link" + shopfront_message_link_prompt: "ilagay ang URL na ipapasok" + shopfront_closed_message: "pagsasarang mensahe ng Shopfront" + shopfront_closed_message_placeholder: > + isang mensahe na nagbibigay ng mas detalyadong paliwanag kung bakit + ang iyong shop ay sarado at/o kapag ang mga customer ay makakaasang + magbubukas ito muli. Ito ay makikita sa iyong shop kapag ikaw ay walang + aktibong order cycle (hal. sarado ang shop). + shopfront_category_ordering: "kategorya ng pag-order sa Shopfront" + open_date: "petsa ng pagbubukas" + close_date: "petsa ng pagsasara" + social: + twitter_placeholder: "hal. @the_prof" + instagram_placeholder: "hal. the_prof" + facebook_placeholder: "hal. www.facebook.com/PageNameHere" + linkedin_placeholder: "hal. www.linkedin.com/in/YourNameHere" + stripe_connect: + connect_with_stripe: "Kumonekta sa Stripe" + stripe_connect_intro: "upang tumanggap ng bayad gamit ang credit card, kailangan munang ikonekta ang iyong Stripe account sa Open Food Network. Gamitin ang pindutan sa kanan para magsimula." + stripe_account_connected: "ang Stripe account ay konektado na." + disconnect: "tanggalin ang koneksyon ng account" + confirm_modal: + title: Kumonekta sa Stripe + part1: ang Stripe ay isang serbisyong nagpoproseso ng mga bayad na ginagawang posible para sa mga shop sa OFN na tumanggap ng bayad gamit ang mga credit card mula sa mga customer. + part2: para magamit ito, kailangang ikonekta ang iyong Stripe account sa OFN. ang pagpindot ng "pumapayag ako" sa ibaba ay ididirekta ka sa Stripe website kung saan mo maaaring ikonek ang iyong Stripe account o gumawa ng bago kung wala ka pa nito. + part3: pinapayagan nito ang Open Food Network na tumanggap para sa iyo ng bayad gamit ang mga credit card mula sa mga customer. tandaan na kailangan mong pangalagaan ang sarili mong Stripe Account, bayaran ang serbisyo ng Stripe, isaayos ang mga paniningil at gawin ang serbisyo sa customer sa sarili mong paraan. + i_agree: pumapayag ako + cancel: i-cancel + tag_rules: + default_rules: + by_default: bilang default + no_rules_yet: wala pang default na panuntunan na ginagamit + add_new_button: '+ magdagdag ng bagong default na panuntunan' + no_tags_yet: walang pang tag na magagamit sa enterprise na ito + no_rules_yet: wala pang panuntunan na magagamit sa tag na ito + for_customers_tagged: 'Para sa mga customer na naka-tag:' + add_new_rule: '+ magdagdag ng bagong panuntunan' + add_new_tag: '+ Magdagdag ng bagong tag' + users: + email_confirmation_notice_html: "ang kumpirmasyon ng email ay nakabinbin pa. kami ay nagpadala ng kumpirmasyon ng email sa %{email}." + resend: Ipadala muli + owner: 'May-ari' + contact: "Makipag-usap" + contact_tip: "ang tagapamahala na makakatanggap ng enterprise emails at notipikasyon. kailangang may kumpirmadong email address." + owner_tip: ang pangunahing gumagamit na responsable sa enterprise na ito. + notifications: notipikasyon + notifications_tip: ang mga notipikasyon tungkol sa mga order ay ipapadala sa email address na ito. + notifications_placeholder: hal. gustav@truffles.com + notifications_note: 'Tandaan: ang bagong email address ay kailangang kumpirmado bago magamit' + managers: Tagapamahala + managers_tip: ang ibang gagamit na may permisong pamahalaan ang enterprise na ito. + invite_manager: "Mag-imbita ng Tagapamahala" + invite_manager_tip: "mag-imbita ng hindi rehistradong gagamit na mag-sign-up at maging tagapamahala ng enterprise na ito." + add_unregistered_user: "magdagdag ng hindi rehistradong user" + email_confirmed: "ang email ay kumpirmado" + email_not_confirmed: "ang email ay hindi kumpirmado" + actions: + edit_profile: Settings + properties: mga katangian + payment_methods: Mga Paraan ng Pagbabayad + payment_methods_tip: ang enterprise na ito ay walang mga paraan ng pagbabayad + shipping_methods: mga paraan ng pagpapadala + shipping_methods_tip: ang enterprise na ito ay may mga paraan ng pagpapadala + enterprise_fees: bayad para sa enterprise + enterprise_fees_tip: ang enterprise na ito walang mga bayarin + admin_index: + name: Pangalan + role: papel na gagampanan + sells: nagbebenta + visible: nakikita? + owner: May-ari + producer: Producer + change_type_form: + producer_profile: Profile ng Producer + connect_ofn: kumonekta gamit ang OFN + always_free: PALAGING LIBRE + producer_description_text: ilagay ang inyong mga produkto sa Open Food Network, upang mapayagan ang mga Hub na mag-stock ng iyong produkto sa kanilang mga tindahan. + producer_shop: Producer Shop + sell_your_produce: magbenta ng sariling produkto + producer_shop_description_text: ibenta ang iyong mga produkto direkta sa mga customer sa pamamagitan ng iyong sariling Open Foof Network shopfront. + producer_shop_description_text2: ang 'Producer Shop' ay para lamang sa iyong produkto, kung nais mong magbenta ng mga produktong itinanim o ginawa sa labas ng site, piliin ang 'Producer Hub' + producer_hub: Producer Hub + producer_hub_text: magbenta ng produkto mula sa sarili at sa iba + producer_hub_description_text: ang iyong enterprise ang saligan ng iyong lokal na sistema ng pagkain. maaari mong ibenta ang sarili mong produkto pati na rin ang mga produktong pinagsama sama mula sa ibang enterprise gamit ang iyong shop sa Open Food Network. + profile: Profile lamang + get_listing: kumuha ng listahan + profile_description_text: Maaari kang mahanap ng mga tao sa Open Food Network. Ang iyong enterprise ay makikita sa mapa, at maaaring mahanap sa mga listahan. + hub_shop: Hub Shop + hub_shop_text: magbenta ng produkto mula sa iba + hub_shop_description_text: ang iyong enterprise ang saligan ng iyong lokal na sistema ng pagkain. maaari mong pagsama samahin ang mga produkto mula sa ibang enterprise at ibenta ito gamit ang iyong shop sa Open Food Network. + choose_option: pumili mula sa pagpipilian sa itaas. + change_now: palitan ngayon + enterprise_user_index: + loading_enterprises: NILO-LOAD ANG MGA ENTERPRISE + no_enterprises_found: walang mahanap na enterprise + search_placeholder: hanapin gamit ang pangalan + manage: pamahalaan + manage_link: settings + producer?: "Producer?" + package: "Package" + status: "Status" + new_form: + owner: may-ari + owner_tip: ang pangunahing gumagamit na responsable sa enterprise na ito. + i_am_producer: ako ay isang producer + contact_name: Contact name + edit: + editing: 'Settings:' + back_link: bumalik sa listahan ng mga enterprise + new: + title: bagong enterprise + back_link: bumalik sa listahan ng mga enterprise + remove_logo: + remove: "alisin ang larawan" + removed_successfully: "matagumpay na natanggal ang logo" + immediate_removal_warning: "ang logo ay tatanggalin agad pagkatapos mong magkumpirma." + remove_promo_image: + remove: "alisin ang larawan" + removed_successfully: "ang promo na larawan ay matagumpay na natanggal" + immediate_removal_warning: "ang promo na larawan ay tatanggalin agad pagkatapos mong magkumpirma." + welcome: + welcome_title: Welcome sa Open Food Network! + welcome_text: matagumpay na nagawa ang + next_step: sunod na hakbang + choose_starting_point: 'pumili ng package:' + profile: 'profile' + producer_profile: 'Profile ng Producer' + invite_manager: + user_already_exists: "ang user ay rehistrado na" + error: "may nangyaring mali" + order_cycles: + loading_flash: + loading_order_cycles: NILO-LOAD ANG MGA ORDER CYCLE + loading: NILO-LOAD... + new: + create: "gumawa" + cancel: "i-cancel" + back_to_list: "bumalik sa listahan" + edit: + advanced_settings: "Advanced settings" + save: "i-save" + save_and_next: "i-save at sunod" + next: "sunod" + cancel: "i-cancel" + back_to_list: "bumalik sa listahan" + save_and_back_to_list: "i-save at bumalik sa listahan" + choose_products_from: "pumili sa mga produkto mula sa:" + incoming: + save: "i-save" + save_and_next: "i-save at sunod" + next: "sunod" + cancel: "i-cancel" + back_to_list: "bumalik sa listahan" + outgoing: + outgoing: "papalabas" + distributor: "Distributor" + products: "mga produkto" + tags: "tags" + delivery_details: "detalye ng pag-deliver" + fees: "mga bayarin" + previous: "nauna" + save: "i-save" + save_and_back_to_list: "i-save at bumalik sa listahan" + cancel: "i-cancel" + back_to_list: "bumalik sa listahan" + wizard_progress: + edit: "1. Pangkalahatang Setting" + incoming: "2. Papasok na mga produkto" + outgoing: "3. Palabas na mga produkto" + exchange_form: + pickup_time_tip: kapag ang mga order mula sa OC ay handa na para sa customer + pickup_instructions_placeholder: "mga panuto sa pagpick-up" + pickup_instructions_tip: ang mga panuto na ito ay ipapakita sa mga customer pagkatapos nilang makumpleto ang pag-order + pickup_time_placeholder: "handa na para sa (hal. Date / Time)" + receival_instructions_placeholder: "panuto sa pagtanggap" + add_fee: 'idagdag ang bayad' + remove: 'tanggalin' + selected: 'napili' + add_exchange_form: + add_supplier: 'magdagdag ng supplier' + add_distributor: 'magdagdag ng distributor' + advanced_settings: + title: Advanced settings + choose_product_tip: maaring limitahan ang mga produktong pumapasok at lumalabas sa imbentaryo lamang ng%{inventory} + preferred_product_selection_from_coordinator_inventory_only_here: imbentaryo lamang ng coordinator + preferred_product_selection_from_coordinator_inventory_only_all: lahat ng produkto + save_reload: i-save at i-reload ang pahina + coordinator_fees: + add: idagdag ang bayad sa coordinator + filters: + search_by_order_cycle_name: "hanapin gamit ang pangalan ng order cycle..." + involving: "kinasangkot" + any_enterprise: "kahit anong enterprise" + any_schedule: "kahit anong petsa" + form: + general_settings: "Pangkalahatang Setting" + incoming: papasok + supplier: Supplier + receival_details: detalye ng pagtanggap + fees: mga bayarin + outgoing: papalabas + distributor: Distributor + products: mga produkto + tags: tags + add_a_tag: magdagdag ng tag + delivery_details: detalye ng pick-up/pagdeliver + index: + schedule: iskedyul + schedules: iskedyul + new_schedule: bagong iskedyul + name_and_timing_form: + name: Pangalan + orders_open: ang mga order ay magbubukas sa + coordinator: coordinator + orders_close: sarado ang mga order + row: + suppliers: mga supplier + distributors: mga distributor + variants: mga uri + simple_form: + ready_for: handa para sa + ready_for_placeholder: petsa/ oras + customer_instructions: panuto ng Customer + customer_instructions_placeholder: tala para sa pag-pick-up o pagdeliver + products: mga produkto + fees: mga bayarin + destroy_errors: + orders_present: ang order cycle na ito ay napili na ng isang customer at hindi na maaaring tanggalin. upang maiwasan na ma-access muli, isarado muna ito. + schedule_present: ang order cycle na ito ay naka-link sa isang iskedyul at hindi maaaring tanggalin. maaaring tanggalin muna ang link o tanggalin muna ang iskedyul. + bulk_update: + no_data: may nangyaring mali. walang mahanap na order cycle. + date_warning: + msg: ang order cycle na ito ay naka-link sa %{n}na bukas na subscription order. ang pagpapalit ng petsa ay hindi maaapektuhan ang iba pang order na nagawa na, ngunit kung maaaring iwasan ay huwag na muling gawin. Gusto bang magpatuloy? + cancel: i-cancel + proceed: magpatuloy + producer_properties: + index: + title: mga katangian ng producer + proxy_orders: + cancel: + could_not_cancel_the_order: hindi ma-cancel ang order + resume: + could_not_resume_the_order: hindi maituloy ang order + shared: + user_guide_link: + user_guide: gabay sa gumagamit + enterprises_hubs_tabs: + has_no_payment_methods: "%{enterprise}ay walang paraan ng pagbabayad" + has_no_shipping_methods: "%{enterprise}ay walang paraan ng pagpapadala" + has_no_enterprise_fees: "%{enterprise}ay walang mga bayarin sa enterpise" + enterprise_issues: + create_new: gumawa ng bago + resend_email: ipadala muli ang email + has_no_payment_methods: "%{enterprise}ay kasakuluyang walang mga paraan ng pagbabayad" + has_no_shipping_methods: "%{enterprise}ay kasalukuyang walang mga paraan ng pagpapadala" + email_confirmation: "ang kumpirmasyon ng email ay nakabinbin pa. kami ay nagpadala ng kumpirmasyon ng email sa %{email}." + not_visible: "%{enterprise}ay hindi nakikita kaya hindi matagpuan sa mapa o sa kahit saang paghahanap" + reports: + hidden: NAKATAGO + unitsize: LAKI KADA YUNIT + total: KABUUAN + total_items: KABUUAN NG MGA ITEM + supplier_totals: kabuuang order cycle ng mga supplier + supplier_totals_by_distributor: kabuuang order cycle ng mga supplier ng Distributor + totals_by_supplier: kabuuang order cycle ng Distributor ng Supplier + customer_totals: kabuuang order cycle ng customer + all_products: lahat ng produkto + inventory: Imbentaryo (on hand) + lettuce_share: LettuceShare + mailing_list: Listahan ng mga pagpapadalahan + addresses: Mga address + payment_methods: ulat ng mga paraan ng pagbabayad + delivery: ulat ukol sa pagdeliver + tax_types: uri ng tax + tax_rates: rate ng mga tax + pack_by_customer: binalot ng Customer + pack_by_supplier: binalot ng Supplier + orders_and_distributors: + name: mga order at Distributor + description: mga order na may detalye ng Distributor + bulk_coop: + name: Bultuhang Co-Op + description: ulat para sa mga order ng Bultuhang Co-Op + payments: + name: ulat ng mga bayad + description: ulat para sa mga bayad + orders_and_fulfillment: + name: ulat ng mga order at fulfillment + customers: + name: mga customer + products_and_inventory: + name: mga produkto at imbentaryo + users_and_enterprises: + name: mga gumagamit at enterprise + description: pag-aari ng enterprise at status + order_cycle_management: + name: pamamahala sa order cycle + sales_tax: + name: tax ng mga benta + xero_invoices: + name: mga invoice ng Xero + description: mga invoice na ililipat sa Xero + packing: + name: ulat sa pagbabalot + enterprise_fee_summary: + name: "buod ng bayad sa enterprise" + description: "buod ng mga nakolektang bayad sa enterprise" + subscriptions: + subscriptions: mga subscription + new: bagong subscription + create: gumawa ng subscription + edit: ayusin ang subscription + table: + edit_subscription: ayusin ang subsciption + pause_subscription: ihinto saglit ang subscription + unpause_subscription: ituloy ang subscription + cancel_subscription: itigil ang subscription + filters: + query_placeholder: "hanapin gamit ang email..." + setup_explanation: + just_a_few_more_steps: 'ilang hakbang na lamang bago ka makapagsimula:' + enable_subscriptions: "paganahin ang subscription sa kahit isa sa iyong mga shop" + enable_subscriptions_step_1_html: 1. pumunta sa%{enterprises_link}pahina, hanapin ang iyong shop at pindutin ang "pamahalaan" + enable_subscriptions_step_2: 2. sa ilalim ng "shop preference", paganahin ang Subscriptions sa pagpipilian + set_up_shipping_and_payment_methods_html: iset-up ang %{shipping_link}at%{payment_link} na pagbabayad + set_up_shipping_and_payment_methods_note_html: tandaan na Cash at Stripe na pamamaraan ang maaaring
gamitin sa mga subscription + ensure_at_least_one_customer_html: siguraduhing mayroong kahit isang%{customer_link}na nakikita + create_at_least_one_schedule: gumawa ng kahit isang iskedyul + create_at_least_one_schedule_step_1_html: 1. pumunta sa %{order_cycles_link}pahina + create_at_least_one_schedule_step_2: 2. gumawa ng order cycle kung hindi pa ito nagagawa + create_at_least_one_schedule_step_3: 3. pindutin ang '+ bagong iskedyul' at sagutan ang form + once_you_are_done_you_can_html: kapag natapos na ito, maaari kang%{reload_this_page_link} + reload_this_page: i-reload ang pahina na ito + steps: + details: 1. pangunahing detalye + address: 2. tirahan + products: 3. magdagdag ng mga produkto + review: 4. suriin at i-save + subscription_line_items: + this_is_an_estimate: | + Ang mga nakalagay na presyo ay tantiya lamang at kinakalkula sa panahon na binago ang subscription. + Kung magpapalit ka ng presyo o bayarin, maa-update ang mga order ngunit ang subscription ay ipapakita pa rin ang dating mga halaga. + not_in_open_and_upcoming_order_cycles_warning: "walang bukas o paparating na mga order cycle para sa produkto na ito." + autocomplete: + name_or_sku: "PANGALAN O SKU" + quantity: "dami" + add: "idagdag" + details: + details: detalye + invalid_error: sagutan ang mga kailangang detalte... + allowed_payment_method_types_tip: Cash at pamamaraang Stripe lamang ang maaaring gamitin sa kasalukuyan. + credit_card: Credit Card + charges_not_allowed: ang paniningil ay hindi pinapayagan ng customer na ito + no_default_card: ang customer ay walang mga card na maaaring singilin + card_ok: ang customer ay may card na maaaring singilin + begins_at_placeholder: "pumili ng petsa" + ends_at_placeholder: "opsyonal" + loading_flash: + loading: NILOLOAD ANG MGA SUBSCRIPTION + review: + details: detalye + address: tirahan + products: mga produkto + no_open_or_upcoming_order_cycle: "walang paparating na order cycle" + products_panel: + save: "I-SAVE" + saving: "SINESAVE" + saved: "NA-SAVE NA" + product_already_in_order: ang produkto na ito ay naidagdag na sa order. ayusin ng direkta ang dami. + stock: + insufficient_stock: "walang sapat na stock" + out_of_stock: "Walang stock" + orders: + number: bilang + confirm_edit: sigurado ka bang nais mo ayusin ang order na ito? maaaring magdulot ito ng mas mahirap na awtomatikong pagsasaayos ng mga subscription sa hinaharap. + confirm_cancel_msg: "sigurado ka bang nais mong itigil ang subscription na ito? hindi na ito maaring ibalik kapag napalitan na." + cancel_failure_msg: "paumahin ngunit hindi naging matagumpay ang pagcancel!" + confirm_pause_msg: "sigurado ka bang nais mong pansamantalang itigil ang subscription na ito?" + pause_failure_msg: "paumanhin ngunit hindi matagumpay ang pansamantalang pagtigil" + confirm_unpause_msg: "kung ikaw ay may bukas na order cycle sa iskedyul ng subscription na ito, isang order ang gagawin para sa customer. sigurado ka bang nais mong ipagpatuloy ang subscription?" + unpause_failure_msg: "paumanhin ngunit hindi naging matagumpay ang pagpatuloy!" + confirm_cancel_open_orders_msg: "ang ibang order sa subscription na ito ay kasalukuyang nakabukas. ang customer ay nasabihan nang ang order ay magpapatuloy. nais mo bang itigil ang order(mga order) o ipagpatuloy ito?" + resume_canceled_orders_msg: "ang ibang order sa subsciption na ito ay maaaring ituloy. maaari mo itong ituloy sa dropdown ng mga order." + yes_cancel_them: wag ituloy + no_keep_them: ituloy + yes_i_am_sure: sigurado ako + order_update_issues_msg: ang ibang mga order ay hindi awtomatikong ma-update, sapagkat ito ay manwal na inayos. Tignan ang mga isyu na nakalista sa baba at gawin ang nararapat na pag-aayos sa bawat order kung kinakailangan. + no_results: + no_subscriptions: wala pang mga subscription.... + why_dont_you_add_one: nais mo bang magdagdag ng isa? :) + no_matching_subscriptions: walang nahanap na katugmang subscription + schedules: + destroy: + associated_subscriptions_error: ang iskedyul na ito ay hindi maialis sapagkat ito ay nauugnay sa ibang mga subscription. + controllers: + enterprises: + stripe_connect_cancelled: "ang pagkonekta sa Stripe ay kinansel" + stripe_connect_success: "matagumpay na nakonekta ang stripe account" + stripe_connect_fail: paumanhin, ang konekyson ng inyong Stripe account ay hindi nagtagumpay + stripe_connect_settings: + resource: pagsasaayos ng pagkonekta sa Stripe + api: + enterprise_logo: + destroy_attachment_does_not_exist: "ang Logo ay hindi matagpuan" + enterprise_promo_image: + destroy_attachment_does_not_exist: "ang promo na larawan ay hindi matagpuan" + orders: + failed_to_update: "hindi nagtagumpay na i-update ang order" + checkout: + already_ordered: + cart: "cart" + message_html: "mayroon ka ng order para sa order cycle na ito. tignan ang%{cart}para makita ang mga item na dating inorder. maaari mo ring i-cancel ang mga item habang ang order cycle ay bukas pa." + failed: "hindi matagumpay ang pag-check out. ipaalam sa amin upang maproseso ang inyong order." + shops: + hubs: + show_closed_shops: "Ipakita ang mga saradong shop" + hide_closed_shops: "itago ang mga saradong shop" + show_on_map: "Ipakita lahat sa mapa" + shared: + menu: + cart: + cart: "Cart" + signed_in: + profile: "Profile" + mobile_menu: + cart: "Cart" + joyride: + checkout: "Mag-checkout na" + already_ordered_products: "Naka-order na sa order cycle na ito" + register_call: + selling_on_ofn: "Interesado ka ba maging parte ng Open Food Network?" + register: "Magrehistro dito" + footer: + footer_secure: "Mapagkakatiwalaan." + footer_secure_text: "Ang Open Food Network ay gumagamit ng SSL encryption (2048 bit RSA) para mapanatiling pribado ang inyong pamimili at pagbababayad. Ang aming mga server ay hindi nagse-save ng mga detalye ng inyong credit card at ang inyong pagbabayad ay pinoproseso ng mga serbisyong PCI-compliant." + footer_contact_headline: "Makipag-ugnayan" + footer_contact_email: "i-email kami" + footer_nav_headline: "Navigate" + footer_join_headline: "Sumali sa amin" + footer_join_body: "Gumawa ng profile, shop, o listahan ng grupo sa Open Food Network." + footer_join_cta: "sabihin pa sa akin ang iba pa!" + footer_legal_call: "basahin ang aming" + footer_legal_tos: "mga tuntunin at kondisyon" + footer_legal_visit: "Hanapin kami sa" + footer_legal_text_html: "ang Open Food Network ay isang libre at bukas ang pinagkukuhanang platform. ang mga nilalaman nito ay lisensiyado ng%{content_license}at ang aming mga code ng %{code_license}." + footer_data_text_with_privacy_policy_html: "Pinangangalagaan namin ang inyong impormasyon. Tignan ang aming%{privacy_policy}at%{cookies_policy}" + footer_data_text_without_privacy_policy_html: "Pinangangalagaan namin ang inyong impormasyon. Tignan ang aming%{cookies_policy}" + footer_data_privacy_policy: "patakaran ng privacy" + footer_data_cookies_policy: "patakaran ng cookies" + shop: + messages: + login: "mag-log-in" + signup: "mag-sign-up" + contact: "makipag-ugnay" + require_customer_login: "ang mga inaprubahang customer lamang ang maaaring gumamit ng shop na ito." + require_login_html: "Kung ikaw ay naaprubahang customer na, %{login} o %{signup}upang magpatuloy. Nais mamili dito? %{contact}%{enterprise}at magtanong kung paano sumali." + require_customer_html: "kung nais mong magsimulang mamili dito, maaaring%{contact}%{enterprise} at magtanong kung paano sumali." + card_could_not_be_updated: hindi ma-update ang card + card_could_not_be_saved: hindi ma-save ang card + spree_gateway_error_flash_for_checkout: "mayroong problema sa inyong ibinigay na impormasyon ng pagbabayad:%{error}" + invoice_billing_address: "Billing Address:" + invoice_column_tax: "GST" + invoice_column_price: "presyo" + invoice_column_item: "Item" + invoice_column_qty: "Dami:" + invoice_column_unit_price_with_taxes: "Presyo kada yunit (kasama ang tax)" + invoice_column_unit_price_without_taxes: "Presyo kada yunit (hindi kasama ang tax)" + invoice_column_price_with_taxes: "Kabuuang Presyo (kasama ang tax)" + invoice_column_price_without_taxes: "Kabuuang Presyo (hindi kasama ang tax)" + invoice_column_tax_rate: "rate ng tax" + invoice_tax_total: "kabuuang GST:" + tax_invoice: "TAX INVOICE" + tax_total: "Kabuuang Tax (%{rate}):" + total_excl_tax: "Kabuuan (Hindi kasama ang tax):" + total_incl_tax: "Kabuuan (Kasama ang tax):" + abn: "ABN:" + acn: "ACN:" + invoice_issued_on: "inilabas ang invoice noong:" + order_number: "numero ng invoice" + date_of_transaction: "Petsa ng Transaksiyon:" + ticket_column_qty: "Dami:" + ticket_column_item: "Item" + ticket_column_unit_price: "Presyo kada Yunit" + ticket_column_total_price: "Kabuuang Presyo" + menu_1_title: "Mga Shop" + menu_1_url: "/shops" + menu_2_title: "Mapa" + menu_2_url: "/map" + menu_3_title: "Mga Producer" + menu_3_url: "/producers" + menu_4_title: "Mga Bayarin" + menu_4_url: "/sell" + menu_5_title: "Tungkol Sa OFN" + menu_5_url: "https://www.openfoodnetwork.org/" + menu_6_title: "Kumonekta" + menu_6_url: "https://openfoodnetwork.org/au/connect/" + menu_7_title: "Matuto" + menu_7_url: "https://openfoodnetwork.org/au/learn/" + logo: "Logo (640x130)" + logo_mobile: "Mobile logo (75x26)" + logo_mobile_svg: "Mobile logo (SVG)" + home_hero: "Hero image" + home_show_stats: "ipakita ang statistics" + footer_logo: "Logo (220x76)" + footer_facebook_url: "Facebook URL" + footer_twitter_url: "Twitter URL" + footer_instagram_url: "Instagram URL" + footer_linkedin_url: "LinkedIn URL" + footer_googleplus_url: "Google Plus URL" + footer_pinterest_url: "Pinterest URL" + footer_email: "email" + footer_links_md: "mga link" + footer_about_url: "tungkol sa URL" + user_guide_link: "Link ng Gabay sa Paggamit" + name: pangalan + first_name: Pangalan + last_name: Apelyido + email: email + phone: telepono + next: sunod + address: tirahan + address_placeholder: eg. 123 High Street + address2: Tirahan (pinagpatuloy) + city: Lungsod + city_placeholder: hal. Northcote + postcode: Postcode + postcode_placeholder: hal. 3070 + suburb: lungsod + state: status + country: Bansa + unauthorized: hindi awtorisado + terms_of_service: "mga palatuntunan ng serbisyo" + on_demand: on demand + none: wala + not_allowed: hindi pinapayagan + no_shipping: walang mga paraan ng pagpapadala + no_payment: walang mga paraan ng pagbabayad + no_shipping_or_payment: walang mga paraan ng pagpapadala o pagbabayad + unconfirmed: hindi kumpirmado + days: mga araw + authorization_failure: "hindi nagtagumpay ang pagpahintulot" + label_shop: "Shop" + label_shops: "mga shop" + label_map: "mapa" + label_producer: "Producer" + label_producers: "Producers" + label_groups: "mga grupo" + label_about: "tungkol sa" + label_connect: "kumonekta" + label_learn: "matuto" + label_blog: "Blog" + label_support: "Suporta" + label_shopping: "Pamimili" + label_login: "Login" + label_logout: "mag-log-out" + label_signup: "Mag-sign-up" + label_administration: "administrasyon" + label_admin: "admin" + label_account: "Account" + label_more: "ipakita lahat" + label_less: "ipakita ang mas kaunti" + label_notices: "mga abiso" + cart_items: "mga item" + cart_headline: "Ang iyong shopping cart" + total: "kabuuan" + cart_updating: "ina-update ang cart" + cart_empty: "walang laman ang cart" + cart_edit: "ayusin ang cart" + card_number: numero ng card + card_securitycode: "Security code" + card_expiry_date: petsa ng pag-expire + card_masked_digit: "X" + card_expiry_abbreviation: "Exp" + new_credit_card: "bagong credit card" + my_credit_cards: ang aking mga credit card + add_new_credit_card: magdagdag ng bagong credit card + saved_cards: i-save ang mga card + add_a_card: magdagdag ng card + add_card: idagdag ang card + you_have_no_saved_cards: wala ka pang nai-save na card. + saving_credit_card: sine-save ang credit card... + card_has_been_removed: "ang iyong card ay tinanggal na (numero:%{number})" + card_could_not_be_removed: paumanhin, hindi maalis ang card + invalid_credit_card: "hindi valid ang credit card" + ie_warning_headline: "ang iyong browser ay luma na :-(" + ie_warning_text: "para sa pinakamagandang karanasan sa Open Food Network, mariin naming nirerekomenda ang pag-upgrade ng inyong browser:" + ie_warning_chrome: i-download ang Chrome + ie_warning_firefox: i-download ang Firefox + ie_warning_ie: i-upgrade ang Internet Explorer + ie_warning_other: "Hindi ma-upgrade ang browser? Subukan ang Open Food Network sa inyong smartphone :-)" + legal: + cookies_policy: + header: "paano kami gumagamit ng cookies" + desc_part_1: "ang mga cookies ay maliliit na text files na naiimbak sa iyong computer kapag bumibisita ka sa mga website" + desc_part_2: "Sa OFN, mahigpit naming pinahahalagahan ang inyong privacy. Gumagamit lamang kami ng cookies na kinakailangan para makapagbigay sa inyo ng serbisyo sa pagbebenta/pamimili ng pagkain sa Internet. Hindi namin binebenta ang inyong impormasyon. Maaaring imungkahi namin sa hinaharap ang pagbahagi ng ilang impormasyon para makabuo ng isang bagong serbisyo na maaaring makatulong sa sistema ng pagkain (tulad ng mga proseso at serbisyo para sa maliliit na kalakalan ng pagkain) ngunit wala pa tayo sa hakbang na iyon sa ngayon, at sisiguraduhin naming hindi namin ito gagawin ng wala ang inyong permiso. :-)" + desc_part_3: "ang pangunahing dahilan sa paggamit ng cookies ay para matandaan kung sino ka kapag ikaw ay naglog-in sa serbisyo at upang panatilihin ang mga item na nilagay mo sa iyong cart habang ikaw ay hindi pa nakalog-in. kung ikaw ay gumagamit ng website ng hindi pinipindot ang \"tanggapin ang cookies\", ipapalagay namin na binibigyan mo kami ng pahintulot na i-save ang mga cookies na lubhang mahalaga sa maayos na paggamit ng website. narito ang listahan ng mga cookies na aming ginagamit!" + essential_cookies: "mahahalagang mga cookies" + essential_cookies_desc: "ang mga sumusunod na cookies ay lubhang kailangan para sa operasyon ng ating website." + essential_cookies_note: "karamihan sa mga cookies ay naglalaman lamang ng natatanging pagkakakilanlan at wala ng iba, kung kaya ang iyong email address at password halimbawa ay hindi kailanman mai-se-save at maipapalam sa iba." + cookie_domain: "Sinet ng:" + cookie_session_desc: "ginagamit upang payagan ang website na matandaan ang mga gumagamit kapag dumadalaw sa pahina, halimbawa, alalahanin ang mga item na nasa cart." + cookie_consent_desc: "ginagamit upang mapanatili ang status ng permiso ng gumagamit sa pag-store ng cookies" + cookie_remember_me_desc: "ginagamit kapag ang user ay humingi ng pahintulot na siya ay maalala. ang cookie na ito ay awtomatikong nabubura makalipas ang 12 araw. kung bilang gumagamit ay nais mong mabura ang cookie, kailangan mo lamang maglog-out. kung hindi mo nais na mailagay ang cookie sa iyong computer, hindi mo dapat lagyan ng check ang \"alalahanin ako\" na kahon kapag nagla-log-in." + cookie_openstreemap_desc: "ay ginagamit ng tagapagbigay sa atin ng serbisyo ukol sa open source mapping(OpennStreetMap) para masiguradong hindi ito makakatanggap ng maraming request sa tinakdang oras, at upang maiwasan na din ang pag-abuso sa kanilang serbisyo." + cookie_stripe_desc: "Mga data na nakolekta ng Stripe, ang tagaproseso para sa bayad, upang magamit sa pag-detect ng fraud https://stripe.com/cookies-policy/legal. hindi lahat ng shop ay gumagamit ng Stripe bilang paraan ng pagbabayad ngunit iminumungkahi namin itong gamitin sa lahat ng pahina upang maiwasan ang fraud at ilegal na pagkuha ng iyong impormasyon." + statistics_cookies: "katayuan ng cookies" + statistics_cookies_desc: "ang mga sumusunod ay hindi mahigpit na kinakailangan, ngunit nakakatulong upang mabigyan namin kayo ng mga pinakamagandang serbisyo sa pamamagitan ng pagpayag na suriin namin ang kilos ng mga gumagamit, alamin ang mga features na madalas gamitin o hindi ginagamit, intindihin ang mga problemang kinaharap ng gumagamit, at iba pa." + statistics_cookies_analytics_desc_html: "upang kolektahin at suriin ang data sa paggamit ng platform, ginagamit namin ang Google Analytics, bilang ito ang default na serbisyo na ginagamit ng Spree (ang e-commerce open source software kung saan kami nagsimula) ngunit ang aming layunin ay makalipat sa Matomo(halimbawa ay Piwik, open source analytics tool na sumusunod sa GDPR at pinangangalagaan ang inyong privacy) sa lalong madaling panahon." + statistics_cookies_matomo_desc_html: "para makolekta at masuri ang mga data na ginagamit, gumagamit kami ngMatomo(halimbawa ay Piwik), isang open source analytics na tool na sumusunod sa GDPR at pinangangalagaan ang inyong privacy." + statistics_cookies_matomo_optout: "nais mo bang gamitin ang Matomo Analytics? hindi kami kumukolekta ng kahit anong personal na impormasyon, at tinutulungan kami ng Matomo na pag-igihin ang aming serbisyo, ngunit mas pinapahalagahan namin ang inyong desisyon :-)" + cookie_analytics_utma_desc: "ginagamit upang pag-ibahin ang mga gumagamit at mga sesyon. Ang cookie ay nabubuo kapag ang javascript library ay naisagawa at walang __utma cookies. ang cookie na ito ay ina-update sa tuwing may ipinapadala na data sa Google Analytics." + cookie_analytics_utmt_desc: "ginagamit upang makontrol ang bilis ng pagpasok ng mga request." + cookie_analytics_utmb_desc: "ginagamit upang matukoy ang mga bagong sesyon/bisita. ang cookie ay nabubuo kapag ang javascript library ay naisagawa at walang __utma cookies. ang cookie na ito ay ina-update sa tuwing may ipinapadala na data sa Google Analytics." + cookie_analytics_utmc_desc: "hindi ginagamit sa ga.js. i-set para sa interoperability sa urchin.js. Kahit sa nakaraan, ang cookie na ito ay ginagamit kasama ang the __utmb cookie para matukoy kung ang gumagamit ay nasa bagong sesyon/bisita." + cookie_analytics_utmz_desc: "sine-save ang traffic source o campaign na nagpapaliwanag kung paano napunta ang gumagamit sa inyong site. ang cookie ay nagagawa kapag ang javascript library ay nagamit at na-update sa tuwing may ipinapadalang data sa Google Analytics." + cookie_matomo_basics_desc: "mga cookies ng Matomo first party para mangolekta ng istatistika." + cookie_matomo_heatmap_desc: "cookies para sa Matomo Heatmap & Session Recording." + cookie_matomo_ignore_desc: "Cookie na ginagamit upang hindi maisama ang gumagamit sa pag-track." + disabling_cookies_header: "Babala sa hindi pagpapagana ng cookies" + disabling_cookies_desc: "ang gumagamit ay maaaring payagan, i-block o burahin ang Open Food Network o ang kahit anong website cookies kahit kailan nila naisin sa pamamagitan ng setting control ng browser na ginagamit. bawat browser ay may iba't ibang proseso. eto ang mga link:" + disabling_cookies_firefox_link: "https://support.mozilla.org/en-US/kb/enable-and-disable-cookies-website-preferences" + disabling_cookies_chrome_link: "https://support.google.com/chrome/answer/95647" + disabling_cookies_ie_link: "https://support.microsoft.com/en-us/help/17442/windows-internet-explorer-delete-manage-cookies" + disabling_cookies_safari_link: "https://www.apple.com/legal/privacy/en-ww/cookies/" + disabling_cookies_note: "Ngunit dapat mong malaman na kapag binura o binago mo ang kinakailangang cookies na ginagamit ng Open Food Network, ang website ay hindi gagana at, halimbawa, hindi ka maaring makapaglagay sa iyong cart upang makapagcheckout." + cookies_banner: + cookies_usage: "ang site na ito ay gumagamit ng mga cookies upang maging mas ligtas at madali ang paggamit ng site. nakakatulong din ito sa amin upang maintindihan kung paano ang inyong paggamit para mas maging maayos ang serbisyong aming ibibigay sa inyo." + cookies_definition: "ang mga cookies ay maliliit na text files na naiimbak sa iyong computer kapag bumibisita ka sa mga website" + cookies_desc: "ginagamit lang namin ang mga cookies na kinakailangan para sa pagbibigay ng serbisyo ng pagbebenta/pamimili ng pagkain gamit ang internet. Hindi namin gagamitin ang inyong data para kumita. ang pangunahing dahilan sa paggamit ng cookies ay para matandaan kung sino ka kapag ikaw ay naglog-in sa serbisyo at upang panatilihin ang mga item na nilagay mo sa iyong cart habang ikaw ay hindi pa nakalog-in. kung ikaw ay gumagamit ng website ng hindi pinipindot ang \"tanggapin ang cookies\", ipapalagay namin na binibigyan mo kami ng pahintulot na i-save ang mga cookies na lubhang mahalaga sa maayos na paggamit ng website." + cookies_policy_link_desc: "para sa karagdagangn impormasyon, tignan ang" + cookies_policy_link: "patakaran ng cookies" + cookies_accept_button: "tanggapin ang cookies" + home_shop: Mamili Ngayon + brandstory_headline: "Etikal na pagkain." + brandstory_intro: "Minsan ang pinakamabuting paraan para ayusin ang sistema ay ang pagbuo ulit ng bago..." + brandstory_part1: "Kami ay nagsimula sa pinakaibaba pataas. Kasama ang mga magsasaka at tagatanim na handang ibahagi at ipagmalaki ang kanilang mga kuwento. May mga tapat at patas na Distributors na handang makipag-usap sa mga gumagawa ng produkto. At mga mamimili na naniniwala na ang mabusising lingguhang pamimili ay magdudulot ng malaking pagbabago sa mundo." + brandstory_part2: "kaya kinailangan naming gumawa ng paraan para gawing totoo ang lahat. isang paraan para bigyan ng kapangyarihan ang lahat ng mga tao na nagtatanim, nagsasaka, nagbebenta at bumibili ng pagkain. isang paraan upang mabigyan ng boses ang lahat at malaman ang kanilang kuwento, matulungan sa pagsasaayos ng mga proseso. isang paraang upang ang mga transaksyon ay gawing pagbabago araw araw." + brandstory_part3: "ito ang dahilan kaya kami ay nagtayo ng online na pamilihan na kalebel na kung ano ang nasa katotohanan. ito ay transparent kaya bumubuo ito ng totoong mga relasyon. ito ay bukas ang pinagkukunan, kaya pag-aari ito ng lahat. ito ay sinusubukan na rin ng iba't ibang rehiyon at nasyon, dahilan kaya ang mga tao ay unti unting nagsisimulang gumawa ng sariling bersyon nito sa iba't ibang panig ng mundo." + brandstory_part4: "ito ay gumagana sa lahat ng lugar. kaya nitong baguhin ang lahat." + brandstory_part5_strong: "tinatawag namin itong Open Food Network." + brandstory_part6: "lahat tayo ay mahilig kumain. ngayon ay maaari narin nating mahalin ang sistema ng pagkain." + learn_body: "galugarin ang mga modelo, mga kuwento at pinagkukuhanan para ikaw ay matulungan sa pagbuo ng sarili mong negosyo o organisayon. Humanap ng mga pagsasanay, kaganapan at iba pang mga oportunidad para matuto sa iba." + learn_cta: "makakuha ng inspirasyon" + connect_body: "tumingin sa aming directory ng mga producer, hub at mga grupo upang makahanap ng patas na mangangalakal ng pagkain na pinakamalapit sa iyo. Ilagay ang iyong negosyo o organisasyon sa OFN para kayo'y makita ng mga mamimili. Sumali sa aming komunidad para makakuha ng mga payo ay makapagtulungan sa paglutas ng mga problema." + connect_cta: "halilka na at ma-explore" + system_headline: "Pamimili - ganito ang paraan." + system_step1: "1. humanap" + system_step1_text: "humanap sa iba't ibang mga shop ng lokal na napapanahong pagkain. humanap sa pamamagitan ng malapit na lokasyon o kategorya ng pagkain, o kung mas nais mo ang pick-up kesa sa delivery." + system_step2: "2. Mamili" + system_step2_text: "baguhin ang paraan ng pakikipagtransaksyon sa pagbili ng mga lokal ng pagkain mula sa iba't ibang producer at hubs. malaman ang mga kwento sa likod ng mga pagkain at sa mga gumagawa nito." + system_step3: "3. Pick-up / Delivery" + system_step3_text: "hintayin ang inyong pagkain o bisitahin ang producer o hub para sa mas personal na koneksyon sa inyong pagkain at pinanggagalingan nito." + cta_headline: "paraan ng pamimili na kayang gawing mas madali at maayos ang mundong ito." + cta_label: "handa na ako" + stats_headline: "kami ay bumubuo ng bagong sistema ng pagkain." + stats_producers: "producer ng pagkain" + stats_shops: "mga tindahan ng pagkain" + stats_shoppers: "mga mamimili ng pagkain" + stats_orders: "mga order ng pagkain" + checkout_title: checkout + checkout_now: mag-checkout ngayon + checkout_order_ready: ang order ay handa na para sa + checkout_hide: itago + checkout_expand: palawigin + checkout_headline: "ok, handa na ba magcheckout?" + checkout_as_guest: "mag-checkout bilang bisita" + checkout_details: "ang inyong detalye" + checkout_billing: "impormasyon sa paniningil" + checkout_default_bill_address: "i-save bilang default na address para sa paniningil" + checkout_shipping: impormasyon sa pagpapadala + checkout_default_ship_address: "i-save bilang default na address para sa pagpapadalahan" + checkout_method_free: libre + checkout_address_same: address ng pagpapadalahan pareho sa address ng paniningil? + checkout_ready_for: "handa na para sa :" + checkout_instructions: "komento o dagdag na tagubilin?" + checkout_payment: kabayaran + checkout_send: i-place ang order ngayon + checkout_your_order: ang iyong order + checkout_cart_total: kabuuan na laman ng cart + checkout_shipping_price: pagpapadala + checkout_total_price: kabuuan + checkout_back_to_cart: "bumalik sa cart" + cost_currency: "halaga ng pera" + order_paid: BAYAD NA + order_not_paid: HINDI PA BAYAD + order_total: kabuuang order + order_payment: "magbabayad sa pamamagitan ng:" + order_billing_address: address na pagsisingilan + order_delivery_on: petsa ng delivery + order_delivery_address: address kung saan ide-deliver + order_delivery_time: oras ng pagde-deliver + order_special_instructions: "ang iyong mga tala" + order_pickup_time: handa na para sa koleksyon + order_pickup_instructions: tagubilin sa pagkolekta + order_produce: produkto + order_total_price: kabuuan + order_includes_tax: (kasama ang tax) + order_payment_paypal_successful: ang iyong bayad gamit ang PayPal ay matagumpay na naproseso. + order_hub_info: impormasyon ng Hub + order_back_to_store: bumalik sa pamillihan + order_back_to_cart: bumalik sa Cart + bom_tip: "gamitin ang pahina na ito para baguhin ang dami ng mga produkto sa maramihang mga order. maaari ding magtanggal ng mga produkto mula sa order kung kinakailangan." + unsaved_changes_warning: "may mga pagbabagong hindi pa na-save at maaaring mawala kung magpapatuloy." + unsaved_changes_error: "ang mga patlang na may pulang border ay may mga error" + products: "mga produkto" + products_in: "sa%{oc}" + products_at: "nasa%{distributor}" + products_elsewhere: "ang mga produkto ay hindi dito natagpuan" + email_confirmed: "Salamat sa pagkumpirma ng inyong email address." + email_confirmation_activate_account: "Bago natin ma-activate ang inyong account, kailangan munang kumpirmahin ang iyong email address." + email_confirmation_greeting: "magandang araw, %{contact}!" + email_confirmation_profile_created: "ang profile para kay/sa %{name}ay matagumpay na nagawa! para i-activate ang inyong profile, kailangan naming kumpirmahin ang email address na ito." + email_confirmation_click_link: "pindutin ang link sa ibaba para kumpirmahin ang iyong email address at upang maipagpatuloy ang pagset-up ng inyong profile." + email_confirmation_link_label: "kumpirmahin ang email address na ito »" + email_confirmation_help_html: "pagkatapos makumpirma ang iyong email, maaari mo na i-access ang iyong administration account para sa enterprise na ito. tignan ang%{link}upang lalong mas maunawaan ang%{sitename}at masimulan na ang paggamit ng inyong profile o online na tindahan." + email_confirmation_notice_unexpected: "natanggap mo ang mensahe na ito sapagkat ikaw ay nagsign-up sa%{sitename}, o inimbitahan para magsign-up ng isang tao na maaring kilala mo. kung hindi maintindihan kung bakit ka nakakatanggap ng ganitong email, maaring sumulat sa%{contact}." + email_social: "kumonekta sa amin:" + email_contact: "i-email kami:" + email_signoff: "Mabuhay," + email_signature: "%{sitename} Team" + email_confirm_customer_greeting: "Magandang araw%{name}," + email_confirm_customer_intro_html: "salamat sa pamimili sa%{distributor}!" + email_confirm_customer_number_html: "kumpirmasyon ng order#%{number}" + email_confirm_customer_details_html: "narito ang mga detalye ng niyong order mula sa%{distributor}:" + email_confirm_customer_signoff: "Lubos na gumagalang," + email_confirm_shop_greeting: "Magandang araw%{name}," + email_confirm_shop_order_html: "binabati kita! may bago kang order para sa%{distributor}!" + email_confirm_shop_number_html: "kumpirmasyon ng order#%{number}" + email_order_summary_item: "Item" + email_order_summary_quantity: "Dami:" + email_order_summary_sku: "SKU" + email_order_summary_price: "presyo" + email_order_summary_subtotal: "Subtotal:" + email_order_summary_total: "Kabuuan:" + email_order_summary_includes_tax: "(kasama ang tax):" + email_payment_paid: BAYAD NA + email_payment_not_paid: HINDI PA BAYAD + email_payment_summary: buod ng kabayaran + email_payment_method: "magbabayad sa pamamagitan ng:" + email_so_placement_intro_html: "mayroon kang bagong order sa%{distributor}" + email_so_placement_details_html: "narito ang mga detalye ng iyong order para sa %{distributor}:" + email_so_placement_changes: "sa kasamaang palad, hindi lahat ng produkto na iyong isinama ay available. ang orihinal na dami ng mga isinamang produkto ay naka-ekis sa baba." + email_so_payment_success_intro_html: "ang awtomatikong pagbabayad ay naproseso para sa iyong order mula sa%{distributor}." + email_so_placement_explainer_html: "ang order na ito ay awtomatikong binuo para sa iyo." + email_so_edit_true_html: "maaari kang gumawa ng mga pagbabago hanggang magsara ang iyong mga order sa%{orders_close_at}." + email_so_edit_false_html: "maari mong tignan ang mga detalye ng order na itokahit kailan." + email_so_contact_distributor_html: "Kung ikaw ay may mga katanungan, maaring makipag-ugnayan sa%{distributor} sa%{email}." + email_so_contact_distributor_to_change_order_html: "Ang order na ito ay awtomatikong binuo para sa iyo. Maaari kang gumawa ng mga pagbabago hanggang magsara ang mga order sa%{orders_close_at} sa pamamagitan ng pakikipagugnayan sa%{distributor} sa%{email}." + email_so_confirmation_intro_html: "ang iyong order kasama ang%{distributor} ay kumpirmado na." + email_so_confirmation_explainer_html: "ang order na ito ay awtomatikong na-place para sa iyo at ngayon ay pinalisa na." + email_so_confirmation_details_html: "ang lahat ng kailangan mong malaman tungkol sa iyong order mula sa%{distributor} ay narito:" + email_so_empty_intro_html: "sinubukan naming mag-place ng bagong order sa%{distributor}, ngunit nagkaroon ng ilang problema..." + email_so_empty_explainer_html: "sa kasamaang palad, wala sa mga produkto na inyong inorder ay available sa ngayon kaya walang na-place na order. ang orihinal na dami na inyong inilagay ay naka-ekis sa ilalim." + email_so_empty_details_html: "narito ang mga detalye ng hindi na-place na order para sa%{distributor}:" + email_so_failed_payment_intro_html: "sinubukan naming iproseso ang isang bayarin ngunit nagkaroon ng mga problema.." + email_so_failed_payment_explainer_html: "ang iyong bayad para sa subscription sa%{distributor} ay hindi nagpatuloy dahil sa problema sa inyong credit card.%{distributor} ay sinabihan ukol sa bayad na ito." + email_so_failed_payment_details_html: "ito ang mga detalye sa kung bakit hindi nagpatuloy ang bayad na ibinigay ng gateway para sa pagbabayad:" + email_shipping_delivery_details: detalye ng pag-deliver + email_shipping_delivery_time: "pagdeliver sa :" + email_shipping_delivery_address: "address ng pagdadalahan:" + email_shipping_collection_details: detalye ng pangongolekta + email_shipping_collection_time: "handa para sa koleksyon:" + email_shipping_collection_instructions: "tagubilin sa pangongolekta:" + email_special_instructions: "ang iyong mga tala" + email_signup_greeting: Magandang araw! + email_signup_welcome: "Welcome sa%{sitename}!" + email_signup_confirmed_email: "salamat sa pagkumpirma ng iyong email." + email_signup_shop_html: "maaari ka ng maglog-in sa%{link}." + email_signup_text: "maraming salamat sa pagsali sa network na ito. kung ikaw ay isang customer, kami ay nagagalak na ipakilala kayo sa aming mga magsasaka, mga Hub at masasarap na pagkain! kung ikaw ang isang producer o enterprise ng pagkain, kami ay nasasabik na maging parte kayo ng aming network." + email_signup_help_html: "para sa inyong mga katanungan at suhestiyon: maaaring gamitin ang Magpadala ng feedback na pindutan sa site o mag-email sa amin sa %{email}" + invite_email: + greeting: "Magandang araw!" + invited_to_manage: "ikaw ay naanyayahan para pamahalaan ang%{enterprise}sa%{instance}." + confirm_your_email: "Maaaring natanggap mo na o matatanggap pa lamang ang email na may link ng kumpirmasyon. hindi mo mapupuntahan ang profile ng%{enterprise}hanggang hindi pa nakukumpirma ang inyong email." + set_a_password: "pagtapos ay dapat kang magset ng password bago mapamahalaan ang enterprise." + mistakenly_sent: "Hindi sigurado kung bakit ka nakatanggap ang email na ito? Makipagugnayan sa%{owner_email} para sa karagdagang impormasyon." + producer_mail_greeting: "Minamahal" + producer_mail_text_before: "ngayon nasa atin na ang lahat ng order ng mga mamimili para sa susunod na pag-drop ng order." + producer_mail_order_text: "narito ang buod ng mga order para inyong mga produkto:" + producer_mail_delivery_instructions: "tagubilin sa Stock pickup/delivery:" + producer_mail_signoff: "Maraming salamat!" + shopping_oc_closed: sarado na ang mga order + shopping_oc_closed_description: "maaaring maghintay sa susunod na pagbukas ng cycle( o makipaguganayan sa amin ng direkta upang malaman kung maaari pa kaming tumanggap ng huling mga order)" + shopping_oc_last_closed: "ang huling cycle ay nagsara%{distance_of_time}ang lumipas" + shopping_oc_next_open: "ang susunod na cycle ay magbubukas sa loob ng%{distance_of_time}" + shopping_oc_select: "pumili..." + shopping_tabs_home: "Home" + shopping_tabs_shop: "Shop" + shopping_tabs_about: "tungkol sa" + shopping_tabs_contact: "Makipag-ugnayan" + shopping_contact_address: "tirahan" + shopping_contact_web: "Makipag-ugnayan" + shopping_contact_social: "sumunod" + shopping_groups_part_of: "ay parte ng:" + shopping_producers_of_hub: "mga producer ng%{hub}:" + enterprises_next_closing: "susunod na order na magsasara" + enterprises_ready_for: "handa para sa" + enterprises_choose: "pumili kung kailan nais umorder:" + maps_open: "bukas" + maps_closed: "sarado" + hubs_buy: "Mamili para sa/kay:" + hubs_shopping_here: "namimili rito" + hubs_orders_closed: "sarado na ang mga order" + hubs_profile_only: "Profile lamang" + hubs_delivery_options: "mga pagpipilian sa pagdeliver" + hubs_pickup: "Pickup" + hubs_delivery: "pagdeliver" + hubs_producers: "ang aming mga producer" + hubs_filter_by: "i-filter gamit ang" + hubs_filter_type: "uri" + hubs_filter_delivery: "pagdeliver" + hubs_filter_property: "ari-arian" + hubs_matches: "ang ibig mo bang sabihin" + hubs_intro: Mamili sa iyong komunidad + hubs_distance: pinakamalapit sa + hubs_distance_filter: "ipakita ang mga shop malapit sa%{location}" + shop_changeable_orders_alert_html: + one: ang iyong order sa%{shop}/%{order} ay maaaring tignan. maaaring gumawa ng pagbabago hanggang%{oc_close}. + other: ikaw ay mayroong%{count} na order sa%{shop} na maaari ngayong tignan. maaaring gumawa ng mga pagbabago hanggang%{oc_close}. + orders_changeable_orders_alert_html: ang order na ito ay nakumpirma na ngunit maaari pang gumawa ng mga pagbabago hanggang%{oc_close}. + products_clear_all: alisin lahat + products_showing: "pinapakita:" + products_or: "O" + products_with: kasama ang + products_search: "hanapin gamit ang produkto o producer" + products_loading: "nilo-load ang mga produkto..." + products_updating_cart: "ina-update ang cart" + products_cart_empty: "walang laman ang cart" + products_edit_cart: "ayusin ang cart" + products_from: mula sa + products_change: "walang pagbabago na isesave" + products_update_error: "hindi nagpatuloy ang pag-save dahil sa mga sumusunod na error(s):" + products_update_error_msg: "hindi nagpatuloy ang pag-save." + products_update_error_data: "hindi nagpatuloy ang pag-save dahil sa hindi valid na data:" + products_changes_saved: "nai-save ang mga pagbabago" + search_no_results_html: "Paumahin, walang resultang nahanap para sa%{query}. Maaari kang sumubok ng isa pang keyword." + components_profiles_popover: "ang mga profile ay walang Shopfront sa Open Food Network, ngunit maaaring mayroong sariling pisikal o online na shop sa ibang lugar" + components_profiles_show: "Ipakita ang mga profile" + components_filters_nofilters: "walang mga filter" + components_filters_clearfilters: "alisin lahat ng mga filter" + groups_title: mga grupo + groups_headline: Grupo/ Mga Rehiyon + groups_text: "Bawat producer ay natatangi. Bawat negosyo ay may iba't ibang bagay na inaalok. ang aming grupo ay samahan ng mga producer, mga hub, at mga distributor na may mga pagkakapareho tulad ng lokasyon, pamilihan at pilosopiya. mas mapapadali nito ang iyong pamimili. kaya halina't subukan ang aming grupo at hayaan mo kaming tulungan ka sa iyong paghahanap at pamimili." + groups_search: "hanapin ang pangalan o keyword" + groups_no_groups: "Walang mahanap na mga grupo" + groups_about: "tungkol sa amin" + groups_producers: "ang aming mga producer" + groups_hubs: "ang aming mga hub" + groups_contact_web: Makipag-ugnayan + groups_contact_social: sumunod + groups_contact_address: tirahan + groups_contact_email: i-email kami + groups_contact_website: bisitahin ang aming website + groups_contact_facebook: sundan kami sa Facebook + groups_signup_title: mag-sign up bilang grupo + groups_signup_headline: Sign up ng grupo + groups_signup_intro: "kami ay isang kamanghamanghang plataporma para sa nagtutulungang kalakalan, ang pinakamadaling paraan para sa inyong mga miyembro at namumuhunan na makakonekta sa mga bagong pamilihan. Kami ay hindi tumutubo, abot-kaya at simple lamang." + groups_signup_email: i-email kami + groups_signup_motivation1: patas naming binabago ang sistema ng pagkain. + groups_signup_motivation2: at iyon ang dahilan kung bakit kami bumabangon araw araw. kami ay pandaigdigan ngunit hindi tumutubo base sa bukas na code ng pinagkukuhanan. kami ay lagi mong mapagkakatiwalaan. + groups_signup_motivation3: alam naming mayroon kayong magagandang ideya at nais namin kayong tulungan. Ibabahagi namin sa inyo ang aming kaalaman, mga network pati na ang pinagkukuhanan. alam naming ang pagsasarili ay hindi makabubuo ng pagbabago, kaya kami ay makikipagtulungan sa inyo. + groups_signup_motivation4: magsisimula tayo kung saan kayo nagmula. + groups_signup_motivation5: maaaring kayo ay samahan ng mga hub ng pagkain, mga producer, mga distributor, kinatawan ng isang industriya o lokal na gobyerno. + groups_signup_motivation6: kung ano man ang iyong parte sa inyong lokal na sistema ng pagkain, handa kaming tumulong sa inyo. maaaring nagtataka ka kung ano ang Open Food Network at kung ano ang ginagawa nito, maaari tayong mag usap tungkol dito. + groups_signup_motivation7: ginagawa naming mas makabuluhan ang daloy ng proseso ng kalakalan ng pagkain. + groups_signup_motivation8: kailangan mong i-activate at paganahin ang iyong mga koneksyon, naririto ang aming plataporma para sa pagkilos at komunikasyon. Ang kailangan mo ay aktwal na pakikipag-ugnayan. tutulungan ka naming makausap ang mga tao sa industriya na ito, mga namumuhunan, lahat ng mga sektor. + groups_signup_motivation9: kailangan mo ng magpagkukunan. Ibibigay namin ang lahat ng tulong at karanasan na mayroon kami. kailangan mo ng kooperasyon. gagabayan ka namin sa pagkonekta sa pandaigdigang mga samahan. + groups_signup_pricing: Account ng grupo + groups_signup_studies: pag-aaral ng kaso + groups_signup_contact: handa na makipagtalakayan? + groups_signup_contact_text: "Makipag-ugnayan upang malaman kung paano ka matutulungan ng OFN:" + groups_signup_detail: "ito ang mga detalye:" + login_invalid: "hindi valid ang email o password" + modal_hubs: "Mga Hub ng pagkain" + modal_hubs_abstract: ang mga Hub ng pagkain ang namamagitan sa iyo at sa mga gumagawa ng inyong pagkain! + modal_hubs_content1: maaari kang humanap ng pinakamalapit na Hub gamit ang lokasyon o pangalan. Ang ibang Hub ay may maraming mga lugar kung saan maaari mong kunin ang iyong pinamili habang ang iba ay bibigyan ka rin ng iba pang opsyon kung paano mo makukuha ang iyong order. Bawat Food Hub ay may iba ibang paraan ng operasyon at proseso kaya asahan ang kaibahan sa mga binibigay na serbisyo. + modal_hubs_content2: Maaari ka lamang mamili sa isang hub ng pagkain sa bawat pagkakataon. + modal_groups: "Mga Grupo / Mga Rehiyon" + modal_groups_content1: ito ang mga organisasyon at mga relasyon na namamagitan sa mga Hub na bumubuo sa Open Food Network. + modal_groups_content2: ang ibang grupo ay pinagsasama sama depende sa lokasyon o lupon, at ang iba ay sa hindi pangheograpiyang pagkakapareho. + modal_how: "Paano it gumagana" + modal_how_shop: Mamili sa Open Food Network + modal_how_shop_explained: maghanap ng hub ng pagkain na pinakamalapit sa iyo para makapagsimulang makapamili. maaring palawakin ng bawat hub upang makita kung anong uri ng pagkain ang inaalok nila at pindutin ng tuluyan para magsimula mamili. (maaari lamang mamili sa isang hub sa isang pagkakataon.) + modal_how_pickup: Singil sa Pick-up, pag-deliver at pagpapadala + modal_how_pickup_explained: ang ibang food hub ay magde-deliver mismo sa inyong tirahan, habang ang iba ay kakailanganin kang kunin ng personal sa kanila ang inyong mga order. Mababasa sa homepage ang mga opsyon, at piliin ang mga produkto na nais sa pahina ng pamimili at checkout. Ang pagpapa-deliver ay mas mahal at ang halagang babayaran ay nakadepende sa iba't ibang food hub. Bawat Food Hub ay may iba't ibang paraan ng operasyon at proseso kaya dapat asahan ang kaibahan sa mga binibigay na serbisyo. + modal_how_more: dagdagan ang kaalaman + modal_how_more_explained: "kung nais mong mas maintindihan ang Open Food Network, kung paano ito gumagana at paano makasali dito, tignan ito:" + modal_producers: "Producers" + modal_producers_explained: "ang aming mga producer ay gumagawa ng masasarap na pagkain na maaari mong mabili sa Open Food Network." + producers_about: Tungkol sa amin + producers_buy: 'mamili para sa ' + producers_contact: Makipag-ugnayan + producers_contact_phone: Tumawag + producers_contact_social: sumunod + producers_buy_at_html: "mamili para sa%{enterprise}na mga produkto sa:" + producers_filter: i-filter gamit ang + producers_filter_type: uri + producers_filter_property: ari-arian + producers_title: Producers + producers_headline: humanap ng lokal na mga producer + producers_signup_title: magsign-up bilang producer + producers_signup_headline: Producer ng pagkain, mas pinalakas. + producers_signup_motivation: Ibenta ang inyong pagkain at magkipagugnayan sa mga iba't ibang pamilihan. makatipid ng oras at pera. Pagbabago ng walang kaakibat na peligro. ginawang patas para sa lahat ang kalakaran. + producers_signup_send: sumali ngayon + producers_signup_enterprise: mga account ng enterprise + producers_signup_studies: mga kwento mula sa ating mga producer + producers_signup_cta_headline: sumali ngayon! + producers_signup_cta_action: sumali ngayon + producers_signup_detail: 'ito ang mga detalye:' + products_item: Item + products_description: paglalarawan + products_variant: Uri + products_quantity: dami + products_available: Mayroong stock? + products_producer: "Producer" + products_price: "presyo" + name_or_sku: "PANGALAN O SKU" + register_title: Magrehistro + sell_title: "Magrehistro" + sell_headline: "pumunta sa Open Food Network!" + sell_motivation: "ipagmalaki ang iyong masasarap na pagkain!" + sell_producers: "Producers" + sell_hubs: "Hubs" + sell_groups: "mga grupo" + sell_producers_detail: "magset-up ng profile para sa inyong negosyo sa OFN sa loob lamang ng ilang minuto. maaari mong i-upgrade ang inyong profile upang maging online store at magbenta ng iyong mga produkto direkta sa mga customer." + sell_hubs_detail: "magset-up ng profile para sa inyong Food enterprise o organisasyon sa OFN. maaari mong i-upgrade ang inyong profile upang maging multi-producer na shop kahit kailan mo naisin." + sell_groups_detail: "magset-up ng directory ng mga enterprise (mga producer at iba pang enterprise ng pagkain) para sa iyong rehiyon o organisasyon." + sell_user_guide: "marami pang maaring malaman sa aming Gabay sa Paggamit" + sell_listing_price: "ang pagpapalista sa OFN ay libre. ang pagbubukas at pagpapatakbo ng shop ay libre hanggang sa $500 na buwanang benta. kung makakabenta ka ng mas marami, maaari kang mamili ng kontribusyon sa komunidad sa pagitan ng 1% at 3% ng kita. para sa karagdagang detalye ukol sa pagpepresyo, maaaring bisitahin ang seksyon ng Software Platform sa pamamagitan ng About link sa taas na menu." + sell_embed: "maari rin naming ilagay ang OFN sa inyong sariling website o magtayo ng sariling lokal na Food Network website sa inyong rehiyon." + sell_ask_services: "magtanong tungkol sa mga serbiyong binibigay ng OFN" + shops_title: mga shop + shops_headline: Pamimili, binago. + shops_text: Ang pagtatanim at paggawa ng pagkain ay nasa mga cycle, ang mga magsasaka ay umaani sa mga cycle, at nag-o-order tayo ng pagkain sa mga cycle. Kung makikita mong sarado ang isang order cycle, maaaring kang bumalik sa ibang pagkakataon. + shops_signup_title: magsign-up bilang Hub + shops_signup_headline: Mga Food Hub, walang limitadong pagpipilian. + shops_signup_motivation: kung ano man ang iyong modelo, susuportahan ka namin. ano mang pagbabago na nais gawin, kasama mo kami. kami ay non-profit, malaya at bukas sa lahat ng impormasyon. kami ang kaibigan at kasangga na matagal mo nang pinapangarap. + shops_signup_action: sumali ngayon + shops_signup_pricing: mga account ng enterprise + shops_signup_stories: mga kwento mula sa aming mga Hub. + shops_signup_help: handa kaming tumulong. + shops_signup_help_text: kailangan mo ng mas malaking kita. kailangan mo ng bagong mga mamimili at mga katulong sa operasyon. kailangang malaman ng lahat ang tungkol sa iyong produkto. + shops_signup_detail: 'ito ang mga detalye:' + orders: mga order + orders_fees: Mga bayarin... + orders_edit_title: Cart para sa pamimili + orders_edit_headline: ang iyong cart sa pamimili + orders_edit_time: ang order ay handa na para sa + orders_edit_continue: magpatuloy sa pamimili + orders_edit_checkout: checkout + orders_form_empty_cart: "alisin ang laman ng cart" + orders_form_subtotal: bahagyang kabuuan ng mga produkto + orders_form_admin: Admin & Handling + orders_form_total: kabuuan + orders_oc_expired_headline: ang mga order ay nagsara na para sa order cycle na ito. + orders_oc_expired_text: "Paumanhin ngunit ang mga order para sa order cycle na ito ay sarado na mula noong%{time}! Direktang makipag-ugnayan sa inyong Hub upang malaman kung maaari pa silang tumanggap ng mga order." + orders_oc_expired_text_others_html: "paumanhin ngunit ang mga order para sa order cycle na ito ay sarado na mula noong %{time}! direktang makipag ugnayan sa inyong Hub upang malaman kung maaari pa silang tumanggap ng mga order%{link}." + orders_oc_expired_text_link: "o tignan ang iba pang order cycle mula sa hub na ito." + orders_oc_expired_email: "Email:" + orders_oc_expired_phone: "Telepono:" + orders_show_title: Kumpirmasyon ng order + orders_show_time: 'ang order ay handa na sa:' + orders_show_order_number: "Order #%{number}" + orders_show_cancelled: Kinansela + orders_show_confirmed: Kumpirmado + orders_your_order_has_been_cancelled: "ang inyong order ay nakansela" + orders_could_not_cancel: "paumanhin sapagkat hindi makansela ang inyong order" + orders_cannot_remove_the_final_item: "hindi matanggal ang huling item mula sa isang order, maaaring kanselahin na lamang ang order." + orders_bought_items_notice: + one: "isang karagdagang item ang nakumpirma na para sa order cycle na ito" + other: "%{count}karagdagang mga item ang nakumpirma para sa order cycle na ito" + orders_bought_edit_button: ayusin ang kumpirmadong mga item + orders_bought_already_confirmed: "* kumpirmado na" + orders_confirm_cancel: sigurado ka bang nais mo na kanselahin ang order na ito? + order_processed_successfully: "ang inyong order ay matagumpay na nakumpirma" + products_cart_distributor_choice: "Distributor ng inyong order:" + products_cart_distributor_change: "ang distributor para sa order na ito ay mapapalitan ng%{name} kung idadagdag ang produktong ito sa inyong cart." + products_cart_distributor_is: "ang distributor para sa order na ito ay%{name}." + products_distributor_error: "kumpletuhin ang inyong order sa%{link} bago mamili sa ibang distributor." + products_oc: "order cycle para sa iyong order:" + products_oc_change: "ang iyong order cycle para sa order na ito ay papalitan ng%{name} kung idadagdag mo ang produktong ito sa inyong cart." + products_oc_is: "ang order cycle para sa order na ito ay%{name}." + products_oc_error: "kumpletuhin ang inyong order mula sa %{link} bago mamili sa ibang order cycle." + products_oc_current: "ang iyong kasalukuyang order cycle" + products_max_quantity: sagad na dami + products_distributor: Distributor + products_distributor_info: kapag pumili ng distributor para sa inyong order, ang kanilang address at oras ng pickup ay makikita dito. + password: Password + remember_me: tandaan ako + are_you_sure: "Sigurado ka ba?" + orders_open: bukas ang mga order + closing: "sinasara" + going_back_to_home_page: "binabalik ka sa homepage" + creating: ginagawa + updating: ina-update + failed_to_create_enterprise: "hindi nagtagumpay sa paggawa ng iyong enterprise" + failed_to_create_enterprise_unknown: "hindi nagtagumpay sa paggawa ng iyong enterprise.\nsiguraduhing ang lahat ng patlang ay nasagutan." + failed_to_update_enterprise_unknown: "hindi nagtagumpay sa pag-update ng iyong enterprise.\nsiguraduhing ang lahat ng patlang ay nasagutan." + enterprise_confirm_delete_message: "mabubura rin ang%{product}na sinusuplay ng enterprise na ito. sigurado ka bang nais mo magpatuloy?" + order_not_saved_yet: "ang order mo ay hindi pa na-save. bigyan kami ng ilang segundo para tapusin ito." + filter_by: "i-filter gamit ang" + hide_filters: "itago ang mga filter" + one_filter_applied: "1 filter ang inilapat" + x_filters_applied: "inilapat ang mga filter" + submitting_order: "sinusimite ang iyong order: maghintay sandali" + confirm_hub_change: "sigurado ka ba? mapapalitan nito ang pinili mong hub at tatanggalin ang mga item sa iyong cart." + confirm_oc_change: "sigurado ka ba? mapapalitan nito ang pinili mong order cycle at tatanggalin ang mga item sa iyong cart." + location_placeholder: "mag-type ng lokasyon..." + error_required: "hindi maaaring iwanang blanko" + error_number: "ay dapat numero" + error_email: "ay dapat email address" + error_not_found_in_database: "%{name}ay hindi mahanap sa database" + error_not_primary_producer: "%{name}ay hindi isang producer" + error_no_permission_for_enterprise: "\"%{name}\": wala kang permiso para pamahalaan ang mga produkto ng enterprise na ito." + item_handling_fees: "bayad sa paghawak ng item (kasama sa kabuuan ng item)" + january: "Enero" + february: "Pebrero" + march: "Marso" + april: "Abril" + may: "Mayo" + june: "Hunyo" + july: "Hulyo" + august: "Agosto" + september: "Setyembre" + october: "Oktubre" + november: "Nobyembre" + december: "Disyembre" + email_not_found: "hindi mahanap ang email address" + email_unconfirmed: "kailangang kumpirmahin muna ang email address bago ma-reset ang password." + email_required: "kailangang magbigay ng email address" + logging_in: "maghintay sandali, ikaw ay nila-log in na namin." + signup_email: "ang iyong email" + choose_password: "pumili ng pasword" + confirm_password: "kumpirmahin ang password" + action_signup: "magsign-up ngayon" + forgot_password: "nakalimutan ang password?" + password_reset_sent: "ang email na may panuto kung paano papalitan ang inyong password ay napadala na!" + reset_password: "palitan ang password" + update_and_recalculate_fees: "i-update at kwentahin muli ang mga bayarin" + registration: + steps: + introduction: + registration_greeting: "Kumusta?" + registration_intro: "maaari ka ng gumawa ng profile para sa inyong Producer o Hub" + registration_checklist: "ano ang kailangan ko gawin?" + registration_time: "5-10 minuto" + registration_enterprise_address: "Address ng enterprise" + registration_contact_details: "pangunahing detalye ng contact" + registration_logo: "ang larawan ng iyong logo" + registration_promo_image: "ang pahigang larawan para sa inyong profile" + registration_about_us: "'Tungkol sa Amin' na teksto" + registration_outcome_headline: "ano ang makukuha ko?" + registration_outcome1_html: "ang iyong profile ang makakatulong sa mga taona hanapinatkontakin ka sa Open Food Network." + registration_outcome2: "gamitin ang espasyo na ito upang ipakilala ang iyong enterprise, para na rin sa pagpapalawig ng iyong koneksyon sa internet." + registration_outcome3: "ito rin ay unang hakbang para makipagkalakalan sa Open Food Network, o pagbubukas ng sariling tindahan sa internet." + registration_action: "Magsimula na tayo!" + details: + title: "detalye" + headline: "magsimula na tayo" + enterprise: "una sa lahat ay kailangan naming mas makilala ang iyong enterprise:" + producer: "una sa lahat ay kailangan naming mas makilala ang iyong bukid:" + enterprise_name_field: "pangalan ng enterprise:" + producer_name_field: "pangalan ng bukid:" + producer_name_field_placeholder: "hal. Charlie's Awesome Farm" + producer_name_field_error: "pumili ng natatanging pangalan para sa inyong enterprise" + address1_field: "linya ng address 1 :" + address1_field_placeholder: "hal. 123 Cranberry Drive" + address1_field_error: "isulat ang address" + address2_field: "linya ng address 2 :" + suburb_field: "lungsod:" + suburb_field_placeholder: "hal. Northcote" + suburb_field_error: "isulat ang lungsod" + postcode_field: "Postcode:" + postcode_field_placeholder: "hal. 3070" + postcode_field_error: "kailangang ilagay ang postcode" + state_field: "Probinsiya:" + state_field_error: "Kailangang ang probinsiya" + country_field: "Bansa:" + country_field_error: "pumili ng bansa" + contact: + title: "Makipag-ugnayan" + who_is_managing_enterprise: "sino ang responsable sa pamamahala ng%{enterprise}?" + contact_field: "Pangunahing contact" + contact_field_placeholder: "Contact name" + contact_field_required: "kailangang maglagay ng pangunahing contact" + phone_field: "telepono" + phone_field_placeholder: "hal. (03) 1234 5678" + type: + title: "uri" + headline: "huling hakbang para maidagdag ang%{enterprise}!" + question: "isa ka bang producer?" + yes_producer: "oo, ako ay isang producer" + no_producer: "hindi ako producer" + producer_field_error: "pumili ng isa. ikaw ba ay isang producer?" + yes_producer_help: "Ang mga producer ay gumagawa ng masasarap na bagay na maaaring makain o mainom. Ikaw ay isang producer kung itinatanim mo ito, pinapalaki, binuburo, niluluto, hinuhurno, ginagatasan o hinuhulma." + no_producer_help: "kung hindi ka isang producer, malamang ikaw ay nagbebenta at namamahagi ng mga pagkain. maaaring ikaw ay isang Hub, coop, grupo ng mamimili, nagtitingi, namamakyaw o iba pa." + create_profile: "gumawa ng profile" + about: + title: "tungkol sa" + headline: "binabati kita!" + message: "ngayon ay ilagay na natin ang mga detalye tungkol sa" + success: "tagumpay!%{enterprise}ay naidagdag na sa Open Food Network." + registration_exit_message: "kung ikaw ay lalabas sa wizard na ito sa kahit anong yugto, maaari kang magpatuloy sa paggawa ng profile sa pamamagitan ng pagpunta sa interface ng admin." + enterprise_description: "maikling paglalarawan" + enterprise_description_placeholder: "isang maikling pangungusap na naglalarawan ng iyong enterprise." + enterprise_long_desc: "mahabang paglalarawan" + enterprise_long_desc_placeholder: "ito ang inyong pagkakataon upang ipakilala ang iyong enterprise-kung ano ang kaibahan mo sa iba at paano ka nakahihigit? iminumungkahi namin na gumamit ng 600 na letra o mas mababa pa o 150 salita sa pagbibigay ng paglalarawan." + enterprise_long_desc_length: "%{num}na mga letra/ hanggang 600 ang iminumungkahi" + enterprise_abn: "ABN" + enterprise_abn_placeholder: "hal. 99 123 456 789" + enterprise_acn: "ACN" + enterprise_acn_placeholder: "hal. 123 456 789" + enterprise_tax_required: "kailangang gumawa ng pagpipilian." + images: + title: "larawan" + headline: "maraming salamat!" + description: "tayo na at mag-upload ng mga larawan upang maging maganda ang iyong profile! :-)" + uploading: "ina-upload...." + continue: "Magpatuloy" + back: "bumalik" + logo: + select_logo: "hakbang 1, pumili ng larawan ng Logo" + logo_tip: "Tip: pinakamaganda ang mga parisukat na larawan, mas mabuti kung ito ay 300x300px" + logo_label: "pumili ng larawan ng logo" + logo_drag: "hilahin at ilagay ang logo dito" + review_logo: "hakbang 2. suriin ang iyong logo" + review_logo_tip: "Tip: para sa mas maayos na resulta, ang logo ay dapat matakpan ang lahat ng espasyo" + logo_placeholder: "ang iyong logo ay makikita dito para masuri kapag na-upload na" + promo: + select_promo_image: "hakbang 3. pumili ng larawan ng promo" + promo_image_tip: "Tip: ipapakita bilang banner, ang mas mabuting laki ay 1200x260px" + promo_image_label: "pumili ng larawan ng promo" + promo_image_drag: "hilahin at ilagay ang promo dito" + review_promo_image: "hakbang 4. suriin ang iyong banner ng promo" + review_promo_image_tip: "Tip: para sa pinakamagandang resulta, ang iyong promo na larawan ay dapat masakop ang lahat ng espasyo" + promo_image_placeholder: "ang iyong logo ay makikita dito para masuri kapag na-upload na" + social: + title: "Social" + enterprise_final_step: "Huling hakbang!" + enterprise_social_text: "paano mahahanap ng mga tao ang%{enterprise}sa internet?" + website: "website" + website_placeholder: "hal. openfoodnetwork.org.au" + facebook: "Facebook" + facebook_placeholder: "hal. www.facebook.com/pangalanngpahina" + linkedin: "LinkedIn" + linkedin_placeholder: "hal. www.linkedin.com/YourNameHere" + twitter: "Twitter" + twitter_placeholder: "hal. @twitter_handle" + instagram: "Instagram" + instagram_placeholder: "hal. @instagram_handle" + limit_reached: + headline: "Oh Hindi!" + message: "Naabot mo na ang limit!" + text: "naabot mo na ang limit na dami ng mga enterprise na iyong pag-aari sa" + action: "bumalik sa homepage" + finished: + headline: "Tapos na!" + thanks: "maraming salamat sa pagbigay ng mga detalye para sa%{enterprise}." + login: "maaari mong palitan o i-update ang iyong enterprise sa pamamagitan ng paglog-in sa Open Food Network at puntahan ang Admin." + action: "pumunta sa dashboard ng Enterprise" + back: "bumalik" + continue: "Magpatuloy" + action_or: "O" + enterprise_limit: Limitasyon ng enterprise + shipping_method_destroy_error: "ang paraan ng pagpapadala ay hindi maaaring burahin sapagkat ito ay nakasangguni na sa isang order:%{number}." + fees: "mga bayarin" + item_cost: "halaga ng item" + bulk: "Bulto" + shop_variant_quantity_min: "pinakakaunti" + shop_variant_quantity_max: "pinakamarami" + follow: "sumunod" + shop_for_products_html: "mamili ng%{enterprise}na mga produkto sa:" + change_shop: "palitan ang shop ng:" + shop_at: "mamili ngayon sa:" + price_breakdown: "ibaba ang listahan ng presyo" + admin_fee: "bayad sa admin" + sales_fee: "bayad sa pagbebenta" + packing_fee: "bayad sa pagbabalot" + transport_fee: "bayad sa pagdadala" + fundraising_fee: "bayad sa pangangalap ng pondo" + price_graph: "graph ng presyo" + included_tax: "kasamang tax" + balance: "Balanse" + transaction: "transaksyon" + transaction_date: "petsa" + payment_state: "status ng bayad" + shipping_state: "status ng pagpapadala" + value: "halaga" + balance_due: "balanseng kelangan bayaran" + credit: "utang" + Paid: "bayad na" + Ready: "handa" + ok: OK + not_visible: hindi nakikita + you_have_no_orders_yet: "wala ka pang mga order" + show_only_complete_orders: "Ipakita lamang ang mga nakumpletong order" + successfully_created: '%{resource}ay matagumpay na nagawa!' + successfully_removed: '%{resource}ay matagumpay na natanggal!' + successfully_updated: '%{resource}ay matagumpay na na-update' + running_balance: "tumatakbong balanse" + outstanding_balance: "natitirang balanse" + admin_enterprise_relationships: "mga permiso ng enterprise" + admin_enterprise_relationships_everything: "lahat" + admin_enterprise_relationships_permits: "mga permit" + admin_enterprise_relationships_seach_placeholder: "hanapin" + admin_enterprise_relationships_button_create: "gumawa" + admin_enterprise_groups: "mga grupo ng enterprise" + admin_enterprise_groups_name: "pangalan" + admin_enterprise_groups_owner: "may-ari" + admin_enterprise_groups_on_front_page: "sa harapang pahina?" + admin_enterprise_groups_enterprise: "enterprises" + admin_enterprise_groups_data_powertip: "ang pangunahing gumagamit na responsable sa grupo na ito" + admin_enterprise_groups_data_powertip_logo: "ito ang logo ng inyong grupo" + admin_enterprise_groups_data_powertip_promo_image: "ang larawan na ito ay makikita sa taas ng profile ng grupo" + admin_enterprise_groups_contact: "Makipag-ugnayan" + admin_enterprise_groups_contact_phone_placeholder: "hal. 98 7654 3210" + admin_enterprise_groups_contact_address1_placeholder: "eg. 123 High Street" + admin_enterprise_groups_contact_city: "lungsod" + admin_enterprise_groups_contact_city_placeholder: "hal. Northcote" + admin_enterprise_groups_contact_zipcode: "Postcode" + admin_enterprise_groups_contact_zipcode_placeholder: "hal. 3070" + admin_enterprise_groups_contact_state_id: "Probinsiya" + admin_enterprise_groups_contact_country_id: "Bansa" + admin_enterprise_groups_web: "mga pinagkukuhanan ng Web" + admin_enterprise_groups_web_twitter: "hal. @the_prof" + admin_enterprise_groups_web_website_placeholder: "hal. www.truffles.com" + admin_order_cycles: "mga order cycle ng Admin" + open: "bukas" + close: "isara" + create: "gumawa" + search: "hanapin" + supplier: "Supplier" + product_name: "pangalan ng produkto" + product_description: "paglalarawan ng produkto" + units: "laki kada yunit" + coordinator: "coordinator" + distributor: "Distributor" + enterprise_fees: "bayad para sa enterprise" + process_my_order: "iproseso ang aking order" + delivery_instructions: mga panuto sa pagdeliver + delivery_method: paraan ng pagdeliver + fee_type: "uri ng kabayaran" + tax_category: "kategorya ng tax" + calculator: "calculator" + calculator_values: "mga halaga sa calculator" + calculator_settings_warning: "kung papalitan ang uri ng calculator, dapat ay i-save muna bago maiayos ang setting ng calculator" + flat_percent_per_item: "Flat percent (kada item)" + flat_rate_per_item: "Flat Rate (kada item)" + flat_rate_per_order: "Flat rate (kada order)" + flexible_rate: "nababagong rate" + price_sack: "Price Sack" + new_order_cycles: "bagong mga order cycle" + new_order_cycle: "bagong order cycle" + select_a_coordinator_for_your_order_cycle: "pumili ng coordinator para sa iyong order cycle" + notify_producers: 'ipagbigay-alam sa mga producer' + edit_order_cycle: "i-edit ang order cycle" + roles: "mga tungkulin" + update: "i-update" + delete: tanggalin + add_producer_property: "magdagdag ng pag-aari ng producer" + in_progress: "nasa proseso" + started_at: "nagsimula sa" + queued: "nakapila" + scheduled_for: "naka-iskedyul para sa" + customers: "mga customer" + please_select_hub: "pumili ng Hub" + loading_customers: "naglo-load ng mga Customer" + no_customers_found: "walang nahanap ng mga customer" + go: "Sige" + hub: "Hub" + producer: "Producer" + product: "produkto" + price: "presyo" + on_hand: "on hand" + review: "suriin" + save_changes: "i-save ang mga pagbabago" + order_saved: "ang order ay na-save na" + no_products: walang mga produkto + spree_admin_overview_enterprises_header: "ang aking mga enterprise" + spree_admin_overview_enterprises_footer: "PAMAHALAAN ANG AKING MGA ENTERPRISE" + spree_admin_enterprises_hubs_name: "pangalan" + spree_admin_enterprises_create_new: "GUMAWA NG BAGO" + spree_admin_enterprises_shipping_methods: "mga paraan ng pagpapadala" + spree_admin_enterprises_fees: "bayad para sa enterprise" + spree_admin_enterprises_none_create_a_new_enterprise: "GUMAWA NG BAGONG ENTERPRISE" + spree_admin_enterprises_none_text: "wala ka pang mga enterprise" + spree_admin_enterprises_tabs_hubs: "MGA HUB" + spree_admin_enterprises_producers_manage_products: "PAMAHALAAN ANG MGA PRODUKTO" + spree_admin_enterprises_create_new_product: "GUMAWA NG BAGONG PRODUKTO" + spree_admin_single_enterprise_alert_mail_confirmation: "kumpirmahin ang email address para sa/kay" + spree_admin_single_enterprise_alert_mail_sent: "naipadala na ang email sa" + spree_admin_overview_action_required: "kinakailangan ng aksyon" + spree_admin_overview_check_your_inbox: "tignan ang iyong inbox para sa karagdagang panuto. maraming salamat!" + spree_admin_unit_value: halaga kada yunit + spree_admin_unit_description: paglalarawan sa bawat yunit + spree_admin_variant_unit: Variant unit + spree_admin_variant_unit_scale: sukat ng Variant unit + spree_admin_supplier: Supplier + spree_admin_product_category: kategorya ng produkto + spree_admin_variant_unit_name: pangalan ng variant unit + unit_name: "pangalan ng yunit" + change_package: "palitan ang package" + spree_admin_single_enterprise_hint: "payo: para mahanap ka ng mga tao, i-turn on ang visibility sa ilalim ng" + spree_admin_eg_pickup_from_school: "hal. 'Pick-up from Primary School'" + spree_admin_eg_collect_your_order: "hal. 'Please collect your order from 123 Imaginary St, Northcote, 3070'" + spree_classification_primary_taxon_error: "ang Tax sa%{taxon}ay ang pangunahing tax ng %{product}at hindi maaaring tanggalin" + spree_order_availability_error: "ang distributor o order cycle ay hindi kayang ibigay ang mga produkto sa inyong cart" + spree_order_populator_error: "ang distributor o order cycle na ito ay hindi kayang ibigay lahat ng mga produkto sa inyong cart. pumili ng iba." + spree_order_populator_availability_error: "ang produktong ito ay hindi ngayon available mula sa napiling distributor o order cycle." + spree_distributors_error: "pumili ng kahit isa sa mga Hub" + spree_user_enterprise_limit_error: "^%{email}ay walang permiso na mag-ari ng karagdagang mga enterprise (ang limitasyon ay%{enterprise_limit})." + spree_variant_product_error: ay dapat mayroong kahit isang uri + your_profil_live: "ang iyong live na profile" + on_ofn_map: "sa Open Food Network map" + see: "Tignan" + live: "live" + manage: "pamahalaan" + resend: "ipadala muli" + add_and_manage_products: "magdagdag at pamahalaan ang mga produkto" + add_and_manage_order_cycles: "magdagdag at pamahalaan ang mga order cycle" + manage_order_cycles: "pamahalaan ang mga order cycle" + manage_products: "pamahalaan ang mga produkto" + edit_profile_details: "ayusin ang mga detalye ng profile" + edit_profile_details_etc: "palitan ang paglalarawan, larawan at iba pa ng iyong profile" + order_cycle: "order cycle" + order_cycles: "order cycles" + enterprise_relationships: "mga permiso ng enterprise" + remove_tax: "alisin ang tax" + first_name_begins_with: "ang pangalan ay nagsisimula sa" + last_name_begins_with: "ang apelyido ay nagsisimula sa" + enterprise_tos_link: "Link para sa palatuntunan ng serbisyo ng Enterprise" + enterprise_tos_message: "nais naming makiisa sa mga taong kapareho ng aming layunin at adhikain. Dahil dito, hinihiling namin sa mga bagong enterprise na sumang-ayon sa aming" + enterprise_tos_link_text: "Palatuntunan ng serbisyo." + enterprise_tos_agree: "ako ay sumasang-ayon sa palatuntunan ng serbisyo na nasa itaas." + tax_settings: "settings ng tax" + products_require_tax_category: "ang mga produkto ay kailangang may kategorya ng tax" + admin_shared_address_1: "tirahan" + admin_shared_address_2: "address (pagpapatuloy)" + admin_share_city: "Lungsod" + admin_share_zipcode: "Postcode" + admin_share_country: "Bansa" + admin_share_state: "Status" + hub_sidebar_hubs: "Hubs" + hub_sidebar_none_available: "walang available" + hub_sidebar_manage: "pamahalaan" + hub_sidebar_at_least: "pumili ng kahit isa sa mga Hub" + hub_sidebar_blue: "bughaw" + hub_sidebar_red: "pula" + report_customers_distributor: "Distributor" + report_customers_supplier: "Suuplier" + report_customers_cycle: "order cycle" + report_customers_type: "uri ng ulat" + report_customers_csv: "i-download bilang csv" + report_producers: "mga producer:" + report_type: "uri ng ulat:" + report_hubs: "mga Hub:" + report_payment: "mga uri ng pagbabayad:" + report_distributor: "Distributor:" + report_payment_by: 'pagbabayad kada uri' + report_itemised_payment: 'kabuuan ng mga in-itemise na bayad' + report_payment_totals: 'kabuuan ng bayad' + report_all: 'lahat' + report_order_cycle: "Order Cycle:" + report_enterprises: "mga Enterprise:" + report_users: "mga gumagamit:" + report_tax_rates: mga rate ng tax + report_tax_types: mga uri ng tax + report_header_order_cycle: order cycle + report_header_user: User + report_header_email: email + report_header_status: Status + report_header_comments: mga puna + report_header_first_name: Pangalan + report_header_last_name: Apelyido + report_header_phone: telepono + report_header_suburb: lungsod + report_header_address: tirahan + report_header_billing_address: Billing Address + report_header_relationship: relasyon + report_header_hub: Hub + report_header_hub_address: address ng Hub + report_header_to_hub: sa Hub + report_header_hub_code: code ng Hub + report_header_code: Code + report_header_paid: bayad na? + report_header_delivery: dini-deliver? + report_header_shipping: pagpapadala + report_header_shipping_method: paraan ng pagpapadala + report_header_shipping_instructions: panuto sa pagpapadala + report_header_ship_street: kalsada na pagpapadalahan + report_header_ship_street_2: kalsada na pagpapadalahan 2 + report_header_ship_city: lungsod na pagpapadalahan + report_header_ship_postcode: postcode ng pagpapadalahan + report_header_ship_state: status ng pagpapadala + report_header_billing_street: address na papadalahan ng bayarin + report_header_billing_street_2: address na papadalahan ng bayarin 2 + report_header_billing_street_3: address na papadalahan ng bayarin 3 + report_header_billing_street_4: address na papadalahan ng bayarin 4 + report_header_billing_city: lungsod na papadalahan ng bayarin + report_header_billing_postcode: postcode ng papadalahan ng bayarin + report_header_billing_state: status ng papadalahan ng bayarin + report_header_incoming_transport: papasok na sasakyan + report_header_special_instructions: espesyal na mga panuto + report_header_order_number: numero ng order + report_header_date: petsa + report_header_confirmation_date: petsa ng kumpirmasyon + report_header_tags: tags + report_header_items: mga item + report_header_items_total: "kabuuan ng mga item%{currency_symbol}" + report_header_taxable_items_total: "kabuuan ng mga item na taxable (%{currency_symbol})" + report_header_sales_tax: "tax sa mga nabenta (%{currency_symbol})" + report_header_delivery_charge: "bayad sa pag-deliver(%{currency_symbol})" + report_header_tax_on_delivery: "tax sa pagdeliver (%{currency_symbol})" + report_header_tax_on_fees: "tax sa mga bayarin (%{currency_symbol})" + report_header_total_tax: "kabuuang tax(%{currency_symbol})" + report_header_enterprise: Enterprise + report_header_customer: customer + report_header_customer_code: Code ng Customer + report_header_product: produkto + report_header_product_properties: mga katangian ng produkto + report_header_quantity: dami + report_header_max_quantity: Pinakamarami + report_header_variant: Uri + report_header_variant_value: Halaga ng Variant + report_header_variant_unit: Yunit ng variant + report_header_total_available: Kabuuan na mayroon + report_header_unallocated: hindi pinapamahalaan + report_header_max_quantity_excess: Sumobra sa limit na pinakamarami + report_header_taxons: Taxons + report_header_supplier: Supplier + report_header_producer: Producer + report_header_producer_suburb: Lungsod ng Producer + report_header_unit: yunit + report_header_group_buy_unit_quantity: Dami ng yunit para sa Maramihang pagbili + report_header_cost: gastos + report_header_shipping_cost: gastos sa pagpapadala + report_header_curr_cost_per_unit: kasalukuyang gastos kada yunit + report_header_total_shipping_cost: 'kabuuang gastos sa pagpapadala ' + report_header_payment_method: paraan ng pagbayad + report_header_sells: nagbebenta + report_header_visible: nakikita + report_header_price: presyo + report_header_unit_size: laki kada yunit + report_header_distributor: Distributor + report_header_distributor_address: Address ng Distributor + report_header_distributor_city: Lungsod ng Distributor + report_header_distributor_postcode: Postcode ng Distributor + report_header_delivery_address: address kung saan ide-deliver + report_header_delivery_postcode: postcode kung saan ide-deliver + report_header_bulk_unit_size: laki ng bawat bultuhang yunit + report_header_weight: timbang + report_header_sum_total: Kabuuan + report_header_date_of_order: Petsa ng Order + report_header_amount_owing: halaga ng utang + report_header_amount_paid: Halagang Nabayaran + report_header_units_required: mga kailangang yunit + report_header_remainder: Natitira + report_header_order_date: Petsa ng order + report_header_order_id: Order Id + report_header_item_name: Pangalan ng Item + report_header_temp_controlled_items: Temp ng mga kontroladong mga item? + report_header_customer_name: Pangalan ng Customer + report_header_customer_email: Email ng Customer + report_header_customer_phone: Telepono ng Customer + report_header_customer_city: Lungsod ng Customer + report_header_payment_state: status ng pagbabayad + report_header_payment_type: uri ng pagbabayad + report_header_item_price: "item(%{currency})" + report_header_item_fees_price: "item + bayad (%{currency})" + report_header_admin_handling_fees: "Admin at paghawak (%{currency})" + report_header_ship_price: "pagdala (%{currency})" + report_header_pay_fee_price: "Bayad sa pagbabayad (%{currency})" + report_header_total_price: "Kabuuan (%{currency})" + report_header_product_total_price: "Kabuuang Produkto (%{currency})" + report_header_shipping_total_price: "kabuuan ng ipapadala (%{currency})" + report_header_outstanding_balance_price: "Kasalukuyang balanse (%{currency})" + report_header_eft_price: "EFT (%{currency})" + report_header_paypal_price: "Paypal (%{currency})" + report_header_sku: SKU + report_header_amount: halaga + report_header_balance: Balanse + report_header_total_cost: "Kabuuang Gastos" + report_header_total_ordered: Kabuuang na-order + report_header_total_max: kabuuang pinakamataas na limit + report_header_total_units: kabuuang yunit + report_header_sum_max_total: "kabuuan" + report_header_total_excl_vat: "Kabuuang tax na hindi kasama (%{currency_symbol})" + report_header_total_incl_vat: "Kabuuang tax na kasama (%{currency_symbol})" + report_header_temp_controlled: TempControlled? + report_header_is_producer: Producer? + report_header_not_confirmed: hindi kumpirmado + report_header_gst_on_income: GST sa Kinikita + report_header_gst_free_income: GST sa Libreng Kinikita + report_header_total_untaxable_produce: kabuuang produkto na untaxable (walang tax) + report_header_total_taxable_produce: kabuuang produkto na taxable (may kasamang tax) + report_header_total_untaxable_fees: kabuuang bayarin na untaxable (walang tax) + report_header_total_taxable_fees: kabuuang bayarin na taxable (may kasamang tax) + report_header_delivery_shipping_cost: Singil sa pagdeliver ng pinapadala (kasama ang tax) + report_header_transaction_fee: Bayad sa Transaksyon (walang tax) + report_header_total_untaxable_admin: kabuuang untaxable na pagsasaayos ng admin (walang tax) + report_header_total_taxable_admin: kabuuang taxable na pagsasaayos ng admin (kasama ang tax) + initial_invoice_number: "paunang numero ng invoice:" + invoice_date: "Petsa ng Invoice:" + due_date: "Due Date:" + account_code: "code ng Account:" + equals: "katumbas" + contains: "naglalaman" + discount: "Diskwento" + filter_products: "i-filter ang mga produkto" + delete_product_variant: "ang huling mga variant ay hindi matanggal!" + progress: "progreso" + saving: "sine-save.." + success: "tagumpay" + failure: "pagkabigo" + unsaved_changes_confirmation: "ang mga hindi na-save na pagbabago ay mawawala. magpatuloy pa rin?" + one_product_unsaved: "ang mga pagbabagong ginawa sa isang produkto ay hindi pa nase-save." + products_unsaved: "ang mga pagbabagong ginawa sa%{n} produkto ay hindi pa nase-save." + is_already_manager: "ay isa nang tagapamahala" + no_change_to_save: "walang pagbabagong ise-save" + user_invited: "%{email}ay naimbitahan na para pamahalaan ang enterprise na ito." + add_manager: "magdagdag ng gumagamit" + users: "mga gumagamit" + about: "tungkol sa" + images: "larawan" + web: "Web" + primary_details: "pangunahing detalye" + adrdress: "tirahan" + contact: "Makipag-ugnayan" + social: "Social" + business_details: "detalye ng negosyo" + properties: "mga katangian" + shipping: "pagpapadala" + shipping_methods: "mga paraan ng pagpapadala" + payment_methods: "Mga Paraan ng Pagbabayad" + payment_method_fee: "bayad sa transaksyon" + payment_processing_failed: "hindi maproseso ang bayad, maaaring suriin ang mga detalyeng inilagay" + payment_method_not_supported: "ang piniling paraan ng pagbabayad ay hindi suportado. pumili ng isa pa" + payment_updated: "na-update na ang bayad" + inventory_settings: "mga setting para sa imbentaryo" + tag_rules: "panuntunan sa pag-tag" + shop_preferences: "mga kagustuhan sa shop" + enterprise_fee_whole_order: Buong order + enterprise_fee_by: "%{type}na bayad ng%{role}%{enterprise_name}" + validation_msg_relationship_already_established: "^ang relasyon ay naitatag na" + validation_msg_at_least_one_hub: "^kailangang kahit isang Hub ay piliin" + validation_msg_tax_category_cant_be_blank: "^ang kategorya ng tax ay hindi maaaring walang sagot" + validation_msg_is_associated_with_an_exising_customer: "ay nauugnay na sa isang customer" + content_configuration_pricing_table: "(DAPATGAWIN: TALAAN NG PRESYO)" + content_configuration_case_studies: "(DAPATGAWIN: mga pag-aaral ng kaso)" + content_configuration_detail: "(DAPATGAWIN: detalye)" + enterprise_name_error: "ay nagamit na. kung ito ay iyong enterprise at nais mong kunin ang pagmaymay-ari, o kung nais mong makipagkalakalan sa enterprise na ito, makipag-ugnayan sa kasalukuyang tagapamahala ng profile na ito sa %{email}." + enterprise_owner_error: "^%{email}ay walang permiso na mag-ari ng karagdagang mga enterprise (ang limitasyon ay%{enterprise_limit})." + enterprise_role_uniqueness_error: "^ang tungkulin na iyon ay may nagmamay-ari na" + inventory_item_visibility_error: ay dapat totoo o hindi totoo + product_importer_file_error: "error: walang file na na-upload" + product_importer_spreadsheet_error: "hindi maproseso ang file: invalid na uri ng file" + product_importer_products_save_error: hindi matagumpay na na-save ang mga produkto + product_import_file_not_found_notice: 'ang file ay hindi mahanap o mabuksan ' + product_import_no_data_in_spreadsheet_notice: 'walang data na mahanap sa spreadsheet' + order_choosing_hub_notice: ang iyong Hub ay napili + order_cycle_selecting_notice: ang iyong order cycle ay napili + adjustments_tax_rate_error: "^siguraduhing ang rate ng tax para sa adjustment na ito ay tama." + active_distributors_not_ready_for_checkout_message_singular: >- + ang Hub na%{distributor_names}ay kasamang nakalista sa isang aktibong order + cyle ngunit walang valid na paraan ng pagbabayad at pagpapadala. Hanggang hindi + pa naisasaayos ang pagset-up, hindi makakapamili ang mga customer sa hub na + ito. + active_distributors_not_ready_for_checkout_message_plural: >- + ang mga Hub na %{distributor_names}ay kasamang nakalista sa isang aktibong order + cycle ngunit walang valid na paraan ng pagpapadala at pagbabayad. Hanggang hindi + pa naisasaayos ang pagset-up, hindi makakapamili ang mga customer sa mga hub + na ito. + enterprise_fees_update_notice: ang mga bayarin ng inyong enterprise ay na-update na + enterprise_register_package_error: "pumili ng package" + enterprise_register_error: "hindi makumpleto ang rehistrasyon para sa%{enterprise}" + enterprise_register_success_notice: "maligayang pagbati! ang rehistrasyon para sa%{enterprise}ay kumpleto na!" + enterprise_bulk_update_success_notice: "ang mga enterprise ay matagumpay na na-update" + enterprise_bulk_update_error: 'hindi matagumpay ang pag-update' + enterprise_shop_show_error: "ang shop na hinahanap mo ay wala o hindi aktibo sa OFN. Maaaring tignan ang ibang shops." + order_cycles_create_notice: 'ang iyong order cycle ay nagawa na.' + order_cycles_update_notice: 'ang iyong order cycle ay na-update na' + order_cycles_bulk_update_notice: 'ang mga order cycle ay na-update na' + order_cycles_clone_notice: "ang iyong order cyle %{name}ay kinopya." + order_cycles_email_to_producers_notice: 'ang mga email na ipapadala sa mga producer ay naghihintay na maipadala.' + order_cycles_no_permission_to_coordinate_error: "wala sa inyong mga enterprise ay may pahintulot na magsa-ayos ng order cycle" + order_cycles_no_permission_to_create_error: "wala kang pahintulot na gumawa ng order cycle na isinaayos ng enterprise na iyon." + back_to_orders_list: "bumalik sa listahan ng order" + no_orders_found: "walang mahanap na mga order" + order_information: "impormasyon tungkol sa order" + date_completed: "petsa kung kailan na kumpleto" + amount: "halaga" + state_names: + ready: handa + pending: nakabinbin + shipped: na-ship na + js: + saving: 'sine-save...' + changes_saved: 'nai-save ang mga pagbabago' + save_changes_first: i-save muna ang mga pagbabago + all_changes_saved: lahat ng pagbabago ay na-save na + unsaved_changes: may mga hindi na-save na pagbabago + all_changes_saved_successfully: lahat ng pagbabago ay matagumpay na na-save + oh_no: "paumanin! hindi ko na-save ang mga pagbabagong ginawa mo." + unauthorized: "ikaw ay hindi awtorisadong i-access ang pahina na ito." + error: Error + unavailable: hindi available + profile: profile + hub: Hub + shop: Shop + choose: pumili + resolve_errors: paki-ayos ang mga sumusunod na mga error + more_items: "+%{count}iba pa" + default_card_updated: na-update ang default card + admin: + enterprise_limit_reached: "naabot mo na ang karaniwang lmitasyon ng dami ng bilang ng mga enterprise sa bawat account. makipag-ugnayan sa%{contact_email}kung kailangan mo itong dagdagan." + modals: + got_it: nakuha na + close: "isara" + invite: "mag-imbita" + invite_title: "mag-imbita ng hindi rehistradong user" + tag_rule_help: + title: panuntunan sa pag-tag + overview: pangkalahatang ideya + overview_text: > + ang panuntunan sa tag na nagbibigay ng paraan upang maisalarawan kung + anong mga item ang nakikita at kung sa kaninong mga customer dapat ito + maipakita. Ang mga item ay maaaring paraan ng pagpapadala, paraan ng + pagbabayad, mga produkto at mga order cycle. + by_default_rules: "'By Default...' mga panuntunan" + by_default_rules_text: > + ang default na mga panuntunan ay papayagan ka na magtago ng mga item + upang hindi ito makita. ang gawaing ito ay maaaring saklawan ng hindi + default na panuntunan para sa mga customer na may tag. + customer_tagged_rules: "'Mga Customer na naka-tag...' mga panuntunan" + customer_tagged_rules_text: > + sa pamamagitan ng paggawa ng mga panuntunan na may kinalaman sa isang + partikular na customer na naka-tag, maaari mong saklawan ang kinagawiang + gawain(sa pagpapakita man o pagtago ng mga item) para sa mga customer + na may tag. + panels: + save: I-SAVE + saved: NA-SAVE NA + saving: SINESAVE + enterprise_package: + hub_profile: profile ng hub + hub_profile_cost: "HALAGANG BABAYARAN: PALAGING LIBRE" + hub_profile_text1: > + Maaari kayong mahanap at makausap ng mga tao sa Open Food Network. ang + inyong enterprise ay makikita sa mapa at maaaring ma-search sa listahan. + hub_profile_text2: > + ang pagkakaroon ng profile at paggawa ng koneksyon sa mga lokal na sistema + ng pagkain gamit ang Open Food Network ay palaging walang bayad. + hub_shop: Hub Shop + hub_shop_text1: > + ang iyong enterprise ang saligan ng iyong lokal na sistema ng pagkain. + pinagsasama sama mo ang mga produkto mula sa ibang mga enterprise at + maaari mo itong ibenta sa pamamagitang ng iyong shop sa Open Food Network. + hub_shop_text2: > + ang mga hub ay maaring co-op ng pagkain, grupo ng mamimili, isang programang + veggie-box o isang lokal na grocery store. + hub_shop_text3: > + kung nais mo ring ibenta ang inyong sariling mga produkto, kailangang + palitan ang enterprise na ito upang maging producer. + choose_package: Pumili ng package + choose_package_text1: > + ang inyong enterprise ay hindi maa-activate hanggang hindi pumipili + ng package mula sa pagpipilian sa kaliwa + choose_package_text2: > + Pumindot sa kahit anong pagpipilian para makita ang detalyadong impormasyon + tungkol sa bawat package. Pindutin ang pulang SAVE na button kapag tapos + na! + profile_only: Profile lamang + profile_only_cost: "HALAGANG BABAYARAN: PALAGING LIBRE" + profile_only_text1: > + maaari kang makita at makausap ng iba sa pamamagitan ng profile at paraan + din ito upang maisalaysay ang inyong kwento. + profile_only_text2: > + kung mas nais mong magpokus sa paggawa ng pagkain at ipaubaya sa iba + ang pagbebenta nito, hindi kailangan ang shop sa Open Food Network. + profile_only_text3: > + idagdag ang inyong produkto sa Open Food Network, upang mabigyan ng + permiso ang mga hub na ilagay ang inyong produkto sa kanilang mga tindahan. + producer_shop: Producer Shop + producer_shop_text1: > + Direktang ibenta ang inyong produkto sa mga customer sa pamamagitan + ng iyong sariling Open Food Network shopfront. + producer_shop_text2: > + ang shop ng Producer ay para lamang sa iyong mga produkto, kung nais + mong magtinda ng mga produkto na itinanim/ginawa sa labas ng site, piliin + ang 'Hub ng producer'. + producer_hub: Producer Hub + producer_hub_text1: > + ang iyong enterprise ang saligan ng iyong lokal na sistema ng pagkain. + maaari mong ibenta ang sarili mong produkto pati na rin ang mga produktong + pinagsama sama mula sa ibang enterprise sa pamamagitan ng iyong shopfront + sa Open Food Network. + producer_hub_text2: > + ang mga hub ng producer ay maaring may iba't ibang anyo tulad ng CSA, + isang programang veggie-box o isang co-op ng pagkain na may hardin sa + rooftop. + producer_hub_text3: > + ang layunin ng Open Food Network ay sumuporta sa mga modelo ng hub gaano + man ito karami, kaya ano man ang inyong sitwasyon, nais naming ibigay + ang lahat ng inyong kakailanganin para mapatakbo ng maayos ang inyong + organisasyon o lokal na negosyo ng pagkain. + get_listing: kumuha ng listahan + always_free: PALAGING LIBRE + sell_produce_others: magbenta ng produkto mula sa iba + sell_own_produce: magbenta ng sariling produkto + sell_both: magbenta ng produkto mula sa sarili at sa iba + enterprise_producer: + producer: Producer + producer_text1: > + Ang mga producer ay gumagawa ng masasarap na bagay na maaaring makain + o mainom. Ikaw ay isang producer kung itinatanim mo ito, pinapalaki, + binuburo, niluluto, hinuhurno, ginagatasan o hinuhulma. + producer_text2: > + ang mga producer ay maaari ring gawin ang ibang tungkulin tulad ng pagsasama-sama + ng pagkain mula sa ibang mga enterprise at pagbebenta nito sa isang + shop sa Open Food Network. + non_producer: Hindi producer + non_producer_text1: > + ang mga hindi producer ay hindi gumagawa ng sarili nilang pagkain, nangangahulgang + wala silang kakayahang gumawa ng sariling mga produkto na maibebenta + sa Open Food Network. + non_producer_text2: > + sa halip, ang mga hindi producer ay dalubhasa sa pag-uugnay ng mga + producer sa mga mamili, maaaring sa pamamagitan ng pagsasama sama, pagmamarka, + pagbabalot, pagbebenta o pagde-deliver ng pagkain. + producer_desc: mga producer ng pagkain + producer_example: hal. NAGPAPATUBO, PANADERO, MANGANGALAKAL, YUMAYARI + non_producer_desc: Iba pang mga enterprise ng pagkain + non_producer_example: hal. Grocery, Food co-ops, Buying groups + enterprise_status: + status_title: "%{name}ay naset-up na at maaari na gamitin!" + severity: kalubhaan + description: paglalarawan + resolve: lutasin + exchange_products: + load_more_variants: "mag-load ng iba pang uri" + load_all_variants: "i-load ang lahat ng uri" + select_all_variants: "piliin lahat%{total_number_of_variants}Variants" + variants_loaded: "%{num_of_variants_loaded}ng%{total_number_of_variants}Variants ay na-load" + loading_variants: "nilo-load ang Variants" + tag_rules: + shipping_method_tagged_top: "naka-tag ng mga paraan ng pagpapadala" + shipping_method_tagged_bottom: "ay:" + payment_method_tagged_top: "naka-tag na paraan ng pagbabayad" + payment_method_tagged_bottom: "ay:" + order_cycle_tagged_top: "naka-tag na mga Order Cycle" + order_cycle_tagged_bottom: "ay:" + inventory_tagged_top: "nakatag- na mga uri ng imbentaryo" + inventory_tagged_bottom: "ay:" + new_tag_rule_dialog: + select_rule_type: "pumili ng uri ng panuntunan:" + add_rule: "magdagdag ng panuntunan" + enterprise_fees: + inherit_from_product: "gayahin mula sa produkto" + orders: + index: + per_page: "%{results}kada pahina" + view_file: "tignan ang file" + compiling_invoices: "tipunin ang mga invoice" + bulk_invoice_created: "nagawa ang maramihang invoice" + bulk_invoice_failed: "hindi nagtagumpay na gumawa ng maramihang invoice" + please_wait: "hintayin na maihanda ang PDF bago isara ang modal na ito." + order_state: + address: "tirahan" + adjustments: "mga pagsasaayos" + awaiting_return: "naghihintay ng pagbalik" + canceled: "na-cancel" + cart: "cart" + complete: "kumpleto" + confirm: "kumpirmahin" + delivery: "pagdeliver" + paused: "nakahinto" + payment: "pagbabayad" + pending: "nakabinbin" + resumed: "nagpatuloy" + returned: "binalik" + skrill: "Skrill" + shipment_states: + backorder: "backorder" + partial: "bahagi" + pending: "nakabinbin" + ready: "handa na" + shipped: "nai-ship na" + canceled: "na-cancel" + payment_states: + balance_due: "balanse" + completed: "nakumpleto na" + checkout: "checkout" + credit_owed: "Utang na Credit" + failed: "hindi nagtagumpay" + paid: "bayad na" + pending: "nakabinbin" + processing: "pinoproseso" + void: "walang bisa" + invalid: "invalid" + resend_user_email_confirmation: + resend: "ipadala muli" + sending: "ipadala muli..." + done: "tapos na ipadala muli ✓" + failed: "hindi matagumpay ang muling pagpapadala ✗" + order_cycles: + schedules: + adding_a_new_schedule: "Pagdadagdag ng Bagong Iskedyul" + updating_a_schedule: "pag-update sa iskedyul" + create_schedule: "Gumawa ng iskedyul" + update_schedule: "i-update ang iskedyul" + delete_schedule: "burahin ang iskedyul" + schedule_name_placeholder: "pangalan ng iskedyul" + created_schedule: "nakagawa ng iskedyul" + updated_schedule: "na-update na iskedyul" + deleted_schedule: "binurang iskedyul" + name_required_error: "Maglagay ng name para sa iskedyul na ito" + no_order_cycles_error: "pumili kahit isang order cycle (i-drag at i-drop)" + available: "Available" + selected: "napili" + customers: + index: + add_customer: "magdagdag ng Customer" + add_a_new_customer_for: "magdadag ng customer para sa%{shop_name}" + customer_placeholder: "customer@example.org" + valid_email_error: "maglagay ng valid na email address" + subscriptions: + error_saving: "error sa pag-save ng subscription" + new: + please_select_a_shop: "Pumili ng shop" + insufficient_stock: "Hindi sapat ang stock, mayroon na lamang%{on_hand} na natitira" + out_of_stock: + reduced_stock_available: binawasan ang stock na magagamit + out_of_stock_text: > + habang ikaw ay namimili, ang lebel ng stock para sa isa o higit pang mga + produkto sa inyong cart ay nabawasan. ito ang nagbago: + now_out_of_stock: ay out of stock na ngayon + only_n_remainging: "ngayon ay may%{num}na natitira" + variants: + on_demand: + 'yes': "on demand" + variant_overrides: + on_demand: + use_producer_settings: "gamitin ang setting ng producer stock" + 'yes': "oo" + 'no': "hindi" + inventory_products: "mga produktong naka-imbentaryo" + hidden_products: "mga nakatagong pprodukto" + new_products: "bagong produkto" + reset_stock_levels: i-reset ang lebel ng stock sa default + changes_to: mga pagbabago sa + one_override: isang override + overrides: mga override + remain_unsaved: nananatiling hindi naka-save. + no_changes_to_save: walang pagbabago na ise-save + no_authorisation: "hindi ko makuha ang awtorisasyon para i-save ang mga pagbabago kaya mananatili ang mga ito na hindi naka-save." + some_trouble: "nagkaroon ako ng problema sa pagse-save: %{errors}" + changing_on_hand_stock: pagbabago sa lebel ng hand stock + stock_reset: ni-reset sa default ang mga stock + tag_rules: + show_hide_variants: 'ipakita o itago ang mga variant sa aking Shopfront' + show_hide_shipping: 'ipakita o itago ang mga paraan ng pagpapadala sa checkout' + show_hide_payment: 'ipakita o itago ang mga paraan ng pagbabayad sa checkout' + show_hide_order_cycles: 'ipakita o itago ang mga order cycle sa aking shopfront' + visible: NAKIKITA + not_visible: HINDI NAKIKITA + services: + unsaved_changes_message: may mga hindi pa nase-save na pagbabago, i-save na ngayon o balewalain? + save: I-SAVE + ignore: HUWAG PANSININ + add_to_order_cycle: "idagdag sa order cycle" + manage_products: "pamahalaan ang mga produkto" + edit_profile: "i-edit ang profile" + add_products_to_inventory: "magdagdag ng mga produkto sa imbentaryo" + resources: + could_not_delete_customer: 'hindi matanggal ang customer' + product_import: + confirmation: | + ise-set nito ang lebel ng stock sa zero para sa lahat ng mga produkto para dito + enterprise na hindi makikita sa inupload na file. + order_cycles: + create_failure: "hindi nagtagumpay sa paggawa ng order cycle" + update_success: 'ang iyong order cycle ay na-update na' + update_failure: "hindi nagtagumpay sa pag-update ng order cycle" + no_distributors: walang distributor sa order cycle na ito. ang order cycle ay hindi makikita ng mga customer hanggang hindi kayo naglalagay ng distributor. Nais mo bang magpatuloy i-save ang order cycle? + enterprises: + producer: "Producer" + non_producer: "hindi producer" + customers: + select_shop: 'pumili muna ng shop' + could_not_create: hindi makagawa + subscriptions: + closes: nagsasara + closed: sarado + close_date_not_set: hindi pa nai-set ang close date + spree: + users: + order: "order" + registration: + welcome_to_ofn: "Welcome sa Open Food Network!" + signup_or_login: "magsimula sa pamamagitan ng pag-sign-up (o pag-log-in)" + have_an_account: "Mayroon ka na bang account?" + action_login: "Maglog-in na ngayon." + inflections: + each: + one: "bawat" + other: "bawat" + bunch: + one: "kumpol" + other: "mga kumpol" + pack: + one: "balot" + other: "mga balot" + box: + one: "mga bote" + other: "mga karton" + bottle: + one: "mga bote" + other: "mga bote" + jar: + one: "mga garapon" + other: "mga garapon" + head: + one: "ulo" + other: "mga ulo" + bag: + one: "supot" + other: "mga supot" + loaf: + one: "tinapay" + other: "mga tinapay" + single: + one: "isahan" + other: "mga isahan" + tub: + one: "batya" + other: "mga batya" + punnet: + one: "punnet" + other: "mga punnet" + packet: + one: "pakete" + other: "mga pakete" + item: + one: "item" + other: "mga item" + dozen: + one: "dosena" + other: "mga dosena" + unit: + one: "yunit" + other: "mga yunit" + serve: + one: "serve" + other: "mga serve" + tray: + one: "tray" + other: "mga tray" + piece: + one: "piraso" + other: "mga piraso" + pot: + one: "paso" + other: "mga paso" + bundle: + one: "bigkis" + other: "mga bigkis" + flask: + one: "prasko" + other: "mga prasko" + basket: + one: "basket" + other: "mga basket" + sack: + one: "sako" + other: "mga sako" + producers: + signup: + start_free_profile: "Magsimula sa libreng profile at palawakin kapag handa ka na!" + order_management: + reports: + enterprise_fee_summary: + date_end_before_start_error: "ay dapat pagkatapos magsimula" + parameter_not_allowed_error: "ikaw ay hindi awtorisadong gumamit ng isa o higit pa na mga filter para sa ulat na ito." + fee_calculated_on_transfer_through_all: "lahat" + fee_calculated_on_transfer_through_entire_orders: "ang buong order sa pamamagitan ng%{distributor}" + tax_category_various: "iba iba" + fee_type: + payment_method: "transaksyon ng bayad" + shipping_method: "kargamento" + fee_placements: + supplier: "papasok" + distributor: "papalabas" + coordinator: "coordinator" + tax_category_name: + shipping_instance_rate: "rate ng platform" + formats: + csv: + header: + fee_type: "uri ng kabayaran" + enterprise_name: "may-ari ng enterprise" + fee_name: "pangalan ng bayarin" + customer_name: "customer" + fee_placement: "paglilipat ng bayad" + fee_calculated_on_transfer_through_name: "Fee Calc sa Transfer Through" + tax_category_name: "kategorya ng tax" + total_amount: "$$ KABUUAN" + html: + header: + fee_type: "uri ng kabayaran" + enterprise_name: "may-ari ng enterprise" + fee_name: "pangalan ng bayarin" + customer_name: "customer" + fee_placement: "paglilipat ng bayad" + fee_calculated_on_transfer_through_name: "Fee Calc sa Transfer Through" + tax_category_name: "kategorya ng tax" + total_amount: "$$ KABUUAN" + invalid_filter_parameters: "ang mga filter na pinili para sa ulat na ito ay hindi valid." + order: "order" + distribution: "pamamahagi" + order_details: "detalye ng order" + customer_details: "detalye ng customer" + adjustments: "mga pagsasa-ayos" + payments: "mga bayad" + payment: "kabayaran" + payment_method: "paraan ng pagbayad" + shipment: "kargamento" + shipment_inc_vat: "kargamento kasama ang VAT" + shipping_tax_rate: "rate ng tax para sa pagpapadala" + category: "kategorya" + delivery: "pagdeliver" + temperature_controlled: "kontrolado ang temperatura" + new_product: "bagong produkto" + administration: "administrasyon" + logged_in_as: "maglog-in bilang" + account: "Account" + logout: "mag-log-out" + date_range: "saklaw na petsa" + status: "status" + new: "Bago" + start: "simula" + end: "katapusan" + stop: "Hinto" + first: "Una" + previous: "nauna" + last: "huli" + spree: + your_order_is_empty_add_product: "ang iyong order ay walang laman, humanap at magdagdag ng produkto sa itaas." + add_product: "magdagdag ng produkto" + name_or_sku: "Pangalan o SKU (ipasok ang 4 na letra sa pangalan ng produkto)" + resend: ipadala muli + back_to_orders_list: bumalik sa listahan ng mga order + return_authorizations: mga awtorisasyon sa pagbabalik + cannot_create_returns: hindi makagawa ng pagbalik sa kadahilanang ang order na ito ay walang shipped na yunit. + select_stock: "Pumili ng stock" + location: "Lokasyon" + count_on_hand: "bilangin ang on hand" + quantity: "dami" + on_demand: "on demand" + on_hand: "on hand" + package_from: "package mula sa" + item_description: "Paglalarawan ng item" + price: "presyo" + total: "kabuuan" + edit: "i-edit" + split: "paghiwalayin" + delete: "tanggalin" + cannot_set_shipping_method_without_address: "hindi ma-set ang paraan ng pagdadala hanggang hindi binibigay ang detalye ng customer." + no_tracking_present: "walang detalye ng tracking na ibinigay." + order_total: "kabuuan ng order" + customer_details: "detalye ng customer" + customer_search: "paghanap ng customer" + choose_a_customer: "pumili ng customer" + account: "Account" + billing_address: "Billing Address" + shipping_address: "Address kung saan ipapadala" + first_name: "Pangalan" + last_name: "apelyido" + street_address: "address ng kalye" + street_address_2: "address ng kalye (pinagpatuloy)" + city: "Lungsod" + zip: "Zip" + country: "Bansa" + state: "status" + phone: "telepono" + update: "i-update" + use_billing_address: "gamitin ang address para sa paniningil" + adjustments: "mga pagsasa-ayos" + continue: "Magpatuloy" + fill_in_customer_info: "sagutan ang impormasyon tungkol sa customer" + new_payment: "Bagong Pagbabayad" + capture: "kunan" + void: "walang bisa" + configurations: "mga pagsasaayos" + general_settings: "Pangkalahatang Setting" + site_name: "Pangalan ng site" + site_url: "URL ng site" + default_seo_title: "default Seo Title" + default_meta_description: "Default na paglalarawan ng Meta" + default_meta_keywords: "Default Meta Keywords" + security_settings: "mga setting para sa seguridad" + allow_ssl_in_development_and_test: "payagan na gamitin ang SSL kapag nasa moda ng pagpapaunlad at pagsubok.." + allow_ssl_in_production: "payagan na gamitin ang SSL sa moda ng produksiyon" + allow_ssl_in_staging: "payagan ang SSL sa moda ng staging" + currency_decimal_mark: "marka para sa currency decimal" + currency_settings: "mga setting para sa currency" + currency_symbol_position: ilagay ang "simbolo ng salapi bago o pagtapos ng halaga ng piso?" + currency_thousands_separator: "tagapaghiwalay ng Currency thousands" + hide_cents: "itago ang sentimo" + display_currency: "ipakita ang currency" + choose_currency: "pumili ng currency" + mail_method_settings: "mga setting para sa Mail Method" + general: "pangkalahatan" + enable_mail_delivery: "paganahin ang pagdedeliver ng sulat" + send_mails_as: "ipadala ang sulat bilang" + smtp_send_all_emails_as_from_following_address: "ipadala lahat ng mga sulat bilang galing sa mga sumusunod na address." + send_copy_of_all_mails_to: "magpadala ng kopya ng lahat ng sulat sa" + smtp_send_copy_to_this_addresses: "nagpapadala ng kopya ng lahat ng lumalabas na mga sulat sa address na ito, para sa maraming address, paghiwalayin gamit ang kuwit." + intercept_email_address: "harangin ang email address" + intercept_email_instructions: "pawalang halaga ang tatanggap ng email at palitan ng address na ito" + smtp: "SMTP" + smtp_domain: "SMTP Domain" + smtp_mail_host: "SMTP Mail Host" + smtp_port: "SMTP Port" + secure_connection_type: "Secure Connection Type" + smtp_authentication_type: "SMTP Authentication Type" + smtp_username: "SMTP username" + smtp_password: "SMTP password" + image_settings: "mga setting ng larawan" + image_settings_warning: "kinakailangang gumawa muli ng mga thumbnail kung ia-update ang mga estilo ng paperclip. gumamit ng rake paperclip:refresh:thumbnails CLASS=Spree::Image para gawin ito." + attachment_default_style: estilo ng mga attachment + attachment_default_url: "Default URL ng mga attachment" + attachment_path: "landas ng mga attachment" + attachment_styles: "estilo ng Paperclips" + attachment_url: "URL ng mga attachment" + add_new_style: "magdagdag ng bagong estilo" + image_settings_updated: "matagumpay na na-update ang settings ng larawan" + tax_categories: "kategorya ng tax" + listing_tax_categories: "kategorya ng nakalistang tax" + back_to_tax_categories_list: "bumalik sa listahan ng kategorya ng tax" + tax rate: "rate ng mga tax" + new_tax_rate: "bagong rate ng tax" + tax_category: "kategorya ng tax" + rate: "rate" + tax_rate_amount_explanation: "ang mga rate ng tax ay mga halagang may decimal na makakatulong sa pagkukuwenta, (hal. kung ang rate ng tax ay 5% ang ilalagay ay 0.05)" + included_in_price: "nakasama sa presyo" + show_rate_in_label: "ipakita ang rate sa tatak" + back_to_tax_rates_list: "bumalik sa listahan ng rate ng tax" + tax_settings: "Settings ng tax" + zones: "mga sona" + new_zone: "bagong sona" + default_tax: "default na tax" + default_tax_zone: "default na sona ng tax" + country_based: "Country Based" + state_based: "Nakabase sa probinsiya" + countries: "Mga Bansa" + listing_countries: "Listahan ng mga Bansa" + iso_name: "pangalan ng ISO" + states_required: "Kailangang may mga probinsiya" + editing_country: "pag-edit ng bansa" + back_to_countries_list: "bumalik sa listahan ng mga bansa" + states: "Mga probinsiya" + abbreviation: "Pinaikli" + new_state: "Bagong Probinsiya" + payment_methods: "Mga Paraan ng Pagbabayad" + new_payment_method: "Bagong Paraan ng pagbabayad" + provider: "tagapagbigay ng serbisyo" + taxonomies: "taxonomies" + new_taxonomy: "bagong taxonomy" + back_to_taxonomies_list: "bumalik sa listahan ng mga taxonomy" + shipping_methods: "mga paraan ng pagpapadala" + shipping_categories: "mga kategorya ng pagpapadala" + new_shipping_category: "bagong kategorya ng pagpapadala" + back_to_shipping_categories: "bumalik sa kategorya ng pagpapadala" + analytics_trackers: "mga tracker ng analytic" + no_trackers_found: "walang natagpuang tracker" + new_tracker: "bagong tracker" + add_one: "Magdagdag ng isa" + google_analytics_id: "Analytics ID" + back_to_trackers_list: "bumalik sa listahan ng tracker" + name: "pangalan" + description: "paglalarawan" + type: "uri" + default: "default" + calculator: "calculator" + zone: "sona" + display: "Ipakita" + environment: "kapaligiran" + active: "aktibo" + nore: "Iba pa" + no_results: "Walang resulta" + create: "gumawa" + loading: "naglo-load" + flat_percent: "Patag na porsiyento" + per_kg: "kada Kg" + amount: "halaga" + currency: "Currency" + first_item: "halaga ng unang item" + additional_item: "halaga ng karagdagang item" + max_items: "sagad na mga item" + minimal_amount: "pinakamaliit na halaga" + normal_amount: "normal na halaga" + discount_amount: "halaga na may diskuwento" + no_images_found: "walang mahanap na larawan" + new_image: "bagong larawan" + filename: "pangalan ng file" + alt_text: "alternatibong teksto" + thumbnail: "thumbnail" + back_to_images_list: "balik sa listahan ng mga larawan" + email: email + account_updated: "na-update na ang Account" + email_updated: "ang account ay maa-update kapag ang bagong email ay nakumpirma na" + my_account: "ang aking account" + date: "petsa" + time: "oras" + inventory_error_flash_for_insufficient_quantity: "ang isang item sa inyong cart ay hindi na available." + inventory: imbentaryo + zipcode: Postcode + weight: timbang (per kg) + error_user_destroy_with_orders: "ang mga gumagamit na may kumpletong order ay hindi maaaring tanggalin" + cannot_create_payment_without_payment_methods: "hindi maaaring magbayad para sa isang order na walang nakasaad na paraan ng pagbabayad." + please_define_payment_methods: "isaad muna ang paraan ng pagbabayad" + options: "pagpipilian" + actions: + update: "i-update" + errors: + messages: + blank: "hindi maaaring iwanang blanko" + layouts: + admin: + header: + store: tindahan + admin: + tab: + dashboard: "Dashboard" + orders: "mga order" + bulk_order_management: "Pamamahala sa pangmaramihang order" + subscriptions: "mga subscription" + products: "mga produkto" + option_types: "mga uri ng pagpipilian" + properties: "mga katangian" + variant_overrides: "imbentaryo" + reports: "mga ulat" + configuration: "pagbabago" + users: "mga gumagamit" + roles: "mga tungkulin" + order_cycles: "order cycles" + enterprises: "enterprises" + enterprise_relationships: "mga pahintulot" + customers: "mga customer" + groups: "mga grupo" + product_properties: + index: + inherits_properties_checkbox_hint: "kopyahin ang mga katangian mula sa%{supplier}? (maliban kung napatungan ang nasa itaas)" + add_product_properties: "magdagdag ng katangian ng produkto" + select_from_prototype: "pumili mula sa prototype" + properties: + index: + properties: "mga katangian" + new_property: "bagong katangian" + name: "pangalan" + presentation: "presentasyon" + new: + new_property: "bagong katangian" + edit: + editing_property: "ayusin ang katangian" + back_to_properties_list: "bumalik sa listahan ng katangian" + form: + name: "pangalan" + presentation: "presentasyon" + return_authorizations: + index: + new_return_authorization: "bagong awtorisasyon sa pagbabalik" + return_authorizations: "mga awtorisasyon sa pagbabalik" + back_to_orders_list: "bumalik sa listahan ng mga order" + rma_number: "numbero ng RMA" + status: "status" + amount: "halaga" + cannot_create_returns: "hindi makagawa ng pagbalik sa kadahilanang ang order na ito ay walang shipped na yunit." + continue: "Magpatuloy" + new: + new_return_authorization: "bagong awtorisasyon sa pagbabalik" + back_to_return_authorizations_list: "bumalik sa listahan ng awtorisasyon sa pagbabalik" + continue: "Magpatuloy" + edit: + receive: "tumanggap" + are_you_sure: "Sigurado ka ba?" + return_authorization: "awtorisasyon sa pagbabalik" + form: + product: "produkto" + quantity_shipped: "Dami ng naipadala" + quantity_returned: "dami ng ibinalik" + return_quantity: "binalik na dami" + amount: "halaga" + rma_value: "RMA Value" + reason: "Dahilan" + stock_location: "Lokasyon ng stock" + states: + authorized: "pinayagan" + received: "natanggap" + canceled: "na-cancel" + orders: + index: + listing_orders: "listahan ng mga order" + new_order: "bagong order" + capture: "kunan" + ship: "ship" + edit: "i-edit" + order_not_updated: "hindi ma-update ang order" + note: "tala" + first: "Una" + last: "huli" + previous: "nauna" + next: "sunod" + loading: "naglo-load" + no_orders_found: "walang mahanap na mga order" + results_found: "%{number}Natagpuang resulta." + viewing: "makikita ang%{start} hanggang%{end}." + print_invoices: "i-print ang mga invoice" + sortable_header: + payment_state: "status ng pagbabayad" + shipment_state: "status ng kargamento" + completed_at: "Natapos sa" + number: "bilang" + state: "status" + email: "Email ng Kustomer" + invoice: + issued_on: "inilabas noong" + tax_invoice: "TAX INVOICE" + code: "Code" + from: "mula" + to: "singilin sa" + shipping: "pagpapadala" + form: + distribution_fields: + title: "pamamahagi" + distributor: "Distributor:" + order_cycle: "Order Cycle:" + line_item_adjustments: "mga pagsasaayos sa linya ng item" + order_adjustments: "mga pagsasaayos sa order" + order_total: "kabuuan ng order" + overview: + enterprises_header: + ofn_with_tip: ang mga enterprise ay mga producer at/o mga Hub na siyang pangunahing yunit ng organisasyon sa loob ng Open Food Network. + products: + active_products: + zero: "wala kang aktibong mga produkto" + one: "Mayroon kang isang aktibong produkto" + other: "mayroon kang%{count}aktibong produkto." + order_cycles: + order_cycles: "order cycles" + order_cycles_tip: "ang mga order cycle ang tumutukoy kung kailan at saan may mga produkto para sa mga customer." + you_have_active: + zero: "wala kang mga aktibong order cycle" + one: "mayroon kang isang aktibong order cycle" + other: "mayroon kang%{count}aktibong order cycle." + manage_order_cycles: "PAMAHALAAN ANG MGA ORDER CYCLE" + shipping_methods: + index: + shipping_methods: "mga paraan ng pagpapadala" + new_shipping_method: "bagong paraan ng pagpapadala" + name: "pangalan" + products_distributor: "Distributor" + zone: "sona" + calculator: "calculator" + display: "Ipakita" + both: "pareho" + front_end: "harapan" + back_end: "Likuran" + no_shipping_methods_found: "walang mahanap na mga paraan ng pagpapadala" + new: + new_shipping_method: "bagong paraan ng pagpapadala" + back_to_shipping_methods_list: "bumalik sa listahan ng mga paraan ng pagpapadala" + edit: + editing_shipping_method: "iayos ang paraan ng pagpapadala" + new: "Bago" + back_to_shipping_methods_list: "bumalik sa listahan ng mga paraan ng pagpapadala" + form: + categories: "mga kategorya" + zones: "mga sona" + both: "pareho" + front_end: "harapan" + back_end: "Likuran" + payment_methods: + new: + new_payment_method: "Bagong Paraan ng pagbabayad" + back_to_payment_methods_list: "bumalik sa listahan ng mga paraan ng pagbabayad" + edit: + editing_payment_method: "iayos ang paraan ng pagbabayad" + back_to_payment_methods_list: "bumalik sa listahan ng mga paraan ng pagbabayad" + stripe_connect: + enterprise_select_placeholder: pumili + loading_account_information_msg: nilo-load ang impormasyon ng account mula sa Stripe, maghintay lamang... + stripe_disabled_msg: ang pagbabayad gamit ang Stripe ay hindi pinagana ng system administrator. + request_failed_msg: Paumahin, may nangyaring mali habang sinusubukang patunayan ang mga detalye ng account sa Stripe + account_missing_msg: walang Stripe account para sa enterprise na ito + connect_one: Connect One + access_revoked_msg: ang access sa Stripe account na ito ay pinawalang bisa, ikonekta muli ang account. + status: status + connected: konektado + account_id: Account ID + business_name: pangalan ng negosyo + charges_enabled: pinagana ang paniningil + payments: + source_forms: + stripe: + error_saving_payment: error sa pag-save ng bayad + submitting_payment: sinusumite ang bayad... + products: + image_upload_error: "ang larawan ng produkto ay hindi makilala. mag-upload ng larawan sa format na PNG o JPG." + new: + title: "bagong produkto" + new_product: "bagong produkto" + supplier: "Supplier" + product_name: "pangalan ng produkto" + units: "laki kada yunit" + value: "halaga" + unit_name: "pangalan ng yunit" + price: "presyo" + on_hand: "on hand" + on_demand: "on demand" + product_description: "paglalarawan ng produkto" + image: "larawan" + or: "o" + unit_name_placeholder: 'hal. mga kumpol' + index: + header: + title: maramihang pag-edit ng mga produkto + indicators: + title: nilo-load ang mga produkto + no_products: "wala pang produkto. nais mo bang magdagdag?" + no_results: "Walang tugmang resulta" + products_head: + name: pangalan + unit: yunit + display_as: Ipakita Bilang + category: kategorya + tax_category: kategorya ng tax + inherits_properties?: minana ang mga katangian? + available_on: Magagamit Nakabukas + av_on: "Av On" + import_date: "petsa ng pag-import" + products_variant: + variant_has_n_overrides: "ang uri ay may%{n}(mga)pagpapalit" + new_variant: "bagong uri" + product_name: pangalan ng produkto + primary_taxon_form: + product_category: kategorya ng produkto + group_buy_form: + group_buy: "grupong pamimili?" + bulk_unit_size: laki ng bultuhang yunit + display_as: + display_as: Ipakita Bilang + reports: + table: + select_and_search: "pumili ng mga filter at pindutin ang%{option} para ma-access ang inyong data." + bulk_coop: + bulk_coop_supplier_report: 'bultuhang Co-Op - kabuuan galing sa Supplier' + bulk_coop_allocation: 'bultuhang Co-Op - Alokasyon' + bulk_coop_packing_sheets: 'bultuhang Co-Op - piraso ng pagbabalot' + bulk_coop_customer_payments: 'bultuhang Co-Op - mga bayad ng customer' + enterprise_fee_summaries: + filters: + date_range: "saklaw na petsa" + report_format_csv: "i-download bilang CSV" + generate_report: "Bumuo ng ulat" + report: + none: "wala" + select_and_search: "pumili ng mga filter at pindutin ang GUMAWA NG REPORT para ma-access ang inyong data." + users: + index: + listing_users: "Nililista ang mga User" + new_user: "Bagong User" + user: "User" + enterprise_limit: "Limitasyon ng enterprise" + search: "hanapin" + email: "email" + edit: + editing_user: "pag-edit ng User" + back_to_users_list: "Bumalik sa listahan ng mga User" + general_settings: "Pangkalahatang Setting" + form: + email: "email" + roles: "mga tungkulin" + enterprise_limit: "Limitasyon ng enterprise" + confirm_password: "Kumpirmahin ang password" + password: "Password" + email_confirmation: + confirmation_pending: "ang pagkumpirma ng email ay hindi pa nagagawa. ipinadala namin ang email ng kumpirmasyon sa %{address}." + variants: + index: + sku: "SKU" + price: "presyo" + options: "pagpipilian" + no_results: "Walang resulta" + to_add_variants_you_must_first_define: "para makapagdagdag ng mga variant, tukuyin muna ang" + option_types: "mga uri ng pagpipilian" + option_values: "Mga halaga ng pagpipilian" + and: "at" + new_variant: "bagong variant" + show_active: "Ipakita Ang Mga Aktibo" + show_deleted: "Ipakita Ang Mga Tinanggal" + new: + new_variant: "bagong variant" + form: + cost_price: "halaga ng gastos" + sku: "SKU" + price: "presyo" + display_as: "Ipakita Bilang" + display_name: "Pangalan na nakikita" + autocomplete: + producer_name: "Producer" + unit: "yunit" + general_settings: + edit: + legal_settings: "Legal Settings" + cookies_consent_banner_toggle: "ipakita ang banner ng pagpayag sa cookies" + privacy_policy_url: "Patakaran sa privacy URL" + enterprises_require_tos: "ang mga enterprise ay dapat tanggapin ang Termino ng serbisyo." + cookies_policy_matomo_section: "ipakita ang seksyon ng Matomo sa pahina ng patakaran sa cookies" + cookies_policy_ga_section: "ipakita ang seksyon ng Google Analytics sa pahina ng patakaran sa cookies" + footer_tos_url: "URL ng Termino ng Serbisyo" + checkout: + payment: + stripe: + choose_one: pumili ng isa + enter_new_card: ipasok ang detalye para sa bagong card + used_saved_card: "gumamit ng naka-save na card:" + or_enter_new_card: "o ipasok ang detalye para sa bagong card:" + remember_this_card: Naaalala ba ang card na ito? + stripe_sca: + choose_one: pumili ng isa + enter_new_card: ipasok ang detalye para sa bagong card + used_saved_card: "gumamit ng naka-save na card:" + or_enter_new_card: "o ipasok ang detalye para sa bagong card:" + remember_this_card: Naaalala ba ang card na ito? + date_picker: + format: '%Y-%m-%d' + js_format: 'yy-mm-dd' + orders: + error_flash_for_unavailable_items: "ang isang item sa inyong cart ay hindi na available." + edit: + login_to_view_order: "Maglog-in para makita ang inyong order." + bought: + item: "na-order na sa order cycle na ito" + line_item: + insufficient_stock: "Hindi sapat ang stock, mayroon na lamang%{on_hand} na natitira" + out_of_stock: "Walang stock" + unavailable_item: "kasalulkuyang hindi available" + shipment_states: + backorder: backorder + partial: bahagi + pending: nakabinbin + ready: handa na + shipped: nai-ship na + payment_states: + balance_due: balanse + completed: nakumpleto na + checkout: checkout + credit_owed: Utang na Credit + failed: hindi nagtagumpay + paid: bayad na + pending: nakabinbin + processing: pinoproseso + void: walang bisa + invalid: invalid + order_mailer: + cancel_email: + customer_greeting: "hi %{name}!" + instructions: "ang iyong order ay NA-CANCEL. Panatilihin ang impormasyon na ito ng kanselasyon para sa inyong talaan." + order_summary_canceled: "Buod ng order [NA-CANCEL]" + subject: "Pag-cancel ng order" + confirm_email: + subject: "Kumpirmasyon ng order" + invoice_email: + hi: "Hi %{name}" + invoice_attached_text: 'tignan ang nakalakip na invoice para sa pinakabagong order mula sa ' + order_state: + address: tirahan + adjustments: mga pagsasaayos + awaiting_return: naghihintay ng pagbalik + canceled: na-cancel + cart: cart + complete: kumpleto + confirm: kumpirmahin + delivery: pagdeliver + paused: nakahinto + payment: pagbabayad + pending: nakabinbin + resumed: nagpatuloy + returned: binalik + skrill: Skrill + subscription_state: + active: aktibo + pending: nakabinbin + ended: natapos na + paused: nakahinto + canceled: na-cancel + user_mailer: + reset_password_instructions: + request_sent_text: | + may ginawang request para i-reset ang inyong password. + kung hindi ikaw ang gumawa nito, huwag pansinin ang email na ito. + link_text: > + kung ikaw ang gumawa ng request na ito, pindutin ang link sa ilalim: + issue_text: | + kung ang URL sa itaas ay hindi gumagana, subukang kopyahin at i-paste ito sa inyong browser. + kung patuloy na magkakaroon ng mga problema, huwag mag-atubiling makipag-ugnayan sa amin. + confirmation_instructions: + subject: kumpirmahin ang inyong OFN account + users: + form: + account_settings: Setting ng Account + show: + tabs: + orders: mga order + cards: Credit cards + transactions: Mga transaksyon + settings: Setting ng Account + unconfirmed_email: "Nakabinbin na kumpirmasyon ng email para sa:%{unconfirmed_email}. ang iyong email address ay maa-update kapag ang bagong email ay nakumpirma." + orders: + open_orders: mga bukas na order + past_orders: mga nakaraang order + transactions: + transaction_history: kasaysayan ng mga transaksyon + open_orders: + order: order + shop: Shop + changes_allowed_until: ang mga pagbabago ay papayagan hanggang + items: mga item + total: kabuuan + edit: i-edit + cancel: i-cancel + closed: sarado + until: hanggang + past_orders: + order: order + shop: Shop + completed_at: Natapos sa + items: mga item + total: kabuuan + paid?: bayad na? + view: tignan + saved_cards: + default?: Default? + delete?: tanggalin? + cards: + authorised_shops: awtorisadong mga shop + authorised_shops_popover: ito ang listahan ng mga shop na may permisong singilin ang iyong default na credit card para sa kahit anong subscription (hal.nauulit na mga order) na mayroon ka. Ang mga detalye ng iyong card ay pananatilihing ligtas at hindi ipapaalam sa mga may-ari ng shop. Ikaw ay aabisuhan kapag ikaw ay nasingil na. + saved_cards_popover: ito ang listahan ng mga card na pinili mong i-save para magamit sa hinaharap. ang iyong 'default' ay awtomatikong mapipili kapag ikaw ay nagcheckout ng order, at maaari ring singilin ng mga shop na binigyan mo ng permiso (tignan sa kanan). + authorised_shops: + shop_name: "pangalan ng shop" + allow_charges?: "pumayag na masingil?" + localized_number: + invalid_format: ay may hindi valid na format. mag.pasok ng numero + api: + invalid_api_key: "hindi valid na API key (%{key}) na tinutukoy." + unauthorized: "ikaw ay hindi awtorisado na gawin ang kilos na iyon." + invalid_resource: "hindi valid na pinagkuhanan. ayusin ang mga error at subukan muli." + resource_not_found: "ang pinagkukuhan ay hindi mahanap." + access: "API Access" + key: "Key" + clear_key: "burahin ang key" + regenerate_key: "gumawa muli ng key" + no_key: "walang key" + generate_key: "gumawa ng API key" + key_generated: "nagawa na ang key" + key_cleared: "binura ang key" + shipment: + cannot_ready: "hindi maihanda ang kargamento" + invalid_taxonomy_id: "hindi valid na taxonomy id." diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 7566b07d58..528c35b883 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -59,7 +59,7 @@ fr: messages: inclusion: "n'est pas inclus dans la liste" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Veuillez ajouter au moins un produit" @@ -596,7 +596,7 @@ fr: max_fulfilled_units: "Nombre max d'unités commandées" order_error: "Des erreurs doivent être résolues avant de pouvoir mettre à jour les commandes.\nLes champs entourés en rouge contiennent des erreurs." variants_without_unit_value: "ATTENTION: certaines variantes n'ont pas de nombre d'unités" - select_variant: "Choisir une variante" + select_variant: "Rechercher un produit et sélectionner une variante" enterprise: select_outgoing_oc_products_from: Sélectionner les produits sortants pour le cycle de vente parmi enterprises: @@ -1543,7 +1543,7 @@ fr: products_loading: "Produits en cours de chargement..." products_updating_cart: "Actualisation du panier..." products_cart_empty: "Panier vide" - products_edit_cart: "Valider votre panier" + products_edit_cart: "Poursuivre" products_from: de products_change: "Aucun changement à sauvegarder." products_update_error: "Échec de l'enregistrement dû à:" @@ -1670,7 +1670,7 @@ fr: orders_form_admin: Admin & traitements orders_form_total: Total orders_oc_expired_headline: Les commandes ne sont plus possibles pour ce cycle de vente. - orders_oc_expired_text: "Désolé, les commandes pour ce cycle de vente ont été clôturées il y a %{time}! Veuillez contacter directement le hub pour voir s'il accepte les commandes tardives." + orders_oc_expired_text: "Désolé, les commandes pour ce cycle de vente ont été clôturées il y a %{time}!" orders_oc_expired_text_others_html: "Désolé, les commandes pour ce cycle de vente ont été clôturées il y a %{time}! Veuillez contacter directement le hub pour voir s'il accepte les commandes tardives %{link}." orders_oc_expired_text_link: "ou voir si d'autres cycles de vente sont ouverts pour ce hub" orders_oc_expired_email: "Email:" @@ -1921,6 +1921,7 @@ fr: admin_enterprise_relationships_permits: "autorise" admin_enterprise_relationships_seach_placeholder: "Rechercher" admin_enterprise_relationships_button_create: "Créer" + admin_enterprise_relationships_to: "à" admin_enterprise_groups: "Groupes d'entreprises" admin_enterprise_groups_name: "Produit/Variante" admin_enterprise_groups_owner: "Gestionnaire principal" @@ -2790,6 +2791,8 @@ fr: location: "Localisation" count_on_hand: "Quantité en stock" quantity: "Quantité" + on_demand: "A volonté" + on_hand: "En stock" package_from: "conditionnement par" item_description: "Description de la pièce" price: "Prix" diff --git a/config/locales/fr_BE.yml b/config/locales/fr_BE.yml index 8ca1872694..b05a488edf 100644 --- a/config/locales/fr_BE.yml +++ b/config/locales/fr_BE.yml @@ -31,6 +31,10 @@ fr_BE: taken: "Un compte existe déjà pour cette adresse électronique. Connectez-vous ou demandez un nouveau mot de passe." spree/order: no_card: Aucune carte de paiement autorisée disponible + spree/credit_card: + attributes: + base: + card_expired: "a expiré" order_cycle: attributes: orders_close_at: @@ -55,7 +59,7 @@ fr_BE: messages: inclusion: "N'est pas inclus dans la liste" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Veuillez ajouter au moins un produit" @@ -248,6 +252,8 @@ fr_BE: notes: Commentaires error: Erreur processing_payment: "Paiement en cours..." + no_pending_payments: "Aucun paiement en attente" + invalid_payment_state: "État de paiement invalide" filter_results: Filtrer les résultats quantity: Quantité pick_up: Retrait @@ -867,6 +873,7 @@ fr_BE: distributor: "Distributeur·trice" products: "Produits" tags: "Tags" + delivery_details: "Détails de la livraison" fees: "Commission" previous: "Précédent" save: "Sauvergarder" @@ -1129,11 +1136,11 @@ fr_BE: shared: menu: cart: - cart: "Cart" + cart: "Panier" signed_in: profile: "Profil" mobile_menu: - cart: "Carte" + cart: "Panier" joyride: checkout: "Passer la commande" already_ordered_products: "Déjà commandé dans ce cycle de vente" @@ -1291,6 +1298,7 @@ fr_BE: saving_credit_card: Enregistrement de la carte de crédit... card_has_been_removed: "Votre carte a été supprimée (numéro : %{number})" card_could_not_be_removed: Désolée, la carte n'a pas pu être supprimée :-( + invalid_credit_card: "Carte de crédit non valable" ie_warning_headline: "Votre navigateur n'est pas à jour :-(" ie_warning_text: "Pour une expérience optimale sur Open Food Network, nous vous recommandons fortement de mettre à jour votre navigateur:" ie_warning_chrome: Télécharger Chrome @@ -1492,6 +1500,7 @@ fr_BE: shopping_oc_closed_description: "Veuillez attendre l'ouverture du prochain cycle de vente (ou contactez directement le comptoir pour voir si nous pouvons accepter une commande tardive)." shopping_oc_last_closed: "Le dernier cycle de vente s'est terminé il y a %{distance_of_time}" shopping_oc_next_open: "Le prochain cycle de vente ouvrira dans %{distance_of_time}" + shopping_oc_select: "Sélectionnez..." shopping_tabs_home: "Accueil" shopping_tabs_shop: "Comptoir" shopping_tabs_about: "A propos" @@ -1865,6 +1874,7 @@ fr_BE: headline: "C'est terminé!" thanks: "Merci d'avoir complété le profil de %{enterprise}" login: "Vous pouvez modifier ou mettre à jour les détails de votre entreprise à tout moment en vous connectant sur Open Food Network, rubrique Admin." + action: "Aller au tableau de bord des entreprises" back: "Retour" continue: "Suivant" action_or: "OU" @@ -2283,6 +2293,7 @@ fr_BE: enterprise_register_success_notice: "Bravo ! L'entreprise %{enterprise} est maintenant inscrite sur Open Food Network :-)" enterprise_bulk_update_success_notice: "Entreprises mises à jour avec succès" enterprise_bulk_update_error: 'Echec dans la mise à jour' + enterprise_shop_show_error: "Le comptoir que vous recherchez n'existe pas ou est inactif sur OFN. Veuillez vérifier les autres comptoirs." order_cycles_create_notice: 'Votre cycle de vente a été créé.' order_cycles_update_notice: 'Votre cycle de vente a été mis à jour.' order_cycles_bulk_update_notice: 'Des cycles de vente ont été mis à jour.' @@ -2444,6 +2455,12 @@ fr_BE: severity: Rigueur description: Description resolve: Résoudre + exchange_products: + load_more_variants: "Charger plus de variantes" + load_all_variants: "Charger toutes les variantes" + select_all_variants: "Sélectionner toutes %{total_number_of_variants}les variantes" + variants_loaded: " %{num_of_variants_loaded}de %{total_number_of_variants}variantes chargées" + loading_variants: "Chargement des variantes" tag_rules: shipping_method_tagged_top: "Méthodes d'expédition étiquetées" shipping_method_tagged_bottom: "sont:" @@ -2685,6 +2702,8 @@ fr_BE: location: "Site" count_on_hand: "Compté à la main" quantity: "Nb commandé" + on_demand: "A volonté" + on_hand: "En stock" package_from: "colis provenant de " item_description: "Description de l'article " price: "Prix" @@ -2956,6 +2975,8 @@ fr_BE: tax_invoice: "FACTURE" code: "Code" from: "De" + to: "Facture à" + shipping: "Expédition" form: distribution_fields: title: "Distribution" diff --git a/config/locales/fr_CA.yml b/config/locales/fr_CA.yml index cf300ce168..f354f638ce 100644 --- a/config/locales/fr_CA.yml +++ b/config/locales/fr_CA.yml @@ -55,7 +55,7 @@ fr_CA: messages: inclusion: "n'est pas inclus dans la liste" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "Veuillez ajouter au moins un produit" @@ -2765,6 +2765,8 @@ fr_CA: location: "Localisation" count_on_hand: "Quantité en stock" quantity: "Quantité" + on_demand: "A volonté" + on_hand: "En stock" package_from: "conditionnement par" item_description: "Description de la pièce" price: "Prix" diff --git a/config/locales/it.yml b/config/locales/it.yml index 67f67b0a28..1e1552af14 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -55,7 +55,7 @@ it: messages: inclusion: "non incluso nella lista" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Aggiungi almeno un prodotto" @@ -2759,6 +2759,8 @@ it: location: "Posizione" count_on_hand: "Conta a mente" quantity: "Quantità" + on_demand: "A richiesta" + on_hand: "Disponibile" package_from: "pacchetto da" item_description: "descrizione dell'articolo" price: "Prezzo" @@ -3030,6 +3032,7 @@ it: tax_invoice: "FATTURA DELLE TASSE" code: "Codice" from: "Da" + shipping: "Spedizione" form: distribution_fields: title: "Distribuzione" diff --git a/config/locales/nb.yml b/config/locales/nb.yml index 471207ccca..9371908c59 100644 --- a/config/locales/nb.yml +++ b/config/locales/nb.yml @@ -55,7 +55,7 @@ nb: messages: inclusion: "er ikke inkludert i listen" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Vennligst legg til minst ett produkt" @@ -2754,6 +2754,8 @@ nb: location: "Plassering" count_on_hand: "Antall På Lager" quantity: "Mengde" + on_demand: "Ved forespørsel" + on_hand: "Tilgjengelig" package_from: "pakke fra" item_description: "Beskrivelse Element" price: "Pris" diff --git a/config/locales/nl_BE.yml b/config/locales/nl_BE.yml index d6d40e6fdc..ee09e5d0f7 100644 --- a/config/locales/nl_BE.yml +++ b/config/locales/nl_BE.yml @@ -53,7 +53,7 @@ nl_BE: payment_method_ids: "Betaalmethodes" errors: models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Gelieve minstens één product toe te voegen" @@ -2641,6 +2641,8 @@ nl_BE: location: "Locatie" count_on_hand: "Count On Hand" quantity: "Kwantiteit" + on_demand: "Op Aanvraag" + on_hand: "Bij de Hand" package_from: "pakje van " item_description: "Artikelbeschrijving" price: "Prijs" diff --git a/config/locales/pt.yml b/config/locales/pt.yml index b5444331ec..c3a1b473fc 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -51,7 +51,7 @@ pt: payment_method_ids: "Métodos de pagamento" errors: models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^Por favor adicione pelo menos um produto" @@ -2597,6 +2597,8 @@ pt: location: "Localização" count_on_hand: "Disponível" quantity: "Quantidade" + on_demand: "Sob Encomenda" + on_hand: "Disponível" package_from: "Embalagem de" item_description: "Descrição do Item" price: "Preço" diff --git a/config/locales/pt_BR.yml b/config/locales/pt_BR.yml index d5dbc46d8d..9966e927c8 100644 --- a/config/locales/pt_BR.yml +++ b/config/locales/pt_BR.yml @@ -16,9 +16,11 @@ pt_BR: spree/product: primary_taxon: "Categoria de Produto" supplier: "Fornecedor" - shipping_category_id: "Tipos de Envio" + shipping_category_id: "Tipos de Frete" variant_unit: "Unidade variante" variant_unit_name: "Nome da unidade variante" + spree/credit_card: + base: "Cartão de Crédito" order_cycle: orders_close_at: Dia de fechamento errors: @@ -29,6 +31,10 @@ pt_BR: taken: "Já existe uma conta para este e-mail. Por favor, faça login ou redefina sua senha." spree/order: no_card: Não há cartões de crédito válidos disponíveis + spree/credit_card: + attributes: + base: + card_expired: "expirou" order_cycle: attributes: orders_close_at: @@ -53,7 +59,7 @@ pt_BR: messages: inclusion: "não está incluso na lista" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^ Por favor, adicione pelo menos um produto" @@ -204,7 +210,7 @@ pt_BR: remove: Remover or: ou collapse_all: Recolher todos - expand_all: Aumentar tudo + expand_all: Expandir tudo loading: Carregando... show_more: Mostrar mais show_all: Mostrar tudo @@ -583,13 +589,13 @@ pt_BR: actions_delete: "Deletar selecionado" loading: "Carregando pedidos" no_results: "Nenhum pedido encontrado. " - group_buy_unit_size: "Tamanho da Unidade para Grupo de Compras" + group_buy_unit_size: "Unidade de Medida para Grupo de Compras" total_qtt_ordered: "Quantidade total do pedido" max_qtt_ordered: "Quantidade máxima do pedido" current_fulfilled_units: "Unidades completadas no momento" max_fulfilled_units: "Máximo de unidades completadas " order_error: "Alguns erros devem ser corrigidos antes de atualizar os pedidos.\nOs campos com bordas vermelhas contém erros." - variants_without_unit_value: "AVISO: Algumas variantes não possuem unidade de valor" + variants_without_unit_value: "AVISO: Algumas variantes não possuem unidade de medida" select_variant: "Selecione uma variante" enterprise: select_outgoing_oc_products_from: 'Selecione a saída do ciclo de pedidos ' @@ -966,7 +972,7 @@ pt_BR: not_visible: "%{enterprise} não está visível e, portanto, não pode ser encontrado no mapa ou em pesquisas" reports: hidden: ESCONDIDO - unitsize: TAMANHO DA UNIDADE + unitsize: Unidade de Medida total: TOTAL total_items: TOTAL DE ITEMS supplier_totals: Total do fornecedor do ciclo de pedidos @@ -1199,7 +1205,7 @@ pt_BR: menu_4_title: "Grupos" menu_4_url: "/groups" menu_5_title: "Sobre" - menu_5_url: "https://about.openfoodnetwork.org.au/" + menu_5_url: "https://about.openfoodbrasil.com.br/" menu_6_title: "Conectar" menu_6_url: "https://openfoodnetwork.org/au/connect/" menu_7_title: "Aprender" @@ -1536,11 +1542,11 @@ pt_BR: products_cart_empty: "Carrinho vazio" products_edit_cart: "Edite seu carrinho" products_from: de - products_change: "Nenhuma modificação a ser salva." + products_change: "Nenhuma alteração a ser salva." products_update_error: "Falha ao salvar, com o seguinte erro:" products_update_error_msg: "Falha ao salvar." products_update_error_data: "Falha no salvamento devido a dados inválidos:" - products_changes_saved: "Modificações salvas." + products_changes_saved: "Alterações salvas." search_no_results_html: "Sinto muito, nenhum resultado encontrado para %{query}. Que tal tentar outra busca?" components_profiles_popover: "Perfis Simples não possuem uma loja virtual na Open Food Brasil, mas podem ter suas próprias lojas físicas ou online em outro endereço" components_profiles_show: "Mostrar perfis" @@ -1893,7 +1899,7 @@ pt_BR: transaction_date: "DataData" payment_state: "Status do Pagamento" shipping_state: "Status da entrega" - value: "Valor" + value: "Quantidade" balance_due: "saldo devedor" credit: "Crédito" Paid: "Pago" @@ -1940,7 +1946,7 @@ pt_BR: supplier: "Fornecedor" product_name: "Nome do Produto" product_description: "Descrição do Produto" - units: "O tamanho da unidade" + units: "Unidade de medida" coordinator: "Coordenador" distributor: "Distribuidor" enterprise_fees: "Taxas da iniciativa" @@ -2129,7 +2135,7 @@ pt_BR: report_header_quantity: Quantidade report_header_max_quantity: Quantidade máxima report_header_variant: Variante - report_header_variant_value: Valor variante + report_header_variant_value: Valor da variante report_header_variant_unit: Unidade variante report_header_total_available: Total disponível report_header_unallocated: Não atribuído @@ -2148,14 +2154,14 @@ pt_BR: report_header_sells: Vende report_header_visible: Visível report_header_price: Preço - report_header_unit_size: Tamanho da Unidade + report_header_unit_size: Unidade de Medida report_header_distributor: Distribuidor report_header_distributor_address: Endereço do distribuidor report_header_distributor_city: Cidade do distribuidor report_header_distributor_postcode: CEP do distribuidor report_header_delivery_address: Endereço para entrega report_header_delivery_postcode: CEP para entrega - report_header_bulk_unit_size: Tamanho de unidade para atacado + report_header_bulk_unit_size: Unidade de Medida para atacado report_header_weight: Peso report_header_sum_total: Soma total report_header_date_of_order: Data do pedido @@ -2301,7 +2307,7 @@ pt_BR: shipped: Enviado js: saving: 'Salvando...' - changes_saved: 'Mudanças salvas.' + changes_saved: 'Alterações salvas.' save_changes_first: Salve as alterações primeiro. all_changes_saved: Todas as alterações foram salvas unsaved_changes: Você possui alterações não salvas @@ -2567,7 +2573,7 @@ pt_BR: visible: VISÍVEL not_visible: NÃO VISÍVEL services: - unsaved_changes_message: Existem mudanças não salvas, salvar agora ou ignorar? + unsaved_changes_message: Existem alterações não salvas. Salvar agora ou ignorar? save: SALVAR ignore: IGNORAR add_to_order_cycle: "adicionar ao ciclo de pedidos" @@ -2758,6 +2764,8 @@ pt_BR: location: "Localização" count_on_hand: "Contagem na mão" quantity: "Quantidade" + on_demand: "Sob Encomenda" + on_hand: "Disponível" package_from: "pacote de" item_description: "Descrição do Item" price: "Preço" @@ -2870,7 +2878,7 @@ pt_BR: back_to_taxonomies_list: "Voltar à lista de taxonomias" shipping_methods: "Métodos de envio" shipping_categories: "Categorias de Remessa" - new_shipping_category: "Nova categoria de remessa" + new_shipping_category: "Nova categoria de frete" back_to_shipping_categories: "Voltar para categorias de remessa" analytics_trackers: "Rastreadores de análise" no_trackers_found: "Nenhum rastreador encontrado" @@ -3113,8 +3121,8 @@ pt_BR: new_product: "Novo produto" supplier: "Fornecedor" product_name: "Nome do Produto" - units: "Tamanho da Unidade" - value: "Valor" + units: "Unidade de Medida" + value: "Quantidade" unit_name: "Nome da Unidade" price: "Preço" on_hand: "Disponível" @@ -3195,7 +3203,7 @@ pt_BR: no_results: "Nenhum Resultado" to_add_variants_you_must_first_define: "Para adicionar variantes, primeiro você precisa definir" option_types: "Tipos de Opções" - option_values: "Valores de Opções" + option_values: "Valores das Opções" and: "e" new_variant: "Nova Variante" show_active: "Mostra Ativos" diff --git a/config/locales/simple_form.en.yml b/config/locales/simple_form.en.yml deleted file mode 100644 index 9810cea163..0000000000 --- a/config/locales/simple_form.en.yml +++ /dev/null @@ -1,25 +0,0 @@ -en: - simple_form: - "yes": 'Yes' - "no": 'No' - required: - text: 'required' - mark: '*' - # You can uncomment the line below if you need to overwrite the whole required html. - # When using html, text and mark won't be used. - # html: '*' - error_notification: - default_message: "Please review the problems below:" - # Labels and hints examples - # labels: - # defaults: - # password: 'Password' - # user: - # new: - # email: 'E-mail to sign in.' - # edit: - # email: 'E-mail.' - # hints: - # defaults: - # username: 'User name to sign in.' - # password: 'No special characters, please.' diff --git a/config/locales/sv.yml b/config/locales/sv.yml index ca90a48659..53985ac51f 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -1898,6 +1898,8 @@ sv: spree: resend: Återsänd quantity: "Antal" + on_demand: "På begäran" + on_hand: "På lager" price: "Pris" total: "Summa" edit: "Redigera" diff --git a/config/locales/tr.yml b/config/locales/tr.yml index b36a8da76b..5f3fd36365 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -9,14 +9,14 @@ tr: shipment_state: ' Teslimat Durumu' completed_at: Oluşturulma Tarihi number: Numara - state: Şehir + state: Durum email: Müşteri E-postası spree/payment: amount: Tutar spree/product: primary_taxon: "Ürün Kategorisi" supplier: "Tedarikçi" - shipping_category_id: "Nakliye Kategorisi" + shipping_category_id: "Teslimat Kategorisi" variant_unit: "Varyant Birimi" variant_unit_name: "Varyant Birim Adı" spree/credit_card: @@ -31,22 +31,26 @@ tr: taken: "Bu e-posta adına kayıtlı bir hesap var. Lütfen giriş yapın veya şifrenizi sıfırlayın." spree/order: no_card: Ödeme alınabilecek kayıtlı bir kredi kartı bulunmamaktadır. + spree/credit_card: + attributes: + base: + card_expired: "süresi doldu" order_cycle: attributes: orders_close_at: after_orders_open_at: Açılış tarihinden sonra olmalı variant_override: count_on_hand: - using_producer_stock_settings_but_count_on_hand_set: "Boş bırakılmalı çünkü üreticinin stokları kullanılıyor" + using_producer_stock_settings_but_count_on_hand_set: "Boş bırakılmalı çünkü üretici stok ayarları kullanılıyor" on_demand_but_count_on_hand_set: "talep üzerine is boş bırakılmalıdır" limited_stock_but_no_count_on_hand: "Sınırlı stok durumundan dolayı belirtilmeli" activemodel: attributes: order_management/reports/enterprise_fee_summary/parameters: start_at: "Başlangıç" - end_at: "Son" + end_at: "Bitiş" distributor_ids: "Pazarlar" - producer_ids: "Üreticiler" + producer_ids: "ÜRETİCİLER" order_cycle_ids: "Sipariş Dönemleri" enterprise_fee_ids: "Ücret İsimleri" shipping_method_ids: "Teslimat Yöntemleri" @@ -55,7 +59,7 @@ tr: messages: inclusion: "Listeye dahil değil" models: - subscription_validator: + order_management/subscriptions/validator: attributes: subscription_line_items: at_least_one_product: "^ Lütfen en az bir ürün ekleyin" @@ -67,12 +71,12 @@ tr: schedule: not_coordinated_by_shop: "%{shop} tarafından koordine edilmiyor" payment_method: - not_available_to_shop: "%{shop} tarafından kullanılamıyor" + not_available_to_shop: "%{shop} için müsait değil" invalid_type: "Nakit veya online ödeme yöntemi olmalıdır" - charges_not_allowed: "^ Bu müşteri tarafından kredi kartı ile ödeme yöntemi kabul edilmemektedir." + charges_not_allowed: "^ Bu müşteri tarafından kredi kartı ücretlendirme kabul edilmemektedir." no_default_card: "^ Bu müşteri için kayıtlı kart bulunmuyor" shipping_method: - not_available_to_shop: "%{shop} tarafından kullanılamıyor" + not_available_to_shop: "%{shop} için kullanıma uygun değil" devise: confirmations: send_instructions: "Birkaç dakika içinde, hesabınızı nasıl doğrulayacağınız ile ilgili talimatları içeren bir e-posta alacaksınız." @@ -118,7 +122,7 @@ tr: welcome: subject: "%{enterprise} şimdi %{sitename} 'de" email_welcome: "Hoşgeldiniz" - email_registered: "şimdi şunun bir parçası" + email_registered: "şimdi bir parçası" email_userguide_html: "Tezgah veya Pazar hesapları ayarları ile ilgili ayrıntılı desteğe sahip Kullanıcı Kılavuzu burada: %{link}" userguide: "Açık Gıda Ağı Kullanıcı Kılavuzu" email_admin_html: "%{link}'dan oturum açarak veya ana sayfanın sağ üst kısmındaki ayarlar simgesini tıkladıktan sonra Yönetim' butonu üzerinden hesabınızı yönetebilirsiniz." @@ -137,8 +141,8 @@ tr: shipment_summary: "Teslimat Özeti" subject: "Teslimat Bildirimi" thanks: "İş birliğiniz için teşekkür ederim." - track_information: "Kargo Takip Bilgileri: %{tracking}" - track_link: "Kargo Takip Bağlantısı: %{url}" + track_information: "Takip Bilgileri: %{tracking}" + track_link: "Takip Bağlantısı: %{url}" subscription_mailer: placement_summary_email: subject: Yakın zamanda oluşturulan üye siparişlerinin bir özeti @@ -149,7 +153,7 @@ tr: greeting: "Merhaba %{name}," intro: "Aşağıda, %{shop} için yeni tamamlanmış olan üye siparişlerinin bir özeti bulunmaktadır." summary_overview: - total: Otomatik işlem için toplam %{count} üye işaretlendi. + total: Otomatik işlem için toplam %{count} üyelik işaretlendi. success_zero: Bunlardan hiçbiri başarıyla işlenmedi. success_some: Bunlardan %{count} işlem başarıyla tamamlandı. success_all: Hepsi başarıyla işlendi. @@ -176,10 +180,10 @@ tr: explainer: Bu siparişlerin otomatik olarak işlenmesi bilinmeyen bir nedenden dolayı başarısız oldu. Bu gerçekleşmemesi gereken bir durum, bu hatayı alıyorsanız lütfen bizimle iletişime geçin. home: "AGA" title: Açık Gıda Ağı - welcome_to: '''na Hoşgeldiniz' - site_meta_description: "Açık Gıda Ağı, farklı ülkelerdeki temiz gıda üreticileri ve yazılımcılar tarafından yeni bir gıda sistemi oluşturmak üzere tasarlandı. Üretici ve türeticilerin bir araya gelerek aracısız bir gıda düzeni ile her açıdan daha sağlıklı bir toplum yaratmaları için çözümler sunar. Toplum yararına çalışır ve tamamen şeffaftır." + welcome_to: 'Hoşgeldiniz' + site_meta_description: "Açık Gıda Ağı, adil ve temiz bir gıda sistemi oluşturmak için tasarlanan bir sosyal girişim projesidir. Üretici ve türeticilerin bir araya gelerek aracısız bir gıda düzeni ile her açıdan daha sağlıklı bir toplum yaratmaları için çözümler sunar. Kar amacı gütmez, toplum yararına çalışır, iletişim, dürüstlük ve dayanışmayı destekler." search_by_name: İsim veya konuma göre arama yapın... - producers_join: Yerel ve temiz üreticiler şimdi Açık Gıda Ağı'na katılabilirler. + producers_join: Temiz gıda üreticileri! Açık Gıda Ağı sizler için kullanıma açıldı. charges_sales_tax: KDV Uyguluyor mu? print_invoice: "Faturayı yazdır" print_ticket: "Etiketi Yazdır" @@ -188,13 +192,13 @@ tr: resend_confirmation: "Onayı Tekrar Gönderin" view_order: "Siparişi Görüntüle" edit_order: "Siparişi Düzenle" - ship_order: "Siparişi Teslim Et" + ship_order: "Siparişi Gönder" cancel_order: "Siparişi İptal Et" confirm_send_invoice: "Bu siparişin faturası müşteriye gönderilecek. Devam etmek istiyor musunuz?" confirm_resend_order_confirmation: "Sipariş onayı e-postasını tekrar göndermek istediğinizden emin misiniz?" must_have_valid_business_number: "Faturaların gönderilebilmesi için %{enterprise_name} adına geçerli bir VKN/TCKN olmalı." invoice: "Fatura" - more: "Daha Fazla?" + more: "Daha Fazla" say_no: "Hayır" say_yes: "Evet" ongoing: Devam eden @@ -220,7 +224,7 @@ tr: enterprise_groups: Gruplar reports: Raporlar variant_overrides: Stok - import: İçe Aktar + import: Aktar spree_products: Spree Ürünleri all: Hepsi current: Güncel @@ -237,20 +241,22 @@ tr: items: Kalemler summary: Özet detailed: Detaylı - updated: Güncellenmiş + updated: Güncel 'yes': "Evet" 'no': "Hayır" - y: 'Y' - n: 'N' - powered_by: Tarafından desteklenmektedir + y: 'E' + n: 'H' + powered_by: Destekleyici blocked_cookies_alert: "Tarayıcınız bu ekranı kullanmak için gereken çerezleri engelliyor olabilir. Çerezlere izin vermek ve sayfayı yeniden yüklemek için aşağıya tıklayın." allow_cookies: "Çerezlere izin ver" notes: Notlar error: Hata processing_payment: "Ödeme İşlemi Gerçekleştiriliyor.." + no_pending_payments: "Bekleyen ödeme yok" + invalid_payment_state: "Geçersiz ödeme durumu" filter_results: Sonuçları Filtrele quantity: Miktar - pick_up: Teslimat Noktası + pick_up: Teslim Alma copy: Kopyala change_my_password: "Şifremi Değiştir" update_password: "Şifreyi Güncelle" @@ -258,8 +264,8 @@ tr: reset_password_token: Şifre kodunu sıfırla expired: Süresi doldu, lütfen yeni bir tane isteyin back_to_payments_list: "Ödeme Listesine Geri Dön" - maestro_or_solo_cards: "Maestro / Solo kartları" - backordered: "Bekleyen Sipariş" + maestro_or_solo_cards: "Ödeme kartları" + backordered: "Bakiye Sipariş" on hand: "Mevcut" ship: "Teslimat" actions: @@ -272,13 +278,13 @@ tr: delete: "Sil" admin: begins_at: Başlangıç - begins_on: Başlangıç + begins_on: Başlangıç vakti customer: Müşteri date: Tarih email: E-posta ends_at: Bitiş - ends_on: 'Bitiş ' - name: Ad + ends_on: Bitiş vakti + name: İsim on_hand: Mevcut on_demand: Talep Üzerine on_demand?: Talep Üzerine? @@ -296,7 +302,7 @@ tr: shipping_method: Teslimat Yöntemi shop: Tezgah sku: Stok Kodu - status_state: Şehir + status_state: Durum tags: Etiketler variant: Varyant weight: Ağırlık @@ -342,11 +348,11 @@ tr: enable_receipt_printing?: "Sipariş listesinde termal yazıcılar kullanarak makbuz yazdırma seçeneklerini göster?" stripe_connect_settings: edit: - title: "Şerit Bağlantısı" + title: "Ödeme Bağlantısı" settings: "Ayarlar" - stripe_connect_enabled: Satıcıların Stripe Connect kullanarak ödeme kabul etmesine izin verilsin mi? - no_api_key_msg: Bu işletme için Stripe hesabı yok. - configuration_explanation_html: Stripe Connect entegrasyonunu yapılandırma hakkında ayrıntılı talimatlar için lütfen bu kılavuza bakın . + stripe_connect_enabled: Satıcıların online ödeme kullanarak ödeme kabul etmesine izin verilsin mi? + no_api_key_msg: Bu işletme için online ödeme hesabı yok. + configuration_explanation_html: Online ödeme entegrasyonunu yapılandırma hakkında ayrıntılı talimatlar için lütfen bu kılavuza bakın . status: Durum ok: Tamam instance_secret_key: Örnek Gizli Anahtarı @@ -355,7 +361,7 @@ tr: charges_enabled: Ücretlendirmeler Etkin charges_enabled_warning: "Uyarı: Hesabınız için ücretlendirmeler etkin değil" auth_fail_error: Girdiğiniz API anahtarı geçersiz - empty_api_key_error_html: Stripe API anahtarı sağlanmadı. API anahtarınızı ayarlamak için lütfen bu talimatları izleyin + empty_api_key_error_html: Ödeme API anahtarı sağlanmadı. API anahtarınızı ayarlamak için lütfen bu talimatları izleyin matomo_settings: edit: title: "Matomo Ayarları" @@ -390,12 +396,12 @@ tr: header: Başlık home_page: Ana Sayfa producer_signup_page: Üretici kayıt sayfası - hub_signup_page: Pazar Yeri kayıt sayfası + hub_signup_page: Pazar kayıt sayfası group_signup_page: Grup kayıt sayfası main_links: Ana Menü Bağlantıları footer_and_external_links: Altbilgi ve Dış Bağlantılar your_content: İçeriğiniz - user_guide: Kullanici Rehberi + user_guide: Kullanici Kılavuzu enterprise_fees: index: title: "İşletme Ücretleri" @@ -470,8 +476,8 @@ tr: index: notice: "Dikkat" beta_notice: "Bu özellik hala beta sürümündedir: kullanırken bazı hatalarla karşılaşabilirsiniz. Lütfen teknik destek için iletişime geçmekten çekinmeyin." - select_file: Yüklemek için bir çizelge seçin - spreadsheet: Çizelge + select_file: Yüklemek için bir dosya seçin + spreadsheet: Dosya choose_import_type: İçe aktarım türünü seçin import_into: İçe aktarım türü product_list: Ürün listesi @@ -484,7 +490,7 @@ tr: category_values: Mevcut Kategori Değerleri product_categories: Ürün Kategorileri tax_categories: Vergi Kategorileri - shipping_categories: Nakliye Kategorileri + shipping_categories: Teslimat Kategorileri import: review: İncele import: İçe Aktar @@ -509,7 +515,7 @@ tr: overwrite_empty: Boşsa üzerine yaz default_stock: Stok seviyesini ayarla default_tax_cat: Vergi kategorisini ayarla - default_shipping_cat: Nakliye kategorisi belirle + default_shipping_cat: Teslimat kategorisi belirle default_available_date: Tarih belirle validation_overview: İçe aktarım doğrulaması gözden geçirme entries_found: İçe aktarılan dosyada bulunan girişler @@ -592,7 +598,7 @@ tr: variants_without_unit_value: "UYARI: Bazı varyantların birim değeri yok" select_variant: "Bir varyant seçin" enterprise: - select_outgoing_oc_products_from: sipariş döneminde dıları gidecek ürünleri şurdan seçin + select_outgoing_oc_products_from: Sipariş dönemi giden ürünleri şurdan seçin enterprises: index: title: İşletmeler @@ -635,7 +641,7 @@ tr: promo_image_placeholder: 'Bu görsel ''Hakkımızda'' kısmında görüntülenir' promo_image_note1: 'DİKKAT:' promo_image_note2: Kapak resmi 1200 x 260 formatına göre kırpılacaktır. - promo_image_note3: Kapak resmi, bir işletmenin profil sayfasının üstünde görüntülenir. + promo_image_note3: Kapak resmi, işletmenin profil sayfasının üstünde görüntülenir. inventory_settings: text1: Stok seviyelerini ve fiyatları şuradan yönetebilirsiniz inventory: Stok @@ -644,8 +650,8 @@ tr: ürünün satış listenize eklenmeden önce Stok listenize eklenip eklenmemesi gerektiğini seçebilirsiniz. Eğer ürünlerinizi yönetmek için Stok sistemini kullanmıyorsanız 'tavsiye edilen' seçeneği ile devam etmeniz gerekir. - preferred_product_selection_from_inventory_only_yes: Tezgahınıza yeni ürünler eklenebilir (önerilir) - preferred_product_selection_from_inventory_only_no: Yeni ürünler tezgahınıza eklemeden önce Stok listesine girilmelidir + preferred_product_selection_from_inventory_only_yes: Vitrininize yeni ürünler eklenebilir (önerilir) + preferred_product_selection_from_inventory_only_no: Yeni ürünler vitrininize eklemeden önce Stok listesine girilmelidir payment_methods: name: Ad applies: Uygulanma? @@ -670,13 +676,13 @@ tr: visible_in_search: Haritada görünsün mü? visible_in_search_tip: Sitede arama yapılırken bu işletmenin müşteriler tarafından görünür olup olmayacağını belirler. visible: Görünür - not_visible: Görünmez + not_visible: Gizli permalink: Bağlantı Adı (boşluk yok) permalink_tip: "Bağlantı adı, mağazanızın bağlantı URL'sini oluşturmak için kullanılır: %{link}sectiginiz-ad/tezgah" link_to_front: Tezgah linkiniz link_to_front_tip: Açık Gıda Ağı’ndaki tezgahınıza doğrudan bağlantı linki ofn_uid: AGA KN - ofn_uid_tip: Açık Gıda Topluluğu'na kayıtlı işletmenize özel tanımlanan kimlik numarası + ofn_uid_tip: Açık Gıda Ağı'na kayıtlı işletmenize özel tanımlanan kimlik numarası shipping_methods: name: Ad applies: Uygulanma? @@ -702,16 +708,16 @@ tr: enable_subscriptions_tip: "Üyelik işlevselliği etkinleştirilsin mi?" enable_subscriptions_false: "Kapalı" enable_subscriptions_true: "Etkin" - shopfront_message: "Tezgah Mesajınız" + shopfront_message: "Vitrin Mesajınız" shopfront_message_placeholder: > Müşterilerinize merhaba diyebilir, tezgahınız ve alışveriş şartlarınız - ile ilgili bilgi verebilirsiniz. Yazdıklarınız, müşteriler tezgahınızı + ile ilgili bilgi verebilirsiniz. Yazdıklarınız, müşteriler vitrininizi ziyaret ettiğinde görünür olacak. shopfront_message_link_tooltip: "Bağlantı ekle / düzenle" shopfront_message_link_prompt: "Lütfen eklemek için bir URL girin" - shopfront_closed_message: "Kapalı Tezgah Mesajı" + shopfront_closed_message: "Kapalı Vitrin Mesajı" shopfront_closed_message_placeholder: > - Tezgahınızın neden satışa kapalı olduğunu ve ne zaman açılacağını müşterilerinize + Vitrininizin neden satışa kapalı olduğunu ve ne zaman açılacağını müşterilerinize açıklayan bir mesaj yazın. Bu mesaj, açık sipariş döneminiz olmadığında sizi ziyaret edenler tarafından görülecek. shopfront_category_ordering: "Vitrin Kategori Sıralaması" @@ -723,15 +729,15 @@ tr: facebook_placeholder: "Örn: www.facebook.com/TurkiyeKoop" linkedin_placeholder: "Örn: www.linkedin.com/in/adınızsoyadınız" stripe_connect: - connect_with_stripe: "Stripe ile bağlan" - stripe_connect_intro: "Kredi kartı ile ödeme kabul etmek için, şerit hesabınızı Açık Gıda Ağına bağlamanız gerekir. Başlamak için sağdaki düğmeyi kullanın." - stripe_account_connected: "Stripe hesabı bağlı." + connect_with_stripe: "Iyzico sistemi ile bağlan" + stripe_connect_intro: "Kredi kartı ile ödeme kabul etmek için, Iyzico hesabınızı Açık Gıda Ağına bağlamanız gerekir. Başlamak için sağdaki düğmeyi kullanın." + stripe_account_connected: "Iyzico hesabı bağlı." disconnect: "Çıkış yap" confirm_modal: - title: Stripe ile bağlan - part1: Stripe, AGA'ya kayıtlı satıcıların, müşterilerinden kredi kartı ödemelerini kabul etmelerine imkan veren bir hizmet sağlayıcıdır. - part2: Bu özelliği kullanmak için Stripe hesabınızı AGA'ya bağlamanız gerekir. Aşağıdaki 'Kabul Ediyorum' butonunu tıkladığınızda, mevcut bir Stripe hesabını bağlayabileceğiniz Stripe web sitesine yönlendirilir veya hesabınız yoksa yeni bir tane oluşturabilirsiniz. - part3: AGA'nın müşterilerden sizin adınıza kredi kartı ödemelerini kabul etmesini sağlayacaktır. Kendi Stripe hesabınızı korumanız, Stripe ücretlerini ödemeniz ve ters ibrazları ve müşteri hizmetlerini kendiniz ele almanız gerektiğini lütfen unutmayın. + title: Iyzico ile bağlan + part1: Iyzico, AGA'ya kayıtlı satıcıların, müşterilerinden kredi kartı ödemelerini kabul etmelerine imkan veren bir hizmet sağlayıcıdır. + part2: Bu özelliği kullanmak için Iyzico hesabınızı AGA'ya bağlamanız gerekir. Aşağıdaki 'Kabul Ediyorum' butonunu tıkladığınızda, mevcut bir Iyzico hesabını bağlayabileceğiniz Iyzico web sitesine yönlendirilir veya hesabınız yoksa yeni bir tane oluşturabilirsiniz. + part3: AGA'nın müşterilerden sizin adınıza kredi kartı ödemelerini kabul etmesini sağlayacaktır. Kendi Iyzico hesabınızı korumanız, Iyzico ücretlerini ödemeniz ve ters ibrazları ve müşteri hizmetlerini kendiniz ele almanız gerektiğini lütfen unutmayın. i_agree: Onaylıyorum cancel: İptal Et tag_rules: @@ -782,7 +788,7 @@ tr: producer_profile: Üretici Profili connect_ofn: AGA üzerinden bağlan always_free: HER ZAMAN ÜCRETSİZ - producer_description_text: Ürünlerinizi Açık Gıda Ağı'na yükleyin. Böylece ürünleriniz ortak hesaplar üzerinden satışa sunulabilir. + producer_description_text: Ürünlerinizi Açık Gıda Ağı'na yükleyin. Böylece ürünleriniz pazar hesapları üzerinden satışa sunulabilir. producer_shop: Üretici Tezgahı sell_your_produce: Kendi ürününü sat producer_shop_description_text: Açık Gıda Ağı üzerinden açtığınız bireysel tezgahınız ile ürünlerinizi doğrudan müşterilere ulaştırabilirsiniz. @@ -864,6 +870,7 @@ tr: distributor: "Dağıtımcı" products: "Ürünler" tags: "Etiketler" + delivery_details: "Teslimat Detayları" fees: "Ücretler" previous: "Önceki" save: "Kaydet" @@ -916,8 +923,8 @@ tr: schedules: Takvimler new_schedule: Yeni Takvim name_and_timing_form: - name: ad - orders_open: 'Siparişler şu zamanda açık:' + name: Ad + orders_open: 'Sipariş açılma vakti:' coordinator: Koordinatör orders_close: Siparişler kapalı row: @@ -950,7 +957,7 @@ tr: could_not_resume_the_order: Sipariş sürdürülemedi shared: user_guide_link: - user_guide: Kullanici rehberi + user_guide: Kullanıcı Kılavuzu enterprises_hubs_tabs: has_no_payment_methods: "%{enterprise} için bir ödeme yöntemi yok" has_no_shipping_methods: "%{enterprise} için bir teslimat yöntemi yok" @@ -1030,7 +1037,7 @@ tr: enable_subscriptions_step_1_html: 1. %{enterprises_link} sayfasına gidin, tezgahınızı bulun ve ‘Yönet’i tıklayın enable_subscriptions_step_2: '''Tezgah Tercihleri'' altındaki Üyelikler seçeneğini etkinleştirin' set_up_shipping_and_payment_methods_html: '%{shipping_link} ve %{payment_link} yöntemlerini ayarlayın' - set_up_shipping_and_payment_methods_note_html: Yalnızca Nakit ve Şerit ödeme yöntemlerinin
'ü üyeliklerle kullanılabilir + set_up_shipping_and_payment_methods_note_html: Yalnızca Nakit ve Online ödeme yöntemlerinin
'ü üyeliklerle kullanılabilir ensure_at_least_one_customer_html: En az bir %{customer_link} bulunduğundan emin olun create_at_least_one_schedule: En az bir Takvim oluşturun create_at_least_one_schedule_step_1_html: 1. %{order_cycles_link} sayfasına gidin @@ -1055,7 +1062,7 @@ tr: details: details: Bilgi invalid_error: Hata! Lütfen zorunlu alanların tümünü doldurun ... - allowed_payment_method_types_tip: Şu anda yalnızca Nakit ve Stripe ödeme yöntemleri kullanılabilir + allowed_payment_method_types_tip: Şu anda yalnızca belirli ödeme yöntemleri kullanılabilir credit_card: Kredi kartı charges_not_allowed: Bu müşteri ücret yansıtılmasına izin vermiyor no_default_card: Müşterinin tahsilat yapılabilecek bir kartı yok @@ -1101,11 +1108,11 @@ tr: associated_subscriptions_error: Bağlantılı üyelikler olduğu için bu takvim silinemiyor controllers: enterprises: - stripe_connect_cancelled: "Stripe bağlantısı iptal edildi" - stripe_connect_success: "Stripe hesabı başarıyla bağlandı" - stripe_connect_fail: Maalesef, Stripe hesabınızın bağlantısı başarısız oldu + stripe_connect_cancelled: "Iyzico bağlantısı iptal edildi" + stripe_connect_success: "Iyzico hesabı başarıyla bağlandı" + stripe_connect_fail: Maalesef, Iyzico hesabınızın bağlantısı başarısız oldu stripe_connect_settings: - resource: Stripe Connect yapılandırması + resource: Iyzico yapılandırması api: enterprise_logo: destroy_attachment_does_not_exist: "Logo mevcut değil" @@ -1120,8 +1127,8 @@ tr: failed: "Ödeme başarısız oldu. Siparişinizi işleme koyabilmemiz için lütfen bizimle iletişime geçin." shops: hubs: - show_closed_shops: "Kapalı pazarları göster" - hide_closed_shops: "Kapalı pazarları gizle" + show_closed_shops: "Kapalı dükkanları göster" + hide_closed_shops: "Kapalı dükkanları gizle" show_on_map: "Tümünü haritada göster" shared: menu: @@ -1143,7 +1150,7 @@ tr: footer_contact_headline: "İrtibatta olalım" footer_contact_email: "Bize e-posta gönderin" footer_nav_headline: "Gezin" - footer_join_headline: "Bize katıl" + footer_join_headline: "Bize katılın" footer_join_body: "Açık Gıda Ağı üzerinden aracısız, adil ve temiz gıdaya ulaşma yolları keşfedin." footer_join_cta: "Daha fazlasını anlat!" footer_legal_call: "Okuyun" @@ -1157,7 +1164,7 @@ tr: shop: messages: login: "oturum aç" - signup: "kaydol" + signup: "Kaydol" contact: "İletişim" require_customer_login: "Yalnızca onaylı müşteriler buradan alışveriş yapabilir." require_login_html: "Zaten onaylanmış bir müşteriyseniz, devam etmek için %{login} veya %{signup}. Buradan alışveriş yapmaya başlamak ister misiniz? Lütfen katılmak için %{contact} %{enterprise} ile iletişime geçin." @@ -1185,24 +1192,24 @@ tr: invoice_issued_on: "Fatura Düznleme Tarihi" order_number: "Fatura numarası:" date_of_transaction: "İşlem tarihi:" - ticket_column_qty: "miktar" - ticket_column_item: "ürün" + ticket_column_qty: "Miktar" + ticket_column_item: "Ürün" ticket_column_unit_price: "Birim fiyat" ticket_column_total_price: "Toplam tutar" - menu_1_title: "Pazarlar" - menu_1_url: "/pazarlar" - menu_2_title: "harita" - menu_2_url: "/harita" - menu_3_title: "üreticiler" - menu_3_url: "/ üreticiler" + menu_1_title: "Pazar Yeri" + menu_1_url: "/shops" + menu_2_title: "HARİTA" + menu_2_url: "/map" + menu_3_title: "ÜRETİCİLER" + menu_3_url: "/producers" menu_4_title: "Gruplar" - menu_4_url: "/ gruplar" + menu_4_url: "/groups" menu_5_title: "hakkında" - menu_5_url: "https://about.openfoodnetwork.org.au/" + menu_5_url: "https://acikgida.com" menu_6_title: "Bağlan" - menu_6_url: "https://openfoodnetwork.org/au/connect/" + menu_6_url: "https://acikgida.com" menu_7_title: "öğren" - menu_7_url: "https://openfoodnetwork.org/au/learn/" + menu_7_url: "https://acikgida.com" logo: "Logo (640x130)" logo_mobile: "Cep telefonu logosu (75x26)" logo_mobile_svg: "Cep Telefonu logo (SVG)" @@ -1234,7 +1241,7 @@ tr: postcode_placeholder: Örn. 16000 suburb: İlçe state: Şehir - country: ülke + country: Ülke unauthorized: Yetkisiz terms_of_service: "Kullanım Şartları" on_demand: Talep üzerine @@ -1247,27 +1254,27 @@ tr: days: günler authorization_failure: "Yetki Hatası" label_shop: "Pazar" - label_shops: "Pazarlar" - label_map: "harita" + label_shops: "Pazar Yeri" + label_map: "HARİTA" label_producer: "Üretici" - label_producers: "üreticiler" + label_producers: "ÜRETİCİLER" label_groups: "Gruplar" label_about: "hakkında" label_connect: "Bağlan" - label_learn: "öğren" + label_learn: "Öğren" label_blog: "Blog" label_support: "Destek" label_shopping: "Alışveriş " label_login: "Oturum aç" label_logout: "Çıkış Yap" - label_signup: "kaydol" - label_administration: "yönetim" - label_admin: "yönetici" - label_account: "hesap" + label_signup: "Kaydol" + label_administration: "Yönetim" + label_admin: "Yönetici" + label_account: "Hesap" label_more: "Daha fazla göster" label_less: "Daha az göster" label_notices: "Uyarılar" - cart_items: "ürünler" + cart_items: "Ürünler" cart_headline: "Alışveriş sepetiniz" total: "Toplam" cart_updating: "Sepet güncelleniyor ..." @@ -1277,7 +1284,7 @@ tr: card_securitycode: "Güvenlik Kodu" card_expiry_date: Son kullanma tarihi card_masked_digit: "X" - card_expiry_abbreviation: "Tecrübe" + card_expiry_abbreviation: "Son kullanma tarihi" new_credit_card: "Yeni kredi kartı" my_credit_cards: Kredi kartlarım add_new_credit_card: Yeni kredi kartı ekle @@ -1337,12 +1344,12 @@ tr: cookies_policy_link_desc: "Daha fazla bilgi edinmek istiyorsanız," cookies_policy_link: "çerezler politikası" cookies_accept_button: "Çerezleri kabul et" - home_shop: Şimdi Alışveriş Yap + home_shop: ŞİMDİ ALIŞVERİŞ YAPIN brandstory_headline: "Bağımsız, adil ve temiz gıda ..." brandstory_intro: "Bazen sistemi düzeltmenin en iyi yolu yeni bir sistem yaratmaktır…" - brandstory_part1: "Açık Gıda Ağı, farklı ülkelerdeki temiz gıda üreticileri ve yazılımcılar tarafından yeni bir gıda sistemi oluşturmak üzere tasarlandı. Üretici ve türeticilerin bir araya gelerek aracısız bir gıda düzeni ile her açıdan daha sağlıklı bir toplum yaratmaları için çözümler sunar. Toplum yararına çalışır ve tamamen şeffaftır." + brandstory_part1: "Açık Gıda Ağı, adil ve temiz bir gıda sistemi oluşturmak için tasarlanan bir sosyal girişim projesidir. Üretici ve türeticilerin bir araya gelerek aracısız bir gıda düzeni ile her açıdan daha sağlıklı bir toplum yaratmaları için çözümler sunar. Kar amacı gütmez, toplum yararına çalışır, iletişim, dürüstlük ve dayanışmayı destekler." brandstory_part2: "AGA, üreticilere ve alıcılara aracısız ticaret faydaları sağlar ve toplumsal iletişimi ve güveni cesaretlendirerek üretici-türetici ilişkisi oluşturmayı hedefler. Gıda yetiştiriciliği ve satışının kendine özgü ihtiyaçlarını karşılamaya ve sorunlarını çözmeye yönelik olarak tasarlanmıştır. Temiz gıdaya ulaşım sürecini ve yönetimini kolaylaştırır." - brandstory_part3: "Platform üzerinden yalnızca temiz gıda üreticileri satış yapabilir. Eğer siz de temiz gıda üreticisi iseniz, ürünlerinizi AGA üzerinden oluşturduğunuz tezgah ile doğrudan alıcılara ulaştırabilirsiniz. Dilerseniz bölgenizdeki diğer üreticiler ile bir araya gelerek kendi ortak 'Üretici Pazarı' nızı oluşturursunuz. Bu şekilde çeşitliliği ve bereketi artırır, dayanışmanın getirdiği diğer faydalardan da yararlanabilirsiniz." + brandstory_part3: "Platform üzerinden yalnızca temiz gıda üreticileri satış yapabilir. Eğer siz de temiz gıda üreticisi iseniz, ürünlerinizi AGA üzerinden oluşturduğunuz tezgah ile doğrudan alıcılara ulaştırabilirsiniz. Dilerseniz bölgenizdeki diğer üreticiler ile bir araya gelerek kendi ortak 'Üretici Pazarı' veya 'Türetici Pazarı' nızı oluşturursunuz. Bu şekilde çeşitliliği ve bereketi artırır, dayanışmanın getirdiği diğer faydalardan da yararlanabilirsiniz." brandstory_part4: "Her yerde çalışıyor. Her şeyi değiştiriyor." brandstory_part5_strong: "Biz buna Açık Gıda Ağı diyoruz." brandstory_part6: "Hepimiz gıdamızı seviyoruz. Artık gıda sistemimizi de sevmeye başlayabiliriz." @@ -1353,17 +1360,17 @@ tr: system_headline: "Alışveriş - işte böyle çalışıyor." system_step1: "1. Ara" system_step1_text: "Yerel, adil, temiz ve mevsimsel gıda için, bağımsız ve cesur üreticilerimizin pazarlarından alışveriş yapın. Uzaklığa göre, ürün kategorisine veya teslimat tercihlerine göre arama yapabilirsiniz. " - system_step2: "2. Pazar" + system_step2: "2. Alışveriş Yap" system_step2_text: "Gıdanızı yerel üretici tezgahlarından, üretici ve türetici pazarlarından temin edin. Yaşanabilir bir dünya için alışkanlıklarınızı şimdi değiştirin. Gıdanızın ve onu size getiren insanların hikayelerini öğrenin!" - system_step3: "Teslimat Noktası / Kargo" - system_step3_text: "Teslimat için bekleyin veya gıdanız ile daha kişisel bir bağ kurmak için üreticinizi veya pazarını ziyaret edin. Doğayla ve gıdayla istediğiniz şekilde ama gerçek bir bağ kurun." + system_step3: "3. Teslimat " + system_step3_text: "Gıdanıza ulaşmak için eve teslim edilmesini ya da kargoyu bekleyin veya gıdanız ile daha kişisel bir bağ kurmak için üreticinizi veya pazarını kendiniz ziyaret edin. Doğayla ve gıdayla istediğiniz şekilde ama gerçek bir bağ kurun. " cta_headline: "Dünyayı daha iyi bir yer yapan alışveriş biçimi." cta_label: "Hazırım" stats_headline: "Yeni bir gıda sistemi yaratıyoruz." - stats_producers: "gıda üreticileri" + stats_producers: "GIDA ÜRETİCİLERİ" stats_shops: "gıda pazarları" stats_shoppers: "gıda alıcıları" - stats_orders: "gıda siparişleri" + stats_orders: "GIDA SİPARİŞLERİ" checkout_title: Ödeme Yap checkout_now: Şimdi ödeme yap checkout_order_ready: Sipariş şu tarihte hazır @@ -1490,6 +1497,7 @@ tr: shopping_oc_closed_description: "Lütfen bir sonraki dönem açılana kadar bekleyin (veya geç siparişleri kabul edip edemeyeceğimizi görmek için doğrudan bizimle iletişime geçin)" shopping_oc_last_closed: "Son dönem %{distance_of_time} önce kapandı" shopping_oc_next_open: "Bir sonraki dönem %{distance_of_time}'da açılıyor" + shopping_oc_select: "Seçin..." shopping_tabs_home: "Ana sayfa" shopping_tabs_shop: "Alışveriş yap" shopping_tabs_about: "hakkında" @@ -1510,11 +1518,11 @@ tr: hubs_profile_only: "Yalnızca profil" hubs_delivery_options: "Teslimat seçenekleri" hubs_pickup: "Teslimat Noktası" - hubs_delivery: "teslimat" + hubs_delivery: "Eve Teslim" hubs_producers: "Üreticilerimiz" - hubs_filter_by: "filtre" - hubs_filter_type: "yazın" - hubs_filter_delivery: "teslimat" + hubs_filter_by: "Filtrele" + hubs_filter_type: "Ürün Çeşidi" + hubs_filter_delivery: "Eve Teslim" hubs_filter_property: "Özellik" hubs_matches: "Bunu mu arıyordunuz?" hubs_intro: Bulunduğunuz bölgeden alışveriş yapın @@ -1539,7 +1547,7 @@ tr: products_update_error_msg: "Kaydetme başarısız oldu." products_update_error_data: "Geçersiz veriler nedeniyle kaydetme başarısız oldu:" products_changes_saved: "Değişiklikler kaydedildi." - search_no_results_html: "Üzgünüz, %{query} için sonuç bulunamadı. Başka bir arama yapmak ister misiniz?" + search_no_results_html: "Üzgünüz, %{query} sonuç bulunamadı. Başka bir arama yapmak ister misiniz?" components_profiles_popover: "Açık Gıda Ağında bir vitrini olmayan ancak başka bir sitede kendi satış siteleri olan hesaplar" components_profiles_show: "Profilleri göster" components_filters_nofilters: "Filtresiz" @@ -1599,7 +1607,7 @@ tr: producers_contact_phone: Ara producers_contact_social: Takip et producers_buy_at_html: "%{enterprise} ürünleri için buradan alışveriş yapın:" - producers_filter: Filtre + producers_filter: Filtrele producers_filter_type: tür producers_filter_property: Özellik producers_title: Üreticiler @@ -1632,12 +1640,12 @@ tr: sell_hubs_detail: "AGA üzerinden gıda işletmeniz veya topluluğunuz için bir profil oluşturun. İstediğiniz zaman profilinizi çok üreticili bir pazara yükseltebilirsiniz." sell_groups_detail: "Bölgenizdeki veya ağınızdaki işletmelerin (üreticilerin, pazarların veya diğer grupların) detaylı rehber listesini oluşturun." sell_user_guide: "Kullanım kılavuzumuzda daha fazla bilgi edinin." - sell_listing_price: "AGA üzerinde görünür olmak ücretsizdir. OFN'de bir mağaza açmak ve işletmek aylık 500 dolara kadar ücretsizdir. Daha fazla satıyorsanız, satışların% 1'i ile% 3'ü arasında topluluk katkınızı seçebilirsiniz. Fiyatlandırma hakkında daha fazla bilgi için, üst menüdeki Hakkında bağlantısını kullanarak Yazılım Platformu bölümünü ziyaret edin." + sell_listing_price: "AGA üzerinde görünür olmak ücretsizdir. Fiyatlandırma hakkında daha fazla bilgi için, üst menüdeki Hakkında bağlantısını kullanarak Yazılım Platformu bölümünü ziyaret edin." sell_embed: "Açık Gıda Ağı üzerinden oluşturduğunuz tezgahınızı kendi web siteniz üzerinden de kullanmanıza yardımcı olabiliriz. Müşterileriniz mevcut internet siteniz üzerinden de aynı şekilde sipariş verebilirler. " sell_ask_services: "Bize AGA hizmetleri hakkında soru sorun." - shops_title: Mağazalar + shops_title: Dükkanlar shops_headline: Alışveriş biçim değiştiriyor - shops_text: Gıdalar döngüler halinde büyür, çiftçiler döngüler halinde hasat eder ve döngüler halinde yiyecek sipariş ederiz. Sipariş döngüsünün kapalı olduğunu fark ederseniz, kısa süre sonra tekrar kontrol edin. + shops_text: Gıda dönemsel yetiştirilir, dönemsel hasat edilir ve dönemsel sipariş edilir. Aradığınız sipariş dönemi kapalı ise kısa süre sonra tekrar kontrol edin. shops_signup_title: Pazar olarak kaydolun shops_signup_headline: Gıda pazarları, sınır yok. shops_signup_motivation: Her türlü gıda işletmesi/topluluğu modelini destekliyoruz. Bağımsız ve şeffaf bir sosyal girişimiz. İşlerinizi kolaylaştırmaya çalışan yol arkadaşlarıyız. @@ -1736,9 +1744,9 @@ tr: email_required: "Bir e-posta adresi sağlamalısınız" logging_in: "Biraz bekleyin, giriş yapıyoruz" signup_email: "E-posta adresiniz" - choose_password: "bir şifre Şeçin" + choose_password: "Bir şifre seçin" confirm_password: "Şifreyi Onayla" - action_signup: "Şimdi üye Ol" + action_signup: "Şimdi Üye Ol" forgot_password: "Parolanızı mı unuttunuz?" password_reset_sent: "Şifrenizi sıfırlama talimatlarını içeren bir e-posta gönderildi!" reset_password: "Şifreyi yenile" @@ -1863,6 +1871,7 @@ tr: headline: "Tamamlandı!" thanks: "%{enterprise} ile ilgili ayrıntıları doldurduğunuz için teşekkür ederiz." login: "Dilediğiniz zaman Açık Gıda Ağı üzerinden giriş yapıp Yönetici paneline giderek işletmenizin ayarlarını güncelleyebilirsiniz." + action: "İşletme Paneline Git" back: "Geri" continue: "Devam et" action_or: "VEYA" @@ -2056,7 +2065,7 @@ tr: report_customers_cycle: "Sipariş Dönemi" report_customers_type: "Rapor türü" report_customers_csv: "Csv olarak indir" - report_producers: "üreticiler:" + report_producers: "ÜRECİTİLER:" report_type: "Rapor türü:" report_hubs: "Pazarlar:" report_payment: "Ödeme yöntemleri:" @@ -2279,6 +2288,7 @@ tr: enterprise_register_success_notice: "Tebrikler! %{enterprise}için kayıt tamamlandı!" enterprise_bulk_update_success_notice: "İşletmeler başarıyla güncellendi" enterprise_bulk_update_error: 'Güncelleştirme başarısız' + enterprise_shop_show_error: "Aradığınız dükkan AGA üzerinde bulunamıyor veya gizli durumda. Lütfen diğerlerini kontrol edin." order_cycles_create_notice: 'Sipariş döneminiz oluşturuldu.' order_cycles_update_notice: 'Sipariş döneminiz güncellendi.' order_cycles_bulk_update_notice: 'Sipariş dönemleri güncellendi.' @@ -2400,7 +2410,7 @@ tr: Açık Gıda Ağı, mümkün olduğunca çok gıda topluluğu/kooperatifi modelini desteklemeye çalışır. Sizin de gıda topluluğunuzu veya gıda işletmenizi en iyi şekilde yönetmeniz için tüm imkanları ve araçları sağlamaya hazırız. - get_listing: Giriş alın + get_listing: Görünür Olun always_free: HER ZAMAN ÜCRETSİZ sell_produce_others: Başkalarının ürünlerini sat sell_own_produce: Kendi ürününü sat @@ -2409,8 +2419,8 @@ tr: producer: Üretici producer_text1: > Dürüst ve bilinçli üreticiler, insanlara sağlıklı gıdalar sağlar. Siz - de birşeyler yetiştiriyor, büyütüyor, sağıyor, hasat ediyor, pişiriyor - kurutuyor veya hazırlıyorsanız, üreticisiniz demektir. + de birşeyler yetiştiriyor, büyütüyor, sağıyor, hasat ediyor, pişiriyor, + kurutuyor veya hazırlıyorsanız, bir üreticisiniz demektir. producer_text2: > Üreticiler sistem üzerinde farklı şekillerde aktif olarak da hem kendilerine hem de diğer işletmelere daha faydalı olabilirler. Çevrelerindeki üreticilerin @@ -2421,9 +2431,9 @@ tr: Üretici olmayan hesaplar kendi ürünleri olmadığı için Açık Gıda Ağı üzerinden ürün oluşturamazlar. non_producer_text2: > - Bunun yerine çevrelerindeki üreticiler adına sipariş ve teslimatları - yönetebilir, adil ve temiz gıdayı nihai tüketiciler ile buluşturmaya - yardımcı olabilirler. + Bunun yerine çevrelerindeki bulunan veya tedarikçileri olan üreticiler + adına sipariş ve teslimatları yönetebilir, adil ve temiz gıdayı nihai + tüketiciler ile buluşturmaya yardımcı olabilirler. producer_desc: Gıda üreticileri producer_example: 'Örn: ÇİFTÇİLER, FIRINLAR, ÜRETİM KOOPERATİFLERİ vs.' non_producer_desc: Diğer tüm gıda işletmeleri @@ -2469,7 +2479,7 @@ tr: cart: "sepet" complete: "tamamla" confirm: "onayla" - delivery: "teslimat" + delivery: "Eve Teslim" paused: "Durduruldu" payment: "ödeme" pending: "Bekliyor" @@ -2718,7 +2728,7 @@ tr: shipment_inc_vat: "KDV dahil teslimat" shipping_tax_rate: "Kargo Vergi Oranı" category: "Kategori" - delivery: "teslimat" + delivery: "Eve Teslim" temperature_controlled: "Soğuk Sevkiyat" new_product: "Yeni ürün" administration: "yönetim" @@ -2746,6 +2756,8 @@ tr: location: "yer" count_on_hand: "Eldeki Miktar" quantity: "miktar" + on_demand: "Talep Üzerine" + on_hand: "Mevcut" package_from: "gelen paket" item_description: "Ürün Açıklaması" price: "Fiyat" @@ -2859,7 +2871,7 @@ tr: shipping_methods: "Teslimat Yöntemleri" shipping_categories: "Nakliye Kategorileri" new_shipping_category: "Yeni Nakliye Kategorisi" - back_to_shipping_categories: "Nakliye Kategorilerine Geri Dön" + back_to_shipping_categories: "Teslimat Kategorilerine Geri Dön" analytics_trackers: "Analitik İzleyiciler" no_trackers_found: "İzleyici Bulunamadı" new_tracker: "Yeni İzleyici" @@ -2868,7 +2880,7 @@ tr: back_to_trackers_list: "İzleyiciler Listesine Geri Dön" name: "ad" description: "Açıklama" - type: "tür" + type: "Çeşit" default: "varsayılan" calculator: "Hesaplama" zone: "bölge" @@ -2890,7 +2902,7 @@ tr: normal_amount: "Normal Tutar" discount_amount: "İndirim tutarı" no_images_found: "Resim Bulunamadı" - new_image: "Yeni görüntü" + new_image: "Yeni Görüntü" filename: "Dosya adı" alt_text: "alternatif metin" thumbnail: "Küçük görsel" @@ -3017,6 +3029,8 @@ tr: tax_invoice: "VERGİ FATURASI" code: "Kod" from: "İtibaren" + to: "Fatura Adresi" + shipping: "Teslimat" form: distribution_fields: title: "Dağıtım" @@ -3095,8 +3109,8 @@ tr: products: image_upload_error: "Ürün resmi tanınamadı. Lütfen PNG veya JPG biçiminde bir resim yükleyin." new: - title: "Yeni ürün" - new_product: "Yeni ürün" + title: "Yeni Ürün" + new_product: "Yeni Ürün" supplier: "Tedarikçi" product_name: "Ürün adı" units: "Ölçü Birimi" @@ -3128,7 +3142,7 @@ tr: import_date: "İçe Aktarım Tarihi" products_variant: variant_has_n_overrides: "Bu varyant %{n} geçersiz kılınma özelliğine sahip" - new_variant: "Yeni varyant" + new_variant: "Yeni Varyant" product_name: Ürün adı primary_taxon_form: product_category: Ürün Kategorisi @@ -3219,7 +3233,7 @@ tr: enter_new_card: Yeni bir kart için bilgileri girin used_saved_card: "Kayıtlı bir kart kullanın:" or_enter_new_card: "Veya yeni bir kart için bilgileri girin:" - remember_this_card: Bu kartı hatırlıyor musunuz? + remember_this_card: Bu kart hatırlansın mı? date_picker: format: '% Y-% A-%d' js_format: 'yy-aa-gg' @@ -3269,7 +3283,7 @@ tr: cart: sepet complete: tamamla confirm: onayla - delivery: teslimat + delivery: Eve Teslim paused: durduruldu payment: ödeme pending: bekliyor @@ -3321,7 +3335,7 @@ tr: until: Şu zamana kadar past_orders: order: Sipariş - shop: Dükkan + shop: Tezgah completed_at: Tamamlanma Tarihi items: Ürünler total: Toplam diff --git a/config/routes.rb b/config/routes.rb index c928027647..5a4638f81d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -89,11 +89,6 @@ Openfoodnetwork::Application.routes.draw do get 'sitemap.xml', to: 'sitemap#index', defaults: { format: 'xml' } - # Mount engine routes - mount Web::Engine, :at => '/' - mount Catalog::Engine, :at => '/' - mount OrderManagement::Engine, :at => '/' - # Mount Spree's routes mount Spree::Core::Engine, :at => '/' end diff --git a/config/routes/api.rb b/config/routes/api.rb index fbd7b23378..1147076112 100644 --- a/config/routes/api.rb +++ b/config/routes/api.rb @@ -33,9 +33,11 @@ Openfoodnetwork::Application.routes.draw do resource :logo, only: [:destroy] resource :promo_image, only: [:destroy] + end - member do - get :shopfront + resources :shops, only: [:show] do + collection do + get :closed_shops end end diff --git a/config/routes/spree.rb b/config/routes/spree.rb index 0dd14c8dea..7a7ba8ad04 100644 --- a/config/routes/spree.rb +++ b/config/routes/spree.rb @@ -156,12 +156,6 @@ Spree::Core::Engine.routes.draw do resources :taxons end - resources :taxons, :only => [] do - collection do - get :search - end - end - resources :tax_rates resource :tax_settings resources :tax_categories diff --git a/db/migrate/20120327000552_spree_zero_nine_zero.rb b/db/migrate/20120327000552_spree_zero_nine_zero.rb deleted file mode 100644 index bd40ead315..0000000000 --- a/db/migrate/20120327000552_spree_zero_nine_zero.rb +++ /dev/null @@ -1,389 +0,0 @@ -class SpreeZeroNineZero < ActiveRecord::Migration - # This is a legacy migration consolidating all of the database changes needed as of Spree 0.9.0 - # (See http://railsdog.lighthouseapp.com/projects/31096-spree/tickets/772) - - def change - create_table :addresses, :force => true do |t| - t.string :firstname, :lastname, :address1, :address2, :city, - :zipcode, :phone, :state_name, :alternative_phone - t.references :state - t.references :country - - t.timestamps - end - - create_table :adjustments, :force => true do |t| - t.integer :position, :adjustment_source_id - t.decimal :amount, :precision => 8, :scale => 2, :default => 0.0, :null => false - t.string :type, :description, :adjustment_source_type, :secondary_type - t.references :order - - t.timestamps - end - - create_table :assets, :force => true do |t| - t.integer :viewable_id, :attachment_width, :attachment_height, - :attachment_size, :position - t.string :viewable_type, :limit => 50 - t.string :attachment_content_type, :attachment_file_name - t.string :type, :limit => 75 - t.datetime :attachment_updated_at - end - - create_table :calculators, :force => true do |t| - t.string :type - t.integer :calculable_id, :null => false - t.string :calculable_type, :null => false - - t.timestamps - end - - create_table :checkouts, :force => true do |t| - t.references :order - t.string :email, :ip_address - t.text :special_instructions - t.integer :bill_address_id - t.datetime :completed_at - - t.timestamps - end - - create_table :configurations, :force => true do |t| - t.string :name - t.string :type, :limit => 50 - - t.timestamps - end - - add_index :configurations, [:name, :type], :name => 'index_configurations_on_name_and_type' - - create_table :countries, :force => true do |t| - t.string :iso_name, :iso, :iso3, :name - t.integer :numcode - end - - create_table :coupons, :force => true do |t| - t.string :code, :description - t.integer :usage_limit - t.boolean :combine - t.datetime :expires_at, :starts_at - - t.timestamps - end - - create_table :creditcard_txns, :force => true do |t| - t.integer :creditcard_payment_id, :txn_type - t.decimal :amount, :precision => 8, :scale => 2, :default => 0.0, :null => false - t.string :response_code - t.text :avs_response, :cvv_response - - t.timestamps - end - - create_table :creditcards, :force => true do |t| - t.text :number, :verification_value - t.string :month, :year, :cc_type, :display_number, :first_name, - :last_name, :start_month, :start_year, :issue_number - t.references :address - t.references :checkout - - t.timestamps - end - - create_table :gateway_configurations, :force => true do |t| - t.references :gateway - - t.timestamps - end - - create_table :gateway_option_values, :force => true do |t| - t.references :gateway_configuration - t.references :gateway_option - t.text :value - - t.timestamps - end - - create_table :gateway_options, :force => true do |t| - t.string :name - t.text :description - t.boolean :textarea, :default => false - t.references :gateway - - t.timestamps - end - - create_table :gateways, :force => true do |t| - t.string :clazz, :name - t.text :description - t.boolean :active - - t.timestamps - end - - create_table :inventory_units, :force => true do |t| - t.integer :lock_version, :default => 0 - t.string :state - t.references :variant - t.references :order - - t.timestamps - end - - create_table :line_items, :force => true do |t| - t.references :order - t.references :variant - t.integer :quantity, :null => false - t.decimal :price, :precision => 8, :scale => 2, :null => false - - t.timestamps - end - - add_index :line_items, :order_id, :name => 'index_line_items_on_order_id' - add_index :line_items, :variant_id, :name => 'index_line_items_on_variant_id' - - create_table :option_types, :force => true do |t| - t.string :name, :limit => 100 - t.string :presentation, :limit => 100 - - t.timestamps - end - - create_table :option_types_prototypes, :id => false, :force => true do |t| - t.references :prototype - t.references :option_type - end - - create_table :option_values, :force => true do |t| - t.integer :position - t.string :name, :presentation - t.references :option_type - - t.timestamps - end - - create_table :option_values_variants, :id => false, :force => true do |t| - t.integer :variant_id - t.integer :option_value_id - end - - add_index :option_values_variants, :variant_id, :name => 'index_option_values_variants_on_variant_id' - - create_table :orders, :force => true do |t| - t.string :number, :limit => 15 - t.decimal :item_total, :precision => 8, :scale => 2, :default => 0.0, :null => false - t.decimal :total, :precision => 8, :scale => 2, :default => 0.0, :null => false - t.string :state - t.string :token - t.decimal :adjustment_total, :precision => 8, :scale => 2, :default => 0.0, :null => false - t.decimal :credit_total, :precision => 8, :scale => 2, :default => 0.0, :null => false - t.references :user - - t.timestamps - end - - add_index :orders, :number, :name => 'index_orders_on_number' - - create_table :payments, :force => true do |t| - t.decimal :amount, :precision => 8, :scale => 2, :default => 0.0, :null => false - t.string :type - t.references :order - t.references :creditcard - - t.timestamps - end - - create_table :preferences, :force => true do |t| - t.string :attribute, :null => false, :limit => 100 - t.integer :owner_id, :null => false, :limit => 30 - t.string :owner_type, :null => false, :limit => 50 - t.integer :group_id - t.string :group_type, :limit => 50 - t.string :value - - t.timestamps - end - - add_index :preferences, [:owner_id, :owner_type, :attribute, :group_id, :group_type], :name => 'index_preferences_on_owner_and_attribute_and_preference', :unique => true - - create_table :product_option_types, :force => true do |t| - t.integer :position - t.references :product - t.references :option_type - - t.timestamps - end - - create_table :product_properties, :force => true do |t| - t.string :value - t.references :product - t.references :property - - t.timestamps - end - - create_table :products, :force => true do |t| - t.string :name, :default => '', :null => false - t.text :description - t.datetime :available_on, :deleted_at - t.string :permalink, :meta_description, :meta_keywords - t.references :tax_category - t.references :shipping_category - - t.timestamps - end - - add_index :products, :available_on, :name => 'index_products_on_available_on' - add_index :products, :deleted_at, :name => 'index_products_on_deleted_at' - add_index :products, :name, :name => 'index_products_on_name' - add_index :products, :permalink, :name => 'index_products_on_permalink' - - create_table :products_taxons, :id => false, :force => true do |t| - t.references :product - t.references :taxon - end - - add_index :products_taxons, :product_id, :name => 'index_products_taxons_on_product_id' - add_index :products_taxons, :taxon_id, :name => 'index_products_taxons_on_taxon_id' - - create_table :properties, :force => true do |t| - t.string :name - t.string :presentation, :null => false - - t.timestamps - end - - create_table :properties_prototypes, :id => false, :force => true do |t| - t.references :prototype - t.references :property - end - - create_table :prototypes, :force => true do |t| - t.string :name - - t.timestamps - end - - create_table :roles, :force => true do |t| - t.string :name - end - - create_table :roles_users, :id => false, :force => true do |t| - t.references :role - t.references :user - end - - add_index :roles_users, :role_id, :name => 'index_roles_users_on_role_id' - add_index :roles_users, :user_id, :name => 'index_roles_users_on_user_id' - - create_table :shipments, :force => true do |t| - t.string :tracking, :number - t.decimal :cost, :precision => 8, :scale => 2 - t.datetime :shipped_at - t.references :order - t.references :shipping_method - t.references :address - - t.timestamps - end - - create_table :shipping_categories, :force => true do |t| - t.string :name - - t.timestamps - end - - create_table :shipping_methods, :force => true do |t| - t.string :name - t.references :zone - - t.timestamps - end - - create_table :state_events, :force => true do |t| - t.string :name, :previous_state - t.references :order - t.references :user - - t.timestamps - end - - create_table :states, :force => true do |t| - t.string :name - t.string :abbr - t.references :country - end - - create_table :tax_categories, :force => true do |t| - t.string :name, :description - - t.timestamps - end - - create_table :tax_rates, :force => true do |t| - t.decimal :amount, :precision => 8, :scale => 4 - t.references :zone - t.references :tax_category - - t.timestamps - end - - create_table :taxonomies, :force => true do |t| - t.string :name, :null => false - - t.timestamps - end - - create_table :taxons, :force => true do |t| - t.integer :parent_id - t.integer :position, :default => 0 - t.string :name, :null => false - t.string :permalink - t.references :taxonomy - - t.timestamps - end - - create_table :users, :force => true do |t| - t.string :crypted_password, :limit => 128, :default => '', :null => false - t.string :salt, :limit => 128, :default => '', :null => false - t.string :email, :remember_token, :remember_token_expires_at, - :persistence_token, :single_access_token, :perishable_token - t.integer :login_count, :default => 0, :null => false - t.integer :failed_login_count, :default => 0, :null => false - t.datetime :last_request_at, :current_login_at, :last_login_at - t.string :current_login_ip, :last_login_ip, :login - t.integer :ship_address_id, :bill_address_id - - t.timestamps - end - - create_table :variants, :force => true do |t| - t.string :sku, :default => '', :null => false - t.decimal :price, :precision => 8, :scale => 2, :null => false - t.decimal :weight, :precision => 8, :scale => 2 - t.decimal :height, :precision => 8, :scale => 2 - t.decimal :width, :precision => 8, :scale => 2 - t.decimal :depth, :precision => 8, :scale => 2 - t.datetime :deleted_at - t.boolean :is_master, :default => false - t.references :product - end - - add_index :variants, :product_id, :name => 'index_variants_on_product_id' - - create_table :zone_members, :force => true do |t| - t.integer :zoneable_id - t.string :zoneable_type - t.references :zone - - t.timestamps - end - - create_table :zones, :force => true do |t| - t.string :name, :description - - t.timestamps - end - end -end diff --git a/db/migrate/20120327000553_create_indexes_for_inventory_units.rb b/db/migrate/20120327000553_create_indexes_for_inventory_units.rb deleted file mode 100644 index 6ce5048610..0000000000 --- a/db/migrate/20120327000553_create_indexes_for_inventory_units.rb +++ /dev/null @@ -1,6 +0,0 @@ -class CreateIndexesForInventoryUnits < ActiveRecord::Migration - def change - add_index :inventory_units, :variant_id - add_index :inventory_units, :order_id - end -end diff --git a/db/migrate/20120327000554_add_count_on_hand_to_variants_and_products.rb b/db/migrate/20120327000554_add_count_on_hand_to_variants_and_products.rb deleted file mode 100644 index 7341e5e268..0000000000 --- a/db/migrate/20120327000554_add_count_on_hand_to_variants_and_products.rb +++ /dev/null @@ -1,49 +0,0 @@ -class AddCountOnHandToVariantsAndProducts < ActiveRecord::Migration - def up - add_column :variants, :count_on_hand, :integer, :default => 0, :null => false - add_column :products, :count_on_hand, :integer, :default => 0, :null => false - - # Due to our namespacing changes, this migration (from earlier Spree versions) is broken - # To fix it, temporarily set table name on each of the models involved - # And then... - Spree::Variant.table_name = 'variants' - Spree::Product.table_name = 'products' - Spree::InventoryUnit.table_name = 'inventory_units' - - # In some cases needed to reflect changes in table structure - Spree::Variant.reset_column_information - Spree::Product.reset_column_information - - say_with_time 'Transfering inventory units with status on_hand to variants table...' do - Spree::Variant.all.each do |v| - v.update_attribute(:count_on_hand, v.inventory_units.with_state('on_hand').size) - Spree::InventoryUnit.destroy_all(:variant_id => v.id, :state => 'on_hand') - end - end - - say_with_time 'Updating products count on hand' do - Spree::Product.all.each do |p| - product_count_on_hand = p.has_variants? ? - p.variants.inject(0) { |acc, v| acc + v.count_on_hand } : - (p.master ? p.master.count_on_hand : 0) - p.update_attribute(:count_on_hand, product_count_on_hand) - end - end - - # ... Switch things back at the end of the migration - Spree::Variant.table_name = 'spree_variants' - Spree::Product.table_name = 'spree_products' - Spree::InventoryUnit.table_name = 'spree_inventory_units' - end - - def down - Spree::Variant.all.each do |v| - v.count_on_hand.times do - Spree::InventoryUnit.create(:variant => variant, :state => 'on_hand') - end - end - - remove_column :variants, :count_on_hand - remove_column :products, :count_on_hand - end -end diff --git a/db/migrate/20120327000555_change_taxons_to_nested_set.rb b/db/migrate/20120327000555_change_taxons_to_nested_set.rb deleted file mode 100644 index d00944142c..0000000000 --- a/db/migrate/20120327000555_change_taxons_to_nested_set.rb +++ /dev/null @@ -1,46 +0,0 @@ -class ChangeTaxonsToNestedSet < ActiveRecord::Migration - def up - add_column :taxons, :lft, :integer - add_column :taxons, :rgt, :integer - - Spree::Taxon.reset_column_information # So the new root ids get saved - - # Temporarily set the table back to taxons - Spree::Taxon.table_name = 'taxons' - - Spree::Taxon.class_eval do - # adapted from awesome nested set to use 'position' information - indices = {} - - left_column_name = 'lft' - right_column_name = 'rgt' - quoted_parent_column_name = 'parent_id' - scope = lambda{|node|} - - set_left_and_rights = lambda do |node| - # set left - node[left_column_name] = indices[scope.call(node)] += 1 - # find - where("#{quoted_parent_column_name} = ?", node).order('position ASC').each{ |n| set_left_and_rights.call(n) } - # set right - node[right_column_name] = indices[scope.call(node)] += 1 - node.save! - end - - # Find root node(s) - where("#{quoted_parent_column_name}" => nil).order('position ASC').each do |root_node| - # setup index for this scope - indices[scope.call(root_node)] ||= 0 - set_left_and_rights.call(root_node) - end - end - - # Set it back after the migration - Spree::Taxon.table_name = 'spree_taxons' - end - - def down - remove_column :taxons, :lft - remove_column :taxons, :rgt - end -end diff --git a/db/migrate/20120327000556_move_to_configurable_gateways.rb b/db/migrate/20120327000556_move_to_configurable_gateways.rb deleted file mode 100644 index a598cce828..0000000000 --- a/db/migrate/20120327000556_move_to_configurable_gateways.rb +++ /dev/null @@ -1,54 +0,0 @@ -class MoveToConfigurableGateways < ActiveRecord::Migration - def up - drop_table :gateways - drop_table :gateway_options - drop_table :gateway_option_values - drop_table :gateway_configurations - - create_table :gateways, :force => true do |t| - t.string :type, :name - t.text :description - t.boolean :active, :default => true - t.string :environment, :default => 'development' - t.string :server, :default => 'test' - t.boolean :test_mode, :default => true - - t.timestamps - end - end - - def down - drop_table :gateways - - create_table :gateway_configurations, :force => true do |t| - t.references :gateway - - t.timestamps - end - - create_table :gateway_option_values, :force => true do |t| - t.text :value - t.references :gateway_configuration - t.references :gateway_option - - t.timestamps - end - - create_table :gateway_options, :force => true do |t| - t.string :name - t.text :description - t.boolean :textarea, :default => false - t.references :gateway - - t.timestamps - end - - create_table :gateways, :force => true do |t| - t.string :clazz, :name - t.text :description - t.boolean :active - - t.timestamps - end - end -end diff --git a/db/migrate/20120327000557_product_groups_and_scopes.rb b/db/migrate/20120327000557_product_groups_and_scopes.rb deleted file mode 100644 index 00a82d0a2b..0000000000 --- a/db/migrate/20120327000557_product_groups_and_scopes.rb +++ /dev/null @@ -1,18 +0,0 @@ -class ProductGroupsAndScopes < ActiveRecord::Migration - def change - create_table :product_groups do |t| - t.string :name, :permalink, :order - end - - create_table :product_scopes do |t| - t.string :name - t.text :arguments - t.references :product_group - end - - add_index :product_groups, :name - add_index :product_groups, :permalink - add_index :product_scopes, :name - add_index :product_scopes, :product_group_id - end -end diff --git a/db/migrate/20120327000558_add_open_id_authentication_tables.rb b/db/migrate/20120327000558_add_open_id_authentication_tables.rb deleted file mode 100644 index fe20ab3ec2..0000000000 --- a/db/migrate/20120327000558_add_open_id_authentication_tables.rb +++ /dev/null @@ -1,15 +0,0 @@ -class AddOpenIdAuthenticationTables < ActiveRecord::Migration - def change - create_table :open_id_authentication_associations, :force => true do |t| - t.integer :issued, :lifetime - t.string :handle, :assoc_type - t.binary :server_url, :secret - end - - create_table :open_id_authentication_nonces, :force => true do |t| - t.integer :timestamp, :null => false - t.string :server_url, :null => true - t.string :salt, :null => false - end - end -end diff --git a/db/migrate/20120327000559_add_openid_field_to_users.rb b/db/migrate/20120327000559_add_openid_field_to_users.rb deleted file mode 100644 index 3ee6288692..0000000000 --- a/db/migrate/20120327000559_add_openid_field_to_users.rb +++ /dev/null @@ -1,24 +0,0 @@ -class AddOpenidFieldToUsers < ActiveRecord::Migration - def up - add_column :users, :openid_identifier, :string - add_index :users, :openid_identifier - - change_column :users, :login, :string, :default => nil, :null => true - change_column :users, :crypted_password, :string, :default => nil, :null => true - change_column :users, :salt, :string, :default => nil, :null => true - end - - def down - remove_column :users, :openid_identifier - - # Due to namespacing change, temporarily set the table back to users - Spree::User.table_name = 'users' - - [:login, :crypted_password, :salt].each do |field| - Spree::User.where(field => nil).each { |user| user.update_attribute(field, '') if user.send(field).nil? } - change_column :users, field, :string, :default => '', :null => false - end - - Spree::User.table_name = 'spree_users' - end -end diff --git a/db/migrate/20120327000560_change_preference_value_type.rb b/db/migrate/20120327000560_change_preference_value_type.rb deleted file mode 100644 index b0e1d07bab..0000000000 --- a/db/migrate/20120327000560_change_preference_value_type.rb +++ /dev/null @@ -1,10 +0,0 @@ -class ChangePreferenceValueType < ActiveRecord::Migration - def up - remove_index :preferences, :name => 'index_preferences_on_owner_and_attribute_and_preference' - change_column :preferences, :value, :text - end - - def down - change_column :preferences, :value, :string - end -end diff --git a/db/migrate/20120327000561_create_billing_integrations.rb b/db/migrate/20120327000561_create_billing_integrations.rb deleted file mode 100644 index c61e2e8932..0000000000 --- a/db/migrate/20120327000561_create_billing_integrations.rb +++ /dev/null @@ -1,12 +0,0 @@ -class CreateBillingIntegrations < ActiveRecord::Migration - def change - create_table :billing_integrations do |t| - t.string :type, :name - t.text :description - t.boolean :active, :default => true - t.string :environment, :default => 'development' - - t.timestamps - end - end -end diff --git a/db/migrate/20120327000562_charge_refactoring.rb b/db/migrate/20120327000562_charge_refactoring.rb deleted file mode 100644 index fdcd31abb0..0000000000 --- a/db/migrate/20120327000562_charge_refactoring.rb +++ /dev/null @@ -1,39 +0,0 @@ -class Checkout < ActiveRecord::Base; end; - -# Hack to prevent issues with legacy migrations -class Order < ActiveRecord::Base - has_one :checkout -end - -class ChargeRefactoring < ActiveRecord::Migration - def up - # Temporarily set table name for legacy support - Spree::Adjustment.table_name = 'adjustments' - - add_column :orders, :completed_at, :timestamp - Order.reset_column_information - Order.all.each { |o| o.update_attribute(:completed_at, o.checkout && o.checkout.read_attribute(:completed_at)) } - remove_column :checkouts, :completed_at - - change_column :adjustments, :amount, :decimal, :null => true, :default => nil, :precision => 8, :scale => 2 - Spree::Adjustment.update_all :type => 'secondary_type' - Spree::Adjustment.where(:type => 'Credit').update_all(:type => 'CouponCredit') - remove_column :adjustments, :secondary_type - - # Reset table name - Spree::Adjustment.table_name = 'spree_adjustments' - end - - def down - add_column :checkouts, :completed_at, :timestamp - Spree::Checkout.reset_column_information - Spree::Checkout.all.each { |c| c.update_attribute(:completed_at, c.order && c.order.completed_at) } - remove_column :orders, :completed_at - - add_column :adjustments, :secondary_type, :string - Spree::Adjustment.update_all :secondary_type => 'type' - Spree::Adjustment.where('type LIKE ?', '%Charge').update_all(:type => 'Charge') - Spree::Adjustment.where('type LIKE ?', '%Credit').update_all(:type => 'Credit') - change_column :adjustments, :amount, :decimal, :null => false, :default => 0, :precision => 8, :scale => 2 - end -end diff --git a/db/migrate/20120327000563_add_some_indexes.rb b/db/migrate/20120327000563_add_some_indexes.rb deleted file mode 100644 index ffb8495876..0000000000 --- a/db/migrate/20120327000563_add_some_indexes.rb +++ /dev/null @@ -1,11 +0,0 @@ -class AddSomeIndexes < ActiveRecord::Migration - def change - add_index :taxons, :permalink - add_index :taxons, :parent_id - add_index :taxons, :taxonomy_id - add_index :assets, :viewable_id - add_index :assets, [:viewable_type, :type] - add_index :product_properties, :product_id - add_index :option_values_variants, [:variant_id, :option_value_id] - end -end diff --git a/db/migrate/20120327000564_checkout_state_machine.rb b/db/migrate/20120327000564_checkout_state_machine.rb deleted file mode 100644 index c80323b30e..0000000000 --- a/db/migrate/20120327000564_checkout_state_machine.rb +++ /dev/null @@ -1,5 +0,0 @@ -class CheckoutStateMachine < ActiveRecord::Migration - def change - add_column :checkouts, :state, :string - end -end diff --git a/db/migrate/20120327000565_state_for_shipments.rb b/db/migrate/20120327000565_state_for_shipments.rb deleted file mode 100644 index b7a3bc4bba..0000000000 --- a/db/migrate/20120327000565_state_for_shipments.rb +++ /dev/null @@ -1,5 +0,0 @@ -class StateForShipments < ActiveRecord::Migration - def change - add_column :shipments, :state, :string - end -end diff --git a/db/migrate/20120327000566_make_state_events_polymorphic.rb b/db/migrate/20120327000566_make_state_events_polymorphic.rb deleted file mode 100644 index ed8cef3659..0000000000 --- a/db/migrate/20120327000566_make_state_events_polymorphic.rb +++ /dev/null @@ -1,12 +0,0 @@ -class MakeStateEventsPolymorphic < ActiveRecord::Migration - def up - rename_column :state_events, :order_id, :stateful_id - add_column :state_events, :stateful_type, :string - execute "UPDATE state_events SET stateful_type = 'Order'" - end - - def down - rename_column :state_events, :stateful_id, :order_id - remove_column :state_events, :stateful_type - end -end diff --git a/db/migrate/20120327000567_ship_address_id_for_checkouts.rb b/db/migrate/20120327000567_ship_address_id_for_checkouts.rb deleted file mode 100644 index c16f4c82c0..0000000000 --- a/db/migrate/20120327000567_ship_address_id_for_checkouts.rb +++ /dev/null @@ -1,5 +0,0 @@ -class ShipAddressIdForCheckouts < ActiveRecord::Migration - def change - add_column :checkouts, :ship_address_id, :integer - end -end diff --git a/db/migrate/20120327000568_shipping_method_id_for_checkouts.rb b/db/migrate/20120327000568_shipping_method_id_for_checkouts.rb deleted file mode 100644 index 6f8edd588a..0000000000 --- a/db/migrate/20120327000568_shipping_method_id_for_checkouts.rb +++ /dev/null @@ -1,5 +0,0 @@ -class ShippingMethodIdForCheckouts < ActiveRecord::Migration - def change - add_column :checkouts, :shipping_method_id, :integer - end -end diff --git a/db/migrate/20120327000569_creditcard_last_four_digits.rb b/db/migrate/20120327000569_creditcard_last_four_digits.rb deleted file mode 100644 index 922df48f8d..0000000000 --- a/db/migrate/20120327000569_creditcard_last_four_digits.rb +++ /dev/null @@ -1,14 +0,0 @@ -class CreditcardLastFourDigits < ActiveRecord::Migration - def up - rename_column :creditcards, :display_number, :last_digits - - creditcards = select_all "SELECT * FROM creditcards" - creditcards.each do |card| - execute "UPDATE creditcards SET last_digits = '#{card['last_digits'].gsub('XXXX-XXXX-XXXX-', '')}' WHERE id = #{card['id']}" if card['last_digits'].present? - end - end - - def down - rename_column :creditcards, :last_digits, :display_number - end -end diff --git a/db/migrate/20120327000570_populate_legacy_shipment_state.rb b/db/migrate/20120327000570_populate_legacy_shipment_state.rb deleted file mode 100644 index 2008e38817..0000000000 --- a/db/migrate/20120327000570_populate_legacy_shipment_state.rb +++ /dev/null @@ -1,15 +0,0 @@ -class PopulateLegacyShipmentState < ActiveRecord::Migration - def up - shipments = select_all "SELECT * FROM shipments" - shipments.each do |shipment| - if shipment['shipped_at'] - execute "UPDATE shipments SET state = 'shipped'" - else - execute "UPDATE shipments SET state = 'pending'" - end - end - end - - def down - end -end diff --git a/db/migrate/20120327000571_add_cost_price.rb b/db/migrate/20120327000571_add_cost_price.rb deleted file mode 100644 index 81dc8d25cb..0000000000 --- a/db/migrate/20120327000571_add_cost_price.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddCostPrice < ActiveRecord::Migration - def change - add_column :variants, :cost_price, :decimal, :null => true, :default => nil, :precision => 8, :scale => 2 - end -end diff --git a/db/migrate/20120327000572_shipment_id_for_inventory_units.rb b/db/migrate/20120327000572_shipment_id_for_inventory_units.rb deleted file mode 100644 index 93aec53f7e..0000000000 --- a/db/migrate/20120327000572_shipment_id_for_inventory_units.rb +++ /dev/null @@ -1,25 +0,0 @@ -class ShipmentIdForInventoryUnits < ActiveRecord::Migration - def up - add_column :inventory_units, :shipment_id, :integer - add_index :inventory_units, :shipment_id - - # migrate legacy shipments - Spree::Shipment.table_name = 'shipments' - - Spree::Shipment.all.each do |shipment| - unless shipment.order - puts "Warning: shipment has invalid order - #{shipment.id}" - next - end - shipment.order.inventory_units.each do |unit| - unit.update_attribute('shipment_id', shipment.id) - end - end - - Spree::Shipment.table_name = 'spree_shipments' - end - - def down - remove_column :inventory_units, :shipment_id - end -end diff --git a/db/migrate/20120327000573_cim_fields_for_creditcards.rb b/db/migrate/20120327000573_cim_fields_for_creditcards.rb deleted file mode 100644 index 417a9613c0..0000000000 --- a/db/migrate/20120327000573_cim_fields_for_creditcards.rb +++ /dev/null @@ -1,6 +0,0 @@ -class CimFieldsForCreditcards < ActiveRecord::Migration - def change - add_column :creditcards, :gateway_customer_profile_id, :string - add_column :creditcards, :gateway_payment_profile_id, :string - end -end diff --git a/db/migrate/20120327000574_create_return_authorizations.rb b/db/migrate/20120327000574_create_return_authorizations.rb deleted file mode 100644 index bb9fed3e00..0000000000 --- a/db/migrate/20120327000574_create_return_authorizations.rb +++ /dev/null @@ -1,12 +0,0 @@ -class CreateReturnAuthorizations < ActiveRecord::Migration - def change - create_table :return_authorizations do |t| - t.string :number, :state - t.decimal :amount, :precision => 8, :scale => 2, :default => 0.0, :null => false - t.references :order - t.text :reason - - t.timestamps - end - end -end diff --git a/db/migrate/20120327000575_add_return_authorization_to_inventory_units.rb b/db/migrate/20120327000575_add_return_authorization_to_inventory_units.rb deleted file mode 100644 index 49a55bc026..0000000000 --- a/db/migrate/20120327000575_add_return_authorization_to_inventory_units.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddReturnAuthorizationToInventoryUnits < ActiveRecord::Migration - def change - add_column :inventory_units, :return_authorization_id, :integer - end -end diff --git a/db/migrate/20120327000576_create_trackers.rb b/db/migrate/20120327000576_create_trackers.rb deleted file mode 100644 index e4e216213b..0000000000 --- a/db/migrate/20120327000576_create_trackers.rb +++ /dev/null @@ -1,10 +0,0 @@ -class CreateTrackers < ActiveRecord::Migration - def change - create_table :trackers do |t| - t.string :environment, :analytics_id - t.boolean :active, :default => true - - t.timestamps - end - end -end diff --git a/db/migrate/20120327000577_creditcard_id_for_creditcard_txns.rb b/db/migrate/20120327000577_creditcard_id_for_creditcard_txns.rb deleted file mode 100644 index 7190e0e711..0000000000 --- a/db/migrate/20120327000577_creditcard_id_for_creditcard_txns.rb +++ /dev/null @@ -1,5 +0,0 @@ -class CreditcardIdForCreditcardTxns < ActiveRecord::Migration - def change - add_column :creditcard_txns, :creditcard_id, :integer - end -end diff --git a/db/migrate/20120327000578_original_creditcard_txn_id_for_creditcard_txns.rb b/db/migrate/20120327000578_original_creditcard_txn_id_for_creditcard_txns.rb deleted file mode 100644 index 54160feac4..0000000000 --- a/db/migrate/20120327000578_original_creditcard_txn_id_for_creditcard_txns.rb +++ /dev/null @@ -1,5 +0,0 @@ -class OriginalCreditcardTxnIdForCreditcardTxns < ActiveRecord::Migration - def change - add_column :creditcard_txns, :original_creditcard_txn_id, :integer - end -end diff --git a/db/migrate/20120327000579_add_test_mode_to_billing_integration.rb b/db/migrate/20120327000579_add_test_mode_to_billing_integration.rb deleted file mode 100644 index aa1be7912b..0000000000 --- a/db/migrate/20120327000579_add_test_mode_to_billing_integration.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddTestModeToBillingIntegration < ActiveRecord::Migration - def change - add_column :billing_integrations, :test_mode, :boolean, :default => true - add_column :billing_integrations, :server, :string, :default => 'test' - end -end diff --git a/db/migrate/20120327000580_create_products_product_groups.rb b/db/migrate/20120327000580_create_products_product_groups.rb deleted file mode 100644 index aaa6533732..0000000000 --- a/db/migrate/20120327000580_create_products_product_groups.rb +++ /dev/null @@ -1,8 +0,0 @@ -class CreateProductsProductGroups < ActiveRecord::Migration - def change - create_table :product_groups_products, :id => false do |t| - t.references :product - t.references :product_group - end - end -end diff --git a/db/migrate/20120327000581_create_payment_methods.rb b/db/migrate/20120327000581_create_payment_methods.rb deleted file mode 100644 index 41145056e7..0000000000 --- a/db/migrate/20120327000581_create_payment_methods.rb +++ /dev/null @@ -1,16 +0,0 @@ -class CreatePaymentMethods < ActiveRecord::Migration - def change - create_table :payment_methods do |t| - t.string :type, :name - t.text :description - t.boolean :active, :default => true - t.string :environment, :default => 'development' - - t.timestamps - end - # TODO - also migrate any legacy configurations for gateways and billing integrations before dropping the old tables - # we probably also need to do this inside the payment_gateway extension b/c table won't exist yet in fresh bootstrap - #drop_table :billing_integrations - #drop_table :gateways - end -end diff --git a/db/migrate/20120327000582_polymorphic_payments.rb b/db/migrate/20120327000582_polymorphic_payments.rb deleted file mode 100644 index d598e48757..0000000000 --- a/db/migrate/20120327000582_polymorphic_payments.rb +++ /dev/null @@ -1,43 +0,0 @@ -# Legacy table support -class Checkout < ActiveRecord::Base; end; -class Spree::Creditcard < ActiveRecord::Base; end; - -class PolymorphicPayments < ActiveRecord::Migration - def up - remove_column :payments, :type - remove_column :payments, :creditcard_id - rename_column :payments, :order_id, :payable_id - change_table :payments do |t| - t.string :payable_type, :payment_method - t.references :source, :polymorphic => true - end - execute "UPDATE payments SET payable_type = 'Order'" - - Spree::Creditcard.table_name = 'creditcards' - - Spree::Creditcard.all.each do |creditcard| - if checkout = Checkout.find_by(id: creditcard.checkout_id) and checkout.order - if payment = checkout.order.payments.first - execute "UPDATE payments SET source_type = 'Creditcard', source_id = #{creditcard.id} WHERE id = #{payment.id}" - end - end - end - - Spree::Creditcard.table_name = 'spree_creditcards' - - remove_column :creditcards, :checkout_id - end - - def down - add_column :creditcards, :checkout_id, :integer - change_table :payments do |t| - t.remove :payable_type - t.remove :payment_method - t.remove :source_id - t.remove :source_type - end - rename_column :payments, :payable_id, :order_id - add_column :payments, :creditcard_id, :integer - add_column :payments, :type, :string - end -end diff --git a/db/migrate/20120327000583_change_payments_payment_method_to_belongs_to.rb b/db/migrate/20120327000583_change_payments_payment_method_to_belongs_to.rb deleted file mode 100644 index 456dace6e2..0000000000 --- a/db/migrate/20120327000583_change_payments_payment_method_to_belongs_to.rb +++ /dev/null @@ -1,11 +0,0 @@ -class ChangePaymentsPaymentMethodToBelongsTo < ActiveRecord::Migration - def up - remove_column :payments, :payment_method - add_column :payments, :payment_method_id, :integer - end - - def down - add_column :payments, :payment_method, :string - remove_column :payments, :payment_method_id - end -end diff --git a/db/migrate/20120327000584_assign_creditcard_txns_to_payment.rb b/db/migrate/20120327000584_assign_creditcard_txns_to_payment.rb deleted file mode 100644 index e3c6850856..0000000000 --- a/db/migrate/20120327000584_assign_creditcard_txns_to_payment.rb +++ /dev/null @@ -1,23 +0,0 @@ -class AssignCreditcardTxnsToPayment < ActiveRecord::Migration - def up - add_column :creditcard_txns, :payment_id, :integer - - # Temporarily set back to creditcards - Spree::Creditcard.table_name = 'creditcards' - - ActiveRecord::Base.connection.select_all('SELECT * FROM creditcard_txns').each do |txn_attrs| - if creditcard = Spree::Creditcard.find_by(id: txn_attrs['creditcard_id']) and creditcard.payments.first - execute "UPDATE creditcard_txns SET payment_id = #{creditcard.payments.first.id} WHERE id = #{txn_attrs['id']}" - end - end - - Spree::Creditcard.table_name = 'spree_creditcards' - - remove_column :creditcard_txns, :creditcard_payment_id - end - - def down - remove_column :creditcard_txns, :payment_id - add_column :creditcard_txns, :creditcard_payment_id, :integer - end -end diff --git a/db/migrate/20120327000585_sti_for_transactions.rb b/db/migrate/20120327000585_sti_for_transactions.rb deleted file mode 100644 index 5d44f725e9..0000000000 --- a/db/migrate/20120327000585_sti_for_transactions.rb +++ /dev/null @@ -1,15 +0,0 @@ -class StiForTransactions < ActiveRecord::Migration - def up - rename_table :creditcard_txns, :transactions - add_column :transactions, :type, :string - remove_column :transactions, :creditcard_id - - execute "UPDATE transactions SET type = 'CreditcardTxn'" - end - - def down - rename_table :transactions, :creditcard_txns - remove_column :transactions, :type - add_column :transactions, :creditcard_id, :integer - end -end diff --git a/db/migrate/20120327000586_drop_billing_integrations.rb b/db/migrate/20120327000586_drop_billing_integrations.rb deleted file mode 100644 index 362a4f6904..0000000000 --- a/db/migrate/20120327000586_drop_billing_integrations.rb +++ /dev/null @@ -1,16 +0,0 @@ -class DropBillingIntegrations < ActiveRecord::Migration - def up - drop_table :billing_integrations - end - - def down - create_table :billing_integrations do |t| - t.string :type, :name - t.text :description - t.boolean :active, :default => true - t.string :environment, :default => 'development' - - t.timestamps - end - end -end diff --git a/db/migrate/20120327000587_deleted_at_for_payment_methods.rb b/db/migrate/20120327000587_deleted_at_for_payment_methods.rb deleted file mode 100644 index 6283733f58..0000000000 --- a/db/migrate/20120327000587_deleted_at_for_payment_methods.rb +++ /dev/null @@ -1,14 +0,0 @@ -class DeletedAtForPaymentMethods < ActiveRecord::Migration - def up - change_table :payment_methods do |t| - t.timestamp :deleted_at, :default => nil - end - end - - def down - remove_column :payments_methods, :column_name - change_table :payment_methods do |t| - t.remove :deleted_at - end - end -end \ No newline at end of file diff --git a/db/migrate/20120327000588_add_adjustments_index.rb b/db/migrate/20120327000588_add_adjustments_index.rb deleted file mode 100644 index 559766d9bd..0000000000 --- a/db/migrate/20120327000588_add_adjustments_index.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddAdjustmentsIndex < ActiveRecord::Migration - def change - add_index :adjustments, :order_id - end -end - diff --git a/db/migrate/20120327000589_fix_by_popularity.rb b/db/migrate/20120327000589_fix_by_popularity.rb deleted file mode 100644 index 756b725bbe..0000000000 --- a/db/migrate/20120327000589_fix_by_popularity.rb +++ /dev/null @@ -1,9 +0,0 @@ -class FixByPopularity < ActiveRecord::Migration - def up - execute("UPDATE product_scopes SET name='descend_by_popularity' WHERE name='by_popularity'") - end - - def down - execute("UPDATE product_scopes SET name='by_popularity' WHERE name='descend_by_popularity'") - end -end diff --git a/db/migrate/20120327000590_add_alt_text_to_images.rb b/db/migrate/20120327000590_add_alt_text_to_images.rb deleted file mode 100644 index 69b9ce2e72..0000000000 --- a/db/migrate/20120327000590_add_alt_text_to_images.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddAltTextToImages < ActiveRecord::Migration - def change - add_column :assets, :alt, :text - end -end diff --git a/db/migrate/20120327000591_fix_existing_coupon_credits.rb b/db/migrate/20120327000591_fix_existing_coupon_credits.rb deleted file mode 100644 index 1f04087051..0000000000 --- a/db/migrate/20120327000591_fix_existing_coupon_credits.rb +++ /dev/null @@ -1,13 +0,0 @@ -class Adjustment < ActiveRecord::Base; end; - -class FixExistingCouponCredits < ActiveRecord::Migration - def up - execute("UPDATE adjustments SET type='PromotionCredit' WHERE type='CouponCredit'") - execute("UPDATE adjustments SET adjustment_source_type='Promotion' WHERE adjustment_source_type='Coupon'") - end - - def down - execute("UPDATE adjustments SET adjustment_source_type='Coupon' WHERE adjustment_source_type='Promotion'") - execute("UPDATE adjustments SET type='CouponCredit' WHERE type='PromotionCredit'") - end -end diff --git a/db/migrate/20120327000592_add_display_to_payment_methods.rb b/db/migrate/20120327000592_add_display_to_payment_methods.rb deleted file mode 100644 index a7097add2f..0000000000 --- a/db/migrate/20120327000592_add_display_to_payment_methods.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddDisplayToPaymentMethods < ActiveRecord::Migration - def change - add_column :payment_methods, :display, :string, :default => nil - end -end diff --git a/db/migrate/20120327000593_add_addresses_checkouts_indexes.rb b/db/migrate/20120327000593_add_addresses_checkouts_indexes.rb deleted file mode 100644 index 4a1c460bae..0000000000 --- a/db/migrate/20120327000593_add_addresses_checkouts_indexes.rb +++ /dev/null @@ -1,8 +0,0 @@ -class AddAddressesCheckoutsIndexes < ActiveRecord::Migration - def change - add_index :addresses, :firstname - add_index :addresses, :lastname - add_index :checkouts, :order_id - add_index :checkouts, :bill_address_id - end -end diff --git a/db/migrate/20120327000594_add_icon_to_taxons.rb b/db/migrate/20120327000594_add_icon_to_taxons.rb deleted file mode 100644 index 625c253779..0000000000 --- a/db/migrate/20120327000594_add_icon_to_taxons.rb +++ /dev/null @@ -1,17 +0,0 @@ -class AddIconToTaxons < ActiveRecord::Migration - def up - # skip this migration if the attribute already exists because of advanced taxon extension - return if column_exists?(:taxons, :icon_file_name) - add_column :taxons, :icon_file_name, :string - add_column :taxons, :icon_content_type, :string - add_column :taxons, :icon_file_size, :integer - add_column :taxons, :icon_updated_at, :datetime - end - - def down - remove_column :taxons, :icon_file_name - remove_column :taxons, :icon_content_type - remove_column :taxons, :icon_file_size - remove_column :taxons, :icon_updated_at - end -end diff --git a/db/migrate/20120327000595_add_description_to_taxons.rb b/db/migrate/20120327000595_add_description_to_taxons.rb deleted file mode 100644 index 287daad048..0000000000 --- a/db/migrate/20120327000595_add_description_to_taxons.rb +++ /dev/null @@ -1,11 +0,0 @@ -class AddDescriptionToTaxons < ActiveRecord::Migration - def up - # skip this migration if the attribute already exists because of advanced taxon extension - return if column_exists?(:taxons, :description) - add_column :taxons, :description, :text - end - - def down - remove_column :taxons, :description - end -end diff --git a/db/migrate/20120327000596_index_for_shipments_number.rb b/db/migrate/20120327000596_index_for_shipments_number.rb deleted file mode 100644 index c1a85d1d23..0000000000 --- a/db/migrate/20120327000596_index_for_shipments_number.rb +++ /dev/null @@ -1,5 +0,0 @@ -class IndexForShipmentsNumber < ActiveRecord::Migration - def change - add_index :shipments, :number - end -end diff --git a/db/migrate/20120327000597_add_index_on_users_persistence_token.rb b/db/migrate/20120327000597_add_index_on_users_persistence_token.rb deleted file mode 100644 index 9b4d65cb63..0000000000 --- a/db/migrate/20120327000597_add_index_on_users_persistence_token.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddIndexOnUsersPersistenceToken < ActiveRecord::Migration - def change - add_index :users, :persistence_token - end -end diff --git a/db/migrate/20120327000598_add_default_to_tax_categories.rb b/db/migrate/20120327000598_add_default_to_tax_categories.rb deleted file mode 100644 index 9845b90449..0000000000 --- a/db/migrate/20120327000598_add_default_to_tax_categories.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddDefaultToTaxCategories < ActiveRecord::Migration - def change - add_column :tax_categories, :is_default, :boolean, :default => false - end -end diff --git a/db/migrate/20120327000599_add_display_to_shipping_methods.rb b/db/migrate/20120327000599_add_display_to_shipping_methods.rb deleted file mode 100644 index ba3aa011ac..0000000000 --- a/db/migrate/20120327000599_add_display_to_shipping_methods.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddDisplayToShippingMethods < ActiveRecord::Migration - def change - add_column :shipping_methods, :display_on, :string, :default => nil - end -end diff --git a/db/migrate/20120327000600_rename_payment_method_display.rb b/db/migrate/20120327000600_rename_payment_method_display.rb deleted file mode 100644 index 1cc727bf9f..0000000000 --- a/db/migrate/20120327000600_rename_payment_method_display.rb +++ /dev/null @@ -1,5 +0,0 @@ -class RenamePaymentMethodDisplay < ActiveRecord::Migration - def change - rename_column :payment_methods, :display, :display_on - end -end diff --git a/db/migrate/20120327000601_rename_preferences_field.rb b/db/migrate/20120327000601_rename_preferences_field.rb deleted file mode 100644 index 19d67680c1..0000000000 --- a/db/migrate/20120327000601_rename_preferences_field.rb +++ /dev/null @@ -1,5 +0,0 @@ -class RenamePreferencesField < ActiveRecord::Migration - def change - rename_column :preferences, :attribute, :name - end -end diff --git a/db/migrate/20120327000602_add_guest_flag.rb b/db/migrate/20120327000602_add_guest_flag.rb deleted file mode 100644 index ec8cbf1156..0000000000 --- a/db/migrate/20120327000602_add_guest_flag.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddGuestFlag < ActiveRecord::Migration - def change - add_column :users, :guest, :boolean - end -end diff --git a/db/migrate/20120327000603_drop_order_token.rb b/db/migrate/20120327000603_drop_order_token.rb deleted file mode 100644 index 5738228ac0..0000000000 --- a/db/migrate/20120327000603_drop_order_token.rb +++ /dev/null @@ -1,9 +0,0 @@ -class DropOrderToken < ActiveRecord::Migration - def up - remove_column :orders, :token - end - - def down - add_column :orders, :token, :string - end -end diff --git a/db/migrate/20120327000604_payments_state_and_assigned_to_order_only.rb b/db/migrate/20120327000604_payments_state_and_assigned_to_order_only.rb deleted file mode 100644 index 69ee291859..0000000000 --- a/db/migrate/20120327000604_payments_state_and_assigned_to_order_only.rb +++ /dev/null @@ -1,14 +0,0 @@ -class PaymentsStateAndAssignedToOrderOnly < ActiveRecord::Migration - def up - # TODO: migrate existing payments - rename_column :payments, :payable_id, :order_id - remove_column :payments, :payable_type - add_column :payments, :state, :string - end - - def down - remove_column :payments, :state - add_column :payments, :payable_type, :string - rename_column :payments, :order_id, :payable_id - end -end diff --git a/db/migrate/20120327000605_create_address_keys_for_order.rb b/db/migrate/20120327000605_create_address_keys_for_order.rb deleted file mode 100644 index ee794c3e50..0000000000 --- a/db/migrate/20120327000605_create_address_keys_for_order.rb +++ /dev/null @@ -1,6 +0,0 @@ -class CreateAddressKeysForOrder < ActiveRecord::Migration - def change - add_column :orders, :bill_address_id, :integer - add_column :orders, :ship_address_id, :integer - end -end \ No newline at end of file diff --git a/db/migrate/20120327000606_payment_total_for_orders.rb b/db/migrate/20120327000606_payment_total_for_orders.rb deleted file mode 100644 index 9190e090af..0000000000 --- a/db/migrate/20120327000606_payment_total_for_orders.rb +++ /dev/null @@ -1,5 +0,0 @@ -class PaymentTotalForOrders < ActiveRecord::Migration - def change - add_column :orders, :payment_total, :decimal, :precision => 8, :scale => 2, :default => 0.0 - end -end diff --git a/db/migrate/20120327000607_shipping_method_id_for_orders.rb b/db/migrate/20120327000607_shipping_method_id_for_orders.rb deleted file mode 100644 index ec0bafb1be..0000000000 --- a/db/migrate/20120327000607_shipping_method_id_for_orders.rb +++ /dev/null @@ -1,5 +0,0 @@ -class ShippingMethodIdForOrders < ActiveRecord::Migration - def change - add_column :orders, :shipping_method_id, :integer - end -end diff --git a/db/migrate/20120327000608_add_shipment_and_payment_state.rb b/db/migrate/20120327000608_add_shipment_and_payment_state.rb deleted file mode 100644 index 240dc95776..0000000000 --- a/db/migrate/20120327000608_add_shipment_and_payment_state.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddShipmentAndPaymentState < ActiveRecord::Migration - def change - add_column :orders, :shipment_state, :string - add_column :orders, :payment_state, :string - end -end \ No newline at end of file diff --git a/db/migrate/20120327000609_refactor_adjustments.rb b/db/migrate/20120327000609_refactor_adjustments.rb deleted file mode 100644 index 77e01fc904..0000000000 --- a/db/migrate/20120327000609_refactor_adjustments.rb +++ /dev/null @@ -1,29 +0,0 @@ -class RefactorAdjustments < ActiveRecord::Migration - def up - change_table :adjustments do |t| - t.boolean :mandatory - t.boolean :frozen - t.rename :adjustment_source_id, :source_id - t.rename :adjustment_source_type, :source_type - t.references :originator - t.string :originator_type - t.remove :type - t.rename :description, :label - t.remove :position - end - end - - def down - change_table :adjustments do |t| - t.integer :position - t.rename :label, :description - t.string :type - t.remove :originator_type - t.remove :originator_id - t.rename :source_type, :adjustment_source_type - t.rename :source_id, :adjustment_source_id - t.remove :frozen - t.remove :mandatory - end - end -end diff --git a/db/migrate/20120327000610_response_code_and_avs_response_for_payments.rb b/db/migrate/20120327000610_response_code_and_avs_response_for_payments.rb deleted file mode 100644 index cc0f6c4164..0000000000 --- a/db/migrate/20120327000610_response_code_and_avs_response_for_payments.rb +++ /dev/null @@ -1,6 +0,0 @@ -class ResponseCodeAndAvsResponseForPayments < ActiveRecord::Migration - def change - add_column :payments, :response_code, :string - add_column :payments, :avs_response, :string - end -end diff --git a/db/migrate/20120327000611_change_guest_flag_to_anonymous.rb b/db/migrate/20120327000611_change_guest_flag_to_anonymous.rb deleted file mode 100644 index ca8ae7a3f7..0000000000 --- a/db/migrate/20120327000611_change_guest_flag_to_anonymous.rb +++ /dev/null @@ -1,5 +0,0 @@ -class ChangeGuestFlagToAnonymous < ActiveRecord::Migration - def change - rename_column :users, :guest, :anonymous - end -end diff --git a/db/migrate/20120327000612_email_for_orders.rb b/db/migrate/20120327000612_email_for_orders.rb deleted file mode 100644 index f766dca878..0000000000 --- a/db/migrate/20120327000612_email_for_orders.rb +++ /dev/null @@ -1,5 +0,0 @@ -class EmailForOrders < ActiveRecord::Migration - def change - add_column :orders, :email, :string - end -end diff --git a/db/migrate/20120327000613_create_mail_methods.rb b/db/migrate/20120327000613_create_mail_methods.rb deleted file mode 100644 index 0860607aa7..0000000000 --- a/db/migrate/20120327000613_create_mail_methods.rb +++ /dev/null @@ -1,10 +0,0 @@ -class CreateMailMethods < ActiveRecord::Migration - def change - create_table :mail_methods do |t| - t.string :environment - t.boolean :active, :default => true - - t.timestamps - end - end -end diff --git a/db/migrate/20120327000614_rename_frozen_to_locked.rb b/db/migrate/20120327000614_rename_frozen_to_locked.rb deleted file mode 100644 index fef534ab16..0000000000 --- a/db/migrate/20120327000614_rename_frozen_to_locked.rb +++ /dev/null @@ -1,5 +0,0 @@ -class RenameFrozenToLocked < ActiveRecord::Migration - def change - rename_column :adjustments, :frozen, :locked - end -end diff --git a/db/migrate/20120327000615_move_special_instructions_to_orders.rb b/db/migrate/20120327000615_move_special_instructions_to_orders.rb deleted file mode 100644 index 4d6b1f4aba..0000000000 --- a/db/migrate/20120327000615_move_special_instructions_to_orders.rb +++ /dev/null @@ -1,10 +0,0 @@ -class MoveSpecialInstructionsToOrders < ActiveRecord::Migration - def up - add_column :orders, :special_instructions, :text - execute "UPDATE orders SET special_instructions = (SELECT special_instructions FROM checkouts WHERE order_id = orders.id)" - end - - def down - remove_column :orders, :special_instructions, :text - end -end diff --git a/db/migrate/20120327000616_create_log_entries.rb b/db/migrate/20120327000616_create_log_entries.rb deleted file mode 100644 index 8a0d7f8d8a..0000000000 --- a/db/migrate/20120327000616_create_log_entries.rb +++ /dev/null @@ -1,11 +0,0 @@ -class CreateLogEntries < ActiveRecord::Migration - def change - create_table :log_entries do |t| - t.integer :source_id - t.string :source_type - t.text :details - - t.timestamps - end - end -end diff --git a/db/migrate/20120327000617_migrate_transactions_to_payment_state.rb b/db/migrate/20120327000617_migrate_transactions_to_payment_state.rb deleted file mode 100644 index 185953157b..0000000000 --- a/db/migrate/20120327000617_migrate_transactions_to_payment_state.rb +++ /dev/null @@ -1,98 +0,0 @@ -class Transaction < ActiveRecord::Base; end -class CreditcardTxn < Transaction; end - -class MigrateTransactionsToPaymentState < ActiveRecord::Migration - - AUTHORIZED=1 - COMPLETED=2 - PURCHASED=3 - VOIDED = 4 - CREDITED =5 - - PAYMENT_COMPLETE = 'completed' - PAYMENT_VOID = 'void' - PAYMENT_PENDING = 'pending' - - # Temporarily set the table back to payments - Spree::Payment.table_name = 'payments' - - def up - migrate_authorized_only_transactions - migrate_voided_transactions - migrate_completed_transactions - migrate_purchased_transactions - migrate_credited_transactions - - Spree::Payment.table_name = 'spree_payments' - end - - def migrate_credited_transactions - credited = Transaction.find_by_sql("SELECT * FROM transactions WHERE txn_type = #{CREDITED}") - credited.each do |tx| - payment = Spree::Payment.find(tx) - order = payment.order - order.create_payment( - :amount => tx.amount, - :source_id => payment.source_id, :source_type => 'Creditcard', - :payment_method_id => payment.payment_method_id, :state => PAYMENT_COMPLETE, - :avs_response => tx.avs_response, :response_code => tx.response_code - ) - end - credited.each { |rec| rec.destroy } - end - - def migrate_voided_transactions - voided = Transaction.find_by_sql("SELECT * FROM transactions WHERE txn_type = #{VOIDED}") - voided.each do |tx| - update_payment(tx, PAYMENT_VOID) - end - unless voided.empty? - all_but_credited = [AUTHORIZED, COMPLETED, PURCHASED, VOIDED] - voided_and_subsequent_transactions = Transaction.find_by_sql("SELECT * FROM transactions WHERE payment_id IN (#{voided.map(&:payment_id).join(',')}) AND txn_type IN (#{all_but_credited.join(',')})") - voided_and_subsequent_transactions.each { |rec| rec.destroy } - end - end - - def migrate_purchased_transactions - migrate_transactions(PURCHASED) - end - - def migrate_completed_transactions - migrate_transactions(COMPLETED) - end - - def migrate_transactions(type) - txs = Transaction.find_by_sql("SELECT * FROM transactions WHERE txn_type = #{type}") - txs.each do |tx| - update_payment(tx, PAYMENT_COMPLETE) - end - txs.each { |rec| rec.destroy } - end - - def migrate_authorized_only_transactions - if (ActiveRecord::Base.connection.adapter_name == 'PostgreSQL') - group_by_clause = 'GROUP BY transactions.' + Transaction.column_names.join(', transactions.') - else - group_by_clause = 'GROUP BY payment_id' - end - authorized_only = Transaction.find_by_sql("SELECT * FROM transactions #{group_by_clause} HAVING COUNT(payment_id) = 1 AND txn_type = #{AUTHORIZED}") - authorized_only.each do |tx| - update_payment(tx, PAYMENT_PENDING) - end - authorized_only.each { |rec| rec.destroy } - end - - def update_payment(tx, state) - payment = Spree::Payment.find(tx.payment_id) - payment.update_attributes_without_callbacks({ - :state => state, - :source_type => 'Creditcard', - :amount => tx.amount, - :response_code => tx.response_code, - :avs_response => tx.avs_response - }) - end - - def down - end -end diff --git a/db/migrate/20120327000618_delete_in_progress_orders.rb b/db/migrate/20120327000618_delete_in_progress_orders.rb deleted file mode 100644 index 3a32449b9c..0000000000 --- a/db/migrate/20120327000618_delete_in_progress_orders.rb +++ /dev/null @@ -1,19 +0,0 @@ -class DeleteInProgressOrders < ActiveRecord::Migration - def up - execute("DELETE FROM orders WHERE orders.state = 'in_progress'") - delete_orphans('adjustments') - delete_orphans('checkouts') - delete_orphans('shipments') - delete_orphans('payments') - delete_orphans('line_items') - delete_orphans('inventory_units') - end - - def down - end - - private - def delete_orphans(table_name) - execute "DELETE FROM #{table_name} WHERE order_id NOT IN (SELECT id FROM orders)" - end -end diff --git a/db/migrate/20120327000619_migrate_checkout_to_orders.rb b/db/migrate/20120327000619_migrate_checkout_to_orders.rb deleted file mode 100644 index 16963fa046..0000000000 --- a/db/migrate/20120327000619_migrate_checkout_to_orders.rb +++ /dev/null @@ -1,23 +0,0 @@ -class MigrateCheckoutToOrders < ActiveRecord::Migration - def up - orders = select_all "SELECT * FROM orders" - - orders.each do |order| - checkout = update_order(order) - execute "DELETE FROM checkouts WHERE id = #{checkout['id']}" if checkout - end - end - - def down - end - - private - def update_order(order) - checkout = select_one "SELECT * FROM checkouts WHERE order_id = #{order['id']}" - - if checkout - execute "UPDATE orders SET email='#{checkout['email']}', bill_address_id = #{checkout['bill_address_id']}, ship_address_id = #{checkout['ship_address_id']} WHERE id = #{checkout['id']}" - end - checkout - end -end diff --git a/db/migrate/20120327000620_remove_shipped_state.rb b/db/migrate/20120327000620_remove_shipped_state.rb deleted file mode 100644 index 2da2eee433..0000000000 --- a/db/migrate/20120327000620_remove_shipped_state.rb +++ /dev/null @@ -1,12 +0,0 @@ -class RemoveShippedState < ActiveRecord::Migration - def up - execute "UPDATE orders SET state = 'complete' WHERE state = 'shipped'" - shipments = select_all "SELECT shipments.id FROM shipments WHERE order_id IN (SELECT orders.id FROM orders WHERE orders.state = 'shipped')" - shipments.each do |shipment| - execute "UPDATE shipments SET state='shipped' WHERE id = #{shipment[:id]}" - end - end - - def down - end -end diff --git a/db/migrate/20120327000621_prevent_nil_payment_total.rb b/db/migrate/20120327000621_prevent_nil_payment_total.rb deleted file mode 100644 index 101a26dc1b..0000000000 --- a/db/migrate/20120327000621_prevent_nil_payment_total.rb +++ /dev/null @@ -1,8 +0,0 @@ -class PreventNilPaymentTotal < ActiveRecord::Migration - def up - execute "UPDATE orders SET payment_total = 0.0 WHERE payment_total IS NULL" - end - - def down - end -end diff --git a/db/migrate/20120327000622_prevent_nil_email.rb b/db/migrate/20120327000622_prevent_nil_email.rb deleted file mode 100644 index 6bb09984c2..0000000000 --- a/db/migrate/20120327000622_prevent_nil_email.rb +++ /dev/null @@ -1,9 +0,0 @@ -class PreventNilEmail < ActiveRecord::Migration - def up - execute "UPDATE orders SET email = 'guest@example.com' WHERE email IS NULL" - execute "UPDATE orders SET email = 'guest@example.com' WHERE email = ''" - end - - def down - end -end diff --git a/db/migrate/20120327000623_generate_anonymous_users.rb b/db/migrate/20120327000623_generate_anonymous_users.rb deleted file mode 100644 index 47509d8778..0000000000 --- a/db/migrate/20120327000623_generate_anonymous_users.rb +++ /dev/null @@ -1,20 +0,0 @@ -class GenerateAnonymousUsers < ActiveRecord::Migration - def up - Spree::User.table_name = 'users' - Spree::Order.table_name = 'orders' - - Spree::User.reset_column_information - Spree::Order.where(:user_id => nil).each do |order| - user = Spree::User.anonymous! - user.email ||= order.email - order.user = user - order.save! - end - - Spree::User.table_name = 'spree_users' - Spree::Order.table_name = 'spree_orders' - end - - def down - end -end diff --git a/db/migrate/20120327000624_update_order_state.rb b/db/migrate/20120327000624_update_order_state.rb deleted file mode 100644 index 174adbc565..0000000000 --- a/db/migrate/20120327000624_update_order_state.rb +++ /dev/null @@ -1,12 +0,0 @@ -class UpdateOrderState < ActiveRecord::Migration - def up - Spree::Order.table_name = 'orders' - - Spree::Order.all.map(&:update!) - - Spree::Order.table_name = 'spree_orders' - end - - def down - end -end diff --git a/db/migrate/20120327000625_cleanup_legacy_tables.rb b/db/migrate/20120327000625_cleanup_legacy_tables.rb deleted file mode 100644 index 7979409209..0000000000 --- a/db/migrate/20120327000625_cleanup_legacy_tables.rb +++ /dev/null @@ -1,11 +0,0 @@ -class CleanupLegacyTables < ActiveRecord::Migration - def up - drop_table :checkouts - drop_table :transactions - drop_table :open_id_authentication_associations - drop_table :open_id_authentication_nonces - end - - def down - end -end diff --git a/db/migrate/20120327000626_remove_number_and_cvv_from_credicard.rb b/db/migrate/20120327000626_remove_number_and_cvv_from_credicard.rb deleted file mode 100644 index 9bfcf2bd7d..0000000000 --- a/db/migrate/20120327000626_remove_number_and_cvv_from_credicard.rb +++ /dev/null @@ -1,11 +0,0 @@ -class RemoveNumberAndCvvFromCredicard < ActiveRecord::Migration - def up - remove_column :creditcards, :number - remove_column :creditcards, :verification_value - end - - def down - add_column :creditcards, :verification_value, :text - add_column :creditcards, :number, :text - end -end diff --git a/db/migrate/20120327000627_drop_anonymous_field_for_user.rb b/db/migrate/20120327000627_drop_anonymous_field_for_user.rb deleted file mode 100644 index 6aadea72ff..0000000000 --- a/db/migrate/20120327000627_drop_anonymous_field_for_user.rb +++ /dev/null @@ -1,9 +0,0 @@ -class DropAnonymousFieldForUser < ActiveRecord::Migration - def up - remove_column :users, :anonymous - end - - def down - add_column :users, :anonymous, :boolean - end -end diff --git a/db/migrate/20120327000628_renamed_rma_cancelled_state.rb b/db/migrate/20120327000628_renamed_rma_cancelled_state.rb deleted file mode 100644 index 1675568cf2..0000000000 --- a/db/migrate/20120327000628_renamed_rma_cancelled_state.rb +++ /dev/null @@ -1,9 +0,0 @@ -class RenamedRmaCancelledState < ActiveRecord::Migration - def up - execute "UPDATE return_authorizations SET state = 'canceled' WHERE state = 'cancelled'" - end - - def down - execute "UPDATE return_authorizations SET state = 'cancelled' WHERE state = 'canceled'" - end -end diff --git a/db/migrate/20120327000629_fix_problematic_index_names.rb b/db/migrate/20120327000629_fix_problematic_index_names.rb deleted file mode 100644 index ec6eb98f57..0000000000 --- a/db/migrate/20120327000629_fix_problematic_index_names.rb +++ /dev/null @@ -1,13 +0,0 @@ -class FixProblematicIndexNames < ActiveRecord::Migration - def up - begin - remove_index :preferences, :name => 'index_preferences_on_owner_and_attribute_and_preference' - rescue ArgumentError - # ignore - already remove then - end - add_index :preferences, [:owner_id, :owner_type, :name, :group_id, :group_type], :name => 'ix_prefs_on_owner_attr_pref', :unique => true - end - - def down - end -end diff --git a/db/migrate/20120327000630_add_position_to_variants.rb b/db/migrate/20120327000630_add_position_to_variants.rb deleted file mode 100644 index 84a4ab5972..0000000000 --- a/db/migrate/20120327000630_add_position_to_variants.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddPositionToVariants < ActiveRecord::Migration - def change - add_column :variants, :position, :integer - end -end diff --git a/db/migrate/20120327000631_add_next_state_to_state_events.rb b/db/migrate/20120327000631_add_next_state_to_state_events.rb deleted file mode 100644 index 4ea7479a72..0000000000 --- a/db/migrate/20120327000631_add_next_state_to_state_events.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddNextStateToStateEvents < ActiveRecord::Migration - def change - add_column :state_events, :next_state, :string - end -end diff --git a/db/migrate/20120327000632_add_position_to_option_types.rb b/db/migrate/20120327000632_add_position_to_option_types.rb deleted file mode 100644 index 61cdf87344..0000000000 --- a/db/migrate/20120327000632_add_position_to_option_types.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddPositionToOptionTypes < ActiveRecord::Migration - def change - add_column :option_types, :position, :integer, :null => false, :default => 0 - end -end diff --git a/db/migrate/20120327000633_remove_trailing_slashes_in_taxon_permalinks.rb b/db/migrate/20120327000633_remove_trailing_slashes_in_taxon_permalinks.rb deleted file mode 100644 index cb2a016fbb..0000000000 --- a/db/migrate/20120327000633_remove_trailing_slashes_in_taxon_permalinks.rb +++ /dev/null @@ -1,19 +0,0 @@ -class RemoveTrailingSlashesInTaxonPermalinks < ActiveRecord::Migration - def up - taxons = select_all "SELECT * FROM taxons" - taxons.each do |taxon| - if taxon['permalink'] && taxon['permalink'][-1..-1] == '/' - execute "UPDATE taxons SET permalink = '#{taxon['permalink'][0...-1]}' WHERE id = #{taxon['id']}" - end - end - end - - def down - taxons = select_all "SELECT * FROM taxons" - taxons.each do |taxon| - if taxon['permalink'] && taxon['permalink'][-1..-1] != '/' - execute "UPDATE taxons SET permalink = '#{taxon['permalink'] + '/'}' WHERE id = #{taxon['id']}" - end - end - end -end diff --git a/db/migrate/20120327000634_create_activators.rb b/db/migrate/20120327000634_create_activators.rb deleted file mode 100644 index 81448f3025..0000000000 --- a/db/migrate/20120327000634_create_activators.rb +++ /dev/null @@ -1,14 +0,0 @@ -class CreateActivators < ActiveRecord::Migration - def change - create_table :activators, :force => true do |t| - t.string :description - t.datetime :expires_at - t.datetime :created_at - t.datetime :updated_at - t.datetime :starts_at - t.string :name - t.string :event_name - t.string :type - end - end -end diff --git a/db/migrate/20120327000635_eligible_for_adjustments.rb b/db/migrate/20120327000635_eligible_for_adjustments.rb deleted file mode 100644 index 0f669ed30e..0000000000 --- a/db/migrate/20120327000635_eligible_for_adjustments.rb +++ /dev/null @@ -1,5 +0,0 @@ -class EligibleForAdjustments < ActiveRecord::Migration - def change - add_column :adjustments, :eligible, :boolean, :default => true - end -end diff --git a/db/migrate/20120327000636_namespace_top_level_models.rb b/db/migrate/20120327000636_namespace_top_level_models.rb deleted file mode 100644 index 88abe8a139..0000000000 --- a/db/migrate/20120327000636_namespace_top_level_models.rb +++ /dev/null @@ -1,52 +0,0 @@ -class NamespaceTopLevelModels < ActiveRecord::Migration - def change - rename_table :activators, :spree_activators - rename_table :addresses, :spree_addresses - rename_table :adjustments, :spree_adjustments - rename_table :configurations, :spree_configurations - rename_table :assets, :spree_assets - rename_table :calculators, :spree_calculators - rename_table :countries, :spree_countries - rename_table :creditcards, :spree_creditcards - rename_table :gateways, :spree_gateways - rename_table :inventory_units, :spree_inventory_units - rename_table :line_items, :spree_line_items - rename_table :log_entries, :spree_log_entries - rename_table :mail_methods, :spree_mail_methods - rename_table :option_types, :spree_option_types - rename_table :option_values, :spree_option_values - rename_table :option_types_prototypes, :spree_option_types_prototypes - rename_table :option_values_variants, :spree_option_values_variants - rename_table :orders, :spree_orders - rename_table :payments, :spree_payments - rename_table :payment_methods, :spree_payment_methods - rename_table :preferences, :spree_preferences - rename_table :products, :spree_products - rename_table :product_groups, :spree_product_groups - rename_table :product_groups_products, :spree_product_groups_products - rename_table :product_option_types, :spree_product_option_types - rename_table :product_properties, :spree_product_properties - rename_table :product_scopes, :spree_product_scopes - rename_table :products_taxons, :spree_products_taxons - rename_table :properties, :spree_properties - rename_table :prototypes, :spree_prototypes - rename_table :properties_prototypes, :spree_properties_prototypes - rename_table :return_authorizations, :spree_return_authorizations - rename_table :roles, :spree_roles - rename_table :roles_users, :spree_roles_users - rename_table :shipments, :spree_shipments - rename_table :shipping_categories, :spree_shipping_categories - rename_table :shipping_methods, :spree_shipping_methods - rename_table :states, :spree_states - rename_table :state_events, :spree_state_events - rename_table :tax_categories, :spree_tax_categories - rename_table :tax_rates, :spree_tax_rates - rename_table :taxons, :spree_taxons - rename_table :taxonomies, :spree_taxonomies - rename_table :trackers, :spree_trackers - rename_table :users, :spree_users - rename_table :variants, :spree_variants - rename_table :zones, :spree_zones - rename_table :zone_members, :spree_zone_members - end -end diff --git a/db/migrate/20120327000637_migrate_namespaced_polymorphic_models.rb b/db/migrate/20120327000637_migrate_namespaced_polymorphic_models.rb deleted file mode 100644 index ec82863a4f..0000000000 --- a/db/migrate/20120327000637_migrate_namespaced_polymorphic_models.rb +++ /dev/null @@ -1,52 +0,0 @@ -class MigrateNamespacedPolymorphicModels < ActiveRecord::Migration - def concat(str1, str2) - dbtype = Rails.configuration.database_configuration[Rails.env]['adapter'].to_sym - - case dbtype - when :mysql, :mysql2 - "CONCAT(#{str1}, #{str2})" - when :sqlserver - "(#{str1} + #{str2})" - else - "(#{str1} || #{str2})" - end - end - - def update_column_data(table_names, column_name) - tables = Array.wrap(table_names) - tables.each do |table| - execute "UPDATE #{table} SET #{column_name} = #{concat("'Spree::'", column_name)}" + - " where #{column_name} NOT LIKE 'Spree::%' AND #{column_name} IS NOT NULL" - end - end - - def replace_column_data(table_names, column_name) - tables = Array.wrap(table_names) - tables.each do |table| - execute "UPDATE #{table} SET #{column_name} = REPLACE(#{column_name}, 'Spree::', '') " + - " where #{column_name} LIKE 'Spree::%'" - end - end - - def up - update_column_data(['spree_payments', 'spree_adjustments', 'spree_log_entries'], 'source_type') - update_column_data('spree_adjustments', 'originator_type') - update_column_data('spree_calculators', 'calculable_type') - update_column_data('spree_preferences', 'owner_type') - update_column_data('spree_state_events', 'stateful_type') - update_column_data(['spree_activators', 'spree_assets', 'spree_calculators', 'spree_configurations', 'spree_gateways', 'spree_payment_methods'], 'type') - update_column_data('spree_assets', 'viewable_type') - update_column_data('spree_zone_members', 'zoneable_type') - end - - def down - replace_column_data(['spree_payments', 'spree_adjustments', 'spree_log_entries'], 'source_type') - replace_column_data('spree_adjustments', 'originator_type') - replace_column_data('spree_calculators', 'calculable_type') - replace_column_data('spree_preferences', 'owner_type') - replace_column_data('spree_state_events', 'stateful_type') - replace_column_data(['spree_activators', 'spree_assets', 'spree_calculators', 'spree_configurations', 'spree_gateways', 'spree_payment_methods'], 'type') - replace_column_data('spree_assets', 'viewable_type') - replace_column_data('spree_zone_members', 'zoneable_type') - end -end diff --git a/db/migrate/20120327000638_make_adjustments_polymorphic.rb b/db/migrate/20120327000638_make_adjustments_polymorphic.rb deleted file mode 100644 index 62ba67cb64..0000000000 --- a/db/migrate/20120327000638_make_adjustments_polymorphic.rb +++ /dev/null @@ -1,9 +0,0 @@ -class MakeAdjustmentsPolymorphic < ActiveRecord::Migration - - def change - add_column :spree_adjustments, :adjustable_type, :string - rename_column :spree_adjustments, :order_id, :adjustable_id - execute "UPDATE spree_adjustments SET adjustable_type = 'Spree::Order'" - end - -end diff --git a/db/migrate/20120327000639_add_company_to_addresses.rb b/db/migrate/20120327000639_add_company_to_addresses.rb deleted file mode 100644 index 60a819ea70..0000000000 --- a/db/migrate/20120327000639_add_company_to_addresses.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddCompanyToAddresses < ActiveRecord::Migration - def change - add_column :spree_addresses, :company, :string - end -end diff --git a/db/migrate/20120327000640_add_inc_tax_to_tax_rates.rb b/db/migrate/20120327000640_add_inc_tax_to_tax_rates.rb deleted file mode 100644 index 715b0b4357..0000000000 --- a/db/migrate/20120327000640_add_inc_tax_to_tax_rates.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddIncTaxToTaxRates < ActiveRecord::Migration - def change - add_column :spree_tax_rates, :inc_tax, :boolean, :default => false - end -end diff --git a/db/migrate/20120327000641_rename_inc_price_attribute.rb b/db/migrate/20120327000641_rename_inc_price_attribute.rb deleted file mode 100644 index 8657f63a58..0000000000 --- a/db/migrate/20120327000641_rename_inc_price_attribute.rb +++ /dev/null @@ -1,5 +0,0 @@ -class RenameIncPriceAttribute < ActiveRecord::Migration - def change - rename_column :spree_tax_rates, :inc_tax, :included_in_price - end -end diff --git a/db/migrate/20120327000642_add_default_tax_zone.rb b/db/migrate/20120327000642_add_default_tax_zone.rb deleted file mode 100644 index d0e831800f..0000000000 --- a/db/migrate/20120327000642_add_default_tax_zone.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddDefaultTaxZone < ActiveRecord::Migration - def change - add_column :spree_zones, :default_tax, :boolean, :default => false - end -end diff --git a/db/migrate/20120327000643_associate_shipping_methods_and_shipping_categories.rb b/db/migrate/20120327000643_associate_shipping_methods_and_shipping_categories.rb deleted file mode 100644 index f7f62b7201..0000000000 --- a/db/migrate/20120327000643_associate_shipping_methods_and_shipping_categories.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AssociateShippingMethodsAndShippingCategories < ActiveRecord::Migration - def change - change_table :spree_shipping_methods do |t| - t.references :shipping_category - end - end -end diff --git a/db/migrate/20120327000644_add_match_rules_to_shipping_methods.rb b/db/migrate/20120327000644_add_match_rules_to_shipping_methods.rb deleted file mode 100644 index e5b5ea32a2..0000000000 --- a/db/migrate/20120327000644_add_match_rules_to_shipping_methods.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AddMatchRulesToShippingMethods < ActiveRecord::Migration - def change - add_column :spree_shipping_methods, :match_none, :boolean - add_column :spree_shipping_methods, :match_all, :boolean - add_column :spree_shipping_methods, :match_one, :boolean - end -end diff --git a/db/migrate/20120327000645_new_preferences.rb b/db/migrate/20120327000645_new_preferences.rb deleted file mode 100644 index 86e5dbbf57..0000000000 --- a/db/migrate/20120327000645_new_preferences.rb +++ /dev/null @@ -1,81 +0,0 @@ -# Spree 1.3.6.beta preference rescue implementation, required for the new -# preferences migration, which is broken since commit ab707cf due to the -# absence of this file. -# -# Migration: db/migrate/20120327000645_new_preferences.rb -# Source: https://raw.githubusercontent.com/spree/spree/1-3-stable/core/lib/spree/core/preference_rescue.rb -# -# rubocop:disable all -module Spree - class OldPrefs < ActiveRecord::Base - self.table_name = "spree_preferences" - belongs_to :owner, :polymorphic => true - attr_accessor :owner_klass - end - - class PreferenceRescue - def self.try - OldPrefs.where(:key => nil).each do |old_pref| - next unless owner = (old_pref.owner rescue nil) - unless old_pref.owner_type == "Spree::Activator" || old_pref.owner_type == "Spree::Configuration" - begin - old_pref.key = [owner.class.name, old_pref.name, owner.id].join('::').underscore - old_pref.value_type = owner.preference_type(old_pref.name) - puts "Migrating Preference: #{old_pref.key}" - old_pref.save - rescue NoMethodError => ex - puts ex.message - end - end - end - end - end -end -# rubocop:enable all - -class NewPreferences < ActiveRecord::Migration - - def up - add_column :spree_preferences, :key, :string - add_column :spree_preferences, :value_type, :string - add_index :spree_preferences, :key, :unique => true - - remove_index :spree_preferences, :name => 'ix_prefs_on_owner_attr_pref' - - # remove old constraints for migration - change_column :spree_preferences, :name, :string, :null => true - change_column :spree_preferences, :owner_id, :integer, :null => true - change_column :spree_preferences, :owner_type, :string, :null => true - change_column :spree_preferences, :group_id, :integer, :null => true - change_column :spree_preferences, :group_type, :string, :null => true - - cfgs = execute("select id, type from spree_configurations").to_a - execute("select id, owner_id, name from spree_preferences where owner_type = 'Spree::Configuration'").each do |pref| - configuration = cfgs.detect { |c| c[0].to_s == pref[1].to_s } - - value_type = configuration[1].constantize.new.send "preferred_#{pref[2]}_type" rescue 'string' - - execute "UPDATE spree_preferences set `key` = '#{configuration[1].underscore}/#{pref[2]}', `value_type` = '#{value_type}' where id = #{pref[0]}" rescue nil - end - - # remove orphaned calculator preferences - Spree::Preference.where(:owner_type => 'Spree::Calculator').each do |preference| - preference.destroy unless Spree::Calculator.exists? preference.owner_id - end - - Spree::PreferenceRescue.try - - Spree::Preference.where(:value_type => nil).update_all(:value_type => 'string') - end - - def down - remove_column :spree_preferences, :key - remove_column :spree_preferences, :value_type - - add_column :spree_preferences, :name, :string - add_column :spree_preferences, :owner_id, :integer - add_column :spree_preferences, :owner_type, :string - add_column :spree_preferences, :group_id, :integer - add_column :spree_preferences, :group_type, :string - end -end diff --git a/db/migrate/20120327000646_add_deleted_at_to_tax_category.rb b/db/migrate/20120327000646_add_deleted_at_to_tax_category.rb deleted file mode 100644 index be24f6b4d0..0000000000 --- a/db/migrate/20120327000646_add_deleted_at_to_tax_category.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddDeletedAtToTaxCategory < ActiveRecord::Migration - def change - add_column :spree_tax_categories, :deleted_at, :datetime - end -end diff --git a/db/migrate/20120327000647_rename_columns_for_devise.rb b/db/migrate/20120327000647_rename_columns_for_devise.rb deleted file mode 100644 index cfd893edee..0000000000 --- a/db/migrate/20120327000647_rename_columns_for_devise.rb +++ /dev/null @@ -1,39 +0,0 @@ -class RenameColumnsForDevise < ActiveRecord::Migration - def up - return if column_exists?(:spree_users, :password_salt) - rename_column :spree_users, :crypted_password, :encrypted_password - rename_column :spree_users, :salt, :password_salt - rename_column :spree_users, :remember_token_expires_at, :remember_created_at - rename_column :spree_users, :login_count, :sign_in_count - rename_column :spree_users, :failed_login_count, :failed_attempts - rename_column :spree_users, :single_access_token, :reset_password_token - rename_column :spree_users, :current_login_at, :current_sign_in_at - rename_column :spree_users, :last_login_at, :last_sign_in_at - rename_column :spree_users, :current_login_ip, :current_sign_in_ip - rename_column :spree_users, :last_login_ip, :last_sign_in_ip - add_column :spree_users, :authentication_token, :string - add_column :spree_users, :unlock_token, :string - add_column :spree_users, :locked_at, :datetime - remove_column :spree_users, :api_key if column_exists?(:spree_users, :api_key) - remove_column :spree_users, :openid_identifier - end - - def down - remove_column :spree_users, :authentication_token - remove_column :spree_users, :locked_at - remove_column :spree_users, :unlock_token - rename_column :table_name, :new_column_name, :column_name - rename_column :spree_users, :last_sign_in_ip, :last_login_ip - rename_column :spree_users, :current_sign_in_ip, :current_login_ip - rename_column :spree_users, :last_sign_in_at, :last_login_at - rename_column :spree_users, :current_sign_in_at, :current_login_at - rename_column :spree_users, :reset_password_token, :single_access_token - rename_column :spree_users, :failed_attempts, :failed_login_count - rename_column :spree_users, :sign_in_count, :login_count - rename_column :spree_users, :remember_created_at, :remember_token_expires_at - rename_column :spree_users, :password_salt, :salt - rename_column :spree_users, :encrypted_password, :crypted_password - add_column :spree_users, :unlock_token, :string - add_column :spree_users, :openid_identifier, :string - end -end diff --git a/db/migrate/20120327000648_convert_user_remember_field.rb b/db/migrate/20120327000648_convert_user_remember_field.rb deleted file mode 100644 index 4514fc5b47..0000000000 --- a/db/migrate/20120327000648_convert_user_remember_field.rb +++ /dev/null @@ -1,11 +0,0 @@ -class ConvertUserRememberField < ActiveRecord::Migration - def up - remove_column :spree_users, :remember_created_at - add_column :spree_users, :remember_created_at, :datetime - end - - def down - remove_column :spree_users, :remember_created_at - add_column :spree_users, :remember_created_at, :string - end -end diff --git a/db/migrate/20120327000649_create_tokenized_permissions.rb b/db/migrate/20120327000649_create_tokenized_permissions.rb deleted file mode 100644 index e7d8df4d60..0000000000 --- a/db/migrate/20120327000649_create_tokenized_permissions.rb +++ /dev/null @@ -1,13 +0,0 @@ -class CreateTokenizedPermissions < ActiveRecord::Migration - def change - create_table :tokenized_permissions do |t| - t.integer :permissable_id - t.string :permissable_type - t.string :token - - t.timestamps - end - - add_index :tokenized_permissions, [:permissable_id, :permissable_type], :name => 'index_tokenized_name_and_type' - end -end diff --git a/db/migrate/20120327000650_tokens_for_legacy_orders.rb b/db/migrate/20120327000650_tokens_for_legacy_orders.rb deleted file mode 100644 index 009177b4e8..0000000000 --- a/db/migrate/20120327000650_tokens_for_legacy_orders.rb +++ /dev/null @@ -1,16 +0,0 @@ -class TokensForLegacyOrders < ActiveRecord::Migration - def up - Spree::TokenizedPermission.table_name = 'tokenized_permissions' - - # add token permissions for legacy orders (stop relying on user persistence token) - Spree::Order.all.each do |order| - next unless order.user - order.create_tokenized_permission(:token => order.user.persistence_token) - end - - Spree::TokenizedPermission.table_name = 'spree_tokenized_permissions' - end - - def down - end -end diff --git a/db/migrate/20120327000651_namespace_tokenized_permission.rb b/db/migrate/20120327000651_namespace_tokenized_permission.rb deleted file mode 100644 index 3eb8baa7b0..0000000000 --- a/db/migrate/20120327000651_namespace_tokenized_permission.rb +++ /dev/null @@ -1,5 +0,0 @@ -class NamespaceTokenizedPermission < ActiveRecord::Migration - def change - rename_table :tokenized_permissions, :spree_tokenized_permissions - end -end diff --git a/db/migrate/20120327000652_migrate_tokenized_permissions.rb b/db/migrate/20120327000652_migrate_tokenized_permissions.rb deleted file mode 100644 index 2fb4e6e155..0000000000 --- a/db/migrate/20120327000652_migrate_tokenized_permissions.rb +++ /dev/null @@ -1,24 +0,0 @@ -class MigrateTokenizedPermissions < ActiveRecord::Migration - def concat(str1, str2) - dbtype = Rails.configuration.database_configuration[Rails.env]['adapter'].to_sym - - case dbtype - when :mysql, :mysql2 - "CONCAT(#{str1}, #{str2})" - when :sqlserver - "(#{str1} + #{str2})" - else - "(#{str1} || #{str2})" - end - end - - def up - execute "UPDATE spree_tokenized_permissions SET permissable_type = #{concat("'Spree::'", "permissable_type")}" + - " WHERE permissable_type NOT LIKE 'Spree::%' AND permissable_type IS NOT NULL" - end - - def down - execute "UPDATE spree_tokenized_permissions SET permissable_type = REPLACE(permissable_type, 'Spree::', '')" + - " WHERE permissable_type LIKE 'Spree::%'" - end -end diff --git a/db/migrate/20120327000653_add_api_key_to_users.rb b/db/migrate/20120327000653_add_api_key_to_users.rb deleted file mode 100644 index 32d98fabba..0000000000 --- a/db/migrate/20120327000653_add_api_key_to_users.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddApiKeyToUsers < ActiveRecord::Migration - def change - add_column :spree_users, :api_key, :string, :limit => 40 - end -end diff --git a/db/migrate/20120327000654_rename_coupons_to_promotions.rb b/db/migrate/20120327000654_rename_coupons_to_promotions.rb deleted file mode 100644 index a5d6bb39e5..0000000000 --- a/db/migrate/20120327000654_rename_coupons_to_promotions.rb +++ /dev/null @@ -1,10 +0,0 @@ -class RenameCouponsToPromotions < ActiveRecord::Migration - def up - drop_table :promotions if table_exists?(:promotions) - rename_table :coupons, :promotions - end - - def down - rename_table :promotions, :coupons - end -end diff --git a/db/migrate/20120327000655_create_promotion_rules.rb b/db/migrate/20120327000655_create_promotion_rules.rb deleted file mode 100644 index f94030b7a4..0000000000 --- a/db/migrate/20120327000655_create_promotion_rules.rb +++ /dev/null @@ -1,24 +0,0 @@ -class CreatePromotionRules < ActiveRecord::Migration - def up - create_table :promotion_rules do |t| - t.references :promotion, :user, :product_group - t.string :type - - t.timestamps - end - add_index :promotion_rules, :product_group_id - add_index :promotion_rules, :user_id - - create_table :products_promotion_rules do |t| - t.integer :product_id, :promotion_rule_id - end - remove_column :products_promotion_rules, :id - add_index :products_promotion_rules, :product_id - add_index :products_promotion_rules, :promotion_rule_id - end - - def down - drop_table :promotion_rules - drop_table :products_promotion_rules - end -end diff --git a/db/migrate/20120327000656_match_policy_for_promotions.rb b/db/migrate/20120327000656_match_policy_for_promotions.rb deleted file mode 100644 index f6c580e452..0000000000 --- a/db/migrate/20120327000656_match_policy_for_promotions.rb +++ /dev/null @@ -1,5 +0,0 @@ -class MatchPolicyForPromotions < ActiveRecord::Migration - def change - add_column :promotions, :match_policy, :string, :default => 'all' - end -end diff --git a/db/migrate/20120327000657_create_promotion_rules_users.rb b/db/migrate/20120327000657_create_promotion_rules_users.rb deleted file mode 100644 index f6c33350e6..0000000000 --- a/db/migrate/20120327000657_create_promotion_rules_users.rb +++ /dev/null @@ -1,14 +0,0 @@ -class CreatePromotionRulesUsers < ActiveRecord::Migration - def up - create_table :promotion_rules_users do |t| - t.integer :user_id, :promotion_rule_id - end - remove_column :promotion_rules_users, :id - add_index :promotion_rules_users, :user_id - add_index :promotion_rules_users, :promotion_rule_id - end - - def down - drop_table :promotion_rules_users - end -end diff --git a/db/migrate/20120327000658_name_for_promotions.rb b/db/migrate/20120327000658_name_for_promotions.rb deleted file mode 100644 index 1a26126e9b..0000000000 --- a/db/migrate/20120327000658_name_for_promotions.rb +++ /dev/null @@ -1,5 +0,0 @@ -class NameForPromotions < ActiveRecord::Migration - def change - add_column :promotions, :name, :string - end -end diff --git a/db/migrate/20120327000659_update_calculable_type_for_promotions.rb b/db/migrate/20120327000659_update_calculable_type_for_promotions.rb deleted file mode 100644 index ccdb8bef84..0000000000 --- a/db/migrate/20120327000659_update_calculable_type_for_promotions.rb +++ /dev/null @@ -1,9 +0,0 @@ -class UpdateCalculableTypeForPromotions < ActiveRecord::Migration - def up - execute "UPDATE spree_calculators SET calculable_type = 'Promotion' WHERE calculable_type = 'Coupon'" - end - - def down - execute "UPDATE spree_calculators SET calculable_type = 'Coupon' WHERE calculable_type = 'Promotion'" - end -end diff --git a/db/migrate/20120327000660_migrate_adjustments.rb b/db/migrate/20120327000660_migrate_adjustments.rb deleted file mode 100644 index 398d23bbc8..0000000000 --- a/db/migrate/20120327000660_migrate_adjustments.rb +++ /dev/null @@ -1,9 +0,0 @@ -class MigrateAdjustments < ActiveRecord::Migration - def up - execute "UPDATE spree_adjustments SET amount = 0.0 WHERE amount IS NULL" - execute "UPDATE spree_adjustments SET mandatory = 't' WHERE locked = 't'" - end - - def down - end -end diff --git a/db/migrate/20120327000661_promotion_changes_to_subclass_of_activator.rb b/db/migrate/20120327000661_promotion_changes_to_subclass_of_activator.rb deleted file mode 100644 index feee9c754e..0000000000 --- a/db/migrate/20120327000661_promotion_changes_to_subclass_of_activator.rb +++ /dev/null @@ -1,22 +0,0 @@ -class PromotionChangesToSubclassOfActivator < ActiveRecord::Migration - def up - drop_table :promotions - rename_column :promotion_rules, :promotion_id, :activator_id - end - - def down - create_table :promotions, :force => true do |t| - t.string :name - t.string :code - t.string :description - t.integer :usage_limit - t.boolean :combine - t.datetime :expires_at - t.datetime :starts_at - t.string :match_policy, :default => 'all' - - t.timestamps - end - rename_column :promotion_rules, :activator_id, :promotion_id - end -end diff --git a/db/migrate/20120327000662_create_promotion_actions.rb b/db/migrate/20120327000662_create_promotion_actions.rb deleted file mode 100644 index 2283154611..0000000000 --- a/db/migrate/20120327000662_create_promotion_actions.rb +++ /dev/null @@ -1,9 +0,0 @@ -class CreatePromotionActions < ActiveRecord::Migration - def change - create_table :promotion_actions do |t| - t.integer :activator_id - t.integer :position - t.string :type - end - end -end diff --git a/db/migrate/20120327000663_create_promotion_action_line_items.rb b/db/migrate/20120327000663_create_promotion_action_line_items.rb deleted file mode 100644 index 9241d58fc3..0000000000 --- a/db/migrate/20120327000663_create_promotion_action_line_items.rb +++ /dev/null @@ -1,10 +0,0 @@ -class CreatePromotionActionLineItems < ActiveRecord::Migration - def change - create_table :promotion_action_line_items do |t| - t.integer :promotion_action_id, :variant_id - t.integer :quantity, :default => 1 - t.references :promotion_action - t.references :variant - end - end -end diff --git a/db/migrate/20120327000664_namespace_promo_tables.rb b/db/migrate/20120327000664_namespace_promo_tables.rb deleted file mode 100644 index 398e65ae16..0000000000 --- a/db/migrate/20120327000664_namespace_promo_tables.rb +++ /dev/null @@ -1,85 +0,0 @@ -require 'spree/core/preference_rescue' - -class NamespacePromoTables < ActiveRecord::Migration - - def concat(str1, str2) - dbtype = Rails.configuration.database_configuration[Rails.env]['adapter'].to_sym - - case dbtype - when :mysql, :mysql2 - "CONCAT(#{str1}, #{str2})" - when :sqlserver - "(#{str1} + #{str2})" - else - "(#{str1} || #{str2})" - end - end - - def update_column_data(table_names, column_name) - tables = Array.wrap(table_names) - tables.each do |table| - execute "UPDATE #{table} SET #{column_name} = #{concat("'Spree::'", column_name)}" + - " where #{column_name} NOT LIKE 'Spree::%' AND #{column_name} IS NOT NULL" - end - end - - def replace_column_data(table_names, column_name) - tables = Array.wrap(table_names) - tables.each do |table| - execute "UPDATE #{table} SET #{column_name} = REPLACE(#{column_name}, 'Spree::', '') " + - " where #{column_name} LIKE 'Spree::%'" - end - end - - def self.up - # namespace promo tables - rename_table :promotion_actions, :spree_promotion_actions - rename_table :promotion_rules, :spree_promotion_rules - rename_table :promotion_rules_users, :spree_promotion_rules_users - rename_table :promotion_action_line_items, :spree_promotion_action_line_items - rename_table :products_promotion_rules, :spree_products_promotion_rules - - update_column_data('spree_promotion_actions', 'type') - update_column_data('spree_promotion_rules', 'type') - - # add old promo preferences as columns - add_column :spree_activators, :usage_limit, :integer - add_column :spree_activators, :match_policy, :string, :default => 'all' - add_column :spree_activators, :code, :string - add_column :spree_activators, :advertise, :boolean, :default => false - - Spree::Activator.reset_column_information - - Spree::Preference.where(:owner_type => 'Spree::Activator').each do |preference| - unless Spree::Activator.exists? preference.owner_id - preference.destroy - next - end - - @activator = Spree::Activator.find(preference.owner_id) - @activator.update_attribute(preference.name, preference.raw_value) - preference.destroy - end - - Spree::PreferenceRescue.try - - # This *should* be in the new_preferences migration inside of Core but... - # This is migration needs to have these keys around so that - # we can convert the promotions over correctly. - # So they hang around until we're *finally* done with them, since promo's - # migrations are copied over *after* core, and then we ditch them. - remove_column :spree_preferences, :group_id - remove_column :spree_preferences, :group_type - end - - def self.down - replace_column_data('spree_promotion_actions', 'type') - replace_column_data('spree_promotion_rules', 'type') - - rename_table :spree_promotion_actions, :promotion_actions - rename_table :spree_promotion_rules, :promotion_rules - rename_table :spree_promotion_rules_users, :promotion_rules_users - rename_table :spree_promotion_action_line_items, :promotion_action_line_items - rename_table :spree_products_promotion_rules, :products_promotion_rules - end -end \ No newline at end of file diff --git a/db/migrate/20120327000665_create_spree_pending_promotions.rb b/db/migrate/20120327000665_create_spree_pending_promotions.rb deleted file mode 100644 index e6de8afdeb..0000000000 --- a/db/migrate/20120327000665_create_spree_pending_promotions.rb +++ /dev/null @@ -1,11 +0,0 @@ -class CreateSpreePendingPromotions < ActiveRecord::Migration - def change - create_table :spree_pending_promotions do |t| - t.references :user - t.references :promotion - end - - add_index :spree_pending_promotions, :user_id - add_index :spree_pending_promotions, :promotion_id - end -end diff --git a/db/migrate/20120327000666_content_visited_event.rb b/db/migrate/20120327000666_content_visited_event.rb deleted file mode 100644 index ea853b2c9b..0000000000 --- a/db/migrate/20120327000666_content_visited_event.rb +++ /dev/null @@ -1,29 +0,0 @@ -# LandingPage used to support static pages, we've moved to a static -# event. This adds path to promotions then migrates the old LandingPage rules -class ContentVisitedEvent < ActiveRecord::Migration - - # Removed Class for Migrations - class Spree::Promotion::Rules::LandingPage < Spree::PromotionRule - preference :path, :string - def eligible?(order, options = {}) - true - end - end - - def up - add_column :spree_activators, :path, :string - - Spree::Promotion::Rules::LandingPage.all.each do |promotion_rule| - promotion = promotion_rule.promotion - say "migrating #{promotion.name} promotion to use 'spree.content.visited' event" - promotion.event_name = 'spree.content.visited' - promotion.path = promotion_rule.preferred_path - promotion.promotion_rules.delete promotion_rule - promotion.save(:validate => false) - end - end - - def down - remove_column :spree_activators, :path - end -end \ No newline at end of file diff --git a/db/migrate/20120327000667_create_skrill_transactions.rb b/db/migrate/20120327000667_create_skrill_transactions.rb deleted file mode 100644 index 0af9924a0b..0000000000 --- a/db/migrate/20120327000667_create_skrill_transactions.rb +++ /dev/null @@ -1,14 +0,0 @@ -class CreateSkrillTransactions < ActiveRecord::Migration - def change - create_table :spree_skrill_transactions do |t| - t.string :email - t.float :amount - t.string :currency - t.integer :transaction_id - t.integer :customer_id - t.string :payment_type - t.timestamps - end - end -end - diff --git a/db/migrate/20120331051742_create_distributors.rb b/db/migrate/20120331051742_create_distributors.rb deleted file mode 100644 index f9096b4fb8..0000000000 --- a/db/migrate/20120331051742_create_distributors.rb +++ /dev/null @@ -1,18 +0,0 @@ -class CreateDistributors < ActiveRecord::Migration - def change - create_table :distributors do |t| - t.string :name - t.string :contact - t.string :phone - t.string :email - t.string :pickup_address - t.string :pickup_times - t.string :url - t.string :abn - t.string :acn - t.string :description - - t.timestamps - end - end -end diff --git a/db/migrate/20120407065132_add_distributor_to_order.rb b/db/migrate/20120407065132_add_distributor_to_order.rb deleted file mode 100644 index 9dd239d214..0000000000 --- a/db/migrate/20120407065132_add_distributor_to_order.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddDistributorToOrder < ActiveRecord::Migration - def change - add_column :spree_orders, :distributor_id, :integer - end -end diff --git a/db/migrate/20120408081918_add_extra_address_fields_to_distributor.rb b/db/migrate/20120408081918_add_extra_address_fields_to_distributor.rb deleted file mode 100644 index 91b65333d6..0000000000 --- a/db/migrate/20120408081918_add_extra_address_fields_to_distributor.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AddExtraAddressFieldsToDistributor < ActiveRecord::Migration - def change - add_column :distributors, :city, :string - add_column :distributors, :post_code, :string - add_column :distributors, :country_id, :integer - end -end diff --git a/db/migrate/20120409004831_add_state_to_distributor.rb b/db/migrate/20120409004831_add_state_to_distributor.rb deleted file mode 100644 index 5480039a1a..0000000000 --- a/db/migrate/20120409004831_add_state_to_distributor.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddStateToDistributor < ActiveRecord::Migration - def change - add_column :distributors, :state_id, :integer - end -end diff --git a/db/migrate/20120422042134_add_supplier.rb b/db/migrate/20120422042134_add_supplier.rb deleted file mode 100644 index 85add9901a..0000000000 --- a/db/migrate/20120422042134_add_supplier.rb +++ /dev/null @@ -1,16 +0,0 @@ -class AddSupplier < ActiveRecord::Migration - def change - create_table :suppliers do |t| - t.string :name - t.string :description - t.string :url - t.string :email - t.string :twitter - t.string :website - - t.integer :address_id - - t.timestamps - end - end -end diff --git a/db/migrate/20120425065453_add_supplier_to_product.rb b/db/migrate/20120425065453_add_supplier_to_product.rb deleted file mode 100644 index 41653e7857..0000000000 --- a/db/migrate/20120425065453_add_supplier_to_product.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddSupplierToProduct < ActiveRecord::Migration - def change - add_column :spree_products, :supplier_id, :integer - end -end diff --git a/db/migrate/20120429071654_replace_spree_address_from_supplier.rb b/db/migrate/20120429071654_replace_spree_address_from_supplier.rb deleted file mode 100644 index e910b373c6..0000000000 --- a/db/migrate/20120429071654_replace_spree_address_from_supplier.rb +++ /dev/null @@ -1,12 +0,0 @@ -class ReplaceSpreeAddressFromSupplier < ActiveRecord::Migration - def change - remove_column :suppliers, :address_id - remove_column :suppliers, :url - - add_column :suppliers, :address, :string - add_column :suppliers, :city, :string - add_column :suppliers, :postcode, :string - add_column :suppliers, :state_id, :integer - add_column :suppliers, :country_id, :integer - end -end diff --git a/db/migrate/20120520062059_rename_state_events_to_state_changes.spree.rb b/db/migrate/20120520062059_rename_state_events_to_state_changes.spree.rb deleted file mode 100644 index 469e730d62..0000000000 --- a/db/migrate/20120520062059_rename_state_events_to_state_changes.spree.rb +++ /dev/null @@ -1,10 +0,0 @@ -# This migration comes from spree (originally 20120203001428) -class RenameStateEventsToStateChanges < ActiveRecord::Migration - def up - rename_table :spree_state_events, :spree_state_changes - end - - def down - rename_table :spree_state_changes, :spree_state_events - end -end diff --git a/db/migrate/20120520062060_migrate_images_from_products_to_variants.spree.rb b/db/migrate/20120520062060_migrate_images_from_products_to_variants.spree.rb deleted file mode 100644 index 5199cbd49d..0000000000 --- a/db/migrate/20120520062060_migrate_images_from_products_to_variants.spree.rb +++ /dev/null @@ -1,36 +0,0 @@ -# This migration comes from spree (originally 20120315064358) -class MigrateImagesFromProductsToVariants < ActiveRecord::Migration - def up - images = select_all("SELECT spree_assets.* FROM spree_assets - WHERE spree_assets.type IN ('Spree::Image') - AND spree_assets.viewable_type = 'Spree::Product'") - - images.each do |image| - master_variant_id = select_value("SELECT id FROM spree_variants - WHERE product_id = #{image['viewable_id']} - AND is_master = #{quoted_true}") - - execute("UPDATE spree_assets SET viewable_type = 'Spree::Variant', viewable_id = #{master_variant_id} - WHERE id = #{image['id']}") if master_variant_id - end - end - - def down - images = select_all("SELECT spree_assets.* FROM spree_assets - JOIN spree_variants - ON spree_variants.id = spree_assets.viewable_id - AND spree_variants.is_master = #{quoted_true} - WHERE spree_assets.type IN ('Spree::Image') - AND spree_assets.viewable_type = 'Spree::Variant'") - - images.each do |image| - product_id = select_value("SELECT spree_products.id FROM spree_products - JOIN spree_variants - ON spree_variants.id = #{image['viewable_id']} - AND spree_products.id = spree_variants.product_id") - - execute("UPDATE spree_assets SET viewable_type = 'Spree::Product', viewable_id = #{product_id} - WHERE id = #{image['id']}") if product_id - end - end -end diff --git a/db/migrate/20120520062061_rename_attachment_size_to_attachment_file_size.spree.rb b/db/migrate/20120520062061_rename_attachment_size_to_attachment_file_size.spree.rb deleted file mode 100644 index 2dec8f2115..0000000000 --- a/db/migrate/20120520062061_rename_attachment_size_to_attachment_file_size.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20120416233427) -class RenameAttachmentSizeToAttachmentFileSize < ActiveRecord::Migration - def change - rename_column :spree_assets, :attachment_size, :attachment_file_size - end -end diff --git a/db/migrate/20120618061537_move_distributor_from_order_to_product.rb b/db/migrate/20120618061537_move_distributor_from_order_to_product.rb deleted file mode 100644 index c5f0b18a59..0000000000 --- a/db/migrate/20120618061537_move_distributor_from_order_to_product.rb +++ /dev/null @@ -1,26 +0,0 @@ -class MoveDistributorFromOrderToProduct < ActiveRecord::Migration - class Distributor < ActiveRecord::Base; end - class Spree::Product < ActiveRecord::Base; end - - def up - remove_column :spree_orders, :distributor_id - - create_table :distributors_products, :id => false do |t| - t.references :product - t.references :distributor - end - - # Associate all products with the first distributor - distributor = Distributor.first - if distributor - Spree::Product.all.each do |product| - product.distributors << distributor - end - end - end - - def down - drop_table :distributors_products - add_column :spree_orders, :distributor_id, :integer - end -end diff --git a/db/migrate/20120621064227_add_distributor_id_to_order.rb b/db/migrate/20120621064227_add_distributor_id_to_order.rb deleted file mode 100644 index 3f6bb57acf..0000000000 --- a/db/migrate/20120621064227_add_distributor_id_to_order.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddDistributorIdToOrder < ActiveRecord::Migration - def change - add_column :spree_orders, :distributor_id, :integer - end -end diff --git a/db/migrate/20120626013846_extract_distributor_and_supplier_address_to_spree_address.rb b/db/migrate/20120626013846_extract_distributor_and_supplier_address_to_spree_address.rb deleted file mode 100644 index 89480427ea..0000000000 --- a/db/migrate/20120626013846_extract_distributor_and_supplier_address_to_spree_address.rb +++ /dev/null @@ -1,92 +0,0 @@ -class ExtractDistributorAndSupplierAddressToSpreeAddress < ActiveRecord::Migration - class Supplier < ActiveRecord::Base; end - class Distributor < ActiveRecord::Base; end - class Spree::Address < ActiveRecord::Base; end - - - def up - # -- Distributors - add_column :distributors, :pickup_address_id, :integer - Distributor.reset_column_information - - Distributor.all.each do |distributor| - pickup_address = Spree::Address.create!(:firstname => 'unused', - :lastname => 'unused', - :phone => 'unused', - :address1 => distributor[:pickup_address], - :city => distributor.city, - :zipcode => distributor.post_code, - :state_id => distributor.state_id, - :country_id => distributor.country_id) - distributor.pickup_address = pickup_address - distributor.save! - end - - %w(pickup_address city post_code state_id country_id).each do |column| - remove_column :distributors, column - end - - - # -- Suppliers - add_column :suppliers, :address_id, :integer - Supplier.reset_column_information - - Supplier.all.each do |supplier| - address = Spree::Address.create!(:firstname => 'unused', - :lastname => 'unused', - :phone => 'unused', - :address1 => supplier[:address], - :city => supplier.city, - :zipcode => supplier.postcode, - :state_id => supplier.state_id, - :country_id => supplier.country_id) - supplier.address = address - supplier.save! - end - - %w(address city postcode state_id country_id).each do |column| - remove_column :suppliers, column - end - end - - def down - # -- Distributors - add_column :distributors, :pickup_address, :string - add_column :distributors, :city, :string - add_column :distributors, :post_code, :string - add_column :distributors, :state_id, :integer - add_column :distributors, :country_id, :integer - Distributor.reset_column_information - - Distributor.all.each do |distributor| - distributor[:pickup_address] = distributor.pickup_address.address1 - distributor.city = distributor.pickup_address.city - distributor.post_code = distributor.pickup_address.zipcode - distributor.state_id = distributor.pickup_address.state_id - distributor.country_id = distributor.pickup_address.country_id - distributor.save! - end - - remove_column :distributors, :pickup_address_id - - - # -- Suppliers - add_column :suppliers, :address, :string - add_column :suppliers, :city, :string - add_column :suppliers, :postcode, :string - add_column :suppliers, :state_id, :integer - add_column :suppliers, :country_id, :integer - Supplier.reset_column_information - - Supplier.all.each do |supplier| - supplier[:address] = supplier.address.address1 - supplier.city = supplier.address.city - supplier.post_code = supplier.address.zipcode - supplier.state_id = supplier.address.state_id - supplier.country_id = supplier.address.country_id - supplier.save! - end - - remove_column :suppliers, :address_id - end -end diff --git a/db/migrate/20120626233350_rename_distributors_products_to_product_distributions.rb b/db/migrate/20120626233350_rename_distributors_products_to_product_distributions.rb deleted file mode 100644 index c2ecd94457..0000000000 --- a/db/migrate/20120626233350_rename_distributors_products_to_product_distributions.rb +++ /dev/null @@ -1,27 +0,0 @@ -class RenameDistributorsProductsToProductDistributions < ActiveRecord::Migration - class Spree::ShippingMethod < ActiveRecord::Base; end - class ProductDistribution < ActiveRecord::Base; end - - def up - # Convert m2m join table into explicit join model, and add a shipping method relation and timestamps - rename_table :distributors_products, :product_distributions - add_column :product_distributions, :id, :primary_key - change_table :product_distributions do |t| - t.references :shipping_method - t.timestamps - end - - # Set default shipping method on all product distributions - sm = Spree::ShippingMethod.unscoped.first - ProductDistribution.update_all(:shipping_method_id => sm.id) if sm - end - - def down - change_table :product_distributions do |t| - t.remove :id - t.remove :shipping_method_id - t.remove :created_at, :updated_at - end - rename_table :product_distributions, :distributors_products - end -end diff --git a/db/migrate/20120629043042_increase_scale_of_tax_rate_amount.spree.rb b/db/migrate/20120629043042_increase_scale_of_tax_rate_amount.spree.rb deleted file mode 100644 index f4725b09d9..0000000000 --- a/db/migrate/20120629043042_increase_scale_of_tax_rate_amount.spree.rb +++ /dev/null @@ -1,10 +0,0 @@ -# This migration comes from spree (originally 20120507232704) -class IncreaseScaleOfTaxRateAmount < ActiveRecord::Migration - def up - change_column :spree_tax_rates, :amount, :decimal, { :scale => 5, :precision => 8 } - end - - def down - change_column :spree_tax_rates, :amount, :decimal, { :scale => 4, :precision => 8 } - end -end diff --git a/db/migrate/20120629043043_add_reset_password_sent_at_to_spree_users.spree_auth.rb b/db/migrate/20120629043043_add_reset_password_sent_at_to_spree_users.spree_auth.rb deleted file mode 100644 index 7632ac3417..0000000000 --- a/db/migrate/20120629043043_add_reset_password_sent_at_to_spree_users.spree_auth.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree_auth (originally 20120203010234) -class AddResetPasswordSentAtToSpreeUsers < ActiveRecord::Migration - def change - add_column :spree_users, :reset_password_sent_at, :datetime - end -end diff --git a/db/migrate/20120629043045_resize_api_key_field.spree_api.rb b/db/migrate/20120629043045_resize_api_key_field.spree_api.rb deleted file mode 100644 index cdd4430364..0000000000 --- a/db/migrate/20120629043045_resize_api_key_field.spree_api.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree_api (originally 20120411123334) -class ResizeApiKeyField < ActiveRecord::Migration - def change - change_column :spree_users, :api_key, :string, :limit => 48 - end -end diff --git a/db/migrate/20120629043647_create_paypal_accounts.spree_paypal_express.rb b/db/migrate/20120629043647_create_paypal_accounts.spree_paypal_express.rb deleted file mode 100644 index 89ee02159b..0000000000 --- a/db/migrate/20120629043647_create_paypal_accounts.spree_paypal_express.rb +++ /dev/null @@ -1,15 +0,0 @@ -# This migration comes from spree_paypal_express (originally 20100224133156) -class CreatePaypalAccounts < ActiveRecord::Migration - def self.up - create_table :paypal_accounts do |t| - t.string :email - t.string :payer_id - t.string :payer_country - t.string :payer_status - end - end - - def self.down - drop_table :paypal_accounts - end -end diff --git a/db/migrate/20120629043648_namespace_paypal_accounts.spree_paypal_express.rb b/db/migrate/20120629043648_namespace_paypal_accounts.spree_paypal_express.rb deleted file mode 100644 index 12a2f0cc83..0000000000 --- a/db/migrate/20120629043648_namespace_paypal_accounts.spree_paypal_express.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree_paypal_express (originally 20120117182027) -class NamespacePaypalAccounts < ActiveRecord::Migration - def change - rename_table :paypal_accounts, :spree_paypal_accounts - end -end diff --git a/db/migrate/20120702020402_add_next_collection_at_to_distributors.rb b/db/migrate/20120702020402_add_next_collection_at_to_distributors.rb deleted file mode 100644 index 1e30199de8..0000000000 --- a/db/migrate/20120702020402_add_next_collection_at_to_distributors.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddNextCollectionAtToDistributors < ActiveRecord::Migration - def change - add_column :distributors, :next_collection_at, :string - end -end diff --git a/db/migrate/20120802031147_add_group_buy_fields.rb b/db/migrate/20120802031147_add_group_buy_fields.rb deleted file mode 100644 index 5cc9efe857..0000000000 --- a/db/migrate/20120802031147_add_group_buy_fields.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddGroupBuyFields < ActiveRecord::Migration - def change - add_column :spree_products, :group_buy, :boolean - add_column :spree_line_items, :max_quantity, :integer - end -end diff --git a/db/migrate/20120913054657_convert_sales_tax_to_default_tax.spree.rb b/db/migrate/20120913054657_convert_sales_tax_to_default_tax.spree.rb deleted file mode 100644 index a15416d63c..0000000000 --- a/db/migrate/20120913054657_convert_sales_tax_to_default_tax.spree.rb +++ /dev/null @@ -1,10 +0,0 @@ -# This migration comes from spree (originally 20120523061241) -class ConvertSalesTaxToDefaultTax < ActiveRecord::Migration - def up - execute "UPDATE spree_calculators SET type='Spree::Calculator::DefaultTax' WHERE type='Spree::Calculator::SalesTax'" - end - - def down - execute "UPDATE spree_calculators SET type='Spree::Calculator::SalesTax' WHERE type='Spree::Calculator::DefaultTax'" - end -end diff --git a/db/migrate/20120913054658_add_deleted_at_to_spree_shipping_methods.spree.rb b/db/migrate/20120913054658_add_deleted_at_to_spree_shipping_methods.spree.rb deleted file mode 100644 index 54c5978c24..0000000000 --- a/db/migrate/20120913054658_add_deleted_at_to_spree_shipping_methods.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20120604030249) -class AddDeletedAtToSpreeShippingMethods < ActiveRecord::Migration - def change - add_column :spree_shipping_methods, :deleted_at, :datetime - end -end diff --git a/db/migrate/20120913054659_make_users_email_index_unique.spree.rb b/db/migrate/20120913054659_make_users_email_index_unique.spree.rb deleted file mode 100644 index 4fd43f21d2..0000000000 --- a/db/migrate/20120913054659_make_users_email_index_unique.spree.rb +++ /dev/null @@ -1,11 +0,0 @@ -# This migration comes from spree (originally 20120605211305) -class MakeUsersEmailIndexUnique < ActiveRecord::Migration - def up - add_index "spree_users", ["email"], :name => "email_idx_unique", :unique => true - end - - def down - remove_index "spree_users", :name => "email_idx_unique" - add_index "spree_users", ["email"], :name => "email_idx_unique" - end -end diff --git a/db/migrate/20120913054660_add_counter_cache_to_zone_members.spree.rb b/db/migrate/20120913054660_add_counter_cache_to_zone_members.spree.rb deleted file mode 100644 index 669434e34d..0000000000 --- a/db/migrate/20120913054660_add_counter_cache_to_zone_members.spree.rb +++ /dev/null @@ -1,15 +0,0 @@ -# This migration comes from spree (originally 20120712172620) -class AddCounterCacheToZoneMembers < ActiveRecord::Migration - def up - add_column :spree_zones, :zone_members_count, :integer, :default => 0 - - Spree::Zone.reset_column_information - Spree::Zone.find(:all).each do |zone| - Spree::Zone.update_counters zone.id, :zone_members_count => zone.zone_members.length - end - end - - def down - remove_column :spree_zones, :zone_members_count - end -end diff --git a/db/migrate/20120919013335_add_shipping_method_to_line_items.rb b/db/migrate/20120919013335_add_shipping_method_to_line_items.rb deleted file mode 100644 index bab7b8533a..0000000000 --- a/db/migrate/20120919013335_add_shipping_method_to_line_items.rb +++ /dev/null @@ -1,20 +0,0 @@ -class AddShippingMethodToLineItems < ActiveRecord::Migration - def up - add_column :spree_line_items, :shipping_method_id, :integer - - Spree::LineItem.all.each do |li| - begin - shipping_method = li.product.shipping_method_for_distributor(li.order.distributor) - rescue ArgumentError - shipping_method = Spree::ShippingMethod.find_by name: 'Producer Delivery' - say "Line item #{li.id} does not have a valid shipping method, setting to '#{shipping_method.name}'" - end - - Spree::LineItem.update_all("shipping_method_id = #{shipping_method.id}", "id = #{li.id}") - end - end - - def down - remove_column :spree_line_items, :shipping_method_id - end -end diff --git a/db/migrate/20121005015852_populate_order_default_shipping_method.rb b/db/migrate/20121005015852_populate_order_default_shipping_method.rb deleted file mode 100644 index 2184ee18b0..0000000000 --- a/db/migrate/20121005015852_populate_order_default_shipping_method.rb +++ /dev/null @@ -1,10 +0,0 @@ -class PopulateOrderDefaultShippingMethod < ActiveRecord::Migration - def up - Spree::Order.where(shipping_method_id: nil).each do |order| - order.send(:set_default_shipping_method) - end - end - - def down - end -end diff --git a/db/migrate/20121009232513_create_cms.rb b/db/migrate/20121009232513_create_cms.rb deleted file mode 100644 index d1c1700a5e..0000000000 --- a/db/migrate/20121009232513_create_cms.rb +++ /dev/null @@ -1,137 +0,0 @@ -class CreateCms < ActiveRecord::Migration - - def self.up - - text_limit = case ActiveRecord::Base.connection.adapter_name - when 'PostgreSQL' - { } - else - { :limit => 16777215 } - end - - # -- Sites -------------------------------------------------------------- - create_table :cms_sites do |t| - t.string :label, :null => false - t.string :identifier, :null => false - t.string :hostname, :null => false - t.string :path - t.string :locale, :null => false, :default => 'en' - t.boolean :is_mirrored, :null => false, :default => false - end - add_index :cms_sites, :hostname - add_index :cms_sites, :is_mirrored - - # -- Layouts ------------------------------------------------------------ - create_table :cms_layouts do |t| - t.integer :site_id, :null => false - t.integer :parent_id - t.string :app_layout - t.string :label, :null => false - t.string :identifier, :null => false - t.text :content, text_limit - t.text :css, text_limit - t.text :js, text_limit - t.integer :position, :null => false, :default => 0 - t.boolean :is_shared, :null => false, :default => false - t.timestamps - end - add_index :cms_layouts, [:parent_id, :position] - add_index :cms_layouts, [:site_id, :identifier], :unique => true - - # -- Pages -------------------------------------------------------------- - create_table :cms_pages do |t| - t.integer :site_id, :null => false - t.integer :layout_id - t.integer :parent_id - t.integer :target_page_id - t.string :label, :null => false - t.string :slug - t.string :full_path, :null => false - t.text :content, text_limit - t.integer :position, :null => false, :default => 0 - t.integer :children_count, :null => false, :default => 0 - t.boolean :is_published, :null => false, :default => true - t.boolean :is_shared, :null => false, :default => false - t.timestamps - end - add_index :cms_pages, [:site_id, :full_path] - add_index :cms_pages, [:parent_id, :position] - - # -- Page Blocks -------------------------------------------------------- - create_table :cms_blocks do |t| - t.integer :page_id, :null => false - t.string :identifier, :null => false - t.text :content - t.timestamps - end - add_index :cms_blocks, [:page_id, :identifier] - - # -- Snippets ----------------------------------------------------------- - create_table :cms_snippets do |t| - t.integer :site_id, :null => false - t.string :label, :null => false - t.string :identifier, :null => false - t.text :content, text_limit - t.integer :position, :null => false, :default => 0 - t.boolean :is_shared, :null => false, :default => false - t.timestamps - end - add_index :cms_snippets, [:site_id, :identifier], :unique => true - add_index :cms_snippets, [:site_id, :position] - - # -- Files -------------------------------------------------------------- - create_table :cms_files do |t| - t.integer :site_id, :null => false - t.integer :block_id - t.string :label, :null => false - t.string :file_file_name, :null => false - t.string :file_content_type, :null => false - t.integer :file_file_size, :null => false - t.string :description, :limit => 2048 - t.integer :position, :null => false, :default => 0 - t.timestamps - end - add_index :cms_files, [:site_id, :label] - add_index :cms_files, [:site_id, :file_file_name] - add_index :cms_files, [:site_id, :position] - add_index :cms_files, [:site_id, :block_id] - - # -- Revisions ----------------------------------------------------------- - create_table :cms_revisions, :force => true do |t| - t.string :record_type, :null => false - t.integer :record_id, :null => false - t.text :data, text_limit - t.datetime :created_at - end - add_index :cms_revisions, [:record_type, :record_id, :created_at] - - # -- Categories --------------------------------------------------------- - create_table :cms_categories, :force => true do |t| - t.integer :site_id, :null => false - t.string :label, :null => false - t.string :categorized_type, :null => false - end - add_index :cms_categories, [:site_id, :categorized_type, :label], :unique => true - - create_table :cms_categorizations, :force => true do |t| - t.integer :category_id, :null => false - t.string :categorized_type, :null => false - t.integer :categorized_id, :null => false - end - add_index :cms_categorizations, [:category_id, :categorized_type, :categorized_id], :unique => true, - :name => 'index_cms_categorizations_on_cat_id_and_catd_type_and_catd_id' - end - - def self.down - drop_table :cms_sites - drop_table :cms_layouts - drop_table :cms_pages - drop_table :cms_snippets - drop_table :cms_blocks - drop_table :cms_files - drop_table :cms_revisions - drop_table :cms_categories - drop_table :cms_categorizations - end -end - diff --git a/db/migrate/20121010004400_add_long_description_to_distributors_and_suppliers.rb b/db/migrate/20121010004400_add_long_description_to_distributors_and_suppliers.rb deleted file mode 100644 index 7b3e2aa9f1..0000000000 --- a/db/migrate/20121010004400_add_long_description_to_distributors_and_suppliers.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddLongDescriptionToDistributorsAndSuppliers < ActiveRecord::Migration - def change - add_column :distributors, :long_description, :text - add_column :suppliers, :long_description, :text - end -end diff --git a/db/migrate/20121018002907_add_group_buy_unit_size_to_products.rb b/db/migrate/20121018002907_add_group_buy_unit_size_to_products.rb deleted file mode 100644 index 4abc9e5923..0000000000 --- a/db/migrate/20121018002907_add_group_buy_unit_size_to_products.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddGroupBuyUnitSizeToProducts < ActiveRecord::Migration - def change - add_column :spree_products, :group_buy_unit_size, :string - end -end diff --git a/db/migrate/20121025012233_combine_suppliers_and_distributors_into_enterprises.rb b/db/migrate/20121025012233_combine_suppliers_and_distributors_into_enterprises.rb deleted file mode 100644 index 7eff3e6961..0000000000 --- a/db/migrate/20121025012233_combine_suppliers_and_distributors_into_enterprises.rb +++ /dev/null @@ -1,69 +0,0 @@ -class CombineSuppliersAndDistributorsIntoEnterprises < ActiveRecord::Migration - class Supplier < ActiveRecord::Base; end - class Distributor < ActiveRecord::Base; end - class Enterprise < ActiveRecord::Base; end - class ProductDistribution < ActiveRecord::Base; end - class Spree::Product < ActiveRecord::Base; end - class Spree::Order < ActiveRecord::Base; end - - - def up - # Create enterprises table - create_table :enterprises do |t| - t.string :name - t.string :description - t.text :long_description - t.boolean :is_primary_producer - t.boolean :is_distributor - t.string :contact - t.string :phone - t.string :email - t.string :website - t.string :twitter - t.string :abn - t.string :acn - t.integer :address_id - t.string :pickup_times - t.integer :pickup_address_id - t.string :next_collection_at - t.timestamps - end - - # Copy suppliers to enterprises table with primary producer flag set - updated_product_ids = [-1] - Supplier.all.each do |s| - attrs = s.attributes - attrs.reject! { |k| k == 'id' } - attrs.merge! is_primary_producer: true, is_distributor: false - e = Enterprise.create! attrs - - # Update supplier_id on product to point at the new enterprise - product_ids = Spree::Product.where(:supplier_id => s.id).pluck(:id) - Spree::Product.update_all("supplier_id=#{e.id}", "supplier_id=#{s.id} AND id NOT IN (#{updated_product_ids.join(', ')})") - updated_product_ids += product_ids - end - - # Copy distributors to enterprises table with distributor flag set - updated_product_distribution_ids = [-1] - updated_order_ids = [-1] - Distributor.all.each do |d| - attrs = d.attributes - attrs['website'] = attrs['url'] - attrs.reject! { |k| ['id', 'url'].include? k } - attrs.merge! is_primary_producer: false, is_distributor: true - e = Enterprise.create! attrs - - # Update distributor_id on product distribution and order to point at the new enterprise - product_distribution_ids = ProductDistribution.where(:distributor_id => d.id).pluck(:id) - order_ids = Spree::Order.where(:distributor_id => d.id).pluck(:id) - ProductDistribution.update_all("distributor_id=#{e.id}", "distributor_id=#{d.id} AND id NOT IN (#{updated_product_distribution_ids.join(', ')})") - Spree::Order.update_all("distributor_id=#{e.id}", "distributor_id=#{d.id} AND id NOT IN (#{updated_order_ids.join(', ')})") - updated_product_distribution_ids += product_distribution_ids - updated_order_ids += order_ids - end - end - - def down - drop_table :enterprises - end -end diff --git a/db/migrate/20121028070200_remove_pickup_address_from_enterprises.rb b/db/migrate/20121028070200_remove_pickup_address_from_enterprises.rb deleted file mode 100644 index d1c7fd0d56..0000000000 --- a/db/migrate/20121028070200_remove_pickup_address_from_enterprises.rb +++ /dev/null @@ -1,21 +0,0 @@ -class RemovePickupAddressFromEnterprises < ActiveRecord::Migration - class Enterprise < ActiveRecord::Base; end - - def up - Enterprise.all.each do |e| - e.address_id ||= e.pickup_address_id - e.save! - end - - remove_column :enterprises, :pickup_address_id - end - - def down - add_column :enterprises, :pickup_address_id, :integer - - Enterprise.all.each do |e| - e.pickup_address_id ||= e.address_id - e.save! - end - end -end diff --git a/db/migrate/20121031203807_change_group_buy_unit_size_from_string_to_float.rb b/db/migrate/20121031203807_change_group_buy_unit_size_from_string_to_float.rb deleted file mode 100644 index 44caf3beaa..0000000000 --- a/db/migrate/20121031203807_change_group_buy_unit_size_from_string_to_float.rb +++ /dev/null @@ -1,21 +0,0 @@ -class ChangeGroupBuyUnitSizeFromStringToFloat < ActiveRecord::Migration - class Spree::Product < ActiveRecord::Base; end - - def up - add_column :spree_products, :group_buy_unit_size_f, :float - Spree::Product.reset_column_information - - Spree::Product.all.each do |product| - product.group_buy_unit_size_f = product.group_buy_unit_size.to_f - product.save! - end - - remove_column :spree_products, :group_buy_unit_size - rename_column :spree_products, :group_buy_unit_size_f, :group_buy_unit_size - end - - def down - change_column :spree_products, :group_buy_unit_size, :string - end - -end diff --git a/db/migrate/20121031222403_remove_suppliers_and_distributors.rb b/db/migrate/20121031222403_remove_suppliers_and_distributors.rb deleted file mode 100644 index ece31be171..0000000000 --- a/db/migrate/20121031222403_remove_suppliers_and_distributors.rb +++ /dev/null @@ -1,37 +0,0 @@ -class RemoveSuppliersAndDistributors < ActiveRecord::Migration - def up - drop_table :suppliers - drop_table :distributors - end - - def down - create_table "distributors" do |t| - t.string :name - t.string :contact - t.string :phone - t.string :email - t.string :pickup_times - t.string :url - t.string :abn - t.string :acn - t.string :description - t.datetime :created_at - t.datetime :updated_at - t.integer :pickup_address_id - t.string :next_collection_at - t.text :long_description - end - - create_table "suppliers" do |t| - t.string :name - t.string :description - t.string :email - t.string :twitter - t.string :website - t.datetime :created_at - t.datetime :updated_at - t.integer :address_id - t.text :long_description - end - end -end diff --git a/db/migrate/20121115010717_create_enterprise_fees.rb b/db/migrate/20121115010717_create_enterprise_fees.rb deleted file mode 100644 index 00c3057bfb..0000000000 --- a/db/migrate/20121115010717_create_enterprise_fees.rb +++ /dev/null @@ -1,11 +0,0 @@ -class CreateEnterpriseFees < ActiveRecord::Migration - def change - create_table :enterprise_fees do |t| - t.references :enterprise - t.string :fee_type - t.string :name - - t.timestamps - end - end -end diff --git a/db/migrate/20121125232613_create_order_cycles.rb b/db/migrate/20121125232613_create_order_cycles.rb deleted file mode 100644 index 9d0e4bab90..0000000000 --- a/db/migrate/20121125232613_create_order_cycles.rb +++ /dev/null @@ -1,35 +0,0 @@ -class CreateOrderCycles < ActiveRecord::Migration - def change - create_table :order_cycles do |t| - t.string :name - t.datetime :orders_open_at - t.datetime :orders_close_at - t.references :coordinator - t.references :coordinator_admin_fee - t.references :coordinator_sales_fee - t.timestamps - end - - create_table :exchanges do |t| - t.references :order_cycle - t.references :sender - t.references :receiver - t.references :payment_enterprise - t.datetime :pickup_time - t.string :pickup_instructions - t.timestamps - end - - create_table :exchange_variants do |t| - t.references :exchange - t.references :variant - t.timestamps - end - - create_table :exchange_fees do |t| - t.references :exchange - t.references :enterprise_fee - t.timestamps - end - end -end diff --git a/db/migrate/20130118031610_change_exchange_pickup_time_to_string.rb b/db/migrate/20130118031610_change_exchange_pickup_time_to_string.rb deleted file mode 100644 index 1fca44c81b..0000000000 --- a/db/migrate/20130118031610_change_exchange_pickup_time_to_string.rb +++ /dev/null @@ -1,9 +0,0 @@ -class ChangeExchangePickupTimeToString < ActiveRecord::Migration - def up - change_column :exchanges, :pickup_time, :string - end - - def down - change_column :exchanges, :pickup_time, :datetime - end -end diff --git a/db/migrate/20130130204355_add_order_cycle_id_to_orders.rb b/db/migrate/20130130204355_add_order_cycle_id_to_orders.rb deleted file mode 100644 index 871cb2b2f7..0000000000 --- a/db/migrate/20130130204355_add_order_cycle_id_to_orders.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddOrderCycleIdToOrders < ActiveRecord::Migration - def change - add_column :spree_orders, :order_cycle_id, :integer - end -end diff --git a/db/migrate/20130207043036_create_tokenized_permissions_table.spree.rb b/db/migrate/20130207043036_create_tokenized_permissions_table.spree.rb deleted file mode 100644 index 91c8ad18ab..0000000000 --- a/db/migrate/20130207043036_create_tokenized_permissions_table.spree.rb +++ /dev/null @@ -1,17 +0,0 @@ -# This migration comes from spree (originally 20120509055454) -class CreateTokenizedPermissionsTable < ActiveRecord::Migration - def change - unless Spree::TokenizedPermission.table_exists? - create_table :spree_tokenized_permissions do |t| - t.integer :permissable_id - t.string :permissable_type - t.string :token - - t.timestamps - end - - add_index :spree_tokenized_permissions, [:permissable_id, :permissable_type], :name => 'index_tokenized_name_and_type' - end - end -end - diff --git a/db/migrate/20130207043037_rename_creditcards_to_credit_cards.spree.rb b/db/migrate/20130207043037_rename_creditcards_to_credit_cards.spree.rb deleted file mode 100644 index b6d61a8a8c..0000000000 --- a/db/migrate/20130207043037_rename_creditcards_to_credit_cards.spree.rb +++ /dev/null @@ -1,12 +0,0 @@ -# This migration comes from spree (originally 20120530012000) -class RenameCreditcardsToCreditCards < ActiveRecord::Migration - def change - rename_table :spree_creditcards, :spree_credit_cards - execute("UPDATE spree_payments SET source_type = 'Spree::CreditCard' WHERE source_type = 'Spree::Creditcard'") - end - - def down - execute("UPDATE spree_payments SET source_type = 'Spree::Creditcard' WHERE source_type = 'Spree::CreditCard'") - rename_table :spree_credit_cards, :spree_creditcards - end -end diff --git a/db/migrate/20130207043038_remove_credit_total_from_orders.spree.rb b/db/migrate/20130207043038_remove_credit_total_from_orders.spree.rb deleted file mode 100644 index 09559d50fa..0000000000 --- a/db/migrate/20130207043038_remove_credit_total_from_orders.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20120604203654) -class RemoveCreditTotalFromOrders < ActiveRecord::Migration - def change - remove_column :spree_orders, :credit_total - end -end diff --git a/db/migrate/20130207043039_add_tax_rate_label.spree.rb b/db/migrate/20130207043039_add_tax_rate_label.spree.rb deleted file mode 100644 index c39a83c5ee..0000000000 --- a/db/migrate/20130207043039_add_tax_rate_label.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20120905145253) -class AddTaxRateLabel < ActiveRecord::Migration - def change - add_column :spree_tax_rates, :name, :string - end -end diff --git a/db/migrate/20130207043040_add_toggle_tax_rate_display.spree.rb b/db/migrate/20130207043040_add_toggle_tax_rate_display.spree.rb deleted file mode 100644 index 83da18b4f4..0000000000 --- a/db/migrate/20130207043040_add_toggle_tax_rate_display.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20120905151823) -class AddToggleTaxRateDisplay < ActiveRecord::Migration - def change - add_column :spree_tax_rates, :show_rate_in_label, :boolean, :default => true - end -end diff --git a/db/migrate/20130207043041_add_lock_version_to_variant.spree.rb b/db/migrate/20130207043041_add_lock_version_to_variant.spree.rb deleted file mode 100644 index 0e8cc92328..0000000000 --- a/db/migrate/20130207043041_add_lock_version_to_variant.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20121009142519) -class AddLockVersionToVariant < ActiveRecord::Migration - def change - add_column :spree_variants, :lock_version, :integer, :default => 0 - end -end diff --git a/db/migrate/20130207043042_remove_not_null_constraint_from_products_on_hand.spree.rb b/db/migrate/20130207043042_remove_not_null_constraint_from_products_on_hand.spree.rb deleted file mode 100644 index acbebfc6cb..0000000000 --- a/db/migrate/20130207043042_remove_not_null_constraint_from_products_on_hand.spree.rb +++ /dev/null @@ -1,12 +0,0 @@ -# This migration comes from spree (originally 20121017010007) -class RemoveNotNullConstraintFromProductsOnHand < ActiveRecord::Migration - def up - change_column :spree_products, :count_on_hand, :integer, :null => true - change_column :spree_variants, :count_on_hand, :integer, :null => true - end - - def down - change_column :spree_products, :count_on_hand, :integer, :null => false - change_column :spree_variants, :count_on_hand, :integer, :null => false - end -end diff --git a/db/migrate/20130207043043_add_position_to_taxonomies.spree.rb b/db/migrate/20130207043043_add_position_to_taxonomies.spree.rb deleted file mode 100644 index 177870b42a..0000000000 --- a/db/migrate/20130207043043_add_position_to_taxonomies.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20121124203911) -class AddPositionToTaxonomies < ActiveRecord::Migration - def change - add_column :spree_taxonomies, :position, :integer, :default => 0 - end -end diff --git a/db/migrate/20130207043044_add_identifier_to_spree_payments.spree.rb b/db/migrate/20130207043044_add_identifier_to_spree_payments.spree.rb deleted file mode 100644 index 91a65d92cb..0000000000 --- a/db/migrate/20130207043044_add_identifier_to_spree_payments.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130203232234) -class AddIdentifierToSpreePayments < ActiveRecord::Migration - def change - add_column :spree_payments, :identifier, :string - end -end diff --git a/db/migrate/20130207043046_rename_api_key_to_spree_api_key.spree_api.rb b/db/migrate/20130207043046_rename_api_key_to_spree_api_key.spree_api.rb deleted file mode 100644 index 7fd09d3b11..0000000000 --- a/db/migrate/20130207043046_rename_api_key_to_spree_api_key.spree_api.rb +++ /dev/null @@ -1,8 +0,0 @@ -# This migration comes from spree_api (originally 20120530054546) -class RenameApiKeyToSpreeApiKey < ActiveRecord::Migration - def change - unless defined?(User) - rename_column :spree_users, :api_key, :spree_api_key - end - end -end diff --git a/db/migrate/20130207043047_create_users.spree_auth.rb b/db/migrate/20130207043047_create_users.spree_auth.rb deleted file mode 100644 index a4e8e602d2..0000000000 --- a/db/migrate/20130207043047_create_users.spree_auth.rb +++ /dev/null @@ -1,30 +0,0 @@ -# This migration comes from spree_auth (originally 20101026184949) -class CreateUsers < ActiveRecord::Migration - def up - unless table_exists?("spree_users") - create_table "spree_users", :force => true do |t| - t.string "crypted_password", :limit => 128 - t.string "salt", :limit => 128 - t.string "email" - t.string "remember_token" - t.string "remember_token_expires_at" - t.string "persistence_token" - t.string "single_access_token" - t.string "perishable_token" - t.integer "login_count", :default => 0, :null => false - t.integer "failed_login_count", :default => 0, :null => false - t.datetime "last_request_at" - t.datetime "current_login_at" - t.datetime "last_login_at" - t.string "current_login_ip" - t.string "last_login_ip" - t.string "login" - t.integer "ship_address_id" - t.integer "bill_address_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.string "openid_identifier" - end - end - end -end diff --git a/db/migrate/20130207043541_spree_one_two.spree.rb b/db/migrate/20130207043541_spree_one_two.spree.rb deleted file mode 100644 index ad81bfeabe..0000000000 --- a/db/migrate/20130207043541_spree_one_two.spree.rb +++ /dev/null @@ -1,482 +0,0 @@ -# This migration comes from spree (originally 20120831092320) -class SpreeOneTwo < ActiveRecord::Migration - def up - # This migration is just a compressed version of all the previous - # migrations for spree_core. Do not run it if one of the core tables - # already exists. Assume the best. - return if table_exists?(:spree_addresses) - - - create_table :spree_activators do |t| - t.string :description - t.datetime :expires_at - t.datetime :starts_at - t.string :name - t.string :event_name - t.string :type - t.integer :usage_limit - t.string :match_policy, :default => 'all' - t.string :code - t.boolean :advertise, :default => false - t.string :path - t.timestamps - end - - create_table :spree_addresses do |t| - t.string :firstname - t.string :lastname - t.string :address1 - t.string :address2 - t.string :city - t.string :zipcode - t.string :phone - t.string :state_name - t.string :alternative_phone - t.string :company - t.references :state - t.references :country - t.timestamps - end - - add_index :spree_addresses, [:firstname], :name => 'index_addresses_on_firstname' - add_index :spree_addresses, [:lastname], :name => 'index_addresses_on_lastname' - - create_table :spree_adjustments do |t| - t.references :source, :polymorphic => true - t.references :adjustable, :polymorphic => true - t.references :originator, :polymorphic => true - t.decimal :amount, :precision => 8, :scale => 2 - t.string :label - t.boolean :mandatory - t.boolean :locked - t.boolean :eligible, :default => true - t.timestamps - end - - add_index :spree_adjustments, [:adjustable_id], :name => 'index_adjustments_on_order_id' - - create_table :spree_assets do |t| - t.references :viewable, :polymorphic => true - t.integer :attachment_width - t.integer :attachment_height - t.integer :attachment_file_size - t.integer :position - t.string :attachment_content_type - t.string :attachment_file_name - t.string :type, :limit => 75 - t.datetime :attachment_updated_at - t.text :alt - end - - add_index :spree_assets, [:viewable_id], :name => 'index_assets_on_viewable_id' - add_index :spree_assets, [:viewable_type, :type], :name => 'index_assets_on_viewable_type_and_type' - - create_table :spree_calculators do |t| - t.string :type - t.references :calculable, :polymorphic => true - t.timestamps - end - - create_table :spree_configurations do |t| - t.string :name - t.string :type, :limit => 50 - t.timestamps - end - - add_index :spree_configurations, [:name, :type], :name => 'index_spree_configurations_on_name_and_type' - - create_table :spree_countries do |t| - t.string :iso_name - t.string :iso - t.string :iso3 - t.string :name - t.integer :numcode - end - - create_table :spree_credit_cards do |t| - t.string :month - t.string :year - t.string :cc_type - t.string :last_digits - t.string :first_name - t.string :last_name - t.string :start_month - t.string :start_year - t.string :issue_number - t.references :address - t.string :gateway_customer_profile_id - t.string :gateway_payment_profile_id - t.timestamps - end - - create_table :spree_gateways do |t| - t.string :type - t.string :name - t.text :description - t.boolean :active, :default => true - t.string :environment, :default => 'development' - t.string :server, :default => 'test' - t.boolean :test_mode, :default => true - t.timestamps - end - - create_table :spree_inventory_units do |t| - t.integer :lock_version, :default => 0 - t.string :state - t.references :variant - t.references :order - t.references :shipment - t.references :return_authorization - t.timestamps - end - - add_index :spree_inventory_units, [:order_id], :name => 'index_inventory_units_on_order_id' - add_index :spree_inventory_units, [:shipment_id], :name => 'index_inventory_units_on_shipment_id' - add_index :spree_inventory_units, [:variant_id], :name => 'index_inventory_units_on_variant_id' - - create_table :spree_line_items do |t| - t.references :variant - t.references :order - t.integer :quantity, :null => false - t.decimal :price, :precision => 8, :scale => 2, :null => false - t.timestamps - end - - add_index :spree_line_items, [:order_id], :name => 'index_spree_line_items_on_order_id' - add_index :spree_line_items, [:variant_id], :name => 'index_spree_line_items_on_variant_id' - - create_table :spree_log_entries do |t| - t.references :source, :polymorphic => true - t.text :details - t.timestamps - end - - create_table :spree_mail_methods do |t| - t.string :environment - t.boolean :active, :default => true - t.timestamps - end - - create_table :spree_option_types do |t| - t.string :name, :limit => 100 - t.string :presentation, :limit => 100 - t.integer :position, :default => 0, :null => false - t.timestamps - end - - create_table :spree_option_types_prototypes, :id => false do |t| - t.references :prototype - t.references :option_type - end - - create_table :spree_option_values do |t| - t.integer :position - t.string :name - t.string :presentation - t.references :option_type - t.timestamps - end - - create_table :spree_option_values_variants, :id => false do |t| - t.references :variant - t.references :option_value - end - - add_index :spree_option_values_variants, [:variant_id, :option_value_id], :name => 'index_option_values_variants_on_variant_id_and_option_value_id' - add_index :spree_option_values_variants, [:variant_id], :name => 'index_spree_option_values_variants_on_variant_id' - - create_table :spree_orders do |t| - t.string :number, :limit => 15 - t.decimal :item_total, :precision => 8, :scale => 2, :default => 0.0, :null => false - t.decimal :total, :precision => 8, :scale => 2, :default => 0.0, :null => false - t.string :state - t.decimal :adjustment_total, :precision => 8, :scale => 2, :default => 0.0, :null => false - t.references :user - t.datetime :completed_at - t.references :bill_address - t.references :ship_address - t.decimal :payment_total, :precision => 8, :scale => 2, :default => 0.0 - t.references :shipping_method - t.string :shipment_state - t.string :payment_state - t.string :email - t.text :special_instructions - t.timestamps - end - - add_index :spree_orders, [:number], :name => 'index_spree_orders_on_number' - - create_table :spree_payment_methods do |t| - t.string :type - t.string :name - t.text :description - t.boolean :active, :default => true - t.string :environment, :default => 'development' - t.datetime :deleted_at - t.string :display_on - t.timestamps - end - - create_table :spree_payments do |t| - t.decimal :amount, :precision => 8, :scale => 2, :default => 0.0, :null => false - t.references :order - t.references :source, :polymorphic => true - t.references :payment_method - t.string :state - t.string :response_code - t.string :avs_response - t.timestamps - end - - create_table :spree_preferences do |t| - t.string :name, :limit => 100 - t.references :owner, :polymorphic => true - t.text :value - t.string :key - t.string :value_type - t.timestamps - end - - add_index :spree_preferences, [:key], :name => 'index_spree_preferences_on_key', :unique => true - - create_table :spree_product_option_types do |t| - t.integer :position - t.references :product - t.references :option_type - t.timestamps - end - - create_table :spree_product_properties do |t| - t.string :value - t.references :product - t.references :property - t.timestamps - end - - add_index :spree_product_properties, [:product_id], :name => 'index_product_properties_on_product_id' - - create_table :spree_products do |t| - t.string :name, :default => '', :null => false - t.text :description - t.datetime :available_on - t.datetime :deleted_at - t.string :permalink - t.string :meta_description - t.string :meta_keywords - t.references :tax_category - t.references :shipping_category - t.integer :count_on_hand, :default => 0, :null => false - t.timestamps - end - - add_index :spree_products, [:available_on], :name => 'index_spree_products_on_available_on' - add_index :spree_products, [:deleted_at], :name => 'index_spree_products_on_deleted_at' - add_index :spree_products, [:name], :name => 'index_spree_products_on_name' - add_index :spree_products, [:permalink], :name => 'index_spree_products_on_permalink' - - create_table :spree_products_taxons, :id => false do |t| - t.references :product - t.references :taxon - end - - add_index :spree_products_taxons, [:product_id], :name => 'index_spree_products_taxons_on_product_id' - add_index :spree_products_taxons, [:taxon_id], :name => 'index_spree_products_taxons_on_taxon_id' - - create_table :spree_properties do |t| - t.string :name - t.string :presentation, :null => false - t.timestamps - end - - create_table :spree_properties_prototypes, :id => false do |t| - t.references :prototype - t.references :property - end - - create_table :spree_prototypes do |t| - t.string :name - t.timestamps - end - - create_table :spree_return_authorizations do |t| - t.string :number - t.string :state - t.decimal :amount, :precision => 8, :scale => 2, :default => 0.0, :null => false - t.references :order - t.text :reason - t.timestamps - end - - create_table :spree_roles do |t| - t.string :name - end - - create_table :spree_roles_users, :id => false do |t| - t.references :role - t.references :user - end - - add_index :spree_roles_users, [:role_id], :name => 'index_spree_roles_users_on_role_id' - add_index :spree_roles_users, [:user_id], :name => 'index_spree_roles_users_on_user_id' - - create_table :spree_shipments do |t| - t.string :tracking - t.string :number - t.decimal :cost, :precision => 8, :scale => 2 - t.datetime :shipped_at - t.references :order - t.references :shipping_method - t.references :address - t.string :state - t.timestamps - end - - add_index :spree_shipments, [:number], :name => 'index_shipments_on_number' - - create_table :spree_shipping_categories do |t| - t.string :name - t.timestamps - end - - create_table :spree_shipping_methods do |t| - t.string :name - t.references :zone - t.string :display_on - t.references :shipping_category - t.boolean :match_none - t.boolean :match_all - t.boolean :match_one - t.datetime :deleted_at - t.timestamps - end - - create_table :spree_state_changes do |t| - t.string :name - t.string :previous_state - t.references :stateful - t.references :user - t.string :stateful_type - t.string :next_state - t.timestamps - end - - create_table :spree_states do |t| - t.string :name - t.string :abbr - t.references :country - end - - create_table :spree_tax_categories do |t| - t.string :name - t.string :description - t.boolean :is_default, :default => false - t.datetime :deleted_at - t.timestamps - end - - create_table :spree_tax_rates do |t| - t.decimal :amount, :precision => 8, :scale => 5 - t.references :zone - t.references :tax_category - t.boolean :included_in_price, :default => false - t.timestamps - end - - create_table :spree_taxonomies do |t| - t.string :name, :null => false - t.timestamps - end - - create_table :spree_taxons do |t| - t.references :parent - t.integer :position, :default => 0 - t.string :name, :null => false - t.string :permalink - t.references :taxonomy - t.integer :lft - t.integer :rgt - t.string :icon_file_name - t.string :icon_content_type - t.integer :icon_file_size - t.datetime :icon_updated_at - t.text :description - t.timestamps - end - - add_index :spree_taxons, [:parent_id], :name => 'index_taxons_on_parent_id' - add_index :spree_taxons, [:permalink], :name => 'index_taxons_on_permalink' - add_index :spree_taxons, [:taxonomy_id], :name => 'index_taxons_on_taxonomy_id' - - create_table :spree_tokenized_permissions, :force => true do |t| - t.references :permissable, :polymorphic => true - t.string :token - t.timestamps - end - - add_index :spree_tokenized_permissions, [:permissable_id, :permissable_type], :name => 'index_tokenized_name_and_type' - - create_table :spree_trackers do |t| - t.string :environment - t.string :analytics_id - t.boolean :active, :default => true - t.timestamps - end - - create_table :spree_users do |t| - t.string :encrypted_password, :limit => 128 - t.string :password_salt, :limit => 128 - t.string :email - t.string :remember_token - t.string :persistence_token - t.string :reset_password_token - t.string :perishable_token - t.integer :sign_in_count, :default => 0, :null => false - t.integer :failed_attempts, :default => 0, :null => false - t.datetime :last_request_at - t.datetime :current_sign_in_at - t.datetime :last_sign_in_at - t.string :current_sign_in_ip - t.string :last_sign_in_ip - t.string :login - t.references :ship_address - t.references :bill_address - t.string :authentication_token - t.string :unlock_token - t.datetime :locked_at - t.datetime :remember_created_at - t.datetime :reset_password_sent_at - t.timestamps - end - - create_table :spree_variants do |t| - t.string :sku, :default => '', :null => false - t.decimal :price, :precision => 8, :scale => 2, :null => false - t.decimal :weight, :precision => 8, :scale => 2 - t.decimal :height, :precision => 8, :scale => 2 - t.decimal :width, :precision => 8, :scale => 2 - t.decimal :depth, :precision => 8, :scale => 2 - t.datetime :deleted_at - t.boolean :is_master, :default => false - t.references :product - t.integer :count_on_hand, :default => 0, :null => false - t.decimal :cost_price, :precision => 8, :scale => 2 - t.integer :position - end - - add_index :spree_variants, [:product_id], :name => 'index_spree_variants_on_product_id' - - create_table :spree_zone_members do |t| - t.references :zoneable, :polymorphic => true - t.references :zone - t.timestamps - end - - create_table :spree_zones do |t| - t.string :name - t.string :description - t.boolean :default_tax, :default => false - t.integer :zone_members_count, :default => 0 - t.timestamps - end - end -end diff --git a/db/migrate/20130207043542_remove_unused_preference_columns.spree.rb b/db/migrate/20130207043542_remove_unused_preference_columns.spree.rb deleted file mode 100644 index 6c049daa22..0000000000 --- a/db/migrate/20130207043542_remove_unused_preference_columns.spree.rb +++ /dev/null @@ -1,9 +0,0 @@ -# This migration comes from spree (originally 20120929093553) -class RemoveUnusedPreferenceColumns < ActiveRecord::Migration - def change - # Columns have already been removed if the application was upgraded from an older version, but must be removed from new apps. - remove_column :spree_preferences, :name if ActiveRecord::Base.connection.column_exists?(:spree_preferences, :name) - remove_column :spree_preferences, :owner_id if ActiveRecord::Base.connection.column_exists?(:spree_preferences, :owner_id) - remove_column :spree_preferences, :owner_type if ActiveRecord::Base.connection.column_exists?(:spree_preferences, :owner_type) - end -end diff --git a/db/migrate/20130207043543_add_states_required_to_countries.spree.rb b/db/migrate/20130207043543_add_states_required_to_countries.spree.rb deleted file mode 100644 index 415001d170..0000000000 --- a/db/migrate/20130207043543_add_states_required_to_countries.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20121010142909) -class AddStatesRequiredToCountries < ActiveRecord::Migration - def change - add_column :spree_countries, :states_required, :boolean,:default => true - end -end diff --git a/db/migrate/20130207043544_add_on_demand_to_product_and_variant.spree.rb b/db/migrate/20130207043544_add_on_demand_to_product_and_variant.spree.rb deleted file mode 100644 index ba258ebf26..0000000000 --- a/db/migrate/20130207043544_add_on_demand_to_product_and_variant.spree.rb +++ /dev/null @@ -1,7 +0,0 @@ -# This migration comes from spree (originally 20121012071449) -class AddOnDemandToProductAndVariant < ActiveRecord::Migration - def change - add_column :spree_products, :on_demand, :boolean, :default => false - add_column :spree_variants, :on_demand, :boolean, :default => false - end -end diff --git a/db/migrate/20130207043545_split_prices_from_variants.spree.rb b/db/migrate/20130207043545_split_prices_from_variants.spree.rb deleted file mode 100644 index f22753470f..0000000000 --- a/db/migrate/20130207043545_split_prices_from_variants.spree.rb +++ /dev/null @@ -1,32 +0,0 @@ -# This migration comes from spree (originally 20121031162139) -class SplitPricesFromVariants < ActiveRecord::Migration - def up - create_table :spree_prices do |t| - t.integer :variant_id, :null => false - t.decimal :amount, :precision => 8, :scale => 2, :null => false - t.string :currency - end - - Spree::Variant.all.each do |variant| - Spree::Price.create!( - :variant_id => variant.id, - :amount => variant[:price], - :currency => Spree::Config[:currency] - ) - end - - remove_column :spree_variants, :price - end - - def down - prices = ActiveRecord::Base.connection.execute("select variant_id, amount from spree_prices") - add_column :spree_variants, :price, :decimal, :after => :sku, :scale => 2, :precision => 8 - - prices.each do |price| - ActiveRecord::Base.connection.execute("update spree_variants set price = #{price['amount']} where id = #{price['variant_id']}") - end - - change_column :spree_variants, :price, :decimal, :after => :sku, :scale => 2, :precision => 8, :null => false - drop_table :spree_prices - end -end diff --git a/db/migrate/20130207043546_remove_not_null_from_spree_prices_amount.spree.rb b/db/migrate/20130207043546_remove_not_null_from_spree_prices_amount.spree.rb deleted file mode 100644 index beb5f7a85f..0000000000 --- a/db/migrate/20130207043546_remove_not_null_from_spree_prices_amount.spree.rb +++ /dev/null @@ -1,10 +0,0 @@ -# This migration comes from spree (originally 20121107003422) -class RemoveNotNullFromSpreePricesAmount < ActiveRecord::Migration - def up - change_column :spree_prices, :amount, :decimal, :precision => 8, :scale => 2, :null => true - end - - def down - change_column :spree_prices, :amount, :decimal, :precision => 8, :scale => 2, :null => false - end -end diff --git a/db/migrate/20130207043547_add_currency_to_line_items.spree.rb b/db/migrate/20130207043547_add_currency_to_line_items.spree.rb deleted file mode 100644 index b0732ee630..0000000000 --- a/db/migrate/20130207043547_add_currency_to_line_items.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20121107184631) -class AddCurrencyToLineItems < ActiveRecord::Migration - def change - add_column :spree_line_items, :currency, :string - end -end diff --git a/db/migrate/20130207043548_add_currency_to_orders.spree.rb b/db/migrate/20130207043548_add_currency_to_orders.spree.rb deleted file mode 100644 index d84bc3b7cc..0000000000 --- a/db/migrate/20130207043548_add_currency_to_orders.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20121107194006) -class AddCurrencyToOrders < ActiveRecord::Migration - def change - add_column :spree_orders, :currency, :string - end -end diff --git a/db/migrate/20130207043549_add_cost_currency_to_variants.spree.rb b/db/migrate/20130207043549_add_cost_currency_to_variants.spree.rb deleted file mode 100644 index a31b96499d..0000000000 --- a/db/migrate/20130207043549_add_cost_currency_to_variants.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20121109173623) -class AddCostCurrencyToVariants < ActiveRecord::Migration - def change - add_column :spree_variants, :cost_currency, :string, :after => :cost_price - end -end diff --git a/db/migrate/20130207043550_remove_display_on_from_payment_methods.spree.rb b/db/migrate/20130207043550_remove_display_on_from_payment_methods.spree.rb deleted file mode 100644 index a763d823e9..0000000000 --- a/db/migrate/20130207043550_remove_display_on_from_payment_methods.spree.rb +++ /dev/null @@ -1,10 +0,0 @@ -# This migration comes from spree (originally 20121111231553) -class RemoveDisplayOnFromPaymentMethods < ActiveRecord::Migration - def up - remove_column :spree_payment_methods, :display_on - end - - def down - add_column :spree_payment_methods, :display_on, :string - end -end diff --git a/db/migrate/20130207043551_add_last_ip_to_spree_orders.spree.rb b/db/migrate/20130207043551_add_last_ip_to_spree_orders.spree.rb deleted file mode 100644 index e85fc41ffe..0000000000 --- a/db/migrate/20130207043551_add_last_ip_to_spree_orders.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20121126040517) -class AddLastIpToSpreeOrders < ActiveRecord::Migration - def change - add_column :spree_orders, :last_ip_address, :string - end -end diff --git a/db/migrate/20130207043552_add_display_on_to_spree_payment_methods.spree.rb b/db/migrate/20130207043552_add_display_on_to_spree_payment_methods.spree.rb deleted file mode 100644 index 240870bbb6..0000000000 --- a/db/migrate/20130207043552_add_display_on_to_spree_payment_methods.spree.rb +++ /dev/null @@ -1,10 +0,0 @@ -# This migration comes from spree (originally 20130114053446) -class AddDisplayOnToSpreePaymentMethods < ActiveRecord::Migration - def self.up - add_column :spree_payment_methods, :display_on, :string - end - - def self.down - remove_column :spree_payment_methods, :display_on - end -end diff --git a/db/migrate/20130207043553_add_position_to_product_properties.spree.rb b/db/migrate/20130207043553_add_position_to_product_properties.spree.rb deleted file mode 100644 index 93da5d87b1..0000000000 --- a/db/migrate/20130207043553_add_position_to_product_properties.spree.rb +++ /dev/null @@ -1,7 +0,0 @@ -# This migration comes from spree (originally 20130120201805) -class AddPositionToProductProperties < ActiveRecord::Migration - def change - add_column :spree_product_properties, :position, :integer, :default => 0 - end -end - diff --git a/db/migrate/20130207043554_add_api_key_to_spree_users.spree_api.rb b/db/migrate/20130207043554_add_api_key_to_spree_users.spree_api.rb deleted file mode 100644 index b9e3fe3884..0000000000 --- a/db/migrate/20130207043554_add_api_key_to_spree_users.spree_api.rb +++ /dev/null @@ -1,8 +0,0 @@ -# This migration comes from spree_api (originally 20100107141738) -class AddApiKeyToSpreeUsers < ActiveRecord::Migration - def change - unless defined?(User) - add_column :spree_users, :api_key, :string, :limit => 40 - end - end -end diff --git a/db/migrate/20130207043555_spree_promo_one_two.spree_promo.rb b/db/migrate/20130207043555_spree_promo_one_two.spree_promo.rb deleted file mode 100644 index 7e808c800b..0000000000 --- a/db/migrate/20130207043555_spree_promo_one_two.spree_promo.rb +++ /dev/null @@ -1,46 +0,0 @@ -# This migration comes from spree_promo (originally 20120831092359) -class SpreePromoOneTwo < ActiveRecord::Migration - def up - # This migration is just a compressed migration for all previous versions of spree_promo - return if table_exists?(:spree_products_promotion_rules) - - create_table :spree_products_promotion_rules, :id => false, :force => true do |t| - t.references :product - t.references :promotion_rule - end - - add_index :spree_products_promotion_rules, [:product_id], :name => 'index_products_promotion_rules_on_product_id' - add_index :spree_products_promotion_rules, [:promotion_rule_id], :name => 'index_products_promotion_rules_on_promotion_rule_id' - - create_table :spree_promotion_action_line_items, :force => true do |t| - t.references :promotion_action - t.references :variant - t.integer :quantity, :default => 1 - end - - create_table :spree_promotion_actions, :force => true do |t| - t.references :activator - t.integer :position - t.string :type - end - - create_table :spree_promotion_rules, :force => true do |t| - t.references :activator - t.references :user - t.references :product_group - t.string :type - t.timestamps - end - - add_index :spree_promotion_rules, [:product_group_id], :name => 'index_promotion_rules_on_product_group_id' - add_index :spree_promotion_rules, [:user_id], :name => 'index_promotion_rules_on_user_id' - - create_table :spree_promotion_rules_users, :id => false, :force => true do |t| - t.references :user - t.references :promotion_rule - end - - add_index :spree_promotion_rules_users, [:promotion_rule_id], :name => 'index_promotion_rules_users_on_promotion_rule_id' - add_index :spree_promotion_rules_users, [:user_id], :name => 'index_promotion_rules_users_on_user_id' - end -end diff --git a/db/migrate/20130426023034_add_distributor_info_to_enterprises.enterprises_distributor_info_rich_text_feature.rb b/db/migrate/20130426023034_add_distributor_info_to_enterprises.enterprises_distributor_info_rich_text_feature.rb deleted file mode 100644 index 69a6b9981e..0000000000 --- a/db/migrate/20130426023034_add_distributor_info_to_enterprises.enterprises_distributor_info_rich_text_feature.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from enterprises_distributor_info_rich_text_feature (originally 20130426022945) -class AddDistributorInfoToEnterprises < ActiveRecord::Migration - def change - add_column :enterprises, :distributor_info, :text - end -end diff --git a/db/migrate/20130629120633_add_order_id_index_to_payments.spree.rb b/db/migrate/20130629120633_add_order_id_index_to_payments.spree.rb deleted file mode 100644 index 49b378abb3..0000000000 --- a/db/migrate/20130629120633_add_order_id_index_to_payments.spree.rb +++ /dev/null @@ -1,10 +0,0 @@ -# This migration comes from spree (originally 20130207155350) -class AddOrderIdIndexToPayments < ActiveRecord::Migration - def self.up - add_index :spree_payments, :order_id - end - - def self.down - remove_index :spree_payments, :order_id - end -end diff --git a/db/migrate/20130629120634_add_primary_to_spree_products_taxons.spree.rb b/db/migrate/20130629120634_add_primary_to_spree_products_taxons.spree.rb deleted file mode 100644 index fd438d5c83..0000000000 --- a/db/migrate/20130629120634_add_primary_to_spree_products_taxons.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130208032954) -class AddPrimaryToSpreeProductsTaxons < ActiveRecord::Migration - def change - add_column :spree_products_taxons, :id, :primary_key - end -end diff --git a/db/migrate/20130629120635_add_order_id_index_to_shipments.spree.rb b/db/migrate/20130629120635_add_order_id_index_to_shipments.spree.rb deleted file mode 100644 index 5d0ebdbc78..0000000000 --- a/db/migrate/20130629120635_add_order_id_index_to_shipments.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130222032153) -class AddOrderIdIndexToShipments < ActiveRecord::Migration - def change - add_index :spree_shipments, :order_id - end -end diff --git a/db/migrate/20130629120636_change_meta_description_on_spree_products_to_text.spree.rb b/db/migrate/20130629120636_change_meta_description_on_spree_products_to_text.spree.rb deleted file mode 100644 index 66fff52115..0000000000 --- a/db/migrate/20130629120636_change_meta_description_on_spree_products_to_text.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130226032817) -class ChangeMetaDescriptionOnSpreeProductsToText < ActiveRecord::Migration - def change - change_column :spree_products, :meta_description, :text, :limit => nil - end -end diff --git a/db/migrate/20130629120637_add_variant_id_index_to_spree_prices.spree.rb b/db/migrate/20130629120637_add_variant_id_index_to_spree_prices.spree.rb deleted file mode 100644 index 0a362f2ee8..0000000000 --- a/db/migrate/20130629120637_add_variant_id_index_to_spree_prices.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130226054936) -class AddVariantIdIndexToSpreePrices < ActiveRecord::Migration - def change - add_index :spree_prices, :variant_id - end -end diff --git a/db/migrate/20130629120638_change_orders_total_precision.spree.rb b/db/migrate/20130629120638_change_orders_total_precision.spree.rb deleted file mode 100644 index cfb1c81e6a..0000000000 --- a/db/migrate/20130629120638_change_orders_total_precision.spree.rb +++ /dev/null @@ -1,9 +0,0 @@ -# This migration comes from spree (originally 20130319062004) -class ChangeOrdersTotalPrecision < ActiveRecord::Migration - def change - change_column :spree_orders, :item_total, :decimal, :precision => 10, :scale => 2, :default => 0.0, :null => false - change_column :spree_orders, :total, :decimal, :precision => 10, :scale => 2, :default => 0.0, :null => false - change_column :spree_orders, :adjustment_total, :decimal, :precision => 10, :scale => 2, :default => 0.0, :null => false - change_column :spree_orders, :payment_total, :decimal, :precision => 10, :scale => 2, :default => 0.0 - end -end diff --git a/db/migrate/20130629120639_change_spree_payments_amount_precision.spree.rb b/db/migrate/20130629120639_change_spree_payments_amount_precision.spree.rb deleted file mode 100644 index 2ac4630836..0000000000 --- a/db/migrate/20130629120639_change_spree_payments_amount_precision.spree.rb +++ /dev/null @@ -1,8 +0,0 @@ -# This migration comes from spree (originally 20130319063911) -class ChangeSpreePaymentsAmountPrecision < ActiveRecord::Migration - def change - - change_column :spree_payments, :amount, :decimal, :precision => 10, :scale => 2, :default => 0.0, :null => false - - end -end diff --git a/db/migrate/20130629120640_change_spree_return_authorization_amount_precision.spree.rb b/db/migrate/20130629120640_change_spree_return_authorization_amount_precision.spree.rb deleted file mode 100644 index cf6cc4b3c2..0000000000 --- a/db/migrate/20130629120640_change_spree_return_authorization_amount_precision.spree.rb +++ /dev/null @@ -1,8 +0,0 @@ -# This migration comes from spree (originally 20130319064308) -class ChangeSpreeReturnAuthorizationAmountPrecision < ActiveRecord::Migration - def change - - change_column :spree_return_authorizations, :amount, :decimal, :precision => 10, :scale => 2, :default => 0.0, :null => false - - end -end diff --git a/db/migrate/20130629120641_change_adjustments_amount_precision.spree.rb b/db/migrate/20130629120641_change_adjustments_amount_precision.spree.rb deleted file mode 100644 index f391987c40..0000000000 --- a/db/migrate/20130629120641_change_adjustments_amount_precision.spree.rb +++ /dev/null @@ -1,8 +0,0 @@ -# This migration comes from spree (originally 20130319082943) -class ChangeAdjustmentsAmountPrecision < ActiveRecord::Migration - def change - - change_column :spree_adjustments, :amount, :decimal, :precision => 10, :scale => 2 - - end -end diff --git a/db/migrate/20130629120642_add_seo_metas_to_taxons.spree.rb b/db/migrate/20130629120642_add_seo_metas_to_taxons.spree.rb deleted file mode 100644 index a947764a27..0000000000 --- a/db/migrate/20130629120642_add_seo_metas_to_taxons.spree.rb +++ /dev/null @@ -1,10 +0,0 @@ -# This migration comes from spree (originally 20130328195253) -class AddSeoMetasToTaxons < ActiveRecord::Migration - def change - change_table :spree_taxons do |t| - t.string :meta_title - t.string :meta_description - t.string :meta_keywords - end - end -end diff --git a/db/migrate/20130629120643_add_cvv_result_code_and_cvv_result_message_to_spree_payments.spree.rb b/db/migrate/20130629120643_add_cvv_result_code_and_cvv_result_message_to_spree_payments.spree.rb deleted file mode 100644 index 0f611c6336..0000000000 --- a/db/migrate/20130629120643_add_cvv_result_code_and_cvv_result_message_to_spree_payments.spree.rb +++ /dev/null @@ -1,7 +0,0 @@ -# This migration comes from spree (originally 20130626232741) -class AddCvvResultCodeAndCvvResultMessageToSpreePayments < ActiveRecord::Migration - def change - add_column :spree_payments, :cvv_response_code, :string - add_column :spree_payments, :cvv_response_message, :string - end -end diff --git a/db/migrate/20130629120644_add_unique_index_to_permalink_on_spree_products.spree.rb b/db/migrate/20130629120644_add_unique_index_to_permalink_on_spree_products.spree.rb deleted file mode 100644 index 310d487116..0000000000 --- a/db/migrate/20130629120644_add_unique_index_to_permalink_on_spree_products.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130628021056) -class AddUniqueIndexToPermalinkOnSpreeProducts < ActiveRecord::Migration - def change - add_index "spree_products", ["permalink"], :name => "permalink_idx_unique", :unique => true - end -end diff --git a/db/migrate/20130629120645_add_unique_index_to_orders_shipments_and_stock_transfers.spree.rb b/db/migrate/20130629120645_add_unique_index_to_orders_shipments_and_stock_transfers.spree.rb deleted file mode 100644 index 054cc7402e..0000000000 --- a/db/migrate/20130629120645_add_unique_index_to_orders_shipments_and_stock_transfers.spree.rb +++ /dev/null @@ -1,7 +0,0 @@ -# This migration comes from spree (originally 20130628022817) -class AddUniqueIndexToOrdersShipmentsAndStockTransfers < ActiveRecord::Migration - def add - add_index "spree_orders", ["number"], :name => "number_idx_unique", :unique => true - add_index "spree_shipments", ["number"], :name => "number_idx_unique", :unique => true - end -end diff --git a/db/migrate/20130729021924_make_order_cycle_coordinator_fees_mtm.rb b/db/migrate/20130729021924_make_order_cycle_coordinator_fees_mtm.rb deleted file mode 100644 index ff88d3f493..0000000000 --- a/db/migrate/20130729021924_make_order_cycle_coordinator_fees_mtm.rb +++ /dev/null @@ -1,19 +0,0 @@ -class MakeOrderCycleCoordinatorFeesMtm < ActiveRecord::Migration - def up - remove_column :order_cycles, :coordinator_admin_fee_id - remove_column :order_cycles, :coordinator_sales_fee_id - - create_table :coordinator_fees, id: false do |t| - t.references :order_cycle - t.references :enterprise_fee - end - end - - def down - drop_table :coordinator_fees - - add_column :order_cycles, :coordinator_admin_fee_id, :integer - add_column :order_cycles, :coordinator_sales_fee_id, :integer - end - -end diff --git a/db/migrate/20130729030515_add_enterprise_role.rb b/db/migrate/20130729030515_add_enterprise_role.rb deleted file mode 100644 index 25a1deeeac..0000000000 --- a/db/migrate/20130729030515_add_enterprise_role.rb +++ /dev/null @@ -1,8 +0,0 @@ -class AddEnterpriseRole < ActiveRecord::Migration - def change - create_table :enterprise_roles do |t| - t.references :user, index: true - t.references :enterprise, index: true - end - end -end diff --git a/db/migrate/20130801005801_create_landing_page_images.rb b/db/migrate/20130801005801_create_landing_page_images.rb deleted file mode 100644 index 6b48464d0a..0000000000 --- a/db/migrate/20130801005801_create_landing_page_images.rb +++ /dev/null @@ -1,7 +0,0 @@ -class CreateLandingPageImages < ActiveRecord::Migration - def change - create_table :landing_page_images do |t| - t.timestamps - end - end -end diff --git a/db/migrate/20130801012854_add_attachment_photo_to_landing_page_image.rb b/db/migrate/20130801012854_add_attachment_photo_to_landing_page_image.rb deleted file mode 100644 index 72a4c40de9..0000000000 --- a/db/migrate/20130801012854_add_attachment_photo_to_landing_page_image.rb +++ /dev/null @@ -1,15 +0,0 @@ -class AddAttachmentPhotoToLandingPageImage < ActiveRecord::Migration - def self.up - add_column :landing_page_images, :photo_file_name, :string - add_column :landing_page_images, :photo_content_type, :string - add_column :landing_page_images, :photo_file_size, :integer - add_column :landing_page_images, :photo_updated_at, :datetime - end - - def self.down - remove_column :landing_page_images, :photo_file_name - remove_column :landing_page_images, :photo_content_type - remove_column :landing_page_images, :photo_file_size - remove_column :landing_page_images, :photo_updated_at - end -end diff --git a/db/migrate/20130805050109_update_line_item_caching.rb b/db/migrate/20130805050109_update_line_item_caching.rb deleted file mode 100644 index 70543775c0..0000000000 --- a/db/migrate/20130805050109_update_line_item_caching.rb +++ /dev/null @@ -1,47 +0,0 @@ -class UpdateLineItemCaching < ActiveRecord::Migration - - class SpreeLineItem < ActiveRecord::Base - belongs_to :shipping_method, class_name: 'Spree::ShippingMethod' - belongs_to :variant, :class_name => "Spree::Variant" - - def itemwise_shipping_cost - order = OpenStruct.new :line_items => [self] - shipping_method.compute_amount(order) - end - - def amount - price * quantity - end - alias total amount - end - - - def up - add_column :spree_line_items, :distribution_fee, :decimal, precision: 10, scale: 2 - add_column :spree_line_items, :shipping_method_name, :string - - SpreeLineItem.all.each do |line_item| - line_item.update_column(:distribution_fee, line_item.itemwise_shipping_cost) - line_item.update_column(:shipping_method_name, line_item.shipping_method.name) - end - - remove_column :spree_line_items, :shipping_method_id - end - - def down - add_column :spree_line_items, :shipping_method_id, :integer - - SpreeLineItem.all.each do |line_item| - shipping_method = Spree::ShippingMethod.find_by(name: line_item.shipping_method_name) - unless shipping_method - say "Shipping method #{line_item.shipping_method_name} not found, using the first available shipping method for LineItem #{line_item.id}" - shipping_method = Spree::ShippingMethod.where("name != 'Delivery'").first - end - - line_item.update_column(:shipping_method_id, shipping_method.id) - end - - remove_column :spree_line_items, :distribution_fee - remove_column :spree_line_items, :shipping_method_name - end -end diff --git a/db/migrate/20130805232516_add_enterprise_fee_to_product_distributions.rb b/db/migrate/20130805232516_add_enterprise_fee_to_product_distributions.rb deleted file mode 100644 index b6154c1dd1..0000000000 --- a/db/migrate/20130805232516_add_enterprise_fee_to_product_distributions.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddEnterpriseFeeToProductDistributions < ActiveRecord::Migration - def change - add_column :product_distributions, :enterprise_fee_id, :integer - end -end diff --git a/db/migrate/20130806055125_create_suburbs.rb b/db/migrate/20130806055125_create_suburbs.rb deleted file mode 100644 index bb09b8522b..0000000000 --- a/db/migrate/20130806055125_create_suburbs.rb +++ /dev/null @@ -1,11 +0,0 @@ -class CreateSuburbs < ActiveRecord::Migration - def change - create_table :suburbs do |t| - t.string :name - t.integer :postcode - t.float :latitude - t.float :longitude - t.integer :state_id - end - end -end diff --git a/db/migrate/20130807002915_add_latitude_and_longitude_to_addresses.rb b/db/migrate/20130807002915_add_latitude_and_longitude_to_addresses.rb deleted file mode 100644 index 7fbfe9c30e..0000000000 --- a/db/migrate/20130807002915_add_latitude_and_longitude_to_addresses.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddLatitudeAndLongitudeToAddresses < ActiveRecord::Migration - def change - add_column :spree_addresses, :latitude, :float - add_column :spree_addresses, :longitude, :float - end -end diff --git a/db/migrate/20130807062657_add_distributor_id_to_payment_method.rb b/db/migrate/20130807062657_add_distributor_id_to_payment_method.rb deleted file mode 100644 index 26ea241019..0000000000 --- a/db/migrate/20130807062657_add_distributor_id_to_payment_method.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddDistributorIdToPaymentMethod < ActiveRecord::Migration - def change - add_column :spree_payment_methods, :distributor_id, :integer - end -end diff --git a/db/migrate/20130807230834_add_cart.rb b/db/migrate/20130807230834_add_cart.rb deleted file mode 100644 index 38d94a7c8e..0000000000 --- a/db/migrate/20130807230834_add_cart.rb +++ /dev/null @@ -1,9 +0,0 @@ -class AddCart < ActiveRecord::Migration - def change - create_table :carts do |t| - t.integer :user_id - end - - add_column :spree_orders, :cart_id, :integer - end -end diff --git a/db/migrate/20130809045637_create_enterprise_fee_records_for_product_distributions.rb b/db/migrate/20130809045637_create_enterprise_fee_records_for_product_distributions.rb deleted file mode 100644 index b826f51fdb..0000000000 --- a/db/migrate/20130809045637_create_enterprise_fee_records_for_product_distributions.rb +++ /dev/null @@ -1,26 +0,0 @@ -class CreateEnterpriseFeeRecordsForProductDistributions < ActiveRecord::Migration - - class ProductDistribution < ActiveRecord::Base - belongs_to :shipping_method, :class_name => 'Spree::ShippingMethod' - belongs_to :distributor, :class_name => 'Enterprise' - belongs_to :enterprise_fee - end - - def up - ProductDistribution.all.each do |pd| - calculator = pd.shipping_method.calculator.dup - calculator.save! - - ef = EnterpriseFee.new enterprise_id: pd.distributor.id, fee_type: 'packing', name: pd.shipping_method.name - ef.calculator = calculator - ef.save! - - pd.enterprise_fee = ef - pd.save! - end - end - - def down - ProductDistribution.update_all :enterprise_fee_id => nil - end -end diff --git a/db/migrate/20130809075103_create_adjustment_metadata.rb b/db/migrate/20130809075103_create_adjustment_metadata.rb deleted file mode 100644 index 4d1c6579eb..0000000000 --- a/db/migrate/20130809075103_create_adjustment_metadata.rb +++ /dev/null @@ -1,13 +0,0 @@ -class CreateAdjustmentMetadata < ActiveRecord::Migration - def change - create_table :adjustment_metadata do |t| - t.integer :adjustment_id - t.integer :enterprise_id - t.string :fee_name - t.string :fee_type - t.string :enterprise_role - end - - add_index :adjustment_metadata, :adjustment_id - end -end diff --git a/db/migrate/20130812233634_remove_shipping_method_from_product_distribution.rb b/db/migrate/20130812233634_remove_shipping_method_from_product_distribution.rb deleted file mode 100644 index cf3fee3020..0000000000 --- a/db/migrate/20130812233634_remove_shipping_method_from_product_distribution.rb +++ /dev/null @@ -1,9 +0,0 @@ -class RemoveShippingMethodFromProductDistribution < ActiveRecord::Migration - def up - remove_column :product_distributions, :shipping_method_id - end - - def down - add_column :product_distributions, :shipping_method_id, :integer - end -end diff --git a/db/migrate/20130814010857_remove_shipping_methods_using_itemwise_calculator.rb b/db/migrate/20130814010857_remove_shipping_methods_using_itemwise_calculator.rb deleted file mode 100644 index 7ba21757fd..0000000000 --- a/db/migrate/20130814010857_remove_shipping_methods_using_itemwise_calculator.rb +++ /dev/null @@ -1,15 +0,0 @@ -class RemoveShippingMethodsUsingItemwiseCalculator < ActiveRecord::Migration - class OpenFoodNetwork::Calculator::Itemwise < Spree::Calculator; end - - def up - Spree::ShippingMethod.all.select { |sm| sm.calculator.type == 'OpenFoodNetwork::Calculator::Itemwise' }.each do |sm| - - say "Destroying itemwise shipping method with id #{sm.id}" - sm.destroy - end - end - - def down - Spree::ShippingMethod.create!({name: 'Delivery', zone: Spree::Zone.last, calculator: OpenFoodNetwork::Calculator::Itemwise.new}) - end -end diff --git a/db/migrate/20130830012138_add_distributor_id_to_shipping_methods.rb b/db/migrate/20130830012138_add_distributor_id_to_shipping_methods.rb deleted file mode 100644 index 3039475a10..0000000000 --- a/db/migrate/20130830012138_add_distributor_id_to_shipping_methods.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddDistributorIdToShippingMethods < ActiveRecord::Migration - def change - add_column :spree_shipping_methods, :distributor_id, :integer - add_index :spree_shipping_methods, :distributor_id - end -end diff --git a/db/migrate/20130912021553_create_distributors_payment_methods.rb b/db/migrate/20130912021553_create_distributors_payment_methods.rb deleted file mode 100644 index a9e2ed1738..0000000000 --- a/db/migrate/20130912021553_create_distributors_payment_methods.rb +++ /dev/null @@ -1,20 +0,0 @@ -class CreateDistributorsPaymentMethods < ActiveRecord::Migration - class Spree::PaymentMethod < ActiveRecord::Base - belongs_to :distributor, class_name: 'Enterprise' - has_and_belongs_to_many :distributors, join_table: 'distributors_payment_methods', :class_name => 'Enterprise', association_foreign_key: 'distributor_id' - end - - def up - create_table :distributors_payment_methods, :id => false do |t| - t.references :distributor - t.references :payment_method - end - Spree::PaymentMethod.all.each do |pm| - pm.distributors << pm.distributor if pm.distributor_id - end - end - - def down - drop_table :distributors_payment_methods - end -end diff --git a/db/migrate/20130912021938_remove_distributor_id_from_payment_method.rb b/db/migrate/20130912021938_remove_distributor_id_from_payment_method.rb deleted file mode 100644 index 58bece17cd..0000000000 --- a/db/migrate/20130912021938_remove_distributor_id_from_payment_method.rb +++ /dev/null @@ -1,12 +0,0 @@ -class RemoveDistributorIdFromPaymentMethod < ActiveRecord::Migration - def up - remove_column :spree_payment_methods, :distributor_id - end - - def down - add_column :spree_payment_methods, :distributor_id, :integer - Spree::PaymentMethod.each do |pm| - pm.distributor_id = pm.distributors.first.distributor_id if pm.distributors.first - end - end -end diff --git a/db/migrate/20130919010513_ensure_shipping_methods_have_distributors.rb b/db/migrate/20130919010513_ensure_shipping_methods_have_distributors.rb deleted file mode 100644 index 09017609eb..0000000000 --- a/db/migrate/20130919010513_ensure_shipping_methods_have_distributors.rb +++ /dev/null @@ -1,20 +0,0 @@ -class EnsureShippingMethodsHaveDistributors < ActiveRecord::Migration - class Enterprise < ActiveRecord::Base - scope :is_distributor, -> { where(is_distributor: true) } - end - - def up - d = Enterprise.is_distributor.first - sms = Spree::ShippingMethod.where('distributor_id IS NULL') - - if d - say "Assigning an arbitrary distributor (#{d.name}) to all shipping methods without one (#{sms.count} total)" - sms.update_all(distributor_id: d) - else - say "There are #{sms.count} shipping methods without distributors, but there are no distributors to assign to them" - end - end - - def down - end -end diff --git a/db/migrate/20131016230055_convert_shipping_methods_distributors_to_habtm.rb b/db/migrate/20131016230055_convert_shipping_methods_distributors_to_habtm.rb deleted file mode 100644 index 8d26c88d9b..0000000000 --- a/db/migrate/20131016230055_convert_shipping_methods_distributors_to_habtm.rb +++ /dev/null @@ -1,37 +0,0 @@ -class ConvertShippingMethodsDistributorsToHabtm < ActiveRecord::Migration - class Spree::ShippingMethod < ActiveRecord::Base - belongs_to :distributor, class_name: 'Enterprise' - has_and_belongs_to_many :distributors, join_table: 'distributors_shipping_methods', :class_name => 'Enterprise', association_foreign_key: 'distributor_id' - end - - def up - create_table :distributors_shipping_methods, id: false do |t| - t.references :distributor - t.references :shipping_method - end - add_index :distributors_shipping_methods, :distributor_id - add_index :distributors_shipping_methods, :shipping_method_id - - Spree::ShippingMethod.all.each do |sm| - sm.distributors << sm.distributor if sm.distributor_id - end - - remove_column :spree_shipping_methods, :distributor_id - end - - def down - add_column :spree_shipping_methods, :distributor_id, :integer - add_index :spree_shipping_methods, :distributor_id - - Spree::ShippingMethod.all.each do |sm| - if sm.distributors.present? - sm.distributor = sm.distributors.first - sm.save! - - say "WARNING: Discarding #{sm.distributors.count-1} distributors while flattening HABTM relation to belongs_to" if sm.distributors.count > 1 - end - end - - drop_table :distributors_shipping_methods - end -end diff --git a/db/migrate/20131024005253_create_enterprise_groups.rb b/db/migrate/20131024005253_create_enterprise_groups.rb deleted file mode 100644 index 4a8d01fd0a..0000000000 --- a/db/migrate/20131024005253_create_enterprise_groups.rb +++ /dev/null @@ -1,13 +0,0 @@ -class CreateEnterpriseGroups < ActiveRecord::Migration - def change - create_table :enterprise_groups do |t| - t.string :name - t.boolean :on_front_page - end - - create_table :enterprise_groups_enterprises, id: false do |t| - t.references :enterprise_group - t.references :enterprise - end - end -end diff --git a/db/migrate/20131030031125_add_position_to_enterprise_groups.rb b/db/migrate/20131030031125_add_position_to_enterprise_groups.rb deleted file mode 100644 index 199a045784..0000000000 --- a/db/migrate/20131030031125_add_position_to_enterprise_groups.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddPositionToEnterpriseGroups < ActiveRecord::Migration - def change - add_column :enterprise_groups, :position, :integer - end -end diff --git a/db/migrate/20131128034556_setup_product_units_and_values.rb b/db/migrate/20131128034556_setup_product_units_and_values.rb deleted file mode 100644 index d6cf779aed..0000000000 --- a/db/migrate/20131128034556_setup_product_units_and_values.rb +++ /dev/null @@ -1,14 +0,0 @@ -class SetupProductUnitsAndValues < ActiveRecord::Migration - def change - change_table :spree_products do |t| - t.string :variant_unit - t.float :variant_unit_scale - t.string :variant_unit_name - end - - change_table :spree_variants do |t| - t.float :unit_value - t.string :unit_description - end - end -end diff --git a/db/migrate/20140110040238_make_unit_description_default_blank.rb b/db/migrate/20140110040238_make_unit_description_default_blank.rb deleted file mode 100644 index 58254259ab..0000000000 --- a/db/migrate/20140110040238_make_unit_description_default_blank.rb +++ /dev/null @@ -1,10 +0,0 @@ -class MakeUnitDescriptionDefaultBlank < ActiveRecord::Migration - def up - execute "UPDATE spree_variants SET unit_description='' WHERE unit_description IS NULL" - change_column :spree_variants, :unit_description, :string, default: '' - end - - def down - change_column :spree_variants, :unit_description, :string, default: nil - end -end diff --git a/db/migrate/20140116030500_add_attachment_logo_to_enterprise.rb b/db/migrate/20140116030500_add_attachment_logo_to_enterprise.rb deleted file mode 100644 index 0f3c6e114f..0000000000 --- a/db/migrate/20140116030500_add_attachment_logo_to_enterprise.rb +++ /dev/null @@ -1,15 +0,0 @@ -class AddAttachmentLogoToEnterprise < ActiveRecord::Migration - def self.up - add_column :enterprises, :logo_file_name, :string - add_column :enterprises, :logo_content_type, :string - add_column :enterprises, :logo_file_size, :integer - add_column :enterprises, :logo_updated_at, :datetime - end - - def self.down - remove_column :enterprises, :logo_file_name - remove_column :enterprises, :logo_content_type - remove_column :enterprises, :logo_file_size - remove_column :enterprises, :logo_updated_at - end -end diff --git a/db/migrate/20140121050239_add_attachment_promo_image_to_enterprise.rb b/db/migrate/20140121050239_add_attachment_promo_image_to_enterprise.rb deleted file mode 100644 index d875f111b2..0000000000 --- a/db/migrate/20140121050239_add_attachment_promo_image_to_enterprise.rb +++ /dev/null @@ -1,15 +0,0 @@ -class AddAttachmentPromoImageToEnterprise < ActiveRecord::Migration - def self.up - add_column :enterprises, :promo_image_file_name, :string - add_column :enterprises, :promo_image_content_type, :string - add_column :enterprises, :promo_image_file_size, :integer - add_column :enterprises, :promo_image_updated_at, :datetime - end - - def self.down - remove_column :enterprises, :promo_image_file_name - remove_column :enterprises, :promo_image_content_type - remove_column :enterprises, :promo_image_file_size - remove_column :enterprises, :promo_image_updated_at - end -end diff --git a/db/migrate/20140204011203_add_notes_to_products.rb b/db/migrate/20140204011203_add_notes_to_products.rb deleted file mode 100644 index 5ec603a85c..0000000000 --- a/db/migrate/20140204011203_add_notes_to_products.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddNotesToProducts < ActiveRecord::Migration - def change - add_column :spree_products, :notes, :text - end -end diff --git a/db/migrate/20140213003443_add_require_ship_address_to_shipping_methods.rb b/db/migrate/20140213003443_add_require_ship_address_to_shipping_methods.rb deleted file mode 100644 index a38ad29242..0000000000 --- a/db/migrate/20140213003443_add_require_ship_address_to_shipping_methods.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddRequireShipAddressToShippingMethods < ActiveRecord::Migration - def change - add_column :spree_shipping_methods, :require_ship_address, :boolean, :default => true - add_column :spree_shipping_methods, :description, :text - end -end diff --git a/db/migrate/20140324025840_add_incoming_to_exchanges.rb b/db/migrate/20140324025840_add_incoming_to_exchanges.rb deleted file mode 100644 index 37df0a48db..0000000000 --- a/db/migrate/20140324025840_add_incoming_to_exchanges.rb +++ /dev/null @@ -1,25 +0,0 @@ -class AddIncomingToExchanges < ActiveRecord::Migration - class Exchange < ActiveRecord::Base - belongs_to :order_cycle - belongs_to :receiver, :class_name => 'Enterprise' - - def incoming? - receiver == order_cycle.coordinator - end - end - - - def up - add_column :exchanges, :incoming, :boolean, null: false, default: false - - # Initialise based on whether the exchange is going to or coming - # from the order cycle coordinator - Exchange.all.each do |exchange| - exchange.update_attribute :incoming, exchange.incoming? - end - end - - def down - remove_column :exchanges, :incoming - end -end diff --git a/db/migrate/20140402032034_add_missing_indexes.rb b/db/migrate/20140402032034_add_missing_indexes.rb deleted file mode 100644 index 5c7713d3b6..0000000000 --- a/db/migrate/20140402032034_add_missing_indexes.rb +++ /dev/null @@ -1,38 +0,0 @@ -class AddMissingIndexes < ActiveRecord::Migration - def change - add_index :adjustment_metadata, :enterprise_id - - add_index :carts, :user_id - - add_index :coordinator_fees, :order_cycle_id - add_index :coordinator_fees, :enterprise_fee_id - - add_index :distributors_payment_methods, :distributor_id - add_index :distributors_payment_methods, :payment_method_id - - add_index :enterprise_fees, :enterprise_id - - add_index :enterprise_groups_enterprises, :enterprise_group_id - add_index :enterprise_groups_enterprises, :enterprise_id - - add_index :enterprise_roles, :user_id - add_index :enterprise_roles, :enterprise_id - - add_index :enterprises, :address_id - - add_index :exchange_fees, :exchange_id - add_index :exchange_fees, :enterprise_fee_id - - add_index :exchange_variants, :exchange_id - add_index :exchange_variants, :variant_id - - add_index :exchanges, :order_cycle_id - add_index :exchanges, :sender_id - add_index :exchanges, :receiver_id - add_index :exchanges, :payment_enterprise_id - - add_index :product_distributions, :product_id - add_index :product_distributions, :distributor_id - add_index :product_distributions, :enterprise_fee_id - end -end diff --git a/db/migrate/20140402033428_add_foreign_keys.rb b/db/migrate/20140402033428_add_foreign_keys.rb deleted file mode 100644 index 1535f4f3f9..0000000000 --- a/db/migrate/20140402033428_add_foreign_keys.rb +++ /dev/null @@ -1,188 +0,0 @@ -class AddForeignKeys < ActiveRecord::Migration - class AdjustmentMetadata < ActiveRecord::Base; end - class CoordinatorFee < ActiveRecord::Base; end - class Enterprise < ActiveRecord::Base - belongs_to :address, :class_name => 'Spree::Address' - end - class ExchangeVariant < ActiveRecord::Base; end - class Spree::InventoryUnit < ActiveRecord::Base; end - class Spree::LineItem < ActiveRecord::Base; end - class Spree::Address < ActiveRecord::Base; end - class Spree::Order < ActiveRecord::Base; end - class Spree::Taxon < ActiveRecord::Base; end - - def change - setup_foreign_keys - end - - # http://stackoverflow.com/a/7679513/2720566 - def migrate(direction) - sanitise_data if direction == :up - super - end - - - private - - def sanitise_data - # Remove orphaned AdjustmentMetadata records - orphaned_adjustment_metadata = AdjustmentMetadata.joins('LEFT OUTER JOIN spree_adjustments ON spree_adjustments.id = adjustment_metadata.adjustment_id').where('spree_adjustments.id IS NULL') - say "Destroying #{orphaned_adjustment_metadata.count} orphaned AdjustmentMetadata (of total #{AdjustmentMetadata.count})" - orphaned_adjustment_metadata.destroy_all - - # Remove orphaned ExchangeVariants - orphaned_exchange_variants = ExchangeVariant.joins('LEFT OUTER JOIN spree_variants ON spree_variants.id=exchange_variants.variant_id').where('spree_variants.id IS NULL') - say "Destroying #{orphaned_exchange_variants.count} orphaned ExchangeVariants (of total #{ExchangeVariant.count})" - orphaned_exchange_variants.destroy_all - - # Remove orphaned ExchangeFee records - orphaned_exchange_fees = ExchangeFee.joins('LEFT OUTER JOIN enterprise_fees ON enterprise_fees.id=exchange_fees.enterprise_fee_id').where('enterprise_fees.id IS NULL') - say "Destroying #{orphaned_exchange_fees.count} orphaned ExchangeFees (of total #{ExchangeFee.count})" - orphaned_exchange_fees.destroy_all - - # Remove orphaned Spree::InventoryUnits - orphaned_inventory_units = Spree::InventoryUnit.joins('LEFT OUTER JOIN spree_variants ON spree_variants.id=spree_inventory_units.variant_id').where('spree_variants.id IS NULL') - say "Destroying #{orphaned_inventory_units.count} orphaned InventoryUnits (of total #{Spree::InventoryUnit.count})" - orphaned_inventory_units.destroy_all - - # Remove orphaned Spree::LineItems - orphaned_line_items = Spree::LineItem. - joins('LEFT OUTER JOIN spree_variants ON spree_variants.id=spree_line_items.variant_id'). - joins('LEFT OUTER JOIN spree_orders ON spree_orders.id=spree_line_items.order_id'). - where('spree_variants.id IS NULL OR spree_orders.id IS NULL') - say "Destroying #{orphaned_line_items.count} orphaned LineItems (of total #{Spree::LineItem.count})" - orphaned_line_items.each { |li| li.delete } - - # Update orders without a distributor with a dummy distributor - state = Spree::State.first - country = state.andand.country - unless country && state - country = Spree::Country.create! name: 'Australia', iso_name: 'AU' - state = country.states.create! name: 'Victoria' - end - - address = Spree::Address.create!(firstname: 'Dummy distributor', lastname: 'Dummy distributor', phone: '12345678', state: state, - address1: 'Dummy distributor', city: 'Dummy distributor', zipcode: '1234', country: country) - Enterprise.reset_column_information - deleted_distributor = Enterprise.create!(name: "Deleted distributor", address: address) - - orphaned_orders = Spree::Order.joins('LEFT OUTER JOIN enterprises ON enterprises.id=spree_orders.distributor_id').where('enterprises.id IS NULL') - say "Assigning a dummy distributor to #{orphaned_orders.count} orders with a deleted distributor (of total #{Spree::Order.count})" - orphaned_orders.update_all distributor_id: deleted_distributor.id - - # Remove orphaned Spree::Taxons - orphaned_taxons = Spree::Taxon.joins('LEFT OUTER JOIN spree_taxonomies ON spree_taxonomies.id=spree_taxons.taxonomy_id').where('spree_taxonomies.id IS NULL') - say "Destroying #{orphaned_taxons.count} orphaned Taxons (of total #{Spree::Taxon.count})" - orphaned_taxons.destroy_all - - # Remove orphaned CoordinatorFee records - orphaned_coordinator_fees = CoordinatorFee.joins('LEFT OUTER JOIN enterprise_fees ON enterprise_fees.id = coordinator_fees.enterprise_fee_id').where('enterprise_fees.id IS NULL') - say "Destroying #{orphaned_coordinator_fees.count} orphaned CoordinatorFees (of total #{CoordinatorFee.count})" - orphaned_coordinator_fees.each do |cf| - CoordinatorFee.connection.execute("DELETE FROM coordinator_fees WHERE coordinator_fees.order_cycle_id=#{cf.order_cycle_id} AND coordinator_fees.enterprise_fee_id=#{cf.enterprise_fee_id}") - end - end - - - def setup_foreign_keys - add_foreign_key "adjustment_metadata", "spree_adjustments", name: "adjustment_metadata_adjustment_id_fk", column: "adjustment_id" - add_foreign_key "adjustment_metadata", "enterprises", name: "adjustment_metadata_enterprise_id_fk" - add_foreign_key "carts", "spree_users", name: "carts_user_id_fk", column: "user_id" - add_foreign_key "cms_blocks", "cms_pages", name: "cms_blocks_page_id_fk", column: "page_id" - add_foreign_key "cms_categories", "cms_sites", name: "cms_categories_site_id_fk", column: "site_id", dependent: :delete - add_foreign_key "cms_categorizations", "cms_categories", name: "cms_categorizations_category_id_fk", column: "category_id" - add_foreign_key "cms_files", "cms_blocks", name: "cms_files_block_id_fk", column: "block_id" - add_foreign_key "cms_files", "cms_sites", name: "cms_files_site_id_fk", column: "site_id" - add_foreign_key "cms_layouts", "cms_layouts", name: "cms_layouts_parent_id_fk", column: "parent_id" - add_foreign_key "cms_layouts", "cms_sites", name: "cms_layouts_site_id_fk", column: "site_id", dependent: :delete - add_foreign_key "cms_pages", "cms_layouts", name: "cms_pages_layout_id_fk", column: "layout_id" - add_foreign_key "cms_pages", "cms_pages", name: "cms_pages_parent_id_fk", column: "parent_id" - add_foreign_key "cms_pages", "cms_sites", name: "cms_pages_site_id_fk", column: "site_id", dependent: :delete - add_foreign_key "cms_pages", "cms_pages", name: "cms_pages_target_page_id_fk", column: "target_page_id" - add_foreign_key "cms_snippets", "cms_sites", name: "cms_snippets_site_id_fk", column: "site_id", dependent: :delete - add_foreign_key "coordinator_fees", "enterprise_fees", name: "coordinator_fees_enterprise_fee_id_fk" - add_foreign_key "coordinator_fees", "order_cycles", name: "coordinator_fees_order_cycle_id_fk" - add_foreign_key "distributors_payment_methods", "enterprises", name: "distributors_payment_methods_distributor_id_fk", column: "distributor_id" - add_foreign_key "distributors_payment_methods", "spree_payment_methods", name: "distributors_payment_methods_payment_method_id_fk", column: "payment_method_id" - add_foreign_key "distributors_shipping_methods", "enterprises", name: "distributors_shipping_methods_distributor_id_fk", column: "distributor_id" - add_foreign_key "distributors_shipping_methods", "spree_shipping_methods", name: "distributors_shipping_methods_shipping_method_id_fk", column: "shipping_method_id" - add_foreign_key "enterprise_fees", "enterprises", name: "enterprise_fees_enterprise_id_fk" - add_foreign_key "enterprise_groups_enterprises", "enterprise_groups", name: "enterprise_groups_enterprises_enterprise_group_id_fk" - add_foreign_key "enterprise_groups_enterprises", "enterprises", name: "enterprise_groups_enterprises_enterprise_id_fk" - add_foreign_key "enterprise_roles", "enterprises", name: "enterprise_roles_enterprise_id_fk" - add_foreign_key "enterprise_roles", "spree_users", name: "enterprise_roles_user_id_fk", column: "user_id" - add_foreign_key "enterprises", "spree_addresses", name: "enterprises_address_id_fk", column: "address_id" - add_foreign_key "exchange_fees", "enterprise_fees", name: "exchange_fees_enterprise_fee_id_fk" - add_foreign_key "exchange_fees", "exchanges", name: "exchange_fees_exchange_id_fk" - add_foreign_key "exchange_variants", "exchanges", name: "exchange_variants_exchange_id_fk" - add_foreign_key "exchange_variants", "spree_variants", name: "exchange_variants_variant_id_fk", column: "variant_id" - add_foreign_key "exchanges", "order_cycles", name: "exchanges_order_cycle_id_fk" - add_foreign_key "exchanges", "enterprises", name: "exchanges_payment_enterprise_id_fk", column: "payment_enterprise_id" - add_foreign_key "exchanges", "enterprises", name: "exchanges_receiver_id_fk", column: "receiver_id" - add_foreign_key "exchanges", "enterprises", name: "exchanges_sender_id_fk", column: "sender_id" - add_foreign_key "order_cycles", "enterprises", name: "order_cycles_coordinator_id_fk", column: "coordinator_id" - add_foreign_key "product_distributions", "enterprises", name: "product_distributions_distributor_id_fk", column: "distributor_id" - add_foreign_key "product_distributions", "enterprise_fees", name: "product_distributions_enterprise_fee_id_fk" - add_foreign_key "product_distributions", "spree_products", name: "product_distributions_product_id_fk", column: "product_id" - add_foreign_key "spree_addresses", "spree_countries", name: "spree_addresses_country_id_fk", column: "country_id" - add_foreign_key "spree_addresses", "spree_states", name: "spree_addresses_state_id_fk", column: "state_id" - add_foreign_key "spree_inventory_units", "spree_orders", name: "spree_inventory_units_order_id_fk", column: "order_id" - add_foreign_key "spree_inventory_units", "spree_return_authorizations", name: "spree_inventory_units_return_authorization_id_fk", column: "return_authorization_id" - add_foreign_key "spree_inventory_units", "spree_shipments", name: "spree_inventory_units_shipment_id_fk", column: "shipment_id" - add_foreign_key "spree_inventory_units", "spree_variants", name: "spree_inventory_units_variant_id_fk", column: "variant_id" - add_foreign_key "spree_line_items", "spree_orders", name: "spree_line_items_order_id_fk", column: "order_id" - add_foreign_key "spree_line_items", "spree_variants", name: "spree_line_items_variant_id_fk", column: "variant_id" - add_foreign_key "spree_option_types_prototypes", "spree_option_types", name: "spree_option_types_prototypes_option_type_id_fk", column: "option_type_id" - add_foreign_key "spree_option_types_prototypes", "spree_prototypes", name: "spree_option_types_prototypes_prototype_id_fk", column: "prototype_id" - add_foreign_key "spree_option_values", "spree_option_types", name: "spree_option_values_option_type_id_fk", column: "option_type_id" - add_foreign_key "spree_option_values_variants", "spree_option_values", name: "spree_option_values_variants_option_value_id_fk", column: "option_value_id" - add_foreign_key "spree_option_values_variants", "spree_variants", name: "spree_option_values_variants_variant_id_fk", column: "variant_id" - add_foreign_key "spree_orders", "spree_addresses", name: "spree_orders_bill_address_id_fk", column: "bill_address_id" - add_foreign_key "spree_orders", "carts", name: "spree_orders_cart_id_fk" - add_foreign_key "spree_orders", "enterprises", name: "spree_orders_distributor_id_fk", column: "distributor_id" - add_foreign_key "spree_orders", "order_cycles", name: "spree_orders_order_cycle_id_fk" - add_foreign_key "spree_orders", "spree_addresses", name: "spree_orders_ship_address_id_fk", column: "ship_address_id" - #add_foreign_key "spree_orders", "spree_shipping_methods", name: "spree_orders_shipping_method_id_fk", column: "shipping_method_id" - add_foreign_key "spree_orders", "spree_users", name: "spree_orders_user_id_fk", column: "user_id" - add_foreign_key "spree_payments", "spree_orders", name: "spree_payments_order_id_fk", column: "order_id" - add_foreign_key "spree_payments", "spree_payment_methods", name: "spree_payments_payment_method_id_fk", column: "payment_method_id" - #add_foreign_key "spree_payments", "spree_payments", name: "spree_payments_source_id_fk", column: "source_id" - add_foreign_key "spree_prices", "spree_variants", name: "spree_prices_variant_id_fk", column: "variant_id" - add_foreign_key "spree_product_option_types", "spree_option_types", name: "spree_product_option_types_option_type_id_fk", column: "option_type_id" - add_foreign_key "spree_product_option_types", "spree_products", name: "spree_product_option_types_product_id_fk", column: "product_id" - add_foreign_key "spree_product_properties", "spree_products", name: "spree_product_properties_product_id_fk", column: "product_id" - add_foreign_key "spree_product_properties", "spree_properties", name: "spree_product_properties_property_id_fk", column: "property_id" - add_foreign_key "spree_products_promotion_rules", "spree_products", name: "spree_products_promotion_rules_product_id_fk", column: "product_id" - add_foreign_key "spree_products_promotion_rules", "spree_promotion_rules", name: "spree_products_promotion_rules_promotion_rule_id_fk", column: "promotion_rule_id" - add_foreign_key "spree_products", "spree_shipping_categories", name: "spree_products_shipping_category_id_fk", column: "shipping_category_id" - add_foreign_key "spree_products", "enterprises", name: "spree_products_supplier_id_fk", column: "supplier_id" - add_foreign_key "spree_products", "spree_tax_categories", name: "spree_products_tax_category_id_fk", column: "tax_category_id" - add_foreign_key "spree_products_taxons", "spree_products", name: "spree_products_taxons_product_id_fk", column: "product_id", dependent: :delete - add_foreign_key "spree_products_taxons", "spree_taxons", name: "spree_products_taxons_taxon_id_fk", column: "taxon_id", dependent: :delete - add_foreign_key "spree_promotion_action_line_items", "spree_promotion_actions", name: "spree_promotion_action_line_items_promotion_action_id_fk", column: "promotion_action_id" - add_foreign_key "spree_promotion_action_line_items", "spree_variants", name: "spree_promotion_action_line_items_variant_id_fk", column: "variant_id" - add_foreign_key "spree_promotion_actions", "spree_activators", name: "spree_promotion_actions_activator_id_fk", column: "activator_id" - add_foreign_key "spree_promotion_rules", "spree_activators", name: "spree_promotion_rules_activator_id_fk", column: "activator_id" - add_foreign_key "spree_properties_prototypes", "spree_properties", name: "spree_properties_prototypes_property_id_fk", column: "property_id" - add_foreign_key "spree_properties_prototypes", "spree_prototypes", name: "spree_properties_prototypes_prototype_id_fk", column: "prototype_id" - add_foreign_key "spree_return_authorizations", "spree_orders", name: "spree_return_authorizations_order_id_fk", column: "order_id" - add_foreign_key "spree_roles_users", "spree_roles", name: "spree_roles_users_role_id_fk", column: "role_id" - add_foreign_key "spree_roles_users", "spree_users", name: "spree_roles_users_user_id_fk", column: "user_id" - add_foreign_key "spree_shipments", "spree_addresses", name: "spree_shipments_address_id_fk", column: "address_id" - add_foreign_key "spree_shipments", "spree_orders", name: "spree_shipments_order_id_fk", column: "order_id" - #add_foreign_key "spree_shipments", "spree_shipping_methods", name: "spree_shipments_shipping_method_id_fk", column: "shipping_method_id" - add_foreign_key "spree_shipping_methods", "spree_shipping_categories", name: "spree_shipping_methods_shipping_category_id_fk", column: "shipping_category_id" - add_foreign_key "spree_shipping_methods", "spree_zones", name: "spree_shipping_methods_zone_id_fk", column: "zone_id" - add_foreign_key "spree_state_changes", "spree_users", name: "spree_state_changes_user_id_fk", column: "user_id" - add_foreign_key "spree_states", "spree_countries", name: "spree_states_country_id_fk", column: "country_id" - add_foreign_key "spree_tax_rates", "spree_tax_categories", name: "spree_tax_rates_tax_category_id_fk", column: "tax_category_id" - add_foreign_key "spree_tax_rates", "spree_zones", name: "spree_tax_rates_zone_id_fk", column: "zone_id" - add_foreign_key "spree_taxons", "spree_taxons", name: "spree_taxons_parent_id_fk", column: "parent_id" - add_foreign_key "spree_taxons", "spree_taxonomies", name: "spree_taxons_taxonomy_id_fk", column: "taxonomy_id" - add_foreign_key "spree_users", "spree_addresses", name: "spree_users_bill_address_id_fk", column: "bill_address_id" - add_foreign_key "spree_users", "spree_addresses", name: "spree_users_ship_address_id_fk", column: "ship_address_id" - add_foreign_key "spree_variants", "spree_products", name: "spree_variants_product_id_fk", column: "product_id" - add_foreign_key "spree_zone_members", "spree_zones", name: "spree_zone_members_zone_id_fk", column: "zone_id" - add_foreign_key "suburbs", "spree_states", name: "suburbs_state_id_fk", column: "state_id" - end -end diff --git a/db/migrate/20140425055718_add_active_flag_to_enterprises.rb b/db/migrate/20140425055718_add_active_flag_to_enterprises.rb deleted file mode 100644 index b0bcc2f3ed..0000000000 --- a/db/migrate/20140425055718_add_active_flag_to_enterprises.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddActiveFlagToEnterprises < ActiveRecord::Migration - def change - add_column :enterprises, :active, :boolean, default: true - end -end diff --git a/db/migrate/20140430020639_rename_active_to_visible_on_enterprises.rb b/db/migrate/20140430020639_rename_active_to_visible_on_enterprises.rb deleted file mode 100644 index 99b011304a..0000000000 --- a/db/migrate/20140430020639_rename_active_to_visible_on_enterprises.rb +++ /dev/null @@ -1,5 +0,0 @@ -class RenameActiveToVisibleOnEnterprises < ActiveRecord::Migration - def change - rename_column :enterprises, :active, :visible - end -end diff --git a/db/migrate/20140514044959_create_enterprise_relationships.rb b/db/migrate/20140514044959_create_enterprise_relationships.rb deleted file mode 100644 index 0467d6e560..0000000000 --- a/db/migrate/20140514044959_create_enterprise_relationships.rb +++ /dev/null @@ -1,16 +0,0 @@ -class CreateEnterpriseRelationships < ActiveRecord::Migration - def change - create_table :enterprise_relationships do |t| - t.integer :parent_id - t.integer :child_id - end - - add_index :enterprise_relationships, :parent_id - add_index :enterprise_relationships, :child_id - - add_index :enterprise_relationships, [:parent_id, :child_id], unique: true - - add_foreign_key :enterprise_relationships, :enterprises, column: :parent_id - add_foreign_key :enterprise_relationships, :enterprises, column: :child_id - end -end diff --git a/db/migrate/20140516042552_add_attachment_promo_image_to_enterprise_group.rb b/db/migrate/20140516042552_add_attachment_promo_image_to_enterprise_group.rb deleted file mode 100644 index bd67cb92f0..0000000000 --- a/db/migrate/20140516042552_add_attachment_promo_image_to_enterprise_group.rb +++ /dev/null @@ -1,15 +0,0 @@ -class AddAttachmentPromoImageToEnterpriseGroup < ActiveRecord::Migration - def self.up - add_column :enterprise_groups, :promo_image_file_name, :string - add_column :enterprise_groups, :promo_image_content_type, :string - add_column :enterprise_groups, :promo_image_file_size, :integer - add_column :enterprise_groups, :promo_image_updated_at, :datetime - end - - def self.down - remove_column :enterprise_groups, :promo_image_file_name - remove_column :enterprise_groups, :promo_image_content_type - remove_column :enterprise_groups, :promo_image_file_size - remove_column :enterprise_groups, :promo_image_updated_at - end -end diff --git a/db/migrate/20140516044750_add_fields_to_groups.rb b/db/migrate/20140516044750_add_fields_to_groups.rb deleted file mode 100644 index a50ef1db14..0000000000 --- a/db/migrate/20140516044750_add_fields_to_groups.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddFieldsToGroups < ActiveRecord::Migration - def change - add_column :enterprise_groups, :description, :text - add_column :enterprise_groups, :long_description, :text - end -end diff --git a/db/migrate/20140516045323_add_attachment_logo_to_enterprise_group.rb b/db/migrate/20140516045323_add_attachment_logo_to_enterprise_group.rb deleted file mode 100644 index 525bccb63e..0000000000 --- a/db/migrate/20140516045323_add_attachment_logo_to_enterprise_group.rb +++ /dev/null @@ -1,15 +0,0 @@ -class AddAttachmentLogoToEnterpriseGroup < ActiveRecord::Migration - def self.up - add_column :enterprise_groups, :logo_file_name, :string - add_column :enterprise_groups, :logo_content_type, :string - add_column :enterprise_groups, :logo_file_size, :integer - add_column :enterprise_groups, :logo_updated_at, :datetime - end - - def self.down - remove_column :enterprise_groups, :logo_file_name - remove_column :enterprise_groups, :logo_content_type - remove_column :enterprise_groups, :logo_file_size - remove_column :enterprise_groups, :logo_updated_at - end -end diff --git a/db/migrate/20140522015012_add_social_media_to_enterprises.rb b/db/migrate/20140522015012_add_social_media_to_enterprises.rb deleted file mode 100644 index 9ca88cf0dc..0000000000 --- a/db/migrate/20140522015012_add_social_media_to_enterprises.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AddSocialMediaToEnterprises < ActiveRecord::Migration - def change - add_column :enterprises, :facebook, :string - add_column :enterprises, :instagram, :string - add_column :enterprises, :linkedin, :string - end -end diff --git a/db/migrate/20140522044009_add_primary_taxon_to_products.rb b/db/migrate/20140522044009_add_primary_taxon_to_products.rb deleted file mode 100644 index 34bfae4efa..0000000000 --- a/db/migrate/20140522044009_add_primary_taxon_to_products.rb +++ /dev/null @@ -1,20 +0,0 @@ -class AddPrimaryTaxonToProducts < ActiveRecord::Migration - def up - add_column :spree_products, :primary_taxon_id, :integer - - add_index :spree_products, :primary_taxon_id - add_foreign_key :spree_products, :spree_taxons, column: :primary_taxon_id - - Spree::Product.all.each do |p| - primary_taxon = p.taxons.where('spree_taxons.name != ?', 'specials').first - first_taxon = Spree::Taxonomy.find_by(name: 'Products').andand.root || Spree::Taxon.first - p.update_column :primary_taxon_id, (primary_taxon || first_taxon) - end - - change_column :spree_products, :primary_taxon_id, :integer, null: false - end - - def down - remove_column :spree_products, :primary_taxon_id - end -end diff --git a/db/migrate/20140604051248_add_display_name_and_display_as_to_spree_variants.rb b/db/migrate/20140604051248_add_display_name_and_display_as_to_spree_variants.rb deleted file mode 100644 index a2c1080b31..0000000000 --- a/db/migrate/20140604051248_add_display_name_and_display_as_to_spree_variants.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddDisplayNameAndDisplayAsToSpreeVariants < ActiveRecord::Migration - def change - add_column :spree_variants, :display_name, :string - add_column :spree_variants, :display_as, :string - end -end diff --git a/db/migrate/20140612020206_remove_deleted_variants_from_order_cycles.rb b/db/migrate/20140612020206_remove_deleted_variants_from_order_cycles.rb deleted file mode 100644 index cb03abe09a..0000000000 --- a/db/migrate/20140612020206_remove_deleted_variants_from_order_cycles.rb +++ /dev/null @@ -1,10 +0,0 @@ -class RemoveDeletedVariantsFromOrderCycles < ActiveRecord::Migration - def up - evs = ExchangeVariant.joins(:variant).where('spree_variants.deleted_at IS NOT NULL') - say "Removing #{evs.count} deleted variants from order cycles..." - evs.destroy_all - end - - def down - end -end diff --git a/db/migrate/20140613004344_create_producer_properties.rb b/db/migrate/20140613004344_create_producer_properties.rb deleted file mode 100644 index b45b3bed5d..0000000000 --- a/db/migrate/20140613004344_create_producer_properties.rb +++ /dev/null @@ -1,18 +0,0 @@ -class CreateProducerProperties < ActiveRecord::Migration - def change - create_table :producer_properties do |t| - t.string :value - t.references :producer - t.references :property - t.integer :position - t.timestamps - end - - add_index :producer_properties, :producer_id - add_index :producer_properties, :property_id - add_index :producer_properties, :position - - add_foreign_key :producer_properties, :enterprises, column: :producer_id - add_foreign_key :producer_properties, :spree_properties, column: :property_id - end -end diff --git a/db/migrate/20140621230121_change_suburb_postcode_to_string.rb b/db/migrate/20140621230121_change_suburb_postcode_to_string.rb deleted file mode 100644 index 4756c71c59..0000000000 --- a/db/migrate/20140621230121_change_suburb_postcode_to_string.rb +++ /dev/null @@ -1,9 +0,0 @@ -class ChangeSuburbPostcodeToString < ActiveRecord::Migration - def up - change_column :suburbs, :postcode, :string - end - - def down - change_column :suburbs, :postcode, 'integer USING (postcode::integer)' - end -end diff --git a/db/migrate/20140702053145_add_fields_to_distributors_shipping_methods.rb b/db/migrate/20140702053145_add_fields_to_distributors_shipping_methods.rb deleted file mode 100644 index 75fa60e7b7..0000000000 --- a/db/migrate/20140702053145_add_fields_to_distributors_shipping_methods.rb +++ /dev/null @@ -1,23 +0,0 @@ -class AddFieldsToDistributorsShippingMethods < ActiveRecord::Migration - class DistributorShippingMethod < ActiveRecord::Base - self.table_name = "distributors_shipping_methods" - end - - def up - add_column :distributors_shipping_methods, :id, :primary_key - add_column :distributors_shipping_methods, :created_at, :datetime - add_column :distributors_shipping_methods, :updated_at, :datetime - - DistributorShippingMethod.reset_column_information - DistributorShippingMethod.update_all created_at: Time.zone.now, updated_at: Time.zone.now - - change_column :distributors_shipping_methods, :created_at, :datetime, null: false - change_column :distributors_shipping_methods, :updated_at, :datetime, null: false - end - - def down - remove_column :distributors_shipping_methods, :id - remove_column :distributors_shipping_methods, :created_at - remove_column :distributors_shipping_methods, :updated_at - end -end diff --git a/db/migrate/20140716051214_drop_landing_page_images.rb b/db/migrate/20140716051214_drop_landing_page_images.rb deleted file mode 100644 index d7324ed94b..0000000000 --- a/db/migrate/20140716051214_drop_landing_page_images.rb +++ /dev/null @@ -1,16 +0,0 @@ -class DropLandingPageImages < ActiveRecord::Migration - def up - drop_table :landing_page_images - end - - def down - create_table :landing_page_images do |t| - t.string :photo_file_name - t.string :photo_content_type - t.integer :photo_file_size - t.datetime :photo_updated_at - - t.timestamps - end - end -end diff --git a/db/migrate/20140723021730_create_spree_paypal_express_checkouts.spree_paypal_express.rb b/db/migrate/20140723021730_create_spree_paypal_express_checkouts.spree_paypal_express.rb deleted file mode 100644 index 1f30b68bff..0000000000 --- a/db/migrate/20140723021730_create_spree_paypal_express_checkouts.spree_paypal_express.rb +++ /dev/null @@ -1,9 +0,0 @@ -# This migration comes from spree_paypal_express (originally 20130723042610) -class CreateSpreePaypalExpressCheckouts < ActiveRecord::Migration - def change - create_table :spree_paypal_express_checkouts do |t| - t.string :token - t.string :payer_id - end - end -end diff --git a/db/migrate/20140723021731_add_transaction_id_to_spree_paypal_express_checkouts.spree_paypal_express.rb b/db/migrate/20140723021731_add_transaction_id_to_spree_paypal_express_checkouts.spree_paypal_express.rb deleted file mode 100644 index 3603e8887a..0000000000 --- a/db/migrate/20140723021731_add_transaction_id_to_spree_paypal_express_checkouts.spree_paypal_express.rb +++ /dev/null @@ -1,7 +0,0 @@ -# This migration comes from spree_paypal_express (originally 20130808030836) -class AddTransactionIdToSpreePaypalExpressCheckouts < ActiveRecord::Migration - def change - add_column :spree_paypal_express_checkouts, :transaction_id, :string - add_index :spree_paypal_express_checkouts, :transaction_id - end -end diff --git a/db/migrate/20140723021732_add_state_to_spree_paypal_express_checkouts.spree_paypal_express.rb b/db/migrate/20140723021732_add_state_to_spree_paypal_express_checkouts.spree_paypal_express.rb deleted file mode 100644 index 56a35ae307..0000000000 --- a/db/migrate/20140723021732_add_state_to_spree_paypal_express_checkouts.spree_paypal_express.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree_paypal_express (originally 20130809013846) -class AddStateToSpreePaypalExpressCheckouts < ActiveRecord::Migration - def change - add_column :spree_paypal_express_checkouts, :state, :string, :default => "complete" - end -end diff --git a/db/migrate/20140723021733_add_refunded_fields_to_spree_paypal_express_checkouts.spree_paypal_express.rb b/db/migrate/20140723021733_add_refunded_fields_to_spree_paypal_express_checkouts.spree_paypal_express.rb deleted file mode 100644 index eb2d10e7f7..0000000000 --- a/db/migrate/20140723021733_add_refunded_fields_to_spree_paypal_express_checkouts.spree_paypal_express.rb +++ /dev/null @@ -1,9 +0,0 @@ -# This migration comes from spree_paypal_express (originally 20130809014319) -class AddRefundedFieldsToSpreePaypalExpressCheckouts < ActiveRecord::Migration - def change - add_column :spree_paypal_express_checkouts, :refund_transaction_id, :string - add_column :spree_paypal_express_checkouts, :refunded_at, :datetime - add_column :spree_paypal_express_checkouts, :refund_type, :string - add_column :spree_paypal_express_checkouts, :created_at, :datetime - end -end diff --git a/db/migrate/20140723023713_switch_paypal_methods.rb b/db/migrate/20140723023713_switch_paypal_methods.rb deleted file mode 100644 index 5b5509cb94..0000000000 --- a/db/migrate/20140723023713_switch_paypal_methods.rb +++ /dev/null @@ -1,13 +0,0 @@ -class SwitchPaypalMethods < ActiveRecord::Migration - def up - Spree::PaymentMethod.connection.execute < 1 - e_limit = 100 - e_limit = 1000 if u.admin? - u.update_column :enterprise_limit, e_limit - end - end - end - - def down - remove_column :spree_users, :enterprise_limit - end -end diff --git a/db/migrate/20140927005000_add_dummy_for_missing_emails.rb b/db/migrate/20140927005000_add_dummy_for_missing_emails.rb deleted file mode 100644 index 08f638e2a3..0000000000 --- a/db/migrate/20140927005000_add_dummy_for_missing_emails.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AddDummyForMissingEmails < ActiveRecord::Migration - def up - Enterprise.all.each do |enterprise| - enterprise.update_column(:email, "missing@example.com") if enterprise.read_attribute(:email).blank? - end - end -end diff --git a/db/migrate/20140927005043_enterprise_config_refactor.rb b/db/migrate/20140927005043_enterprise_config_refactor.rb deleted file mode 100644 index 6b51ac6e50..0000000000 --- a/db/migrate/20140927005043_enterprise_config_refactor.rb +++ /dev/null @@ -1,57 +0,0 @@ -class EnterpriseConfigRefactor < ActiveRecord::Migration - class Enterprise < ActiveRecord::Base - self.inheritance_column = nil - end - - def up - add_column :enterprises, :sells, :string, null: false, default: 'none' - add_index :enterprises, :sells - add_index :enterprises, [:is_primary_producer, :sells] - - Enterprise.reset_column_information - - Enterprise.all.each do |enterprise| - enterprise.update_attributes!({:sells => sells_what?(enterprise)}) - end - - remove_column :enterprises, :type - remove_column :enterprises, :is_distributor - end - - def down - # This process is lossy. Producer profiles wont exist. - add_column :enterprises, :type, :string, null: false, default: 'profile' - add_column :enterprises, :is_distributor, :boolean - - Enterprise.reset_column_information - - Enterprise.all.each do |enterprise| - enterprise.update_attributes!({ - :type => type?(enterprise), - :is_distributor => distributes?(enterprise) - }) - end - - remove_column :enterprises, :sells - end - - def sells_what?(enterprise) - is_distributor = enterprise.read_attribute(:is_distributor) - is_primary_producer = enterprise.read_attribute(:is_primary_producer) - type = enterprise.read_attribute(:type) - return "own" if type == "single" && (is_distributor || is_primary_producer) - return "none" if !is_distributor || type == "profile" - return "any" - end - - def distributes?(enterprise) - enterprise.read_attribute(:sells) != "none" - end - - def type?(enterprise) - sells = enterprise.read_attribute(:sells) - return "profile" if sells == "none" - return "single" if sells == "own" - return "full" - end -end diff --git a/db/migrate/20141003060622_add_standard_variant_to_products.rb b/db/migrate/20141003060622_add_standard_variant_to_products.rb deleted file mode 100644 index 5242f86686..0000000000 --- a/db/migrate/20141003060622_add_standard_variant_to_products.rb +++ /dev/null @@ -1,63 +0,0 @@ -class AddStandardVariantToProducts < ActiveRecord::Migration - def up - # Make sure that all products have a variant_unit - Spree::Product.where("variant_unit IS NULL OR variant_unit = ''").update_all(variant_unit: "items", variant_unit_name: "each") - - # Find products without any standard variants - products_with_only_master = Spree::Product.includes(:variants).where('spree_variants.id IS NULL').select('DISTINCT spree_products.*') - - products_with_only_master.each do |product| - # Add a unit_value to the master variant if it doesn't have one - if product.unit_value.blank? - if product.variant_unit == "weight" && match = product.unit_description.andand.match(/^(\d+(\.\d*)?)(k?g) ?(.*)$/) - scale = (match[3] == "kg" ? 1000 : 1) - product.unit_value = (match[1].to_i*scale) - product.unit_description = match[4] - product.save! - else - unless product.variant_unit == "items" && product.unit_description.present? - product.unit_value = 1 - product.save! - end - end - end - - # Run the callback to add a copy of the master variant as a standard variant - product.send(:ensure_standard_variant) - - existing_master = product.master - new_variant = product.variants.first - - # Replace any relevant references to the master variant with the new standard variant - - # Inventory Units - # Strategy: do nothing to inventory units pertaining to existing_master, - # new inventory units will be created with reference to new_variant - - # Line Items - # Strategy: do nothing to line items pertaining to existing_master, - # new line items will be created with reference to new_variant - - # Option Values - # Strategy: add all option values on existing_master to new_variant, and keep on existing_master - option_values = existing_master.option_values - option_values.each do |option_value| - variant_ids = option_value.variant_ids - variant_ids << new_variant.id - option_value.update_attributes(variant_ids: variant_ids) - end - - # Prices - # Strategy: duplicate all prices on existing_master and assign them to new_variant - existing_prices = existing_master.prices - existing_prices.each do |price| - new_variant.prices << price.dup - end - - # Exchange Variants - # Strategy: Replace all references to existing master in exchanges with new_variant - exchange_variants = ExchangeVariant.where(variant_id: existing_master.id) - exchange_variants.update_all(variant_id: new_variant.id) - end - end -end diff --git a/db/migrate/20141010043405_add_confirmable_to_enterprise.rb b/db/migrate/20141010043405_add_confirmable_to_enterprise.rb deleted file mode 100644 index 9c29bd5f2c..0000000000 --- a/db/migrate/20141010043405_add_confirmable_to_enterprise.rb +++ /dev/null @@ -1,16 +0,0 @@ -class AddConfirmableToEnterprise < ActiveRecord::Migration - def up - add_column :enterprises, :confirmation_token, :string - add_column :enterprises, :confirmed_at, :datetime - add_column :enterprises, :confirmation_sent_at, :datetime - add_column :enterprises, :unconfirmed_email, :string - add_index :enterprises, :confirmation_token, :unique => true - - # Existing enterprises are assumed to be confirmed - Enterprise.update_all(:confirmed_at => Time.zone.now) - end - - def down - remove_columns :enterprises, :confirmation_token, :confirmed_at, :confirmation_sent_at, :unconfirmed_email - end -end diff --git a/db/migrate/20141022050659_add_shop_trial_start_date_to_enterprises.rb b/db/migrate/20141022050659_add_shop_trial_start_date_to_enterprises.rb deleted file mode 100644 index c9680f4e40..0000000000 --- a/db/migrate/20141022050659_add_shop_trial_start_date_to_enterprises.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddShopTrialStartDateToEnterprises < ActiveRecord::Migration - def change - add_column :enterprises, :shop_trial_start_date, :datetime, default: nil - end -end diff --git a/db/migrate/20141023050324_add_producer_profile_only_to_enterprises.rb b/db/migrate/20141023050324_add_producer_profile_only_to_enterprises.rb deleted file mode 100644 index fb73d123f8..0000000000 --- a/db/migrate/20141023050324_add_producer_profile_only_to_enterprises.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddProducerProfileOnlyToEnterprises < ActiveRecord::Migration - def change - add_column :enterprises, :producer_profile_only, :boolean, default: false - end -end diff --git a/db/migrate/20141113053004_create_variant_overrides.rb b/db/migrate/20141113053004_create_variant_overrides.rb deleted file mode 100644 index ae3746f828..0000000000 --- a/db/migrate/20141113053004_create_variant_overrides.rb +++ /dev/null @@ -1,15 +0,0 @@ -class CreateVariantOverrides < ActiveRecord::Migration - def change - create_table :variant_overrides do |t| - t.references :variant - t.references :hub - t.decimal :price, precision: 8, scale: 2 - t.integer :count_on_hand - end - - add_foreign_key :variant_overrides, :spree_variants, column: :variant_id - add_foreign_key :variant_overrides, :enterprises, column: :hub_id - - add_index :variant_overrides, [:variant_id, :hub_id] - end -end diff --git a/db/migrate/20141210233407_add_not_null_to_variant_override_relations.rb b/db/migrate/20141210233407_add_not_null_to_variant_override_relations.rb deleted file mode 100644 index b2f50167c9..0000000000 --- a/db/migrate/20141210233407_add_not_null_to_variant_override_relations.rb +++ /dev/null @@ -1,11 +0,0 @@ -class AddNotNullToVariantOverrideRelations < ActiveRecord::Migration - def up - change_column :variant_overrides, :hub_id, :integer, null: false - change_column :variant_overrides, :variant_id, :integer, null: false - end - - def down - change_column :variant_overrides, :hub_id, :integer, null: true - change_column :variant_overrides, :variant_id, :integer, null: true - end -end diff --git a/db/migrate/20141219034321_add_permalink_to_enterprises.rb b/db/migrate/20141219034321_add_permalink_to_enterprises.rb deleted file mode 100644 index 850e1cf171..0000000000 --- a/db/migrate/20141219034321_add_permalink_to_enterprises.rb +++ /dev/null @@ -1,25 +0,0 @@ -class AddPermalinkToEnterprises < ActiveRecord::Migration - def up - add_column :enterprises, :permalink, :string - - Enterprise.reset_column_information - - Enterprise.all.each do |enterprise| - counter = 1 - permalink = enterprise.name.parameterize - permalink = "my-enterprise-name" if permalink == "" - while Enterprise.find_by(permalink: permalink) do - permalink = enterprise.name.parameterize + counter.to_s - counter += 1 - end - - enterprise.update_column :permalink, permalink - end - - change_column :enterprises, :permalink, :string, null: false - end - - def down - remove_column :enterprises, :permalink - end -end diff --git a/db/migrate/20141229094516_add_receival_time_to_exchange.rb b/db/migrate/20141229094516_add_receival_time_to_exchange.rb deleted file mode 100644 index 06933ed051..0000000000 --- a/db/migrate/20141229094516_add_receival_time_to_exchange.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddReceivalTimeToExchange < ActiveRecord::Migration - def change - add_column :exchanges, :receival_time, :string - add_column :exchanges, :receival_instructions, :string - end -end diff --git a/db/migrate/20150115050935_add_addresses_ref_to_enterprise_groups.rb b/db/migrate/20150115050935_add_addresses_ref_to_enterprise_groups.rb deleted file mode 100644 index 566b35bb88..0000000000 --- a/db/migrate/20150115050935_add_addresses_ref_to_enterprise_groups.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddAddressesRefToEnterpriseGroups < ActiveRecord::Migration - def change - add_column :enterprise_groups, :address_id, :integer - add_foreign_key :enterprise_groups, :spree_addresses, column: "address_id" - end -end diff --git a/db/migrate/20150115050936_add_address_instances_to_existing_enterprise_groups.rb b/db/migrate/20150115050936_add_address_instances_to_existing_enterprise_groups.rb deleted file mode 100644 index 0ef08a39dc..0000000000 --- a/db/migrate/20150115050936_add_address_instances_to_existing_enterprise_groups.rb +++ /dev/null @@ -1,19 +0,0 @@ -class AddAddressInstancesToExistingEnterpriseGroups < ActiveRecord::Migration - def change - country = Spree::Country.find_by(iso: ENV['DEFAULT_COUNTRY_CODE']) - state = country.states.first - EnterpriseGroup.all.each do |g| - next if g.address.present? - address = Spree::Address.new(firstname: 'unused', lastname: 'unused', address1: 'undefined', city: 'undefined', zipcode: 'undefined', state: state, country: country, phone: 'undefined') - g.address = address - # some groups are invalid, because of a missing description - g.save!(validate: false) - end - end - - def self.down - # we can't know which addresses were already there and which weren't - # and we can't remove addresses as long as they are referenced and - # required by the model - end -end diff --git a/db/migrate/20150121030627_add_web_contact_to_enterprise_groups.rb b/db/migrate/20150121030627_add_web_contact_to_enterprise_groups.rb deleted file mode 100644 index afea2dbeea..0000000000 --- a/db/migrate/20150121030627_add_web_contact_to_enterprise_groups.rb +++ /dev/null @@ -1,10 +0,0 @@ -class AddWebContactToEnterpriseGroups < ActiveRecord::Migration - def change - add_column :enterprise_groups, :email, :string, null: false, default: '' - add_column :enterprise_groups, :website, :string, null: false, default: '' - add_column :enterprise_groups, :facebook, :string, null: false, default: '' - add_column :enterprise_groups, :instagram, :string, null: false, default: '' - add_column :enterprise_groups, :linkedin, :string, null: false, default: '' - add_column :enterprise_groups, :twitter, :string, null: false, default: '' - end -end diff --git a/db/migrate/20150122145607_create_customers.rb b/db/migrate/20150122145607_create_customers.rb deleted file mode 100644 index 12e5a721e8..0000000000 --- a/db/migrate/20150122145607_create_customers.rb +++ /dev/null @@ -1,18 +0,0 @@ -class CreateCustomers < ActiveRecord::Migration - def change - create_table :customers do |t| - t.string :email, null: false - t.references :enterprise, null: false - t.string :code, null: false - t.references :user - - t.timestamps - end - add_index :customers, [:enterprise_id, :code], unique: true - add_index :customers, :email - add_index :customers, :user_id - - add_foreign_key :customers, :enterprises, column: :enterprise_id - add_foreign_key :customers, :spree_users, column: :user_id - end -end diff --git a/db/migrate/20150202000203_add_owner_to_enterprise_groups.rb b/db/migrate/20150202000203_add_owner_to_enterprise_groups.rb deleted file mode 100644 index f2e46452df..0000000000 --- a/db/migrate/20150202000203_add_owner_to_enterprise_groups.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddOwnerToEnterpriseGroups < ActiveRecord::Migration - def change - add_column :enterprise_groups, :owner_id, :integer - add_foreign_key :enterprise_groups, :spree_users, column: "owner_id" - end -end diff --git a/db/migrate/20150216075336_add_temperature_controlled_to_spree_shipping_categories.rb b/db/migrate/20150216075336_add_temperature_controlled_to_spree_shipping_categories.rb deleted file mode 100644 index 89035fc16f..0000000000 --- a/db/migrate/20150216075336_add_temperature_controlled_to_spree_shipping_categories.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddTemperatureControlledToSpreeShippingCategories < ActiveRecord::Migration - def change - add_column :spree_shipping_categories, :temperature_controlled, :boolean, null: false, default: false - end -end diff --git a/db/migrate/20150219021742_add_owner_index_to_enterprise_groups.rb b/db/migrate/20150219021742_add_owner_index_to_enterprise_groups.rb deleted file mode 100644 index 062e9523e6..0000000000 --- a/db/migrate/20150219021742_add_owner_index_to_enterprise_groups.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddOwnerIndexToEnterpriseGroups < ActiveRecord::Migration - def change - add_index :enterprise_groups, :owner_id - end -end diff --git a/db/migrate/20150220035501_add_address_id_index_to_enterprise_groups.rb b/db/migrate/20150220035501_add_address_id_index_to_enterprise_groups.rb deleted file mode 100644 index 32094cbde7..0000000000 --- a/db/migrate/20150220035501_add_address_id_index_to_enterprise_groups.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddAddressIdIndexToEnterpriseGroups < ActiveRecord::Migration - def change - add_index :enterprise_groups, :address_id - end -end diff --git a/db/migrate/20150225111538_add_tax_category_to_enterprise_fee.rb b/db/migrate/20150225111538_add_tax_category_to_enterprise_fee.rb deleted file mode 100644 index 05b5410587..0000000000 --- a/db/migrate/20150225111538_add_tax_category_to_enterprise_fee.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AddTaxCategoryToEnterpriseFee < ActiveRecord::Migration - def change - add_column :enterprise_fees, :tax_category_id, :integer - add_foreign_key :enterprise_fees, :spree_tax_categories, column: :tax_category_id - add_index :enterprise_fees, :tax_category_id - end -end diff --git a/db/migrate/20150225232938_add_included_tax_to_adjustments.rb b/db/migrate/20150225232938_add_included_tax_to_adjustments.rb deleted file mode 100644 index f3815dec2a..0000000000 --- a/db/migrate/20150225232938_add_included_tax_to_adjustments.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddIncludedTaxToAdjustments < ActiveRecord::Migration - def change - add_column :spree_adjustments, :included_tax, :decimal, precision: 10, scale: 2, null: false, default: 0 - end -end diff --git a/db/migrate/20150305004846_add_weight_to_line_items.rb b/db/migrate/20150305004846_add_weight_to_line_items.rb deleted file mode 100644 index a4df1a12f0..0000000000 --- a/db/migrate/20150305004846_add_weight_to_line_items.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddWeightToLineItems < ActiveRecord::Migration - def change - add_column :spree_line_items, :unit_value, :decimal, :precision => 8, :scale => 2 - end -end diff --git a/db/migrate/20150407234739_add_charges_sales_tax_to_enterprises.rb b/db/migrate/20150407234739_add_charges_sales_tax_to_enterprises.rb deleted file mode 100644 index ba8dfa7a08..0000000000 --- a/db/migrate/20150407234739_add_charges_sales_tax_to_enterprises.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddChargesSalesTaxToEnterprises < ActiveRecord::Migration - def change - add_column :enterprises, :charges_sales_tax, :boolean, null: false, default: false - end -end diff --git a/db/migrate/20150410043302_create_delayed_jobs.rb b/db/migrate/20150410043302_create_delayed_jobs.rb deleted file mode 100644 index f7de70bdc5..0000000000 --- a/db/migrate/20150410043302_create_delayed_jobs.rb +++ /dev/null @@ -1,22 +0,0 @@ -class CreateDelayedJobs < ActiveRecord::Migration - def self.up - create_table :delayed_jobs, :force => true do |table| - table.integer :priority, :default => 0, :null => false # Allows some jobs to jump to the front of the queue - table.integer :attempts, :default => 0, :null => false # Provides for retries, but still fail eventually. - table.text :handler, :null => false # YAML-encoded string of the object that will do work - table.text :last_error # reason for last failure (See Note below) - table.datetime :run_at # When to run. Could be Time.zone.now for immediately, or sometime in the future. - table.datetime :locked_at # Set when a client is working on this object - table.datetime :failed_at # Set when all retries have failed (actually, by default, the record is deleted instead) - table.string :locked_by # Who is working on this object (if locked) - table.string :queue # The name of the queue this job is in - table.timestamps - end - - add_index :delayed_jobs, [:priority, :run_at], :name => 'delayed_jobs_priority' - end - - def self.down - drop_table :delayed_jobs - end -end diff --git a/db/migrate/20150422014819_add_inherits_properties_to_product.rb b/db/migrate/20150422014819_add_inherits_properties_to_product.rb deleted file mode 100644 index aba8bbbe45..0000000000 --- a/db/migrate/20150422014819_add_inherits_properties_to_product.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddInheritsPropertiesToProduct < ActiveRecord::Migration - def change - add_column :spree_products, :inherits_properties, :boolean, null: false, default: true - end -end diff --git a/db/migrate/20150424025907_add_default_and_not_null_to_producer_properties_position.rb b/db/migrate/20150424025907_add_default_and_not_null_to_producer_properties_position.rb deleted file mode 100644 index 8c5a2d1f2c..0000000000 --- a/db/migrate/20150424025907_add_default_and_not_null_to_producer_properties_position.rb +++ /dev/null @@ -1,9 +0,0 @@ -class AddDefaultAndNotNullToProducerPropertiesPosition < ActiveRecord::Migration - def change - ProducerProperty.where(position: nil).each do |producer_property| - producer_property.update_attribute(:position, 0) - end - - change_column :producer_properties, :position, :integer, null: false, default: 0 - end -end diff --git a/db/migrate/20150424151117_populate_line_item_unit_value.rb b/db/migrate/20150424151117_populate_line_item_unit_value.rb deleted file mode 100644 index 2122b84472..0000000000 --- a/db/migrate/20150424151117_populate_line_item_unit_value.rb +++ /dev/null @@ -1,9 +0,0 @@ -class PopulateLineItemUnitValue < ActiveRecord::Migration - def up - execute "UPDATE spree_line_items SET unit_value = spree_variants.unit_value FROM spree_variants WHERE spree_line_items.variant_id = spree_variants.id" - end - - def down - raise ActiveRecord::IrreversibleMigration - end -end diff --git a/db/migrate/20150508030520_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb b/db/migrate/20150508030520_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb deleted file mode 100644 index 6bbd5594ea..0000000000 --- a/db/migrate/20150508030520_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb +++ /dev/null @@ -1,31 +0,0 @@ -# This migration comes from acts_as_taggable_on_engine (originally 1) -class ActsAsTaggableOnMigration < ActiveRecord::Migration - def self.up - create_table :tags do |t| - t.string :name - end - - create_table :taggings do |t| - t.references :tag - - # You should make sure that the column created is - # long enough to store the required class names. - t.references :taggable, polymorphic: true - t.references :tagger, polymorphic: true - - # Limit is created to prevent MySQL error on index - # length for MyISAM table type: http://bit.ly/vgW2Ql - t.string :context, limit: 128 - - t.datetime :created_at - end - - add_index :taggings, :tag_id - add_index :taggings, [:taggable_id, :taggable_type, :context] - end - - def self.down - drop_table :taggings - drop_table :tags - end -end diff --git a/db/migrate/20150508030521_add_missing_unique_indices.acts_as_taggable_on_engine.rb b/db/migrate/20150508030521_add_missing_unique_indices.acts_as_taggable_on_engine.rb deleted file mode 100644 index 4ca676f6c7..0000000000 --- a/db/migrate/20150508030521_add_missing_unique_indices.acts_as_taggable_on_engine.rb +++ /dev/null @@ -1,20 +0,0 @@ -# This migration comes from acts_as_taggable_on_engine (originally 2) -class AddMissingUniqueIndices < ActiveRecord::Migration - def self.up - add_index :tags, :name, unique: true - - remove_index :taggings, :tag_id - remove_index :taggings, [:taggable_id, :taggable_type, :context] - add_index :taggings, - [:tag_id, :taggable_id, :taggable_type, :context, :tagger_id, :tagger_type], - unique: true, name: 'taggings_idx' - end - - def self.down - remove_index :tags, :name - - remove_index :taggings, name: 'taggings_idx' - add_index :taggings, :tag_id - add_index :taggings, [:taggable_id, :taggable_type, :context] - end -end diff --git a/db/migrate/20150508030522_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb b/db/migrate/20150508030522_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb deleted file mode 100644 index 8edb508078..0000000000 --- a/db/migrate/20150508030522_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb +++ /dev/null @@ -1,15 +0,0 @@ -# This migration comes from acts_as_taggable_on_engine (originally 3) -class AddTaggingsCounterCacheToTags < ActiveRecord::Migration - def self.up - add_column :tags, :taggings_count, :integer, default: 0 - - ActsAsTaggableOn::Tag.reset_column_information - ActsAsTaggableOn::Tag.find_each do |tag| - ActsAsTaggableOn::Tag.reset_counters(tag.id, :taggings) - end - end - - def self.down - remove_column :tags, :taggings_count - end -end diff --git a/db/migrate/20150508030523_add_missing_taggable_index.acts_as_taggable_on_engine.rb b/db/migrate/20150508030523_add_missing_taggable_index.acts_as_taggable_on_engine.rb deleted file mode 100644 index 71f2d7f433..0000000000 --- a/db/migrate/20150508030523_add_missing_taggable_index.acts_as_taggable_on_engine.rb +++ /dev/null @@ -1,10 +0,0 @@ -# This migration comes from acts_as_taggable_on_engine (originally 4) -class AddMissingTaggableIndex < ActiveRecord::Migration - def self.up - add_index :taggings, [:taggable_id, :taggable_type, :context] - end - - def self.down - remove_index :taggings, [:taggable_id, :taggable_type, :context] - end -end diff --git a/db/migrate/20150508030524_change_collation_for_tag_names.acts_as_taggable_on_engine.rb b/db/migrate/20150508030524_change_collation_for_tag_names.acts_as_taggable_on_engine.rb deleted file mode 100644 index bfb06bc7cd..0000000000 --- a/db/migrate/20150508030524_change_collation_for_tag_names.acts_as_taggable_on_engine.rb +++ /dev/null @@ -1,10 +0,0 @@ -# This migration comes from acts_as_taggable_on_engine (originally 5) -# This migration is added to circumvent issue #623 and have special characters -# work properly -class ChangeCollationForTagNames < ActiveRecord::Migration - def up - if ActsAsTaggableOn::Utils.using_mysql? - execute("ALTER TABLE tags MODIFY name varchar(255) CHARACTER SET utf8 COLLATE utf8_bin;") - end - end -end diff --git a/db/migrate/20150508072454_remove_customer_code_not_null_constraint.rb b/db/migrate/20150508072454_remove_customer_code_not_null_constraint.rb deleted file mode 100644 index deeacbc608..0000000000 --- a/db/migrate/20150508072454_remove_customer_code_not_null_constraint.rb +++ /dev/null @@ -1,9 +0,0 @@ -class RemoveCustomerCodeNotNullConstraint < ActiveRecord::Migration - def up - change_column :customers, :code, :string, null: true - end - - def down - change_column :customers, :code, :string, null: false - end -end diff --git a/db/migrate/20150508072938_add_customer_to_orders.rb b/db/migrate/20150508072938_add_customer_to_orders.rb deleted file mode 100644 index e961840255..0000000000 --- a/db/migrate/20150508072938_add_customer_to_orders.rb +++ /dev/null @@ -1,16 +0,0 @@ -class AddCustomerToOrders < ActiveRecord::Migration - def change - add_column :spree_orders, :customer_id, :integer - add_index :spree_orders, :customer_id - add_foreign_key :spree_orders, :customers, column: :customer_id - - Spree::Order.where("spree_orders.email IS NOT NULL AND distributor_id IS NOT NULL AND customer_id IS NULL").each do |order| - customer = Customer.find_by(email: order.email, enterprise_id: order.distributor_id) - unless customer.present? - user = Spree::User.find_by(email: order.email) - customer = Customer.create!(email: order.email, enterprise_id: order.distributor_id, user_id: user.andand.id ) - end - order.update_attribute(:customer, customer) - end - end -end diff --git a/db/migrate/20150527004427_add_permalink_to_groups.rb b/db/migrate/20150527004427_add_permalink_to_groups.rb deleted file mode 100644 index df40798492..0000000000 --- a/db/migrate/20150527004427_add_permalink_to_groups.rb +++ /dev/null @@ -1,26 +0,0 @@ -class AddPermalinkToGroups < ActiveRecord::Migration - def up - add_column :enterprise_groups, :permalink, :string - - EnterpriseGroup.reset_column_information - - EnterpriseGroup.all.each do |group| - counter = 1 - permalink = group.name.parameterize - permalink = "my-group-name" if permalink == "" - while EnterpriseGroup.find_by(permalink: permalink) do - permalink = group.name.parameterize + counter.to_s - counter += 1 - end - - group.update_column :permalink, permalink - end - - change_column :enterprise_groups, :permalink, :string, null: false - add_index :enterprise_groups, :permalink, :unique => true - end - - def down - remove_column :enterprise_groups, :permalink - end -end diff --git a/db/migrate/20150603001843_add_unique_index_to_enterprise_permalink.rb b/db/migrate/20150603001843_add_unique_index_to_enterprise_permalink.rb deleted file mode 100644 index e8841b2c5f..0000000000 --- a/db/migrate/20150603001843_add_unique_index_to_enterprise_permalink.rb +++ /dev/null @@ -1,16 +0,0 @@ -class AddUniqueIndexToEnterprisePermalink < ActiveRecord::Migration - def change - duplicates = Enterprise.group(:permalink).having('count(*) > 1').pluck(:permalink) - duplicates.each { |p| resolve_permalink(p) }; - add_index :enterprises, :permalink, :unique => true - end - - def resolve_permalink(permalink) - conflicting = Enterprise.where(permalink: permalink) - while conflicting.size > 1 do - enterprise = conflicting.pop - enterprise.permalink = nil - enterprise.save - end - end -end diff --git a/db/migrate/20150604045725_add_sessions_table.rb b/db/migrate/20150604045725_add_sessions_table.rb deleted file mode 100644 index 4c879564a5..0000000000 --- a/db/migrate/20150604045725_add_sessions_table.rb +++ /dev/null @@ -1,12 +0,0 @@ -class AddSessionsTable < ActiveRecord::Migration - def change - create_table :sessions do |t| - t.string :session_id, :null => false - t.text :data - t.timestamps - end - - add_index :sessions, :session_id - add_index :sessions, :updated_at - end -end diff --git a/db/migrate/20150605052516_dependent_delete_adjustment_metadata.rb b/db/migrate/20150605052516_dependent_delete_adjustment_metadata.rb deleted file mode 100644 index ee9d8d4af8..0000000000 --- a/db/migrate/20150605052516_dependent_delete_adjustment_metadata.rb +++ /dev/null @@ -1,11 +0,0 @@ -class DependentDeleteAdjustmentMetadata < ActiveRecord::Migration - def up - remove_foreign_key "adjustment_metadata", name: "adjustment_metadata_adjustment_id_fk" - add_foreign_key "adjustment_metadata", "spree_adjustments", name: "adjustment_metadata_adjustment_id_fk", column: "adjustment_id", dependent: :delete - end - - def down - remove_foreign_key "adjustment_metadata", name: "adjustment_metadata_adjustment_id_fk" - add_foreign_key "adjustment_metadata", "spree_adjustments", name: "adjustment_metadata_adjustment_id_fk", column: "adjustment_id" - end -end diff --git a/db/migrate/20150612045544_make_enterprises_name_unique.rb b/db/migrate/20150612045544_make_enterprises_name_unique.rb deleted file mode 100644 index da92f6a8fe..0000000000 --- a/db/migrate/20150612045544_make_enterprises_name_unique.rb +++ /dev/null @@ -1,20 +0,0 @@ -class MakeEnterprisesNameUnique < ActiveRecord::Migration - def up - dup_names = Enterprise.group('name').select('name, COUNT(*) AS num_enterprises') - - dup_names.each do |data| - (data.num_enterprises.to_i - 1).times do |i| - e = Enterprise.find_by name: data.name - new_name = "#{data.name}-#{i+1}" - e.update_column :name, new_name - say "Renamed enterprise #{data.name} to #{new_name}" - end - end - - add_index :enterprises, :name, unique: true - end - - def down - remove_index :enterprises, :name - end -end diff --git a/db/migrate/20150619020711_create_versions.rb b/db/migrate/20150619020711_create_versions.rb deleted file mode 100644 index 23be970c66..0000000000 --- a/db/migrate/20150619020711_create_versions.rb +++ /dev/null @@ -1,13 +0,0 @@ -class CreateVersions < ActiveRecord::Migration - def change - create_table :versions do |t| - t.string :item_type, :null => false - t.integer :item_id, :null => false - t.string :event, :null => false - t.string :whodunnit - t.text :object - t.datetime :created_at - end - add_index :versions, [:item_type, :item_id] - end -end diff --git a/db/migrate/20150619100137_create_bill_items.rb b/db/migrate/20150619100137_create_bill_items.rb deleted file mode 100644 index fec80692b1..0000000000 --- a/db/migrate/20150619100137_create_bill_items.rb +++ /dev/null @@ -1,15 +0,0 @@ -class CreateBillItems < ActiveRecord::Migration - def change - create_table :bill_items do |t| - t.references :enterprise, nil: false - t.references :owner, nil: false - t.datetime :begins_at, default: nil - t.datetime :ends_at, default: nil - t.string :sells, default: nil - t.boolean :trial, default: false - t.decimal :turnover, default: 0.0 - t.foreign_key :enterprises - t.foreign_key :spree_users, column: :owner_id - end - end -end diff --git a/db/migrate/20150626090338_rename_bill_items_to_billable_periods.rb b/db/migrate/20150626090338_rename_bill_items_to_billable_periods.rb deleted file mode 100644 index caa2fb9a4d..0000000000 --- a/db/migrate/20150626090338_rename_bill_items_to_billable_periods.rb +++ /dev/null @@ -1,9 +0,0 @@ -class RenameBillItemsToBillablePeriods < ActiveRecord::Migration - def up - rename_table :bill_items, :billable_periods - end - - def down - rename_table :billable_periods, :bill_items - end -end diff --git a/db/migrate/20150701034055_add_timestamps_to_billable_periods.rb b/db/migrate/20150701034055_add_timestamps_to_billable_periods.rb deleted file mode 100644 index 6c3ea52356..0000000000 --- a/db/migrate/20150701034055_add_timestamps_to_billable_periods.rb +++ /dev/null @@ -1,8 +0,0 @@ -class AddTimestampsToBillablePeriods < ActiveRecord::Migration - def change - change_table(:billable_periods) do |t| - t.datetime :deleted_at, default: nil - t.timestamps - end - end -end diff --git a/db/migrate/20150719111807_add_default_stock_to_variant_overrides.rb b/db/migrate/20150719111807_add_default_stock_to_variant_overrides.rb deleted file mode 100644 index 880a1b8349..0000000000 --- a/db/migrate/20150719111807_add_default_stock_to_variant_overrides.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddDefaultStockToVariantOverrides < ActiveRecord::Migration - def change - add_column :variant_overrides, :default_stock, :integer - end -end diff --git a/db/migrate/20150719153136_rename_line_item_unit_value.rb b/db/migrate/20150719153136_rename_line_item_unit_value.rb deleted file mode 100644 index 9dbdce75c5..0000000000 --- a/db/migrate/20150719153136_rename_line_item_unit_value.rb +++ /dev/null @@ -1,5 +0,0 @@ -class RenameLineItemUnitValue < ActiveRecord::Migration - def change - rename_column :spree_line_items, :unit_value, :final_weight_volume - end -end diff --git a/db/migrate/20150719153732_update_precision_on_line_item_final_weight_volume.rb b/db/migrate/20150719153732_update_precision_on_line_item_final_weight_volume.rb deleted file mode 100644 index c1b3482c0f..0000000000 --- a/db/migrate/20150719153732_update_precision_on_line_item_final_weight_volume.rb +++ /dev/null @@ -1,11 +0,0 @@ -class UpdatePrecisionOnLineItemFinalWeightVolume < ActiveRecord::Migration - def up - change_column :spree_line_items, :final_weight_volume, :decimal, :precision => 10, :scale => 2 - end - - def down - raise ActiveRecord::IrreversibleMigration - end -end - - diff --git a/db/migrate/20150730160010_update_spree_line_item_final_weight_volume.rb b/db/migrate/20150730160010_update_spree_line_item_final_weight_volume.rb deleted file mode 100644 index 4d51a7160b..0000000000 --- a/db/migrate/20150730160010_update_spree_line_item_final_weight_volume.rb +++ /dev/null @@ -1,9 +0,0 @@ -class UpdateSpreeLineItemFinalWeightVolume < ActiveRecord::Migration - def up - execute "UPDATE spree_line_items SET final_weight_volume = final_weight_volume * quantity" - end - - def down - raise ActiveRecord::IrreversibleMigration - end -end diff --git a/db/migrate/20150827194622_add_enable_reset_to_variant_overrides.rb b/db/migrate/20150827194622_add_enable_reset_to_variant_overrides.rb deleted file mode 100644 index 172cce6588..0000000000 --- a/db/migrate/20150827194622_add_enable_reset_to_variant_overrides.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddEnableResetToVariantOverrides < ActiveRecord::Migration - def change - add_column :variant_overrides, :enable_reset, :boolean - end -end diff --git a/db/migrate/20150916012814_create_account_invoices.rb b/db/migrate/20150916012814_create_account_invoices.rb deleted file mode 100644 index 7e92a53593..0000000000 --- a/db/migrate/20150916012814_create_account_invoices.rb +++ /dev/null @@ -1,18 +0,0 @@ -class CreateAccountInvoices < ActiveRecord::Migration - def change - create_table :account_invoices do |t| - t.references :user, null: false - t.references :order - t.integer :year, null: false - t.integer :month, null: false - t.datetime :issued_at - - t.timestamps - end - add_index :account_invoices, :user_id - add_index :account_invoices, :order_id - - add_foreign_key :account_invoices, :spree_orders, column: :order_id - add_foreign_key :account_invoices, :spree_users, column: :user_id - end -end diff --git a/db/migrate/20150916061809_add_account_invoice_to_billable_periods.rb b/db/migrate/20150916061809_add_account_invoice_to_billable_periods.rb deleted file mode 100644 index ee1d9d5d93..0000000000 --- a/db/migrate/20150916061809_add_account_invoice_to_billable_periods.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AddAccountInvoiceToBillablePeriods < ActiveRecord::Migration - def change - add_column :billable_periods, :account_invoice_id, :integer, null: false - add_index :billable_periods, :account_invoice_id - add_foreign_key :billable_periods, :account_invoices, column: :account_invoice_id - end -end diff --git a/db/migrate/20150924054538_add_option_values_line_items_join_table.rb b/db/migrate/20150924054538_add_option_values_line_items_join_table.rb deleted file mode 100644 index 7a51c851ec..0000000000 --- a/db/migrate/20150924054538_add_option_values_line_items_join_table.rb +++ /dev/null @@ -1,14 +0,0 @@ -class AddOptionValuesLineItemsJoinTable < ActiveRecord::Migration - def change - create_table :spree_option_values_line_items, :id => false, :force => true do |t| - t.integer :line_item_id - t.integer :option_value_id - end - - Spree::LineItem.all.each do |line_item| - line_item.update_units - end - - add_index :spree_option_values_line_items, :line_item_id, :name => 'index_option_values_line_items_on_line_item_id' - end -end diff --git a/db/migrate/20151002020537_ensure_address_for_account_invoice_orders.rb b/db/migrate/20151002020537_ensure_address_for_account_invoice_orders.rb deleted file mode 100644 index 6d2c7d45c5..0000000000 --- a/db/migrate/20151002020537_ensure_address_for_account_invoice_orders.rb +++ /dev/null @@ -1,15 +0,0 @@ -class EnsureAddressForAccountInvoiceOrders < ActiveRecord::Migration - def up - AccountInvoice.where('order_id IS NOT NULL').each do |account_invoice| - billable_periods = account_invoice.billable_periods.order(:enterprise_id).reject{ |bp| bp.turnover == 0 } - - if billable_periods.any? - address = billable_periods.first.enterprise.address - account_invoice.order.update_attributes(bill_address: address, ship_address: address) - end - end - end - - def down - end -end diff --git a/db/migrate/20151125051510_combine_exchange_receival_time_receival_instructions.rb b/db/migrate/20151125051510_combine_exchange_receival_time_receival_instructions.rb deleted file mode 100644 index 434a2053ab..0000000000 --- a/db/migrate/20151125051510_combine_exchange_receival_time_receival_instructions.rb +++ /dev/null @@ -1,9 +0,0 @@ -class CombineExchangeReceivalTimeReceivalInstructions < ActiveRecord::Migration - def up - remove_column :exchanges, :receival_time - end - - def down - add_column :exchanges, :receival_time, :string - end -end diff --git a/db/migrate/20151126235409_add_on_demand_and_sku_to_variant_overrides.rb b/db/migrate/20151126235409_add_on_demand_and_sku_to_variant_overrides.rb deleted file mode 100644 index 9c47bfbc27..0000000000 --- a/db/migrate/20151126235409_add_on_demand_and_sku_to_variant_overrides.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddOnDemandAndSkuToVariantOverrides < ActiveRecord::Migration - def change - add_column :variant_overrides, :sku, :string, :default => nil, :after => :hub_id - add_column :variant_overrides, :on_demand, :boolean, :default => nil, :after => :count_on_hand - end -end diff --git a/db/migrate/20151128185900_rename_enable_reset_to_resettable.rb b/db/migrate/20151128185900_rename_enable_reset_to_resettable.rb deleted file mode 100644 index 461e2efe25..0000000000 --- a/db/migrate/20151128185900_rename_enable_reset_to_resettable.rb +++ /dev/null @@ -1,3 +0,0 @@ -class RenameEnableResetToResettable < ActiveRecord::Migration - rename_column :variant_overrides, :enable_reset, :resettable -end diff --git a/db/migrate/20160114001844_create_inventory_items.rb b/db/migrate/20160114001844_create_inventory_items.rb deleted file mode 100644 index 2ca54dce4d..0000000000 --- a/db/migrate/20160114001844_create_inventory_items.rb +++ /dev/null @@ -1,13 +0,0 @@ -class CreateInventoryItems < ActiveRecord::Migration - def change - create_table :inventory_items do |t| - t.references :enterprise, null: false, index: true - t.references :variant, null: false, index: true - t.boolean :visible, default: true, null: false - - t.timestamps - end - - add_index "inventory_items", [:enterprise_id, :variant_id], unique: true - end -end diff --git a/db/migrate/20160116024333_create_column_preferences.rb b/db/migrate/20160116024333_create_column_preferences.rb deleted file mode 100644 index e38c51d858..0000000000 --- a/db/migrate/20160116024333_create_column_preferences.rb +++ /dev/null @@ -1,13 +0,0 @@ -class CreateColumnPreferences < ActiveRecord::Migration - def change - create_table :column_preferences do |t| - t.references :user, null: false, index: true - t.string :action_name, null: false, index: true - t.string :column_name, null: false - t.boolean :visible, null: false - - t.timestamps - end - add_index :column_preferences, [:user_id, :action_name, :column_name], unique: true, name: 'index_column_prefs_on_user_id_and_action_name_and_column_name' - end -end diff --git a/db/migrate/20160204013914_add_id_to_coordinator_fees.rb b/db/migrate/20160204013914_add_id_to_coordinator_fees.rb deleted file mode 100644 index 74326a6006..0000000000 --- a/db/migrate/20160204013914_add_id_to_coordinator_fees.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddIdToCoordinatorFees < ActiveRecord::Migration - def change - add_column :coordinator_fees, :id, :primary_key - end -end diff --git a/db/migrate/20160204031816_add_inherits_tax_category_to_enterprise_fees.rb b/db/migrate/20160204031816_add_inherits_tax_category_to_enterprise_fees.rb deleted file mode 100644 index 49751cc479..0000000000 --- a/db/migrate/20160204031816_add_inherits_tax_category_to_enterprise_fees.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddInheritsTaxCategoryToEnterpriseFees < ActiveRecord::Migration - def change - add_column :enterprise_fees, :inherits_tax_category, :boolean, null: false, default: false - end -end diff --git a/db/migrate/20160205044930_add_email_address_to_enterprises.rb b/db/migrate/20160205044930_add_email_address_to_enterprises.rb deleted file mode 100644 index b1047fe4b8..0000000000 --- a/db/migrate/20160205044930_add_email_address_to_enterprises.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddEmailAddressToEnterprises < ActiveRecord::Migration - def change - add_column :enterprises, :email_address, :string - end -end diff --git a/db/migrate/20160212092908_set_enterprise_email_address.rb b/db/migrate/20160212092908_set_enterprise_email_address.rb deleted file mode 100644 index a43591624a..0000000000 --- a/db/migrate/20160212092908_set_enterprise_email_address.rb +++ /dev/null @@ -1,8 +0,0 @@ -class SetEnterpriseEmailAddress < ActiveRecord::Migration - def up - Enterprise.all.each do |enterprise| - enterprise.email_address = enterprise.email - enterprise.save - end - end -end diff --git a/db/migrate/20160218235221_populate_inventories.rb b/db/migrate/20160218235221_populate_inventories.rb deleted file mode 100644 index 2b9d1be8b6..0000000000 --- a/db/migrate/20160218235221_populate_inventories.rb +++ /dev/null @@ -1,22 +0,0 @@ -class PopulateInventories < ActiveRecord::Migration - def up - # If hubs are actively using overrides, populate their inventories with all variants they have permission to override - # Otherwise leave their inventories empty - - hubs_using_overrides = Enterprise.joins("LEFT OUTER JOIN variant_overrides ON variant_overrides.hub_id = enterprises.id") - .where("variant_overrides.id IS NOT NULL").select("DISTINCT enterprises.*") - - hubs_using_overrides.each do |hub| - overridable_producers = OpenFoodNetwork::Permissions.new(hub.owner).variant_override_producers - - variants = Spree::Variant.where(is_master: false, product_id: Spree::Product.not_deleted.where(supplier_id: overridable_producers)) - - variants.each do |variant| - InventoryItem.create(enterprise: hub, variant: variant, visible: true) - end - end - end - - def down - end -end diff --git a/db/migrate/20160224034034_grant_explicit_variant_override_permissions.rb b/db/migrate/20160224034034_grant_explicit_variant_override_permissions.rb deleted file mode 100644 index e66c5ee7db..0000000000 --- a/db/migrate/20160224034034_grant_explicit_variant_override_permissions.rb +++ /dev/null @@ -1,30 +0,0 @@ -class GrantExplicitVariantOverridePermissions < ActiveRecord::Migration - def up - hubs = Enterprise.is_distributor - - begin - EnterpriseRelationship.skip_callback :save, :after, :apply_variant_override_permissions - - hubs.each do |hub| - next if hub.owner.admin? - explicitly_granting_producer_ids = hub.relationships_as_child - .with_permission(:create_variant_overrides).map(&:parent_id) - - managed_producer_ids = Enterprise.managed_by(hub.owner).is_primary_producer.pluck(:id) - implicitly_granting_producer_ids = managed_producer_ids - explicitly_granting_producer_ids - [hub.id] - - # create explicit VO permissions for producers currently granting implicit permission - Enterprise.where(id: implicitly_granting_producer_ids).each do |producer| - relationship = producer.relationships_as_parent.find_or_initialize_by(child_id: hub.id) - permission = relationship.permissions.find_or_initialize_by(name: :create_variant_overrides) - relationship.save! unless permission.persisted? - end - end - ensure - EnterpriseRelationship.set_callback :save, :after, :apply_variant_override_permissions - end - end - - def down - end -end diff --git a/db/migrate/20160224230143_add_permission_revoked_at_to_variant_overrides.rb b/db/migrate/20160224230143_add_permission_revoked_at_to_variant_overrides.rb deleted file mode 100644 index afa58ebe26..0000000000 --- a/db/migrate/20160224230143_add_permission_revoked_at_to_variant_overrides.rb +++ /dev/null @@ -1,21 +0,0 @@ -class AddPermissionRevokedAtToVariantOverrides < ActiveRecord::Migration - def up - add_column :variant_overrides, :permission_revoked_at, :datetime, default: nil - - variant_override_hubs = Enterprise.where(id: VariantOverride.all.map(&:hub_id).uniq) - - variant_override_hubs.each do |hub| - permitting_producer_ids = hub.relationships_as_child - .with_permission(:create_variant_overrides).map(&:parent_id) - - variant_overrides_with_revoked_permissions = VariantOverride.for_hubs(hub) - .joins(variant: :product).where("spree_products.supplier_id NOT IN (?)", permitting_producer_ids) - - variant_overrides_with_revoked_permissions.update_all(permission_revoked_at: Time.now) - end - end - - def down - remove_column :variant_overrides, :permission_revoked_at - end -end diff --git a/db/migrate/20160302044850_repopulate_inventories.rb b/db/migrate/20160302044850_repopulate_inventories.rb deleted file mode 100644 index e38628439a..0000000000 --- a/db/migrate/20160302044850_repopulate_inventories.rb +++ /dev/null @@ -1,30 +0,0 @@ -class RepopulateInventories < ActiveRecord::Migration - # Previous version of this migration (20160218235221) relied on Permissions#variant_override_producers - # which was then changed, meaning that an incomplete set of variants were added to inventories of most hubs - # Re-running this now will ensure that all permitted variants (including those allowed by 20160224034034) are - # added to the relevant inventories - - def up - # If hubs are actively using overrides, populate their inventories with all variants they have permission to override - # Otherwise leave their inventories empty - - hubs_using_overrides = Enterprise.joins("LEFT OUTER JOIN variant_overrides ON variant_overrides.hub_id = enterprises.id") - .where("variant_overrides.id IS NOT NULL").select("DISTINCT enterprises.*") - - hubs_using_overrides.each do |hub| - overridable_producer_ids = hub.relationships_as_child.with_permission(:create_variant_overrides).map(&:parent_id) | [hub.id] - - variants = Spree::Variant.where(is_master: false, product_id: Spree::Product.not_deleted.where(supplier_id: overridable_producer_ids)) - - variants_to_add = variants.joins("LEFT OUTER JOIN (SELECT * from inventory_items WHERE enterprise_id = #{hub.id}) AS o_inventory_items ON o_inventory_items.variant_id = spree_variants.id") - .where('o_inventory_items.id IS NULL') - - variants_to_add.each do |variant| - inventory_item = InventoryItem.create(enterprise: hub, variant: variant, visible: true) - end - end - end - - def down - end -end diff --git a/db/migrate/20160303004210_create_tag_rules.rb b/db/migrate/20160303004210_create_tag_rules.rb deleted file mode 100644 index 157fee1e69..0000000000 --- a/db/migrate/20160303004210_create_tag_rules.rb +++ /dev/null @@ -1,10 +0,0 @@ -class CreateTagRules < ActiveRecord::Migration - def change - create_table :tag_rules do |t| - t.references :enterprise, null: false, index: true - t.string :type, null: false - - t.timestamps - end - end -end diff --git a/db/migrate/20160316051131_add_require_login_to_enterprise.rb b/db/migrate/20160316051131_add_require_login_to_enterprise.rb deleted file mode 100644 index 68de642b62..0000000000 --- a/db/migrate/20160316051131_add_require_login_to_enterprise.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddRequireLoginToEnterprise < ActiveRecord::Migration - def change - add_column :enterprises, :require_login, :boolean, default: false, null: false - end -end diff --git a/db/migrate/20160401043927_change_value_type_of_paypal_passwords.rb b/db/migrate/20160401043927_change_value_type_of_paypal_passwords.rb deleted file mode 100644 index e03ed25f9e..0000000000 --- a/db/migrate/20160401043927_change_value_type_of_paypal_passwords.rb +++ /dev/null @@ -1,15 +0,0 @@ -class ChangeValueTypeOfPaypalPasswords < ActiveRecord::Migration - def up - Spree::Preference - .where("key like ?", "spree/gateway/pay_pal_express/password/%") - .where(value_type: "string") - .update_all(value_type: "password") - end - - def down - Spree::Preference - .where("key like ?", "spree/gateway/pay_pal_express/password/%") - .where(value_type: "password") - .update_all(value_type: "string") - end -end diff --git a/db/migrate/20160520065217_add_is_default_to_tag_rule.rb b/db/migrate/20160520065217_add_is_default_to_tag_rule.rb deleted file mode 100644 index 209520b693..0000000000 --- a/db/migrate/20160520065217_add_is_default_to_tag_rule.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddIsDefaultToTagRule < ActiveRecord::Migration - def change - add_column :tag_rules, :is_default, :boolean, default: false, null: false - end -end diff --git a/db/migrate/20160527012603_add_priority_to_tag_rule.rb b/db/migrate/20160527012603_add_priority_to_tag_rule.rb deleted file mode 100644 index 7080d7a9ac..0000000000 --- a/db/migrate/20160527012603_add_priority_to_tag_rule.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddPriorityToTagRule < ActiveRecord::Migration - def change - add_column :tag_rules, :priority, :integer, default: 99, null: false - end -end diff --git a/db/migrate/20160630052453_create_schedules.rb b/db/migrate/20160630052453_create_schedules.rb deleted file mode 100644 index f1cf5fa5c5..0000000000 --- a/db/migrate/20160630052453_create_schedules.rb +++ /dev/null @@ -1,8 +0,0 @@ -class CreateSchedules < ActiveRecord::Migration - def change - create_table :schedules do |t| - t.string :name, null: false - t.timestamps - end - end -end diff --git a/db/migrate/20160630055825_create_order_cycle_schedules.rb b/db/migrate/20160630055825_create_order_cycle_schedules.rb deleted file mode 100644 index 99147467c9..0000000000 --- a/db/migrate/20160630055825_create_order_cycle_schedules.rb +++ /dev/null @@ -1,14 +0,0 @@ -class CreateOrderCycleSchedules < ActiveRecord::Migration - def change - create_table :order_cycle_schedules do |t| - t.references :order_cycle, null: false - t.references :schedule, null: false - end - - add_index :order_cycle_schedules, :order_cycle_id - add_index :order_cycle_schedules, :schedule_id - - add_foreign_key :order_cycle_schedules, :order_cycles, name: 'oc_schedules_order_cycle_id_fk' - add_foreign_key :order_cycle_schedules, :schedules, name: 'oc_schedules_schedule_id_fk' - end -end diff --git a/db/migrate/20160707023818_drop_cms.rb b/db/migrate/20160707023818_drop_cms.rb deleted file mode 100644 index 018b755466..0000000000 --- a/db/migrate/20160707023818_drop_cms.rb +++ /dev/null @@ -1,154 +0,0 @@ -class DropCms < ActiveRecord::Migration - - # Reverse of CreateCms in 20121009232513_create_cms.rb, including foreign keys defined - # in 20140402033428_add_foreign_keys.rb - - def up - drop_table_cascade :cms_sites - drop_table_cascade :cms_layouts - drop_table_cascade :cms_pages - drop_table_cascade :cms_snippets - drop_table_cascade :cms_blocks - drop_table_cascade :cms_files - drop_table_cascade :cms_revisions - drop_table_cascade :cms_categories - drop_table_cascade :cms_categorizations - end - - def down - text_limit = case ActiveRecord::Base.connection.adapter_name - when 'PostgreSQL' - { } - else - { :limit => 16777215 } - end - - # -- Sites -------------------------------------------------------------- - create_table :cms_sites do |t| - t.string :label, :null => false - t.string :identifier, :null => false - t.string :hostname, :null => false - t.string :path - t.string :locale, :null => false, :default => 'en' - t.boolean :is_mirrored, :null => false, :default => false - end - add_index :cms_sites, :hostname - add_index :cms_sites, :is_mirrored - - # -- Layouts ------------------------------------------------------------ - create_table :cms_layouts do |t| - t.integer :site_id, :null => false - t.integer :parent_id - t.string :app_layout - t.string :label, :null => false - t.string :identifier, :null => false - t.text :content, text_limit - t.text :css, text_limit - t.text :js, text_limit - t.integer :position, :null => false, :default => 0 - t.boolean :is_shared, :null => false, :default => false - t.timestamps - end - add_index :cms_layouts, [:parent_id, :position] - add_index :cms_layouts, [:site_id, :identifier], :unique => true - - # -- Pages -------------------------------------------------------------- - create_table :cms_pages do |t| - t.integer :site_id, :null => false - t.integer :layout_id - t.integer :parent_id - t.integer :target_page_id - t.string :label, :null => false - t.string :slug - t.string :full_path, :null => false - t.text :content, text_limit - t.integer :position, :null => false, :default => 0 - t.integer :children_count, :null => false, :default => 0 - t.boolean :is_published, :null => false, :default => true - t.boolean :is_shared, :null => false, :default => false - t.timestamps - end - add_index :cms_pages, [:site_id, :full_path] - add_index :cms_pages, [:parent_id, :position] - - # -- Page Blocks -------------------------------------------------------- - create_table :cms_blocks do |t| - t.integer :page_id, :null => false - t.string :identifier, :null => false - t.text :content - t.timestamps - end - add_index :cms_blocks, [:page_id, :identifier] - - # -- Snippets ----------------------------------------------------------- - create_table :cms_snippets do |t| - t.integer :site_id, :null => false - t.string :label, :null => false - t.string :identifier, :null => false - t.text :content, text_limit - t.integer :position, :null => false, :default => 0 - t.boolean :is_shared, :null => false, :default => false - t.timestamps - end - add_index :cms_snippets, [:site_id, :identifier], :unique => true - add_index :cms_snippets, [:site_id, :position] - - # -- Files -------------------------------------------------------------- - create_table :cms_files do |t| - t.integer :site_id, :null => false - t.integer :block_id - t.string :label, :null => false - t.string :file_file_name, :null => false - t.string :file_content_type, :null => false - t.integer :file_file_size, :null => false - t.string :description, :limit => 2048 - t.integer :position, :null => false, :default => 0 - t.timestamps - end - add_index :cms_files, [:site_id, :label] - add_index :cms_files, [:site_id, :file_file_name] - add_index :cms_files, [:site_id, :position] - add_index :cms_files, [:site_id, :block_id] - - # -- Revisions ----------------------------------------------------------- - create_table :cms_revisions, :force => true do |t| - t.string :record_type, :null => false - t.integer :record_id, :null => false - t.text :data, text_limit - t.datetime :created_at - end - add_index :cms_revisions, [:record_type, :record_id, :created_at] - - # -- Categories --------------------------------------------------------- - create_table :cms_categories, :force => true do |t| - t.integer :site_id, :null => false - t.string :label, :null => false - t.string :categorized_type, :null => false - end - add_index :cms_categories, [:site_id, :categorized_type, :label], :unique => true - - create_table :cms_categorizations, :force => true do |t| - t.integer :category_id, :null => false - t.string :categorized_type, :null => false - t.integer :categorized_id, :null => false - end - add_index :cms_categorizations, [:category_id, :categorized_type, :categorized_id], :unique => true, - :name => 'index_cms_categorizations_on_cat_id_and_catd_type_and_catd_id' - - - # -- Foreign keys, from 20140402033428_add_foreign_keys.rb - add_foreign_key "cms_blocks", "cms_pages", name: "cms_blocks_page_id_fk", column: "page_id" - add_foreign_key "cms_categories", "cms_sites", name: "cms_categories_site_id_fk", column: "site_id", dependent: :delete - add_foreign_key "cms_categorizations", "cms_categories", name: "cms_categorizations_category_id_fk", column: "category_id" - add_foreign_key "cms_files", "cms_blocks", name: "cms_files_block_id_fk", column: "block_id" - add_foreign_key "cms_files", "cms_sites", name: "cms_files_site_id_fk", column: "site_id" - add_foreign_key "cms_layouts", "cms_layouts", name: "cms_layouts_parent_id_fk", column: "parent_id" - add_foreign_key "cms_layouts", "cms_sites", name: "cms_layouts_site_id_fk", column: "site_id", dependent: :delete - add_foreign_key "cms_pages", "cms_layouts", name: "cms_pages_layout_id_fk", column: "layout_id" - add_foreign_key "cms_pages", "cms_pages", name: "cms_pages_parent_id_fk", column: "parent_id" - add_foreign_key "cms_pages", "cms_sites", name: "cms_pages_site_id_fk", column: "site_id", dependent: :delete - add_foreign_key "cms_pages", "cms_pages", name: "cms_pages_target_page_id_fk", column: "target_page_id" - add_foreign_key "cms_snippets", "cms_sites", name: "cms_snippets_site_id_fk", column: "site_id", dependent: :delete - - end -end diff --git a/db/migrate/20160713003535_add_bill_address_and_ship_address_to_customer.rb b/db/migrate/20160713003535_add_bill_address_and_ship_address_to_customer.rb deleted file mode 100644 index 306276bcc0..0000000000 --- a/db/migrate/20160713003535_add_bill_address_and_ship_address_to_customer.rb +++ /dev/null @@ -1,12 +0,0 @@ -class AddBillAddressAndShipAddressToCustomer < ActiveRecord::Migration - def change - add_column :customers, :bill_address_id, :integer - add_column :customers, :ship_address_id, :integer - - add_index :customers, :bill_address_id - add_index :customers, :ship_address_id - - add_foreign_key :customers, :spree_addresses, column: :bill_address_id - add_foreign_key :customers, :spree_addresses, column: :ship_address_id - end -end diff --git a/db/migrate/20160713013358_add_name_to_customer.rb b/db/migrate/20160713013358_add_name_to_customer.rb deleted file mode 100644 index 832816657e..0000000000 --- a/db/migrate/20160713013358_add_name_to_customer.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddNameToCustomer < ActiveRecord::Migration - def change - add_column :customers, :name, :string - end -end diff --git a/db/migrate/20160819045727_create_standing_orders.rb b/db/migrate/20160819045727_create_standing_orders.rb deleted file mode 100644 index 661bf7411b..0000000000 --- a/db/migrate/20160819045727_create_standing_orders.rb +++ /dev/null @@ -1,25 +0,0 @@ -class CreateStandingOrders < ActiveRecord::Migration - def change - create_table :standing_orders do |t| - t.references :shop, null: false - t.references :customer, null: false - t.references :schedule, null: false - t.references :payment_method, null: false - t.references :shipping_method, null: false - t.datetime :begins_at, :ends_at - t.timestamps - end - - add_index :standing_orders, :shop_id - add_index :standing_orders, :customer_id - add_index :standing_orders, :schedule_id - add_index :standing_orders, :payment_method_id - add_index :standing_orders, :shipping_method_id - - add_foreign_key :standing_orders, :enterprises, name: 'oc_standing_orders_shop_id_fk', column: :shop_id - add_foreign_key :standing_orders, :customers, name: 'oc_standing_orders_customer_id_fk' - add_foreign_key :standing_orders, :schedules, name: 'oc_standing_orders_schedule_id_fk' - add_foreign_key :standing_orders, :spree_payment_methods, name: 'oc_standing_orders_payment_method_id_fk', column: :payment_method_id - add_foreign_key :standing_orders, :spree_shipping_methods, name: 'oc_standing_orders_shipping_method_id_fk', column: :shipping_method_id - end -end diff --git a/db/migrate/20160819065331_swap_calculator_to_flat_percent_per_item.rb b/db/migrate/20160819065331_swap_calculator_to_flat_percent_per_item.rb deleted file mode 100644 index eb8e206e8f..0000000000 --- a/db/migrate/20160819065331_swap_calculator_to_flat_percent_per_item.rb +++ /dev/null @@ -1,29 +0,0 @@ -class SwapCalculatorToFlatPercentPerItem < ActiveRecord::Migration - class Spree::Calculator < ActiveRecord::Base - end - - def up - Spree::Calculator.where(calculable_type: "EnterpriseFee", type: 'Spree::Calculator::FlatPercentItemTotal').each do |c| - swap_calculator_type c, 'Calculator::FlatPercentPerItem' - end - end - - def down - Spree::Calculator.where(calculable_type: "EnterpriseFee", type: 'Spree::Calculator::FlatPercentPerItem').each do |c| - swap_calculator_type c, 'Calculator::FlatPercentItemTotal' - end - end - - - private - - def swap_calculator_type(calculator, to_class) - value = calculator.preferred_flat_percent - - calculator.type = to_class - calculator.save - - calculator = Spree::Calculator.find calculator.id - calculator.preferred_flat_percent = value - end -end diff --git a/db/migrate/20160824013751_create_standing_line_items.rb b/db/migrate/20160824013751_create_standing_line_items.rb deleted file mode 100644 index 90a0d46af3..0000000000 --- a/db/migrate/20160824013751_create_standing_line_items.rb +++ /dev/null @@ -1,16 +0,0 @@ -class CreateStandingLineItems < ActiveRecord::Migration - def change - create_table :standing_line_items do |t| - t.references :standing_order, null: false - t.references :variant, null: false - t.integer :quantity, null: false - t.timestamps - end - - add_index :standing_line_items, :standing_order_id - add_index :standing_line_items, :variant_id - - add_foreign_key :standing_line_items, :standing_orders, name: 'oc_standing_line_items_standing_order_id_fk' - add_foreign_key :standing_line_items, :spree_variants, name: 'oc_standing_line_items_variant_id_fk', column: :variant_id - end -end diff --git a/db/migrate/20160828115018_create_stripe_accounts.rb b/db/migrate/20160828115018_create_stripe_accounts.rb deleted file mode 100644 index 56ab206540..0000000000 --- a/db/migrate/20160828115018_create_stripe_accounts.rb +++ /dev/null @@ -1,12 +0,0 @@ -class CreateStripeAccounts < ActiveRecord::Migration - def change - create_table :stripe_accounts do |t| - t.string :stripe_user_id - t.string :stripe_publishable_key - t.timestamps - t.belongs_to :enterprise - end - - add_index :stripe_accounts, :enterprise_id, unique: true - end -end diff --git a/db/migrate/20160916024535_add_state_to_spree_adjustments.spree.rb b/db/migrate/20160916024535_add_state_to_spree_adjustments.spree.rb deleted file mode 100644 index a4224678df..0000000000 --- a/db/migrate/20160916024535_add_state_to_spree_adjustments.spree.rb +++ /dev/null @@ -1,7 +0,0 @@ -# This migration comes from spree (originally 20121213162028) -class AddStateToSpreeAdjustments < ActiveRecord::Migration - def change - add_column :spree_adjustments, :state, :string - remove_column :spree_adjustments, :locked - end -end diff --git a/db/migrate/20160921060442_add_allow_guest_orders_to_enterprise.rb b/db/migrate/20160921060442_add_allow_guest_orders_to_enterprise.rb deleted file mode 100644 index 7e92c7e74c..0000000000 --- a/db/migrate/20160921060442_add_allow_guest_orders_to_enterprise.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddAllowGuestOrdersToEnterprise < ActiveRecord::Migration - def change - add_column :enterprises, :allow_guest_orders, :boolean, default: true, null: false - end -end diff --git a/db/migrate/20161012022142_add_allow_order_changes_to_enterprise.rb b/db/migrate/20161012022142_add_allow_order_changes_to_enterprise.rb deleted file mode 100644 index 887ce44058..0000000000 --- a/db/migrate/20161012022142_add_allow_order_changes_to_enterprise.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddAllowOrderChangesToEnterprise < ActiveRecord::Migration - def change - add_column :enterprises, :allow_order_changes, :boolean, default: false, null: false - end -end diff --git a/db/migrate/20161014000216_add_ship_and_bill_address_to_standing_orders.rb b/db/migrate/20161014000216_add_ship_and_bill_address_to_standing_orders.rb deleted file mode 100644 index 259227be5f..0000000000 --- a/db/migrate/20161014000216_add_ship_and_bill_address_to_standing_orders.rb +++ /dev/null @@ -1,12 +0,0 @@ -class AddShipAndBillAddressToStandingOrders < ActiveRecord::Migration - def change - add_column :standing_orders, :bill_address_id, :integer, null: false - add_column :standing_orders, :ship_address_id, :integer, null: false - - add_index :standing_orders, :bill_address_id - add_index :standing_orders, :ship_address_id - - add_foreign_key :standing_orders, :spree_addresses, column: :bill_address_id - add_foreign_key :standing_orders, :spree_addresses, column: :ship_address_id - end -end diff --git a/db/migrate/20161020012017_create_standing_order_orders.rb b/db/migrate/20161020012017_create_standing_order_orders.rb deleted file mode 100644 index cbaa0c14cc..0000000000 --- a/db/migrate/20161020012017_create_standing_order_orders.rb +++ /dev/null @@ -1,16 +0,0 @@ -class CreateStandingOrderOrders < ActiveRecord::Migration - def change - create_table :standing_order_orders do |t| - t.references :standing_order, null: false - t.references :order, null: false - t.datetime :cancelled_at - t.timestamps - end - - add_index :standing_order_orders, :standing_order_id - add_index :standing_order_orders, :order_id, unique: true - - add_foreign_key "standing_order_orders", "standing_orders", name: "standing_order_id_fk", column: "standing_order_id" - add_foreign_key "standing_order_orders", "spree_orders", name: "order_id_fk", column: "order_id" - end -end diff --git a/db/migrate/20161110002554_add_standing_orders_placed_at_to_order_cycles.rb b/db/migrate/20161110002554_add_standing_orders_placed_at_to_order_cycles.rb deleted file mode 100644 index 9becae9930..0000000000 --- a/db/migrate/20161110002554_add_standing_orders_placed_at_to_order_cycles.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddStandingOrdersPlacedAtToOrderCycles < ActiveRecord::Migration - def change - add_column :order_cycles, :standing_orders_placed_at, :datetime - end -end diff --git a/db/migrate/20161130001339_add_price_estimate_to_standing_line_items.rb b/db/migrate/20161130001339_add_price_estimate_to_standing_line_items.rb deleted file mode 100644 index 967a24b838..0000000000 --- a/db/migrate/20161130001339_add_price_estimate_to_standing_line_items.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddPriceEstimateToStandingLineItems < ActiveRecord::Migration - def change - add_column :standing_line_items, :price_estimate, :decimal, :precision => 8, :scale => 2 - end -end diff --git a/db/migrate/20161206232009_add_canceled_at_to_standing_orders.rb b/db/migrate/20161206232009_add_canceled_at_to_standing_orders.rb deleted file mode 100644 index f004e28557..0000000000 --- a/db/migrate/20161206232009_add_canceled_at_to_standing_orders.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddCanceledAtToStandingOrders < ActiveRecord::Migration - def change - add_column :standing_orders, :canceled_at, :datetime - end -end diff --git a/db/migrate/20161207040232_rename_standing_order_orders_cancelled_at.rb b/db/migrate/20161207040232_rename_standing_order_orders_cancelled_at.rb deleted file mode 100644 index 6d2c3d0c3f..0000000000 --- a/db/migrate/20161207040232_rename_standing_order_orders_cancelled_at.rb +++ /dev/null @@ -1,7 +0,0 @@ -class RenameStandingOrderOrdersCancelledAt < ActiveRecord::Migration - def change - # No, I'm not illiterate. I just want to maintain consistency with - # existing Spree column names that are spelt using US English - rename_column :standing_order_orders, :cancelled_at, :canceled_at - end -end diff --git a/db/migrate/20161207042153_add_paused_at_to_standing_orders.rb b/db/migrate/20161207042153_add_paused_at_to_standing_orders.rb deleted file mode 100644 index e6e6e95852..0000000000 --- a/db/migrate/20161207042153_add_paused_at_to_standing_orders.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddPausedAtToStandingOrders < ActiveRecord::Migration - def change - add_column :standing_orders, :paused_at, :datetime - end -end diff --git a/db/migrate/20161208233703_add_standing_orders_confirmed_at_to_order_cycles.rb b/db/migrate/20161208233703_add_standing_orders_confirmed_at_to_order_cycles.rb deleted file mode 100644 index 3f4bb3c378..0000000000 --- a/db/migrate/20161208233703_add_standing_orders_confirmed_at_to_order_cycles.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddStandingOrdersConfirmedAtToOrderCycles < ActiveRecord::Migration - def change - add_column :order_cycles, :standing_orders_confirmed_at, :datetime - end -end diff --git a/db/migrate/20161210225156_rename_standing_order_orders_to_proxy_orders.rb b/db/migrate/20161210225156_rename_standing_order_orders_to_proxy_orders.rb deleted file mode 100644 index 964037f823..0000000000 --- a/db/migrate/20161210225156_rename_standing_order_orders_to_proxy_orders.rb +++ /dev/null @@ -1,9 +0,0 @@ -class RenameStandingOrderOrdersToProxyOrders < ActiveRecord::Migration - def change - remove_index :standing_order_orders, :order_id - remove_index :standing_order_orders, :standing_order_id - rename_table :standing_order_orders, :proxy_orders - add_index :proxy_orders, :order_id, unique: true - add_index :proxy_orders, :standing_order_id - end -end diff --git a/db/migrate/20161210235939_add_order_cycle_id_to_proxy_orders.rb b/db/migrate/20161210235939_add_order_cycle_id_to_proxy_orders.rb deleted file mode 100644 index fd18937ea0..0000000000 --- a/db/migrate/20161210235939_add_order_cycle_id_to_proxy_orders.rb +++ /dev/null @@ -1,20 +0,0 @@ -class AddOrderCycleIdToProxyOrders < ActiveRecord::Migration - def up - add_column :proxy_orders, :order_cycle_id, :integer - - ProxyOrder.find_each do |proxy_order| - order_cycle_id = proxy_order.order.order_cycle_id - proxy_order.update_attribute(:order_cycle_id, order_cycle_id) - end - - change_column :proxy_orders, :order_cycle_id, :integer, null: false - add_index :proxy_orders, [:order_cycle_id, :standing_order_id], unique: true - add_foreign_key :proxy_orders, :order_cycles - end - - def down - remove_foreign_key :proxy_orders, :order_cycles - remove_index :proxy_orders, :order_cycle_id - remove_column :proxy_orders, :order_cycle_id - end -end diff --git a/db/migrate/20161211210859_remove_proxy_order_order_not_null_constraint.rb b/db/migrate/20161211210859_remove_proxy_order_order_not_null_constraint.rb deleted file mode 100644 index 726dde623a..0000000000 --- a/db/migrate/20161211210859_remove_proxy_order_order_not_null_constraint.rb +++ /dev/null @@ -1,9 +0,0 @@ -class RemoveProxyOrderOrderNotNullConstraint < ActiveRecord::Migration - def up - change_column :proxy_orders, :order_id, :integer, null: true - end - - def down - change_column :proxy_orders, :order_id, :integer, null: false - end -end diff --git a/db/migrate/20161215032136_add_enable_standing_orders_to_enterprises.rb b/db/migrate/20161215032136_add_enable_standing_orders_to_enterprises.rb deleted file mode 100644 index 3bd4ad13cb..0000000000 --- a/db/migrate/20161215032136_add_enable_standing_orders_to_enterprises.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddEnableStandingOrdersToEnterprises < ActiveRecord::Migration - def change - add_column :enterprises, :enable_standing_orders, :boolean, default: false, null: false - end -end diff --git a/db/migrate/20161215230219_add_invoice_text_and_invoice_logo_to_enterprises.rb b/db/migrate/20161215230219_add_invoice_text_and_invoice_logo_to_enterprises.rb deleted file mode 100644 index d9cfca91ba..0000000000 --- a/db/migrate/20161215230219_add_invoice_text_and_invoice_logo_to_enterprises.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddInvoiceTextAndInvoiceLogoToEnterprises < ActiveRecord::Migration - def change - add_column :enterprises, :invoice_text, :text - add_column :enterprises, :display_invoice_logo, :boolean, default: false - end -end diff --git a/db/migrate/20161222022340_add_placed_at_and_confirmed_at_to_proxy_orders.rb b/db/migrate/20161222022340_add_placed_at_and_confirmed_at_to_proxy_orders.rb deleted file mode 100644 index daf67b1211..0000000000 --- a/db/migrate/20161222022340_add_placed_at_and_confirmed_at_to_proxy_orders.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddPlacedAtAndConfirmedAtToProxyOrders < ActiveRecord::Migration - def change - add_column :proxy_orders, :placed_at, :datetime - add_column :proxy_orders, :confirmed_at, :datetime - end -end diff --git a/db/migrate/20170225203658_add_user_id_to_spree_credit_cards.rb b/db/migrate/20170225203658_add_user_id_to_spree_credit_cards.rb deleted file mode 100644 index 29e50e0c1a..0000000000 --- a/db/migrate/20170225203658_add_user_id_to_spree_credit_cards.rb +++ /dev/null @@ -1,8 +0,0 @@ -class AddUserIdToSpreeCreditCards < ActiveRecord::Migration - def change - unless Spree::CreditCard.column_names.include? "user_id" - add_column :spree_credit_cards, :user_id, :integer - add_index :spree_credit_cards, :user_id - end - end -end diff --git a/db/migrate/20170304151129_add_payment_method_to_spree_credit_cards.rb b/db/migrate/20170304151129_add_payment_method_to_spree_credit_cards.rb deleted file mode 100644 index 76c1cab805..0000000000 --- a/db/migrate/20170304151129_add_payment_method_to_spree_credit_cards.rb +++ /dev/null @@ -1,8 +0,0 @@ -class AddPaymentMethodToSpreeCreditCards < ActiveRecord::Migration - def change - unless Spree::CreditCard.column_names.include? "payment_method_id" - add_column :spree_credit_cards, :payment_method_id, :integer - add_index :spree_credit_cards, :payment_method_id - end - end -end diff --git a/db/migrate/20170310231746_add_import_date_to_spree_variants.rb b/db/migrate/20170310231746_add_import_date_to_spree_variants.rb deleted file mode 100644 index d5acbf882e..0000000000 --- a/db/migrate/20170310231746_add_import_date_to_spree_variants.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddImportDateToSpreeVariants < ActiveRecord::Migration - def change - add_column :spree_variants, :import_date, :datetime - end -end diff --git a/db/migrate/20170314132401_add_import_date_to_variant_overrides.rb b/db/migrate/20170314132401_add_import_date_to_variant_overrides.rb deleted file mode 100644 index daef32ec61..0000000000 --- a/db/migrate/20170314132401_add_import_date_to_variant_overrides.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddImportDateToVariantOverrides < ActiveRecord::Migration - def change - add_column :variant_overrides, :import_date, :datetime - end -end diff --git a/db/migrate/20170413074528_rename_payment_methods.spree_paypal_express.rb b/db/migrate/20170413074528_rename_payment_methods.spree_paypal_express.rb deleted file mode 100644 index 2c426824d8..0000000000 --- a/db/migrate/20170413074528_rename_payment_methods.spree_paypal_express.rb +++ /dev/null @@ -1,14 +0,0 @@ -# This migration comes from spree_paypal_express (originally 20140117051315) -class RenamePaymentMethods < ActiveRecord::Migration - def up - execute <<-SQL - update spree_payment_methods set type = 'Spree::Gateway::PayPalExpress' WHERE type = 'Spree::BillingIntegration::PaypalExpress' - SQL - end - - def down - execute <<-SQL - update spree_payment_methods set type = 'Spree::BillingIntegration::PaypalExpress' WHERE type = 'Spree::Gateway::PayPalExpress' - SQL - end -end diff --git a/db/migrate/20170413083148_add_tracking_url_to_spree_shipping_methods.spree.rb b/db/migrate/20170413083148_add_tracking_url_to_spree_shipping_methods.spree.rb deleted file mode 100644 index 28a9807184..0000000000 --- a/db/migrate/20170413083148_add_tracking_url_to_spree_shipping_methods.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130301205200) -class AddTrackingUrlToSpreeShippingMethods < ActiveRecord::Migration - def change - add_column :spree_shipping_methods, :tracking_url, :string - end -end diff --git a/db/migrate/20170512115519_add_locale_to_spree_users.rb b/db/migrate/20170512115519_add_locale_to_spree_users.rb deleted file mode 100644 index f694bff1f7..0000000000 --- a/db/migrate/20170512115519_add_locale_to_spree_users.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddLocaleToSpreeUsers < ActiveRecord::Migration - def change - add_column :spree_users, :locale, :string, limit: 5 - end -end diff --git a/db/migrate/20170710145821_add_confirmable_to_user.rb b/db/migrate/20170710145821_add_confirmable_to_user.rb deleted file mode 100644 index cd458545e0..0000000000 --- a/db/migrate/20170710145821_add_confirmable_to_user.rb +++ /dev/null @@ -1,16 +0,0 @@ -class AddConfirmableToUser < ActiveRecord::Migration - def up - add_column :spree_users, :confirmation_token, :string - add_column :spree_users, :confirmed_at, :datetime - add_column :spree_users, :confirmation_sent_at, :datetime - add_column :spree_users, :unconfirmed_email, :string - add_index :spree_users, :confirmation_token, :unique => true - - # Set all current users to confirmed - Spree::User.update_all(confirmed_at: Time.zone.now) - end - - def down - remove_columns :spree_users, :confirmation_token, :confirmed_at, :confirmation_sent_at, :unconfirmed_email - end -end diff --git a/db/migrate/20170719125120_remove_confirmable_from_enterprises.rb b/db/migrate/20170719125120_remove_confirmable_from_enterprises.rb deleted file mode 100644 index a4aad51dd4..0000000000 --- a/db/migrate/20170719125120_remove_confirmable_from_enterprises.rb +++ /dev/null @@ -1,16 +0,0 @@ -class RemoveConfirmableFromEnterprises < ActiveRecord::Migration - def up - remove_columns :enterprises, :confirmation_token, :confirmed_at, :confirmation_sent_at, :unconfirmed_email - end - - def down - add_column :enterprises, :confirmation_token, :string - add_column :enterprises, :confirmed_at, :datetime - add_column :enterprises, :confirmation_sent_at, :datetime - add_column :enterprises, :unconfirmed_email, :string - add_index :enterprises, :confirmation_token, :unique => true - - # Existing enterprises are assumed to be confirmed - Enterprise.update_all(:confirmed_at => Time.zone.now) - end -end diff --git a/db/migrate/20170727104900_add_receives_notifications_to_enterprise_roles.rb b/db/migrate/20170727104900_add_receives_notifications_to_enterprise_roles.rb deleted file mode 100644 index 128cc2a554..0000000000 --- a/db/migrate/20170727104900_add_receives_notifications_to_enterprise_roles.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddReceivesNotificationsToEnterpriseRoles < ActiveRecord::Migration - def change - add_column :enterprise_roles, :receives_notifications, :boolean, default: false - end -end diff --git a/db/migrate/20170728140134_remove_email_from_enterprises.rb b/db/migrate/20170728140134_remove_email_from_enterprises.rb deleted file mode 100644 index b5cd8420c0..0000000000 --- a/db/migrate/20170728140134_remove_email_from_enterprises.rb +++ /dev/null @@ -1,48 +0,0 @@ -class RemoveEmailFromEnterprises < ActiveRecord::Migration - class Enterprise < ActiveRecord::Base; end - class Spree::User < ActiveRecord::Base; end - - class EnterpriseRole < ActiveRecord::Base - belongs_to :user, class_name: 'Spree::User' - belongs_to :enterprise, class_name: 'Enterprise' - end - - def up - Enterprise.reset_column_information - Spree::User.reset_column_information - EnterpriseRole.reset_column_information - - Enterprise.select([:id, :email, :owner_id]).each do |enterprise| - update_enterprise_contact enterprise - end - - remove_column :enterprises, :email - rename_column :enterprises, :contact, :contact_name - end - - def down - Enterprise.reset_column_information - Spree::User.reset_column_information - EnterpriseRole.reset_column_information - - add_column :enterprises, :email, :string - rename_column :enterprises, :contact_name, :contact - - Enterprise.select(:id).each do |e| - manager = EnterpriseRole.find_by(enterprise_id: e.id, receives_notifications: true) - user = Spree::User.find(manager.user_id) - e.update_attribute :email, user.email - end - end - - def update_enterprise_contact(enterprise) - contact_user = contact_or_owner(enterprise) - - role = EnterpriseRole.find_or_initialize_by(user_id: contact_user.id, enterprise_id: enterprise.id) - role.update_attribute :receives_notifications, true - end - - def contact_or_owner(enterprise) - Spree::User.find_by(email: enterprise.email) || Spree::User.find(enterprise.owner_id) - end -end diff --git a/db/migrate/20170913205345_change_default_value_of_spree_users_enterprise_limit.rb b/db/migrate/20170913205345_change_default_value_of_spree_users_enterprise_limit.rb deleted file mode 100644 index 2db2182d9c..0000000000 --- a/db/migrate/20170913205345_change_default_value_of_spree_users_enterprise_limit.rb +++ /dev/null @@ -1,9 +0,0 @@ -class ChangeDefaultValueOfSpreeUsersEnterpriseLimit < ActiveRecord::Migration - def up - change_column :spree_users, :enterprise_limit, :integer, default: 5 - end - - def down - change_column :spree_users, :enterprise_limit, :integer, default: 1 - end -end diff --git a/db/migrate/20170921065259_update_adjustment_states.spree.rb b/db/migrate/20170921065259_update_adjustment_states.spree.rb deleted file mode 100644 index 9040709751..0000000000 --- a/db/migrate/20170921065259_update_adjustment_states.spree.rb +++ /dev/null @@ -1,17 +0,0 @@ -# This migration comes from spree (originally 20130417120035) -class UpdateAdjustmentStates < ActiveRecord::Migration - def up - Spree::Order.complete.find_each do |order| - order.adjustments.update_all(:state => 'closed') - end - - Spree::Shipment.shipped.includes(:adjustment).find_each do |shipment| - shipment.adjustment.update_column(:state, 'finalized') if shipment.adjustment - end - - Spree::Adjustment.where(:state => nil).update_all(:state => 'open') - end - - def down - end -end diff --git a/db/migrate/20171027005930_add_credit_card_to_standing_orders.rb b/db/migrate/20171027005930_add_credit_card_to_standing_orders.rb deleted file mode 100644 index 60e5133a72..0000000000 --- a/db/migrate/20171027005930_add_credit_card_to_standing_orders.rb +++ /dev/null @@ -1,7 +0,0 @@ -class AddCreditCardToStandingOrders < ActiveRecord::Migration - def change - add_column :standing_orders, :credit_card_id, :integer - add_index :standing_orders, :credit_card_id - add_foreign_key :standing_orders, :spree_credit_cards, name: :standing_orders_credit_card_id_fk, column: :credit_card_id - end -end diff --git a/db/migrate/20180202024104_rename_standing_orders_to_subscriptions.rb b/db/migrate/20180202024104_rename_standing_orders_to_subscriptions.rb deleted file mode 100644 index 91c90d90b5..0000000000 --- a/db/migrate/20180202024104_rename_standing_orders_to_subscriptions.rb +++ /dev/null @@ -1,99 +0,0 @@ -class RenameStandingOrdersToSubscriptions < ActiveRecord::Migration - def up - remove_foreign_key :proxy_orders, name: :standing_order_id_fk - remove_foreign_key :standing_line_items, name: :oc_standing_line_items_standing_order_id_fk - - remove_foreign_key :standing_orders, name: :oc_standing_orders_customer_id_fk - remove_foreign_key :standing_orders, name: :oc_standing_orders_shop_id_fk - remove_foreign_key :standing_orders, name: :oc_standing_orders_schedule_id_fk - remove_foreign_key :standing_orders, name: :standing_orders_bill_address_id_fk - remove_foreign_key :standing_orders, name: :standing_orders_ship_address_id_fk - remove_foreign_key :standing_orders, name: :standing_orders_credit_card_id_fk - remove_foreign_key :standing_orders, name: :oc_standing_orders_payment_method_id_fk - remove_foreign_key :standing_orders, name: :oc_standing_orders_shipping_method_id_fk - - remove_index :proxy_orders, :column => [:order_cycle_id, :standing_order_id] - remove_index :proxy_orders, :column => [:standing_order_id] - remove_index :standing_line_items, :column => [:standing_order_id] - - rename_table :standing_orders, :subscriptions - - rename_index :subscriptions, :index_standing_orders_on_bill_address_id, :index_subscriptions_on_bill_address_id - rename_index :subscriptions, :index_standing_orders_on_credit_card_id, :index_subscriptions_on_credit_card_id - rename_index :subscriptions, :index_standing_orders_on_customer_id, :index_subscriptions_on_customer_id - rename_index :subscriptions, :index_standing_orders_on_payment_method_id, :index_subscriptions_on_payment_method_id - rename_index :subscriptions, :index_standing_orders_on_schedule_id, :index_subscriptions_on_schedule_id - rename_index :subscriptions, :index_standing_orders_on_ship_address_id, :index_subscriptions_on_ship_address_id - rename_index :subscriptions, :index_standing_orders_on_shipping_method_id, :index_subscriptions_on_shipping_method_id - rename_index :subscriptions, :index_standing_orders_on_shop_id, :index_subscriptions_on_shop_id - - rename_column :enterprises, :enable_standing_orders, :enable_subscriptions - rename_column :proxy_orders, :standing_order_id, :subscription_id - rename_column :standing_line_items, :standing_order_id, :subscription_id - - add_index :proxy_orders, [:order_cycle_id, :subscription_id], unique: true - add_index :proxy_orders, :subscription_id - add_index :standing_line_items, :subscription_id - - add_foreign_key :proxy_orders, :subscriptions, name: :proxy_orders_subscription_id_fk - add_foreign_key :standing_line_items, :subscriptions, name: :standing_line_items_subscription_id_fk - - add_foreign_key :subscriptions, :customers, name: :subscriptions_customer_id_fk - add_foreign_key :subscriptions, :enterprises, name: :subscriptions_shop_id_fk, column: :shop_id - add_foreign_key :subscriptions, :schedules, name: :subscriptions_schedule_id_fk - add_foreign_key :subscriptions, :spree_addresses, name: :subscriptions_bill_address_id_fk, column: :bill_address_id - add_foreign_key :subscriptions, :spree_addresses, name: :subscriptions_ship_address_id_fk, column: :ship_address_id - add_foreign_key :subscriptions, :spree_credit_cards, name: :subscriptions_credit_card_id_fk, column: :credit_card_id - add_foreign_key :subscriptions, :spree_payment_methods, name: :subscriptions_payment_method_id_fk, column: :payment_method_id - add_foreign_key :subscriptions, :spree_shipping_methods, name: :subscriptions_shipping_method_id_fk, column: :shipping_method_id - end - - def down - remove_foreign_key :proxy_orders, name: :proxy_orders_subscription_id_fk - remove_foreign_key :standing_line_items, name: :standing_line_items_subscription_id_fk - - remove_foreign_key :subscriptions, name: :subscriptions_customer_id_fk - remove_foreign_key :subscriptions, name: :subscriptions_shop_id_fk - remove_foreign_key :subscriptions, name: :subscriptions_schedule_id_fk - remove_foreign_key :subscriptions, name: :subscriptions_bill_address_id_fk - remove_foreign_key :subscriptions, name: :subscriptions_ship_address_id_fk - remove_foreign_key :subscriptions, name: :subscriptions_credit_card_id_fk - remove_foreign_key :subscriptions, name: :subscriptions_payment_method_id_fk - remove_foreign_key :subscriptions, name: :subscriptions_shipping_method_id_fk - - remove_index :proxy_orders, :column => [:order_cycle_id, :subscription_id] - remove_index :proxy_orders, :column => [:subscription_id] - remove_index :standing_line_items, :column => [:subscription_id] - - rename_table :subscriptions, :standing_orders - - rename_index :standing_orders, :index_subscriptions_on_bill_address_id, :index_standing_orders_on_bill_address_id - rename_index :standing_orders, :index_subscriptions_on_credit_card_id, :index_standing_orders_on_credit_card_id - rename_index :standing_orders, :index_subscriptions_on_customer_id, :index_standing_orders_on_customer_id - rename_index :standing_orders, :index_subscriptions_on_payment_method_id, :index_standing_orders_on_payment_method_id - rename_index :standing_orders, :index_subscriptions_on_schedule_id, :index_standing_orders_on_schedule_id - rename_index :standing_orders, :index_subscriptions_on_ship_address_id, :index_standing_orders_on_ship_address_id - rename_index :standing_orders, :index_subscriptions_on_shipping_method_id, :index_standing_orders_on_shipping_method_id - rename_index :standing_orders, :index_subscriptions_on_shop_id, :index_standing_orders_on_shop_id - - rename_column :enterprises, :enable_subscriptions, :enable_standing_orders - rename_column :proxy_orders, :subscription_id, :standing_order_id - rename_column :standing_line_items, :subscription_id, :standing_order_id - - add_index :proxy_orders, [:order_cycle_id, :standing_order_id], unique: true - add_index :proxy_orders, :standing_order_id - add_index :standing_line_items, :standing_order_id - - add_foreign_key :proxy_orders, :standing_orders, name: :standing_order_id_fk - add_foreign_key :standing_line_items, :standing_orders, name: :oc_standing_line_items_standing_order_id_fk - - add_foreign_key :standing_orders, :customers, name: :oc_standing_orders_customer_id_fk - add_foreign_key :standing_orders, :enterprises, name: :oc_standing_orders_shop_id_fk, column: :shop_id - add_foreign_key :standing_orders, :schedules, name: :oc_standing_orders_schedule_id_fk - add_foreign_key :standing_orders, :spree_addresses, name: :standing_orders_bill_address_id_fk, column: :bill_address_id - add_foreign_key :standing_orders, :spree_addresses, name: :standing_orders_ship_address_id_fk, column: :ship_address_id - add_foreign_key :standing_orders, :spree_credit_cards, name: :standing_orders_credit_card_id_fk, column: :credit_card_id - add_foreign_key :standing_orders, :spree_payment_methods, name: :oc_standing_orders_payment_method_id_fk, column: :payment_method_id - add_foreign_key :standing_orders, :spree_shipping_methods, name: :oc_standing_orders_shipping_method_id_fk, column: :shipping_method_id - end -end diff --git a/db/migrate/20180204235108_rename_standing_line_items_to_subscription_line_items.rb b/db/migrate/20180204235108_rename_standing_line_items_to_subscription_line_items.rb deleted file mode 100644 index eda85f905b..0000000000 --- a/db/migrate/20180204235108_rename_standing_line_items_to_subscription_line_items.rb +++ /dev/null @@ -1,27 +0,0 @@ -class RenameStandingLineItemsToSubscriptionLineItems < ActiveRecord::Migration - def up - remove_foreign_key :standing_line_items, name: :oc_standing_line_items_variant_id_fk - remove_foreign_key :standing_line_items, name: :standing_line_items_subscription_id_fk - - rename_table :standing_line_items, :subscription_line_items - - rename_index :subscription_line_items, :index_standing_line_items_on_subscription_id, :index_subscription_line_items_on_subscription_id - rename_index :subscription_line_items, :index_standing_line_items_on_variant_id, :index_subscription_line_items_on_variant_id - - add_foreign_key :subscription_line_items, :spree_variants, name: :subscription_line_items_variant_id_fk, column: :variant_id - add_foreign_key :subscription_line_items, :subscriptions, name: :subscription_line_items_subscription_id_fk - end - - def down - remove_foreign_key :subscription_line_items, name: :subscription_line_items_variant_id_fk - remove_foreign_key :subscription_line_items, name: :subscription_line_items_subscription_id_fk - - rename_table :subscription_line_items, :standing_line_items - - rename_index :standing_line_items, :index_subscription_line_items_on_subscription_id, :index_standing_line_items_on_subscription_id - rename_index :standing_line_items, :index_subscription_line_items_on_variant_id, :index_standing_line_items_on_variant_id - - add_foreign_key :standing_line_items, :spree_variants, name: :oc_standing_line_items_variant_id_fk, column: :variant_id - add_foreign_key :standing_line_items, :subscriptions, name: :standing_line_items_subscription_id_fk - end -end diff --git a/db/migrate/20180222231639_add_shipping_fee_estimate_and_payment_fee_estimate_to_subscription.rb b/db/migrate/20180222231639_add_shipping_fee_estimate_and_payment_fee_estimate_to_subscription.rb deleted file mode 100644 index 2c4f29d891..0000000000 --- a/db/migrate/20180222231639_add_shipping_fee_estimate_and_payment_fee_estimate_to_subscription.rb +++ /dev/null @@ -1,6 +0,0 @@ -class AddShippingFeeEstimateAndPaymentFeeEstimateToSubscription < ActiveRecord::Migration - def change - add_column :subscriptions, :shipping_fee_estimate, :decimal, :precision => 8, :scale => 2 - add_column :subscriptions, :payment_fee_estimate, :decimal, :precision => 8, :scale => 2 - end -end diff --git a/db/migrate/20180316034336_remove_placed_at_and_confirmed_at_from_order_cycles.rb b/db/migrate/20180316034336_remove_placed_at_and_confirmed_at_from_order_cycles.rb deleted file mode 100644 index b41d698eb3..0000000000 --- a/db/migrate/20180316034336_remove_placed_at_and_confirmed_at_from_order_cycles.rb +++ /dev/null @@ -1,11 +0,0 @@ -class RemovePlacedAtAndConfirmedAtFromOrderCycles < ActiveRecord::Migration - def up - remove_column :order_cycles, :standing_orders_placed_at - remove_column :order_cycles, :standing_orders_confirmed_at - end - - def down - add_column :order_cycles, :standing_orders_placed_at, :datetime - add_column :order_cycles, :standing_orders_confirmed_at, :datetime - end -end diff --git a/db/migrate/20180406045821_add_charges_allowed_to_customers.rb b/db/migrate/20180406045821_add_charges_allowed_to_customers.rb deleted file mode 100644 index 4503dc87b6..0000000000 --- a/db/migrate/20180406045821_add_charges_allowed_to_customers.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddChargesAllowedToCustomers < ActiveRecord::Migration - def change - add_column :customers, :allow_charges, :boolean, default: false, null: false - end -end diff --git a/db/migrate/20180418025217_add_is_default_to_credit_card.rb b/db/migrate/20180418025217_add_is_default_to_credit_card.rb deleted file mode 100644 index c39b3e44dc..0000000000 --- a/db/migrate/20180418025217_add_is_default_to_credit_card.rb +++ /dev/null @@ -1,5 +0,0 @@ -class AddIsDefaultToCreditCard < ActiveRecord::Migration - def change - add_column :spree_credit_cards, :is_default, :boolean, default: false - end -end diff --git a/db/migrate/20180426145630_create_spree_stock_items.spree.rb b/db/migrate/20180426145630_create_spree_stock_items.spree.rb deleted file mode 100644 index cd6f349740..0000000000 --- a/db/migrate/20180426145630_create_spree_stock_items.spree.rb +++ /dev/null @@ -1,15 +0,0 @@ -# This migration comes from spree (originally 20130211190146) -class CreateSpreeStockItems < ActiveRecord::Migration - def change - create_table :spree_stock_items do |t| - t.belongs_to :stock_location - t.belongs_to :variant - t.integer :count_on_hand, null: false, default: 0 - t.integer :lock_version - - t.timestamps - end - add_index :spree_stock_items, :stock_location_id - add_index :spree_stock_items, [:stock_location_id, :variant_id], :name => 'stock_item_by_loc_and_var_id' - end -end diff --git a/db/migrate/20180426145631_create_spree_stock_locations.spree.rb b/db/migrate/20180426145631_create_spree_stock_locations.spree.rb deleted file mode 100644 index a3e4d1a4dc..0000000000 --- a/db/migrate/20180426145631_create_spree_stock_locations.spree.rb +++ /dev/null @@ -1,12 +0,0 @@ -# This migration comes from spree (originally 20130211191120) -class CreateSpreeStockLocations < ActiveRecord::Migration - def change - create_table :spree_stock_locations do |t| - t.string :name - t.belongs_to :address - - t.timestamps - end - add_index :spree_stock_locations, :address_id - end -end diff --git a/db/migrate/20180426145632_create_default_stock.spree.rb b/db/migrate/20180426145632_create_default_stock.spree.rb deleted file mode 100644 index 7e1d188e4a..0000000000 --- a/db/migrate/20180426145632_create_default_stock.spree.rb +++ /dev/null @@ -1,34 +0,0 @@ -Spree::Stock::Quantifier.class_eval do - def initialize(variant) - @variant = variant - @stock_items = Spree::StockItem.joins(:stock_location).where(:variant_id => @variant) - end -end - -# This migration comes from spree (originally 20130213191427) -class CreateDefaultStock < ActiveRecord::Migration - def up - Spree::StockLocation.skip_callback(:create, :after, :create_stock_items) - Spree::StockItem.skip_callback(:save, :after, :process_backorders) - location = Spree::StockLocation.create(name: 'default') - Spree::Variant.all.each do |variant| - stock_item = location.stock_items.build(variant: variant) - stock_item.send(:count_on_hand=, variant.count_on_hand) - stock_item.save! - end - - remove_column :spree_variants, :count_on_hand - end - - def down - add_column :spree_variants, :count_on_hand, :integer - - Spree::StockItem.all.each do |stock_item| - stock_item.variant.update_column :count_on_hand, stock_item.count_on_hand - end - - Spree::StockLocation.delete_all - Spree::StockItem.delete_all - end -end - diff --git a/db/migrate/20180426145633_add_stock_location_id_to_spree_shipments.spree.rb b/db/migrate/20180426145633_add_stock_location_id_to_spree_shipments.spree.rb deleted file mode 100644 index e102d7febb..0000000000 --- a/db/migrate/20180426145633_add_stock_location_id_to_spree_shipments.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130226191231) -class AddStockLocationIdToSpreeShipments < ActiveRecord::Migration - def change - add_column :spree_shipments, :stock_location_id, :integer - end -end diff --git a/db/migrate/20180426145634_add_pending_to_inventory_unit.spree.rb b/db/migrate/20180426145634_add_pending_to_inventory_unit.spree.rb deleted file mode 100644 index c3879d3604..0000000000 --- a/db/migrate/20180426145634_add_pending_to_inventory_unit.spree.rb +++ /dev/null @@ -1,7 +0,0 @@ -# This migration comes from spree (originally 20130227143905) -class AddPendingToInventoryUnit < ActiveRecord::Migration - def change - add_column :spree_inventory_units, :pending, :boolean, :default => true - Spree::InventoryUnit.update_all(:pending => false) - end -end diff --git a/db/migrate/20180426145635_remove_on_demand_from_product_and_variant.spree.rb b/db/migrate/20180426145635_remove_on_demand_from_product_and_variant.spree.rb deleted file mode 100644 index 0732d4ffd0..0000000000 --- a/db/migrate/20180426145635_remove_on_demand_from_product_and_variant.spree.rb +++ /dev/null @@ -1,7 +0,0 @@ -# This migration comes from spree (originally 20130228164411) -class RemoveOnDemandFromProductAndVariant < ActiveRecord::Migration - def change - remove_column :spree_products, :on_demand - # we are removing spree_variants.on_demand in a later migration - end -end diff --git a/db/migrate/20180426145636_create_shipping_method_zone.spree.rb b/db/migrate/20180426145636_create_shipping_method_zone.spree.rb deleted file mode 100644 index 2d99447b13..0000000000 --- a/db/migrate/20180426145636_create_shipping_method_zone.spree.rb +++ /dev/null @@ -1,23 +0,0 @@ -# This migration comes from spree (originally 20130228210442) -class CreateShippingMethodZone < ActiveRecord::Migration - def up - create_table :shipping_methods_zones, :id => false do |t| - t.integer :shipping_method_id - t.integer :zone_id - end - # This association has been corrected in a latter migration - # but when this database migration runs, the table is still incorrectly named - # 'shipping_methods_zones' instead of 'spre_shipping_methods_zones' - Spree::ShippingMethod.has_and_belongs_to_many :zones, :join_table => 'shipping_methods_zones', - :class_name => 'Spree::Zone', - :foreign_key => 'shipping_method_id' - Spree::ShippingMethod.all.each{|sm| sm.zones << Spree::Zone.find(sm.zone_id)} - - remove_column :spree_shipping_methods, :zone_id - end - - def down - drop_table :shipping_methods_zones - add_column :spree_shipping_methods, :zone_id, :integer - end -end diff --git a/db/migrate/20180426145637_remove_shipping_category_id_from_shipping_method.spree.rb b/db/migrate/20180426145637_remove_shipping_category_id_from_shipping_method.spree.rb deleted file mode 100644 index f686ac4aa7..0000000000 --- a/db/migrate/20180426145637_remove_shipping_category_id_from_shipping_method.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130301162745) -class RemoveShippingCategoryIdFromShippingMethod < ActiveRecord::Migration - def change - remove_column :spree_shipping_methods, :shipping_category_id - end -end diff --git a/db/migrate/20180426145638_create_shipping_method_categories.spree.rb b/db/migrate/20180426145638_create_shipping_method_categories.spree.rb deleted file mode 100644 index 2af03a7ec0..0000000000 --- a/db/migrate/20180426145638_create_shipping_method_categories.spree.rb +++ /dev/null @@ -1,14 +0,0 @@ -# This migration comes from spree (originally 20130301162924) -class CreateShippingMethodCategories < ActiveRecord::Migration - def change - create_table :spree_shipping_method_categories do |t| - t.integer :shipping_method_id, :null => false - t.integer :shipping_category_id, :null => false - - t.timestamps - end - - add_index :spree_shipping_method_categories, :shipping_method_id - add_index :spree_shipping_method_categories, :shipping_category_id - end -end diff --git a/db/migrate/20180426145639_create_spree_shipping_rates.spree.rb b/db/migrate/20180426145639_create_spree_shipping_rates.spree.rb deleted file mode 100644 index f2932a57b3..0000000000 --- a/db/migrate/20180426145639_create_spree_shipping_rates.spree.rb +++ /dev/null @@ -1,25 +0,0 @@ -# This migration comes from spree (originally 20130304162240) -class CreateSpreeShippingRates < ActiveRecord::Migration - def up - create_table :spree_shipping_rates do |t| - t.belongs_to :shipment - t.belongs_to :shipping_method - t.boolean :selected, :default => false - t.decimal :cost, :precision => 8, :scale => 2 - t.timestamps - end - add_index(:spree_shipping_rates, [:shipment_id, :shipping_method_id], - :name => 'spree_shipping_rates_join_index', - :unique => true) - - # Spree::Shipment.all.each do |shipment| - # shipping_method = Spree::ShippingMethod.find(shipment.shipment_method_id) - # shipment.add_shipping_method(shipping_method, true) - # end - end - - def down - # add_column :spree_shipments, :shipping_method_id, :integer - drop_table :spree_shipping_rates - end -end diff --git a/db/migrate/20180426145640_remove_category_match_attributes_from_shipping_method.spree.rb b/db/migrate/20180426145640_remove_category_match_attributes_from_shipping_method.spree.rb deleted file mode 100644 index 1562aecdb2..0000000000 --- a/db/migrate/20180426145640_remove_category_match_attributes_from_shipping_method.spree.rb +++ /dev/null @@ -1,8 +0,0 @@ -# This migration comes from spree (originally 20130304192936) -class RemoveCategoryMatchAttributesFromShippingMethod < ActiveRecord::Migration - def change - remove_column :spree_shipping_methods, :match_none - remove_column :spree_shipping_methods, :match_one - remove_column :spree_shipping_methods, :match_all - end -end diff --git a/db/migrate/20180426145641_create_stock_movements.spree.rb b/db/migrate/20180426145641_create_stock_movements.spree.rb deleted file mode 100644 index d7c8cb88d3..0000000000 --- a/db/migrate/20180426145641_create_stock_movements.spree.rb +++ /dev/null @@ -1,13 +0,0 @@ -# This migration comes from spree (originally 20130305143310) -class CreateStockMovements < ActiveRecord::Migration - def change - create_table :spree_stock_movements do |t| - t.belongs_to :stock_item - t.integer :quantity - t.string :action - - t.timestamps - end - add_index :spree_stock_movements, :stock_item_id - end -end diff --git a/db/migrate/20180426145642_add_address_fields_to_stock_location.spree.rb b/db/migrate/20180426145642_add_address_fields_to_stock_location.spree.rb deleted file mode 100644 index 4a16efeb40..0000000000 --- a/db/migrate/20180426145642_add_address_fields_to_stock_location.spree.rb +++ /dev/null @@ -1,23 +0,0 @@ -# This migration comes from spree (originally 20130306181701) -class AddAddressFieldsToStockLocation < ActiveRecord::Migration - def change - remove_column :spree_stock_locations, :address_id - - add_column :spree_stock_locations, :address1, :string - add_column :spree_stock_locations, :address2, :string - add_column :spree_stock_locations, :city, :string - add_column :spree_stock_locations, :state_id, :integer - add_column :spree_stock_locations, :state_name, :string - add_column :spree_stock_locations, :country_id, :integer - add_column :spree_stock_locations, :zipcode, :string - add_column :spree_stock_locations, :phone, :string - - - usa = Spree::Country.where(:iso => 'US').first - # In case USA isn't found. - # See #3115 - country = usa || Spree::Country.first - Spree::Country.reset_column_information - Spree::StockLocation.update_all(:country_id => country) - end -end diff --git a/db/migrate/20180426145643_add_active_field_to_stock_locations.spree.rb b/db/migrate/20180426145643_add_active_field_to_stock_locations.spree.rb deleted file mode 100644 index 0e69642de2..0000000000 --- a/db/migrate/20180426145643_add_active_field_to_stock_locations.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130306191917) -class AddActiveFieldToStockLocations < ActiveRecord::Migration - def change - add_column :spree_stock_locations, :active, :boolean, :default => true - end -end diff --git a/db/migrate/20180426145644_add_backorderable_to_stock_item.spree.rb b/db/migrate/20180426145644_add_backorderable_to_stock_item.spree.rb deleted file mode 100644 index 839e3b3d09..0000000000 --- a/db/migrate/20180426145644_add_backorderable_to_stock_item.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130306195650) -class AddBackorderableToStockItem < ActiveRecord::Migration - def change - add_column :spree_stock_items, :backorderable, :boolean, :default => true - end -end diff --git a/db/migrate/20180426145645_add_default_quantity_to_stock_movement.spree.rb b/db/migrate/20180426145645_add_default_quantity_to_stock_movement.spree.rb deleted file mode 100644 index c991b94e4a..0000000000 --- a/db/migrate/20180426145645_add_default_quantity_to_stock_movement.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130307161754) -class AddDefaultQuantityToStockMovement < ActiveRecord::Migration - def change - change_column :spree_stock_movements, :quantity, :integer, :default => 0 - end -end diff --git a/db/migrate/20180426145646_add_source_and_destination_to_stock_movements.spree.rb b/db/migrate/20180426145646_add_source_and_destination_to_stock_movements.spree.rb deleted file mode 100644 index 7e0f0987b7..0000000000 --- a/db/migrate/20180426145646_add_source_and_destination_to_stock_movements.spree.rb +++ /dev/null @@ -1,9 +0,0 @@ -# This migration comes from spree (originally 20130318151756) -class AddSourceAndDestinationToStockMovements < ActiveRecord::Migration - def change - change_table :spree_stock_movements do |t| - t.references :source, polymorphic: true - t.references :destination, polymorphic: true - end - end -end diff --git a/db/migrate/20180426145647_add_originator_to_stock_movement.spree.rb b/db/migrate/20180426145647_add_originator_to_stock_movement.spree.rb deleted file mode 100644 index 7c1a74679a..0000000000 --- a/db/migrate/20180426145647_add_originator_to_stock_movement.spree.rb +++ /dev/null @@ -1,8 +0,0 @@ -# This migration comes from spree (originally 20130319183250) -class AddOriginatorToStockMovement < ActiveRecord::Migration - def change - change_table :spree_stock_movements do |t| - t.references :originator, polymorphic: true - end - end -end diff --git a/db/migrate/20180426145648_drop_source_and_destination_from_stock_movement.spree.rb b/db/migrate/20180426145648_drop_source_and_destination_from_stock_movement.spree.rb deleted file mode 100644 index 6735614f4e..0000000000 --- a/db/migrate/20180426145648_drop_source_and_destination_from_stock_movement.spree.rb +++ /dev/null @@ -1,16 +0,0 @@ -# This migration comes from spree (originally 20130319190507) -class DropSourceAndDestinationFromStockMovement < ActiveRecord::Migration - def up - change_table :spree_stock_movements do |t| - t.remove_references :source, :polymorphic => true - t.remove_references :destination, :polymorphic => true - end - end - - def down - change_table :spree_stock_movements do |t| - t.references :source, polymorphic: true - t.references :destination, polymorphic: true - end - end -end diff --git a/db/migrate/20180426145649_migrate_inventory_unit_sold_to_on_hand.spree.rb b/db/migrate/20180426145649_migrate_inventory_unit_sold_to_on_hand.spree.rb deleted file mode 100644 index 4f759427ee..0000000000 --- a/db/migrate/20180426145649_migrate_inventory_unit_sold_to_on_hand.spree.rb +++ /dev/null @@ -1,10 +0,0 @@ -# This migration comes from spree (originally 20130325163316) -class MigrateInventoryUnitSoldToOnHand < ActiveRecord::Migration - def up - Spree::InventoryUnit.where(:state => 'sold').update_all(:state => 'on_hand') - end - - def down - Spree::InventoryUnit.where(:state => 'on_hand').update_all(:state => 'sold') - end -end diff --git a/db/migrate/20180426145650_add_stock_location_to_rma.spree.rb b/db/migrate/20180426145650_add_stock_location_to_rma.spree.rb deleted file mode 100644 index 54d85f76a4..0000000000 --- a/db/migrate/20180426145650_add_stock_location_to_rma.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130326175857) -class AddStockLocationToRma < ActiveRecord::Migration - def change - add_column :spree_return_authorizations, :stock_location_id, :integer - end -end diff --git a/db/migrate/20180426145651_update_shipment_state_for_canceled_orders.spree.rb b/db/migrate/20180426145651_update_shipment_state_for_canceled_orders.spree.rb deleted file mode 100644 index f5c1b5a0cf..0000000000 --- a/db/migrate/20180426145651_update_shipment_state_for_canceled_orders.spree.rb +++ /dev/null @@ -1,16 +0,0 @@ -# This migration comes from spree (originally 20130328130308) -class UpdateShipmentStateForCanceledOrders < ActiveRecord::Migration - def up - shipments = Spree::Shipment.joins(:order). - where("spree_orders.state = 'canceled'") - case Spree::Shipment.connection.adapter_name - when "SQLite3" - shipments.update_all("state = 'cancelled'") - when "MySQL" || "PostgreSQL" - shipments.update_all("spree_shipments.state = 'cancelled'") - end - end - - def down - end -end diff --git a/db/migrate/20180426145652_remove_stock_item_and_variant_lock.spree.rb b/db/migrate/20180426145652_remove_stock_item_and_variant_lock.spree.rb deleted file mode 100644 index c522a765cc..0000000000 --- a/db/migrate/20180426145652_remove_stock_item_and_variant_lock.spree.rb +++ /dev/null @@ -1,15 +0,0 @@ -# This migration comes from spree (originally 20130329134939) -class RemoveStockItemAndVariantLock < ActiveRecord::Migration - def up - # we are moving to pessimistic locking on stock_items - remove_column :spree_stock_items, :lock_version - - # variants no longer manage their count_on_hand so we are removing their lock - remove_column :spree_variants, :lock_version - end - - def down - add_column :spree_stock_items, :lock_version, :integer - add_column :spree_variants, :lock_version, :integer - end -end diff --git a/db/migrate/20180426145653_add_shipping_rates_to_shipments.spree.rb b/db/migrate/20180426145653_add_shipping_rates_to_shipments.spree.rb deleted file mode 100644 index 67c24f568d..0000000000 --- a/db/migrate/20180426145653_add_shipping_rates_to_shipments.spree.rb +++ /dev/null @@ -1,16 +0,0 @@ -# This migration comes from spree (originally 20130417123427) -class AddShippingRatesToShipments < ActiveRecord::Migration - def up - Spree::Shipment.all.each do |shipment| - shipment.shipping_rates.create!(:shipping_method_id => shipment.shipping_method_id, - :cost => shipment.cost, - :selected => true) - end - - remove_column :spree_shipments, :shipping_method_id - end - - def down - add_column :spree_shipments, :shipping_method_id, :integer - end -end diff --git a/db/migrate/20180426145654_create_spree_stock_transfers.spree.rb b/db/migrate/20180426145654_create_spree_stock_transfers.spree.rb deleted file mode 100644 index 1b73d9b176..0000000000 --- a/db/migrate/20180426145654_create_spree_stock_transfers.spree.rb +++ /dev/null @@ -1,15 +0,0 @@ -# This migration comes from spree (originally 20130418125341) -class CreateSpreeStockTransfers < ActiveRecord::Migration - def change - create_table :spree_stock_transfers do |t| - t.string :type - t.string :reference_number - t.integer :source_location_id - t.integer :destination_location_id - t.timestamps - end - - add_index :spree_stock_transfers, :source_location_id - add_index :spree_stock_transfers, :destination_location_id - end -end diff --git a/db/migrate/20180426145655_drop_products_count_on_hand.spree.rb b/db/migrate/20180426145655_drop_products_count_on_hand.spree.rb deleted file mode 100644 index 29cb947a56..0000000000 --- a/db/migrate/20180426145655_drop_products_count_on_hand.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130423110707) -class DropProductsCountOnHand < ActiveRecord::Migration - def up - remove_column :spree_products, :count_on_hand - end -end diff --git a/db/migrate/20180426145656_set_default_shipping_rate_cost.spree.rb b/db/migrate/20180426145656_set_default_shipping_rate_cost.spree.rb deleted file mode 100644 index 64b9ccb108..0000000000 --- a/db/migrate/20180426145656_set_default_shipping_rate_cost.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130423223847) -class SetDefaultShippingRateCost < ActiveRecord::Migration - def change - change_column :spree_shipping_rates, :cost, :decimal, default: 0, precision: 8, scale: 2 - end -end diff --git a/db/migrate/20180426145657_add_number_to_stock_transfer.spree.rb b/db/migrate/20180426145657_add_number_to_stock_transfer.spree.rb deleted file mode 100644 index cf06743da0..0000000000 --- a/db/migrate/20180426145657_add_number_to_stock_transfer.spree.rb +++ /dev/null @@ -1,24 +0,0 @@ -# This migration comes from spree (originally 20130509115210) -class AddNumberToStockTransfer < ActiveRecord::Migration - def up - remove_index :spree_stock_transfers, :source_location_id - remove_index :spree_stock_transfers, :destination_location_id - - rename_column :spree_stock_transfers, :reference_number, :reference - add_column :spree_stock_transfers, :number, :string - - Spree::StockTransfer.all.each do |transfer| - transfer.send(:generate_stock_transfer_number) - transfer.save! - end - - add_index :spree_stock_transfers, :number - add_index :spree_stock_transfers, :source_location_id - add_index :spree_stock_transfers, :destination_location_id - end - - def down - rename_column :spree_stock_transfers, :reference, :reference_number - remove_column :spree_stock_transfers, :number, :string - end -end diff --git a/db/migrate/20180426145658_add_sku_index_to_spree_variants.spree.rb b/db/migrate/20180426145658_add_sku_index_to_spree_variants.spree.rb deleted file mode 100644 index cd089f846d..0000000000 --- a/db/migrate/20180426145658_add_sku_index_to_spree_variants.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130514151929) -class AddSkuIndexToSpreeVariants < ActiveRecord::Migration - def change - add_index :spree_variants, :sku - end -end diff --git a/db/migrate/20180426145659_add_backorderable_default_to_spree_stock_location.spree.rb b/db/migrate/20180426145659_add_backorderable_default_to_spree_stock_location.spree.rb deleted file mode 100644 index 29939c59e6..0000000000 --- a/db/migrate/20180426145659_add_backorderable_default_to_spree_stock_location.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130515180736) -class AddBackorderableDefaultToSpreeStockLocation < ActiveRecord::Migration - def change - add_column :spree_stock_locations, :backorderable_default, :boolean, default: true - end -end diff --git a/db/migrate/20180426145660_add_propage_all_variants_to_spree_stock_location.spree.rb b/db/migrate/20180426145660_add_propage_all_variants_to_spree_stock_location.spree.rb deleted file mode 100644 index bfc55eac56..0000000000 --- a/db/migrate/20180426145660_add_propage_all_variants_to_spree_stock_location.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130516151222) -class AddPropageAllVariantsToSpreeStockLocation < ActiveRecord::Migration - def change - add_column :spree_stock_locations, :propagate_all_variants, :boolean, default: true - end -end diff --git a/db/migrate/20180426145661_rename_shipping_methods_zones_to_spree_shipping_methods_zones.spree.rb b/db/migrate/20180426145661_rename_shipping_methods_zones_to_spree_shipping_methods_zones.spree.rb deleted file mode 100644 index 5c7ee6dd95..0000000000 --- a/db/migrate/20180426145661_rename_shipping_methods_zones_to_spree_shipping_methods_zones.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130611054351) -class RenameShippingMethodsZonesToSpreeShippingMethodsZones < ActiveRecord::Migration - def change - rename_table :shipping_methods_zones, :spree_shipping_methods_zones - end -end diff --git a/db/migrate/20180426145662_add_deleted_at_to_spree_tax_rates.spree.rb b/db/migrate/20180426145662_add_deleted_at_to_spree_tax_rates.spree.rb deleted file mode 100644 index c804d9a1f7..0000000000 --- a/db/migrate/20180426145662_add_deleted_at_to_spree_tax_rates.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130708052307) -class AddDeletedAtToSpreeTaxRates < ActiveRecord::Migration - def change - add_column :spree_tax_rates, :deleted_at, :datetime - end -end diff --git a/db/migrate/20180426145663_remove_lock_version_from_inventory_units.spree.rb b/db/migrate/20180426145663_remove_lock_version_from_inventory_units.spree.rb deleted file mode 100644 index 42c60bd3f3..0000000000 --- a/db/migrate/20180426145663_remove_lock_version_from_inventory_units.spree.rb +++ /dev/null @@ -1,7 +0,0 @@ -# This migration comes from spree (originally 20130711200933) -class RemoveLockVersionFromInventoryUnits < ActiveRecord::Migration - def change - # we are moving to pessimistic locking on stock_items - remove_column :spree_inventory_units, :lock_version - end -end diff --git a/db/migrate/20180426145664_add_cost_price_to_line_item.spree.rb b/db/migrate/20180426145664_add_cost_price_to_line_item.spree.rb deleted file mode 100644 index d54222f559..0000000000 --- a/db/migrate/20180426145664_add_cost_price_to_line_item.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130718042445) -class AddCostPriceToLineItem < ActiveRecord::Migration - def change - add_column :spree_line_items, :cost_price, :decimal, :precision => 8, :scale => 2 - end -end diff --git a/db/migrate/20180426145665_set_backorderable_to_default_to_false.spree.rb b/db/migrate/20180426145665_set_backorderable_to_default_to_false.spree.rb deleted file mode 100644 index a05f4279a4..0000000000 --- a/db/migrate/20180426145665_set_backorderable_to_default_to_false.spree.rb +++ /dev/null @@ -1,7 +0,0 @@ -# This migration comes from spree (originally 20130718233855) -class SetBackorderableToDefaultToFalse < ActiveRecord::Migration - def change - change_column :spree_stock_items, :backorderable, :boolean, :default => false - change_column :spree_stock_locations, :backorderable_default, :boolean, :default => false - end -end diff --git a/db/migrate/20180426145666_add_created_by_id_to_spree_orders.spree.rb b/db/migrate/20180426145666_add_created_by_id_to_spree_orders.spree.rb deleted file mode 100644 index fe59c0fc21..0000000000 --- a/db/migrate/20180426145666_add_created_by_id_to_spree_orders.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130725031716) -class AddCreatedByIdToSpreeOrders < ActiveRecord::Migration - def change - add_column :spree_orders, :created_by_id, :integer - end -end diff --git a/db/migrate/20180426145667_index_completed_at_on_spree_orders.spree.rb b/db/migrate/20180426145667_index_completed_at_on_spree_orders.spree.rb deleted file mode 100644 index c4c279ca4c..0000000000 --- a/db/migrate/20180426145667_index_completed_at_on_spree_orders.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130729214043) -class IndexCompletedAtOnSpreeOrders < ActiveRecord::Migration - def change - add_index :spree_orders, :completed_at - end -end diff --git a/db/migrate/20180426145668_add_tax_category_id_to_spree_line_items.spree.rb b/db/migrate/20180426145668_add_tax_category_id_to_spree_line_items.spree.rb deleted file mode 100644 index 2b7e1a51bc..0000000000 --- a/db/migrate/20180426145668_add_tax_category_id_to_spree_line_items.spree.rb +++ /dev/null @@ -1,6 +0,0 @@ -# This migration comes from spree (originally 20130802014537) -class AddTaxCategoryIdToSpreeLineItems < ActiveRecord::Migration - def change - add_column :spree_line_items, :tax_category_id, :integer - end -end diff --git a/db/migrate/20180426145669_migrate_tax_categories_to_line_items.spree.rb b/db/migrate/20180426145669_migrate_tax_categories_to_line_items.spree.rb deleted file mode 100644 index 4ce74249b3..0000000000 --- a/db/migrate/20180426145669_migrate_tax_categories_to_line_items.spree.rb +++ /dev/null @@ -1,14 +0,0 @@ -# This migration comes from spree (originally 20130802022321) -class MigrateTaxCategoriesToLineItems < ActiveRecord::Migration - def change - Spree::LineItem.includes(:variant => { :product => :tax_category }).find_in_batches do |line_items| - line_items.each do |line_item| - next if line_item.variant.nil? - next if line_item.variant.product.nil? - next if line_item.product.nil? - next unless line_item.product.tax_category.present? - line_item.update_column(:tax_category_id, line_item.product.tax_category.id) - end - end - end -end diff --git a/db/migrate/20180510083800_remove_credit_card_from_subscriptions.rb b/db/migrate/20180510083800_remove_credit_card_from_subscriptions.rb deleted file mode 100644 index 0821fbef61..0000000000 --- a/db/migrate/20180510083800_remove_credit_card_from_subscriptions.rb +++ /dev/null @@ -1,13 +0,0 @@ -class RemoveCreditCardFromSubscriptions < ActiveRecord::Migration - def up - remove_foreign_key :subscriptions, name: :subscriptions_credit_card_id_fk - remove_index :subscriptions, :credit_card_id - remove_column :subscriptions, :credit_card_id - end - - def down - add_column :subscriptions, :credit_card_id, :integer - add_index :subscriptions, :credit_card_id - add_foreign_key :subscriptions, :spree_credit_cards, name: :subscriptions_credit_card_id_fk, column: :credit_card_id - end -end diff --git a/db/migrate/20180812214434_drop_carts.rb b/db/migrate/20180812214434_drop_carts.rb deleted file mode 100644 index f3dfb36ee7..0000000000 --- a/db/migrate/20180812214434_drop_carts.rb +++ /dev/null @@ -1,7 +0,0 @@ -class DropCarts < ActiveRecord::Migration - def change - remove_foreign_key :spree_orders, column: :cart_id - remove_column :spree_orders, :cart_id - drop_table :carts - end -end diff --git a/db/migrate/20180906094641_add_uniqueness_of_variant_id_to_spree_stock_items.rb b/db/migrate/20180906094641_add_uniqueness_of_variant_id_to_spree_stock_items.rb deleted file mode 100644 index 93b2853208..0000000000 --- a/db/migrate/20180906094641_add_uniqueness_of_variant_id_to_spree_stock_items.rb +++ /dev/null @@ -1,8 +0,0 @@ -# Since OFN has only a single default StockLocation, variants in OFN can only -# have a stock item. By adding this unique index we constraint that at DB level -# ensuring data integrity. -class AddUniquenessOfVariantIdToSpreeStockItems < ActiveRecord::Migration - def change - add_index :spree_stock_items, :variant_id, unique: true - end -end diff --git a/db/migrate/20180910155506_add_uniqueness_of_order_id_to_spree_shipments.rb b/db/migrate/20180910155506_add_uniqueness_of_order_id_to_spree_shipments.rb deleted file mode 100644 index 0ee5849afd..0000000000 --- a/db/migrate/20180910155506_add_uniqueness_of_order_id_to_spree_shipments.rb +++ /dev/null @@ -1,92 +0,0 @@ -# This migration is an OFN specific migration that enforces an order to have a single shipment at all times -class AddUniquenessOfOrderIdToSpreeShipments < ActiveRecord::Migration - def change - Spree::InventoryUnit.connection.schema_cache.clear! - Spree::InventoryUnit.reset_column_information - - destroy_all_but_latest_shipments - - remove_index :spree_shipments, :order_id - add_index :spree_shipments, :order_id, unique: true - end - - private - - # Destroy all but the latest shipment in each order - def destroy_all_but_latest_shipments - latest_shipments = Spree::Shipment. - select("order_id, MAX(updated_at) updated_at"). - group(:order_id). - having("count(*) > 1") - - all_duplicated_shipments = Spree::Shipment. - joins("INNER JOIN (#{latest_shipments.to_sql}) latest_shipments ON spree_shipments.order_id = latest_shipments.order_id") - backup_to_csv(all_duplicated_shipments) - - shipments_to_delete = Spree::Shipment. - joins("INNER JOIN (#{latest_shipments.to_sql}) latest_shipments ON spree_shipments.order_id = latest_shipments.order_id AND spree_shipments.updated_at != latest_shipments.updated_at") - remove_association_to_adjustments(shipments_to_delete) - shipments_to_delete.destroy_all - end - - def remove_association_to_adjustments(shipments) - Spree::Adjustment. - joins("INNER JOIN (#{shipments.to_sql}) shipments_to_delete ON shipments_to_delete.id = spree_adjustments.source_id and spree_adjustments.source_type = 'Spree::Shipment'"). - update_all(source_id: nil, source_type: nil, originator_id: nil, originator_type: nil, mandatory: nil) - end - - def backup_to_csv(shipments) - CSV.open(csv_path, "w") do |csv| - csv << csv_header_row - - shipments.each do |shipment| - csv << shipment_csv_row(shipment) - end - end - end - - def csv_header_row - %w( - id - tracking - number - order_number - shipping_method_name - cost - state - shipped_at - created_at - updated_at - address_json - ) - end - - def shipment_csv_row(shipment) - [ - shipment.id, - shipment.tracking, - shipment.number, - shipment.order.number, - shipment.shipping_method.andand.name, - shipment.cost, - shipment.state, - shipment.shipped_at, - shipment.created_at, - shipment.updated_at, - shipment.address.to_json - ] - end - - def csv_path - ensure_reports_path_exists - reports_path.join("duplicated_shipments_backup.csv") - end - - def reports_path - Rails.root.join("reports") - end - - def ensure_reports_path_exists - Dir.mkdir(reports_path) unless File.exist?(reports_path) - end -end diff --git a/db/migrate/20180919102548_remove_shipping_method_name_from_spree_line_items.rb b/db/migrate/20180919102548_remove_shipping_method_name_from_spree_line_items.rb deleted file mode 100644 index eaae250a18..0000000000 --- a/db/migrate/20180919102548_remove_shipping_method_name_from_spree_line_items.rb +++ /dev/null @@ -1,9 +0,0 @@ -class RemoveShippingMethodNameFromSpreeLineItems < ActiveRecord::Migration - def up - remove_column :spree_line_items, :shipping_method_name - end - - def down - add_column :spree_line_items, :shipping_method_name, :string - end -end diff --git a/db/migrate/20181008201815_update_instagram_data.rb b/db/migrate/20181008201815_update_instagram_data.rb deleted file mode 100644 index d1a45dc155..0000000000 --- a/db/migrate/20181008201815_update_instagram_data.rb +++ /dev/null @@ -1,8 +0,0 @@ -class UpdateInstagramData < ActiveRecord::Migration - def change - Enterprise.where("instagram like ?", "%instagram.com%").find_each do |e| - e.instagram = e.instagram.split('/').last - e.save - end - end -end diff --git a/db/migrate/20181010093850_fix_variants_missing_unit_value.rb b/db/migrate/20181010093850_fix_variants_missing_unit_value.rb deleted file mode 100644 index c4226d0dc2..0000000000 --- a/db/migrate/20181010093850_fix_variants_missing_unit_value.rb +++ /dev/null @@ -1,49 +0,0 @@ -# Fixes variants whose product.variant_unit is 'weight' and miss a unit_value, -# showing 1 unit of the specified weight. That is, if the user chose Kg, it'll -# display 1 as unit. -class FixVariantsMissingUnitValue < ActiveRecord::Migration - HUMAN_UNIT_VALUE = 1 - - def up - logger.info "Fixing variants missing unit_value...\n" - - variants_missing_unit_value.find_each do |variant| - logger.info "Processing variant #{variant.id}..." - - fix_unit_value(variant) - end - - logger.info "Done!" - end - - def down - end - - private - - def variants_missing_unit_value - Spree::Variant - .joins(:product) - .readonly(false) - .where( - spree_products: { variant_unit: 'weight' }, - spree_variants: { unit_value: nil } - ) - end - - def fix_unit_value(variant) - variant.unit_value = HUMAN_UNIT_VALUE * variant.product.variant_unit_scale - - if variant.save - logger.info "Successfully fixed variant #{variant.id}" - else - logger.info "Failed fixing variant #{variant.id}" - end - - logger.info "" - end - - def logger - @logger ||= Logger.new('log/migrate.log') - end -end diff --git a/db/migrate/20181020103501_revoke_variant_overrideswithout_permissions.rb b/db/migrate/20181020103501_revoke_variant_overrideswithout_permissions.rb deleted file mode 100644 index d8140c9bf3..0000000000 --- a/db/migrate/20181020103501_revoke_variant_overrideswithout_permissions.rb +++ /dev/null @@ -1,17 +0,0 @@ -class RevokeVariantOverrideswithoutPermissions < ActiveRecord::Migration - def up - # This process was executed when the permission_revoked_at colum was created (see AddPermissionRevokedAtToVariantOverrides) - # It needs to be repeated due to #2739 - variant_override_hubs = Enterprise.where(id: VariantOverride.select(:hub_id).uniq) - - variant_override_hubs.find_each do |hub| - permitting_producer_ids = hub.relationships_as_child - .with_permission(:create_variant_overrides).pluck(:parent_id) - - variant_overrides_with_revoked_permissions = VariantOverride.for_hubs(hub) - .joins(variant: :product).where("spree_products.supplier_id NOT IN (?)", permitting_producer_ids) - - variant_overrides_with_revoked_permissions.update_all(permission_revoked_at: Time.now) - end - end -end diff --git a/db/migrate/20181031105158_allow_all_suppliers_own_variant_overrides.rb b/db/migrate/20181031105158_allow_all_suppliers_own_variant_overrides.rb deleted file mode 100644 index a04bd5dfff..0000000000 --- a/db/migrate/20181031105158_allow_all_suppliers_own_variant_overrides.rb +++ /dev/null @@ -1,12 +0,0 @@ -class AllowAllSuppliersOwnVariantOverrides < ActiveRecord::Migration - def up - # This migration is fixing a detail of previous migration RevokeVariantOverrideswithoutPermissions - # Here we allow all variant_overrides where hub_id is the products supplier_id - # This is needed when the supplier herself uses the inventory to manage stock and not the catalog - owned_variant_overrides = VariantOverride.unscoped - .joins(variant: :product).where("spree_products.supplier_id = variant_overrides.hub_id") - - owned_variant_overrides.update_all(permission_revoked_at: nil) - end -end - diff --git a/db/migrate/20181106162211_update_weight_calculator_type_class_name.rb b/db/migrate/20181106162211_update_weight_calculator_type_class_name.rb deleted file mode 100644 index f8e15b3414..0000000000 --- a/db/migrate/20181106162211_update_weight_calculator_type_class_name.rb +++ /dev/null @@ -1,9 +0,0 @@ -class UpdateWeightCalculatorTypeClassName < ActiveRecord::Migration - def up - Spree::Calculator.connection.execute("UPDATE spree_calculators SET type = 'Calculator::Weight' WHERE type = 'OpenFoodNetwork::Calculator::Weight'") - end - - def down - Spree::Calculator.connection.execute("UPDATE spree_calculators SET type = 'OpenFoodNetwork::Calculator::Weight' WHERE type = 'Calculator::Weight'") - end -end diff --git a/db/migrate/20181123012635_associate_customers_to_users.rb b/db/migrate/20181123012635_associate_customers_to_users.rb deleted file mode 100644 index 95fab93677..0000000000 --- a/db/migrate/20181123012635_associate_customers_to_users.rb +++ /dev/null @@ -1,42 +0,0 @@ -# When we introduced the Customer model, we didn't associate any existing -# customers with users that have the same email address. -# Later we decided to create that association when users sign up. But we didn't -# update all the existing customers. We do that now for data consistency and to -# solve several bugs. -# -# - https://github.com/openfoodfoundation/openfoodnetwork/pull/2084 -# - https://github.com/openfoodfoundation/openfoodnetwork/issues/2841 -class AssociateCustomersToUsers < ActiveRecord::Migration - class Customer < ActiveRecord::Base - end - - def up - save_customers - execute "UPDATE customers - SET user_id = spree_users.id - FROM spree_users - WHERE customers.email = spree_users.email - AND customers.user_id IS NULL;" - end - - def down - customers = backed_up_customers - Customer.where(id: customers).update_all(user_id: nil) - end - - def save_customers - customers = Customer. - joins("INNER JOIN spree_users ON customers.email = spree_users.email"). - where(user_id: nil).all - - File.write(backup_file, YAML.dump(customers)) - end - - def backed_up_customers - YAML.load(File.read(backup_file)) - end - - def backup_file - File.join("log", "customers_without_user_association.log") - end -end diff --git a/db/migrate/20181128054803_old_migrations_removed.rb b/db/migrate/20181128054803_old_migrations_removed.rb new file mode 100644 index 0000000000..47d233f0aa --- /dev/null +++ b/db/migrate/20181128054803_old_migrations_removed.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +class OldMigrationsRemoved < ActiveRecord::Migration + def up + raise StandardError, <<-MESSAGE + + You haven't updated your dev environment in a long time! + Legacy migration files before 2019 have now been removed. + Run `rake db:schema:load` before running `rake db:migrate`. + + MESSAGE + end +end diff --git a/db/migrate/20181128054803_simplify_variant_override_stock_settings.rb b/db/migrate/20181128054803_simplify_variant_override_stock_settings.rb deleted file mode 100644 index 6627dca015..0000000000 --- a/db/migrate/20181128054803_simplify_variant_override_stock_settings.rb +++ /dev/null @@ -1,165 +0,0 @@ -# This simplifies variant overrides to have only the following combinations: -# -# on_demand | count_on_hand -# -----------+--------------- -# true | nil -# false | set -# nil | nil -# -# Refer to the table {here}[https://github.com/openfoodfoundation/openfoodnetwork/issues/3067] for -# the effect of different variant and variant override stock configurations. -# -# Furthermore, this will allow all existing variant overrides to satisfy the newly added model -# validation rules. -class SimplifyVariantOverrideStockSettings < ActiveRecord::Migration - class VariantOverride < ActiveRecord::Base - belongs_to :variant - belongs_to :hub, class_name: "Enterprise" - - scope :with_count_on_hand, -> { where("count_on_hand IS NOT NULL") } - scope :without_count_on_hand, -> { where(count_on_hand: nil) } - end - - class Variant < ActiveRecord::Base - self.table_name = "spree_variants" - - belongs_to :product - - def name - namer = OpenFoodNetwork::OptionValueNamer.new(self) - namer.name - end - end - - class Product < ActiveRecord::Base - self.table_name = "spree_products" - - belongs_to :supplier, class_name: "Enterprise" - end - - class Enterprise < ActiveRecord::Base; end - - def up - ensure_reports_path_exists - - CSV.open(csv_path, "w") do |csv| - csv << csv_header_row - - update_use_producer_stock_settings_with_count_on_hand(csv) - update_on_demand_with_count_on_hand(csv) - update_limited_stock_without_count_on_hand(csv) - end - - split_csv_by_distributor - end - - def down - CSV.foreach(csv_path, headers: true) do |row| - VariantOverride.where(id: row["variant_override_id"]) - .update_all(on_demand: row["previous_on_demand"], - count_on_hand: row["previous_count_on_hand"]) - end - end - - private - - def reports_path - Rails.root.join("reports", "SimplifyVariantOverrideStockSettings") - end - - def ensure_reports_path_exists - Dir.mkdir(reports_path) unless File.exist?(reports_path) - end - - def csv_path - reports_path.join("changed_variant_overrides.csv") - end - - def distributor_csv_path(name, id) - reports_path.join("changed_variant_overrides-#{name.parameterize('_')}-#{id}.csv") - end - - # When on_demand is nil but count_on_hand is set, force limited stock. - def update_use_producer_stock_settings_with_count_on_hand(csv) - variant_overrides = VariantOverride.where(on_demand: nil).with_count_on_hand - update_variant_overrides_and_log(csv, variant_overrides) do |variant_override| - variant_override.update_attributes!(on_demand: false) - end - end - - # Clear count_on_hand if forcing on demand. - def update_on_demand_with_count_on_hand(csv) - variant_overrides = VariantOverride.where(on_demand: true).with_count_on_hand - update_variant_overrides_and_log(csv, variant_overrides) do |variant_override| - variant_override.update_attributes!(count_on_hand: nil) - end - end - - # When on_demand is false but count on hand is not specified, set this to use producer stock - # settings. - def update_limited_stock_without_count_on_hand(csv) - variant_overrides = VariantOverride.where(on_demand: false).without_count_on_hand - update_variant_overrides_and_log(csv, variant_overrides) do |variant_override| - variant_override.update_attributes!(on_demand: nil) - end - end - - def update_variant_overrides_and_log(csv, variant_overrides) - variant_overrides.find_each do |variant_override| - csv << variant_override_log_row(variant_override) do - yield variant_override - end - end - end - - def csv_header_row - %w( - variant_override_id - distributor_name distributor_id - producer_name producer_id - product_name product_id - variant_description variant_id - previous_on_demand previous_count_on_hand - updated_on_demand updated_count_on_hand - ) - end - - def variant_override_log_row(variant_override) - variant = variant_override.variant - distributor = variant_override.hub - product = variant.andand.product - supplier = product.andand.supplier - - row = [ - variant_override.id, - distributor.andand.name, distributor.andand.id, - supplier.andand.name, supplier.andand.id, - product.andand.name, product.andand.id, - variant.andand.name, variant.andand.id, - variant_override.on_demand, variant_override.count_on_hand - ] - - yield variant_override - - row + [variant_override.on_demand, variant_override.count_on_hand] - end - - def split_csv_by_distributor - table = CSV.read(csv_path) - distributor_ids = table[1..-1].map { |row| row[2] }.uniq # Don't use the header row. - - distributor_ids.each do |distributor_id| - distributor_data_rows = filter_data_rows_for_distributor(table[1..-1], distributor_id) - distributor_name = distributor_data_rows.first[1] - - CSV.open(distributor_csv_path(distributor_name, distributor_id), "w") do |csv| - csv << table[0] # Header row - distributor_data_rows.each { |row| csv << row } - end - end - end - - def filter_data_rows_for_distributor(data_rows, distributor_id) - data_rows.select { |row| row[2] == distributor_id } - end -end diff --git a/db/migrate/20200404080853_add_user_id_index_to_spree_orders.rb b/db/migrate/20200404080853_add_user_id_index_to_spree_orders.rb new file mode 100644 index 0000000000..cb8ef67b0e --- /dev/null +++ b/db/migrate/20200404080853_add_user_id_index_to_spree_orders.rb @@ -0,0 +1,5 @@ +class AddUserIdIndexToSpreeOrders < ActiveRecord::Migration + def change + add_index :spree_orders, :user_id + end +end diff --git a/db/migrate/20200404081018_add_supplier_id_index_to_spree_products.rb b/db/migrate/20200404081018_add_supplier_id_index_to_spree_products.rb new file mode 100644 index 0000000000..eadc5a7c50 --- /dev/null +++ b/db/migrate/20200404081018_add_supplier_id_index_to_spree_products.rb @@ -0,0 +1,5 @@ +class AddSupplierIdIndexToSpreeProducts < ActiveRecord::Migration + def change + add_index :spree_products, :supplier_id + end +end diff --git a/db/migrate/20200406085833_increase_characters_of_locale_in_spree_users.rb b/db/migrate/20200406085833_increase_characters_of_locale_in_spree_users.rb new file mode 100644 index 0000000000..5cac7dab5b --- /dev/null +++ b/db/migrate/20200406085833_increase_characters_of_locale_in_spree_users.rb @@ -0,0 +1,9 @@ +class IncreaseCharactersOfLocaleInSpreeUsers < ActiveRecord::Migration + def up + change_column :spree_users, :locale, :string, limit: 6 + end + + def down + change_column :spree_users, :locale, :string, limit: 5 + end +end diff --git a/db/schema.rb b/db/schema.rb index 36cd344ea1..d786441da1 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(:version => 20200327105910) do +ActiveRecord::Schema.define(:version => 20200406085833) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -578,7 +578,7 @@ ActiveRecord::Schema.define(:version => 20200327105910) do add_index "spree_orders", ["number"], name: "index_orders_on_number", using: :btree add_index "spree_orders", ["distributor_id"], name: "index_spree_orders_on_distributor_id", using: :btree add_index "spree_orders", ["order_cycle_id"], name: "index_spree_orders_on_order_cycle_id", using: :btree - + add_index "spree_orders", ["user_id"], name: "index_spree_orders_on_user_id", using: :btree create_table "spree_payment_methods", force: true do |t| t.string "type" @@ -728,6 +728,7 @@ ActiveRecord::Schema.define(:version => 20200327105910) do add_index "spree_products", ["permalink"], name: "index_products_on_permalink", using: :btree add_index "spree_products", ["permalink"], name: "permalink_idx_unique", unique: true, using: :btree add_index "spree_products", ["primary_taxon_id"], name: "index_spree_products_on_primary_taxon_id", using: :btree + add_index "spree_products", ["supplier_id"], name: "index_spree_products_on_supplier_id" create_table "spree_products_promotion_rules", id: false, force: true do |t| t.integer "product_id" @@ -1050,7 +1051,7 @@ ActiveRecord::Schema.define(:version => 20200327105910) do t.datetime "reset_password_sent_at" t.string "api_key", limit: 40 t.integer "enterprise_limit", default: 5, null: false - t.string "locale", limit: 5 + t.string "locale", limit: 6 t.string "confirmation_token" t.datetime "confirmed_at" t.datetime "confirmation_sent_at" diff --git a/docker-compose.yml b/docker-compose.yml index 5025cfd929..f4407eb6a4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -28,10 +28,7 @@ services: ADMIN_PASSWORD: ofn123 OFN_DB_HOST: db command: > - bash -c "(bundle check || bundle install) && - wait-for-it -t 30 db:5432 && - bundle exec rake db:reset && - bundle exec rake db:test:prepare ofn:sample_data || true && + bash -c "wait-for-it -t 30 db:5432 && rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'" diff --git a/engines/catalog/config/routes.rb b/engines/catalog/config/routes.rb index a56f4a0b70..166898de46 100644 --- a/engines/catalog/config/routes.rb +++ b/engines/catalog/config/routes.rb @@ -1,2 +1,2 @@ -Catalog::Engine.routes.draw do +Openfoodnetwork::Application.routes.prepend do end diff --git a/engines/order_management/app/controllers/order_management/reports/enterprise_fee_summaries_controller.rb b/engines/order_management/app/controllers/order_management/reports/enterprise_fee_summaries_controller.rb new file mode 100644 index 0000000000..08b6c602c5 --- /dev/null +++ b/engines/order_management/app/controllers/order_management/reports/enterprise_fee_summaries_controller.rb @@ -0,0 +1,64 @@ +module OrderManagement + module Reports + class EnterpriseFeeSummariesController < Spree::Admin::BaseController + before_filter :load_report_parameters + before_filter :load_permissions + + def new; end + + def create + return respond_to_invalid_parameters unless @report_parameters.valid? + + @report_parameters.authorize!(@permissions) + + @report = report_klass::ReportService.new(@permissions, @report_parameters) + renderer.render(self) + rescue ::Reports::Authorizer::ParameterNotAllowedError => e + flash[:error] = e.message + render_report_form + end + + private + + def respond_to_invalid_parameters + flash[:error] = I18n.t("invalid_filter_parameters", scope: i18n_scope) + render_report_form + end + + def i18n_scope + "order_management.reports.enterprise_fee_summary" + end + + def render_report_form + render action: :new + end + + def report_klass + OrderManagement::Reports::EnterpriseFeeSummary + end + + def load_report_parameters + @report_parameters = report_klass::Parameters.new(params[:report] || {}) + end + + def load_permissions + @permissions = report_klass::Permissions.new(spree_current_user) + end + + def report_renderer_klass + case params[:report_format] + when "csv" + report_klass::Renderers::CsvRenderer + when nil, "", "html" + report_klass::Renderers::HtmlRenderer + else + raise Reports::UnsupportedReportFormatException + end + end + + def renderer + @renderer ||= report_renderer_klass.new(@report) + end + end + end +end diff --git a/engines/order_management/app/services/order_management/subscriptions/count.rb b/engines/order_management/app/services/order_management/subscriptions/count.rb new file mode 100644 index 0000000000..80f066d209 --- /dev/null +++ b/engines/order_management/app/services/order_management/subscriptions/count.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module OrderManagement + module Subscriptions + class Count + def initialize(order_cycles) + @order_cycles = order_cycles + end + + def for(order_cycle_id) + active[order_cycle_id] || 0 + end + + private + + attr_accessor :order_cycles + + def active + return @active unless @active.nil? + return @active = [] if order_cycles.blank? + + @active ||= ProxyOrder. + not_canceled. + group(:order_cycle_id). + where(order_cycle_id: order_cycles). + count + end + end + end +end diff --git a/engines/order_management/app/services/order_management/subscriptions/estimator.rb b/engines/order_management/app/services/order_management/subscriptions/estimator.rb new file mode 100644 index 0000000000..e358e031bf --- /dev/null +++ b/engines/order_management/app/services/order_management/subscriptions/estimator.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +require 'open_food_network/scope_variant_to_hub' + +# Responsible for estimating prices and fees for subscriptions +# Used by Form as part of the create/update process +# The values calculated here are intended to be persisted in the db + +module OrderManagement + module Subscriptions + class Estimator + def initialize(subscription) + @subscription = subscription + end + + def estimate! + assign_price_estimates + assign_fee_estimates + end + + private + + attr_accessor :subscription + + delegate :subscription_line_items, :shipping_method, :payment_method, :shop, to: :subscription + + def assign_price_estimates + subscription_line_items.each do |item| + item.price_estimate = + price_estimate_for(item.variant, item.price_estimate_was) + end + end + + def price_estimate_for(variant, fallback) + return fallback unless fee_calculator && variant + + scoper.scope(variant) + fees = fee_calculator.indexed_fees_for(variant) + (variant.price + fees).to_d + end + + def fee_calculator + return @fee_calculator unless @fee_calculator.nil? + + next_oc = subscription.schedule.andand.current_or_next_order_cycle + return nil unless shop && next_oc + + @fee_calculator = OpenFoodNetwork::EnterpriseFeeCalculator.new(shop, next_oc) + end + + def scoper + OpenFoodNetwork::ScopeVariantToHub.new(shop) + end + + def assign_fee_estimates + subscription.shipping_fee_estimate = shipping_fee_estimate + subscription.payment_fee_estimate = payment_fee_estimate + end + + def shipping_fee_estimate + shipping_method.calculator.compute(subscription) + end + + def payment_fee_estimate + payment_method.calculator.compute(subscription) + end + end + end +end diff --git a/engines/order_management/app/services/order_management/subscriptions/form.rb b/engines/order_management/app/services/order_management/subscriptions/form.rb new file mode 100644 index 0000000000..2e354835be --- /dev/null +++ b/engines/order_management/app/services/order_management/subscriptions/form.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +require 'order_management/subscriptions/proxy_order_syncer' + +module OrderManagement + module Subscriptions + class Form + attr_accessor :subscription, :subscription_params, :order_update_issues, + :validator, :order_syncer, :estimator + + delegate :json_errors, :valid?, to: :validator + delegate :order_update_issues, to: :order_syncer + + def initialize(subscription, subscription_params = {}) + @subscription = subscription + @subscription_params = subscription_params + @estimator = OrderManagement::Subscriptions::Estimator.new(subscription) + @validator = OrderManagement::Subscriptions::Validator.new(subscription) + @order_syncer = OrderSyncer.new(subscription) + end + + def save + subscription.assign_attributes(subscription_params) + return false unless valid? + + subscription.transaction do + estimator.estimate! + proxy_order_syncer.sync! + order_syncer.sync! + subscription.save! + end + end + + private + + def proxy_order_syncer + OrderManagement::Subscriptions::ProxyOrderSyncer.new(subscription) + end + end + end +end diff --git a/engines/order_management/app/services/order_management/subscriptions/payment_setup.rb b/engines/order_management/app/services/order_management/subscriptions/payment_setup.rb new file mode 100644 index 0000000000..6d90236466 --- /dev/null +++ b/engines/order_management/app/services/order_management/subscriptions/payment_setup.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +module OrderManagement + module Subscriptions + class PaymentSetup + def initialize(order) + @order = order + end + + def call! + payment = create_payment + return if @order.errors.any? + + payment.update_attributes(amount: @order.outstanding_balance) + payment + end + + private + + def create_payment + payment = OrderPaymentFinder.new(@order).last_pending_payment + return payment if payment.present? + + @order.payments.create( + payment_method_id: @order.subscription.payment_method_id + ) + end + end + end +end diff --git a/engines/order_management/app/services/order_management/subscriptions/proxy_order_syncer.rb b/engines/order_management/app/services/order_management/subscriptions/proxy_order_syncer.rb new file mode 100644 index 0000000000..4f45e7421f --- /dev/null +++ b/engines/order_management/app/services/order_management/subscriptions/proxy_order_syncer.rb @@ -0,0 +1,99 @@ +# frozen_string_literal: false + +module OrderManagement + module Subscriptions + class ProxyOrderSyncer + attr_reader :subscription + + delegate :order_cycles, :proxy_orders, :begins_at, :ends_at, to: :subscription + + def initialize(subscriptions) + case subscriptions + when Subscription + @subscription = subscriptions + when ActiveRecord::Relation + @subscriptions = subscriptions.not_ended.not_canceled + else + raise "ProxyOrderSyncer must be initialized with " \ + "an instance of Subscription or ActiveRecord::Relation" + end + end + + def sync! + return sync_subscriptions! if @subscriptions + + return initialise_proxy_orders! unless @subscription.id + + sync_subscription! + end + + private + + def sync_subscriptions! + @subscriptions.each do |subscription| + @subscription = subscription + sync_subscription! + end + end + + def initialise_proxy_orders! + uninitialised_order_cycle_ids.each do |order_cycle_id| + Rails.logger.info "Initializing Proxy Order " \ + "of subscription #{@subscription.id} in order cycle #{order_cycle_id}" + proxy_orders << ProxyOrder.new(subscription: subscription, order_cycle_id: order_cycle_id) + end + end + + def sync_subscription! + Rails.logger.info "Syncing Proxy Orders of subscription #{@subscription.id}" + create_proxy_orders! + remove_orphaned_proxy_orders! + end + + def create_proxy_orders! + return unless not_closed_in_range_order_cycles.any? + + query = "INSERT INTO proxy_orders (subscription_id, order_cycle_id, updated_at, created_at)" + query << " VALUES #{insert_values}" + query << " ON CONFLICT DO NOTHING" + + ActiveRecord::Base.connection.exec_query(query) + end + + def uninitialised_order_cycle_ids + not_closed_in_range_order_cycles.pluck(:id) - proxy_orders.map(&:order_cycle_id) + end + + def remove_orphaned_proxy_orders! + orphaned_proxy_orders.where(nil).delete_all + end + + # Remove Proxy Orders that have not been placed yet + # and are in Order Cycles that are out of range + def orphaned_proxy_orders + orphaned = proxy_orders.where(placed_at: nil) + order_cycle_ids = in_range_order_cycles.pluck(:id) + return orphaned unless order_cycle_ids.any? + + orphaned.where('order_cycle_id NOT IN (?)', order_cycle_ids) + end + + def insert_values + now = Time.now.utc.iso8601 + not_closed_in_range_order_cycles + .map{ |oc| "(#{subscription.id},#{oc.id},'#{now}','#{now}')" } + .join(",") + end + + def not_closed_in_range_order_cycles + in_range_order_cycles.merge(OrderCycle.not_closed) + end + + def in_range_order_cycles + order_cycles.where("orders_close_at >= ? AND orders_close_at <= ?", + begins_at, + ends_at || 100.years.from_now) + end + end + end +end diff --git a/engines/order_management/app/services/order_management/subscriptions/stripe_payment_setup.rb b/engines/order_management/app/services/order_management/subscriptions/stripe_payment_setup.rb new file mode 100644 index 0000000000..37e3a097f3 --- /dev/null +++ b/engines/order_management/app/services/order_management/subscriptions/stripe_payment_setup.rb @@ -0,0 +1,52 @@ +# frozen_string_literal: true + +module OrderManagement + module Subscriptions + class StripePaymentSetup + def initialize(order) + @order = order + @payment = OrderPaymentFinder.new(@order).last_pending_payment + end + + def call! + return if @payment.blank? + + ensure_payment_source + @payment + end + + private + + def ensure_payment_source + return unless stripe_payment_method? && !card_set? + + if saved_credit_card.present? && allow_charges? + use_saved_credit_card + else + @order.errors.add(:base, :no_card) + end + end + + def stripe_payment_method? + [Spree::Gateway::StripeConnect, + Spree::Gateway::StripeSCA].include? @payment.payment_method.class + end + + def card_set? + @payment.source.is_a? Spree::CreditCard + end + + def saved_credit_card + @order.user.default_card + end + + def allow_charges? + @order.customer.allow_charges? + end + + def use_saved_credit_card + @payment.update_attributes(source: saved_credit_card) + end + end + end +end diff --git a/engines/order_management/app/services/order_management/subscriptions/stripe_sca_payment_authorize.rb b/engines/order_management/app/services/order_management/subscriptions/stripe_sca_payment_authorize.rb new file mode 100644 index 0000000000..ea4fbe5ce7 --- /dev/null +++ b/engines/order_management/app/services/order_management/subscriptions/stripe_sca_payment_authorize.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module OrderManagement + module Subscriptions + class StripeScaPaymentAuthorize + def initialize(order) + @order = order + @payment = OrderPaymentFinder.new(@order).last_pending_payment + end + + def call! + return unless @payment&.checkout? + + @payment.authorize! + + @order.errors.add(:base, I18n.t('authorization_failure')) unless @payment.pending? + + @payment + end + end + end +end diff --git a/engines/order_management/app/services/order_management/subscriptions/summarizer.rb b/engines/order_management/app/services/order_management/subscriptions/summarizer.rb new file mode 100644 index 0000000000..0642e22044 --- /dev/null +++ b/engines/order_management/app/services/order_management/subscriptions/summarizer.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +# Used by for SubscriptionPlacementJob and SubscriptionConfirmJob to summarize the +# result of automatic processing of subscriptions for the relevant shop owners. +module OrderManagement + module Subscriptions + class Summarizer + def initialize + @summaries = {} + end + + def record_order(order) + summary_for(order).record_order(order) + end + + def record_success(order) + summary_for(order).record_success(order) + end + + def record_issue(type, order, message = nil) + Rails.logger.info "Issue in Subscription Order #{order.id}: #{type}" + summary_for(order).record_issue(type, order, message) + end + + def record_and_log_error(type, order) + return record_issue(type, order) unless order.errors.any? + + error = "Subscription#{type.to_s.camelize}Error" + line1 = "#{error}: Cannot process order #{order.number} due to errors" + line2 = "Errors: #{order.errors.full_messages.join(', ')}" + Rails.logger.info("#{line1}\n#{line2}") + record_issue(type, order, line2) + end + + def send_placement_summary_emails + @summaries.values.each do |summary| + SubscriptionMailer.placement_summary_email(summary).deliver + end + end + + def send_confirmation_summary_emails + @summaries.values.each do |summary| + SubscriptionMailer.confirmation_summary_email(summary).deliver + end + end + + private + + def summary_for(order) + shop_id = order.distributor_id + @summaries[shop_id] ||= Summary.new(shop_id) + end + end + end +end diff --git a/engines/order_management/app/services/order_management/subscriptions/summary.rb b/engines/order_management/app/services/order_management/subscriptions/summary.rb new file mode 100644 index 0000000000..c37272c6d3 --- /dev/null +++ b/engines/order_management/app/services/order_management/subscriptions/summary.rb @@ -0,0 +1,53 @@ +# frozen_string_literal: true + +module OrderManagement + module Subscriptions + class Summary + attr_reader :shop_id, :issues + + def initialize(shop_id) + @shop_id = shop_id + @order_ids = [] + @success_ids = [] + @issues = {} + end + + def record_order(order) + @order_ids << order.id + end + + def record_success(order) + @success_ids << order.id + end + + def record_issue(type, order, message) + issues[type] ||= {} + issues[type][order.id] = message + end + + def order_count + @order_ids.count + end + + def success_count + @success_ids.count + end + + def issue_count + (@order_ids - @success_ids).count + end + + def orders_affected_by(type) + case type + when :other then Spree::Order.where(id: unrecorded_ids) + else Spree::Order.where(id: issues[type].keys) + end + end + + def unrecorded_ids + recorded_ids = issues.values.map(&:keys).flatten + @order_ids - @success_ids - recorded_ids + end + end + end +end diff --git a/engines/order_management/app/services/order_management/subscriptions/validator.rb b/engines/order_management/app/services/order_management/subscriptions/validator.rb new file mode 100644 index 0000000000..a8bc6b3086 --- /dev/null +++ b/engines/order_management/app/services/order_management/subscriptions/validator.rb @@ -0,0 +1,132 @@ +# frozen_string_literal: true + +# Encapsulation of all of the validation logic required for subscriptions +# Public interface consists of #valid? method provided by ActiveModel::Validations +# and #json_errors which compiles a serializable hash of errors +module OrderManagement + module Subscriptions + class Validator + include ActiveModel::Naming + include ActiveModel::Conversion + include ActiveModel::Validations + + attr_reader :subscription + + validates :shop, :customer, :schedule, :shipping_method, :payment_method, presence: true + validates :bill_address, :ship_address, :begins_at, presence: true + validate :shipping_method_allowed? + validate :payment_method_allowed? + validate :payment_method_type_allowed? + validate :ends_at_after_begins_at? + validate :customer_allowed? + validate :schedule_allowed? + validate :credit_card_ok? + validate :subscription_line_items_present? + validate :requested_variants_available? + + delegate :shop, :customer, :schedule, :shipping_method, :payment_method, to: :subscription + delegate :bill_address, :ship_address, :begins_at, :ends_at, to: :subscription + delegate :subscription_line_items, to: :subscription + + def initialize(subscription) + @subscription = subscription + end + + def json_errors + errors.messages.each_with_object({}) do |(key, value), errors| + errors[key] = value.map { |msg| build_msg_from(key, msg) } + end + end + + private + + def shipping_method_allowed? + return unless shipping_method + return if shipping_method.distributors.include?(shop) + + errors.add(:shipping_method, :not_available_to_shop, shop: shop.name) + end + + def payment_method_allowed? + return unless payment_method + return if payment_method.distributors.include?(shop) + + errors.add(:payment_method, :not_available_to_shop, shop: shop.name) + end + + def payment_method_type_allowed? + return unless payment_method + return if Subscription::ALLOWED_PAYMENT_METHOD_TYPES.include? payment_method.type + + errors.add(:payment_method, :invalid_type) + end + + def ends_at_after_begins_at? + # Only validates ends_at if it is present + return if begins_at.blank? || ends_at.blank? + return if ends_at > begins_at + + errors.add(:ends_at, :after_begins_at) + end + + def customer_allowed? + return unless customer + return if customer.enterprise == shop + + errors.add(:customer, :does_not_belong_to_shop, shop: shop.name) + end + + def schedule_allowed? + return unless schedule + return if schedule.coordinators.include?(shop) + + errors.add(:schedule, :not_coordinated_by_shop, shop: shop.name) + end + + def credit_card_ok? + return unless customer && payment_method + return unless stripe_payment_method?(payment_method) + return errors.add(:payment_method, :charges_not_allowed) unless customer.allow_charges + return if customer.user.andand.default_card.present? + + errors.add(:payment_method, :no_default_card) + end + + def stripe_payment_method?(payment_method) + payment_method.type == "Spree::Gateway::StripeConnect" || + payment_method.type == "Spree::Gateway::StripeSCA" + end + + def subscription_line_items_present? + return if subscription_line_items.reject(&:marked_for_destruction?).any? + + errors.add(:subscription_line_items, :at_least_one_product) + end + + def requested_variants_available? + subscription_line_items.each { |sli| verify_availability_of(sli.variant) } + end + + def verify_availability_of(variant) + return if available_variant_ids.include? variant.id + + name = "#{variant.product.name} - #{variant.full_name}" + errors.add(:subscription_line_items, :not_available, name: name) + end + + def available_variant_ids + return @available_variant_ids if @available_variant_ids.present? + + subscription_variant_ids = subscription_line_items.map(&:variant_id) + @available_variant_ids = OrderManagement::Subscriptions::VariantsList.eligible_variants(shop) + .where(id: subscription_variant_ids).pluck(:id) + end + + def build_msg_from(key, msg) + return msg[1..-1] if msg.starts_with?("^") + + errors.full_message(key, msg) + end + end + end +end diff --git a/engines/order_management/app/services/order_management/subscriptions/variants_list.rb b/engines/order_management/app/services/order_management/subscriptions/variants_list.rb new file mode 100644 index 0000000000..5c5a3fddb3 --- /dev/null +++ b/engines/order_management/app/services/order_management/subscriptions/variants_list.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: false + +module OrderManagement + module Subscriptions + class VariantsList + # Includes the following variants: + # - Variants of permitted producers + # - Variants of hub + # - Variants that are in outgoing exchanges where the hub is receiver + def self.eligible_variants(distributor) + variant_conditions = ["spree_products.supplier_id IN (?)", + permitted_producer_ids(distributor)] + exchange_variant_ids = outgoing_exchange_variant_ids(distributor) + if exchange_variant_ids.present? + variant_conditions[0] << " OR spree_variants.id IN (?)" + variant_conditions << exchange_variant_ids + end + + Spree::Variant.joins(:product).where(is_master: false).where(*variant_conditions) + end + + def self.in_open_and_upcoming_order_cycles?(distributor, schedule, variant) + scope = ExchangeVariant.joins(exchange: { order_cycle: :schedules }) + .where(variant_id: variant, exchanges: { incoming: false, receiver_id: distributor }) + .merge(OrderCycle.not_closed) + scope = scope.where(schedules: { id: schedule }) + scope.any? + end + + def self.permitted_producer_ids(distributor) + other_permitted_producer_ids = EnterpriseRelationship.joins(:parent) + .permitting(distributor.id).with_permission(:add_to_order_cycle) + .merge(Enterprise.is_primary_producer) + .pluck(:parent_id) + + other_permitted_producer_ids | [distributor.id] + end + + def self.outgoing_exchange_variant_ids(distributor) + ExchangeVariant.select("DISTINCT exchange_variants.variant_id").joins(:exchange) + .where(exchanges: { incoming: false, receiver_id: distributor.id }) + .pluck(:variant_id) + end + end + end +end diff --git a/app/views/spree/admin/reports/enterprise_fee_summaries/_filters.html.haml b/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/_filters.html.haml similarity index 93% rename from app/views/spree/admin/reports/enterprise_fee_summaries/_filters.html.haml rename to engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/_filters.html.haml index 744097e9a5..0aee85d71e 100644 --- a/app/views/spree/admin/reports/enterprise_fee_summaries/_filters.html.haml +++ b/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/_filters.html.haml @@ -1,4 +1,4 @@ -= form_for @report_parameters, as: :report, url: spree.admin_reports_enterprise_fee_summary_path, method: :post do |f| += form_for @report_parameters, as: :report, url: main_app.order_management_reports_enterprise_fee_summary_path, method: :post do |f| .row.date-range-filter .sixteen.columns.alpha = label_tag nil, t(".date_range") diff --git a/app/views/spree/admin/reports/enterprise_fee_summaries/_report.html.haml b/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/_report.html.haml similarity index 87% rename from app/views/spree/admin/reports/enterprise_fee_summaries/_report.html.haml rename to engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/_report.html.haml index 4427c511ba..332253b143 100644 --- a/app/views/spree/admin/reports/enterprise_fee_summaries/_report.html.haml +++ b/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/_report.html.haml @@ -13,7 +13,7 @@ - if @renderer.data_rows.empty? %tr - %td{colspan: @renderer.header.length}= t(:none) + %td{colspan: @renderer.header.length}= t('.none') - else %p.report__message = t(".select_and_search") diff --git a/app/views/spree/admin/reports/enterprise_fee_summaries/create.html.haml b/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/create.html.haml similarity index 100% rename from app/views/spree/admin/reports/enterprise_fee_summaries/create.html.haml rename to engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/create.html.haml diff --git a/app/views/spree/admin/reports/enterprise_fee_summaries/new.html.haml b/engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/new.html.haml similarity index 100% rename from app/views/spree/admin/reports/enterprise_fee_summaries/new.html.haml rename to engines/order_management/app/views/order_management/reports/enterprise_fee_summaries/new.html.haml diff --git a/engines/order_management/config/routes.rb b/engines/order_management/config/routes.rb index e221867e7e..79706c635a 100644 --- a/engines/order_management/config/routes.rb +++ b/engines/order_management/config/routes.rb @@ -1,5 +1,5 @@ -Spree::Core::Engine.routes.prepend do - namespace :admin do +Openfoodnetwork::Application.routes.prepend do + namespace :order_management do namespace :reports do resource :enterprise_fee_summary, only: [:new, :create] end diff --git a/spec/controllers/spree/admin/reports/enterprise_fee_summaries_controller_spec.rb b/engines/order_management/spec/controllers/order_management/reports/enterprise_fee_summaries_controller_spec.rb similarity index 94% rename from spec/controllers/spree/admin/reports/enterprise_fee_summaries_controller_spec.rb rename to engines/order_management/spec/controllers/order_management/reports/enterprise_fee_summaries_controller_spec.rb index d9d8962f9b..3282bd7258 100644 --- a/spec/controllers/spree/admin/reports/enterprise_fee_summaries_controller_spec.rb +++ b/engines/order_management/spec/controllers/order_management/reports/enterprise_fee_summaries_controller_spec.rb @@ -1,6 +1,6 @@ require "spec_helper" -describe Spree::Admin::Reports::EnterpriseFeeSummariesController, type: :controller do +describe OrderManagement::Reports::EnterpriseFeeSummariesController, type: :controller do let(:report_klass) { OrderManagement::Reports::EnterpriseFeeSummary } let!(:distributor) { create(:distributor_enterprise) } @@ -76,6 +76,6 @@ describe Spree::Admin::Reports::EnterpriseFeeSummariesController, type: :control end def new_template_path - "spree/admin/reports/enterprise_fee_summaries/new" + "order_management/reports/enterprise_fee_summaries/new" end end diff --git a/spec/features/admin/reports/enterprise_fee_summaries_spec.rb b/engines/order_management/spec/features/order_management/reports/enterprise_fee_summaries_spec.rb similarity index 93% rename from spec/features/admin/reports/enterprise_fee_summaries_spec.rb rename to engines/order_management/spec/features/order_management/reports/enterprise_fee_summaries_spec.rb index 57a8de346e..7930ea75a3 100644 --- a/spec/features/admin/reports/enterprise_fee_summaries_spec.rb +++ b/engines/order_management/spec/features/order_management/reports/enterprise_fee_summaries_spec.rb @@ -41,7 +41,7 @@ feature "enterprise fee summaries", js: true do it "does not allow access to the report" do visit spree.admin_reports_path expect(page).to have_no_link(I18n.t("admin.reports.enterprise_fee_summary.name")) - visit spree.new_admin_reports_enterprise_fee_summary_path + visit main_app.new_order_management_reports_enterprise_fee_summary_path expect(page).to have_content(I18n.t("unauthorized")) end end @@ -49,7 +49,7 @@ feature "enterprise fee summaries", js: true do describe "smoke test for filters" do before do - visit spree.new_admin_reports_enterprise_fee_summary_path + visit main_app.new_order_management_reports_enterprise_fee_summary_path end context "when logged in as admin" do @@ -80,7 +80,7 @@ feature "enterprise fee summaries", js: true do describe "smoke test for generation of report based on permissions" do before do - visit spree.new_admin_reports_enterprise_fee_summary_path + visit main_app.new_order_management_reports_enterprise_fee_summary_path end context "when logged in as admin" do @@ -138,7 +138,7 @@ feature "enterprise fee summaries", js: true do let(:current_user) { create(:admin_user) } before do - visit spree.new_admin_reports_enterprise_fee_summary_path + visit main_app.new_order_management_reports_enterprise_fee_summary_path end it "generates file with data for selected order cycle" do @@ -155,6 +155,6 @@ feature "enterprise fee summaries", js: true do end def i18n_scope - "spree.admin.reports.enterprise_fee_summaries" + "order_management.reports.enterprise_fee_summaries" end end diff --git a/engines/order_management/spec/performance/order_management/subscriptions/proxy_order_syncer_spec.rb b/engines/order_management/spec/performance/order_management/subscriptions/proxy_order_syncer_spec.rb new file mode 100644 index 0000000000..b62267b714 --- /dev/null +++ b/engines/order_management/spec/performance/order_management/subscriptions/proxy_order_syncer_spec.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +module OrderManagement + module Subscriptions + describe ProxyOrderSyncer, performance: true do + let(:start) { Time.zone.now.beginning_of_day } + let!(:schedule) { create(:schedule, order_cycles: order_cycles) } + + let!(:order_cycles) do + Array.new(10) do |i| + create(:simple_order_cycle, orders_open_at: start + i.days, + orders_close_at: start + (i + 1).days ) + end + end + + let!(:subscriptions) do + Array.new(150) do |_i| + create(:subscription, schedule: schedule, begins_at: start, ends_at: start + 10.days) + end + Subscription.where(schedule_id: schedule) + end + + context "measuring performance for initialisation" do + it "reports the average run time for adding 10 OCs to 150 subscriptions" do + expect(ProxyOrder.count).to be 0 + times = [] + 10.times do + syncer = ProxyOrderSyncer.new(subscriptions.reload) + + t1 = Time.zone.now + syncer.sync! + t2 = Time.zone.now + diff = t2 - t1 + times << diff + puts diff.round(2) + + expect(ProxyOrder.count).to be 1500 + ProxyOrder.destroy_all + end + puts "AVG: #{(times.sum / times.count).round(2)}" + end + end + + context "measuring performance for removal" do + it "reports the average run time for removing 8 OCs from 150 subscriptions" do + times = [] + 10.times do + syncer = ProxyOrderSyncer.new(subscriptions.reload) + syncer.sync! + expect(ProxyOrder.count).to be 1500 + subscriptions.update_all(begins_at: start + 8.days + 1.minute) + syncer = ProxyOrderSyncer.new(subscriptions.reload) + + t1 = Time.zone.now + syncer.sync! + t2 = Time.zone.now + diff = t2 - t1 + times << diff + puts diff.round(2) + + expect(ProxyOrder.count).to be 300 + subscriptions.update_all(begins_at: start) + end + puts "AVG: #{(times.sum / times.count).round(2)}" + end + end + end + end +end diff --git a/engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/renderers/html_renderer_spec.rb b/engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/renderers/html_renderer_spec.rb index 5b9c62b03c..1bd591e021 100644 --- a/engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/renderers/html_renderer_spec.rb +++ b/engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/renderers/html_renderer_spec.rb @@ -5,7 +5,7 @@ describe OrderManagement::Reports::EnterpriseFeeSummary::Renderers::HtmlRenderer let!(:permissions) { report_klass::Permissions.new(current_user) } let!(:parameters) { report_klass::Parameters.new } - let!(:controller) { Spree::Admin::Reports::EnterpriseFeeSummariesController.new } + let!(:controller) { OrderManagement::Reports::EnterpriseFeeSummariesController.new } let!(:service) { report_klass::ReportService.new(permissions, parameters) } let!(:renderer) { described_class.new(service) } diff --git a/engines/order_management/spec/services/order_management/subscriptions/count_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/count_spec.rb new file mode 100644 index 0000000000..14b5a8c041 --- /dev/null +++ b/engines/order_management/spec/services/order_management/subscriptions/count_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +module OrderManagement + module Subscriptions + describe Count do + let(:oc1) { create(:simple_order_cycle) } + let(:oc2) { create(:simple_order_cycle) } + let(:subscriptions_count) { Count.new(order_cycles) } + + describe "#for" do + context "when the collection has not been set" do + let(:order_cycles) { nil } + it "returns 0" do + expect(subscriptions_count.for(oc1.id)).to eq 0 + end + end + + context "when the collection has been set" do + let(:order_cycles) { OrderCycle.where(id: [oc1]) } + let!(:po1) { create(:proxy_order, order_cycle: oc1) } + let!(:po2) { create(:proxy_order, order_cycle: oc1) } + let!(:po3) { create(:proxy_order, order_cycle: oc2) } + + context "but the requested id is not present in the list of order cycles provided" do + it "returns 0" do + # Note that po3 applies to oc2, but oc2 in not in the collection + expect(subscriptions_count.for(oc2.id)).to eq 0 + end + end + + context "and the requested id is present in the list of order cycles provided" do + it "returns a count of active proxy orders associated with the requested order cycle" do + expect(subscriptions_count.for(oc1.id)).to eq 2 + end + end + end + end + end + end +end diff --git a/engines/order_management/spec/services/order_management/subscriptions/estimator_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/estimator_spec.rb new file mode 100644 index 0000000000..e8fe7bf957 --- /dev/null +++ b/engines/order_management/spec/services/order_management/subscriptions/estimator_spec.rb @@ -0,0 +1,171 @@ +# frozen_string_literal: true + +module OrderManagement + module Subscriptions + describe Estimator do + describe "estimating prices for subscription line items" do + let!(:subscription) { create(:subscription, with_items: true) } + let!(:sli1) { subscription.subscription_line_items.first } + let!(:sli2) { subscription.subscription_line_items.second } + let!(:sli3) { subscription.subscription_line_items.third } + let(:estimator) { Estimator.new(subscription) } + + before do + sli1.update_attributes(price_estimate: 4.0) + sli2.update_attributes(price_estimate: 5.0) + sli3.update_attributes(price_estimate: 6.0) + sli1.variant.update_attributes(price: 1.0) + sli2.variant.update_attributes(price: 2.0) + sli3.variant.update_attributes(price: 3.0) + + # Simulating assignment of attrs from params + sli1.assign_attributes(price_estimate: 7.0) + sli2.assign_attributes(price_estimate: 8.0) + sli3.assign_attributes(price_estimate: 9.0) + end + + context "when a insufficient information exists to calculate price estimates" do + before do + # This might be because a shop has not been assigned yet, or no + # current or future order cycles exist for the schedule + allow(estimator).to receive(:fee_calculator) { nil } + end + + it "resets the price estimates for all items" do + estimator.estimate! + expect(sli1.price_estimate).to eq 4.0 + expect(sli2.price_estimate).to eq 5.0 + expect(sli3.price_estimate).to eq 6.0 + end + end + + context "when sufficient information to calculate price estimates exists" do + let(:fee_calculator) { instance_double(OpenFoodNetwork::EnterpriseFeeCalculator) } + + before do + allow(estimator).to receive(:fee_calculator) { fee_calculator } + allow(fee_calculator).to receive(:indexed_fees_for).with(sli1.variant) { 1.0 } + allow(fee_calculator).to receive(:indexed_fees_for).with(sli2.variant) { 0.0 } + allow(fee_calculator).to receive(:indexed_fees_for).with(sli3.variant) { 3.0 } + end + + context "when no variant overrides apply" do + it "recalculates price_estimates based on variant prices and associated fees" do + estimator.estimate! + expect(sli1.price_estimate).to eq 2.0 + expect(sli2.price_estimate).to eq 2.0 + expect(sli3.price_estimate).to eq 6.0 + end + end + + context "when variant overrides apply" do + let!(:override1) { + create(:variant_override, hub: subscription.shop, variant: sli1.variant, price: 1.2) + } + let!(:override2) { + create(:variant_override, hub: subscription.shop, variant: sli2.variant, price: 2.3) + } + + it "recalculates price_estimates based on override prices and associated fees" do + estimator.estimate! + expect(sli1.price_estimate).to eq 2.2 + expect(sli2.price_estimate).to eq 2.3 + expect(sli3.price_estimate).to eq 6.0 + end + end + end + end + + describe "updating estimates for shipping and payment fees" do + let(:subscription) { + create(:subscription, with_items: true, + payment_method: payment_method, + shipping_method: shipping_method) + } + let!(:sli1) { subscription.subscription_line_items.first } + let!(:sli2) { subscription.subscription_line_items.second } + let!(:sli3) { subscription.subscription_line_items.third } + let(:estimator) { OrderManagement::Subscriptions::Estimator.new(subscription) } + + before do + allow(estimator).to receive(:assign_price_estimates) + sli1.update_attributes(price_estimate: 4.0) + sli2.update_attributes(price_estimate: 5.0) + sli3.update_attributes(price_estimate: 6.0) + end + + context "using flat rate calculators" do + let(:shipping_method) { + create(:shipping_method, + calculator: Spree::Calculator::FlatRate.new(preferred_amount: 12.34)) + } + let(:payment_method) { + create(:payment_method, + calculator: Spree::Calculator::FlatRate.new(preferred_amount: 9.12)) + } + + it "calculates fees based on the rates provided" do + estimator.estimate! + expect(subscription.shipping_fee_estimate.to_f).to eq 12.34 + expect(subscription.payment_fee_estimate.to_f).to eq 9.12 + end + end + + context "using flat percent item total calculators" do + let(:shipping_method) { + create(:shipping_method, + calculator: Spree::Calculator::FlatPercentItemTotal.new( + preferred_flat_percent: 10 + )) + } + let(:payment_method) { + create(:payment_method, + calculator: Spree::Calculator::FlatPercentItemTotal.new( + preferred_flat_percent: 20 + )) + } + + it "calculates fees based on the estimated item total and percentage provided" do + estimator.estimate! + expect(subscription.shipping_fee_estimate.to_f).to eq 1.5 + expect(subscription.payment_fee_estimate.to_f).to eq 3.0 + end + end + + context "using flat percent per item calculators" do + let(:shipping_method) { + create(:shipping_method, + calculator: Calculator::FlatPercentPerItem.new(preferred_flat_percent: 5)) + } + let(:payment_method) { + create(:payment_method, + calculator: Calculator::FlatPercentPerItem.new(preferred_flat_percent: 10)) + } + + it "calculates fees based on the estimated item prices and percentage provided" do + estimator.estimate! + expect(subscription.shipping_fee_estimate.to_f).to eq 0.75 + expect(subscription.payment_fee_estimate.to_f).to eq 1.5 + end + end + + context "using per item calculators" do + let(:shipping_method) { + create(:shipping_method, + calculator: Spree::Calculator::PerItem.new(preferred_amount: 1.2)) + } + let(:payment_method) { + create(:payment_method, + calculator: Spree::Calculator::PerItem.new(preferred_amount: 0.3)) + } + + it "calculates fees based on the number of items and rate provided" do + estimator.estimate! + expect(subscription.shipping_fee_estimate.to_f).to eq 3.6 + expect(subscription.payment_fee_estimate.to_f).to eq 0.9 + end + end + end + end + end +end diff --git a/engines/order_management/spec/services/order_management/subscriptions/form_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/form_spec.rb new file mode 100644 index 0000000000..a86dbac0e9 --- /dev/null +++ b/engines/order_management/spec/services/order_management/subscriptions/form_spec.rb @@ -0,0 +1,148 @@ +# frozen_string_literal: true + +require 'spec_helper' + +module OrderManagement + module Subscriptions + describe Form do + describe "creating a new subscription" do + let!(:shop) { create(:distributor_enterprise) } + let!(:customer) { create(:customer, enterprise: shop) } + let!(:product1) { create(:product, supplier: shop) } + let!(:product2) { create(:product, supplier: shop) } + let!(:product3) { create(:product, supplier: shop) } + let!(:variant1) { + create(:variant, product: product1, unit_value: '100', price: 12.00, option_values: []) + } + let!(:variant2) { + create(:variant, product: product2, unit_value: '1000', price: 6.00, option_values: []) + } + let!(:variant3) { + create(:variant, product: product2, unit_value: '1000', + price: 2.50, option_values: [], on_hand: 1) + } + let!(:enterprise_fee) { create(:enterprise_fee, amount: 1.75) } + let!(:order_cycle1) { + create(:simple_order_cycle, coordinator: shop, + orders_open_at: 9.days.ago, + orders_close_at: 2.days.ago) + } + let!(:order_cycle2) { + create(:simple_order_cycle, coordinator: shop, + orders_open_at: 2.days.ago, + orders_close_at: 5.days.from_now) + } + let!(:order_cycle3) { + create(:simple_order_cycle, coordinator: shop, + orders_open_at: 5.days.from_now, + orders_close_at: 12.days.from_now) + } + let!(:order_cycle4) { + create(:simple_order_cycle, coordinator: shop, + orders_open_at: 12.days.from_now, + orders_close_at: 19.days.from_now) + } + let!(:outgoing_exchange1) { + order_cycle1.exchanges.create(sender: shop, + receiver: shop, + variants: [variant1, variant2, variant3], + enterprise_fees: [enterprise_fee]) + } + let!(:outgoing_exchange2) { + order_cycle2.exchanges.create(sender: shop, + receiver: shop, + variants: [variant1, variant2, variant3], + enterprise_fees: [enterprise_fee]) + } + let!(:outgoing_exchange3) { + order_cycle3.exchanges.create(sender: shop, + receiver: shop, + variants: [variant1, variant3], + enterprise_fees: []) + } + let!(:outgoing_exchange4) { + order_cycle4.exchanges.create(sender: shop, + receiver: shop, + variants: [variant1, variant2, variant3], + enterprise_fees: [enterprise_fee]) + } + let!(:schedule) { + create(:schedule, order_cycles: [order_cycle1, order_cycle2, order_cycle3, order_cycle4]) + } + let!(:payment_method) { create(:payment_method, distributors: [shop]) } + let!(:shipping_method) { create(:shipping_method, distributors: [shop]) } + let!(:address) { create(:address) } + let(:subscription) { Subscription.new } + + let!(:params) { + { + shop_id: shop.id, + customer_id: customer.id, + schedule_id: schedule.id, + bill_address_attributes: address.clone.attributes, + ship_address_attributes: address.clone.attributes, + payment_method_id: payment_method.id, + shipping_method_id: shipping_method.id, + begins_at: 4.days.ago, + ends_at: 14.days.from_now, + subscription_line_items_attributes: [ + { variant_id: variant1.id, quantity: 1, price_estimate: 7.0 }, + { variant_id: variant2.id, quantity: 2, price_estimate: 8.0 }, + { variant_id: variant3.id, quantity: 3, price_estimate: 9.0 } + ] + } + } + + let(:form) { OrderManagement::Subscriptions::Form.new(subscription, params) } + + it "creates orders for each order cycle in the schedule" do + expect(form.save).to be true + + expect(subscription.proxy_orders.count).to be 2 + expect(subscription.subscription_line_items.count).to be 3 + expect(subscription.subscription_line_items[0].price_estimate).to eq 13.75 + expect(subscription.subscription_line_items[1].price_estimate).to eq 7.75 + expect(subscription.subscription_line_items[2].price_estimate).to eq 4.25 + + # This order cycle has already closed, so no order is initialized + proxy_order1 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle1.id) + expect(proxy_order1).to be nil + + # Currently open order cycle, closing after begins_at and before ends_at + proxy_order2 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle2.id) + expect(proxy_order2).to be_a ProxyOrder + order2 = proxy_order2.initialise_order! + expect(order2.line_items.count).to eq 3 + expect(order2.line_items.find_by(variant_id: variant3.id).quantity).to be 3 + expect(order2.shipments.count).to eq 1 + expect(order2.shipments.first.shipping_method).to eq shipping_method + expect(order2.payments.count).to eq 1 + expect(order2.payments.first.payment_method).to eq payment_method + expect(order2.payments.first.state).to eq 'checkout' + expect(order2.total).to eq 42 + expect(order2.completed?).to be false + + # Future order cycle, closing after begins_at and before ends_at + # Adds line items for variants that aren't yet available from the order cycle + proxy_order3 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle3.id) + expect(proxy_order3).to be_a ProxyOrder + order3 = proxy_order3.initialise_order! + expect(order3).to be_a Spree::Order + expect(order3.line_items.count).to eq 3 + expect(order2.line_items.find_by(variant_id: variant3.id).quantity).to be 3 + expect(order3.shipments.count).to eq 1 + expect(order3.shipments.first.shipping_method).to eq shipping_method + expect(order3.payments.count).to eq 1 + expect(order3.payments.first.payment_method).to eq payment_method + expect(order3.payments.first.state).to eq 'checkout' + expect(order3.total).to eq 31.50 + expect(order3.completed?).to be false + + # Future order cycle closing after ends_at + proxy_order4 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle4.id) + expect(proxy_order4).to be nil + end + end + end + end +end diff --git a/engines/order_management/spec/services/order_management/subscriptions/payment_setup_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/payment_setup_spec.rb new file mode 100644 index 0000000000..32bf3874d0 --- /dev/null +++ b/engines/order_management/spec/services/order_management/subscriptions/payment_setup_spec.rb @@ -0,0 +1,67 @@ +# frozen_string_literal: true + +require 'spec_helper' + +module OrderManagement + module Subscriptions + describe PaymentSetup do + let(:order) { create(:order) } + let(:payment_setup) { OrderManagement::Subscriptions::PaymentSetup.new(order) } + + describe "#call!" do + let!(:payment){ create(:payment, amount: 10) } + + context "when no pending payments are present" do + let(:payment_method) { create(:payment_method) } + let(:subscription) { double(:subscription, payment_method_id: payment_method.id) } + + before do + allow(order).to receive(:pending_payments).once { [] } + allow(order).to receive(:outstanding_balance) { 5 } + allow(order).to receive(:subscription) { subscription } + end + + it "creates a new payment on the order" do + expect{ payment_setup.call! }.to change(Spree::Payment, :count).by(1) + expect(order.payments.first.amount).to eq 5 + end + end + + context "when a payment is present" do + before { allow(order).to receive(:pending_payments).once { [payment] } } + + context "when the payment total doesn't match the outstanding balance on the order" do + before { allow(order).to receive(:outstanding_balance) { 5 } } + it "updates the payment total to reflect the outstanding balance" do + expect{ payment_setup.call! }.to change(payment, :amount).from(10).to(5) + end + end + + context "when the payment total matches the outstanding balance on the order" do + before { allow(order).to receive(:outstanding_balance) { 10 } } + + it "does nothing" do + expect{ payment_setup.call! }.to_not change(payment, :amount).from(10) + end + end + end + + context "when more that one payment exists on the order" do + let!(:payment1) { create(:payment, order: order) } + let!(:payment2) { create(:payment, order: order) } + + before do + allow(order).to receive(:outstanding_balance) { 7 } + allow(order).to receive(:pending_payments).once { [payment1, payment2] } + end + + it "updates the amount of the last payment to reflect the outstanding balance" do + payment_setup.call! + expect(payment1.amount).to eq 45.75 + expect(payment2.amount).to eq 7 + end + end + end + end + end +end diff --git a/engines/order_management/spec/services/order_management/subscriptions/proxy_order_syncer_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/proxy_order_syncer_spec.rb new file mode 100644 index 0000000000..501f6fa67e --- /dev/null +++ b/engines/order_management/spec/services/order_management/subscriptions/proxy_order_syncer_spec.rb @@ -0,0 +1,437 @@ +# frozen_string_literal: true + +module OrderManagement + module Subscriptions + describe ProxyOrderSyncer do + describe "initialization" do + let!(:subscription) { create(:subscription) } + + it "raises an error when initialized with an object + that is not a Subscription or an ActiveRecord::Relation" do + expect{ ProxyOrderSyncer.new(subscription) }.to_not raise_error + expect{ ProxyOrderSyncer.new(Subscription.where(id: subscription.id)) }.to_not raise_error + expect{ ProxyOrderSyncer.new("something") }.to raise_error RuntimeError + end + end + + describe "#sync!" do + let(:now) { Time.zone.now } + let(:schedule) { create(:schedule) } + let(:closed_oc) { # Closed + create(:simple_order_cycle, schedules: [schedule], + orders_open_at: now - 1.minute, + orders_close_at: now) + } + let(:open_oc_closes_before_begins_at_oc) { # Open, but closes before begins at + create(:simple_order_cycle, schedules: [schedule], + orders_open_at: now - 1.minute, + orders_close_at: now + 59.seconds) + } + let(:open_oc) { # Open & closes between begins at and ends at + create(:simple_order_cycle, schedules: [schedule], + orders_open_at: now - 1.minute, + orders_close_at: now + 90.seconds) + } + let(:upcoming_closes_before_begins_at_oc) { # Upcoming, but closes before begins at + create(:simple_order_cycle, schedules: [schedule], + orders_open_at: now + 30.seconds, + orders_close_at: now + 59.seconds) + } + let(:upcoming_closes_on_begins_at_oc) { # Upcoming & closes on begins at + create(:simple_order_cycle, schedules: [schedule], + orders_open_at: now + 30.seconds, + orders_close_at: now + 1.minute) + } + let(:upcoming_closes_on_ends_at_oc) { # Upcoming & closes on ends at + create(:simple_order_cycle, schedules: [schedule], + orders_open_at: now + 30.seconds, + orders_close_at: now + 2.minutes) + } + let(:upcoming_closes_after_ends_at_oc) { # Upcoming & closes after ends at + create(:simple_order_cycle, schedules: [schedule], + orders_open_at: now + 30.seconds, + orders_close_at: now + 121.seconds) + } + let(:subscription) { + build(:subscription, schedule: schedule, + begins_at: now + 1.minute, + ends_at: now + 2.minutes) + } + let(:proxy_orders) { subscription.reload.proxy_orders } + let(:order_cycles) { proxy_orders.map(&:order_cycle) } + let(:syncer) { ProxyOrderSyncer.new(subscription) } + + context "when the subscription is not persisted" do + before do + oc # Ensure oc is created before we attempt to sync + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0) + end + + context "and the schedule includes a closed oc (ie. closed before opens_at)" do + let(:oc) { closed_oc } + it "does not create a new proxy order for that oc" do + expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0) + expect(order_cycles).to_not include oc + end + end + + context "and the schedule includes an open oc that closes before begins_at" do + let(:oc) { open_oc_closes_before_begins_at_oc } + it "does not create a new proxy order for that oc" do + expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0) + expect(order_cycles).to_not include oc + end + end + + context "and the schedule has an open OC that closes between begins_at and ends_at" do + let(:oc) { open_oc } + it "creates a new proxy order for that oc" do + expect{ subscription.save! }.to change(ProxyOrder, :count).from(0).to(1) + expect(order_cycles).to include oc + end + end + + context "and the schedule includes upcoming oc that closes before begins_at" do + let(:oc) { upcoming_closes_before_begins_at_oc } + it "does not create a new proxy order for that oc" do + expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0) + expect(order_cycles).to_not include oc + end + end + + context "and the schedule includes upcoming oc that closes on begins_at" do + let(:oc) { upcoming_closes_on_begins_at_oc } + it "creates a new proxy order for that oc" do + expect{ subscription.save! }.to change(ProxyOrder, :count).from(0).to(1) + expect(order_cycles).to include oc + end + end + + context "and the schedule includes upcoming oc that closes after ends_at" do + let(:oc) { upcoming_closes_on_ends_at_oc } + it "creates a new proxy order for that oc" do + expect{ subscription.save! }.to change(ProxyOrder, :count).from(0).to(1) + expect(order_cycles).to include oc + end + end + + context "and the schedule includes upcoming oc that closes after ends_at" do + let(:oc) { upcoming_closes_after_ends_at_oc } + it "does not create a new proxy order for that oc" do + expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0) + expect(order_cycles).to_not include oc + end + end + end + + context "when the subscription is persisted" do + before { expect(subscription.save!).to be true } + + context "when a proxy order exists" do + let!(:proxy_order) { create(:proxy_order, subscription: subscription, order_cycle: oc) } + + context "for an oc included in the relevant schedule" do + context "and the proxy order has already been placed" do + before { proxy_order.update_attributes(placed_at: 5.minutes.ago) } + + context "the oc is closed (ie. closed before opens_at)" do + let(:oc) { closed_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + + context "and the schedule includes an open oc that closes before begins_at" do + let(:oc) { open_oc_closes_before_begins_at_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + + context "and the oc is open and closes between begins_at and ends_at" do + let(:oc) { open_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + + context "and the oc is upcoming and closes before begins_at" do + let(:oc) { upcoming_closes_before_begins_at_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + + context "and the oc is upcoming and closes on begins_at" do + let(:oc) { upcoming_closes_on_begins_at_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + + context "and the oc is upcoming and closes on ends_at" do + let(:oc) { upcoming_closes_on_ends_at_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + + context "and the oc is upcoming and closes after ends_at" do + let(:oc) { upcoming_closes_after_ends_at_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + end + + context "and the proxy order has not already been placed" do + context "the oc is closed (ie. closed before opens_at)" do + let(:oc) { closed_oc } + it "removes the proxy order" do + expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) + expect(proxy_orders).to_not include proxy_order + end + end + + context "and the schedule includes an open oc that closes before begins_at" do + let(:oc) { open_oc_closes_before_begins_at_oc } + it "removes the proxy order" do + expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) + expect(proxy_orders).to_not include proxy_order + end + end + + context "and the oc is open and closes between begins_at and ends_at" do + let(:oc) { open_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + + context "and the oc is upcoming and closes before begins_at" do + let(:oc) { upcoming_closes_before_begins_at_oc } + it "removes the proxy order" do + expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) + expect(proxy_orders).to_not include proxy_order + end + end + + context "and the oc is upcoming and closes on begins_at" do + let(:oc) { upcoming_closes_on_begins_at_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + + context "and the oc is upcoming and closes on ends_at" do + let(:oc) { upcoming_closes_on_ends_at_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + + context "and the oc is upcoming and closes after ends_at" do + let(:oc) { upcoming_closes_after_ends_at_oc } + it "removes the proxy order" do + expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) + expect(proxy_orders).to_not include proxy_order + end + end + end + end + + context "for an oc not included in the relevant schedule" do + let!(:proxy_order) { + create(:proxy_order, subscription: subscription, order_cycle: open_oc) + } + before do + open_oc.schedule_ids = [] + expect(open_oc.save!).to be true + end + + context "and the proxy order has already been placed" do + before { proxy_order.update_attributes(placed_at: 5.minutes.ago) } + + context "the oc is closed (ie. closed before opens_at)" do + let(:oc) { closed_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + + context "and the schedule includes an open oc that closes before begins_at" do + let(:oc) { open_oc_closes_before_begins_at_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + + context "and the oc is open and closes between begins_at and ends_at" do + let(:oc) { open_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + + context "and the oc is upcoming and closes before begins_at" do + let(:oc) { upcoming_closes_before_begins_at_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + + context "and the oc is upcoming and closes on begins_at" do + let(:oc) { upcoming_closes_on_begins_at_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + + context "and the oc is upcoming and closes on ends_at" do + let(:oc) { upcoming_closes_on_ends_at_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + + context "and the oc is upcoming and closes after ends_at" do + let(:oc) { upcoming_closes_after_ends_at_oc } + it "keeps the proxy order" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) + expect(proxy_orders).to include proxy_order + end + end + end + + context "and the proxy order has not already been placed" do + # This shouldn't really happen, but it is possible + context "the oc is closed (ie. closed before opens_at)" do + let(:oc) { closed_oc } + it "removes the proxy order" do + expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) + expect(proxy_orders).to_not include proxy_order + end + end + + # This shouldn't really happen, but it is possible + context "and the oc is open and closes between begins_at and ends_at" do + let(:oc) { open_oc } + it "removes the proxy order" do + expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) + expect(proxy_orders).to_not include proxy_order + end + end + + context "and the oc is upcoming and closes before begins_at" do + let(:oc) { upcoming_closes_before_begins_at_oc } + it "removes the proxy order" do + expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) + expect(proxy_orders).to_not include proxy_order + end + end + + context "and the oc is upcoming and closes on begins_at" do + let(:oc) { upcoming_closes_on_begins_at_oc } + it "removes the proxy order" do + expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) + expect(proxy_orders).to_not include proxy_order + end + end + + context "and the oc is upcoming and closes on ends_at" do + let(:oc) { upcoming_closes_on_ends_at_oc } + it "removes the proxy order" do + expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) + expect(proxy_orders).to_not include proxy_order + end + end + + context "and the oc is upcoming and closes after ends_at" do + let(:oc) { upcoming_closes_after_ends_at_oc } + it "removes the proxy order" do + expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) + expect(proxy_orders).to_not include proxy_order + end + end + end + end + end + + context "when a proxy order does not exist" do + context "and the schedule includes a closed oc (ie. closed before opens_at)" do + let!(:oc) { closed_oc } + it "does not create a new proxy order for that oc" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0) + expect(order_cycles).to_not include oc + end + end + + context "and the schedule includes an open oc that closes before begins_at" do + let(:oc) { open_oc_closes_before_begins_at_oc } + it "does not create a new proxy order for that oc" do + expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0) + expect(order_cycles).to_not include oc + end + end + + context "and the schedule has an open oc that closes between begins_at and ends_at" do + let!(:oc) { open_oc } + it "creates a new proxy order for that oc" do + expect{ syncer.sync! }.to change(ProxyOrder, :count).from(0).to(1) + expect(order_cycles).to include oc + end + end + + context "and the schedule includes upcoming oc that closes before begins_at" do + let!(:oc) { upcoming_closes_before_begins_at_oc } + it "does not create a new proxy order for that oc" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0) + expect(order_cycles).to_not include oc + end + end + + context "and the schedule includes upcoming oc that closes on begins_at" do + let!(:oc) { upcoming_closes_on_begins_at_oc } + it "creates a new proxy order for that oc" do + expect{ syncer.sync! }.to change(ProxyOrder, :count).from(0).to(1) + expect(order_cycles).to include oc + end + end + + context "and the schedule includes upcoming oc that closes on ends_at" do + let!(:oc) { upcoming_closes_on_ends_at_oc } + it "creates a new proxy order for that oc" do + expect{ syncer.sync! }.to change(ProxyOrder, :count).from(0).to(1) + expect(order_cycles).to include oc + end + end + + context "and the schedule includes upcoming oc that closes after ends_at" do + let!(:oc) { upcoming_closes_after_ends_at_oc } + it "does not create a new proxy order for that oc" do + expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0) + expect(order_cycles).to_not include oc + end + end + end + end + end + end + end +end diff --git a/engines/order_management/spec/services/order_management/subscriptions/stripe_payment_setup_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/stripe_payment_setup_spec.rb new file mode 100644 index 0000000000..c928ddd95b --- /dev/null +++ b/engines/order_management/spec/services/order_management/subscriptions/stripe_payment_setup_spec.rb @@ -0,0 +1,109 @@ +# frozen_string_literal: true + +require 'spec_helper' + +module OrderManagement + module Subscriptions + describe StripePaymentSetup do + let(:order) { create(:order) } + let(:payment_setup) { OrderManagement::Subscriptions::StripePaymentSetup.new(order) } + + describe "#call!" do + context "when no pending payments are present" do + before do + allow(order).to receive(:pending_payments).once { [] } + end + + it "does nothing" do + expect(payment_setup.call!).to eq nil + end + end + + context "when a payment is present" do + let(:payment) { create(:payment, payment_method: payment_method, amount: 10) } + + before { allow(order).to receive(:pending_payments).once { [payment] } } + + context "when the payment method is not a stripe payment method" do + let(:payment_method) { create(:payment_method) } + + it "returns the pending payment with no change" do + expect(payment).to_not receive(:update_attributes) + expect(payment_setup.call!).to eq payment + end + end + + context "when the payment method is a stripe payment method" do + let(:payment_method) { create(:stripe_payment_method) } + + context "and the card is already set (the payment source is a credit card)" do + it "returns the pending payment with no change" do + expect(payment).to_not receive(:update_attributes) + expect(payment_setup.call!).to eq payment + end + end + + context "and the card is not set (the payment source is not a credit card)" do + before { payment.update_attribute :source, nil } + + context "and no default credit card has been saved by the customer" do + before do + allow(order).to receive(:user) { instance_double(Spree::User, default_card: nil) } + end + + it "adds an error to the order and does not update the payment" do + payment_setup.call! + + expect(payment).to_not receive(:update_attributes) + expect(payment_setup.call!).to eq payment + expect(order.errors[:base].first).to eq "There are no authorised "\ + "credit cards available to charge" + end + end + + context "and a default credit card has been saved by the customer" do + let(:saved_credit_card) { create(:credit_card) } + + before do + allow(order).to receive(:user) { + instance_double(Spree::User, default_card: saved_credit_card) + } + end + + context "but the customer has not authorised the shop to charge credit cards" do + before do + allow(order).to receive(:customer) { + instance_double(Customer, allow_charges?: false) + } + end + + it "adds an error to the order and does not update the payment" do + payment_setup.call! + + expect(payment).to_not receive(:update_attributes) + expect(payment_setup.call!).to eq payment + expect(order.errors[:base].first).to eq "There are no authorised "\ + "credit cards available to charge" + end + end + + context "and the customer has authorised the shop to charge credit cards" do + before do + allow(order).to receive(:customer) { + instance_double(Customer, allow_charges?: true) + } + end + + it "uses the saved credit card as the source for the payment" do + payment_setup.call! + expect(payment.source).to eq saved_credit_card + end + end + end + end + end + end + end + end + end +end diff --git a/engines/order_management/spec/services/order_management/subscriptions/stripe_sca_payment_authorize_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/stripe_sca_payment_authorize_spec.rb new file mode 100644 index 0000000000..17ece20be4 --- /dev/null +++ b/engines/order_management/spec/services/order_management/subscriptions/stripe_sca_payment_authorize_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +require 'spec_helper' + +module OrderManagement + module Subscriptions + describe StripeScaPaymentAuthorize do + let(:order) { create(:order) } + let(:payment_authorize) { + OrderManagement::Subscriptions::StripeScaPaymentAuthorize.new(order) + } + + describe "#call!" do + context "when no pending payments are present" do + before { allow(order).to receive(:pending_payments).once { [] } } + + it "does nothing" do + expect(payment_authorize.call!).to eq nil + end + end + + context "when a payment is present" do + let(:payment) { create(:payment, amount: 10) } + + before { allow(order).to receive(:pending_payments).once { [payment] } } + + context "in a state that is not checkout" do + before { payment.state = "processing" } + + it "does nothing" do + payment_authorize.call! + + expect(payment.state).to eq "processing" + expect(order.errors.size).to eq 0 + end + end + + context "in the checkout state" do + before { payment.state = "checkout" } + + context "and payment authorize moves the payment state to pending" do + before { expect(payment).to receive(:authorize!) { payment.state = "pending" } } + + it "does nothing" do + payment_authorize.call! + + expect(order.errors.size).to eq 0 + end + end + + context "and payment authorize does not move the payment state to pending" do + before { allow(payment).to receive(:authorize!) { payment.state = "failed" } } + + it "adds an error to the order indicating authorization failure" do + payment_authorize.call! + + expect(order.errors[:base].first).to eq "Authorization Failure" + end + end + end + end + end + end + end +end diff --git a/engines/order_management/spec/services/order_management/subscriptions/summarizer_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/summarizer_spec.rb new file mode 100644 index 0000000000..09013c204c --- /dev/null +++ b/engines/order_management/spec/services/order_management/subscriptions/summarizer_spec.rb @@ -0,0 +1,132 @@ +# frozen_string_literal: true + +require 'spec_helper' + +module OrderManagement + module Subscriptions + describe Summarizer do + let(:order) { create(:order) } + let(:summarizer) { OrderManagement::Subscriptions::Summarizer.new } + + before { allow(Rails.logger).to receive(:info) } + + describe "#summary_for" do + let(:order) { double(:order, distributor_id: 123) } + + context "when a summary for the order's distributor doesn't already exist" do + it "initializes a new summary object, and returns it" do + expect(summarizer.instance_variable_get(:@summaries).count).to be 0 + summary = summarizer.__send__(:summary_for, order) + expect(summary.shop_id).to be 123 + expect(summarizer.instance_variable_get(:@summaries).count).to be 1 + end + end + + context "when a summary for the order's distributor already exists" do + let(:summary) { double(:summary) } + + before do + summarizer.instance_variable_set(:@summaries, 123 => summary) + end + + it "returns the existing summary object" do + expect(summarizer.instance_variable_get(:@summaries).count).to be 1 + expect(summarizer.__send__(:summary_for, order)).to eq summary + expect(summarizer.instance_variable_get(:@summaries).count).to be 1 + end + end + end + + describe "recording events" do + let(:order) { double(:order) } + let(:summary) { double(:summary) } + before { allow(summarizer).to receive(:summary_for).with(order) { summary } } + + describe "#record_order" do + it "requests a summary for the order and calls #record_order on it" do + expect(summary).to receive(:record_order).with(order).once + summarizer.record_order(order) + end + end + + describe "#record_success" do + it "requests a summary for the order and calls #record_success on it" do + expect(summary).to receive(:record_success).with(order).once + summarizer.record_success(order) + end + end + + describe "#record_issue" do + it "requests a summary for the order and calls #record_issue on it" do + expect(order).to receive(:id) + expect(summary).to receive(:record_issue).with(:type, order, "message").once + summarizer.record_issue(:type, order, "message") + end + end + + describe "#record_and_log_error" do + before do + allow(order).to receive(:number) { "123" } + end + + context "when errors exist on the order" do + before do + allow(order).to receive(:errors) { + double(:errors, any?: true, full_messages: ["Some error"]) + } + end + + it "sends error info to rails logger and calls #record_issue with an error message" do + expect(summarizer).to receive(:record_issue).with(:processing, + order, "Errors: Some error") + summarizer.record_and_log_error(:processing, order) + end + end + + context "when no errors exist on the order" do + before do + allow(order).to receive(:errors) { double(:errors, any?: false) } + end + + it "falls back to calling record_issue" do + expect(summarizer).to receive(:record_issue).with(:processing, order) + summarizer.record_and_log_error(:processing, order) + end + end + end + end + + describe "#send_placement_summary_emails" do + let(:summary1) { double(:summary) } + let(:summary2) { double(:summary) } + let(:summaries) { { 1 => summary1, 2 => summary2 } } + let(:mail_mock) { double(:mail, deliver: true) } + + before do + summarizer.instance_variable_set(:@summaries, summaries) + end + + it "sends a placement summary email for each summary" do + expect(SubscriptionMailer).to receive(:placement_summary_email).twice { mail_mock } + summarizer.send_placement_summary_emails + end + end + + describe "#send_confirmation_summary_emails" do + let(:summary1) { double(:summary) } + let(:summary2) { double(:summary) } + let(:summaries) { { 1 => summary1, 2 => summary2 } } + let(:mail_mock) { double(:mail, deliver: true) } + + before do + summarizer.instance_variable_set(:@summaries, summaries) + end + + it "sends a placement summary email for each summary" do + expect(SubscriptionMailer).to receive(:confirmation_summary_email).twice { mail_mock } + summarizer.send_confirmation_summary_emails + end + end + end + end +end diff --git a/engines/order_management/spec/services/order_management/subscriptions/summary_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/summary_spec.rb new file mode 100644 index 0000000000..5e6360c542 --- /dev/null +++ b/engines/order_management/spec/services/order_management/subscriptions/summary_spec.rb @@ -0,0 +1,127 @@ +# frozen_string_literal: true + +module OrderManagement + module Subscriptions + describe Summary do + let(:summary) { OrderManagement::Subscriptions::Summary.new(123) } + + describe "#initialize" do + it "initializes instance variables: shop_id, order_count, success_count and issues" do + expect(summary.shop_id).to be 123 + expect(summary.order_count).to be 0 + expect(summary.success_count).to be 0 + expect(summary.issues).to be_a Hash + end + end + + describe "#record_order" do + let(:order) { double(:order, id: 37) } + it "adds the order id to the order_ids array" do + summary.record_order(order) + expect(summary.instance_variable_get(:@order_ids)).to eq [order.id] + end + end + + describe "#record_success" do + let(:order) { double(:order, id: 37) } + it "adds the order id to the success_ids array" do + summary.record_success(order) + expect(summary.instance_variable_get(:@success_ids)).to eq [order.id] + end + end + + describe "#record_issue" do + let(:order) { double(:order, id: 1) } + + context "when no issues of the same type have been recorded yet" do + it "adds a new type to the issues hash, and stores a new issue against it" do + summary.record_issue(:some_type, order, "message") + expect(summary.issues.keys).to include :some_type + expect(summary.issues[:some_type][order.id]).to eq "message" + end + end + + context "when an issue of the same type has already been recorded" do + let(:existing_issue) { double(:existing_issue) } + + before { summary.issues[:some_type] = [existing_issue] } + + it "stores a new issue against the existing type" do + summary.record_issue(:some_type, order, "message") + expect(summary.issues[:some_type]).to include existing_issue + expect(summary.issues[:some_type][order.id]).to eq "message" + end + end + end + + describe "#order_count" do + let(:order_ids) { [1, 2, 3, 4, 5, 6, 7] } + it "counts the number of items in the order_ids instance_variable" do + summary.instance_variable_set(:@order_ids, order_ids) + expect(summary.order_count).to be 7 + end + end + + describe "#success_count" do + let(:success_ids) { [1, 2, 3, 4, 5, 6, 7] } + it "counts the number of items in the success_ids instance_variable" do + summary.instance_variable_set(:@success_ids, success_ids) + expect(summary.success_count).to be 7 + end + end + + describe "#issue_count" do + let(:order_ids) { [1, 3, 5, 7, 9] } + let(:success_ids) { [1, 2, 3, 4, 5] } + + it "counts the number of items in order_ids that are not in success_ids" do + summary.instance_variable_set(:@order_ids, order_ids) + summary.instance_variable_set(:@success_ids, success_ids) + expect(summary.issue_count).to be 2 # 7 & 9 + end + end + + describe "#orders_affected_by" do + let(:order1) { create(:order) } + let(:order2) { create(:order) } + + before do + allow(summary).to receive(:unrecorded_ids) { [order1.id] } + allow(summary).to receive(:issues) { { failure: { order2.id => "A message" } } } + end + + context "when the issue type is :other" do + let(:orders) { summary.orders_affected_by(:other) } + + it "returns orders specified by unrecorded_ids" do + expect(orders).to include order1 + expect(orders).to_not include order2 + end + end + + context "when the issue type is :other" do + let(:orders) { summary.orders_affected_by(:failure) } + + it "returns orders specified by the relevant issue hash" do + expect(orders).to include order2 + expect(orders).to_not include order1 + end + end + end + + describe "#unrecorded_ids" do + let(:issues) { { type: { 7 => "message", 8 => "message" } } } + + before do + summary.instance_variable_set(:@order_ids, [1, 3, 5, 7, 9]) + summary.instance_variable_set(:@success_ids, [1, 2, 3, 4, 5]) + summary.instance_variable_set(:@issues, issues) + end + + it "returns order_ids that are not marked as an issue or a success" do + expect(summary.unrecorded_ids).to eq [9] + end + end + end + end +end diff --git a/engines/order_management/spec/services/order_management/subscriptions/validator_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/validator_spec.rb new file mode 100644 index 0000000000..7c52fba12a --- /dev/null +++ b/engines/order_management/spec/services/order_management/subscriptions/validator_spec.rb @@ -0,0 +1,524 @@ +# frozen_string_literal: true + +require "spec_helper" + +module OrderManagement + module Subscriptions + describe Validator do + let(:owner) { create(:user) } + let(:shop) { create(:enterprise, name: "Shop", owner: owner) } + + describe "delegation" do + let(:subscription) { create(:subscription, shop: shop) } + let(:validator) { Validator.new(subscription) } + + it "delegates to subscription" do + expect(validator.shop).to eq subscription.shop + expect(validator.customer).to eq subscription.customer + expect(validator.schedule).to eq subscription.schedule + expect(validator.shipping_method).to eq subscription.shipping_method + expect(validator.payment_method).to eq subscription.payment_method + expect(validator.bill_address).to eq subscription.bill_address + expect(validator.ship_address).to eq subscription.ship_address + expect(validator.begins_at).to eq subscription.begins_at + expect(validator.ends_at).to eq subscription.ends_at + end + end + + describe "validations" do + let(:subscription_stubs) do + { + shop: shop, + customer: true, + schedule: true, + shipping_method: true, + payment_method: true, + bill_address: true, + ship_address: true, + begins_at: true, + ends_at: true, + } + end + + let(:validation_stubs) do + { + shipping_method_allowed?: true, + payment_method_allowed?: true, + payment_method_type_allowed?: true, + ends_at_after_begins_at?: true, + customer_allowed?: true, + schedule_allowed?: true, + credit_card_ok?: true, + subscription_line_items_present?: true, + requested_variants_available?: true + } + end + + let(:subscription) { instance_double(Subscription, subscription_stubs) } + let(:validator) { OrderManagement::Subscriptions::Validator.new(subscription) } + + def stub_validations(validator, methods) + methods.each do |name, value| + allow(validator).to receive(name) { value } + end + end + + describe "shipping method validation" do + let(:subscription) { + instance_double(Subscription, subscription_stubs.except(:shipping_method)) + } + before { stub_validations(validator, validation_stubs.except(:shipping_method_allowed?)) } + + context "when no shipping method is present" do + before { expect(subscription).to receive(:shipping_method).at_least(:once) { nil } } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:shipping_method]).to_not be_empty + end + end + + context "when a shipping method is present" do + let(:shipping_method) { instance_double(Spree::ShippingMethod, distributors: [shop]) } + before { + expect(subscription).to receive(:shipping_method).at_least(:once) { shipping_method } + } + + context "and the shipping method is not associated with the shop" do + before { allow(shipping_method).to receive(:distributors) { [double(:enterprise)] } } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:shipping_method]).to_not be_empty + end + end + + context "and the shipping method is associated with the shop" do + before { allow(shipping_method).to receive(:distributors) { [shop] } } + + it "returns true" do + expect(validator.valid?).to be true + expect(validator.errors[:shipping_method]).to be_empty + end + end + end + end + + describe "payment method validation" do + let(:subscription) { + instance_double(Subscription, subscription_stubs.except(:payment_method)) + } + before { stub_validations(validator, validation_stubs.except(:payment_method_allowed?)) } + + context "when no payment method is present" do + before { expect(subscription).to receive(:payment_method).at_least(:once) { nil } } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:payment_method]).to_not be_empty + end + end + + context "when a payment method is present" do + let(:payment_method) { instance_double(Spree::PaymentMethod, distributors: [shop]) } + before { + expect(subscription).to receive(:payment_method).at_least(:once) { payment_method } + } + + context "and the payment method is not associated with the shop" do + before { allow(payment_method).to receive(:distributors) { [double(:enterprise)] } } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:payment_method]).to_not be_empty + end + end + + context "and the payment method is associated with the shop" do + before { allow(payment_method).to receive(:distributors) { [shop] } } + + it "returns true" do + expect(validator.valid?).to be true + expect(validator.errors[:payment_method]).to be_empty + end + end + end + end + + describe "payment method type validation" do + let(:subscription) { + instance_double(Subscription, subscription_stubs.except(:payment_method)) + } + before { + stub_validations(validator, validation_stubs.except(:payment_method_type_allowed?)) + } + + context "when a payment method is present" do + let(:payment_method) { instance_double(Spree::PaymentMethod, distributors: [shop]) } + before { + expect(subscription).to receive(:payment_method).at_least(:once) { payment_method } + } + + context "and the payment method type is not in the approved list" do + before { allow(payment_method).to receive(:type) { "Blah" } } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:payment_method]).to_not be_empty + end + end + + context "and the payment method is in the approved list" do + let(:approved_type) { Subscription::ALLOWED_PAYMENT_METHOD_TYPES.first } + before { allow(payment_method).to receive(:type) { approved_type } } + + it "returns true" do + expect(validator.valid?).to be true + expect(validator.errors[:payment_method]).to be_empty + end + end + end + end + + describe "dates" do + let(:subscription) { + instance_double(Subscription, subscription_stubs.except(:begins_at, :ends_at)) + } + before { stub_validations(validator, validation_stubs.except(:ends_at_after_begins_at?)) } + before { expect(subscription).to receive(:begins_at).at_least(:once) { begins_at } } + + context "when no begins_at is present" do + let(:begins_at) { nil } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:begins_at]).to_not be_empty + end + end + + context "when a start date is present" do + let(:begins_at) { Time.zone.today } + before { expect(subscription).to receive(:ends_at).at_least(:once) { ends_at } } + + context "when no ends_at is present" do + let(:ends_at) { nil } + + it "returns true" do + expect(validator.valid?).to be true + expect(validator.errors[:ends_at]).to be_empty + end + end + + context "when ends_at is equal to begins_at" do + let(:ends_at) { Time.zone.today } + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:ends_at]).to_not be_empty + end + end + + context "when ends_at is before begins_at" do + let(:ends_at) { Time.zone.today - 1.day } + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:ends_at]).to_not be_empty + end + end + + context "when ends_at is after begins_at" do + let(:ends_at) { Time.zone.today + 1.day } + it "adds an error and returns false" do + expect(validator.valid?).to be true + expect(validator.errors[:ends_at]).to be_empty + end + end + end + end + + describe "addresses" do + before { stub_validations(validator, validation_stubs) } + let(:subscription) { + instance_double(Subscription, subscription_stubs.except(:bill_address, :ship_address)) + } + before { expect(subscription).to receive(:bill_address).at_least(:once) { bill_address } } + before { expect(subscription).to receive(:ship_address).at_least(:once) { ship_address } } + + context "when bill_address and ship_address are not present" do + let(:bill_address) { nil } + let(:ship_address) { nil } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:bill_address]).to_not be_empty + expect(validator.errors[:ship_address]).to_not be_empty + end + end + + context "when bill_address and ship_address are present" do + let(:bill_address) { instance_double(Spree::Address) } + let(:ship_address) { instance_double(Spree::Address) } + + it "returns true" do + expect(validator.valid?).to be true + expect(validator.errors[:bill_address]).to be_empty + expect(validator.errors[:ship_address]).to be_empty + end + end + end + + describe "customer" do + let(:subscription) { instance_double(Subscription, subscription_stubs.except(:customer)) } + before { stub_validations(validator, validation_stubs.except(:customer_allowed?)) } + before { expect(subscription).to receive(:customer).at_least(:once) { customer } } + + context "when no customer is present" do + let(:customer) { nil } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:customer]).to_not be_empty + end + end + + context "when a customer is present" do + let(:customer) { instance_double(Customer) } + + context "and the customer is not associated with the shop" do + before { allow(customer).to receive(:enterprise) { double(:enterprise) } } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:customer]).to_not be_empty + end + end + + context "and the customer is associated with the shop" do + before { allow(customer).to receive(:enterprise) { shop } } + + it "returns true" do + expect(validator.valid?).to be true + expect(validator.errors[:customer]).to be_empty + end + end + end + end + + describe "schedule" do + let(:subscription) { instance_double(Subscription, subscription_stubs.except(:schedule)) } + before { stub_validations(validator, validation_stubs.except(:schedule_allowed?)) } + before { expect(subscription).to receive(:schedule).at_least(:once) { schedule } } + + context "when no schedule is present" do + let(:schedule) { nil } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:schedule]).to_not be_empty + end + end + + context "when a schedule is present" do + let(:schedule) { instance_double(Schedule) } + + context "and the schedule is not associated with the shop" do + before { allow(schedule).to receive(:coordinators) { [double(:enterprise)] } } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:schedule]).to_not be_empty + end + end + + context "and the schedule is associated with the shop" do + before { allow(schedule).to receive(:coordinators) { [shop] } } + + it "returns true" do + expect(validator.valid?).to be true + expect(validator.errors[:schedule]).to be_empty + end + end + end + end + + describe "credit card" do + let(:subscription) { + instance_double(Subscription, subscription_stubs.except(:payment_method)) + } + before { stub_validations(validator, validation_stubs.except(:credit_card_ok?)) } + before { + expect(subscription).to receive(:payment_method).at_least(:once) { payment_method } + } + + context "when using a Check payment method" do + let(:payment_method) { + instance_double(Spree::PaymentMethod, type: "Spree::PaymentMethod::Check") + } + + it "returns true" do + expect(validator.valid?).to be true + expect(validator.errors[:subscription_line_items]).to be_empty + end + end + + context "when using the StripeConnect payment gateway" do + let(:payment_method) { + instance_double(Spree::PaymentMethod, type: "Spree::Gateway::StripeConnect") + } + before { expect(subscription).to receive(:customer).at_least(:once) { customer } } + + context "when the customer does not allow charges" do + let(:customer) { instance_double(Customer, allow_charges: false) } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:payment_method]).to_not be_empty + end + end + + context "when the customer allows charges" do + let(:customer) { instance_double(Customer, allow_charges: true) } + + context "and the customer is not associated with a user" do + before { allow(customer).to receive(:user) { nil } } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:payment_method]).to_not be_empty + end + end + + context "and the customer is associated with a user" do + before { expect(customer).to receive(:user).once { user } } + + context "and the user has no default card set" do + let(:user) { instance_double(Spree::User, default_card: nil) } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:payment_method]).to_not be_empty + end + end + + context "and the user has a default card set" do + let(:user) { instance_double(Spree::User, default_card: 'some card') } + + it "returns true" do + expect(validator.valid?).to be true + expect(validator.errors[:payment_method]).to be_empty + end + end + end + end + end + end + + describe "subscription line items" do + let(:subscription) { instance_double(Subscription, subscription_stubs) } + before { + stub_validations(validator, validation_stubs.except(:subscription_line_items_present?)) + } + before { + expect(subscription).to receive(:subscription_line_items).at_least(:once) { + subscription_line_items + } + } + + context "when no subscription line items exist" do + let(:subscription_line_items) { [] } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:subscription_line_items]).to_not be_empty + end + end + + context "when subscription line items exist but all are marked for destruction" do + let(:subscription_line_item1) { + instance_double(SubscriptionLineItem, marked_for_destruction?: true) + } + let(:subscription_line_items) { [subscription_line_item1] } + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:subscription_line_items]).to_not be_empty + end + end + + context "when subscription line items exist and some are not marked for destruction" do + let(:subscription_line_item1) { + instance_double(SubscriptionLineItem, marked_for_destruction?: true) + } + let(:subscription_line_item2) { + instance_double(SubscriptionLineItem, marked_for_destruction?: false) + } + let(:subscription_line_items) { [subscription_line_item1, subscription_line_item2] } + + it "returns true" do + expect(validator.valid?).to be true + expect(validator.errors[:subscription_line_items]).to be_empty + end + end + end + + describe "variant availability" do + let(:subscription) { instance_double(Subscription, subscription_stubs) } + before { + stub_validations(validator, validation_stubs.except(:requested_variants_available?)) + } + before { + expect(subscription).to receive(:subscription_line_items).at_least(:once) { + subscription_line_items + } + } + + context "when no subscription line items exist" do + let(:subscription_line_items) { [] } + + it "returns true" do + expect(validator.valid?).to be true + expect(validator.errors[:subscription_line_items]).to be_empty + end + end + + context "when subscription line items exist" do + let(:variant1) { instance_double(Spree::Variant, id: 1) } + let(:variant2) { instance_double(Spree::Variant, id: 2) } + let(:subscription_line_item1) { + instance_double(SubscriptionLineItem, variant: variant1) + } + let(:subscription_line_item2) { + instance_double(SubscriptionLineItem, variant: variant2) + } + let(:subscription_line_items) { [subscription_line_item1] } + + context "but some variants are unavailable" do + let(:product) { instance_double(Spree::Product, name: "some_name") } + + before do + allow(validator).to receive(:available_variant_ids) { [variant2.id] } + allow(variant1).to receive(:product) { product } + allow(variant1).to receive(:full_name) { "some name" } + end + + it "adds an error and returns false" do + expect(validator.valid?).to be false + expect(validator.errors[:subscription_line_items]).to_not be_empty + end + end + + context "and all requested variants are available" do + before do + allow(validator).to receive(:available_variant_ids) { [variant1.id, variant2.id] } + end + + it "returns true" do + expect(validator.valid?).to be true + expect(validator.errors[:subscription_line_items]).to be_empty + end + end + end + end + end + end + end +end diff --git a/engines/order_management/spec/services/order_management/subscriptions/variants_list_spec.rb b/engines/order_management/spec/services/order_management/subscriptions/variants_list_spec.rb new file mode 100644 index 0000000000..2ea3206045 --- /dev/null +++ b/engines/order_management/spec/services/order_management/subscriptions/variants_list_spec.rb @@ -0,0 +1,165 @@ +# frozen_string_literal: true + +require "spec_helper" + +module OrderManagement + module Subscriptions + describe VariantsList do + describe "variant eligibility for subscription" do + let!(:shop) { create(:distributor_enterprise) } + let!(:producer) { create(:supplier_enterprise) } + let!(:product) { create(:product, supplier: producer) } + let!(:variant) { product.variants.first } + + let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) } + let!(:subscription) { create(:subscription, shop: shop, schedule: schedule) } + let!(:subscription_line_item) do + create(:subscription_line_item, subscription: subscription, variant: variant) + end + + let(:current_order_cycle) do + create(:simple_order_cycle, coordinator: shop, orders_open_at: 1.week.ago, + orders_close_at: 1.week.from_now) + end + + let(:future_order_cycle) do + create(:simple_order_cycle, coordinator: shop, orders_open_at: 1.week.from_now, + orders_close_at: 2.weeks.from_now) + end + + let(:past_order_cycle) do + create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.weeks.ago, + orders_close_at: 1.week.ago) + end + + let!(:order_cycle) { current_order_cycle } + + context "if the shop is the supplier for the product" do + let!(:producer) { shop } + + it "is eligible" do + expect(described_class.eligible_variants(shop)).to include(variant) + end + end + + context "if the supplier is permitted for the shop" do + let!(:enterprise_relationship) { + create(:enterprise_relationship, child: shop, + parent: product.supplier, + permissions_list: [:add_to_order_cycle]) + } + + it "is eligible" do + expect(described_class.eligible_variants(shop)).to include(variant) + end + end + + context "if the variant is involved in an exchange" do + let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) } + let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) } + + context "if it is an incoming exchange where the shop is the receiver" do + let!(:incoming_exchange) { + order_cycle.exchanges.create(sender: product.supplier, + receiver: shop, + incoming: true, variants: [variant]) + } + + it "is not eligible" do + expect(described_class.eligible_variants(shop)).to_not include(variant) + end + end + + context "if it is an outgoing exchange where the shop is the receiver" do + let!(:outgoing_exchange) { + order_cycle.exchanges.create(sender: product.supplier, + receiver: shop, + incoming: false, + variants: [variant]) + } + + context "if the order cycle is currently open" do + let!(:order_cycle) { current_order_cycle } + + it "is eligible" do + expect(described_class.eligible_variants(shop)).to include(variant) + end + end + + context "if the order cycle opens in the future" do + let!(:order_cycle) { future_order_cycle } + + it "is eligible" do + expect(described_class.eligible_variants(shop)).to include(variant) + end + end + + context "if the order cycle closed in the past" do + let!(:order_cycle) { past_order_cycle } + + it "is eligible" do + expect(described_class.eligible_variants(shop)).to include(variant) + end + end + end + end + + context "if the variant is unrelated" do + it "is not eligible" do + expect(described_class.eligible_variants(shop)).to_not include(variant) + end + end + end + + describe "checking if variant in open and upcoming order cycles" do + let!(:shop) { create(:enterprise) } + let!(:product) { create(:product) } + let!(:variant) { product.variants.first } + let!(:schedule) { create(:schedule) } + + context "if the variant is involved in an exchange" do + let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) } + let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) } + + context "if it is an incoming exchange where the shop is the receiver" do + let!(:incoming_exchange) { + order_cycle.exchanges.create(sender: product.supplier, + receiver: shop, + incoming: true, + variants: [variant]) + } + + it "is is false" do + expect(described_class).not_to be_in_open_and_upcoming_order_cycles(shop, + schedule, + variant) + end + end + + context "if it is an outgoing exchange where the shop is the receiver" do + let!(:outgoing_exchange) { + order_cycle.exchanges.create(sender: product.supplier, + receiver: shop, + incoming: false, + variants: [variant]) + } + + it "is true" do + expect(described_class).to be_in_open_and_upcoming_order_cycles(shop, + schedule, + variant) + end + end + end + + context "if the variant is unrelated" do + it "is false" do + expect(described_class).to_not be_in_open_and_upcoming_order_cycles(shop, + schedule, + variant) + end + end + end + end + end +end diff --git a/engines/web/config/routes.rb b/engines/web/config/routes.rb index 121f3bdd9a..0b56f00a6d 100644 --- a/engines/web/config/routes.rb +++ b/engines/web/config/routes.rb @@ -1,9 +1,7 @@ -Web::Engine.routes.draw do - namespace :api do - scope '/cookies' do - resource :consent, only: [:show, :create, :destroy], controller: "cookies_consent" - end +Openfoodnetwork::Application.routes.prepend do + scope '/api/cookies' do + resource :consent, only: [:show, :create, :destroy], controller: "web/api/cookies_consent" end - get "/angular-templates/:id", to: "angular_templates#show", constraints: { name: %r{[\/\w\.]+} } + get "/angular-templates/:id", to: "web/angular_templates#show", constraints: { name: %r{[\/\w\.]+} } end diff --git a/spec/features/consumer/cookies_spec.rb b/engines/web/spec/features/consumer/cookies_spec.rb similarity index 100% rename from spec/features/consumer/cookies_spec.rb rename to engines/web/spec/features/consumer/cookies_spec.rb diff --git a/lib/open_food_network/orders_and_fulfillments_report.rb b/lib/open_food_network/orders_and_fulfillments_report.rb index 90b0ff59c9..f386be439a 100644 --- a/lib/open_food_network/orders_and_fulfillments_report.rb +++ b/lib/open_food_network/orders_and_fulfillments_report.rb @@ -18,6 +18,7 @@ module OpenFoodNetwork @options = options @report_type = options[:report_type] @render_table = render_table + @variant_scopers_by_distributor_id = {} end def search @@ -56,6 +57,14 @@ module OpenFoodNetwork total_units.round(3) end + def variant_scoper_for(distributor_id) + @variant_scopers_by_distributor_id[distributor_id] ||= + OpenFoodNetwork::ScopeVariantToHub.new( + distributor_id, + report_variant_overrides[distributor_id] || {}, + ) + end + private def report @@ -89,5 +98,13 @@ module OpenFoodNetwork def report_line_items @report_line_items ||= Reports::LineItems.new(order_permissions, options) end + + def report_variant_overrides + @report_variant_overrides ||= + VariantOverridesIndexed.new( + order_permissions.visible_line_items.select('DISTINCT variant_id'), + report_line_items.orders.result.select('DISTINCT distributor_id'), + ).indexed + end end end diff --git a/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report.rb b/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report.rb index 593933e157..8225d45eea 100644 --- a/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report.rb +++ b/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report.rb @@ -7,9 +7,11 @@ module OpenFoodNetwork attr_reader :context delegate :line_item_name, to: :context + delegate :variant_scoper_for, to: :context def initialize(context) @context = context + @scopers_by_distributor_id = {} end # rubocop:disable Metrics/AbcSize @@ -159,7 +161,11 @@ module OpenFoodNetwork }, proc { |_line_items| "" }, - proc { |line_items| line_items.first.variant.sku }, + proc do |line_items| + line_item = line_items.first + variant_scoper_for(line_item.order.distributor_id).scope(line_item.variant) + line_item.variant.sku + end, proc { |line_items| line_items.first.order.order_cycle.andand.name }, proc { |line_items| diff --git a/lib/open_food_network/proxy_order_syncer.rb b/lib/open_food_network/proxy_order_syncer.rb deleted file mode 100644 index 8f867057ab..0000000000 --- a/lib/open_food_network/proxy_order_syncer.rb +++ /dev/null @@ -1,95 +0,0 @@ -module OpenFoodNetwork - class ProxyOrderSyncer - attr_reader :subscription - - delegate :order_cycles, :proxy_orders, :begins_at, :ends_at, to: :subscription - - def initialize(subscriptions) - case subscriptions - when Subscription - @subscription = subscriptions - when ActiveRecord::Relation - @subscriptions = subscriptions.not_ended.not_canceled - else - raise "ProxyOrderSyncer must be initialized with " \ - "an instance of Subscription or ActiveRecord::Relation" - end - end - - def sync! - return sync_subscriptions! if @subscriptions - - return initialise_proxy_orders! unless @subscription.id - - sync_subscription! - end - - private - - def sync_subscriptions! - @subscriptions.each do |subscription| - @subscription = subscription - sync_subscription! - end - end - - def initialise_proxy_orders! - uninitialised_order_cycle_ids.each do |order_cycle_id| - Rails.logger.info "Initializing Proxy Order " \ - "of subscription #{@subscription.id} in order cycle #{order_cycle_id}" - proxy_orders << ProxyOrder.new(subscription: subscription, order_cycle_id: order_cycle_id) - end - end - - def sync_subscription! - Rails.logger.info "Syncing Proxy Orders of subscription #{@subscription.id}" - create_proxy_orders! - remove_orphaned_proxy_orders! - end - - def create_proxy_orders! - return unless not_closed_in_range_order_cycles.any? - - query = "INSERT INTO proxy_orders (subscription_id, order_cycle_id, updated_at, created_at)" - query << " VALUES #{insert_values}" - query << " ON CONFLICT DO NOTHING" - - ActiveRecord::Base.connection.exec_query(query) - end - - def uninitialised_order_cycle_ids - not_closed_in_range_order_cycles.pluck(:id) - proxy_orders.map(&:order_cycle_id) - end - - def remove_orphaned_proxy_orders! - orphaned_proxy_orders.where(nil).delete_all - end - - # Remove Proxy Orders that have not been placed yet - # and are in Order Cycles that are out of range - def orphaned_proxy_orders - orphaned = proxy_orders.where(placed_at: nil) - order_cycle_ids = in_range_order_cycles.pluck(:id) - return orphaned unless order_cycle_ids.any? - - orphaned.where('order_cycle_id NOT IN (?)', order_cycle_ids) - end - - def insert_values - now = Time.now.utc.iso8601 - not_closed_in_range_order_cycles - .map{ |oc| "(#{subscription.id},#{oc.id},'#{now}','#{now}')" } - .join(",") - end - - def not_closed_in_range_order_cycles - in_range_order_cycles.merge(OrderCycle.not_closed) - end - - def in_range_order_cycles - order_cycles.where("orders_close_at >= ? AND orders_close_at <= ?", - begins_at, - ends_at || 100.years.from_now) - end - end -end diff --git a/lib/open_food_network/scope_variants_for_search.rb b/lib/open_food_network/scope_variants_for_search.rb index ddf1d48771..5d16eafefe 100644 --- a/lib/open_food_network/scope_variants_for_search.rb +++ b/lib/open_food_network/scope_variants_for_search.rb @@ -61,7 +61,7 @@ module OpenFoodNetwork end def scope_to_eligible_for_subscriptions_in_distributor - eligible_variants_scope = SubscriptionVariantsService.eligible_variants(distributor) + eligible_variants_scope = OrderManagement::Subscriptions::VariantsList.eligible_variants(distributor) @variants = @variants.merge(eligible_variants_scope) scope_variants_to_distributor(@variants, distributor) end diff --git a/lib/open_food_network/subscription_payment_updater.rb b/lib/open_food_network/subscription_payment_updater.rb deleted file mode 100644 index 4a9c8fa144..0000000000 --- a/lib/open_food_network/subscription_payment_updater.rb +++ /dev/null @@ -1,65 +0,0 @@ -module OpenFoodNetwork - class SubscriptionPaymentUpdater - def initialize(order) - @order = order - end - - def update! - create_payment - ensure_payment_source - return if order.errors.any? - - payment.update_attributes(amount: order.outstanding_balance) - end - - private - - attr_reader :order - - def payment - @payment ||= order.pending_payments.last - end - - def create_payment - return if payment.present? - - @payment = order.payments.create( - payment_method_id: order.subscription.payment_method_id, - amount: order.outstanding_balance - ) - end - - def card_required? - [Spree::Gateway::StripeConnect, - Spree::Gateway::StripeSCA].include? payment.payment_method.class - end - - def card_set? - payment.source is_a? Spree::CreditCard - end - - def ensure_payment_source - return unless card_required? && !card_set? - - ensure_credit_card || order.errors.add(:base, :no_card) - end - - def ensure_credit_card - return false if saved_credit_card.blank? || !allow_charges? - - payment.update_attributes(source: saved_credit_card) - end - - def allow_charges? - order.customer.allow_charges? - end - - def saved_credit_card - order.user.default_card - end - - def errors_present? - order.errors.any? - end - end -end diff --git a/lib/open_food_network/subscription_summarizer.rb b/lib/open_food_network/subscription_summarizer.rb deleted file mode 100644 index 6e4b95da8b..0000000000 --- a/lib/open_food_network/subscription_summarizer.rb +++ /dev/null @@ -1,53 +0,0 @@ -require 'open_food_network/subscription_summary' - -# Used by for SubscriptionPlacementJob and SubscriptionConfirmJob to summarize the -# result of automatic processing of subscriptions for the relevant shop owners. -module OpenFoodNetwork - class SubscriptionSummarizer - def initialize - @summaries = {} - end - - def record_order(order) - summary_for(order).record_order(order) - end - - def record_success(order) - summary_for(order).record_success(order) - end - - def record_issue(type, order, message = nil) - Rails.logger.info "Issue in Subscription Order #{order.id}: #{type}" - summary_for(order).record_issue(type, order, message) - end - - def record_and_log_error(type, order) - return record_issue(type, order) unless order.errors.any? - - error = "Subscription#{type.to_s.camelize}Error" - line1 = "#{error}: Cannot process order #{order.number} due to errors" - line2 = "Errors: #{order.errors.full_messages.join(', ')}" - Rails.logger.info("#{line1}\n#{line2}") - record_issue(type, order, line2) - end - - def send_placement_summary_emails - @summaries.values.each do |summary| - SubscriptionMailer.placement_summary_email(summary).deliver - end - end - - def send_confirmation_summary_emails - @summaries.values.each do |summary| - SubscriptionMailer.confirmation_summary_email(summary).deliver - end - end - - private - - def summary_for(order) - shop_id = order.distributor_id - @summaries[shop_id] ||= SubscriptionSummary.new(shop_id) - end - end -end diff --git a/lib/open_food_network/subscription_summary.rb b/lib/open_food_network/subscription_summary.rb deleted file mode 100644 index fb2a1dc066..0000000000 --- a/lib/open_food_network/subscription_summary.rb +++ /dev/null @@ -1,49 +0,0 @@ -module OpenFoodNetwork - class SubscriptionSummary - attr_reader :shop_id, :order_count, :success_count, :issues - - def initialize(shop_id) - @shop_id = shop_id - @order_ids = [] - @success_ids = [] - @issues = {} - end - - def record_order(order) - @order_ids << order.id - end - - def record_success(order) - @success_ids << order.id - end - - def record_issue(type, order, message) - issues[type] ||= {} - issues[type][order.id] = message - end - - def order_count - @order_ids.count - end - - def success_count - @success_ids.count - end - - def issue_count - (@order_ids - @success_ids).count - end - - def orders_affected_by(type) - case type - when :other then Spree::Order.where(id: unrecorded_ids) - else Spree::Order.where(id: issues[type].keys) - end - end - - def unrecorded_ids - recorded_ids = issues.values.map(&:keys).flatten - @order_ids - @success_ids - recorded_ids - end - end -end diff --git a/lib/tasks/sample_data/group_factory.rb b/lib/tasks/sample_data/group_factory.rb index 15e1ed1fb9..1e63866582 100644 --- a/lib/tasks/sample_data/group_factory.rb +++ b/lib/tasks/sample_data/group_factory.rb @@ -10,19 +10,21 @@ class GroupFactory return if EnterpriseGroup.where(name: "Producer group").exists? create_group( - name: "Producer group", - owner: enterprises.first.owner, - on_front_page: true, - description: "The seed producers", - address: "6 Rollings Road, Upper Ferntree Gully, 3156" + { + name: "Producer group", + owner: enterprises.first.owner, + on_front_page: true, + description: "The seed producers" + }, + "6 Rollings Road, Upper Ferntree Gully, 3156" ) end private - def create_group(params) + def create_group(params, group_address) group = EnterpriseGroup.new(params) - group.address = address(params[:address]) + group.address = address(group_address) group.enterprises = enterprises group.save! end diff --git a/lib/templates/erb/scaffold/_form.html.erb b/lib/templates/erb/scaffold/_form.html.erb deleted file mode 100644 index 201a069e2c..0000000000 --- a/lib/templates/erb/scaffold/_form.html.erb +++ /dev/null @@ -1,13 +0,0 @@ -<%%= simple_form_for(@<%= singular_table_name %>) do |f| %> - <%%= f.error_notification %> - -
- <%- attributes.each do |attribute| -%> - <%%= f.<%= attribute.reference? ? :association : :input %> :<%= attribute.name %> %> - <%- end -%> -
- -
- <%%= f.button :submit %> -
-<%% end %> diff --git a/script/mirror_db.sh b/script/mirror_db.sh index ede932c821..c69db3490d 100755 --- a/script/mirror_db.sh +++ b/script/mirror_db.sh @@ -10,6 +10,7 @@ HOST="$1" BUCKET="$2" : ${DB_USER='ofn_user'} : ${DB_DATABASE='openfoodnetwork'} +: ${DB_CACHE_FILE="tmp/$HOST.sql"} DB_OPTIONS=( --exclude-table-data=sessions @@ -32,20 +33,30 @@ fi # -- Mirror database echo "Mirroring database..." -dropdb -h localhost -U ofn open_food_network_dev +dropdb -h localhost -U ofn open_food_network_dev --if-exists createdb -h localhost -U ofn open_food_network_dev -ssh -C "$HOST" "pg_dump -h localhost -U $DB_USER $DB_DATABASE ${DB_OPTIONS[@]}" | psql -h localhost -U ofn open_food_network_dev + +if [ -s "$DB_CACHE_FILE" ]; then + echo "Using cached dump '$DB_CACHE_FILE'." + psql -h localhost -U ofn open_food_network_dev < "$DB_CACHE_FILE" +else + echo "Downlowding dump to '$DB_CACHE_FILE'." + ssh -C "$HOST" "pg_dump -h localhost -U $DB_USER $DB_DATABASE ${DB_OPTIONS[@]}"\ + | tee "$DB_CACHE_FILE"\ + | psql -h localhost -U ofn open_food_network_dev +fi # -- Disable S3 echo "Preparing mirrored database..." $RAILS_RUN script/prepare_imported_db.rb # -- Mirror images -if [ -n "$BUCKET" ] && hash aws 2>/dev/null; then +if [ -n "$BUCKET" ]; then + if hash aws 2>/dev/null; then echo "Mirroring images..." aws s3 sync "s3://$BUCKET/public public/" - -else + else echo "Please install the AWS CLI tools so that I can copy the images from $BUCKET for you." echo "eg. sudo easy_install awscli" + fi fi diff --git a/spec/controllers/admin/schedules_controller_spec.rb b/spec/controllers/admin/schedules_controller_spec.rb index 299ff5e4d2..99b73f4e03 100644 --- a/spec/controllers/admin/schedules_controller_spec.rb +++ b/spec/controllers/admin/schedules_controller_spec.rb @@ -90,7 +90,7 @@ describe Admin::SchedulesController, type: :controller do it "syncs proxy orders when order_cycle_ids change" do syncer_mock = double(:syncer) - allow(OpenFoodNetwork::ProxyOrderSyncer).to receive(:new) { syncer_mock } + allow(OrderManagement::Subscriptions::ProxyOrderSyncer).to receive(:new) { syncer_mock } expect(syncer_mock).to receive(:sync!).exactly(2).times spree_put :update, format: :json, id: coordinated_schedule.id, order_cycle_ids: [coordinated_order_cycle.id, coordinated_order_cycle2.id] @@ -150,7 +150,7 @@ describe Admin::SchedulesController, type: :controller do it "sync proxy orders" do syncer_mock = double(:syncer) - allow(OpenFoodNetwork::ProxyOrderSyncer).to receive(:new) { syncer_mock } + allow(OrderManagement::Subscriptions::ProxyOrderSyncer).to receive(:new) { syncer_mock } expect(syncer_mock).to receive(:sync!).once create_schedule params diff --git a/spec/controllers/api/enterprises_controller_spec.rb b/spec/controllers/api/enterprises_controller_spec.rb index 15c4606567..ef21340e3f 100644 --- a/spec/controllers/api/enterprises_controller_spec.rb +++ b/spec/controllers/api/enterprises_controller_spec.rb @@ -92,29 +92,5 @@ module Api end end end - - context "as a non-authenticated user" do - let!(:hub) { - create(:distributor_enterprise, with_payment_and_shipping: true, name: 'Shopfront Test Hub') - } - let!(:producer) { create(:supplier_enterprise, name: 'Shopfront Test Producer') } - let!(:category) { create(:taxon, name: 'Fruit') } - let!(:product) { create(:product, supplier: producer, primary_taxon: category ) } - let!(:relationship) { create(:enterprise_relationship, parent: hub, child: producer) } - - before do - allow(controller).to receive(:spree_current_user) { nil } - end - - describe "fetching shopfronts data" do - it "returns data for an enterprise" do - spree_get :shopfront, id: producer.id, format: :json - - expect(json_response['name']).to eq 'Shopfront Test Producer' - expect(json_response['hubs'][0]['name']).to eq 'Shopfront Test Hub' - expect(json_response['supplied_taxons'][0]['name']).to eq 'Fruit' - end - end - end end end diff --git a/spec/controllers/api/shops_controller_spec.rb b/spec/controllers/api/shops_controller_spec.rb new file mode 100644 index 0000000000..3ae4e55a01 --- /dev/null +++ b/spec/controllers/api/shops_controller_spec.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +require 'spec_helper' + +module Api + describe ShopsController, type: :controller do + include AuthenticationWorkflow + render_views + + context "as a non-authenticated user" do + let!(:hub) { + create(:distributor_enterprise, with_payment_and_shipping: true, name: 'Shopfront Test Hub') + } + let!(:producer) { create(:supplier_enterprise, name: 'Shopfront Test Producer') } + let!(:category) { create(:taxon, name: 'Fruit') } + let!(:product) { create(:product, supplier: producer, primary_taxon: category ) } + let!(:relationship) { create(:enterprise_relationship, parent: hub, child: producer) } + let!(:closed_hub1) { create(:distributor_enterprise) } + let!(:closed_hub2) { create(:distributor_enterprise) } + + before do + allow(controller).to receive(:spree_current_user) { nil } + end + + describe "#show" do + it "returns shopfront data for an enterprise" do + spree_get :show, id: producer.id + + expect(json_response['name']).to eq 'Shopfront Test Producer' + expect(json_response['hubs'][0]['name']).to eq 'Shopfront Test Hub' + expect(json_response['supplied_taxons'][0]['name']).to eq 'Fruit' + end + end + + describe "#closed_shops" do + it "returns data for all closed shops" do + spree_get :closed_shops, nil + + expect(json_response).not_to match hub.name + expect(json_response[0]['id']).to eq closed_hub1.id + expect(json_response[1]['id']).to eq closed_hub2.id + end + end + end + end +end diff --git a/spec/controllers/shops_controller_spec.rb b/spec/controllers/shops_controller_spec.rb index 023e7b0245..9d468b7995 100644 --- a/spec/controllers/shops_controller_spec.rb +++ b/spec/controllers/shops_controller_spec.rb @@ -4,11 +4,7 @@ describe ShopsController, type: :controller do include WebHelper render_views - let!(:distributor) { create(:distributor_enterprise) } - - before do - allow(OpenFoodNetwork::EnterpriseInjectionData).to receive(:active_distributor_ids) { [distributor.id] } - end + let!(:distributor) { create(:distributor_enterprise, with_payment_and_shipping: true) } it 'renders distributed product properties' do product_property = create(:property, presentation: 'eggs') diff --git a/spec/controllers/spree/admin/payments_controller_spec.rb b/spec/controllers/spree/admin/payments_controller_spec.rb index 55b20d3484..53dd604ebd 100644 --- a/spec/controllers/spree/admin/payments_controller_spec.rb +++ b/spec/controllers/spree/admin/payments_controller_spec.rb @@ -12,16 +12,114 @@ describe Spree::Admin::PaymentsController, type: :controller do context "#create" do let!(:payment_method) { create(:payment_method, distributors: [shop]) } - let!(:order) do - create(:order_with_totals_and_distribution, distributor: shop, state: "payment") - end - let(:params) { { amount: order.total, payment_method_id: payment_method.id } } - it "advances the order state" do - expect { - spree_post :create, payment: params, order_id: order.number - }.to change { order.reload.state }.from("payment").to("complete") + context "order is not complete" do + let!(:order) do + create(:order_with_totals_and_distribution, distributor: shop, state: "payment") + end + + it "advances the order state" do + expect { + spree_post :create, payment: params, order_id: order.number + }.to change { order.reload.state }.from("payment").to("complete") + end + end + + context "order is complete" do + let!(:order) do + create(:order_with_totals_and_distribution, distributor: shop, + state: "complete", + completed_at: Time.zone.now) + end + + context "with Check payment (payment.process! does nothing)" do + it "redirects to list of payments with success flash" do + spree_post :create, payment: params, order_id: order.number + + redirects_to_list_of_payments_with_success_flash + expect(order.reload.payments.last.state).to eq "checkout" + end + end + + context "with Stripe payment where payment.process! errors out" do + let!(:payment_method) { create(:stripe_payment_method, distributors: [shop]) } + before do + allow_any_instance_of(Spree::Payment). + to receive(:process!). + and_raise(Spree::Core::GatewayError.new("Payment Gateway Error")) + end + + it "redirects to new payment page with flash error" do + spree_post :create, payment: params, order_id: order.number + + redirects_to_new_payment_page_with_flash_error("Payment Gateway Error") + expect(order.reload.payments.last.state).to eq "checkout" + end + end + + context "with StripeSCA payment" do + let!(:payment_method) { create(:stripe_sca_payment_method, distributors: [shop]) } + + context "where payment.authorize! raises GatewayError" do + before do + allow_any_instance_of(Spree::Payment). + to receive(:authorize!). + and_raise(Spree::Core::GatewayError.new("Stripe Authorization Failure")) + end + + it "redirects to new payment page with flash error" do + spree_post :create, payment: params, order_id: order.number + + redirects_to_new_payment_page_with_flash_error("Stripe Authorization Failure") + expect(order.reload.payments.last.state).to eq "checkout" + end + end + + context "where payment.authorize! does not move payment to pending state" do + before do + allow_any_instance_of(Spree::Payment).to receive(:authorize!).and_return(true) + end + + it "redirects to new payment page with flash error" do + spree_post :create, payment: params, order_id: order.number + + redirects_to_new_payment_page_with_flash_error("Authorization Failure") + expect(order.reload.payments.last.state).to eq "checkout" + end + end + + context "where both payment.process! and payment.authorize! work" do + before do + allow_any_instance_of(Spree::Payment).to receive(:authorize!) do |payment| + payment.update_attribute :state, "pending" + end + allow_any_instance_of(Spree::Payment).to receive(:process!).and_return(true) + end + + it "redirects to list of payments with success flash" do + spree_post :create, payment: params, order_id: order.number + + redirects_to_list_of_payments_with_success_flash + expect(order.reload.payments.last.state).to eq "pending" + end + end + end + + def redirects_to_list_of_payments_with_success_flash + expect_redirect_to spree.admin_order_payments_url(order) + expect(flash[:success]).to eq "Payment has been successfully created!" + end + + def redirects_to_new_payment_page_with_flash_error(flash_error) + expect_redirect_to spree.new_admin_order_payment_url(order) + expect(flash[:error]).to eq flash_error + end + + def expect_redirect_to(path) + expect(response.status).to eq 302 + expect(response.location).to eq path + end end end @@ -38,8 +136,10 @@ describe Spree::Admin::PaymentsController, type: :controller do context "that was processed by stripe" do let!(:payment_method) { create(:stripe_payment_method, distributors: [shop]) } - # let!(:credit_card) { create(:credit_card, gateway_customer_profile_id: "cus_1", gateway_payment_profile_id: 'card_2') } - let!(:payment) { create(:payment, order: order, state: 'completed', payment_method: payment_method, response_code: 'ch_1a2b3c', amount: order.total) } + let!(:payment) do + create(:payment, order: order, state: 'completed', payment_method: payment_method, + response_code: 'ch_1a2b3c', amount: order.total) + end before do allow(Stripe).to receive(:api_key) { "sk_test_12345" } @@ -49,7 +149,8 @@ describe Spree::Admin::PaymentsController, type: :controller do before do stub_request(:post, "https://api.stripe.com/v1/charges/ch_1a2b3c/refunds"). with(basic_auth: ["sk_test_12345", ""]). - to_return(status: 200, body: JSON.generate(id: 're_123', object: 'refund', status: 'succeeded') ) + to_return(status: 200, + body: JSON.generate(id: 're_123', object: 'refund', status: 'succeeded') ) end it "voids the payment" do @@ -94,7 +195,10 @@ describe Spree::Admin::PaymentsController, type: :controller do context "that was processed by stripe" do let!(:payment_method) { create(:stripe_payment_method, distributors: [shop]) } - let!(:payment) { create(:payment, order: order, state: 'completed', payment_method: payment_method, response_code: 'ch_1a2b3c', amount: order.total + 5) } + let!(:payment) do + create(:payment, order: order, state: 'completed', payment_method: payment_method, + response_code: 'ch_1a2b3c', amount: order.total + 5) + end before do allow(Stripe).to receive(:api_key) { "sk_test_12345" } @@ -104,7 +208,8 @@ describe Spree::Admin::PaymentsController, type: :controller do before do stub_request(:post, "https://api.stripe.com/v1/charges/ch_1a2b3c/refunds"). with(basic_auth: ["sk_test_12345", ""]). - to_return(status: 200, body: JSON.generate(id: 're_123', object: 'refund', status: 'succeeded') ) + to_return(status: 200, + body: JSON.generate(id: 're_123', object: 'refund', status: 'succeeded') ) end it "partially refunds the payment" do diff --git a/spec/features/admin/order_print_ticket_spec.rb b/spec/features/admin/order_print_ticket_spec.rb new file mode 100644 index 0000000000..add2ef9e7d --- /dev/null +++ b/spec/features/admin/order_print_ticket_spec.rb @@ -0,0 +1,93 @@ +# frozen_string_literal: true + +require "spec_helper" + +feature ' + As an administrator + I want to print a ticket for an order +', js: true do + include AuthenticationWorkflow + include CheckoutHelper + include ActionView::Helpers::NumberHelper + + context "as an enterprise manager" do + let!(:shipping_method) { create(:shipping_method, distributors: [distributor]) } + let!(:distributor) { create(:distributor_enterprise) } + + let!(:order) do + create(:order_with_taxes, distributor: distributor, ship_address: create(:address), + product_price: 110, tax_rate_amount: 0.1, + tax_rate_name: "Tax 1").tap do |record| + Spree::TaxRate.adjust(record) + record.update_shipping_fees! + end + end + + before do + @enterprise_user = create_enterprise_user + @enterprise_user.enterprise_roles.build(enterprise: distributor).save + + quick_login_as @enterprise_user + + Spree::Config[:enable_receipt_printing?] = true + end + + feature "viewing the edit page" do + scenario "can print an order's ticket" do + visit spree.edit_admin_order_path(order) + + find("#links-dropdown .ofn-drop-down").click + + ticket_window = window_opened_by do + within('#links-dropdown') do + click_link('Print Ticket') + end + end + + within_window ticket_window do + accept_alert do + print_data = page.evaluate_script('printData'); + elements_in_print_data = [ + order.distributor.name, + order.distributor.address.address_part1, + order.distributor.address.address_part2, + order.distributor.contact.email, order.number, + line_items_in_print_data, + adjustments_in_print_data, + order.display_total.format(with_currency: false), + taxes_in_print_data, + display_checkout_total_less_tax(order).format(with_currency: false) + ] + expect(print_data.join).to include(*elements_in_print_data.flatten) + end + end + end + + def line_items_in_print_data + order.line_items.map { |line_item| + [line_item.quantity.to_s, + line_item.product.name, + line_item.single_display_amount_with_adjustments.format(symbol: false, + with_currency: false), + line_item.display_amount_with_adjustments.format(symbol: false, with_currency: false)] + } + end + + def adjustments_in_print_data + checkout_adjustments_for(order, exclude: [:line_item]). + reject { |a| a.amount == 0 }. + map do |adjustment| + [raw(adjustment.label), + display_adjustment_amount(adjustment).format(symbol: false, with_currency: false)] + end + end + + def taxes_in_print_data + display_checkout_taxes_hash(order).map { |tax_rate, tax_value| + [tax_rate, + tax_value.format(with_currency: false)] + } + end + end + end +end diff --git a/spec/features/admin/order_spec.rb b/spec/features/admin/order_spec.rb new file mode 100644 index 0000000000..934b7f02f9 --- /dev/null +++ b/spec/features/admin/order_spec.rb @@ -0,0 +1,353 @@ +# frozen_string_literal: true + +require "spec_helper" + +feature ' + As an administrator + I want to create and edit orders +', js: true do + include AuthenticationWorkflow + include WebHelper + + let(:user) { create(:user) } + let(:product) { create(:simple_product) } + let(:distributor) { create(:distributor_enterprise, owner: user, charges_sales_tax: true) } + let(:order_cycle) do + create(:simple_order_cycle, name: 'One', distributors: [distributor], + variants: [product.variants.first]) + end + + let(:order) do + create(:order_with_totals_and_distribution, user: user, distributor: distributor, + order_cycle: order_cycle, state: 'complete', + payment_state: 'balance_due') + end + let(:customer) { order.customer } + + before do + # ensure order has a payment to capture + order.finalize! + + create :check_payment, order: order, amount: order.total + end + + def new_order_with_distribution(distributor, order_cycle) + visit spree.new_admin_order_path + expect(page).to have_selector('#s2id_order_distributor_id') + select2_select distributor.name, from: 'order_distributor_id' + select2_select order_cycle.name, from: 'order_order_cycle_id' + click_button 'Next' + end + + scenario "creating an order with distributor and order cycle" do + distributor_disabled = create(:distributor_enterprise) + create(:simple_order_cycle, name: 'Two') + + quick_login_as_admin + visit spree.admin_orders_path + click_link 'New Order' + + # Distributors without an order cycle should be shown as disabled + open_select2('#s2id_order_distributor_id') + expect(page).to have_selector "ul.select2-results li.select2-result.select2-disabled", + text: distributor_disabled.name + close_select2('#s2id_order_distributor_id') + + # Order cycle selector should be disabled + expect(page).to have_selector "#s2id_order_order_cycle_id.select2-container-disabled" + + # The distributor selector should limit the order cycle selection to those for that distributor + select2_select distributor.name, from: 'order_distributor_id' + expect(page).to have_select2 'order_order_cycle_id', options: ['One (open)'] + select2_select order_cycle.name, from: 'order_order_cycle_id' + click_button 'Next' + + # it suppresses validation errors when setting distribution + expect(page).not_to have_selector '#errorExplanation' + expect(page).to have_content 'ADD PRODUCT' + targetted_select2_search product.name, from: '#add_variant_id', dropdown_css: '.select2-drop' + find('button.add_variant').click + page.has_selector? "table.index tbody[data-hook='admin_order_form_line_items'] tr" # Wait for JS + expect(page).to have_selector 'td', text: product.name + + click_button 'Update' + + expect(page).to have_selector 'h1', text: 'Customer Details' + o = Spree::Order.last + expect(o.distributor).to eq(distributor) + expect(o.order_cycle).to eq(order_cycle) + end + + scenario "can add a product to an existing order" do + quick_login_as_admin + visit spree.edit_admin_order_path(order) + + targetted_select2_search product.name, from: '#add_variant_id', dropdown_css: '.select2-drop' + + find('button.add_variant').click + + expect(page).to have_selector 'td', text: product.name + expect(order.line_items(true).map(&:product)).to include product + end + + scenario "displays error when incorrect distribution for products is chosen" do + d = create(:distributor_enterprise) + oc = create(:simple_order_cycle, distributors: [d]) + + # Move the order back to the cart state + order.state = 'cart' + order.completed_at = nil + # A nil user keeps the order in the cart state + # Even if the edit page tries to automatically progress the order workflow + order.user = nil + order.save + + quick_login_as_admin + visit spree.edit_admin_order_path(order) + + expect(page).to have_select2 "order_distributor_id", with_options: [d.name] + select2_select d.name, from: 'order_distributor_id' + select2_select oc.name, from: 'order_order_cycle_id' + + click_button 'Update And Recalculate Fees' + expect(page).to have_content "Distributor or order cycle " \ + "cannot supply the products in your cart" + end + + scenario "can't add products to an order outside the order's hub and order cycle" do + product = create(:simple_product) + + quick_login_as_admin + visit spree.edit_admin_order_path(order) + + expect(page).not_to have_select2 "add_variant_id", with_options: [product.name] + end + + scenario "can't change distributor or order cycle once order has been finalized" do + quick_login_as_admin + visit spree.edit_admin_order_path(order) + + expect(page).not_to have_select2 'order_distributor_id' + expect(page).not_to have_select2 'order_order_cycle_id' + + expect(page).to have_selector 'p', text: "Distributor: #{order.distributor.name}" + expect(page).to have_selector 'p', text: "Order cycle: #{order.order_cycle.name}" + end + + scenario "filling customer details" do + # Given a customer with an order, which includes their shipping and billing address + + # We change the 1st order's address details, this way + # we validate that the original details (stored in customer) are picked up in the 2nd order + order.ship_address = create(:address, lastname: 'Ship') + order.bill_address = create(:address, lastname: 'Bill') + order.save! + + # We set the existing ship method to delivery, this ship method will be used in the 2nd order + # Otherwise order_updater.shipping_address_from_distributor will set + # the 2nd order address to the distributor address + order.shipping_method.update_attribute :require_ship_address, true + + # When I create a new order + quick_login_as user + new_order_with_distribution(distributor, order_cycle) + targetted_select2_search product.name, from: '#add_variant_id', dropdown_css: '.select2-drop' + find('button.add_variant').click + page.has_selector? "table.index tbody[data-hook='admin_order_form_line_items'] tr" # Wait for JS + click_button 'Update' + + expect(page).to have_selector 'h1.page-title', text: "Customer Details" + + # The customer selection partial should be visible + expect(page).to have_selector '#select-customer' + + # And I select that customer's email address and save the order + targetted_select2_search customer.email, from: '#customer_search_override', + dropdown_css: '.select2-drop' + click_button 'Update' + expect(page).to have_selector "h1.page-title", text: "Customer Details" + + # Then their addresses should be associated with the order + order = Spree::Order.last + expect(order.ship_address.lastname).to eq customer.ship_address.lastname + expect(order.bill_address.lastname).to eq customer.bill_address.lastname + end + + context "as an enterprise manager" do + let(:coordinator1) { create(:distributor_enterprise) } + let(:coordinator2) { create(:distributor_enterprise) } + let!(:order_cycle1) { create(:order_cycle, coordinator: coordinator1) } + let!(:order_cycle2) { create(:simple_order_cycle, coordinator: coordinator2) } + let!(:supplier1) { order_cycle1.suppliers.first } + let!(:supplier2) { order_cycle1.suppliers.last } + let!(:distributor1) { order_cycle1.distributors.first } + let!(:distributor2) do + order_cycle1.distributors.reject{ |d| d == distributor1 }.last # ensure d1 != d2 + end + let(:product) { order_cycle1.products.first } + + before(:each) do + @enterprise_user = create_enterprise_user + @enterprise_user.enterprise_roles.build(enterprise: supplier1).save + @enterprise_user.enterprise_roles.build(enterprise: coordinator1).save + @enterprise_user.enterprise_roles.build(enterprise: distributor1).save + + quick_login_as @enterprise_user + end + + feature "viewing the edit page" do + let!(:shipping_method_for_distributor1) do + create(:shipping_method, name: "Normal", distributors: [distributor1]) + end + let!(:order) do + create(:order_with_taxes, distributor: distributor1, ship_address: create(:address), + product_price: 110, tax_rate_amount: 0.1, + tax_rate_name: "Tax 1").tap do |record| + Spree::TaxRate.adjust(record) + record.update_shipping_fees! + end + end + + background do + distributor1.update_attribute(:abn, '12345678') + + visit spree.edit_admin_order_path(order) + end + + scenario "verifying page contents" do + # shows a list of line_items + within('table.index tbody', match: :first) do + order.line_items.each do |item| + expect(page).to have_selector "td", match: :first, text: item.full_name + expect(page).to have_selector "td.item-price", text: item.single_display_amount + expect(page).to have_selector "input#quantity[value='#{item.quantity}']", visible: false + expect(page).to have_selector "td.item-total", text: item.display_amount + end + end + + # shows the order items total + within('fieldset#order-total') do + expect(page).to have_selector "span.order-total", text: order.display_item_total + end + + # shows the order non-tax adjustments + order.adjustments.eligible.each do |adjustment| + expect(page).to have_selector "td", match: :first, text: adjustment.label + expect(page).to have_selector "td.total", text: adjustment.display_amount + end + + # shows the order total + expect(page).to have_selector "fieldset#order-total", text: order.display_total + + # shows the order tax adjustments + within('fieldset', text: I18n.t('spree.admin.orders.form.line_item_adjustments').upcase) do + expect(page).to have_selector "td", match: :first, text: "Tax 1" + expect(page).to have_selector "td.total", text: Spree::Money.new(10) + end + + # shows the dropdown menu" do + find("#links-dropdown .ofn-drop-down").click + within "#links-dropdown" do + expect(page).to have_link "Resend Confirmation", + href: spree.resend_admin_order_path(order) + expect(page).to have_link "Send Invoice", href: spree.invoice_admin_order_path(order) + expect(page).to have_link "Print Invoice", href: spree.print_admin_order_path(order) + expect(page).to have_link "Cancel Order", href: spree.fire_admin_order_path(order, e: 'cancel') + end + end + + scenario "cannot split the order in different stock locations" do + # There's only 1 stock location in OFN, + # so the split functionality that comes with spree should be hidden + expect(page).to_not have_selector '.split-item' + end + + context "with different shipping methods" do + let!(:different_shipping_method_for_distributor1) do + create(:shipping_method, name: "Different", distributors: [distributor1]) + end + let!(:shipping_method_for_distributor2) do + create(:shipping_method, name: "Other", distributors: [distributor2]) + end + + scenario "can edit shipping method" do + visit spree.edit_admin_order_path(order) + + expect(page).to_not have_content different_shipping_method_for_distributor1.name + + find('.edit-method').click + expect(page).to have_select2 'selected_shipping_rate_id', + with_options: [ + shipping_method_for_distributor1.name, + different_shipping_method_for_distributor1.name + ], without_options: [shipping_method_for_distributor2.name] + select2_select different_shipping_method_for_distributor1.name, + from: 'selected_shipping_rate_id' + find('.save-method').click + + expect(page).to have_content different_shipping_method_for_distributor1.name + end + end + + scenario "can edit tracking number" do + test_tracking_number = "ABCCBA" + expect(page).to_not have_content test_tracking_number + + find('.edit-tracking').click + fill_in "tracking", with: test_tracking_number + find('.save-tracking').click + + expect(page).to have_content test_tracking_number + end + + scenario "editing shipping fees" do + click_link "Adjustments" + shipping_adjustment_tr_selector = "tr#spree_adjustment_#{order.adjustments.shipping.first.id}" + page.find("#{shipping_adjustment_tr_selector} td.actions a.icon-edit").click + + fill_in "Amount", with: "5" + click_button "Continue" + + expect(page.find("#{shipping_adjustment_tr_selector} td.amount")).to have_content "5.00" + end + + context "when an included variant has been deleted" do + let!(:deleted_variant) do + order.line_items.first.variant.tap(&:delete) + end + + it "still lists the variant in the order page" do + within ".stock-contents" do + expect(page).to have_content deleted_variant.product_and_full_name + end + end + end + end + + scenario "creating an order with distributor and order cycle" do + new_order_with_distribution(distributor1, order_cycle1) + + expect(page).to have_content 'ADD PRODUCT' + targetted_select2_search product.name, from: '#add_variant_id', dropdown_css: '.select2-drop' + + find('button.add_variant').click + page.has_selector? "table.index tbody[data-hook='admin_order_form_line_items'] tr" + expect(page).to have_selector 'td', text: product.name + + expect(page).to have_select2 'order_distributor_id', with_options: [distributor1.name] + expect(page).to_not have_select2 'order_distributor_id', with_options: [distributor2.name] + + expect(page).to have_select2 'order_order_cycle_id', + with_options: ["#{order_cycle1.name} (open)"] + expect(page).to_not have_select2 'order_order_cycle_id', + with_options: ["#{order_cycle2.name} (open)"] + + click_button 'Update' + + expect(page).to have_selector 'h1', text: 'Customer Details' + o = Spree::Order.last + expect(o.distributor).to eq distributor1 + expect(o.order_cycle).to eq order_cycle1 + end + end +end diff --git a/spec/features/admin/orders_spec.rb b/spec/features/admin/orders_spec.rb index caa0a1613b..6713a7521f 100644 --- a/spec/features/admin/orders_spec.rb +++ b/spec/features/admin/orders_spec.rb @@ -1,5 +1,6 @@ +# frozen_string_literal: true + require "spec_helper" -include ActionView::Helpers::NumberHelper feature ' As an administrator @@ -7,413 +8,87 @@ feature ' ', js: true do include AuthenticationWorkflow include WebHelper - include CheckoutHelper - background do - @user = create(:user) - @product = create(:simple_product) - @distributor = create(:distributor_enterprise, owner: @user, charges_sales_tax: true) - @order_cycle = create(:simple_order_cycle, name: 'One', distributors: [@distributor], variants: [@product.variants.first]) - - @order = create(:order_with_totals_and_distribution, user: @user, distributor: @distributor, order_cycle: @order_cycle, state: 'complete', payment_state: 'balance_due') - @customer = create(:customer, enterprise: @distributor, email: @user.email, user: @user, ship_address: create(:address)) - - # ensure order has a payment to capture - @order.finalize! - - create :check_payment, order: @order, amount: @order.total + let(:user) { create(:user) } + let(:product) { create(:simple_product) } + let(:distributor) { create(:distributor_enterprise, owner: user, charges_sales_tax: true) } + let(:order_cycle) do + create(:simple_order_cycle, name: 'One', distributors: [distributor], + variants: [product.variants.first]) end - def new_order_with_distribution(distributor, order_cycle) - visit 'admin/orders/new' - expect(page).to have_selector('#s2id_order_distributor_id') - select2_select distributor.name, from: 'order_distributor_id' - select2_select order_cycle.name, from: 'order_order_cycle_id' - click_button 'Next' - end - - scenario "order cycles appear in descending order by close date on orders page" do - create(:simple_order_cycle, name: 'Two', orders_close_at: 2.weeks.from_now) - create(:simple_order_cycle, name: 'Four', orders_close_at: 4.weeks.from_now) - create(:simple_order_cycle, name: 'Three', orders_close_at: 3.weeks.from_now) - - quick_login_as_admin - visit 'admin/orders' - - open_select2('#s2id_q_order_cycle_id_in') - - expect(find('#q_order_cycle_id_in', visible: :all)[:innerHTML]).to have_content(/.*Four.*Three.*Two.*One/m) - end - - scenario "creating an order with distributor and order cycle" do - distributor_disabled = create(:distributor_enterprise) - create(:simple_order_cycle, name: 'Two') - - quick_login_as_admin - - visit '/admin/orders' - click_link 'New Order' - - # Distributors without an order cycle should be shown as disabled - open_select2('#s2id_order_distributor_id') - expect(page).to have_selector "ul.select2-results li.select2-result.select2-disabled", text: distributor_disabled.name - close_select2('#s2id_order_distributor_id') - - # Order cycle selector should be disabled - expect(page).to have_selector "#s2id_order_order_cycle_id.select2-container-disabled" - - # When we select a distributor, it should limit order cycle selection to those for that distributor - select2_select @distributor.name, from: 'order_distributor_id' - expect(page).to have_select2 'order_order_cycle_id', options: ['One (open)'] - select2_select @order_cycle.name, from: 'order_order_cycle_id' - click_button 'Next' - - # it suppresses validation errors when setting distribution - expect(page).not_to have_selector '#errorExplanation' - expect(page).to have_content 'ADD PRODUCT' - targetted_select2_search @product.name, from: '#add_variant_id', dropdown_css: '.select2-drop' - find('button.add_variant').click - page.has_selector? "table.index tbody[data-hook='admin_order_form_line_items'] tr" # Wait for JS - expect(page).to have_selector 'td', text: @product.name - - click_button 'Update' - - expect(page).to have_selector 'h1', text: 'Customer Details' - o = Spree::Order.last - expect(o.distributor).to eq(@distributor) - expect(o.order_cycle).to eq(@order_cycle) - end - - scenario "can add a product to an existing order" do - quick_login_as_admin - visit '/admin/orders' - - click_icon :edit - - targetted_select2_search @product.name, from: '#add_variant_id', dropdown_css: '.select2-drop' - - find('button.add_variant').click - - expect(page).to have_selector 'td', text: @product.name - expect(@order.line_items(true).map(&:product)).to include @product - end - - scenario "displays error when incorrect distribution for products is chosen" do - d = create(:distributor_enterprise) - oc = create(:simple_order_cycle, distributors: [d]) - - # Move the order back to the cart state - @order.state = 'cart' - @order.completed_at = nil - # A nil user keeps the order in the cart state - # Even if the edit page tries to automatically progress the order workflow - @order.user = nil - @order.save - - quick_login_as_admin - visit '/admin/orders' - uncheck 'Only show complete orders' - page.find('a.icon-search').click - - click_icon :edit - expect(page).to have_select2 "order_distributor_id", with_options: [d.name] - select2_select d.name, from: 'order_distributor_id' - select2_select oc.name, from: 'order_order_cycle_id' - - click_button 'Update And Recalculate Fees' - expect(page).to have_content "Distributor or order cycle cannot supply the products in your cart" - end - - scenario "can't add products to an order outside the order's hub and order cycle" do - product = create(:simple_product) - - quick_login_as_admin - visit '/admin/orders' - page.find('td.actions a.icon-edit').click - - expect(page).not_to have_select2 "add_variant_id", with_options: [product.name] - end - - scenario "can't change distributor or order cycle once order has been finalized" do - quick_login_as_admin - visit '/admin/orders' - page.find('td.actions a.icon-edit').click - - expect(page).not_to have_select2 'order_distributor_id' - expect(page).not_to have_select2 'order_order_cycle_id' - - expect(page).to have_selector 'p', text: "Distributor: #{@order.distributor.name}" - expect(page).to have_selector 'p', text: "Order cycle: #{@order.order_cycle.name}" - end - - scenario "filling customer details" do - # Given a customer with an order, which includes their shipping and billing address - - # We change the 1st order's address details - # This way we validate that the original details (stored in customer) are picked up in the 2nd order - @order.ship_address = create(:address, lastname: 'Ship') - @order.bill_address = create(:address, lastname: 'Bill') - @order.save! - - # We set the existing shipping method to delivery, this shipping method will be used in the 2nd order - # Otherwise order_updater.shipping_address_from_distributor will set the 2nd order address to the distributor address - @order.shipping_method.update_attribute :require_ship_address, true - - # When I create a new order - quick_login_as @user - new_order_with_distribution(@distributor, @order_cycle) - targetted_select2_search @product.name, from: '#add_variant_id', dropdown_css: '.select2-drop' - find('button.add_variant').click - page.has_selector? "table.index tbody[data-hook='admin_order_form_line_items'] tr" # Wait for JS - click_button 'Update' - - expect(page).to have_selector 'h1.page-title', text: "Customer Details" - - # The customer selection partial should be visible - expect(page).to have_selector '#select-customer' - - # And I select that customer's email address and save the order - targetted_select2_search @customer.email, from: '#customer_search_override', dropdown_css: '.select2-drop' - click_button 'Update' - expect(page).to have_selector "h1.page-title", text: "Customer Details" - - # Then their addresses should be associated with the order - order = Spree::Order.last - expect(order.ship_address.lastname).to eq @customer.ship_address.lastname - expect(order.bill_address.lastname).to eq @customer.bill_address.lastname - end - - scenario "capture payment from the orders index page" do - quick_login_as_admin - - visit spree.admin_orders_path - expect(page).to have_current_path spree.admin_orders_path - - # click the 'capture' link for the order - page.find("[data-powertip=Capture]").click - - expect(page).to have_css "i.success" - expect(page).to have_css "button.icon-road" - - # check the order was captured - expect(@order.reload.payment_state).to eq "paid" - - # we should still be on the same page - expect(page).to have_current_path spree.admin_orders_path - end - - scenario "ship order from the orders index page" do - @order.payments.first.capture! - quick_login_as_admin - visit spree.admin_orders_path - - page.find("[data-powertip=Ship]").click - - expect(page).to have_css "i.success" - expect(@order.reload.shipments.any?(&:shipped?)).to be true - end - - context "as an enterprise manager" do - let(:coordinator1) { create(:distributor_enterprise) } - let(:coordinator2) { create(:distributor_enterprise) } - let!(:order_cycle1) { create(:order_cycle, coordinator: coordinator1) } - let!(:order_cycle2) { create(:simple_order_cycle, coordinator: coordinator2) } - let!(:supplier1) { order_cycle1.suppliers.first } - let!(:supplier2) { order_cycle1.suppliers.last } - let!(:distributor1) { order_cycle1.distributors.first } - let!(:distributor2) { order_cycle1.distributors.reject{ |d| d == distributor1 }.last } # ensure d1 != d2 - let(:product) { order_cycle1.products.first } - - before(:each) do - @enterprise_user = create_enterprise_user - @enterprise_user.enterprise_roles.build(enterprise: supplier1).save - @enterprise_user.enterprise_roles.build(enterprise: coordinator1).save - @enterprise_user.enterprise_roles.build(enterprise: distributor1).save - - quick_login_as @enterprise_user + context "with a complete order" do + let(:order) do + create(:order_with_totals_and_distribution, user: user, distributor: distributor, + order_cycle: order_cycle, + state: 'complete', payment_state: 'balance_due') end - feature "viewing the edit page" do - let!(:shipping_method_for_distributor1) { create(:shipping_method, name: "Normal", distributors: [distributor1]) } - let!(:different_shipping_method_for_distributor1) { create(:shipping_method, name: "Different", distributors: [distributor1]) } - let!(:shipping_method_for_distributor2) { create(:shipping_method, name: "Other", distributors: [distributor2]) } + scenario "order cycles appear in descending order by close date on orders page" do + create(:simple_order_cycle, name: 'Two', orders_close_at: 2.weeks.from_now) + create(:simple_order_cycle, name: 'Four', orders_close_at: 4.weeks.from_now) + create(:simple_order_cycle, name: 'Three', orders_close_at: 3.weeks.from_now) - let!(:order) do - create(:order_with_taxes, distributor: distributor1, ship_address: create(:address), - product_price: 110, tax_rate_amount: 0.1, - tax_rate_name: "Tax 1").tap do |record| - Spree::TaxRate.adjust(record) - record.update_shipping_fees! - end - end + quick_login_as_admin + visit 'admin/orders' - background do - Spree::Config[:enable_receipt_printing?] = true - distributor1.update_attribute(:abn, '12345678') + open_select2('#s2id_q_order_cycle_id_in') - visit spree.edit_admin_order_path(order) - end - - scenario "shows a list of line_items" do - within('table.index tbody', match: :first) do - order.line_items.each do |item| - expect(page).to have_selector "td", match: :first, text: item.full_name - expect(page).to have_selector "td.item-price", text: item.single_display_amount - expect(page).to have_selector "input#quantity[value='#{item.quantity}']", visible: false - expect(page).to have_selector "td.item-total", text: item.display_amount - end - end - end - - scenario "shows the order items total" do - within('fieldset#order-total') do - expect(page).to have_selector "span.order-total", text: order.display_item_total - end - end - - scenario "shows the order non-tax adjustments" do - within('table.index tbody') do - order.adjustments.eligible.each do |adjustment| - expect(page).to have_selector "td", match: :first, text: adjustment.label - expect(page).to have_selector "td.total", text: adjustment.display_amount - end - end - end - - scenario "shows the order total" do - expect(page).to have_selector "fieldset#order-total", text: order.display_total - end - - scenario "shows the order tax adjustments" do - within('fieldset', text: I18n.t('spree.admin.orders.form.line_item_adjustments').upcase) do - expect(page).to have_selector "td", match: :first, text: "Tax 1" - expect(page).to have_selector "td.total", text: Spree::Money.new(10) - end - end - - scenario "shows the dropdown menu" do - find("#links-dropdown .ofn-drop-down").click - within "#links-dropdown" do - expect(page).to have_link "Resend Confirmation", href: spree.resend_admin_order_path(order) - expect(page).to have_link "Send Invoice", href: spree.invoice_admin_order_path(order) - expect(page).to have_link "Print Invoice", href: spree.print_admin_order_path(order) - expect(page).to have_link "Cancel Order", href: spree.fire_admin_order_path(order, e: 'cancel') - end - end - - scenario "cannot split the order in different stock locations" do - # There's only 1 stock location in OFN, so the split functionality that comes with spree should be hidden - expect(page).to_not have_selector '.split-item' - end - - scenario "can edit shipping method" do - expect(page).to_not have_content different_shipping_method_for_distributor1.name - - find('.edit-method').click - expect(page).to have_select2 'selected_shipping_rate_id', with_options: [shipping_method_for_distributor1.name, different_shipping_method_for_distributor1.name], without_options: [shipping_method_for_distributor2.name] - select2_select different_shipping_method_for_distributor1.name, from: 'selected_shipping_rate_id' - find('.save-method').click - - expect(page).to have_content different_shipping_method_for_distributor1.name - end - - scenario "can edit tracking number" do - test_tracking_number = "ABCCBA" - expect(page).to_not have_content test_tracking_number - - find('.edit-tracking').click - fill_in "tracking", with: test_tracking_number - find('.save-tracking').click - - expect(page).to have_content test_tracking_number - end - - scenario "can print an order's ticket" do - find("#links-dropdown .ofn-drop-down").click - - ticket_window = window_opened_by do - within('#links-dropdown') do - click_link('Print Ticket') - end - end - - within_window ticket_window do - accept_alert do - print_data = page.evaluate_script('printData'); - elements_in_print_data = - [ - order.distributor.name, - order.distributor.address.address_part1, - order.distributor.address.address_part2, - order.distributor.contact.email, - order.number, - order.line_items.map { |line_item| - [line_item.quantity.to_s, - line_item.product.name, - line_item.single_display_amount_with_adjustments.format(symbol: false, with_currency: false), - line_item.display_amount_with_adjustments.format(symbol: false, with_currency: false)] - }, - checkout_adjustments_for(order, exclude: [:line_item]).reject { |a| a.amount == 0 }.map { |adjustment| - [raw(adjustment.label), - display_adjustment_amount(adjustment).format(symbol: false, with_currency: false)] - }, - order.display_total.format(with_currency: false), - display_checkout_taxes_hash(order).map { |tax_rate, tax_value| - [tax_rate, - tax_value.format(with_currency: false)] - }, - display_checkout_total_less_tax(order).format(with_currency: false) - ] - expect(print_data.join).to include(*elements_in_print_data.flatten) - end - end - end - - scenario "editing shipping fees" do - click_link "Adjustments" - page.find('td.actions a.icon-edit').click - - fill_in "Amount", with: "5" - click_button "Continue" - - expect(page.find("td.amount")).to have_content "$5.00" - end - - context "when an included variant has been deleted" do - let!(:deleted_variant) do - order.line_items.first.variant.tap(&:delete) - end - - it "still lists the variant in the order page" do - within ".stock-contents" do - expect(page).to have_content deleted_variant.product_and_full_name - end - end - end + expect(find('#q_order_cycle_id_in', + visible: :all)[:innerHTML]).to have_content(/.*Four.*Three.*Two/m) end - scenario "creating an order with distributor and order cycle" do - new_order_with_distribution(distributor1, order_cycle1) + context "with a capturable order" do + before do + order.finalize! # ensure order has a payment to capture + create :check_payment, order: order, amount: order.total + end - expect(page).to have_content 'ADD PRODUCT' - targetted_select2_search product.name, from: '#add_variant_id', dropdown_css: '.select2-drop' + scenario "capture payment" do + quick_login_as_admin - find('button.add_variant').click - page.has_selector? "table.index tbody[data-hook='admin_order_form_line_items'] tr" # Wait for JS - expect(page).to have_selector 'td', text: product.name + visit spree.admin_orders_path + expect(page).to have_current_path spree.admin_orders_path - expect(page).to have_select2 'order_distributor_id', with_options: [distributor1.name] - expect(page).to_not have_select2 'order_distributor_id', with_options: [distributor2.name] + # click the 'capture' link for the order + page.find("[data-powertip=Capture]").click - expect(page).to have_select2 'order_order_cycle_id', with_options: ["#{order_cycle1.name} (open)"] - expect(page).to_not have_select2 'order_order_cycle_id', with_options: ["#{order_cycle2.name} (open)"] + expect(page).to have_css "i.success" + expect(page).to have_css "button.icon-road" - click_button 'Update' + # check the order was captured + expect(order.reload.payment_state).to eq "paid" - expect(page).to have_selector 'h1', text: 'Customer Details' - o = Spree::Order.last - expect(o.distributor).to eq distributor1 - expect(o.order_cycle).to eq order_cycle1 + # we should still be on the same page + expect(page).to have_current_path spree.admin_orders_path + end + + scenario "ship order from the orders index page" do + order.payments.first.capture! + quick_login_as_admin + visit spree.admin_orders_path + + page.find("[data-powertip=Ship]").click + + expect(page).to have_css "i.success" + expect(order.reload.shipments.any?(&:shipped?)).to be true + end + end + end + + context "with incomplete order" do + scenario "can edit order" do + incomplete_order = create(:order, distributor: distributor, order_cycle: order_cycle) + + quick_login_as_admin + + visit spree.admin_orders_path + uncheck 'Only show complete orders' + page.find('a.icon-search').click + + click_icon :edit + + expect(page).to have_current_path spree.edit_admin_order_path(incomplete_order) end end end diff --git a/spec/features/consumer/account_spec.rb b/spec/features/consumer/account_spec.rb index 23494f6a2c..f6a205bd29 100644 --- a/spec/features/consumer/account_spec.rb +++ b/spec/features/consumer/account_spec.rb @@ -42,8 +42,14 @@ feature ' # Lists all other orders expect(page).to have_content d1o1.number.to_s expect(page).to have_content d1o2.number.to_s + expect(page).to have_link(distributor1.name, + href: "#{distributor1.permalink}/shop", count: 2) expect(page).to have_content d2o1.number.to_s + expect(page).to have_link(distributor2.name, + href: "#{distributor2.permalink}/shop", count: 1) expect(page).to have_content credit_order.number.to_s + expect(page).to have_link(distributor_credit.name, + href: "#{distributor_credit.permalink}/shop", count: 1) # Viewing transaction history click_link I18n.t('spree.users.show.tabs.transactions') @@ -75,6 +81,8 @@ feature ' expect(page).to have_link d1o1.number, href: spree.order_path(d1o1) expect(page).to have_link d1o2.number, href: spree.order_path(d1o2) + expect(page).to have_link(distributor1.name, + href: "#{distributor1.permalink}/shop", count: 2) expect(page).to have_link I18n.t('spree.users.open_orders.cancel'), href: spree.cancel_order_path(d1o1) expect(page).to have_link I18n.t('spree.users.open_orders.cancel'), href: spree.cancel_order_path(d1o2) end diff --git a/spec/features/consumer/groups_spec.rb b/spec/features/consumer/groups_spec.rb index c59835c344..dc9a3e4b75 100644 --- a/spec/features/consumer/groups_spec.rb +++ b/spec/features/consumer/groups_spec.rb @@ -60,8 +60,8 @@ feature 'Groups', js: true do let!(:group) { create(:enterprise_group, enterprises: [d1, d2], on_front_page: true) } let!(:order_cycle) { create(:simple_order_cycle, distributors: [d1, d2], coordinator: create(:distributor_enterprise)) } let(:producer) { create(:supplier_enterprise) } - let(:d1) { create(:distributor_enterprise) } - let(:d2) { create(:distributor_enterprise) } + let(:d1) { create(:distributor_enterprise, with_payment_and_shipping: true) } + let(:d2) { create(:distributor_enterprise, with_payment_and_shipping: true) } let(:p1) { create(:simple_product, supplier: producer) } let(:p2) { create(:simple_product, supplier: create(:supplier_enterprise)) } let(:ex_d1) { order_cycle.exchanges.outgoing.where(receiver_id: d1).first } diff --git a/spec/helpers/products_helper_spec.rb b/spec/helpers/products_helper_spec.rb deleted file mode 100644 index 876c263eed..0000000000 --- a/spec/helpers/products_helper_spec.rb +++ /dev/null @@ -1,24 +0,0 @@ -require 'spec_helper' - -module Spree - describe ProductsHelper, type: :helper do - it "displays variant price differences as absolute, not relative values" do - variant = make_variant_stub(10.00, 10.00) - expect(helper.variant_price_diff(variant)).to eq("(#{with_currency(10.00)})") - - variant = make_variant_stub(10.00, 15.55) - expect(helper.variant_price_diff(variant)).to eq("(#{with_currency(15.55)})") - - variant = make_variant_stub(10.00, 5.55) - expect(helper.variant_price_diff(variant)).to eq("(#{with_currency(5.55)})") - end - - private - - def make_variant_stub(product_price, variant_price) - product = double(:product, price: product_price) - variant = double(:variant, product: product, price: variant_price) - variant - end - end -end diff --git a/spec/javascripts/unit/admin/controllers/variant_overrides_controller_spec.js.coffee b/spec/javascripts/unit/admin/controllers/variant_overrides_controller_spec.js.coffee index 5724fe1353..1c860e8e91 100644 --- a/spec/javascripts/unit/admin/controllers/variant_overrides_controller_spec.js.coffee +++ b/spec/javascripts/unit/admin/controllers/variant_overrides_controller_spec.js.coffee @@ -51,9 +51,9 @@ describe "VariantOverridesCtrl", -> it "adds products", -> spyOn(VariantOverrides, "ensureDataFor") expect(scope.products).toEqual [] - scope.addProducts ['a', 'b'] + scope.addProducts { products: ['a', 'b'] } expect(scope.products).toEqual ['a', 'b'] - scope.addProducts ['c', 'd'] + scope.addProducts { products: ['c', 'd'] } expect(scope.products).toEqual ['a', 'b', 'c', 'd'] expect(VariantOverrides.ensureDataFor).toHaveBeenCalled() diff --git a/spec/javascripts/unit/admin/customers/controllers/customers_controller_spec.js.coffee b/spec/javascripts/unit/admin/customers/controllers/customers_controller_spec.js.coffee index a30eb4eeb8..2ffde63a3e 100644 --- a/spec/javascripts/unit/admin/customers/controllers/customers_controller_spec.js.coffee +++ b/spec/javascripts/unit/admin/customers/controllers/customers_controller_spec.js.coffee @@ -20,7 +20,6 @@ describe "CustomersCtrl", -> {id: 109, name: "Australia", states: [{id: 55, name: "ACT", abbr: "ACT"}]} ] - inject ($controller, $rootScope, _CustomerResource_, $httpBackend) -> scope = $rootScope http = $httpBackend diff --git a/spec/javascripts/unit/admin/orders/controllers/orders_controller_spec.js.coffee b/spec/javascripts/unit/admin/orders/controllers/orders_controller_spec.js.coffee index 7886d8ddd6..2e7cfee530 100644 --- a/spec/javascripts/unit/admin/orders/controllers/orders_controller_spec.js.coffee +++ b/spec/javascripts/unit/admin/orders/controllers/orders_controller_spec.js.coffee @@ -36,9 +36,18 @@ describe "ordersCtrl", -> 'q[s]': 'completed_at desc' })) - describe "using pagination", -> it "changes the page", -> $scope.changePage(2) expect($scope.page).toEqual 2 expect(Orders.index).toHaveBeenCalled() + + describe "sorting products", -> + it "sorts orders", -> + spyOn $scope, "fetchResults" + + $scope.sortOptions.toggle('number') + $scope.$apply() + + expect($scope.sorting).toEqual 'number asc' + expect($scope.fetchResults).toHaveBeenCalled() diff --git a/spec/javascripts/unit/darkswarm/services/checkout_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/checkout_spec.js.coffee index 4ff2f0d97a..d7e23b457b 100644 --- a/spec/javascripts/unit/darkswarm/services/checkout_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/checkout_spec.js.coffee @@ -3,10 +3,13 @@ describe 'Checkout service', -> orderData = null $httpBackend = null Navigation = null + navigationSpy = null flash = null scope = null FlashLoaderMock = - loadFlash: (arg)-> + loadFlash: (arg) -> + Loading = + clear: (arg)-> paymentMethods = [{ id: 99 test: "foo" @@ -48,6 +51,7 @@ describe 'Checkout service', -> module 'Darkswarm' module ($provide)-> $provide.value "RailsFlashLoader", FlashLoaderMock + $provide.value "Loading", Loading $provide.value "currentOrder", orderData $provide.value "shippingMethods", shippingMethods $provide.value "paymentMethods", paymentMethods @@ -61,7 +65,7 @@ describe 'Checkout service', -> scope.Checkout = Checkout Navigation = $injector.get("Navigation") flash = $injector.get("flash") - spyOn(Navigation, "go") # Stubbing out writes to window.location + navigationSpy = spyOn(Navigation, "go") # Stubbing out writes to window.location it "defaults to no shipping method", -> expect(Checkout.order.shipping_method_id).toEqual null @@ -116,12 +120,46 @@ describe 'Checkout service', -> $httpBackend.flush() expect(FlashLoaderMock.loadFlash).toHaveBeenCalledWith {error: "frogs"} - it "puts errors into the scope", -> - $httpBackend.expectPUT("/checkout.json").respond 400, {errors: {error: "frogs"}} + it "puts errors into the scope when there is a flash messages", -> + $httpBackend.expectPUT("/checkout.json").respond 400, {errors: {error: "frogs"}, flash: {error: "flash frogs"}} Checkout.submit() + $httpBackend.flush() expect(Checkout.errors).toEqual {error: "frogs"} + it "throws exception and sends generic flash message when there are errors but no flash message", -> + $httpBackend.expectPUT("/checkout.json").respond 400, {errors: {error: "broken response"}} + try + Checkout.submit() + $httpBackend.flush() + catch error + expect(error.data.errors.error).toBe("broken response") + + expect(Checkout.errors).toEqual {} + + it "throws an exception and sends a flash message to the flash service when reponse doesnt contain errors nor a flash message", -> + spyOn(FlashLoaderMock, "loadFlash") # Stubbing out writes to window.location + $httpBackend.expectPUT("/checkout.json").respond 400, "broken response" + try + Checkout.submit() + $httpBackend.flush() + catch error + expect(error.data).toBe("broken response") + + expect(FlashLoaderMock.loadFlash).toHaveBeenCalledWith({ error: t("checkout.failed") }) + + it "throws an exception and sends a flash message to the flash service when an exception is thrown while handling the error", -> + spyOn(FlashLoaderMock, "loadFlash") # Stubbing out writes to window.location + navigationSpy.and.callFake(-> throw "unexpected error") + $httpBackend.expectPUT("/checkout.json").respond 400, {path: 'path'} + try + Checkout.submit() + $httpBackend.flush() + catch error + expect(error).toBe("unexpected error") + + expect(FlashLoaderMock.loadFlash).toHaveBeenCalledWith({ error: t("checkout.failed") }) + describe "when using the Stripe Connect gateway", -> beforeEach inject ($injector, StripeElements) -> Checkout.order.payment_method_id = 666 diff --git a/spec/javascripts/unit/darkswarm/services/enterprise_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/enterprise_spec.js.coffee index 8b393a6aab..82c26397ca 100644 --- a/spec/javascripts/unit/darkswarm/services/enterprise_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/enterprise_spec.js.coffee @@ -1,5 +1,5 @@ describe "Enterprises service", -> - Enterprises = null + Enterprises = $rootScope = null CurrentHubMock = {} Geo = OK: 'ok' @@ -36,15 +36,17 @@ describe "Enterprises service", -> angular.module('Darkswarm').value('enterprises', enterprises) angular.module('Darkswarm').value('taxons', taxons) - inject ($injector)-> + inject ($injector, _$rootScope_)-> Enterprises = $injector.get("Enterprises") + $rootScope = _$rootScope_ it "stores enterprises as id/object pairs", -> expect(Enterprises.enterprises_by_id["1"]).toBe enterprises[0] expect(Enterprises.enterprises_by_id["2"]).toBe enterprises[1] it "stores enterprises as an array", -> - expect(Enterprises.enterprises).toBe enterprises + $rootScope.$digest() + expect(Enterprises.enterprises).toEqual enterprises it "puts the same objects in enterprises and enterprises_by_id", -> expect(Enterprises.enterprises[0]).toBe Enterprises.enterprises_by_id["1"] diff --git a/spec/jobs/subscription_confirm_job_spec.rb b/spec/jobs/subscription_confirm_job_spec.rb index 3c433bf94d..a061d0fbd4 100644 --- a/spec/jobs/subscription_confirm_job_spec.rb +++ b/spec/jobs/subscription_confirm_job_spec.rb @@ -16,7 +16,7 @@ describe SubscriptionConfirmJob do placed_at: 5.minutes.ago) end let!(:order) { proxy_order.initialise_order! } - let(:proxy_orders) { job.send(:proxy_orders) } + let(:proxy_orders) { job.send(:unconfirmed_proxy_orders) } before do AdvanceOrderService.new(order).call! @@ -80,8 +80,8 @@ describe SubscriptionConfirmJob do before do proxy_order.initialise_order! - allow(job).to receive(:proxy_orders) { ProxyOrder.where(id: proxy_order.id) } - allow(job).to receive(:process!) + allow(job).to receive(:unconfirmed_proxy_orders) { ProxyOrder.where(id: proxy_order.id) } + allow(job).to receive(:confirm_order!) allow(job).to receive(:send_confirmation_summary_emails) end @@ -92,8 +92,7 @@ describe SubscriptionConfirmJob do it "processes confirmable proxy_orders" do job.perform - expect(job).to have_received(:process!) - expect(job.instance_variable_get(:@order)).to eq proxy_order.reload.order + expect(job).to have_received(:confirm_order!).with(proxy_order.reload.order) end it "sends a summary email" do @@ -117,7 +116,7 @@ describe SubscriptionConfirmJob do end end - describe "processing an order" do + describe "confirming an order" do let(:shop) { create(:distributor_enterprise) } let(:order_cycle1) { create(:simple_order_cycle, coordinator: shop) } let(:order_cycle2) { create(:simple_order_cycle, coordinator: shop) } @@ -128,35 +127,34 @@ describe SubscriptionConfirmJob do before do AdvanceOrderService.new(order).call! - allow(job).to receive(:send_confirm_email).and_call_original - job.instance_variable_set(:@order, order) + allow(job).to receive(:send_confirmation_email).and_call_original setup_email - expect(job).to receive(:record_order).with(order) + expect(job).to receive(:record_order) end context "when payments need to be processed" do let(:payment_method) { create(:payment_method) } - let(:payment) { double(:payment, amount: 10) } + let(:payment) { create(:payment, amount: 10) } before do - allow(order).to receive(:payment_total) { 0 } - allow(order).to receive(:total) { 10 } allow(order).to receive(:payment_required?) { true } allow(order).to receive(:pending_payments) { [payment] } end context "and an error is added to the order when updating payments" do - before { expect(job).to receive(:update_payment!) { order.errors.add(:base, "a payment error") } } + before do + expect(job).to receive(:setup_payment!) { |order| order.errors.add(:base, "a payment error") } + end it "sends a failed payment email" do expect(job).to receive(:send_failed_payment_email) - expect(job).to_not receive(:send_confirm_email) - job.send(:process!) + expect(job).to_not receive(:send_confirmation_email) + job.send(:confirm_order!, order) end end context "and no errors are added when updating payments" do - before { expect(job).to receive(:update_payment!) { true } } + before { expect(job).to receive(:setup_payment!) { true } } context "when an error occurs while processing the payment" do before do @@ -165,8 +163,8 @@ describe SubscriptionConfirmJob do it "sends a failed payment email" do expect(job).to receive(:send_failed_payment_email) - expect(job).to_not receive(:send_confirm_email) - job.send(:process!) + expect(job).to_not receive(:send_confirmation_email) + job.send(:confirm_order!, order) end end @@ -182,8 +180,8 @@ describe SubscriptionConfirmJob do it "sends only a subscription confirm email, no regular confirmation emails" do ActionMailer::Base.deliveries.clear - expect{ job.send(:process!) }.to_not enqueue_job ConfirmOrderJob - expect(job).to have_received(:send_confirm_email).once + expect{ job.send(:confirm_order!, order) }.to_not enqueue_job ConfirmOrderJob + expect(job).to have_received(:send_confirmation_email).once expect(ActionMailer::Base.deliveries.count).to be 1 end end @@ -191,19 +189,18 @@ describe SubscriptionConfirmJob do end end - describe "#send_confirm_email" do + describe "#send_confirmation_email" do let(:order) { instance_double(Spree::Order) } let(:mail_mock) { double(:mailer_mock, deliver: true) } before do - job.instance_variable_set(:@order, order) allow(SubscriptionMailer).to receive(:confirmation_email) { mail_mock } end it "records a success and sends the email" do expect(order).to receive(:update!) expect(job).to receive(:record_success).with(order).once - job.send(:send_confirm_email) + job.send(:send_confirmation_email, order) expect(SubscriptionMailer).to have_received(:confirmation_email).with(order) expect(mail_mock).to have_received(:deliver) end @@ -214,14 +211,13 @@ describe SubscriptionConfirmJob do let(:mail_mock) { double(:mailer_mock, deliver: true) } before do - job.instance_variable_set(:@order, order) allow(SubscriptionMailer).to receive(:failed_payment_email) { mail_mock } end it "records and logs an error and sends the email" do expect(order).to receive(:update!) expect(job).to receive(:record_and_log_error).with(:failed_payment, order).once - job.send(:send_failed_payment_email) + job.send(:send_failed_payment_email, order) expect(SubscriptionMailer).to have_received(:failed_payment_email).with(order) expect(mail_mock).to have_received(:deliver) end diff --git a/spec/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report_spec.rb b/spec/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report_spec.rb index 29064b63f8..eb2e2f3cc9 100644 --- a/spec/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report_spec.rb +++ b/spec/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report_spec.rb @@ -62,4 +62,26 @@ RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::CustomerTotalsRepor expect(shipping_method_name_field).to eq shipping_method2.name end end + + context 'when a variant override applies' do + let!(:order) do + create(:completed_order_with_totals, line_items_count: 1, user: customer.user, + customer: customer, distributor: distributor) + end + let(:overidden_sku) { 'magical_sku' } + + before do + create( + :variant_override, + hub: distributor, + variant: order.line_items.first.variant, + sku: overidden_sku + ) + end + + it 'uses the sku from the variant override' do + sku_field = report_table.first[23] + expect(sku_field).to eq overidden_sku + end + end end diff --git a/spec/lib/open_food_network/proxy_order_syncer_spec.rb b/spec/lib/open_food_network/proxy_order_syncer_spec.rb deleted file mode 100644 index 9b059d178f..0000000000 --- a/spec/lib/open_food_network/proxy_order_syncer_spec.rb +++ /dev/null @@ -1,400 +0,0 @@ -require 'open_food_network/proxy_order_syncer' - -module OpenFoodNetwork - describe ProxyOrderSyncer do - describe "initialization" do - let!(:subscription) { create(:subscription) } - - it "raises an error when initialized with an object that is not a Subscription or an ActiveRecord::Relation" do - expect{ ProxyOrderSyncer.new(subscription) }.to_not raise_error - expect{ ProxyOrderSyncer.new(Subscription.where(id: subscription.id)) }.to_not raise_error - expect{ ProxyOrderSyncer.new("something") }.to raise_error RuntimeError - end - end - - describe "#sync!" do - let(:now) { Time.zone.now } - let(:schedule) { create(:schedule) } - let(:closed_oc) { create(:simple_order_cycle, schedules: [schedule], orders_open_at: now - 1.minute, orders_close_at: now) } # Closed - let(:open_oc_closes_before_begins_at_oc) { create(:simple_order_cycle, schedules: [schedule], orders_open_at: now - 1.minute, orders_close_at: now + 59.seconds) } # Open, but closes before begins at - let(:open_oc) { create(:simple_order_cycle, schedules: [schedule], orders_open_at: now - 1.minute, orders_close_at: now + 90.seconds) } # Open & closes between begins at and ends at - let(:upcoming_closes_before_begins_at_oc) { create(:simple_order_cycle, schedules: [schedule], orders_open_at: now + 30.seconds, orders_close_at: now + 59.seconds) } # Upcoming, but closes before begins at - let(:upcoming_closes_on_begins_at_oc) { create(:simple_order_cycle, schedules: [schedule], orders_open_at: now + 30.seconds, orders_close_at: now + 1.minute) } # Upcoming & closes on begins at - let(:upcoming_closes_on_ends_at_oc) { create(:simple_order_cycle, schedules: [schedule], orders_open_at: now + 30.seconds, orders_close_at: now + 2.minutes) } # Upcoming & closes on ends at - let(:upcoming_closes_after_ends_at_oc) { create(:simple_order_cycle, schedules: [schedule], orders_open_at: now + 30.seconds, orders_close_at: now + 121.seconds) } # Upcoming & closes after ends at - let(:subscription) { build(:subscription, schedule: schedule, begins_at: now + 1.minute, ends_at: now + 2.minutes) } - let(:proxy_orders) { subscription.reload.proxy_orders } - let(:order_cycles) { proxy_orders.map(&:order_cycle) } - let(:syncer) { ProxyOrderSyncer.new(subscription) } - - context "when the subscription is not persisted" do - before do - oc # Ensure oc is created before we attempt to sync - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0) - end - - context "and the schedule includes a closed oc (ie. closed before opens_at)" do - let(:oc) { closed_oc } - it "does not create a new proxy order for that oc" do - expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0) - expect(order_cycles).to_not include oc - end - end - - context "and the schedule includes an open oc that closes before begins_at" do - let(:oc) { open_oc_closes_before_begins_at_oc } - it "does not create a new proxy order for that oc" do - expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0) - expect(order_cycles).to_not include oc - end - end - - context "and the schedule includes an open oc that closes between begins_at and ends_at" do - let(:oc) { open_oc } - it "creates a new proxy order for that oc" do - expect{ subscription.save! }.to change(ProxyOrder, :count).from(0).to(1) - expect(order_cycles).to include oc - end - end - - context "and the schedule includes upcoming oc that closes before begins_at" do - let(:oc) { upcoming_closes_before_begins_at_oc } - it "does not create a new proxy order for that oc" do - expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0) - expect(order_cycles).to_not include oc - end - end - - context "and the schedule includes upcoming oc that closes on begins_at" do - let(:oc) { upcoming_closes_on_begins_at_oc } - it "creates a new proxy order for that oc" do - expect{ subscription.save! }.to change(ProxyOrder, :count).from(0).to(1) - expect(order_cycles).to include oc - end - end - - context "and the schedule includes upcoming oc that closes after ends_at" do - let(:oc) { upcoming_closes_on_ends_at_oc } - it "creates a new proxy order for that oc" do - expect{ subscription.save! }.to change(ProxyOrder, :count).from(0).to(1) - expect(order_cycles).to include oc - end - end - - context "and the schedule includes upcoming oc that closes after ends_at" do - let(:oc) { upcoming_closes_after_ends_at_oc } - it "does not create a new proxy order for that oc" do - expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0) - expect(order_cycles).to_not include oc - end - end - end - - context "when the subscription is persisted" do - before { expect(subscription.save!).to be true } - - context "when a proxy order exists" do - let!(:proxy_order) { create(:proxy_order, subscription: subscription, order_cycle: oc) } - - context "for an oc included in the relevant schedule" do - context "and the proxy order has already been placed" do - before { proxy_order.update_attributes(placed_at: 5.minutes.ago) } - - context "the oc is closed (ie. closed before opens_at)" do - let(:oc) { closed_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - - context "and the schedule includes an open oc that closes before begins_at" do - let(:oc) { open_oc_closes_before_begins_at_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - - context "and the oc is open and closes between begins_at and ends_at" do - let(:oc) { open_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - - context "and the oc is upcoming and closes before begins_at" do - let(:oc) { upcoming_closes_before_begins_at_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - - context "and the oc is upcoming and closes on begins_at" do - let(:oc) { upcoming_closes_on_begins_at_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - - context "and the oc is upcoming and closes on ends_at" do - let(:oc) { upcoming_closes_on_ends_at_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - - context "and the oc is upcoming and closes after ends_at" do - let(:oc) { upcoming_closes_after_ends_at_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - end - - context "and the proxy order has not already been placed" do - context "the oc is closed (ie. closed before opens_at)" do - let(:oc) { closed_oc } - it "removes the proxy order" do - expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) - expect(proxy_orders).to_not include proxy_order - end - end - - context "and the schedule includes an open oc that closes before begins_at" do - let(:oc) { open_oc_closes_before_begins_at_oc } - it "removes the proxy order" do - expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) - expect(proxy_orders).to_not include proxy_order - end - end - - context "and the oc is open and closes between begins_at and ends_at" do - let(:oc) { open_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - - context "and the oc is upcoming and closes before begins_at" do - let(:oc) { upcoming_closes_before_begins_at_oc } - it "removes the proxy order" do - expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) - expect(proxy_orders).to_not include proxy_order - end - end - - context "and the oc is upcoming and closes on begins_at" do - let(:oc) { upcoming_closes_on_begins_at_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - - context "and the oc is upcoming and closes on ends_at" do - let(:oc) { upcoming_closes_on_ends_at_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - - context "and the oc is upcoming and closes after ends_at" do - let(:oc) { upcoming_closes_after_ends_at_oc } - it "removes the proxy order" do - expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) - expect(proxy_orders).to_not include proxy_order - end - end - end - end - - context "for an oc not included in the relevant schedule" do - let!(:proxy_order) { create(:proxy_order, subscription: subscription, order_cycle: open_oc) } - before do - open_oc.schedule_ids = [] - expect(open_oc.save!).to be true - end - - context "and the proxy order has already been placed" do - before { proxy_order.update_attributes(placed_at: 5.minutes.ago) } - - context "the oc is closed (ie. closed before opens_at)" do - let(:oc) { closed_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - - context "and the schedule includes an open oc that closes before begins_at" do - let(:oc) { open_oc_closes_before_begins_at_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - - context "and the oc is open and closes between begins_at and ends_at" do - let(:oc) { open_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - - context "and the oc is upcoming and closes before begins_at" do - let(:oc) { upcoming_closes_before_begins_at_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - - context "and the oc is upcoming and closes on begins_at" do - let(:oc) { upcoming_closes_on_begins_at_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - - context "and the oc is upcoming and closes on ends_at" do - let(:oc) { upcoming_closes_on_ends_at_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - - context "and the oc is upcoming and closes after ends_at" do - let(:oc) { upcoming_closes_after_ends_at_oc } - it "keeps the proxy order" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(1) - expect(proxy_orders).to include proxy_order - end - end - end - - context "and the proxy order has not already been placed" do - # This shouldn't really happen, but it is possible - context "the oc is closed (ie. closed before opens_at)" do - let(:oc) { closed_oc } - it "removes the proxy order" do - expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) - expect(proxy_orders).to_not include proxy_order - end - end - - # This shouldn't really happen, but it is possible - context "and the oc is open and closes between begins_at and ends_at" do - let(:oc) { open_oc } - it "removes the proxy order" do - expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) - expect(proxy_orders).to_not include proxy_order - end - end - - context "and the oc is upcoming and closes before begins_at" do - let(:oc) { upcoming_closes_before_begins_at_oc } - it "removes the proxy order" do - expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) - expect(proxy_orders).to_not include proxy_order - end - end - - context "and the oc is upcoming and closes on begins_at" do - let(:oc) { upcoming_closes_on_begins_at_oc } - it "removes the proxy order" do - expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) - expect(proxy_orders).to_not include proxy_order - end - end - - context "and the oc is upcoming and closes on ends_at" do - let(:oc) { upcoming_closes_on_ends_at_oc } - it "removes the proxy order" do - expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) - expect(proxy_orders).to_not include proxy_order - end - end - - context "and the oc is upcoming and closes after ends_at" do - let(:oc) { upcoming_closes_after_ends_at_oc } - it "removes the proxy order" do - expect{ syncer.sync! }.to change(ProxyOrder, :count).from(1).to(0) - expect(proxy_orders).to_not include proxy_order - end - end - end - end - end - - context "when a proxy order does not exist" do - context "and the schedule includes a closed oc (ie. closed before opens_at)" do - let!(:oc) { closed_oc } - it "does not create a new proxy order for that oc" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0) - expect(order_cycles).to_not include oc - end - end - - context "and the schedule includes an open oc that closes before begins_at" do - let(:oc) { open_oc_closes_before_begins_at_oc } - it "does not create a new proxy order for that oc" do - expect{ subscription.save! }.to_not change(ProxyOrder, :count).from(0) - expect(order_cycles).to_not include oc - end - end - - context "and the schedule includes an open oc that closes between begins_at and ends_at" do - let!(:oc) { open_oc } - it "creates a new proxy order for that oc" do - expect{ syncer.sync! }.to change(ProxyOrder, :count).from(0).to(1) - expect(order_cycles).to include oc - end - end - - context "and the schedule includes upcoming oc that closes before begins_at" do - let!(:oc) { upcoming_closes_before_begins_at_oc } - it "does not create a new proxy order for that oc" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0) - expect(order_cycles).to_not include oc - end - end - - context "and the schedule includes upcoming oc that closes on begins_at" do - let!(:oc) { upcoming_closes_on_begins_at_oc } - it "creates a new proxy order for that oc" do - expect{ syncer.sync! }.to change(ProxyOrder, :count).from(0).to(1) - expect(order_cycles).to include oc - end - end - - context "and the schedule includes upcoming oc that closes on ends_at" do - let!(:oc) { upcoming_closes_on_ends_at_oc } - it "creates a new proxy order for that oc" do - expect{ syncer.sync! }.to change(ProxyOrder, :count).from(0).to(1) - expect(order_cycles).to include oc - end - end - - context "and the schedule includes upcoming oc that closes after ends_at" do - let!(:oc) { upcoming_closes_after_ends_at_oc } - it "does not create a new proxy order for that oc" do - expect{ syncer.sync! }.to_not change(ProxyOrder, :count).from(0) - expect(order_cycles).to_not include oc - end - end - end - end - end - end -end diff --git a/spec/lib/open_food_network/subscription_payment_updater_spec.rb b/spec/lib/open_food_network/subscription_payment_updater_spec.rb deleted file mode 100644 index 77be81020e..0000000000 --- a/spec/lib/open_food_network/subscription_payment_updater_spec.rb +++ /dev/null @@ -1,216 +0,0 @@ -require 'spec_helper' -require 'open_food_network/subscription_payment_updater' - -module OpenFoodNetwork - describe SubscriptionPaymentUpdater do - let(:order) { create(:order) } - let(:updater) { OpenFoodNetwork::SubscriptionPaymentUpdater.new(order) } - - describe "#payment" do - context "when only one payment exists on the order" do - let!(:payment) { create(:payment, order: order) } - - context "where the payment is pending" do - it { expect(updater.send(:payment)).to eq payment } - end - - context "where the payment is failed" do - before { payment.update_attribute(:state, 'failed') } - it { expect(updater.send(:payment)).to be nil } - end - end - - context "when more that one payment exists on the order" do - let!(:payment1) { create(:payment, order: order) } - let!(:payment2) { create(:payment, order: order) } - - context "where more than one payment is pending" do - it { expect([payment1, payment2]).to include updater.send(:payment) } - end - - context "where only one payment is pending" do - before { payment1.update_attribute(:state, 'failed') } - it { expect(updater.send(:payment)).to eq payment2 } - end - - context "where no payments are pending" do - before do - payment1.update_attribute(:state, 'failed') - payment2.update_attribute(:state, 'failed') - end - - it { expect(updater.send(:payment)).to be nil } - end - end - end - - describe "#update!" do - let!(:payment){ create(:payment, amount: 10) } - - context "when no pending payments are present" do - let(:payment_method) { create(:payment_method) } - let(:subscription) { double(:subscription, payment_method_id: payment_method.id) } - - before do - allow(order).to receive(:pending_payments).once { [] } - allow(order).to receive(:outstanding_balance) { 5 } - allow(order).to receive(:subscription) { subscription } - end - - it "creates a new payment on the order" do - expect{ updater.update! }.to change(Spree::Payment, :count).by(1) - expect(order.payments.first.amount).to eq 5 - end - end - - context "when a payment is present" do - before { allow(order).to receive(:pending_payments).once { [payment] } } - - context "when a credit card is not required" do - before do - allow(updater).to receive(:card_required?) { false } - expect(updater).to_not receive(:card_available?) - expect(updater).to_not receive(:ensure_credit_card) - end - - context "when the payment total doesn't match the outstanding balance on the order" do - before { allow(order).to receive(:outstanding_balance) { 5 } } - it "updates the payment total to reflect the outstanding balance" do - expect{ updater.update! }.to change(payment, :amount).from(10).to(5) - end - end - - context "when the payment total matches the outstanding balance on the order" do - before { allow(order).to receive(:outstanding_balance) { 10 } } - - it "does nothing" do - expect{ updater.update! }.to_not change(payment, :amount).from(10) - end - end - end - - context "when a credit card is required" do - before do - expect(updater).to receive(:card_required?) { true } - end - - context "and the payment source is not a credit card" do - before { expect(updater).to receive(:card_set?) { false } } - - context "and no default credit card has been set by the customer" do - before do - allow(order).to receive(:user) { instance_double(Spree::User, default_card: nil) } - end - - it "adds an error to the order and does not update the payment" do - expect(payment).to_not receive(:update_attributes) - expect{ updater.update! }.to change(order.errors[:base], :count).from(0).to(1) - end - end - - context "and the customer has not authorised the shop to charge to credit cards" do - before do - allow(order).to receive(:user) { instance_double(Spree::User, default_card: create(:credit_card)) } - allow(order).to receive(:customer) { instance_double(Customer, allow_charges?: false) } - end - - it "adds an error to the order and does not update the payment" do - expect(payment).to_not receive(:update_attributes) - expect{ updater.update! }.to change(order.errors[:base], :count).from(0).to(1) - end - end - - context "and an authorised default credit card is available to charge" do - before do - allow(order).to receive(:user) { instance_double(Spree::User, default_card: create(:credit_card)) } - allow(order).to receive(:customer) { instance_double(Customer, allow_charges?: true) } - end - - context "when the payment total doesn't match the outstanding balance on the order" do - before { allow(order).to receive(:outstanding_balance) { 5 } } - it "updates the payment total to reflect the outstanding balance" do - expect{ updater.update! }.to change(payment, :amount).from(10).to(5) - end - end - - context "when the payment total matches the outstanding balance on the order" do - before { allow(order).to receive(:outstanding_balance) { 10 } } - - it "does nothing" do - expect{ updater.update! }.to_not change(payment, :amount).from(10) - end - end - end - end - - context "and the payment source is already a credit card" do - before { expect(updater).to receive(:card_set?) { true } } - - context "when the payment total doesn't match the outstanding balance on the order" do - before { allow(order).to receive(:outstanding_balance) { 5 } } - it "updates the payment total to reflect the outstanding balance" do - expect{ updater.update! }.to change(payment, :amount).from(10).to(5) - end - end - - context "when the payment total matches the outstanding balance on the order" do - before { allow(order).to receive(:outstanding_balance) { 10 } } - - it "does nothing" do - expect{ updater.update! }.to_not change(payment, :amount).from(10) - end - end - end - end - end - end - - describe "#ensure_credit_card" do - let!(:payment) { create(:payment, source: nil) } - before { allow(updater).to receive(:payment) { payment } } - - context "when no default credit card is found" do - before do - allow(order).to receive(:user) { instance_double(Spree::User, default_card: nil) } - end - - it "returns false and down not update the payment source" do - expect do - expect(updater.send(:ensure_credit_card)).to be false - end.to_not change(payment, :source).from(nil) - end - end - - context "when a default credit card is found" do - let(:credit_card) { create(:credit_card) } - before do - allow(order).to receive(:user) { instance_double(Spree::User, default_card: credit_card) } - end - - context "and charge have not been authorised by the customer" do - before do - allow(order).to receive(:customer) { instance_double(Customer, allow_charges?: false) } - end - - it "returns false and does not update the payment source" do - expect do - expect(updater.send(:ensure_credit_card)).to be false - end.to_not change(payment, :source).from(nil) - end - end - - context "and charges have been authorised by the customer" do - before do - allow(order).to receive(:customer) { instance_double(Customer, allow_charges?: true) } - end - - it "returns true and stores the credit card as the payment source" do - expect do - expect(updater.send(:ensure_credit_card)).to be true - end.to change(payment, :source_id).from(nil).to(credit_card.id) - end - end - end - end - end -end diff --git a/spec/lib/open_food_network/subscription_summarizer_spec.rb b/spec/lib/open_food_network/subscription_summarizer_spec.rb deleted file mode 100644 index a0d2b3f7bf..0000000000 --- a/spec/lib/open_food_network/subscription_summarizer_spec.rb +++ /dev/null @@ -1,126 +0,0 @@ -require 'spec_helper' -require 'open_food_network/subscription_summarizer' - -module OpenFoodNetwork - describe SubscriptionSummarizer do - let(:order) { create(:order) } - let(:summarizer) { OpenFoodNetwork::SubscriptionSummarizer.new } - - before { allow(Rails.logger).to receive(:info) } - - describe "#summary_for" do - let(:order) { double(:order, distributor_id: 123) } - - context "when a summary for the order's distributor doesn't already exist" do - it "initializes a new summary object, and returns it" do - expect(summarizer.instance_variable_get(:@summaries).count).to be 0 - summary = summarizer.send(:summary_for, order) - expect(summary.shop_id).to be 123 - expect(summarizer.instance_variable_get(:@summaries).count).to be 1 - end - end - - context "when a summary for the order's distributor already exists" do - let(:summary) { double(:summary) } - - before do - summarizer.instance_variable_set(:@summaries, 123 => summary) - end - - it "returns the existing summary object" do - expect(summarizer.instance_variable_get(:@summaries).count).to be 1 - expect(summarizer.send(:summary_for, order)).to eq summary - expect(summarizer.instance_variable_get(:@summaries).count).to be 1 - end - end - end - - describe "recording events" do - let(:order) { double(:order) } - let(:summary) { double(:summary) } - before { allow(summarizer).to receive(:summary_for).with(order) { summary } } - - describe "#record_order" do - it "requests a summary for the order and calls #record_order on it" do - expect(summary).to receive(:record_order).with(order).once - summarizer.record_order(order) - end - end - - describe "#record_success" do - it "requests a summary for the order and calls #record_success on it" do - expect(summary).to receive(:record_success).with(order).once - summarizer.record_success(order) - end - end - - describe "#record_issue" do - it "requests a summary for the order and calls #record_issue on it" do - expect(order).to receive(:id) - expect(summary).to receive(:record_issue).with(:type, order, "message").once - summarizer.record_issue(:type, order, "message") - end - end - - describe "#record_and_log_error" do - before do - allow(order).to receive(:number) { "123" } - end - - context "when errors exist on the order" do - before do - allow(order).to receive(:errors) { double(:errors, any?: true, full_messages: ["Some error"]) } - end - - it "sends error info to the rails logger and calls #record_issue on itself with an error message" do - expect(summarizer).to receive(:record_issue).with(:processing, order, "Errors: Some error") - summarizer.record_and_log_error(:processing, order) - end - end - - context "when no errors exist on the order" do - before do - allow(order).to receive(:errors) { double(:errors, any?: false) } - end - - it "falls back to calling record_issue" do - expect(summarizer).to receive(:record_issue).with(:processing, order) - summarizer.record_and_log_error(:processing, order) - end - end - end - end - - describe "#send_placement_summary_emails" do - let(:summary1) { double(:summary) } - let(:summary2) { double(:summary) } - let(:summaries) { { 1 => summary1, 2 => summary2 } } - let(:mail_mock) { double(:mail, deliver: true) } - - before do - summarizer.instance_variable_set(:@summaries, summaries) - end - - it "sends a placement summary email for each summary" do - expect(SubscriptionMailer).to receive(:placement_summary_email).twice { mail_mock } - summarizer.send_placement_summary_emails - end - end - - describe "#send_confirmation_summary_emails" do - let(:summary1) { double(:summary) } - let(:summary2) { double(:summary) } - let(:summaries) { { 1 => summary1, 2 => summary2 } } - let(:mail_mock) { double(:mail, deliver: true) } - - before do - summarizer.instance_variable_set(:@summaries, summaries) - end - - it "sends a placement summary email for each summary" do - expect(SubscriptionMailer).to receive(:confirmation_summary_email).twice { mail_mock } - summarizer.send_confirmation_summary_emails - end - end - end -end diff --git a/spec/lib/open_food_network/subscription_summary_spec.rb b/spec/lib/open_food_network/subscription_summary_spec.rb deleted file mode 100644 index f5b0cd8d71..0000000000 --- a/spec/lib/open_food_network/subscription_summary_spec.rb +++ /dev/null @@ -1,125 +0,0 @@ -require 'open_food_network/subscription_summary' - -module OpenFoodNetwork - describe SubscriptionSummary do - let(:summary) { OpenFoodNetwork::SubscriptionSummary.new(123) } - - describe "#initialize" do - it "initializes instance variables: shop_id, order_count, success_count and issues" do - expect(summary.shop_id).to be 123 - expect(summary.order_count).to be 0 - expect(summary.success_count).to be 0 - expect(summary.issues).to be_a Hash - end - end - - describe "#record_order" do - let(:order) { double(:order, id: 37) } - it "adds the order id to the order_ids array" do - summary.record_order(order) - expect(summary.instance_variable_get(:@order_ids)).to eq [order.id] - end - end - - describe "#record_success" do - let(:order) { double(:order, id: 37) } - it "adds the order id to the success_ids array" do - summary.record_success(order) - expect(summary.instance_variable_get(:@success_ids)).to eq [order.id] - end - end - - describe "#record_issue" do - let(:order) { double(:order, id: 1) } - - context "when no issues of the same type have been recorded yet" do - it "adds a new type to the issues hash, and stores a new issue against it" do - summary.record_issue(:some_type, order, "message") - expect(summary.issues.keys).to include :some_type - expect(summary.issues[:some_type][order.id]).to eq "message" - end - end - - context "when an issue of the same type has already been recorded" do - let(:existing_issue) { double(:existing_issue) } - - before { summary.issues[:some_type] = [existing_issue] } - - it "stores a new issue against the existing type" do - summary.record_issue(:some_type, order, "message") - expect(summary.issues[:some_type]).to include existing_issue - expect(summary.issues[:some_type][order.id]).to eq "message" - end - end - end - - describe "#order_count" do - let(:order_ids) { [1, 2, 3, 4, 5, 6, 7] } - it "counts the number of items in the order_ids instance_variable" do - summary.instance_variable_set(:@order_ids, order_ids) - expect(summary.order_count).to be 7 - end - end - - describe "#success_count" do - let(:success_ids) { [1, 2, 3, 4, 5, 6, 7] } - it "counts the number of items in the success_ids instance_variable" do - summary.instance_variable_set(:@success_ids, success_ids) - expect(summary.success_count).to be 7 - end - end - - describe "#issue_count" do - let(:order_ids) { [1, 3, 5, 7, 9] } - let(:success_ids) { [1, 2, 3, 4, 5] } - - it "counts the number of items in order_ids that are not in success_ids" do - summary.instance_variable_set(:@order_ids, order_ids) - summary.instance_variable_set(:@success_ids, success_ids) - expect(summary.issue_count).to be 2 # 7 & 9 - end - end - - describe "#orders_affected_by" do - let(:order1) { create(:order) } - let(:order2) { create(:order) } - - before do - allow(summary).to receive(:unrecorded_ids) { [order1.id] } - allow(summary).to receive(:issues) { { failure: { order2.id => "A message" } } } - end - - context "when the issue type is :other" do - let(:orders) { summary.orders_affected_by(:other) } - - it "returns orders specified by unrecorded_ids" do - expect(orders).to include order1 - expect(orders).to_not include order2 - end - end - - context "when the issue type is :other" do - let(:orders) { summary.orders_affected_by(:failure) } - - it "returns orders specified by the relevant issue hash" do - expect(orders).to include order2 - expect(orders).to_not include order1 - end - end - end - - describe "#unrecorded_ids" do - let(:issues) { { type: { 7 => "message", 8 => "message" } } } - - before do - summary.instance_variable_set(:@order_ids, [1, 3, 5, 7, 9]) - summary.instance_variable_set(:@success_ids, [1, 2, 3, 4, 5]) - summary.instance_variable_set(:@issues, issues) - end - - it "returns order_ids that are not marked as an issue or a success" do - expect(summary.unrecorded_ids).to eq [9] - end - end - end -end diff --git a/spec/mailers/producer_mailer_spec.rb b/spec/mailers/producer_mailer_spec.rb index c74998c3ab..2449d450c0 100644 --- a/spec/mailers/producer_mailer_spec.rb +++ b/spec/mailers/producer_mailer_spec.rb @@ -101,6 +101,19 @@ describe ProducerMailer, type: :mailer do end.to change(ActionMailer::Base.deliveries, :count).by(0) end + it "shows a deleted variant's full name" do + variant = p1.variants.first + full_name = variant.full_name + variant.delete + + expect(mail.body.encoded).to include(full_name) + end + + it 'shows deleted products' do + p1.delete + expect(mail.body.encoded).to include(p1.name) + end + private def body_lines_including(mail, s) diff --git a/spec/models/producer_property_spec.rb b/spec/models/producer_property_spec.rb deleted file mode 100644 index a39d5fd609..0000000000 --- a/spec/models/producer_property_spec.rb +++ /dev/null @@ -1,74 +0,0 @@ -require 'spec_helper' - -describe ProducerProperty do - let(:producer) { create(:supplier_enterprise) } - let(:pp) { producer.producer_properties.first } - - before do - producer.set_producer_property 'Organic Certified', 'NASAA 54321' - end - - describe ".currently_sold_by and .ever_sold_by" do - let!(:shop) { create(:distributor_enterprise) } - let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first]) } - let(:product) { create(:simple_product, supplier: producer) } - let(:producer_other) { create(:supplier_enterprise) } - let(:product_other) { create(:simple_product, supplier: producer_other) } - let(:pp_other) { producer_other.producer_properties.first } - - before do - producer_other.set_producer_property 'Spiffy', 'Ya' - end - - describe "with an associated producer property" do - it "returns the producer property" do - expect(ProducerProperty.currently_sold_by(shop)).to eq [pp] - expect(ProducerProperty.ever_sold_by(shop)).to eq [pp] - end - end - - describe "with a producer property for a producer not carried by that shop" do - let!(:exchange) { create(:exchange, order_cycle: oc, incoming: true, sender: producer_other, receiver: oc.coordinator) } - - it "doesn't return the producer property" do - expect(ProducerProperty.currently_sold_by(shop)).not_to include pp_other - expect(ProducerProperty.ever_sold_by(shop)).not_to include pp_other - end - end - - describe "with a producer property for a product in a different shop" do - let(:shop_other) { create(:distributor_enterprise) } - let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first]) } - let!(:exchange) { create(:exchange, order_cycle: oc, incoming: false, sender: oc.coordinator, receiver: shop_other, variants: [product_other.variants.first]) } - - it "doesn't return the producer property" do - expect(ProducerProperty.currently_sold_by(shop)).not_to include pp_other - expect(ProducerProperty.ever_sold_by(shop)).not_to include pp_other - end - end - - describe "with a producer property for a product in a closed order cycle" do - before do - oc.update_attributes! orders_open_at: 2.weeks.ago, orders_close_at: 1.week.ago - end - - it "doesn't return the producer property for .currently_sold_by" do - expect(ProducerProperty.currently_sold_by(shop)).not_to include pp - end - - it "returns the producer property for .ever_sold_by" do - expect(ProducerProperty.ever_sold_by(shop)).to include pp - end - end - - describe "with a duplicate producer property" do - let(:product2) { create(:simple_product, supplier: producer) } - let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first, product2.variants.first]) } - - it "doesn't return duplicates" do - expect(ProducerProperty.currently_sold_by(shop).to_a.size).to eq 1 - expect(ProducerProperty.ever_sold_by(shop).to_a.size).to eq 1 - end - end - end -end diff --git a/spec/models/spree/calculator/price_sack_spec.rb b/spec/models/spree/calculator/price_sack_spec.rb index 9b0a38d0e8..921b657f88 100644 --- a/spec/models/spree/calculator/price_sack_spec.rb +++ b/spec/models/spree/calculator/price_sack_spec.rb @@ -8,11 +8,11 @@ describe Spree::Calculator::PriceSack do calculator.preferred_discount_amount = 1 calculator end - let(:line_item) { build(:line_item, price: price, quantity: 2) } context 'when the order amount is below preferred minimal' do let(:price) { 2 } + it "uses the preferred normal amount" do expect(calculator.compute(line_item)).to eq(10) end @@ -20,11 +20,35 @@ describe Spree::Calculator::PriceSack do context 'when the order amount is above preferred minimal' do let(:price) { 6 } + it "uses the preferred discount amount" do expect(calculator.compute(line_item)).to eq(1) end end + context "preferred discount amount is float" do + before do + calculator.preferred_normal_amount = 10.4 + calculator.preferred_discount_amount = 1.2 + end + + context 'when the order amount is below preferred minimal' do + let(:price) { 2 } + + it "uses the float preferred normal amount" do + expect(calculator.compute(line_item)).to eq(10.4) + end + end + + context 'when the order amount is above preferred minimal' do + let(:price) { 6 } + + it "uses the float preferred discount amount" do + expect(calculator.compute(line_item)).to eq(1.2) + end + end + end + context "extends LocalizedNumber" do it_behaves_like "a model using the LocalizedNumber module", [:preferred_minimal_amount, :preferred_normal_amount, :preferred_discount_amount] end diff --git a/spec/models/spree/property_spec.rb b/spec/models/spree/property_spec.rb deleted file mode 100644 index a155cbfa45..0000000000 --- a/spec/models/spree/property_spec.rb +++ /dev/null @@ -1,99 +0,0 @@ -require 'spec_helper' - -module Spree - describe Property do - describe "scopes" do - describe ".applied_by" do - let(:producer) { create(:supplier_enterprise) } - let(:producer_other) { create(:supplier_enterprise) } - let(:product) { create(:simple_product, supplier: producer) } - let(:product_other_producer) { create(:simple_product, supplier: producer_other) } - let(:product_other_property) { create(:simple_product, supplier: producer) } - let(:property) { product.properties.last } - let(:property_other) { product_other_producer.properties.last } - - before do - product.set_property 'Organic', 'NASAA 12345' - product_other_property.set_property 'Organic', 'NASAA 12345' - product_other_producer.set_property 'Biodynamic', 'ASDF 1234' - end - - it "returns properties applied to supplied products" do - expect(Spree::Property.applied_by(producer)).to eq [property] - end - - it "doesn't return properties not applied" do - expect(Spree::Property.applied_by(producer)).not_to include property_other - end - - it "doesn't return duplicates" do - expect(Spree::Property.applied_by(producer).to_a.size).to eq 1 - end - end - - describe ".currently_sold_by and .ever_sold_by" do - let!(:shop) { create(:distributor_enterprise) } - let!(:shop_other) { create(:distributor_enterprise) } - let!(:product) { create(:simple_product) } - let!(:product_other_ex) { create(:simple_product) } - let!(:product_no_oc) { create(:simple_product) } - let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first]) } - let!(:exchange_other_shop) { create(:exchange, order_cycle: oc, sender: oc.coordinator, receiver: shop_other, variants: [product_other_ex.variants.first]) } - let(:property) { product.properties.last } - let(:property_other_ex) { product_other_ex.properties.last } - let(:property_no_oc) { product_no_oc.properties.last } - - before do - product.set_property 'Organic', 'NASAA 12345' - product_other_ex.set_property 'Biodynamic', 'ASDF 12345' - product_no_oc.set_property 'Shiny', 'Very' - end - - it "returns the property" do - expect(Property.currently_sold_by(shop)).to eq [property] - expect(Property.ever_sold_by(shop)).to eq [property] - end - - it "doesn't return the property from another exchange" do - expect(Property.currently_sold_by(shop)).not_to include property_other_ex - expect(Property.ever_sold_by(shop)).not_to include property_other_ex - end - - it "doesn't return the property with no order cycle" do - expect(Property.currently_sold_by(shop)).not_to include property_no_oc - expect(Property.ever_sold_by(shop)).not_to include property_no_oc - end - - describe "closed order cyces" do - let!(:product_closed_oc) { create(:simple_product) } - let!(:oc_closed) { create(:closed_order_cycle, distributors: [shop], variants: [product_closed_oc.variants.first]) } - let(:property_closed_oc) { product_closed_oc.properties.last } - - before { product_closed_oc.set_property 'Spiffy', 'Ooh yeah' } - - it "doesn't return the property for .currently_sold_by" do - expect(Property.currently_sold_by(shop)).not_to include property_closed_oc - end - - it "returns the property for .ever_sold_by" do - expect(Property.ever_sold_by(shop)).to include property_closed_oc - end - end - - context "with another product in the order cycle" do - let!(:product2) { create(:simple_product) } - let!(:oc) { create(:simple_order_cycle, distributors: [shop], variants: [product.variants.first, product2.variants.first]) } - - before do - product2.set_property 'Organic', 'NASAA 12345' - end - - it "doesn't return duplicates" do - expect(Property.currently_sold_by(shop).to_a.size).to eq 1 - expect(Property.ever_sold_by(shop).to_a.size).to eq 1 - end - end - end - end - end -end diff --git a/spec/performance/proxy_order_syncer_spec.rb b/spec/performance/proxy_order_syncer_spec.rb deleted file mode 100644 index 95678c68a2..0000000000 --- a/spec/performance/proxy_order_syncer_spec.rb +++ /dev/null @@ -1,67 +0,0 @@ -require 'open_food_network/proxy_order_syncer' - -module OpenFoodNetwork - describe ProxyOrderSyncer, performance: true do - let(:start) { Time.zone.now.beginning_of_day } - let!(:schedule) { create(:schedule, order_cycles: order_cycles) } - - let!(:order_cycles) do - Array.new(10) do |i| - create(:simple_order_cycle, orders_open_at: start + i.days, - orders_close_at: start + (i + 1).days ) - end - end - - let!(:subscriptions) do - Array.new(150) do |_i| - create(:subscription, schedule: schedule, begins_at: start, ends_at: start + 10.days) - end - Subscription.where(schedule_id: schedule) - end - - context "measuring performance for initialisation" do - it "reports the average run time for adding 10 OCs to 150 subscriptions" do - expect(ProxyOrder.count).to be 0 - times = [] - 10.times do - syncer = ProxyOrderSyncer.new(subscriptions.reload) - - t1 = Time.zone.now - syncer.sync! - t2 = Time.zone.now - diff = t2 - t1 - times << diff - puts diff.round(2) - - expect(ProxyOrder.count).to be 1500 - ProxyOrder.destroy_all - end - puts "AVG: #{(times.sum / times.count).round(2)}" - end - end - - context "measuring performance for removal" do - it "reports the average run time for removing 8 OCs from 150 subscriptions" do - times = [] - 10.times do - syncer = ProxyOrderSyncer.new(subscriptions.reload) - syncer.sync! - expect(ProxyOrder.count).to be 1500 - subscriptions.update_all(begins_at: start + 8.days + 1.minute) - syncer = ProxyOrderSyncer.new(subscriptions.reload) - - t1 = Time.zone.now - syncer.sync! - t2 = Time.zone.now - diff = t2 - t1 - times << diff - puts diff.round(2) - - expect(ProxyOrder.count).to be 300 - subscriptions.update_all(begins_at: start) - end - puts "AVG: #{(times.sum / times.count).round(2)}" - end - end - end -end diff --git a/spec/serializers/api/admin/customer_serializer_spec.rb b/spec/serializers/api/admin/customer_serializer_spec.rb index 02c97e3948..0d9b1625d9 100644 --- a/spec/serializers/api/admin/customer_serializer_spec.rb +++ b/spec/serializers/api/admin/customer_serializer_spec.rb @@ -1,12 +1,16 @@ require 'spec_helper' describe Api::Admin::CustomerSerializer do - let(:customer) { create(:customer, tag_list: "one, two, three") } + let(:tag_list) { ["one", "two", "three"] } + let(:customer) { create(:customer, tag_list: tag_list) } let!(:tag_rule) { create(:tag_rule, enterprise: customer.enterprise, preferred_customer_tags: "two") } it "serializes a customer with tags" do tag_rule_mapping = TagRule.mapping_for(Enterprise.where(id: customer.enterprise_id)) - serializer = Api::Admin::CustomerSerializer.new customer, tag_rule_mapping: tag_rule_mapping + customer_tag_list = { customer.id => tag_list } + serializer = Api::Admin::CustomerSerializer.new customer, + tag_rule_mapping: tag_rule_mapping, + customer_tags: customer_tag_list result = JSON.parse(serializer.to_json) expect(result['email']).to eq customer.email tags = result['tags'] @@ -27,4 +31,11 @@ describe Api::Admin::CustomerSerializer do expect(tag['rules']).to be nil end end + + it 'serializes a customer without customer_tags' do + serializer = Api::Admin::CustomerSerializer.new customer + result = JSON.parse(serializer.to_json) + + expect(result['tags'].first['text']).to eq tag_list.first + end end diff --git a/spec/serializers/api/cached_enterprise_serializer_spec.rb b/spec/serializers/api/cached_enterprise_serializer_spec.rb index c4e5624fa8..6bcaeffdc3 100644 --- a/spec/serializers/api/cached_enterprise_serializer_spec.rb +++ b/spec/serializers/api/cached_enterprise_serializer_spec.rb @@ -53,17 +53,9 @@ describe Api::CachedEnterpriseSerializer do instance_double(OpenFoodNetwork::EnterpriseInjectionData, active_distributor_ids: []) end - it 'does not duplicate properties' do + it 'does not serialize distributed properties' do properties = cached_enterprise_serializer.distributed_properties - expect(properties.map(&:presentation)).to eq([property.presentation]) - end - - it 'fetches producer properties' do - distributed_producer_properties = cached_enterprise_serializer - .distributed_producer_properties - - expect(distributed_producer_properties.map(&:presentation)) - .to eq(producer.producer_properties.map(&:property).map(&:presentation)) + expect(properties).to eq [] end end diff --git a/spec/services/order_cycle_form_spec.rb b/spec/services/order_cycle_form_spec.rb index f264592763..a085961e26 100644 --- a/spec/services/order_cycle_form_spec.rb +++ b/spec/services/order_cycle_form_spec.rb @@ -1,4 +1,5 @@ require 'spec_helper' +require 'order_management/subscriptions/proxy_order_syncer' describe OrderCycleForm do describe "save" do @@ -68,10 +69,10 @@ describe OrderCycleForm do context "where I manage the order_cycle's coordinator" do let(:form) { OrderCycleForm.new(coordinated_order_cycle, params, user) } - let(:syncer_mock) { instance_double(OpenFoodNetwork::ProxyOrderSyncer, sync!: true) } + let(:syncer_mock) { instance_double(OrderManagement::Subscriptions::ProxyOrderSyncer, sync!: true) } before do - allow(OpenFoodNetwork::ProxyOrderSyncer).to receive(:new) { syncer_mock } + allow(OrderManagement::Subscriptions::ProxyOrderSyncer).to receive(:new) { syncer_mock } end context "and I add an schedule that I own, and remove another that I own" do diff --git a/spec/services/order_payment_finder_spec.rb b/spec/services/order_payment_finder_spec.rb new file mode 100644 index 0000000000..3d71d9a706 --- /dev/null +++ b/spec/services/order_payment_finder_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe OrderPaymentFinder do + let(:order) { create(:order_with_distributor) } + let(:finder) { OrderPaymentFinder.new(order) } + + context "when order has several non pending payments" do + let!(:failed_payment) { create(:payment, order: order, state: 'failed') } + let!(:complete_payment) { create(:payment, order: order, state: 'completed') } + + it "#last_payment returns the last payment" do + expect(finder.last_payment).to eq complete_payment + end + + it "#last_pending_payment returns nil" do + expect(finder.last_pending_payment).to be nil + end + end + + context "when order has a pending payment and a non pending payment" do + let!(:processing_payment) { create(:payment, order: order, state: 'processing') } + let!(:failed_payment) { create(:payment, order: order, state: 'failed') } + + it "#last_payment returns the last payment" do + expect(finder.last_payment).to eq failed_payment + end + + it "#last_pending_payment returns the pending payment" do + # a payment in the processing state is a pending payment + expect(finder.last_pending_payment).to eq processing_payment + end + + context "and an extra last pending payment" do + let!(:pending_payment) { create(:payment, order: order, state: 'pending') } + + it "#last_payment returns the last payment" do + expect(finder.last_payment).to eq pending_payment + end + + it "#last_pending_payment returns the pending payment" do + expect(finder.last_pending_payment).to eq pending_payment + end + end + end +end diff --git a/spec/services/permissions/order_spec.rb b/spec/services/permissions/order_spec.rb index d60d6968e2..88e3666aca 100644 --- a/spec/services/permissions/order_spec.rb +++ b/spec/services/permissions/order_spec.rb @@ -47,6 +47,18 @@ module Permissions it "should let me see the order" do expect(permissions.visible_orders).to include order end + + context "with search params" do + let(:search_params) { { completed_at_gt: Time.zone.now.yesterday.strftime('%Y-%m-%d') } } + let(:permissions) { Permissions::Order.new(user, search_params) } + + it "only returns completed, non-cancelled orders within search filter range" do + expect(permissions.visible_orders).to include order_completed + expect(permissions.visible_orders).to_not include order_cancelled + expect(permissions.visible_orders).to_not include order_cart + expect(permissions.visible_orders).to_not include order_from_last_year + end + end end context "as a producer which has granted P-OC to the distributor of an order" do @@ -71,18 +83,6 @@ module Permissions expect(permissions.visible_orders).to_not include order end end - - context "with search params" do - let(:search_params) { { completed_at_gt: Time.zone.now.yesterday.strftime('%Y-%m-%d') } } - let(:permissions) { Permissions::Order.new(user, search_params) } - - it "only returns completed, non-cancelled orders within search filter range" do - expect(permissions.visible_orders).to include order_completed - expect(permissions.visible_orders).to_not include order_cancelled - expect(permissions.visible_orders).to_not include order_cart - expect(permissions.visible_orders).to_not include order_from_last_year - end - end end context "as an enterprise that is a distributor in the order cycle, but not the distributor of the order" do diff --git a/spec/services/subscription_estimator_spec.rb b/spec/services/subscription_estimator_spec.rb deleted file mode 100644 index 5230057888..0000000000 --- a/spec/services/subscription_estimator_spec.rb +++ /dev/null @@ -1,129 +0,0 @@ -describe SubscriptionEstimator do - describe "estimating prices for subscription line items" do - let!(:subscription) { create(:subscription, with_items: true) } - let!(:sli1) { subscription.subscription_line_items.first } - let!(:sli2) { subscription.subscription_line_items.second } - let!(:sli3) { subscription.subscription_line_items.third } - let(:estimator) { SubscriptionEstimator.new(subscription) } - - before do - sli1.update_attributes(price_estimate: 4.0) - sli2.update_attributes(price_estimate: 5.0) - sli3.update_attributes(price_estimate: 6.0) - sli1.variant.update_attributes(price: 1.0) - sli2.variant.update_attributes(price: 2.0) - sli3.variant.update_attributes(price: 3.0) - - # Simulating assignment of attrs from params - sli1.assign_attributes(price_estimate: 7.0) - sli2.assign_attributes(price_estimate: 8.0) - sli3.assign_attributes(price_estimate: 9.0) - end - - context "when a insufficient information exists to calculate price estimates" do - before do - # This might be because a shop has not been assigned yet, or no - # current or future order cycles exist for the schedule - allow(estimator).to receive(:fee_calculator) { nil } - end - - it "resets the price estimates for all items" do - estimator.estimate! - expect(sli1.price_estimate).to eq 4.0 - expect(sli2.price_estimate).to eq 5.0 - expect(sli3.price_estimate).to eq 6.0 - end - end - - context "when sufficient information to calculate price estimates exists" do - let(:fee_calculator) { instance_double(OpenFoodNetwork::EnterpriseFeeCalculator) } - - before do - allow(estimator).to receive(:fee_calculator) { fee_calculator } - allow(fee_calculator).to receive(:indexed_fees_for).with(sli1.variant) { 1.0 } - allow(fee_calculator).to receive(:indexed_fees_for).with(sli2.variant) { 0.0 } - allow(fee_calculator).to receive(:indexed_fees_for).with(sli3.variant) { 3.0 } - end - - context "when no variant overrides apply" do - it "recalculates price_estimates based on variant prices and associated fees" do - estimator.estimate! - expect(sli1.price_estimate).to eq 2.0 - expect(sli2.price_estimate).to eq 2.0 - expect(sli3.price_estimate).to eq 6.0 - end - end - - context "when variant overrides apply" do - let!(:override1) { create(:variant_override, hub: subscription.shop, variant: sli1.variant, price: 1.2) } - let!(:override2) { create(:variant_override, hub: subscription.shop, variant: sli2.variant, price: 2.3) } - - it "recalculates price_estimates based on override prices and associated fees" do - estimator.estimate! - expect(sli1.price_estimate).to eq 2.2 - expect(sli2.price_estimate).to eq 2.3 - expect(sli3.price_estimate).to eq 6.0 - end - end - end - end - - describe "updating estimates for shipping and payment fees" do - let(:subscription) { create(:subscription, with_items: true, payment_method: payment_method, shipping_method: shipping_method) } - let!(:sli1) { subscription.subscription_line_items.first } - let!(:sli2) { subscription.subscription_line_items.second } - let!(:sli3) { subscription.subscription_line_items.third } - let(:estimator) { SubscriptionEstimator.new(subscription) } - - before do - allow(estimator).to receive(:assign_price_estimates) - sli1.update_attributes(price_estimate: 4.0) - sli2.update_attributes(price_estimate: 5.0) - sli3.update_attributes(price_estimate: 6.0) - end - - context "using flat rate calculators" do - let(:shipping_method) { create(:shipping_method, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 12.34)) } - let(:payment_method) { create(:payment_method, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 9.12)) } - - it "calculates fees based on the rates provided" do - estimator.estimate! - expect(subscription.shipping_fee_estimate.to_f).to eq 12.34 - expect(subscription.payment_fee_estimate.to_f).to eq 9.12 - end - end - - context "using flat percent item total calculators" do - let(:shipping_method) { create(:shipping_method, calculator: Spree::Calculator::FlatPercentItemTotal.new(preferred_flat_percent: 10)) } - let(:payment_method) { create(:payment_method, calculator: Spree::Calculator::FlatPercentItemTotal.new(preferred_flat_percent: 20)) } - - it "calculates fees based on the estimated item total and percentage provided" do - estimator.estimate! - expect(subscription.shipping_fee_estimate.to_f).to eq 1.5 - expect(subscription.payment_fee_estimate.to_f).to eq 3.0 - end - end - - context "using flat percent per item calculators" do - let(:shipping_method) { create(:shipping_method, calculator: Calculator::FlatPercentPerItem.new(preferred_flat_percent: 5)) } - let(:payment_method) { create(:payment_method, calculator: Calculator::FlatPercentPerItem.new(preferred_flat_percent: 10)) } - - it "calculates fees based on the estimated item prices and percentage provided" do - estimator.estimate! - expect(subscription.shipping_fee_estimate.to_f).to eq 0.75 - expect(subscription.payment_fee_estimate.to_f).to eq 1.5 - end - end - - context "using per item calculators" do - let(:shipping_method) { create(:shipping_method, calculator: Spree::Calculator::PerItem.new(preferred_amount: 1.2)) } - let(:payment_method) { create(:payment_method, calculator: Spree::Calculator::PerItem.new(preferred_amount: 0.3)) } - - it "calculates fees based on the number of items and rate provided" do - estimator.estimate! - expect(subscription.shipping_fee_estimate.to_f).to eq 3.6 - expect(subscription.payment_fee_estimate.to_f).to eq 0.9 - end - end - end -end diff --git a/spec/services/subscription_form_spec.rb b/spec/services/subscription_form_spec.rb deleted file mode 100644 index ae27363c8a..0000000000 --- a/spec/services/subscription_form_spec.rb +++ /dev/null @@ -1,97 +0,0 @@ -require 'spec_helper' - -describe SubscriptionForm do - describe "creating a new subscription" do - let!(:shop) { create(:distributor_enterprise) } - let!(:customer) { create(:customer, enterprise: shop) } - let!(:product1) { create(:product, supplier: shop) } - let!(:product2) { create(:product, supplier: shop) } - let!(:product3) { create(:product, supplier: shop) } - let!(:variant1) { create(:variant, product: product1, unit_value: '100', price: 12.00, option_values: []) } - let!(:variant2) { create(:variant, product: product2, unit_value: '1000', price: 6.00, option_values: []) } - let!(:variant3) { create(:variant, product: product2, unit_value: '1000', price: 2.50, option_values: [], on_hand: 1) } - let!(:enterprise_fee) { create(:enterprise_fee, amount: 1.75) } - let!(:order_cycle1) { create(:simple_order_cycle, coordinator: shop, orders_open_at: 9.days.ago, orders_close_at: 2.days.ago) } - let!(:order_cycle2) { create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.days.ago, orders_close_at: 5.days.from_now) } - let!(:order_cycle3) { create(:simple_order_cycle, coordinator: shop, orders_open_at: 5.days.from_now, orders_close_at: 12.days.from_now) } - let!(:order_cycle4) { create(:simple_order_cycle, coordinator: shop, orders_open_at: 12.days.from_now, orders_close_at: 19.days.from_now) } - let!(:outgoing_exchange1) { order_cycle1.exchanges.create(sender: shop, receiver: shop, variants: [variant1, variant2, variant3], enterprise_fees: [enterprise_fee]) } - let!(:outgoing_exchange2) { order_cycle2.exchanges.create(sender: shop, receiver: shop, variants: [variant1, variant2, variant3], enterprise_fees: [enterprise_fee]) } - let!(:outgoing_exchange3) { order_cycle3.exchanges.create(sender: shop, receiver: shop, variants: [variant1, variant3], enterprise_fees: []) } - let!(:outgoing_exchange4) { order_cycle4.exchanges.create(sender: shop, receiver: shop, variants: [variant1, variant2, variant3], enterprise_fees: [enterprise_fee]) } - let!(:schedule) { create(:schedule, order_cycles: [order_cycle1, order_cycle2, order_cycle3, order_cycle4]) } - let!(:payment_method) { create(:payment_method, distributors: [shop]) } - let!(:shipping_method) { create(:shipping_method, distributors: [shop]) } - let!(:address) { create(:address) } - let(:subscription) { Subscription.new } - - let!(:params) { - { - shop_id: shop.id, - customer_id: customer.id, - schedule_id: schedule.id, - bill_address_attributes: address.clone.attributes, - ship_address_attributes: address.clone.attributes, - payment_method_id: payment_method.id, - shipping_method_id: shipping_method.id, - begins_at: 4.days.ago, - ends_at: 14.days.from_now, - subscription_line_items_attributes: [ - { variant_id: variant1.id, quantity: 1, price_estimate: 7.0 }, - { variant_id: variant2.id, quantity: 2, price_estimate: 8.0 }, - { variant_id: variant3.id, quantity: 3, price_estimate: 9.0 } - ] - } - } - - let(:form) { SubscriptionForm.new(subscription, params) } - - it "creates orders for each order cycle in the schedule" do - expect(form.save).to be true - - expect(subscription.proxy_orders.count).to be 2 - expect(subscription.subscription_line_items.count).to be 3 - expect(subscription.subscription_line_items[0].price_estimate).to eq 13.75 - expect(subscription.subscription_line_items[1].price_estimate).to eq 7.75 - expect(subscription.subscription_line_items[2].price_estimate).to eq 4.25 - - # This order cycle has already closed, so no order is initialized - proxy_order1 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle1.id) - expect(proxy_order1).to be nil - - # Currently open order cycle, closing after begins_at and before ends_at - proxy_order2 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle2.id) - expect(proxy_order2).to be_a ProxyOrder - order2 = proxy_order2.initialise_order! - expect(order2.line_items.count).to eq 3 - expect(order2.line_items.find_by(variant_id: variant3.id).quantity).to be 3 - expect(order2.shipments.count).to eq 1 - expect(order2.shipments.first.shipping_method).to eq shipping_method - expect(order2.payments.count).to eq 1 - expect(order2.payments.first.payment_method).to eq payment_method - expect(order2.payments.first.state).to eq 'checkout' - expect(order2.total).to eq 42 - expect(order2.completed?).to be false - - # Future order cycle, closing after begins_at and before ends_at - # Adds line items for variants that aren't yet available from the order cycle - proxy_order3 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle3.id) - expect(proxy_order3).to be_a ProxyOrder - order3 = proxy_order3.initialise_order! - expect(order3).to be_a Spree::Order - expect(order3.line_items.count).to eq 3 - expect(order2.line_items.find_by(variant_id: variant3.id).quantity).to be 3 - expect(order3.shipments.count).to eq 1 - expect(order3.shipments.first.shipping_method).to eq shipping_method - expect(order3.payments.count).to eq 1 - expect(order3.payments.first.payment_method).to eq payment_method - expect(order3.payments.first.state).to eq 'checkout' - expect(order3.total).to eq 31.50 - expect(order3.completed?).to be false - - # Future order cycle closing after ends_at - proxy_order4 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle4.id) - expect(proxy_order4).to be nil - end - end -end diff --git a/spec/services/subscription_validator_spec.rb b/spec/services/subscription_validator_spec.rb deleted file mode 100644 index bdcd14bea5..0000000000 --- a/spec/services/subscription_validator_spec.rb +++ /dev/null @@ -1,470 +0,0 @@ -require "spec_helper" - -describe SubscriptionValidator do - let(:owner) { create(:user) } - let(:shop) { create(:enterprise, name: "Shop", owner: owner) } - - describe "delegation" do - let(:subscription) { create(:subscription, shop: shop) } - let(:validator) { SubscriptionValidator.new(subscription) } - - it "delegates to subscription" do - expect(validator.shop).to eq subscription.shop - expect(validator.customer).to eq subscription.customer - expect(validator.schedule).to eq subscription.schedule - expect(validator.shipping_method).to eq subscription.shipping_method - expect(validator.payment_method).to eq subscription.payment_method - expect(validator.bill_address).to eq subscription.bill_address - expect(validator.ship_address).to eq subscription.ship_address - expect(validator.begins_at).to eq subscription.begins_at - expect(validator.ends_at).to eq subscription.ends_at - end - end - - describe "validations" do - let(:subscription_stubs) do - { - shop: shop, - customer: true, - schedule: true, - shipping_method: true, - payment_method: true, - bill_address: true, - ship_address: true, - begins_at: true, - ends_at: true, - } - end - - let(:validation_stubs) do - { - shipping_method_allowed?: true, - payment_method_allowed?: true, - payment_method_type_allowed?: true, - ends_at_after_begins_at?: true, - customer_allowed?: true, - schedule_allowed?: true, - credit_card_ok?: true, - subscription_line_items_present?: true, - requested_variants_available?: true - } - end - - let(:subscription) { instance_double(Subscription, subscription_stubs) } - let(:validator) { SubscriptionValidator.new(subscription) } - - def stub_validations(validator, methods) - methods.each do |name, value| - allow(validator).to receive(name) { value } - end - end - - describe "shipping method validation" do - let(:subscription) { instance_double(Subscription, subscription_stubs.except(:shipping_method)) } - before { stub_validations(validator, validation_stubs.except(:shipping_method_allowed?)) } - - context "when no shipping method is present" do - before { expect(subscription).to receive(:shipping_method).at_least(:once) { nil } } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:shipping_method]).to_not be_empty - end - end - - context "when a shipping method is present" do - let(:shipping_method) { instance_double(Spree::ShippingMethod, distributors: [shop]) } - before { expect(subscription).to receive(:shipping_method).at_least(:once) { shipping_method } } - - context "and the shipping method is not associated with the shop" do - before { allow(shipping_method).to receive(:distributors) { [double(:enterprise)] } } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:shipping_method]).to_not be_empty - end - end - - context "and the shipping method is associated with the shop" do - before { allow(shipping_method).to receive(:distributors) { [shop] } } - - it "returns true" do - expect(validator.valid?).to be true - expect(validator.errors[:shipping_method]).to be_empty - end - end - end - end - - describe "payment method validation" do - let(:subscription) { instance_double(Subscription, subscription_stubs.except(:payment_method)) } - before { stub_validations(validator, validation_stubs.except(:payment_method_allowed?)) } - - context "when no payment method is present" do - before { expect(subscription).to receive(:payment_method).at_least(:once) { nil } } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:payment_method]).to_not be_empty - end - end - - context "when a payment method is present" do - let(:payment_method) { instance_double(Spree::PaymentMethod, distributors: [shop]) } - before { expect(subscription).to receive(:payment_method).at_least(:once) { payment_method } } - - context "and the payment method is not associated with the shop" do - before { allow(payment_method).to receive(:distributors) { [double(:enterprise)] } } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:payment_method]).to_not be_empty - end - end - - context "and the payment method is associated with the shop" do - before { allow(payment_method).to receive(:distributors) { [shop] } } - - it "returns true" do - expect(validator.valid?).to be true - expect(validator.errors[:payment_method]).to be_empty - end - end - end - end - - describe "payment method type validation" do - let(:subscription) { instance_double(Subscription, subscription_stubs.except(:payment_method)) } - before { stub_validations(validator, validation_stubs.except(:payment_method_type_allowed?)) } - - context "when a payment method is present" do - let(:payment_method) { instance_double(Spree::PaymentMethod, distributors: [shop]) } - before { expect(subscription).to receive(:payment_method).at_least(:once) { payment_method } } - - context "and the payment method type is not in the approved list" do - before { allow(payment_method).to receive(:type) { "Blah" } } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:payment_method]).to_not be_empty - end - end - - context "and the payment method is in the approved list" do - let(:approved_type) { Subscription::ALLOWED_PAYMENT_METHOD_TYPES.first } - before { allow(payment_method).to receive(:type) { approved_type } } - - it "returns true" do - expect(validator.valid?).to be true - expect(validator.errors[:payment_method]).to be_empty - end - end - end - end - - describe "dates" do - let(:subscription) { instance_double(Subscription, subscription_stubs.except(:begins_at, :ends_at)) } - before { stub_validations(validator, validation_stubs.except(:ends_at_after_begins_at?)) } - before { expect(subscription).to receive(:begins_at).at_least(:once) { begins_at } } - - context "when no begins_at is present" do - let(:begins_at) { nil } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:begins_at]).to_not be_empty - end - end - - context "when a start date is present" do - let(:begins_at) { Time.zone.today } - before { expect(subscription).to receive(:ends_at).at_least(:once) { ends_at } } - - context "when no ends_at is present" do - let(:ends_at) { nil } - - it "returns true" do - expect(validator.valid?).to be true - expect(validator.errors[:ends_at]).to be_empty - end - end - - context "when ends_at is equal to begins_at" do - let(:ends_at) { Time.zone.today } - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:ends_at]).to_not be_empty - end - end - - context "when ends_at is before begins_at" do - let(:ends_at) { Time.zone.today - 1.day } - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:ends_at]).to_not be_empty - end - end - - context "when ends_at is after begins_at" do - let(:ends_at) { Time.zone.today + 1.day } - it "adds an error and returns false" do - expect(validator.valid?).to be true - expect(validator.errors[:ends_at]).to be_empty - end - end - end - end - - describe "addresses" do - before { stub_validations(validator, validation_stubs) } - let(:subscription) { instance_double(Subscription, subscription_stubs.except(:bill_address, :ship_address)) } - before { expect(subscription).to receive(:bill_address).at_least(:once) { bill_address } } - before { expect(subscription).to receive(:ship_address).at_least(:once) { ship_address } } - - context "when bill_address and ship_address are not present" do - let(:bill_address) { nil } - let(:ship_address) { nil } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:bill_address]).to_not be_empty - expect(validator.errors[:ship_address]).to_not be_empty - end - end - - context "when bill_address and ship_address are present" do - let(:bill_address) { instance_double(Spree::Address) } - let(:ship_address) { instance_double(Spree::Address) } - - it "returns true" do - expect(validator.valid?).to be true - expect(validator.errors[:bill_address]).to be_empty - expect(validator.errors[:ship_address]).to be_empty - end - end - end - - describe "customer" do - let(:subscription) { instance_double(Subscription, subscription_stubs.except(:customer)) } - before { stub_validations(validator, validation_stubs.except(:customer_allowed?)) } - before { expect(subscription).to receive(:customer).at_least(:once) { customer } } - - context "when no customer is present" do - let(:customer) { nil } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:customer]).to_not be_empty - end - end - - context "when a customer is present" do - let(:customer) { instance_double(Customer) } - - context "and the customer is not associated with the shop" do - before { allow(customer).to receive(:enterprise) { double(:enterprise) } } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:customer]).to_not be_empty - end - end - - context "and the customer is associated with the shop" do - before { allow(customer).to receive(:enterprise) { shop } } - - it "returns true" do - expect(validator.valid?).to be true - expect(validator.errors[:customer]).to be_empty - end - end - end - end - - describe "schedule" do - let(:subscription) { instance_double(Subscription, subscription_stubs.except(:schedule)) } - before { stub_validations(validator, validation_stubs.except(:schedule_allowed?)) } - before { expect(subscription).to receive(:schedule).at_least(:once) { schedule } } - - context "when no schedule is present" do - let(:schedule) { nil } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:schedule]).to_not be_empty - end - end - - context "when a schedule is present" do - let(:schedule) { instance_double(Schedule) } - - context "and the schedule is not associated with the shop" do - before { allow(schedule).to receive(:coordinators) { [double(:enterprise)] } } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:schedule]).to_not be_empty - end - end - - context "and the schedule is associated with the shop" do - before { allow(schedule).to receive(:coordinators) { [shop] } } - - it "returns true" do - expect(validator.valid?).to be true - expect(validator.errors[:schedule]).to be_empty - end - end - end - end - - describe "credit card" do - let(:subscription) { instance_double(Subscription, subscription_stubs.except(:payment_method)) } - before { stub_validations(validator, validation_stubs.except(:credit_card_ok?)) } - before { expect(subscription).to receive(:payment_method).at_least(:once) { payment_method } } - - context "when using a Check payment method" do - let(:payment_method) { instance_double(Spree::PaymentMethod, type: "Spree::PaymentMethod::Check") } - - it "returns true" do - expect(validator.valid?).to be true - expect(validator.errors[:subscription_line_items]).to be_empty - end - end - - context "when using the StripeConnect payment gateway" do - let(:payment_method) { instance_double(Spree::PaymentMethod, type: "Spree::Gateway::StripeConnect") } - before { expect(subscription).to receive(:customer).at_least(:once) { customer } } - - context "when the customer does not allow charges" do - let(:customer) { instance_double(Customer, allow_charges: false) } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:payment_method]).to_not be_empty - end - end - - context "when the customer allows charges" do - let(:customer) { instance_double(Customer, allow_charges: true) } - - context "and the customer is not associated with a user" do - before { allow(customer).to receive(:user) { nil } } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:payment_method]).to_not be_empty - end - end - - context "and the customer is associated with a user" do - before { expect(customer).to receive(:user).once { user } } - - context "and the user has no default card set" do - let(:user) { instance_double(Spree::User, default_card: nil) } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:payment_method]).to_not be_empty - end - end - - context "and the user has a default card set" do - let(:user) { instance_double(Spree::User, default_card: 'some card') } - - it "returns true" do - expect(validator.valid?).to be true - expect(validator.errors[:payment_method]).to be_empty - end - end - end - end - end - end - - describe "subscription line items" do - let(:subscription) { instance_double(Subscription, subscription_stubs) } - before { stub_validations(validator, validation_stubs.except(:subscription_line_items_present?)) } - before { expect(subscription).to receive(:subscription_line_items).at_least(:once) { subscription_line_items } } - - context "when no subscription line items are present" do - let(:subscription_line_items) { [] } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:subscription_line_items]).to_not be_empty - end - end - - context "when subscription line items are present but they are all marked for destruction" do - let(:subscription_line_item1) { instance_double(SubscriptionLineItem, marked_for_destruction?: true) } - let(:subscription_line_items) { [subscription_line_item1] } - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:subscription_line_items]).to_not be_empty - end - end - - context "when subscription line items are present and some and not marked for destruction" do - let(:subscription_line_item1) { instance_double(SubscriptionLineItem, marked_for_destruction?: true) } - let(:subscription_line_item2) { instance_double(SubscriptionLineItem, marked_for_destruction?: false) } - let(:subscription_line_items) { [subscription_line_item1, subscription_line_item2] } - - it "returns true" do - expect(validator.valid?).to be true - expect(validator.errors[:subscription_line_items]).to be_empty - end - end - end - - describe "variant availability" do - let(:subscription) { instance_double(Subscription, subscription_stubs) } - before { stub_validations(validator, validation_stubs.except(:requested_variants_available?)) } - before { expect(subscription).to receive(:subscription_line_items).at_least(:once) { subscription_line_items } } - - context "when no subscription line items are present" do - let(:subscription_line_items) { [] } - - it "returns true" do - expect(validator.valid?).to be true - expect(validator.errors[:subscription_line_items]).to be_empty - end - end - - context "when subscription line items are present" do - let(:variant1) { instance_double(Spree::Variant, id: 1) } - let(:variant2) { instance_double(Spree::Variant, id: 2) } - let(:subscription_line_item1) { instance_double(SubscriptionLineItem, variant: variant1) } - let(:subscription_line_item2) { instance_double(SubscriptionLineItem, variant: variant2) } - let(:subscription_line_items) { [subscription_line_item1] } - - context "but some variants are unavailable" do - let(:product) { instance_double(Spree::Product, name: "some_name") } - - before do - allow(validator).to receive(:available_variant_ids) { [variant2.id] } - allow(variant1).to receive(:product) { product } - allow(variant1).to receive(:full_name) { "some name" } - end - - it "adds an error and returns false" do - expect(validator.valid?).to be false - expect(validator.errors[:subscription_line_items]).to_not be_empty - end - end - - context "and all requested variants are available" do - before do - allow(validator).to receive(:available_variant_ids) { [variant1.id, variant2.id] } - end - - it "returns true" do - expect(validator.valid?).to be true - expect(validator.errors[:subscription_line_items]).to be_empty - end - end - end - end - end -end diff --git a/spec/services/subscription_variants_service_spec.rb b/spec/services/subscription_variants_service_spec.rb deleted file mode 100644 index 31d0ff4ca7..0000000000 --- a/spec/services/subscription_variants_service_spec.rb +++ /dev/null @@ -1,130 +0,0 @@ -require "spec_helper" - -describe SubscriptionVariantsService do - describe "variant eligibility for subscription" do - let!(:shop) { create(:distributor_enterprise) } - let!(:producer) { create(:supplier_enterprise) } - let!(:product) { create(:product, supplier: producer) } - let!(:variant) { product.variants.first } - - let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) } - let!(:subscription) { create(:subscription, shop: shop, schedule: schedule) } - let!(:subscription_line_item) do - create(:subscription_line_item, subscription: subscription, variant: variant) - end - - let(:current_order_cycle) do - create(:simple_order_cycle, coordinator: shop, orders_open_at: 1.week.ago, - orders_close_at: 1.week.from_now) - end - - let(:future_order_cycle) do - create(:simple_order_cycle, coordinator: shop, orders_open_at: 1.week.from_now, - orders_close_at: 2.weeks.from_now) - end - - let(:past_order_cycle) do - create(:simple_order_cycle, coordinator: shop, orders_open_at: 2.weeks.ago, - orders_close_at: 1.week.ago) - end - - let!(:order_cycle) { current_order_cycle } - - context "if the shop is the supplier for the product" do - let!(:producer) { shop } - - it "is eligible" do - expect(described_class.eligible_variants(shop)).to include(variant) - end - end - - context "if the supplier is permitted for the shop" do - let!(:enterprise_relationship) { create(:enterprise_relationship, child: shop, parent: product.supplier, permissions_list: [:add_to_order_cycle]) } - - it "is eligible" do - expect(described_class.eligible_variants(shop)).to include(variant) - end - end - - context "if the variant is involved in an exchange" do - let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) } - let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) } - - context "if it is an incoming exchange where the shop is the receiver" do - let!(:incoming_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: true, variants: [variant]) } - - it "is not eligible" do - expect(described_class.eligible_variants(shop)).to_not include(variant) - end - end - - context "if it is an outgoing exchange where the shop is the receiver" do - let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: false, variants: [variant]) } - - context "if the order cycle is currently open" do - let!(:order_cycle) { current_order_cycle } - - it "is eligible" do - expect(described_class.eligible_variants(shop)).to include(variant) - end - end - - context "if the order cycle opens in the future" do - let!(:order_cycle) { future_order_cycle } - - it "is eligible" do - expect(described_class.eligible_variants(shop)).to include(variant) - end - end - - context "if the order cycle closed in the past" do - let!(:order_cycle) { past_order_cycle } - - it "is eligible" do - expect(described_class.eligible_variants(shop)).to include(variant) - end - end - end - end - - context "if the variant is unrelated" do - it "is not eligible" do - expect(described_class.eligible_variants(shop)).to_not include(variant) - end - end - end - - describe "checking if variant in open and upcoming order cycles" do - let!(:shop) { create(:enterprise) } - let!(:product) { create(:product) } - let!(:variant) { product.variants.first } - let!(:schedule) { create(:schedule) } - - context "if the variant is involved in an exchange" do - let!(:order_cycle) { create(:simple_order_cycle, coordinator: shop) } - let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) } - - context "if it is an incoming exchange where the shop is the receiver" do - let!(:incoming_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: true, variants: [variant]) } - - it "is is false" do - expect(described_class).not_to be_in_open_and_upcoming_order_cycles(shop, schedule, variant) - end - end - - context "if it is an outgoing exchange where the shop is the receiver" do - let!(:outgoing_exchange) { order_cycle.exchanges.create(sender: product.supplier, receiver: shop, incoming: false, variants: [variant]) } - - it "is true" do - expect(described_class).to be_in_open_and_upcoming_order_cycles(shop, schedule, variant) - end - end - end - - context "if the variant is unrelated" do - it "is false" do - expect(described_class).to_not be_in_open_and_upcoming_order_cycles(shop, schedule, variant) - end - end - end -end diff --git a/spec/services/subscriptions_count_spec.rb b/spec/services/subscriptions_count_spec.rb deleted file mode 100644 index 2446bcc8bf..0000000000 --- a/spec/services/subscriptions_count_spec.rb +++ /dev/null @@ -1,34 +0,0 @@ -describe SubscriptionsCount do - let(:oc1) { create(:simple_order_cycle) } - let(:oc2) { create(:simple_order_cycle) } - let(:subscriptions_count) { SubscriptionsCount.new(order_cycles) } - - describe "#for" do - context "when the collection has not been set" do - let(:order_cycles) { nil } - it "returns 0" do - expect(subscriptions_count.for(oc1.id)).to eq 0 - end - end - - context "when the collection has been set" do - let(:order_cycles) { OrderCycle.where(id: [oc1]) } - let!(:po1) { create(:proxy_order, order_cycle: oc1) } - let!(:po2) { create(:proxy_order, order_cycle: oc1) } - let!(:po3) { create(:proxy_order, order_cycle: oc2) } - - context "but the requested id is not present in the list of order cycles provided" do - it "returns 0" do - # Note that po3 applies to oc2, but oc2 in not in the collection - expect(subscriptions_count.for(oc2.id)).to eq 0 - end - end - - context "and the requested id is present in the list of order cycles provided" do - it "returns a count of active proxy orders associated with the requested order cycle" do - expect(subscriptions_count.for(oc1.id)).to eq 2 - end - end - end - end -end diff --git a/spec/services/variant_overrides_indexed_spec.rb b/spec/services/variant_overrides_indexed_spec.rb new file mode 100644 index 0000000000..15af405683 --- /dev/null +++ b/spec/services/variant_overrides_indexed_spec.rb @@ -0,0 +1,61 @@ +require 'spec_helper' + +describe VariantOverridesIndexed do + subject(:variant_overrides) { described_class.new([variant.id],[distributor.id]) } + + let(:distributor) { create(:distributor_enterprise) } + let(:variant) { create(:variant) } + let!(:variant_override) do + create( + :variant_override, + hub: vo_distributor, + variant: vo_variant, + ) + end + + describe '#indexed' do + let(:result) { variant_overrides.indexed } + + context 'when variant overrides exist for variants of specified variants' do + let(:vo_variant) { variant } + + context 'when variant overrides apply to one of the specified distributors' do + let(:vo_distributor) { distributor } + + it 'they are included in the mapping' do + expect(result).to eq( + distributor.id => { variant => variant_override } + ) + end + end + + context 'when variant overrides don\'t apply to one of the specified distributors' do + let(:vo_distributor) { create(:distributor_enterprise) } + + it 'they are not included in the mapping' do + expect(result).to eq({}) + end + end + end + + context 'when variant overrides exist for other variants' do + let(:vo_variant) { create(:variant) } + + context 'when variant overrides apply to one of the specified distributors' do + let(:vo_distributor) { distributor } + + it 'they are not included in the mapping' do + expect(result).to eq({}) + end + end + + context 'when variant overrides don\'t apply to one of the specified distributors' do + let(:vo_distributor) { create(:distributor_enterprise) } + + it 'they are not included in the mapping' do + expect(result).to eq({}) + end + end + end + end +end