diff --git a/.codeclimate.yml b/.codeclimate.yml index 3880986cad..1892bc1fb8 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -16,6 +16,10 @@ plugins: enabled: false PropertySortOrder: enabled: false + StringQuotes: + enabled: false + DeclarationOrder: + enabled: false duplication: enabled: true exclude_patterns: diff --git a/.rubocop_manual_todo.yml b/.rubocop_manual_todo.yml index e55124201f..ace78ed248 100644 --- a/.rubocop_manual_todo.yml +++ b/.rubocop_manual_todo.yml @@ -142,7 +142,6 @@ Layout/LineLength: - spec/controllers/api/product_images_controller_spec.rb - spec/controllers/api/products_controller_spec.rb - spec/controllers/api/promo_images_controller_spec.rb - - spec/controllers/api/shipments_controller_spec.rb - spec/controllers/api/variants_controller_spec.rb - spec/controllers/cart_controller_spec.rb - spec/controllers/checkout_controller_spec.rb diff --git a/.rubocop_styleguide.yml b/.rubocop_styleguide.yml index 9615d7b9ba..eb73f8a511 100644 --- a/.rubocop_styleguide.yml +++ b/.rubocop_styleguide.yml @@ -5,7 +5,7 @@ # rubocop locally, the default configuration file `.rubocop.yml` loads # our "todo lists" to ignore all current violations. AllCops: - TargetRailsVersion: 3.2 + TargetRailsVersion: 4.0 Exclude: - 'bin/**/*' - 'db/**/*' @@ -20,9 +20,6 @@ AllCops: # # Cop settings that have been agreed upon by the OFN community -Rails: - Enabled: true - Style/Documentation: Enabled: false @@ -61,24 +58,6 @@ Lint/UselessAssignment: Exclude: - spec/**/* -# AFAIK, there is no good alternative to dynamic matchers until we upgrade -# to Rails 4 and can use #find_by. If there is a better approach, let's do it. -Rails/DynamicFindBy: - Enabled: false - -# Same as above, #find_by is not available until Rails 4 -Rails/FindBy: - Enabled: false - -# Same as above, #update! is not available until Rails 4 -Rails/ActiveRecordAliases: - Enabled: false - -# This should be the programmer's discretion, perhaps we should review all of -# the uses of it an make specific exceptions though. -Rails/SkipsModelValidations: - Enabled: false - ## Relaxed.Ruby.Style SETTINGS # # These styles are a starting point for the conversation around conventions diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index c9d8e0b187..1c482dbc82 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config --exclude-limit 1400` -# on 2020-01-09 11:26:09 +1100 using RuboCop version 0.79.0. +# on 2020-02-22 11:23:29 +0000 using RuboCop version 0.80.0. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -14,10 +14,11 @@ Layout/EmptyLineAfterGuardClause: - 'lib/open_food_network/orders_and_fulfillments_report.rb' - 'lib/open_food_network/packing_report.rb' -# Offense count: 1 +# Offense count: 2 # Cop supports --auto-correct. Layout/EmptyLines: Exclude: + - 'app/models/spree/adjustment_decorator.rb' - 'spec/features/admin/order_cycles_spec.rb' # Offense count: 1 @@ -28,6 +29,14 @@ Layout/EmptyLinesAroundBlockBody: Exclude: - 'spec/controllers/api/orders_controller_spec.rb' +# Offense count: 1 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyleAlignWith, AutoCorrect, Severity. +# SupportedStylesAlignWith: keyword, variable, start_of_line +Layout/EndAlignment: + Exclude: + - 'lib/open_food_network/permalink_generator.rb' + # Offense count: 2 # Cop supports --auto-correct. # Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle. @@ -38,12 +47,27 @@ Layout/HashAlignment: Exclude: - 'spec/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report_spec.rb' -# Offense count: 27 +# Offense count: 8 +# Cop supports --auto-correct. +# Configuration parameters: AllowDoxygenCommentStyle, AllowGemfileRubyComment. +Layout/LeadingCommentSpace: + Exclude: + - 'Gemfile' + - 'app/helpers/application_helper.rb' + - 'app/models/enterprise.rb' + +# Offense count: 3 # Cop supports --auto-correct. # Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns. # URISchemes: http, https Layout/LineLength: - Max: 129 + Max: 115 + +# Offense count: 1 +# Cop supports --auto-correct. +Layout/SpaceAfterColon: + Exclude: + - 'lib/open_food_network/order_cycle_form_applicator.rb' # Offense count: 2 # Cop supports --auto-correct. @@ -54,14 +78,26 @@ Layout/SpaceAroundOperators: - 'app/services/cart_service.rb' - 'spec/support/cancan_helper.rb' -# Offense count: 4 +# Offense count: 2 +# Cop supports --auto-correct. +# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces. +# SupportedStyles: space, no_space, compact +# SupportedStylesForEmptyBraces: space, no_space +Layout/SpaceInsideHashLiteralBraces: + Exclude: + - 'spec/controllers/checkout_controller_spec.rb' + +# Offense count: 2 Lint/AmbiguousOperator: Exclude: - - 'app/controllers/spree/admin/orders/customer_details_controller_decorator.rb' - - 'app/controllers/spree/admin/orders_controller_decorator.rb' - 'spec/controllers/api/enterprise_fees_controller_spec.rb' - 'spec/controllers/spree/admin/payments_controller_spec.rb' +# Offense count: 2 +Lint/Debugger: + Exclude: + - 'app/services/order_factory.rb' + # Offense count: 1 Lint/DuplicateHashKey: Exclude: @@ -116,16 +152,32 @@ Lint/UselessAccessModifier: - 'lib/open_food_network/reports/bulk_coop_report.rb' - 'spec/lib/open_food_network/reports/report_spec.rb' +# Offense count: 1 +Lint/UselessAssignment: + Exclude: + - 'spec/**/*' + - 'app/models/enterprise.rb' + # Offense count: 1 # Configuration parameters: CheckForMethodsWithNoSideEffects. Lint/Void: Exclude: - 'app/serializers/api/enterprise_serializer.rb' +# Offense count: 1 +Metrics/AbcSize: + Max: 16 + +# Offense count: 1 +# Configuration parameters: CountComments, ExcludedMethods. +# ExcludedMethods: refine +Metrics/BlockLength: + Max: 27 + # Offense count: 1 # Configuration parameters: CountComments. Metrics/ModuleLength: - Max: 114 + Max: 121 # Offense count: 8 Naming/AccessorMethodName: @@ -143,20 +195,18 @@ Naming/HeredocDelimiterNaming: Exclude: - 'app/models/content_configuration.rb' -# Offense count: 4 +# Offense count: 3 # Configuration parameters: EnforcedStyleForLeadingUnderscores. # SupportedStylesForLeadingUnderscores: disallowed, required, optional Naming/MemoizedInstanceVariableName: Exclude: - - 'app/controllers/spree/admin/payments_controller_decorator.rb' - 'lib/open_food_network/address_finder.rb' -# Offense count: 8 +# Offense count: 7 # Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames. -# AllowedNames: io, id, to, by, on, in, at, ip, db, os +# AllowedNames: io, id, to, by, on, in, at, ip, db, os, pp Naming/MethodParameterName: Exclude: - - 'app/helpers/spree/admin/base_helper_decorator.rb' - 'app/helpers/spree/base_helper_decorator.rb' - 'engines/order_management/app/services/order_management/subscriptions/validator.rb' - 'lib/open_food_network/reports/bulk_coop_report.rb' @@ -190,7 +240,7 @@ Naming/PredicateName: - 'lib/open_food_network/packing_report.rb' - 'lib/tasks/data.rake' -# Offense count: 152 +# Offense count: 154 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle, Include. # SupportedStyles: action, filter @@ -231,22 +281,22 @@ Rails/ActionFilter: - 'app/controllers/spree/admin/base_controller.rb' - 'app/controllers/spree/admin/images_controller.rb' - 'app/controllers/spree/admin/mail_methods_controller.rb' - - 'app/controllers/spree/admin/orders/customer_details_controller_decorator.rb' - - 'app/controllers/spree/admin/orders_controller_decorator.rb' + - 'app/controllers/spree/admin/orders/customer_details_controller.rb' + - 'app/controllers/spree/admin/orders_controller.rb' - 'app/controllers/spree/admin/payment_methods_controller.rb' - - 'app/controllers/spree/admin/payments_controller_decorator.rb' + - 'app/controllers/spree/admin/payments_controller.rb' - 'app/controllers/spree/admin/product_properties_controller.rb' - - 'app/controllers/spree/admin/products_controller_decorator.rb' + - 'app/controllers/spree/admin/products_controller.rb' - 'app/controllers/spree/admin/reports/enterprise_fee_summaries_controller.rb' - 'app/controllers/spree/admin/reports_controller.rb' + - 'app/controllers/spree/admin/resource_controller.rb' + - 'app/controllers/spree/admin/search_controller.rb' - 'app/controllers/spree/admin/shipping_methods_controller.rb' - 'app/controllers/spree/admin/states_controller.rb' - 'app/controllers/spree/admin/tax_rates_controller.rb' - 'app/controllers/spree/admin/users_controller.rb' - 'app/controllers/spree/admin/zones_controller.rb' - - 'app/controllers/spree/checkout_controller.rb' - 'app/controllers/spree/orders_controller.rb' - - 'app/controllers/spree/paypal_controller_decorator.rb' - 'app/controllers/spree/store_controller.rb' - 'app/controllers/spree/user_registrations_controller.rb' - 'app/controllers/spree/user_sessions_controller.rb' @@ -255,6 +305,78 @@ Rails/ActionFilter: - 'app/controllers/user_passwords_controller.rb' - 'app/controllers/user_registrations_controller.rb' +# Offense count: 192 +# Cop supports --auto-correct. +Rails/ActiveRecordAliases: + Exclude: + - 'app/controllers/admin/bulk_line_items_controller.rb' + - 'app/controllers/admin/enterprises_controller.rb' + - 'app/controllers/admin/subscriptions_controller.rb' + - 'app/controllers/api/customers_controller.rb' + - 'app/controllers/api/enterprise_attachment_controller.rb' + - 'app/controllers/api/enterprises_controller.rb' + - 'app/controllers/api/product_images_controller.rb' + - 'app/controllers/api/products_controller.rb' + - 'app/controllers/api/shipments_controller.rb' + - 'app/controllers/api/taxons_controller.rb' + - 'app/controllers/api/variants_controller.rb' + - 'app/controllers/checkout_controller.rb' + - 'app/controllers/spree/admin/orders/customer_details_controller.rb' + - 'app/controllers/spree/admin/orders_controller.rb' + - 'app/controllers/spree/admin/payment_methods_controller.rb' + - 'app/controllers/spree/admin/resource_controller.rb' + - 'app/controllers/spree/admin/taxons_controller.rb' + - 'app/controllers/spree/admin/users_controller.rb' + - 'app/controllers/spree/credit_cards_controller.rb' + - 'app/controllers/spree/orders_controller.rb' + - 'app/controllers/spree/users_controller.rb' + - 'app/helpers/i18n_helper.rb' + - 'app/jobs/subscription_placement_job.rb' + - 'app/models/spree/adjustment_decorator.rb' + - 'app/models/spree/line_item_decorator.rb' + - 'app/models/spree/product_set.rb' + - 'app/services/line_item_syncer.rb' + - 'app/services/order_factory.rb' + - 'app/services/order_syncer.rb' + - 'app/services/user_default_address_setter.rb' + - 'lib/open_food_network/order_cycle_form_applicator.rb' + - 'lib/open_food_network/subscription_payment_updater.rb' + - 'lib/stripe/profile_storer.rb' + - 'spec/controllers/admin/proxy_orders_controller_spec.rb' + - 'spec/controllers/admin/subscriptions_controller_spec.rb' + - 'spec/controllers/api/orders_controller_spec.rb' + - 'spec/controllers/line_items_controller_spec.rb' + - 'spec/controllers/spree/admin/payment_methods_controller_spec.rb' + - 'spec/controllers/spree/orders_controller_spec.rb' + - 'spec/features/admin/order_cycles_spec.rb' + - 'spec/features/admin/subscriptions_spec.rb' + - 'spec/features/admin/variant_overrides_spec.rb' + - 'spec/features/admin/variants_spec.rb' + - 'spec/features/consumer/account_spec.rb' + - 'spec/features/consumer/registration_spec.rb' + - 'spec/features/consumer/shopping/cart_spec.rb' + - 'spec/features/consumer/shopping/orders_spec.rb' + - 'spec/features/consumer/shopping/shopping_spec.rb' + - 'spec/jobs/subscription_confirm_job_spec.rb' + - 'spec/jobs/subscription_placement_job_spec.rb' + - 'spec/lib/open_food_network/proxy_order_syncer_spec.rb' + - 'spec/models/customer_spec.rb' + - 'spec/models/enterprise_caching_spec.rb' + - 'spec/models/exchange_spec.rb' + - 'spec/models/order_cycle_spec.rb' + - 'spec/models/producer_property_spec.rb' + - 'spec/models/proxy_order_spec.rb' + - 'spec/models/spree/adjustment_spec.rb' + - 'spec/models/spree/credit_card_spec.rb' + - 'spec/models/spree/line_item_spec.rb' + - 'spec/models/spree/order_spec.rb' + - 'spec/models/spree/product_spec.rb' + - 'spec/models/spree/user_spec.rb' + - 'spec/models/spree/variant_spec.rb' + - 'spec/requests/checkout/stripe_connect_spec.rb' + - 'spec/services/order_syncer_spec.rb' + - 'spec/services/subscription_estimator_spec.rb' + # Offense count: 1 # Configuration parameters: EnforcedStyle. # SupportedStyles: strict, flexible @@ -262,6 +384,18 @@ Rails/Date: Exclude: - 'app/models/order_cycle.rb' +# Offense count: 5 +# Cop supports --auto-correct. +# Configuration parameters: Whitelist. +# Whitelist: find_by_sql +Rails/DynamicFindBy: + Exclude: + - 'app/controllers/spree/admin/orders/customer_details_controller.rb' + - 'app/controllers/spree/admin/orders_controller.rb' + - 'app/controllers/spree/admin/payments_controller.rb' + - 'app/controllers/spree/admin/products_controller.rb' + - 'spec/support/request/web_helper.rb' + # Offense count: 16 # Configuration parameters: EnforcedStyle. # SupportedStyles: slashes, arguments @@ -280,6 +414,18 @@ Rails/FilePath: - 'spec/serializers/api/admin/enterprise_serializer_spec.rb' - 'spec/support/downloads_helper.rb' +# Offense count: 7 +# Cop supports --auto-correct. +# Configuration parameters: Include. +# Include: app/models/**/*.rb +Rails/FindBy: + Exclude: + - 'app/models/enterprise.rb' + - 'app/models/product_import/entry_processor.rb' + - 'app/models/product_import/entry_validator.rb' + - 'app/models/product_import/spreadsheet_data.rb' + - 'app/models/spree/user.rb' + # Offense count: 7 # Configuration parameters: Include. # Include: app/models/**/*.rb @@ -292,7 +438,7 @@ Rails/HasAndBelongsToMany: - 'app/models/spree/concerns/payment_method_distributors.rb' - 'app/models/spree/line_item_decorator.rb' -# Offense count: 26 +# Offense count: 24 # Configuration parameters: Include. # Include: app/models/**/*.rb Rails/HasManyOrHasOneDependent: @@ -309,7 +455,7 @@ Rails/HasManyOrHasOneDependent: - 'app/models/spree/variant_decorator.rb' - 'app/models/subscription.rb' -# Offense count: 78 +# Offense count: 83 # Configuration parameters: Include. # Include: app/helpers/**/*.rb Rails/HelperInstanceVariable: @@ -321,19 +467,27 @@ Rails/HelperInstanceVariable: - 'app/helpers/injection_helper.rb' - 'app/helpers/order_cycles_helper.rb' - 'app/helpers/shared_helper.rb' - - 'app/helpers/spree/admin/orders_helper_decorator.rb' + - 'app/helpers/shop_helper.rb' + - 'app/helpers/spree/admin/orders_helper.rb' - 'app/helpers/spree/orders_helper.rb' -# Offense count: 6 +# Offense count: 1 +# Configuration parameters: Include. +# Include: app/**/*.rb, config/**/*.rb, db/**/*.rb, lib/**/*.rb +Rails/Output: + Exclude: + - 'app/services/order_factory.rb' + +# Offense count: 12 Rails/OutputSafety: Exclude: - 'app/controllers/spree/admin/reports_controller.rb' - 'app/helpers/angular_form_helper.rb' - 'app/helpers/spree/admin/base_helper.rb' - - 'app/helpers/spree/admin/zones_helper.rb' - - 'app/helpers/spree/reports_helper.rb' - 'app/helpers/spree/admin/navigation_helper.rb' - 'app/helpers/spree/admin/orders_helper.rb' + - 'app/helpers/spree/admin/zones_helper.rb' + - 'app/helpers/spree/reports_helper.rb' - 'app/serializers/api/product_serializer.rb' - 'lib/spree/money_decorator.rb' - 'spec/features/admin/orders_spec.rb' @@ -353,6 +507,86 @@ Rails/ReflectionClassName: - 'app/models/enterprise_role.rb' - 'app/models/subscription.rb' +# Offense count: 213 +# Configuration parameters: Blacklist, Whitelist. +# Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters +Rails/SkipsModelValidations: + Exclude: + - 'app/controllers/spree/admin/payment_methods_controller.rb' + - 'app/controllers/spree/admin/resource_controller.rb' + - 'app/controllers/spree/admin/shipping_methods_controller.rb' + - 'app/controllers/spree/admin/taxons_controller.rb' + - 'app/controllers/spree/orders_controller.rb' + - 'app/jobs/subscription_confirm_job.rb' + - 'app/jobs/subscription_placement_job.rb' + - 'app/models/enterprise.rb' + - 'app/models/enterprise_relationship.rb' + - 'app/models/product_import/inventory_reset_strategy.rb' + - 'app/models/proxy_order.rb' + - 'app/models/spree/address_decorator.rb' + - 'app/models/spree/credit_card_decorator.rb' + - 'app/models/spree/order_decorator.rb' + - 'app/models/spree/payment_decorator.rb' + - 'app/models/subscription.rb' + - 'app/models/variant_override.rb' + - 'app/services/order_factory.rb' + - 'engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/report_service_spec.rb' + - 'lib/tasks/data/anonymize_data.rake' + - 'lib/tasks/sample_data/product_factory.rb' + - 'lib/tasks/users.rake' + - 'spec/controllers/admin/subscription_line_items_controller_spec.rb' + - 'spec/controllers/admin/variant_overrides_controller_spec.rb' + - 'spec/controllers/api/order_cycles_controller_spec.rb' + - 'spec/controllers/api/orders_controller_spec.rb' + - 'spec/controllers/api/products_controller_spec.rb' + - 'spec/controllers/api/shipments_controller_spec.rb' + - 'spec/controllers/api/variants_controller_spec.rb' + - 'spec/controllers/checkout_controller_spec.rb' + - 'spec/controllers/enterprises_controller_spec.rb' + - 'spec/controllers/spree/admin/orders_controller_spec.rb' + - 'spec/controllers/spree/admin/overview_controller_spec.rb' + - 'spec/controllers/spree/admin/payment_methods_controller_spec.rb' + - 'spec/controllers/spree/credit_cards_controller_spec.rb' + - 'spec/factories.rb' + - 'spec/factories/order_factory.rb' + - 'spec/features/admin/bulk_order_management_spec.rb' + - 'spec/features/admin/bulk_product_update_spec.rb' + - 'spec/features/admin/configuration/tax_rates_spec.rb' + - 'spec/features/admin/order_cycles_spec.rb' + - 'spec/features/admin/orders_spec.rb' + - 'spec/features/admin/reports_spec.rb' + - 'spec/features/consumer/shopping/checkout_spec.rb' + - 'spec/features/consumer/shopping/products_spec.rb' + - 'spec/features/consumer/shopping/shopping_spec.rb' + - 'spec/helpers/enterprises_helper_spec.rb' + - 'spec/helpers/order_cycles_helper_spec.rb' + - 'spec/jobs/subscription_placement_job_spec.rb' + - 'spec/lib/open_food_network/address_finder_spec.rb' + - 'spec/lib/open_food_network/enterprise_fee_calculator_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/scope_variant_to_hub_spec.rb' + - 'spec/lib/open_food_network/subscription_payment_updater_spec.rb' + - 'spec/models/calculator/weight_spec.rb' + - 'spec/models/concerns/variant_stock_spec.rb' + - 'spec/models/enterprise_relationship_spec.rb' + - 'spec/models/exchange_spec.rb' + - 'spec/models/spree/adjustment_spec.rb' + - 'spec/models/spree/line_item_spec.rb' + - 'spec/models/spree/order_spec.rb' + - 'spec/models/spree/product_spec.rb' + - 'spec/models/spree/variant_spec.rb' + - 'spec/models/tag_rule/discount_order_spec.rb' + - 'spec/performance/proxy_order_syncer_spec.rb' + - 'spec/serializers/api/admin/subscription_line_item_serializer_spec.rb' + - 'spec/services/order_cycle_distributed_products_spec.rb' + - 'spec/services/order_factory_spec.rb' + - 'spec/services/order_syncer_spec.rb' + - 'spec/services/product_tag_rules_filterer_spec.rb' + - 'spec/services/products_renderer_spec.rb' + - 'spec/services/restart_checkout_spec.rb' + - 'spec/support/request/shop_workflow.rb' + # Offense count: 1 # Configuration parameters: Environments. # Environments: development, test, production @@ -473,10 +707,10 @@ Style/FormatStringToken: - 'lib/open_food_network/sales_tax_report.rb' - 'spec/features/admin/bulk_order_management_spec.rb' -# Offense count: 928 +# Offense count: 920 # Cop supports --auto-correct. # Configuration parameters: EnforcedStyle. -# SupportedStyles: always, never +# SupportedStyles: always, always_true, never Style/FrozenStringLiteralComment: Exclude: - 'Gemfile' @@ -511,7 +745,6 @@ Style/FrozenStringLiteralComment: - 'app/controllers/api/enterprise_attachment_controller.rb' - 'app/controllers/api/enterprise_fees_controller.rb' - 'app/controllers/api/enterprises_controller.rb' - - 'app/controllers/api/exchange_products_controller.rb' - 'app/controllers/api/logos_controller.rb' - 'app/controllers/api/order_cycles_controller.rb' - 'app/controllers/api/orders_controller.rb' @@ -526,7 +759,6 @@ Style/FrozenStringLiteralComment: - 'app/controllers/application_controller.rb' - 'app/controllers/base_controller.rb' - 'app/controllers/cart_controller.rb' - - 'app/controllers/checkout_controller.rb' - 'app/controllers/discourse_sso_controller.rb' - 'app/controllers/enterprises_controller.rb' - 'app/controllers/groups_controller.rb' @@ -547,19 +779,18 @@ Style/FrozenStringLiteralComment: - 'app/controllers/spree/admin/images_controller.rb' - 'app/controllers/spree/admin/invoices_controller.rb' - 'app/controllers/spree/admin/mail_methods_controller.rb' - - 'app/controllers/spree/admin/orders/customer_details_controller_decorator.rb' - - 'app/controllers/spree/admin/orders_controller_decorator.rb' + - 'app/controllers/spree/admin/orders/customer_details_controller.rb' + - 'app/controllers/spree/admin/orders_controller.rb' - 'app/controllers/spree/admin/overview_controller.rb' - 'app/controllers/spree/admin/payment_methods_controller.rb' - - 'app/controllers/spree/admin/payments_controller_decorator.rb' - 'app/controllers/spree/admin/product_properties_controller.rb' - - 'app/controllers/spree/admin/products_controller_decorator.rb' + - 'app/controllers/spree/admin/products_controller.rb' - 'app/controllers/spree/admin/properties_controller.rb' - 'app/controllers/spree/admin/reports/enterprise_fee_summaries_controller.rb' - 'app/controllers/spree/admin/reports_controller.rb' - - 'app/controllers/spree/admin/resource_controller_decorator.rb' + - 'app/controllers/spree/admin/resource_controller.rb' - 'app/controllers/spree/admin/return_authorizations_controller.rb' - - 'app/controllers/spree/admin/search_controller_decorator.rb' + - 'app/controllers/spree/admin/search_controller.rb' - 'app/controllers/spree/admin/shipping_categories_controller.rb' - 'app/controllers/spree/admin/shipping_methods_controller.rb' - 'app/controllers/spree/admin/states_controller.rb' @@ -569,13 +800,11 @@ Style/FrozenStringLiteralComment: - 'app/controllers/spree/admin/taxonomies_controller.rb' - 'app/controllers/spree/admin/taxons_controller.rb' - 'app/controllers/spree/admin/users_controller.rb' - - 'app/controllers/spree/admin/variants_controller_decorator.rb' + - 'app/controllers/spree/admin/variants_controller.rb' - 'app/controllers/spree/admin/zones_controller.rb' - - 'app/controllers/spree/checkout_controller.rb' - 'app/controllers/spree/credit_cards_controller.rb' - 'app/controllers/spree/home_controller.rb' - 'app/controllers/spree/orders_controller.rb' - - 'app/controllers/spree/paypal_controller_decorator.rb' - 'app/controllers/spree/store_controller.rb' - 'app/controllers/spree/user_passwords_controller.rb' - 'app/controllers/spree/user_registrations_controller.rb' @@ -586,6 +815,7 @@ Style/FrozenStringLiteralComment: - 'app/controllers/user_confirmations_controller.rb' - 'app/controllers/user_passwords_controller.rb' - 'app/controllers/user_registrations_controller.rb' + - 'app/helpers/admin/enterprises_helper.rb' - 'app/helpers/admin/image_settings_helper.rb' - 'app/helpers/admin/injection_helper.rb' - 'app/helpers/admin/orders_helper.rb' @@ -604,16 +834,16 @@ Style/FrozenStringLiteralComment: - 'app/helpers/injection_helper.rb' - 'app/helpers/map_helper.rb' - 'app/helpers/markdown_helper.rb' - - 'app/helpers/order_cycles_helper.rb' - 'app/helpers/serializer_helper.rb' - 'app/helpers/shared_helper.rb' - 'app/helpers/shop_helper.rb' - 'app/helpers/shop_mail_helper.rb' - - 'app/helpers/spree/admin/base_helper_decorator.rb' + - 'app/helpers/spree/admin/base_helper.rb' - 'app/helpers/spree/admin/general_settings_helper.rb' - - 'app/helpers/spree/admin/navigation_helper_decorator.rb' - - 'app/helpers/spree/admin/orders_helper_decorator.rb' + - 'app/helpers/spree/admin/orders_helper.rb' + - 'app/helpers/spree/admin/payments_helper.rb' - 'app/helpers/spree/admin/taxons_helper.rb' + - 'app/helpers/spree/admin/zones_helper.rb' - 'app/helpers/spree/api/api_helpers.rb' - 'app/helpers/spree/base_helper_decorator.rb' - 'app/helpers/spree/orders_helper.rb' @@ -739,7 +969,6 @@ Style/FrozenStringLiteralComment: - 'app/models/tag_rule/filter_shipping_methods.rb' - 'app/models/variant_override.rb' - 'app/models/variant_override_set.rb' - - 'app/presenters/variant_presenter.rb' - 'app/serializers/api/address_serializer.rb' - 'app/serializers/api/adjustment_serializer.rb' - 'app/serializers/api/admin/basic_enterprise_fee_serializer.rb' @@ -819,6 +1048,7 @@ Style/FrozenStringLiteralComment: - 'app/serializers/api/uncached_enterprise_serializer.rb' - 'app/serializers/api/user_serializer.rb' - 'app/serializers/api/variant_serializer.rb' + - 'app/services/action_callbacks.rb' - 'app/services/advance_order_service.rb' - 'app/services/bulk_invoice_service.rb' - 'app/services/cart_service.rb' @@ -827,7 +1057,6 @@ Style/FrozenStringLiteralComment: - 'app/services/default_shipping_category.rb' - 'app/services/default_stock_location.rb' - 'app/services/embedded_page_service.rb' - - 'app/services/exchange_products_renderer.rb' - 'app/services/exchange_variant_bulk_updater.rb' - 'app/services/exchange_variant_deleter.rb' - 'app/services/invoice_renderer.rb' @@ -921,7 +1150,6 @@ Style/FrozenStringLiteralComment: - 'lib/open_food_network/lettuce_share_report.rb' - 'lib/open_food_network/locking.rb' - 'lib/open_food_network/model_class_from_controller_name.rb' - - 'lib/open_food_network/option_value_namer.rb' - 'lib/open_food_network/order_and_distributor_report.rb' - 'lib/open_food_network/order_cycle_form_applicator.rb' - 'lib/open_food_network/order_cycle_management_report.rb' @@ -1056,10 +1284,8 @@ Style/FrozenStringLiteralComment: - 'spec/controllers/spree/admin/shipping_methods_controller_spec.rb' - 'spec/controllers/spree/admin/users_controller_spec.rb' - 'spec/controllers/spree/admin/variants_controller_spec.rb' - - 'spec/controllers/spree/checkout_controller_spec.rb' - 'spec/controllers/spree/credit_cards_controller_spec.rb' - 'spec/controllers/spree/orders_controller_spec.rb' - - 'spec/controllers/spree/paypal_controller_spec.rb' - 'spec/controllers/spree/store_controller_spec.rb' - 'spec/controllers/spree/user_sessions_controller_spec.rb' - 'spec/controllers/spree/users_controller_spec.rb' @@ -1258,7 +1484,6 @@ Style/FrozenStringLiteralComment: - 'spec/models/spree/classification_spec.rb' - 'spec/models/spree/credit_card_spec.rb' - 'spec/models/spree/gateway/stripe_connect_spec.rb' - - 'spec/models/spree/gateway_tagging_spec.rb' - 'spec/models/spree/image_spec.rb' - 'spec/models/spree/line_item_spec.rb' - 'spec/models/spree/order/checkout_spec.rb' @@ -1332,6 +1557,7 @@ Style/FrozenStringLiteralComment: - 'spec/services/order_cycle_distributed_products_spec.rb' - 'spec/services/order_cycle_distributed_variants_spec.rb' - 'spec/services/order_cycle_form_spec.rb' + - 'spec/services/order_cycle_warning_spec.rb' - 'spec/services/order_factory_spec.rb' - 'spec/services/order_syncer_spec.rb' - 'spec/services/permissions/order_spec.rb' @@ -1388,7 +1614,7 @@ Style/FrozenStringLiteralComment: - 'spec/views/spree/admin/orders/edit.html.haml_spec.rb' - 'spec/views/spree/admin/orders/index.html.haml_spec.rb' -# Offense count: 58 +# Offense count: 50 # Configuration parameters: MinBodyLength. Style/GuardClause: Exclude: @@ -1399,11 +1625,7 @@ Style/GuardClause: - 'app/controllers/base_controller.rb' - 'app/controllers/checkout_controller.rb' - 'app/controllers/home_controller.rb' - - 'app/controllers/spree/admin/orders_controller_decorator.rb' - - 'app/controllers/spree/admin/variants_controller_decorator.rb' - - 'app/controllers/spree/checkout_controller.rb' - 'app/controllers/spree/orders_controller.rb' - - 'app/controllers/spree/paypal_controller_decorator.rb' - 'app/models/enterprise.rb' - 'app/models/enterprise_group.rb' - 'app/models/producer_property.rb' @@ -1423,14 +1645,13 @@ Style/GuardClause: - 'spec/support/request/distribution_helper.rb' - 'spec/support/request/shop_workflow.rb' -# Offense count: 4 +# Offense count: 3 # Configuration parameters: AllowIfModifier. Style/IfInsideElse: Exclude: - 'app/controllers/admin/column_preferences_controller.rb' - 'app/controllers/admin/variant_overrides_controller.rb' - 'app/controllers/api/taxons_controller.rb' - - 'app/controllers/spree/admin/products_controller_decorator.rb' # Offense count: 1 # Cop supports --auto-correct. @@ -1498,16 +1719,17 @@ Style/NumericPredicate: - 'lib/spree/money_decorator.rb' - 'lib/tasks/sample_data.rake' -# Offense count: 15 +# Offense count: 16 # Cop supports --auto-correct. # Configuration parameters: ConvertCodeThatCanStartToReturnNil, AllowedMethods. # AllowedMethods: present?, blank?, presence, try, try! Style/SafeNavigation: Exclude: - - 'app/controllers/checkout_controller.rb' + - 'app/controllers/spree/admin/payments_controller.rb' - 'app/controllers/spree/credit_cards_controller.rb' - 'app/controllers/spree/orders_controller.rb' - 'app/helpers/i18n_helper.rb' + - 'app/helpers/shop_helper.rb' - 'app/models/producer_property.rb' - 'app/models/product_import/entry_validator.rb' - 'app/models/product_import/product_importer.rb' @@ -1515,10 +1737,9 @@ Style/SafeNavigation: - 'lib/discourse/single_sign_on.rb' - 'spec/factories.rb' -# Offense count: 235 +# Offense count: 232 Style/Send: Exclude: - - 'app/controllers/spree/checkout_controller.rb' - 'app/models/spree/shipping_method_decorator.rb' - 'spec/controllers/admin/subscriptions_controller_spec.rb' - 'spec/controllers/checkout_controller_spec.rb' diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 779fce90ae..cac1468c67 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,9 +1,9 @@ # Contributing -We love pull requests from everyone. Any contribution is valuable, but there are two issue streams that we especially love people to work on: +We love pull requests from everyone. Any contribution is valuable! -1) Our delivery backlog, is managed via a ZenHub board (ZenHub extensions are available for most major browsers). We use a Kanban-style approach, whereby devs pick issues from the top of the backlog which has been organised according to current priorities. If you have some time and are interested in working on some issues from the backlog, please make yourself known on the [#dev][slack-dev] channel on Slack and we can direct you to the most appropriate issue to pick up. +If you have some time and are interested in working on some issues please make yourself known on the [#dev][slack-dev] channel on Slack. -2) Our list of bugs and other self-contained issues that we consider to be a good starting point for new contributors, or devs who aren’t able to commit to seeing a whole feature through. These issues are marked with the `# good first issue` label. +We have curated all issues we consider to be a good starting point for new members of the community within the [Welcome New Developers project board][welcome-dev]. Have a look and pick the one you would prefer working on! ## Set up @@ -19,10 +19,6 @@ If you want to run the whole test suite, we recommend using a free CI service to bundle exec rspec spec -## Which issue to pick first? - -We have curated all issues interesting for new members of the community within the [Welcome New Developers project board][welcome-dev]. Have a look and pick the one you would prefer working on! - ## Internationalisation (i18n) The locale `en` is maintained in the source code, but other locales are managed at [Transifex][ofn-transifex]. Read more about [internationalisation][i18n] in the developer wiki. diff --git a/Dockerfile b/Dockerfile index 202bbeccf7..c30df2f92f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,8 +13,8 @@ WORKDIR /usr/src/app COPY .ruby-version . # 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 && \ +RUN git clone --depth 1 --branch v1.1.2 https://github.com/rbenv/rbenv.git ${RBENV_ROOT} && \ + git clone --depth 1 --branch v20200520 https://github.com/rbenv/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build && \ ${RBENV_ROOT}/plugins/ruby-build/install.sh && \ echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh && \ rbenv install $(cat .ruby-version) && \ @@ -43,4 +43,5 @@ RUN wget https://chromedriver.storage.googleapis.com/2.41/chromedriver_linux64.z # Copy code and install app dependencies COPY . /usr/src/app/ -RUN bundle install +# Run bundler install in parallel with the amount of available CPUs +RUN bundle install --jobs="$(nproc)" diff --git a/GETTING_STARTED.md b/GETTING_STARTED.md index 67f38e7390..b252993215 100644 --- a/GETTING_STARTED.md +++ b/GETTING_STARTED.md @@ -2,21 +2,17 @@ This is a general guide to setting up an Open Food Network development environment on your local machine. -The fastest way to make it work locally is to use Docker, see the [Docker setup guide](DOCKER.md). +### Requirements -The following guides are located in the wiki and provide more OS-specific step-by-step instructions: - -- [Ubuntu Setup Guide][ubuntu] -- [macOS Sierra Setup Guide][sierra] -- [OSX El Capitan Setup Guide][el-capitan] - -### Dependencies - -* Rails 3.2.x -* Ruby 2.3.7 +The fastest way to make it work locally is to use Docker, you only need to setup git, see the [Docker setup guide](DOCKER.md). +Otherwise, for a local setup you will need: +* Ruby 2.3.7 and bundler * PostgreSQL database -* PhantomJS (for testing) -* See Gemfile for a list of gems required +* Chrome (for testing) + +The following guides will provide OS-specific step-by-step instructions to get these requirements installed: +- [Ubuntu Setup Guide][ubuntu] +- [OSX Setup Guide][osx] If you are likely to need to manage multiple version of ruby on your local machine, we recommend version managers such as [rbenv](https://github.com/rbenv/rbenv) or [RVM](https://rvm.io/). @@ -52,14 +48,12 @@ This will create the "ofn" user as superuser and allowing it to create databases Once done, run `script/setup`. If the script succeeds you're ready to start developing. If not, take a look at the output as it should be informative enough to help you troubleshoot. -If you run into any other issues getting your local environment up and running please consult [the wiki][wiki]. - -If still you get stuck do not hesitate to open an issue reporting the full output of the script. - Now, your dreams of spinning up a development server can be realised: bundle exec rails server +Go to [http://localhost:3000](http://localhost:3000) to play around! + To login as the default user, use: email: ofn@example.com @@ -79,7 +73,7 @@ The tests of all custom engines can be run with: bundle exec rake ofn:specs:engines:rspec -Note: If your OS is not explicitly supported in the setup guides then not all tests may pass. However, you may still be able to develop. Get in touch with the [#dev][slack-dev] channel on Slack to troubleshoot issues and determine if they will preclude you from contributing to OFN. +Note: If your OS is not explicitly supported in the setup guides then not all tests may pass. However, you may still be able to develop. Note: The time zone on your machine should match the one defined in `config/application.yml`. @@ -120,8 +114,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%2C-Mojave-and-Catalina%29 -[el-capitan]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup:-OS-X-(El-Capitan) +[osx]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup:-OS-X [ubuntu]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup:-Ubuntu [wiki]: https://github.com/openfoodfoundation/openfoodnetwork/wiki [zeus]: https://github.com/burke/zeus diff --git a/Gemfile b/Gemfile index 861e193b16..a9d3c89755 100644 --- a/Gemfile +++ b/Gemfile @@ -3,9 +3,9 @@ ruby "2.3.7" git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" } gem 'i18n', '~> 0.6.11' -gem 'i18n-js', '~> 3.6.0' -gem 'rails', '~> 3.2.22' -gem 'rails-i18n', '~> 3.0.0' +gem 'i18n-js', '~> 3.7.0' +gem 'rails', '~> 4.0.13' +gem 'rails-i18n', '~> 4.0' gem 'rails_safe_tasks', '~> 1.0' gem "activerecord-import" @@ -21,22 +21,36 @@ gem 'pg', '~> 0.21.0' # OFN-maintained and patched version of Spree v2.0.4. See # https://github.com/openfoodfoundation/openfoodnetwork/wiki/Tech-Doc:-OFN's-Spree-fork%F0%9F%8D%B4 # for details. -gem 'spree_core', github: 'openfoodfoundation/spree', branch: '2-0-4-stable' +gem 'spree_core', github: 'openfoodfoundation/spree', branch: '2-1-0-stable' + +### Dependencies brought from spree core +gem 'acts_as_list', '= 0.2.0' +gem 'awesome_nested_set', '~> 3.0.0.rc.1' +gem 'cancan', '~> 1.6.10' +gem 'ffaker', '~> 1.16' +gem 'highline', '= 1.6.18' # Necessary for the install generator +gem 'httparty', '~> 0.18' # Used to check alerts in spree_core, this is not used in OFN. +gem 'json', '>= 1.7.7' +gem 'money', '5.1.1' +gem 'paranoia', '~> 2.0' +gem 'ransack', '~> 1.2.3' +gem 'state_machine', '1.2.0' +gem 'stringex', '~> 1.5.1' gem 'spree_i18n', github: 'spree/spree_i18n', branch: '1-3-stable' # Our branch contains two changes # - Pass customer email and phone number to PayPal (merged to upstream master) # - Change type of password from string to password to hide it in the form -gem 'spree_paypal_express', github: "openfoodfoundation/better_spree_paypal_express", branch: "2-0-stable" +gem 'spree_paypal_express', github: 'openfoodfoundation/better_spree_paypal_express', branch: '2-1-0-stable' gem 'stripe' # We need at least this version to have Digicert's root certificate # which is needed for Pin Payments (and possibly others). -gem 'activemerchant', '~> 1.78' +gem 'activemerchant', '~> 1.78.0' -gem 'devise', '~> 2.2.5' -gem 'devise-encryptable', '0.2.0' +gem 'devise', '~> 3.0.1' +gem 'devise-encryptable' gem 'jwt', '~> 2.2' gem 'oauth2', '~> 1.4.4' # Used for Stripe Connect @@ -50,19 +64,21 @@ gem 'kaminari', '~> 0.14.1' gem 'andand' gem 'angularjs-rails', '1.5.5' -gem 'aws-sdk' +gem 'aws-sdk', '1.11.1' # temporarily locked down due to https://github.com/aws/aws-sdk-ruby/issues/273 gem 'bugsnag' gem 'db2fog' gem 'haml' gem 'redcarpet' -gem 'sass', "~> 3.3" -gem 'sass-rails', '~> 3.2.3' -gem 'truncate_html' +gem 'sass' +gem 'sass-rails' +gem 'truncate_html', '0.9.2' gem 'unicorn' +gem 'actionpack-action_caching' # AMS is pinned to 0.8.4 because 0.9.x is a complete re-write, as is 0.10.x # Once Rails is updated to 5.x we should bump directly to 0.10.x gem "active_model_serializers", "0.8.4" +gem 'activerecord-session_store' gem 'acts-as-taggable-on', '~> 3.4' gem 'angularjs-file-upload-rails', '~> 2.4.1' gem 'custom_error_message', github: 'jeremydurham/custom-err-msg' @@ -77,7 +93,6 @@ gem 'paperclip', '~> 3.4.1' gem 'rack-rewrite' gem 'rack-ssl', require: 'rack/ssl' gem 'roadie-rails', '~> 1.3.0' -gem 'spinjs-rails' gem 'combine_pdf' gem 'wicked_pdf' @@ -91,7 +106,7 @@ gem 'whenever', require: false gem 'test-unit', '~> 3.3' -gem 'coffee-rails', '~> 3.2.1' +gem 'coffee-rails', '~> 4.2.2' gem 'compass-rails' gem 'mini_racer', '0.2.14' @@ -101,16 +116,15 @@ gem 'uglifier', '>= 1.0.3' gem 'angular-rails-templates', '~> 0.3.0' gem 'foundation-icons-sass-rails' gem 'momentjs-rails' -gem 'turbo-sprockets-rails3' -gem "foundation-rails" +gem 'foundation-rails', '= 5.5.2.1' gem 'jquery-migrate-rails' gem 'jquery-rails', '3.1.5' gem 'jquery-ui-rails', '~> 4.2' gem 'select2-rails', '~> 3.4.7' -gem 'ofn-qz', github: 'openfoodfoundation/ofn-qz', ref: '60da2ae4c44cbb4c8d602f59fb5fff8d0f21db3c' +gem 'ofn-qz', github: 'openfoodfoundation/ofn-qz', branch: 'ofn-rails-4' group :production, :staging do gem 'ddtrace' @@ -122,8 +136,8 @@ group :test, :development do gem 'atomic' gem 'awesome_print' gem 'capybara', '>= 2.18.0' # 3.0 requires rack 1.6 that only works with Rails 4.2 - gem 'database_cleaner', '0.7.1', require: false - gem "factory_bot_rails", require: false + gem 'database_cleaner', require: false + gem "factory_bot_rails", '4.10.0', require: false gem 'fuubar', '~> 2.5.0' gem 'json_spec', '~> 1.1.4' gem 'knapsack' @@ -152,7 +166,7 @@ group :development do gem 'pry-byebug', '~> 3.7.0' # 3.8 requires ruby 2.4 gem 'rubocop' gem 'rubocop-rails' - gem 'spring', '1.7.2' + gem 'spring' gem 'spring-commands-rspec' # 1.0.9 fixed openssl issues on macOS https://github.com/eventmachine/eventmachine/issues/602 diff --git a/Gemfile.lock b/Gemfile.lock index dc1aa80cf5..a4dbce97bc 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -6,31 +6,30 @@ GIT GIT remote: https://github.com/openfoodfoundation/better_spree_paypal_express.git - revision: 27ad7165ea4c6e8c5f120b42b676cb9c2c272100 - branch: 2-0-stable + revision: e28e4a8c5cedba504eea9cdad4be440d277d7e68 + branch: 2-1-0-stable specs: spree_paypal_express (2.0.3) paypal-sdk-merchant (= 1.106.1) - spree_core (~> 2.0.3) + spree_core (~> 2.1.0) GIT remote: https://github.com/openfoodfoundation/ofn-qz.git - revision: 60da2ae4c44cbb4c8d602f59fb5fff8d0f21db3c - ref: 60da2ae4c44cbb4c8d602f59fb5fff8d0f21db3c + revision: 467f6ea1c44529c7c91cac4c8211bbd863588c0b + branch: ofn-rails-4 specs: ofn-qz (0.1.0) - railties (~> 3.1) GIT remote: https://github.com/openfoodfoundation/spree.git - revision: e10ca1f689b1658040b081939b7523f6fb68895a - branch: 2-0-4-stable + revision: 0b0c422369c82b6dd7e7cb627a24e3a9fca19a6c + branch: 2-1-0-stable specs: - spree_core (2.0.4) - activemerchant (~> 1.34) + spree_core (2.1.0) + activemerchant (= 1.78.0) acts_as_list (= 0.2.0) - awesome_nested_set (= 2.1.5) - aws-sdk (~> 1.11.1) + awesome_nested_set (~> 3.0.0.rc.1) + aws-sdk (= 1.11.1) cancan (~> 1.6.10) ffaker (~> 1.16) highline (= 1.6.18) @@ -39,9 +38,9 @@ GIT kaminari (~> 0.14.1) money (= 5.1.1) paperclip (~> 3.4.1) - paranoia (~> 1.3) - rails (~> 3.2.14) - ransack (= 0.7.2) + paranoia (~> 2.0) + rails (~> 4.0) + ransack (~> 1.0) state_machine (= 1.2.0) stringex (~> 1.5.1) truncate_html (= 0.9.2) @@ -82,19 +81,17 @@ GEM remote: https://rubygems.org/ specs: CFPropertyList (2.3.6) - actionmailer (3.2.22.5) - actionpack (= 3.2.22.5) - mail (~> 2.5.4) - actionpack (3.2.22.5) - activemodel (= 3.2.22.5) - activesupport (= 3.2.22.5) - builder (~> 3.0.0) + actionmailer (4.0.13) + actionpack (= 4.0.13) + mail (~> 2.5, >= 2.5.4) + actionpack (4.0.13) + activesupport (= 4.0.13) + builder (~> 3.1.0) erubis (~> 2.7.0) - journey (~> 1.0.4) - rack (~> 1.4.5) - rack-cache (~> 1.2) - rack-test (~> 0.6.1) - sprockets (~> 2.2.1) + rack (~> 1.5.2) + rack-test (~> 0.6.2) + actionpack-action_caching (1.2.1) + actionpack (>= 4.0.0) active_model_serializers (0.8.4) activemodel (>= 3.0) activemerchant (1.78.0) @@ -102,24 +99,31 @@ GEM builder (>= 2.1.2, < 4.0.0) i18n (>= 0.6.9) nokogiri (~> 1.4) - activemodel (3.2.22.5) - activesupport (= 3.2.22.5) - builder (~> 3.0.0) - activerecord (3.2.22.5) - activemodel (= 3.2.22.5) - activesupport (= 3.2.22.5) - arel (~> 3.0.2) - tzinfo (~> 0.3.29) + activemodel (4.0.13) + activesupport (= 4.0.13) + builder (~> 3.1.0) + activerecord (4.0.13) + activemodel (= 4.0.13) + activerecord-deprecated_finders (~> 1.0.2) + activesupport (= 4.0.13) + arel (~> 4.0.0) + activerecord-deprecated_finders (1.0.4) activerecord-import (1.0.5) activerecord (>= 3.2) activerecord-postgresql-adapter (0.0.1) pg - activeresource (3.2.22.5) - activemodel (= 3.2.22.5) - activesupport (= 3.2.22.5) - activesupport (3.2.22.5) - i18n (~> 0.6, >= 0.6.4) - multi_json (~> 1.0) + activerecord-session_store (1.1.3) + actionpack (>= 4.0) + activerecord (>= 4.0) + multi_json (~> 1.11, >= 1.11.2) + rack (>= 1.5.2, < 3) + railties (>= 4.0) + activesupport (4.0.13) + i18n (~> 0.6, >= 0.6.9) + minitest (~> 4.2) + multi_json (~> 1.3) + thread_safe (~> 0.1) + tzinfo (~> 0.3.37) acts-as-taggable-on (3.5.0) activerecord (>= 3.2, < 5) acts_as_list (0.2.0) @@ -133,11 +137,11 @@ GEM tilt angularjs-file-upload-rails (2.4.1) angularjs-rails (1.5.5) - arel (3.0.3) + arel (4.0.2) ast (2.4.0) atomic (1.1.101) - awesome_nested_set (2.1.5) - activerecord (>= 3.0.0) + awesome_nested_set (3.0.3) + activerecord (>= 4.0.0, < 5) awesome_print (1.8.0) aws-sdk (1.11.1) json (~> 1.4) @@ -148,7 +152,7 @@ GEM bcrypt (>= 3.1.3) bugsnag (6.13.1) concurrent-ruby (~> 1.0) - builder (3.0.4) + builder (3.1.4) byebug (11.0.1) cancan (1.6.10) capybara (2.18.0) @@ -165,13 +169,13 @@ GEM cocaine (0.5.8) climate_control (>= 0.0.3, < 1.0) coderay (1.1.2) - coffee-rails (3.2.2) + coffee-rails (4.2.2) coffee-script (>= 2.2.0) - railties (~> 3.2.0) + railties (>= 4.0.0) coffee-script (2.4.1) coffee-script-source execjs - coffee-script-source (1.10.0) + coffee-script-source (1.12.2) combine_pdf (1.0.16) ruby-rc4 (>= 0.1.5) compass (1.0.3) @@ -193,16 +197,16 @@ GEM concurrent-ruby (1.1.6) crack (0.4.3) safe_yaml (~> 1.0.0) - css_parser (1.7.0) + css_parser (1.7.1) addressable daemons (1.3.1) dalli (2.7.10) - database_cleaner (0.7.1) + database_cleaner (1.7.0) db2fog (0.9.0) activerecord (>= 3.2.0, < 5.0) fog (~> 1.0) rails (>= 3.2.0, < 5.0) - ddtrace (0.35.2) + ddtrace (0.36.0) msgpack debugger-linecache (1.2.0) delayed_job (4.1.8) @@ -215,11 +219,11 @@ GEM delayed_job (> 2.0.3) rack-protection (>= 1.5.5) sinatra (>= 1.4.4) - devise (2.2.8) + devise (3.0.4) bcrypt-ruby (~> 3.0) orm_adapter (~> 0.1) - railties (~> 3.1) - warden (~> 1.2.1) + railties (>= 3.2.6, < 5) + warden (~> 1.2.3) devise-encryptable (0.2.0) devise (>= 2.1.0) diff-lcs (1.3) @@ -277,7 +281,7 @@ GEM fog-xml (~> 0.1.1) ipaddress (~> 0.5) json (>= 1.8, < 2.0) - fog-aliyun (0.3.2) + fog-aliyun (0.3.5) fog-core fog-json ipaddress (~> 0.8) @@ -335,8 +339,8 @@ GEM multi_json (~> 1.10) fog-local (0.6.0) fog-core (>= 1.27, < 3.0) - fog-openstack (0.1.25) - fog-core (~> 1.40) + fog-openstack (0.3.10) + fog-core (>= 1.45, <= 2.1.0) fog-json (>= 1.0) ipaddress (>= 0.8) fog-powerdns (0.2.0) @@ -380,12 +384,13 @@ GEM fog-voxel (0.1.0) fog-core fog-xml - fog-vsphere (2.3.0) + fog-vsphere (3.2.1) fog-core - rbvmomi (~> 1.9) - fog-xenserver (0.3.0) + rbvmomi (>= 1.9, < 3) + fog-xenserver (1.0.0) fog-core fog-xml + xmlrpc fog-xml (0.1.3) fog-core nokogiri (>= 1.5.11, < 2.0.0) @@ -401,25 +406,26 @@ GEM fuubar (2.5.0) rspec-core (~> 3.0) ruby-progressbar (~> 1.4) - geocoder (1.1.8) + geocoder (1.5.2) get_process_mem (0.2.5) ffi (~> 1.0) - gmaps4rails (1.5.6) - haml (4.0.7) + gmaps4rails (2.1.2) + haml (5.1.2) + temple (>= 0.8.0) tilt hashdiff (1.0.1) highline (1.6.18) hike (1.2.3) - httparty (0.16.2) + httparty (0.18.1) + mime-types (~> 3.0) multi_xml (>= 0.5.2) i18n (0.6.11) - i18n-js (3.6.0) + i18n-js (3.7.0) i18n (>= 0.6.6) immigrant (0.3.6) activerecord (>= 3.0) ipaddress (0.8.3) jaro_winkler (1.5.4) - journey (1.0.4) jquery-migrate-rails (1.2.1) jquery-rails (3.1.5) railties (>= 3.0, < 5.0) @@ -442,15 +448,17 @@ GEM letter_opener (1.7.0) launchy (~> 2.2) libv8 (7.3.492.27.1) - mail (2.5.5) - mime-types (~> 1.16) - treetop (~> 1.4.8) + mail (2.7.1) + mini_mime (>= 0.1.1) method_source (0.9.2) - mime-types (1.25.1) - mini_mime (1.0.1) + mime-types (3.3.1) + mime-types-data (~> 3.2015) + mime-types-data (3.2020.0512) + mini_mime (1.0.2) mini_portile2 (2.4.0) mini_racer (0.2.14) libv8 (> 7.3) + minitest (4.7.5) momentjs-rails (2.20.1) railties (>= 3.1) money (5.1.1) @@ -469,6 +477,7 @@ GEM multi_xml (~> 0.5) rack (>= 1.2, < 3) oj (3.10.6) + optimist (3.0.0) orm_adapter (0.5.0) paper_trail (5.2.3) activerecord (>= 3.0, < 6.0) @@ -480,8 +489,8 @@ GEM cocaine (~> 0.5.0) mime-types parallel (1.19.1) - paranoia (1.3.4) - activerecord (~> 3.1) + paranoia (2.4.2) + activerecord (>= 4.0, < 6.1) parser (2.7.1.0) ast (~> 2.4.0) paypal-sdk-core (0.2.10) @@ -490,10 +499,9 @@ GEM paypal-sdk-merchant (1.106.1) paypal-sdk-core (~> 0.2.3) pg (0.21.0) - polyamorous (0.5.0) - activerecord (~> 3.0) - polyglot (0.3.5) - power_assert (1.1.5) + polyamorous (1.0.0) + activerecord (>= 3.0) + power_assert (1.2.0) pry (0.12.2) coderay (~> 1.1.0) method_source (~> 0.9.0) @@ -501,54 +509,50 @@ GEM byebug (~> 11.0) pry (~> 0.10) public_suffix (4.0.3) - rack (1.4.7) - rack-cache (1.11.0) - rack (>= 0.4) + rack (1.5.5) rack-mini-profiler (2.0.2) rack (>= 1.2.0) rack-protection (1.5.5) rack rack-rewrite (1.5.1) - rack-ssl (1.3.4) + rack-ssl (1.4.1) rack rack-test (0.6.3) rack (>= 1.0) - rails (3.2.22.5) - actionmailer (= 3.2.22.5) - actionpack (= 3.2.22.5) - activerecord (= 3.2.22.5) - activeresource (= 3.2.22.5) - activesupport (= 3.2.22.5) - bundler (~> 1.0) - railties (= 3.2.22.5) - rails-i18n (3.0.1) - i18n (~> 0.5) - rails (>= 3.0.0, < 4.0.0) + rails (4.0.13) + actionmailer (= 4.0.13) + actionpack (= 4.0.13) + activerecord (= 4.0.13) + activesupport (= 4.0.13) + bundler (>= 1.3.0, < 2.0) + railties (= 4.0.13) + sprockets-rails (~> 2.0) + rails-i18n (4.0.5) + i18n (~> 0.6) + railties (~> 4.0) rails_safe_tasks (1.0.0) - railties (3.2.22.5) - actionpack (= 3.2.22.5) - activesupport (= 3.2.22.5) - rack-ssl (~> 1.3.2) + railties (4.0.13) + actionpack (= 4.0.13) + activesupport (= 4.0.13) rake (>= 0.8.7) - rdoc (~> 3.4) - thor (>= 0.14.6, < 2.0) + thor (>= 0.18.1, < 2.0) rainbow (3.0.0) raindrops (0.19.1) rake (13.0.1) - ransack (0.7.2) - actionpack (~> 3.0) - activerecord (~> 3.0) - polyamorous (~> 0.5.0) + ransack (1.2.3) + actionpack (>= 3.0) + activerecord (>= 3.0) + activesupport (>= 3.0) + i18n + polyamorous (~> 1.0.0) rb-fsevent (0.10.3) rb-inotify (0.10.1) ffi (~> 1.0) - rbvmomi (1.13.0) + rbvmomi (2.2.0) builder (~> 3.0) json (>= 1.8) nokogiri (~> 1.5) - trollop (~> 2.1) - rdoc (3.12.2) - json (~> 1.4) + optimist (~> 3.0) redcarpet (3.5.0) request_store (1.4.1) rack (>= 1.4) @@ -601,54 +605,53 @@ GEM ruby-rc4 (0.1.5) rubyzip (1.3.0) safe_yaml (1.0.5) - sass (3.3.14) - sass-rails (3.2.6) - railties (~> 3.2.0) - sass (>= 3.1.10) - tilt (~> 1.3) + sass (3.4.25) + sass-rails (5.0.7) + railties (>= 4.0.0, < 6) + sass (~> 3.1) + sprockets (>= 2.8, < 4.0) + sprockets-rails (>= 2.0, < 4.0) + tilt (>= 1.1, < 3) select2-rails (3.4.9) sass-rails thor (~> 0.14) selenium-webdriver (3.142.7) childprocess (>= 0.5, < 4.0) rubyzip (>= 1.2.2) - shoulda-matchers (2.8.0) - activesupport (>= 3.0.0) + shoulda-matchers (3.1.3) + activesupport (>= 4.0.0) simplecov (0.17.1) docile (~> 1.1) json (>= 1.8, < 3) simplecov-html (~> 0.10.0) simplecov-html (0.10.2) - sinatra (1.4.6) - rack (~> 1.4) + sinatra (1.4.8) + rack (~> 1.5) rack-protection (~> 1.4) tilt (>= 1.3, < 3) - spinjs-rails (1.4) - rails (>= 3.1) spring (1.7.2) spring-commands-rspec (1.0.4) spring (>= 0.9.1) - sprockets (2.2.3) + sprockets (2.12.5) hike (~> 1.2) multi_json (~> 1.0) rack (~> 1.0) tilt (~> 1.1, != 1.3.0) + sprockets-rails (2.3.3) + actionpack (>= 3.0) + activesupport (>= 3.0) + sprockets (>= 2.8, < 4.0) state_machine (1.2.0) stringex (1.5.1) - stripe (5.15.0) - test-unit (3.3.5) + stripe (5.22.0) + temple (0.8.2) + test-unit (3.3.6) power_assert thor (0.20.3) + thread_safe (0.3.6) tilt (1.4.1) timecop (0.9.1) - treetop (1.4.15) - polyglot - polyglot (>= 0.3.1) - trollop (2.9.9) truncate_html (0.9.2) - turbo-sprockets-rails3 (0.3.14) - railties (> 3.2.8, < 4.0.0) - sprockets (>= 2.2.0) tzinfo (0.3.57) uglifier (4.2.0) execjs (>= 0.3.0, < 3) @@ -673,11 +676,13 @@ GEM addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - whenever (0.11.0) + whenever (1.0.0) chronic (>= 0.6.3) - wicked_pdf (1.1.0) + wicked_pdf (1.4.0) + activesupport wkhtmltopdf-binary (0.12.5) xml-simple (1.1.5) + xmlrpc (0.3.0) xpath (2.1.0) nokogiri (~> 1.3) @@ -685,54 +690,63 @@ PLATFORMS ruby DEPENDENCIES + actionpack-action_caching active_model_serializers (= 0.8.4) - activemerchant (~> 1.78) + activemerchant (~> 1.78.0) activerecord-import activerecord-postgresql-adapter + activerecord-session_store acts-as-taggable-on (~> 3.4) + acts_as_list (= 0.2.0) andand angular-rails-templates (~> 0.3.0) angularjs-file-upload-rails (~> 2.4.1) angularjs-rails (= 1.5.5) atomic + awesome_nested_set (~> 3.0.0.rc.1) awesome_print - aws-sdk + aws-sdk (= 1.11.1) bugsnag byebug (~> 11.0.0) + cancan (~> 1.6.10) capybara (>= 2.18.0) catalog! - coffee-rails (~> 3.2.1) + coffee-rails (~> 4.2.2) combine_pdf compass-rails custom_error_message! daemons dalli - database_cleaner (= 0.7.1) + database_cleaner db2fog ddtrace debugger-linecache delayed_job_active_record delayed_job_web - devise (~> 2.2.5) - devise-encryptable (= 0.2.0) + devise (~> 3.0.1) + devise-encryptable dfc_provider! diffy eventmachine (>= 1.2.3) - factory_bot_rails + factory_bot_rails (= 4.10.0) + ffaker (~> 1.16) figaro foreigner foundation-icons-sass-rails - foundation-rails + foundation-rails (= 5.5.2.1) fuubar (~> 2.5.0) geocoder gmaps4rails haml + highline (= 1.6.18) + httparty (~> 0.18) i18n (~> 0.6.11) - i18n-js (~> 3.6.0) + i18n-js (~> 3.7.0) immigrant jquery-migrate-rails jquery-rails (= 3.1.5) jquery-ui-rails (~> 4.2) + json (>= 1.7.7) json_spec (~> 1.1.4) jwt (~> 2.2) kaminari (~> 0.14.1) @@ -740,6 +754,7 @@ DEPENDENCIES letter_opener (>= 1.4.1) mini_racer (= 0.2.14) momentjs-rails + money (= 5.1.1) newrelic_rpm (~> 3.0) oauth2 (~> 1.4.4) ofn-qz! @@ -747,15 +762,17 @@ DEPENDENCIES order_management! paper_trail (~> 5.2.3) paperclip (~> 3.4.1) + paranoia (~> 2.0) pg (~> 0.21.0) pry (~> 0.12.0) pry-byebug (~> 3.7.0) rack-mini-profiler (< 3.0.0) rack-rewrite rack-ssl - rails (~> 3.2.22) - rails-i18n (~> 3.0.0) + rails (~> 4.0.13) + rails-i18n (~> 4.0) rails_safe_tasks (~> 1.0) + ransack (~> 1.2.3) redcarpet roadie-rails (~> 1.3.0) roo (~> 2.8.3) @@ -763,23 +780,23 @@ DEPENDENCIES rspec-retry rubocop rubocop-rails - sass (~> 3.3) - sass-rails (~> 3.2.3) + sass + sass-rails select2-rails (~> 3.4.7) selenium-webdriver shoulda-matchers simplecov - spinjs-rails spree_core! spree_i18n! spree_paypal_express! - spring (= 1.7.2) + spring spring-commands-rspec + state_machine (= 1.2.0) + stringex (~> 1.5.1) stripe test-unit (~> 3.3) timecop - truncate_html - turbo-sprockets-rails3 + truncate_html (= 0.9.2) uglifier (>= 1.0.3) unicorn unicorn-rails diff --git a/app/assets/images/home/groups-bg.svg b/app/assets/images/home/groups-bg.svg deleted file mode 100644 index 19d7f926c5..0000000000 --- a/app/assets/images/home/groups-bg.svg +++ /dev/null @@ -1,1051 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/assets/images/home/home-apples.jpg b/app/assets/images/home/home-apples.jpg deleted file mode 100644 index 91bfd4cfa5..0000000000 Binary files a/app/assets/images/home/home-apples.jpg and /dev/null differ diff --git a/app/assets/images/home/home-oranges.jpg b/app/assets/images/home/home-oranges.jpg deleted file mode 100644 index 671f02d979..0000000000 Binary files a/app/assets/images/home/home-oranges.jpg and /dev/null differ diff --git a/app/assets/images/home/home-strawberries.jpg b/app/assets/images/home/home-strawberries.jpg deleted file mode 100644 index cb2bf15c0e..0000000000 Binary files a/app/assets/images/home/home-strawberries.jpg and /dev/null differ diff --git a/app/assets/images/home/home1.jpg b/app/assets/images/home/home1.jpg deleted file mode 100644 index 015b203bcf..0000000000 Binary files a/app/assets/images/home/home1.jpg and /dev/null differ diff --git a/app/assets/images/home/home2.jpg b/app/assets/images/home/home2.jpg deleted file mode 100644 index 4e5cf61b08..0000000000 Binary files a/app/assets/images/home/home2.jpg and /dev/null differ diff --git a/app/assets/images/home/home3.jpg b/app/assets/images/home/home3.jpg deleted file mode 100644 index 307ad38c1b..0000000000 Binary files a/app/assets/images/home/home3.jpg and /dev/null differ diff --git a/app/assets/images/home/macbook.png b/app/assets/images/home/macbook.png deleted file mode 100644 index ab0d7dfe07..0000000000 Binary files a/app/assets/images/home/macbook.png and /dev/null differ diff --git a/app/assets/images/home/maps-bg.svg b/app/assets/images/home/maps-bg.svg deleted file mode 100644 index 48153cc191..0000000000 --- a/app/assets/images/home/maps-bg.svg +++ /dev/null @@ -1,1090 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/assets/images/home/producers-bg.svg b/app/assets/images/home/producers-bg.svg deleted file mode 100644 index 2a47eed65a..0000000000 --- a/app/assets/images/home/producers-bg.svg +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/assets/images/menu/btn-menu-mobile.png b/app/assets/images/menu/btn-menu-mobile.png new file mode 100644 index 0000000000..1d2d414473 Binary files /dev/null and b/app/assets/images/menu/btn-menu-mobile.png differ diff --git a/app/assets/javascripts/admin/all.js b/app/assets/javascripts/admin/all.js index 2bb2176233..eee8a874c9 100644 --- a/app/assets/javascripts/admin/all.js +++ b/app/assets/javascripts/admin/all.js @@ -30,7 +30,6 @@ //= require spree //= require admin/spree/spree-select2 //= require modernizr -//= require spin //= require equalize //= require css_browser_selector_dev //= require responsive-tables diff --git a/app/assets/javascripts/admin/bulk_product_update.js.coffee b/app/assets/javascripts/admin/bulk_product_update.js.coffee index d92bc73566..94939f3f91 100644 --- a/app/assets/javascripts/admin/bulk_product_update.js.coffee +++ b/app/assets/javascripts/admin/bulk_product_update.js.coffee @@ -105,6 +105,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout $scope.producerFilter = "0" $scope.categoryFilter = "0" $scope.importDateFilter = "0" + $scope.fetchProducts() $scope.$watch 'sortOptions', (sort) -> return unless sort && sort.predicate != "" 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 f6d4c964d6..751ddf8866 100644 --- a/app/assets/javascripts/admin/orders/controllers/orders_controller.js.coffee +++ b/app/assets/javascripts/admin/orders/controllers/orders_controller.js.coffee @@ -37,6 +37,7 @@ angular.module("admin.orders").controller "ordersCtrl", ($scope, $timeout, Reque 'q[distributor_id_in][]': $scope['q']['distributor_id_in'], 'q[order_cycle_id_in][]': $scope['q']['order_cycle_id_in'], 'q[s]': $scope.sorting || 'completed_at desc', + shipping_method_id: $scope.shipping_method_id, per_page: $scope.per_page, page: page } diff --git a/app/assets/javascripts/admin/side_menu/services/side_menu.js.coffee b/app/assets/javascripts/admin/side_menu/services/side_menu.js.coffee index 4f6fe5ab59..4e1ae9abbb 100644 --- a/app/assets/javascripts/admin/side_menu/services/side_menu.js.coffee +++ b/app/assets/javascripts/admin/side_menu/services/side_menu.js.coffee @@ -4,7 +4,6 @@ angular.module("admin.side_menu") items: [] selected: null - # Checks for path and uses it to set the view # If no path, loads first view init: => @@ -31,11 +30,3 @@ angular.module("admin.side_menu") for item in @items when item.name is name return item null - - hide_item_by_name: (name) => - item = @find_by_name(name) - item.visible = false if item - - show_item_by_name: (name) => - item = @find_by_name(name) - item.visible = true if item diff --git a/app/assets/javascripts/admin/spree/progress.coffee b/app/assets/javascripts/admin/spree/progress.coffee index edc20a541b..f099e40842 100644 --- a/app/assets/javascripts/admin/spree/progress.coffee +++ b/app/assets/javascripts/admin/spree/progress.coffee @@ -1,27 +1,7 @@ $(document).ready -> - opts = - lines: 11 - length: 2 - width: 3 - radius: 9 - corners: 1 - rotate: 0 - color: '#fff' - speed: 0.8 - trail: 48 - shadow: false - hwaccel: true - className: 'spinner' - zIndex: 2e9 - top: 'auto' - left: 'auto' - - target = document.getElementById("spinner") - $(document).ajaxStart -> $("#progress").fadeIn() - spinner = new Spinner(opts).spin(target) $(document).ajaxStop -> - $("#progress").fadeOut() + $("#progress").fadeOut() diff --git a/app/assets/javascripts/darkswarm/all.js.coffee b/app/assets/javascripts/darkswarm/all.js.coffee index aa0fafa058..605eeb3b07 100644 --- a/app/assets/javascripts/darkswarm/all.js.coffee +++ b/app/assets/javascripts/darkswarm/all.js.coffee @@ -1,13 +1,15 @@ #= require jquery #= require jquery_ujs #= require jquery.ui.all -#= require spin # #= require angular #= require angular-cookies #= require angular-sanitize #= require angular-animate #= require angular-resource +#= require autocomplete.min.js +#= require leaflet-1.6.0.js +#= require leaflet-providers.js #= require lodash.underscore.js # bluebird.js is a dependency of angular-google-maps.js 2.0.0 #= require bluebird.js diff --git a/app/assets/javascripts/darkswarm/controllers/cart_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/cart_controller.js.coffee index ebad820ebd..28d6cb4cfe 100644 --- a/app/assets/javascripts/darkswarm/controllers/cart_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/cart_controller.js.coffee @@ -1,2 +1,4 @@ -Darkswarm.controller "CartCtrl", ($scope, Cart, $timeout) -> +Darkswarm.controller "CartCtrl", ($scope, Cart, CurrentHub) -> $scope.Cart = Cart + $scope.CurrentHub = CurrentHub + $scope.max_characters = 20 diff --git a/app/assets/javascripts/darkswarm/controllers/cart_dropdown_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/cart_dropdown_controller.js.coffee new file mode 100644 index 0000000000..048459ecd8 --- /dev/null +++ b/app/assets/javascripts/darkswarm/controllers/cart_dropdown_controller.js.coffee @@ -0,0 +1,7 @@ +Darkswarm.controller "CartDropdownCtrl", ($scope, Cart, BodyScroll) -> + $scope.Cart = Cart + $scope.showCartSidebar = false + + $scope.toggleCartSidebar = -> + $scope.showCartSidebar = !$scope.showCartSidebar + BodyScroll.toggle() diff --git a/app/assets/javascripts/darkswarm/controllers/group_page_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/group_page_controller.js.coffee index 7b44cb749b..ff7a695777 100644 --- a/app/assets/javascripts/darkswarm/controllers/group_page_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/group_page_controller.js.coffee @@ -1,6 +1,3 @@ -Darkswarm.controller "GroupPageCtrl", ($scope, enterprises, Enterprises, MapConfiguration, OfnMap) -> +Darkswarm.controller "GroupPageCtrl", ($scope, enterprises, Enterprises) -> $scope.Enterprises = Enterprises - - $scope.map = angular.copy MapConfiguration.options - $scope.mapMarkers = OfnMap.enterprise_markers enterprises $scope.embedded_layout = window.location.search.indexOf("embedded_shopfront=true") != -1 diff --git a/app/assets/javascripts/darkswarm/controllers/products/product_node_controller.js.coffee b/app/assets/javascripts/darkswarm/controllers/products/product_node_controller.js.coffee index a692af3fb5..fb8ac8d288 100644 --- a/app/assets/javascripts/darkswarm/controllers/products/product_node_controller.js.coffee +++ b/app/assets/javascripts/darkswarm/controllers/products/product_node_controller.js.coffee @@ -2,6 +2,5 @@ Darkswarm.controller "ProductNodeCtrl", ($scope, $modal, FilterSelectorsService) $scope.enterprise = $scope.product.supplier # For the modal, so it's consistent $scope.triggerProductModal = -> - $scope.productTaxonSelectors = FilterSelectorsService.createSelectors() $scope.productPropertySelectors = FilterSelectorsService.createSelectors() $modal.open(templateUrl: "product_modal.html", scope: $scope) diff --git a/app/assets/javascripts/darkswarm/directives/body_scroll.js.coffee b/app/assets/javascripts/darkswarm/directives/body_scroll.js.coffee new file mode 100644 index 0000000000..183d828d03 --- /dev/null +++ b/app/assets/javascripts/darkswarm/directives/body_scroll.js.coffee @@ -0,0 +1,9 @@ +Darkswarm.directive "bodyScroll", ($rootScope, BodyScroll) -> + restrict: 'A' + scope: true + link: (scope, elem, attrs) -> + $rootScope.$on "toggleBodyScroll", -> + if BodyScroll.disabled + elem.addClass "disable-scroll" + else + elem.removeClass "disable-scroll" diff --git a/app/assets/javascripts/darkswarm/directives/cart_toggle.js.coffee b/app/assets/javascripts/darkswarm/directives/cart_toggle.js.coffee deleted file mode 100644 index cb7e574d87..0000000000 --- a/app/assets/javascripts/darkswarm/directives/cart_toggle.js.coffee +++ /dev/null @@ -1,19 +0,0 @@ -Darkswarm.directive "cartToggle", ($document) -> - # Toggles visibility of the "cart" popover - restrict: 'A' - link: (scope, elem, attr)-> - scope.open = false - - $document.bind 'click', (event) -> - cart_button = elem[0] - element_and_parents = [event.target, event.target.parentElement, event.target.parentElement.parentElement] - cart_button_clicked = (element_and_parents.indexOf(cart_button) != -1) - - if cart_button_clicked - scope.$apply -> - scope.open = !scope.open - else - scope.$apply -> - scope.open = false - - return diff --git a/app/assets/javascripts/darkswarm/directives/open_street_map.js.coffee b/app/assets/javascripts/darkswarm/directives/open_street_map.js.coffee new file mode 100644 index 0000000000..7dbdc73669 --- /dev/null +++ b/app/assets/javascripts/darkswarm/directives/open_street_map.js.coffee @@ -0,0 +1,100 @@ +Darkswarm.directive 'ofnOpenStreetMap', ($window, Enterprises, EnterpriseModal, availableCountries, openStreetMapConfig) -> + restrict: 'E' + replace: true + scope: true + template: "
" + + link: (scope, element, attrs, ctrl, transclude)-> + map = null + markers = [] + enterpriseNames = [] + openStreetMapProviderName = openStreetMapConfig.open_street_map_provider_name + openStreetMapProviderOptions = JSON.parse(openStreetMapConfig.open_street_map_provider_options) + + average = (values) -> + total = values.reduce (sum, value) -> + sum = sum + value + , 0 + total / values.length + + averageAngle = (angleName) -> + positiveAngles = [] + negativeAngles = [] + for enterprise in Enterprises.enterprises + if enterprise.latitude? && enterprise.longitude? + if enterprise[angleName] > 0 + positiveAngles.push(enterprise[angleName]) + else + negativeAngles.push(enterprise[angleName]) + + averageNegativeAngle = average(negativeAngles) + averagePositiveAngle = average(positiveAngles) + + if negativeAngles.length == 0 + averagePositiveAngle + else if positiveAngles.length == 0 + averageNegativeAngle + else if averagePositiveAngle > averageNegativeAngle + averagePositiveAngle - averageNegativeAngle + else + averageNegativeAngle - averagePositiveAngle + + buildMarker = (enterprise, latlng, title) -> + icon = L.icon + iconUrl: enterprise.icon + marker = L.marker latlng, + draggable: true, + icon: icon, + riseOnHover: true, + title: title + marker.on "click", -> + EnterpriseModal.open enterprise + marker + + enterpriseName = (enterprise) -> + return enterprise.name + " (" + enterprise.address.address1 + ", " + enterprise.address.city + ", " + enterprise.address.state_name + ")"; + + goToEnterprise = (selectedEnterpriseName) -> + enterprise = Enterprises.enterprises.find (enterprise) -> + enterpriseName(enterprise) == selectedEnterpriseName + map.setView([enterprise.latitude, enterprise.longitude], 12) + + displayMap = -> + setMapDimensions() + averageLatitude = averageAngle("latitude") + averageLongitude = averageAngle("longitude") + zoomLevel = 6 + map = L.map('open-street-map') + L.tileLayer.provider(openStreetMapProviderName, openStreetMapProviderOptions).addTo(map) + map.setView([averageLatitude, averageLongitude], zoomLevel) + + displayEnterprises = -> + for enterprise in Enterprises.enterprises + if enterprise.latitude? && enterprise.longitude? + marker = buildMarker(enterprise, { lat: enterprise.latitude, lng: enterprise.longitude }, enterprise.name).addTo(map) + enterpriseNames.push(enterpriseName(enterprise)) + markers.push(marker) + + displaySearchField = () -> + new Autocomplete('#open-street-map--search', + onSubmit: goToEnterprise + search: searchEnterprises + ) + overwriteInlinePositionRelativeToPositionSearchField = -> + $('#open-street-map--search').css("position", "absolute") + overwriteInlinePositionRelativeToPositionSearchField() + + searchEnterprises = (input) -> + if input.length < 1 + return [] + enterpriseNames.filter (country) -> + country.toLowerCase().includes input.toLowerCase() + + setMapDimensions = -> + height = $window.innerHeight - element.offset().top + element.css "width", "100%" + element.css "height", (height + "px") + + displayMap() + displayEnterprises() + displaySearchField() diff --git a/app/assets/javascripts/darkswarm/directives/page_alert.js.coffee b/app/assets/javascripts/darkswarm/directives/page_alert.js.coffee index a3858444ae..666daaec64 100644 --- a/app/assets/javascripts/darkswarm/directives/page_alert.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/page_alert.js.coffee @@ -14,8 +14,8 @@ Darkswarm.directive "ofnPageAlert", ($timeout) -> # Wait a moment after page load before showing the alert. Otherwise we often miss the # start of the animation. $timeout -> - container_elems.addClass("move-down") + container_elems.addClass("move-up") , 1000 scope.close = -> - container_elems.removeClass("move-down") + container_elems.removeClass("move-up") diff --git a/app/assets/javascripts/darkswarm/directives/smooth_scroll_to.js.coffee b/app/assets/javascripts/darkswarm/directives/smooth_scroll_to.js.coffee index c3bcc9590d..34552016c4 100644 --- a/app/assets/javascripts/darkswarm/directives/smooth_scroll_to.js.coffee +++ b/app/assets/javascripts/darkswarm/directives/smooth_scroll_to.js.coffee @@ -10,6 +10,5 @@ Darkswarm.directive "ofnSmoothScrollTo", ($location, $document)-> # Scrolling is confused by our position:fixed top bar and page alert bar # - add an offset to scroll to the correct location, plus 5px buffer offset = $("nav.top-bar").height() - offset += $(".page-alert.move-down").height() offset += 5 $document.scrollTo target, offset, 1000 diff --git a/app/assets/javascripts/darkswarm/services/body_scroll.js.coffee b/app/assets/javascripts/darkswarm/services/body_scroll.js.coffee new file mode 100644 index 0000000000..84c8ed9337 --- /dev/null +++ b/app/assets/javascripts/darkswarm/services/body_scroll.js.coffee @@ -0,0 +1,7 @@ +angular.module("Darkswarm").factory "BodyScroll", ($rootScope) -> + new class BodyScroll + disabled: false + + toggle: -> + @disabled = !@disabled + $rootScope.$broadcast "toggleBodyScroll" diff --git a/app/assets/javascripts/darkswarm/services/checkout.js.coffee b/app/assets/javascripts/darkswarm/services/checkout.js.coffee index f0da646ebe..4ec3081ad3 100644 --- a/app/assets/javascripts/darkswarm/services/checkout.js.coffee +++ b/app/assets/javascripts/darkswarm/services/checkout.js.coffee @@ -21,14 +21,18 @@ Darkswarm.factory 'Checkout', ($injector, CurrentOrder, ShippingMethods, StripeE 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 + try + @loadFlash(error: t("checkout.failed")) # inform the user about the unexpected error + finally + throw error # generate a BugsnagJS alert handle_checkout_error_response: (response) => - if response.data.path + throw response unless response.data? + + if response.data.path? Navigation.go response.data.path else - throw response unless response.data.flash + throw response unless response.data.flash? @errors = response.data.errors @loadFlash(response.data.flash) diff --git a/app/assets/javascripts/darkswarm/services/enterprises.js.coffee b/app/assets/javascripts/darkswarm/services/enterprises.js.coffee index 46e50cb574..843749c2e6 100644 --- a/app/assets/javascripts/darkswarm/services/enterprises.js.coffee +++ b/app/assets/javascripts/darkswarm/services/enterprises.js.coffee @@ -1,4 +1,4 @@ -Darkswarm.factory 'Enterprises', (enterprises, ShopsResource, CurrentHub, Taxons, Dereferencer, Matcher, Geo, $rootScope) -> +Darkswarm.factory 'Enterprises', (enterprises, ShopsResource, CurrentHub, Taxons, Dereferencer, Matcher, GmapsGeo, $rootScope) -> new class Enterprises enterprises: [] enterprises_by_id: {} @@ -59,7 +59,7 @@ Darkswarm.factory 'Enterprises', (enterprises, ShopsResource, CurrentHub, Taxons false calculateDistance: (query, firstMatching) -> - if query?.length > 0 and Geo.OK + if query?.length > 0 and GmapsGeo.OK if firstMatching? @setDistanceFrom firstMatching else @@ -68,9 +68,9 @@ Darkswarm.factory 'Enterprises', (enterprises, ShopsResource, CurrentHub, Taxons @resetDistance() calculateDistanceGeo: (query) -> - Geo.geocode query, (results, status) => + GmapsGeo.geocode query, (results, status) => $rootScope.$apply => - if status == Geo.OK + if status == GmapsGeo.OK #console.log "Geocoded #{query} -> #{results[0].geometry.location}." @setDistanceFrom results[0].geometry.location else @@ -79,7 +79,7 @@ Darkswarm.factory 'Enterprises', (enterprises, ShopsResource, CurrentHub, Taxons setDistanceFrom: (locatable) -> for enterprise in @enterprises - enterprise.distance = Geo.distanceBetween enterprise, locatable + enterprise.distance = GmapsGeo.distanceBetween enterprise, locatable $rootScope.$broadcast 'enterprisesChanged' resetDistance: -> diff --git a/app/assets/javascripts/darkswarm/services/geo.js.erb.coffee b/app/assets/javascripts/darkswarm/services/gmaps_geo.js.erb.coffee similarity index 84% rename from app/assets/javascripts/darkswarm/services/geo.js.erb.coffee rename to app/assets/javascripts/darkswarm/services/gmaps_geo.js.erb.coffee index 866dc2f742..9b78ea4bcc 100644 --- a/app/assets/javascripts/darkswarm/services/geo.js.erb.coffee +++ b/app/assets/javascripts/darkswarm/services/gmaps_geo.js.erb.coffee @@ -1,5 +1,5 @@ -Darkswarm.service "Geo", -> - new class Geo +Darkswarm.service "GmapsGeo", -> + new class GmapsGeo OK: google?.maps?.GeocoderStatus?.OK # Usage: @@ -10,7 +10,7 @@ Darkswarm.service "Geo", -> # console.log "Error: #{status}" geocode: (address, callback) -> geocoder = new google.maps.Geocoder() - geocoder.geocode {'address': address, 'region': "<%= Spree::Country.find_by_id(Spree::Config[:default_country_id]).iso %>"}, callback + geocoder.geocode {'address': address, 'region': "<%= Spree::Country.find_by(id: Spree::Config[:default_country_id]).iso %>"}, callback distanceBetween: (src, dst) -> google.maps.geometry.spherical.computeDistanceBetween @toLatLng(src), @toLatLng(dst) diff --git a/app/assets/javascripts/darkswarm/services/map_configuration.js.coffee b/app/assets/javascripts/darkswarm/services/map_configuration.js.erb.coffee similarity index 95% rename from app/assets/javascripts/darkswarm/services/map_configuration.js.coffee rename to app/assets/javascripts/darkswarm/services/map_configuration.js.erb.coffee index 93e4104f0a..61598c414c 100644 --- a/app/assets/javascripts/darkswarm/services/map_configuration.js.coffee +++ b/app/assets/javascripts/darkswarm/services/map_configuration.js.erb.coffee @@ -4,7 +4,7 @@ Darkswarm.factory "MapConfiguration", -> center: latitude: -37.4713077 longitude: 144.7851531 - cluster_icon: 'assets/map_009-cluster.svg' + cluster_icon: "<%= image_path('map_009-cluster.svg') %>" zoom: 12 additional_options: # mapTypeId: 'satellite' diff --git a/app/assets/javascripts/darkswarm/services/variants.js.coffee b/app/assets/javascripts/darkswarm/services/variants.js.coffee index 456fd00f01..a650db5cd7 100644 --- a/app/assets/javascripts/darkswarm/services/variants.js.coffee +++ b/app/assets/javascripts/darkswarm/services/variants.js.coffee @@ -20,7 +20,6 @@ Darkswarm.factory 'Variants', -> name = variant.product_name else name = "#{variant.product_name} - #{variant.name_to_display}" - name += " (#{variant.options_text})" if variant.options_text name lineItemFor: (variant) -> diff --git a/app/assets/javascripts/templates/admin/columns_dropdown.html.haml b/app/assets/javascripts/templates/admin/columns_dropdown.html.haml index cae123bbcf..f06944182a 100644 --- a/app/assets/javascripts/templates/admin/columns_dropdown.html.haml +++ b/app/assets/javascripts/templates/admin/columns_dropdown.html.haml @@ -4,7 +4,7 @@ %div.menu{ 'ng-show' => "expanded" } %div.menu_item{ ng: { repeat: "column in columns", click: "toggle(column)", class: "{selected: column.visible}" } } %span.check - %span.name {{column.name }} + %span.name {{ column.name }} %hr %div.menu_item.text-center %input.fullwidth.orange{ type: "button", ng: { value: "saved() ? 'Saved': 'Saving'", show: "saved() || saving", disabled: "saved()" } } diff --git a/app/assets/javascripts/templates/product_modal.html.haml b/app/assets/javascripts/templates/product_modal.html.haml index 6282bc439e..9c65bbbad7 100644 --- a/app/assets/javascripts/templates/product_modal.html.haml +++ b/app/assets/javascripts/templates/product_modal.html.haml @@ -1,6 +1,5 @@ .row - - .columns.small-12.large-6.product-header + .columns.small-12.medium-6.large-6.product-header %h3{"ng-bind" => "::product.name"} %span %em {{'products_from' | t}} @@ -8,19 +7,14 @@ %br - .filter-shopfront.taxon-selectors.inline-block - %filter-selector{ 'selector-set' => "productTaxonSelectors", objects: "[product] | taxonsOf" } - .filter-shopfront.property-selectors.inline-block %filter-selector{ 'selector-set' => "productPropertySelectors", objects: "[product] | propertiesWithValuesOf" } - %div{"ng-if" => "product.description_html"} - %hr + .product-description{"ng-if" => "product.description_html"} %p.text-small{"ng-bind-html" => "::product.description_html"} - %hr - .columns.small-12.large-6 - %img.product-img{"ng-src" => "{{::product.largeImage}}", "ng-if" => "::product.largeImage"} - %img.product-img.placeholder{ src: "/assets/noimage/large.png", "ng-if" => "::!product.largeImage"} + .columns.small-12.medium-6.large-6.product-img + %img{"ng-src" => "{{::product.largeImage}}", "ng-if" => "::product.largeImage"} + %img.placeholder{ src: "/assets/noimage/large.png", "ng-if" => "::!product.largeImage"} %ng-include{src: "'partials/close.html'"} diff --git a/app/assets/javascripts/templates/signup.html.haml b/app/assets/javascripts/templates/signup.html.haml index eb7de03203..4ee026adb5 100644 --- a/app/assets/javascripts/templates/signup.html.haml +++ b/app/assets/javascripts/templates/signup.html.haml @@ -40,6 +40,8 @@ tabindex: 2, inputmode: "password", "ng-model" => "spree_user.password_confirmation"} + %span.error{"ng-show" => "errors.password_confirmation != null"} + {{ errors.password_confirmation.join(' ') }} .row .large-12.columns %input.button.primary{name: "commit", diff --git a/app/assets/stylesheets/admin/components/progress.scss b/app/assets/stylesheets/admin/components/progress.scss index 189689c764..c3ea8c69b3 100644 --- a/app/assets/stylesheets/admin/components/progress.scss +++ b/app/assets/stylesheets/admin/components/progress.scss @@ -1,38 +1,31 @@ @import 'admin/globals/variables'; @import 'admin/globals/mixins'; -#progress { - display: none; +#progress { + @include border-radius(10px); position: fixed; - top: 0; + top: -10px; + left: 50%; z-index: 1000; opacity: 0.8; - width: 100%; + width: 200px; + background-color: $spree-blue; + color: $color-1; + display: none; + font-size: 120%; + font-weight: bold; + line-height: 40px; + margin-left: -100px; + padding-top: 15px; + text-align: center; + text-transform: uppercase; - .wrapper { - @include border-radius(10px); - top: -10px; + .spinner { position: absolute; left: 50%; - width: 200px; - margin-left: -100px; - padding: 11px 0; - background-color: $color-3; - color: $color-1; - text-align: center; + width: 30px; + height: 30px; + top: -5px; + margin-left: -15px; } - - #spinner { - position: absolute; - top: 10px; - left: 50%; - margin-left: -5px; - } - - .progress-message { - font-size: 120%; - font-weight: $font-weight-bold; - margin-top: 20px; - text-transform: uppercase; - } -} \ No newline at end of file +} diff --git a/app/assets/stylesheets/admin/components/todo.scss b/app/assets/stylesheets/admin/components/todo.scss index 8528e0cb8e..2edb71995d 100644 --- a/app/assets/stylesheets/admin/components/todo.scss +++ b/app/assets/stylesheets/admin/components/todo.scss @@ -1,5 +1,3 @@ -@import '../plugins/font-awesome'; - .todolist{ .todo { &.done { @@ -18,10 +16,6 @@ .steps { display: none; } - - i { - @extend .icon-check - } } } } diff --git a/app/assets/stylesheets/admin/icons.css.scss b/app/assets/stylesheets/admin/icons.css.scss index 9bd900d083..e69de29bb2 100644 --- a/app/assets/stylesheets/admin/icons.css.scss +++ b/app/assets/stylesheets/admin/icons.css.scss @@ -1,4 +0,0 @@ -@import 'plugins/font-awesome'; - -.icon-refund:before { @extend .icon-ok:before } -.icon-credit:before { @extend .icon-ok:before } diff --git a/app/assets/stylesheets/admin/welcome.css.scss b/app/assets/stylesheets/admin/welcome.css.scss index 77cd21e134..89f277db4d 100644 --- a/app/assets/stylesheets/admin/welcome.css.scss +++ b/app/assets/stylesheets/admin/welcome.css.scss @@ -7,7 +7,7 @@ @include fullbg; background-color: black; - background-image: url("/assets/home/tagline-bg.jpg"); + background-image: image-url("home/tagline-bg.jpg"); background-repeat: no-repeat; background-position: center center; margin-bottom: 2em; diff --git a/app/assets/stylesheets/darkswarm/_shop-filters.css.scss b/app/assets/stylesheets/darkswarm/_shop-filters.css.scss index 5bb8b5e381..91bb5c7933 100644 --- a/app/assets/stylesheets/darkswarm/_shop-filters.css.scss +++ b/app/assets/stylesheets/darkswarm/_shop-filters.css.scss @@ -27,13 +27,11 @@ a, a.button { display: block; - padding-top: 0.5rem; @include border-radius(0.5em); border: 1px solid $border-clr; padding: 0.5em 0.625em; - font-size: 0.875em; color: $base-clr; font-size: 0.75em; background: white; diff --git a/app/assets/stylesheets/darkswarm/_shop-modals.css.scss b/app/assets/stylesheets/darkswarm/_shop-modals.css.scss index 6215e22c9f..bb6b6480dc 100644 --- a/app/assets/stylesheets/darkswarm/_shop-modals.css.scss +++ b/app/assets/stylesheets/darkswarm/_shop-modals.css.scss @@ -1,9 +1,30 @@ .product-header { + padding-left: 1.5rem; + h1, h2, h3, h4, h5, h6 { - margin: 0; + margin: 0.2rem 1.5rem 0 0; } - hr { - margin: 0.5em 0; + span { + color: $grey-500; + } + + .product-description { + margin: 1rem 0.25rem 0.25rem 0; + } + + .property-selectors li { + margin: 0 0.25rem 0.25rem 0; + padding: 0.4rem 0 0; + + a { + border: 1px solid $grey-300; + font-weight: normal; + padding: 0.15rem 0.5rem; + } + + span { + color: $grey-600; + } } } diff --git a/app/assets/stylesheets/darkswarm/_shop-navigation.css.scss b/app/assets/stylesheets/darkswarm/_shop-navigation.css.scss index 95bd6b1059..d3febdb28f 100644 --- a/app/assets/stylesheets/darkswarm/_shop-navigation.css.scss +++ b/app/assets/stylesheets/darkswarm/_shop-navigation.css.scss @@ -62,7 +62,9 @@ ordercycle { } select { - background-image: url('/assets/white-caret.svg'); + background-image: image-url('white-caret.svg'); + background-size: 30px auto; + background-position-x: 102%; } p { @@ -71,24 +73,27 @@ ordercycle { select, p { - width: inherit; display: inline-block; color: $white; background-color: transparent; border: 0; + border-radius: 0 $radius-small $radius-small 0; margin-bottom: 0; + padding: 0.5em 1.25em 0.5em 0.75em; font-size: 1em; line-height: 1.3em; - padding: 0.5em 1.25em 0.5em 0.75em; height: 2.35em; - background-size: 30px auto; - border-radius: 0 $radius-small $radius-small 0; min-width: 13em; + width: 200px; @include breakpoint(mobile) { width: 100%; min-width: 0; } + + @media all and (min-width: 640px) and (max-width: 1024px), (min-width: 1200px) { + width: 250px; + } } option { @@ -107,6 +112,7 @@ ordercycle { @include breakpoint(mobile) { display: flex; + margin-right: 0; } } @@ -141,7 +147,7 @@ shop ordercycle { select { background-color: $white; - background-image: url('/assets/black-caret.svg'); + background-image: image-url('black-caret.svg'); color: $grey-500; font-style: italic; } @@ -162,7 +168,7 @@ shop ordercycle { @include breakpoint(tablet) { float: none; - padding: 0 0 10px; + padding: 0; } } diff --git a/app/assets/stylesheets/darkswarm/_shop-taxon-flag.css.scss b/app/assets/stylesheets/darkswarm/_shop-taxon-flag.css.scss index e1b0d8ccbe..b6b237215e 100644 --- a/app/assets/stylesheets/darkswarm/_shop-taxon-flag.css.scss +++ b/app/assets/stylesheets/darkswarm/_shop-taxon-flag.css.scss @@ -4,7 +4,7 @@ products { product { .taxon-flag { - background: transparent url("/assets/flag.svg") top center no-repeat; + background: transparent image-url("flag.svg") top center no-repeat; background-size: 34px 39px; min-height: 40px; width: 34px; diff --git a/app/assets/stylesheets/darkswarm/all.scss b/app/assets/stylesheets/darkswarm/all.scss index ee1c4fc690..7698726035 100644 --- a/app/assets/stylesheets/darkswarm/all.scss +++ b/app/assets/stylesheets/darkswarm/all.scss @@ -3,6 +3,9 @@ * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at * the top of the compiled file, but it's generally better to create a new file per style scope. + *= require autocomplete + *= require leaflet + *= require_self */ @import 'variables'; @@ -13,7 +16,7 @@ @import 'layout/*'; @import '*'; @import 'pages/*'; -@import '../web/all'; +@import 'web/all'; ofn-modal { display: block; diff --git a/app/assets/stylesheets/darkswarm/animations.scss b/app/assets/stylesheets/darkswarm/animations.scss index b3848777ba..d7fb952907 100644 --- a/app/assets/stylesheets/darkswarm/animations.scss +++ b/app/assets/stylesheets/darkswarm/animations.scss @@ -143,8 +143,8 @@ } .reveal-modal-bg.in { - filter: alpha(opacity = 50); - opacity: 0.5; + filter: alpha(opacity = 75); + opacity: 0.75; } .animate-repeat { diff --git a/app/assets/stylesheets/darkswarm/cart-dropdown.css.scss b/app/assets/stylesheets/darkswarm/cart-dropdown.css.scss new file mode 100644 index 0000000000..ca3dd6a1a2 --- /dev/null +++ b/app/assets/stylesheets/darkswarm/cart-dropdown.css.scss @@ -0,0 +1,124 @@ +@import "mixins"; +@import "variables"; +@import "branding"; + +.expanding-sidebar.cart-sidebar { + .background { + z-index: 150; + } + + .sidebar { + padding: $topbar-height 0 0; + background-color: $white; + z-index: 160; + + @include breakpoint(desktop) { + padding: $mobile-nav-height 0 0; + } + } + + .cart-header { + background-color: $white; + border-bottom: 1px solid $grey-100; + min-height: 3.5em; + padding: 1em; + position: sticky; + top: 0; + + .title { + color: $grey-800; + margin: 0; + } + + .close { + color: $grey-500; + float: right; + + i { + vertical-align: middle; + } + } + } + + .cart-content { + margin-bottom: $sidebar-footer-height + 2em; + + .cart-empty { + text-align: center; + padding-top: 10em; + width: 100%; + + p { + font-size: 1.5em; + } + } + } + + .go-shopping { + display: none; + padding: 0 1.5em; + + @include breakpoint(mobile) { + display: inline-block; + } + } + + table { + width: 100%; + border: 0; + border-spacing: 0; + margin: 0; + + .product-cart { + background-color: $white; + + td { + border-bottom: 1px solid $grey-100; + padding: 0.75em 1em 0.5em; + vertical-align: top; + + &.image { + width: 42px; + padding: 0.5em 0 0.5em 1em; + } + + span { + color: $grey-800; + font-size: 16px; + line-height: 1.4em; + } + + img { + max-width: 56px; + max-height: 56px; + } + + .options-text { + color: $grey-500; + font-size: 14px; + } + } + } + } + + .cart-total { + color: $white; + text-align: center; + margin: -0.5em 0 0.75em; + } + + .sidebar, + .sidebar-footer { + width: 375px; + margin-right: -375px; + + @include breakpoint(mobile) { + width: 100%; + margin-right: -100%; + } + } + + .sidebar-footer { + z-index: 170; + } +} diff --git a/app/assets/stylesheets/darkswarm/cart-page.css.scss b/app/assets/stylesheets/darkswarm/cart-page.css.scss new file mode 100644 index 0000000000..b2b17fa0bb --- /dev/null +++ b/app/assets/stylesheets/darkswarm/cart-page.css.scss @@ -0,0 +1,75 @@ +@import "mixins"; +@import "branding"; +@import "compass/css3/user-interface"; +@import "variables"; + +#update-cart { + #errorExplanation { + display: none; + } +} + +#cart-detail { + .cart-item-delete, + .bought-item-delete { + a { + font-size: 1.125em; + } + } + + .out-of-stock { + color: $clr-brick; + } + + button, + .button { + margin: 0; + } + + .toggle-bought { + cursor: pointer; + } + + .bought td { + color: $med-grey; + + h5 { + color: $med-grey; + } + + .already-confirmed { + float: right; + } + } + + input { + &.ng-invalid-stock, + &.ng-invalid-number { + border: 1px solid $clr-brick; + } + } +} + +.item-thumb-image { + display: none; + + @media screen and (min-width: 640px) { + display: inline-block; + float: left; + padding-right: 0.5em; + width: 36px; + height: 36px; + } +} + +.links { + .button { + padding: 1.125rem 0 1.1875rem; + width: 210px; + font-size: 1.1em; + + @include breakpoint(mobile) { + width: 100%; + } + } +} diff --git a/app/assets/stylesheets/darkswarm/distributor_header.css.scss b/app/assets/stylesheets/darkswarm/distributor_header.css.scss index 8e9ebf769b..f7591cd986 100644 --- a/app/assets/stylesheets/darkswarm/distributor_header.css.scss +++ b/app/assets/stylesheets/darkswarm/distributor_header.css.scss @@ -11,7 +11,7 @@ section { display: block; background: $white; position: relative; - z-index: 2; + z-index: 20; .details { box-sizing: border-box; @@ -20,10 +20,6 @@ section { padding: 30px 0 0; position: relative; - select { - width: 200px; - } - img { display: block; height: 100px; diff --git a/app/assets/stylesheets/darkswarm/expanding-sidebar.css.scss b/app/assets/stylesheets/darkswarm/expanding-sidebar.css.scss new file mode 100644 index 0000000000..da1034cf42 --- /dev/null +++ b/app/assets/stylesheets/darkswarm/expanding-sidebar.css.scss @@ -0,0 +1,79 @@ +@import "mixins"; +@import "variables"; +@import "branding"; + +.expanding-sidebar { + display: flex; + flex-direction: column; + height: 100%; + + .background { + position: fixed; + top: 0; + right: 0; + z-index: 200; + height: 100%; + width: 100%; + background-color: $shop-sidebar-overlay; + opacity: 0; + transition: opacity $transition-sidebar; + } + + &.shown { + .background { + opacity: 1; + } + + .sidebar, + .sidebar-footer { + margin-right: 0; + } + } + + .sidebar { + position: fixed; + top: 0; + right: 0; + z-index: 210; + height: 100%; + width: $sidebar-large-width; + margin-right: -$sidebar-large-width; + background-color: rgba($white, 0.95); + padding: 1em; + transition: margin $transition-sidebar; + overflow-y: auto; + } + + .sidebar-footer { + background-color: $grey-800; + width: $sidebar-large-width; + margin-right: -$sidebar-large-width; + min-height: $sidebar-footer-height; + position: fixed; + bottom: 0; + right: 0; + transition: margin $transition-sidebar; + padding: 1em; + + button, + a.button { + width: 48%; + } + } + + @include breakpoint(tablet) { + .sidebar, + .sidebar-footer { + width: $sidebar-medium-width; + margin-right: -$sidebar-medium-width; + } + } + + @include breakpoint(mobile) { + .sidebar, + .sidebar-footer { + width: $sidebar-small-width; + margin-right: -$sidebar-small-width; + } + } +} diff --git a/app/assets/stylesheets/darkswarm/footer.scss b/app/assets/stylesheets/darkswarm/footer.scss index 6a7f12dda6..9826970141 100644 --- a/app/assets/stylesheets/darkswarm/footer.scss +++ b/app/assets/stylesheets/darkswarm/footer.scss @@ -50,7 +50,7 @@ footer { width: 100%; border: 1px solid rgba($dark-grey, 0.35); - background-image: url("/assets/tile-wide.png"); + background-image: image-url("tile-wide.png"); background-position: center center; background-color: #bbb; padding: 12px 0 8px 0; diff --git a/app/assets/stylesheets/darkswarm/home_panes.css.scss b/app/assets/stylesheets/darkswarm/home_panes.css.scss index 60f881462d..20a8d82687 100644 --- a/app/assets/stylesheets/darkswarm/home_panes.css.scss +++ b/app/assets/stylesheets/darkswarm/home_panes.css.scss @@ -42,7 +42,7 @@ } #stats.pane { - background-image: url("/assets/home/background-blurred-oranges.jpg"); + background-image: image-url("home/background-blurred-oranges.jpg"); background-position: center center; background-color: $ofn-grey; @@ -94,7 +94,7 @@ } .home-icon-box { - background-image: url("/assets/ofn-o.png"); + background-image: image-url("ofn-o.png"); background-position: center center; background-repeat: no-repeat; background-size: auto 100%; @@ -121,15 +121,15 @@ background-size: auto 100%; &.search { - background-image: url("/assets/icon-mask-magnifier.png"); + background-image: image-url("icon-mask-magnifier.png"); } &.shop { - background-image: url("/assets/icon-mask-apple.png"); + background-image: image-url("icon-mask-apple.png"); } &.pick-up-delivery { - background-image: url("/assets/icon-mask-truck.png"); + background-image: image-url("icon-mask-truck.png"); } } } diff --git a/app/assets/stylesheets/darkswarm/home_tagline.css.scss b/app/assets/stylesheets/darkswarm/home_tagline.css.scss index ffe4204869..c6cc15c9e8 100644 --- a/app/assets/stylesheets/darkswarm/home_tagline.css.scss +++ b/app/assets/stylesheets/darkswarm/home_tagline.css.scss @@ -13,7 +13,7 @@ @include fullbg; background-color: $ofn-grey; - background-image: url("/assets/home/home.jpg"); + background-image: image-url("home/home.jpg"); position: fixed; left: 0; right: 0; diff --git a/app/assets/stylesheets/darkswarm/images.css.scss b/app/assets/stylesheets/darkswarm/images.css.scss index cd939e3b42..739914d709 100644 --- a/app/assets/stylesheets/darkswarm/images.css.scss +++ b/app/assets/stylesheets/darkswarm/images.css.scss @@ -3,18 +3,22 @@ @import "branding"; .product-img { - padding: 5px; - margin-bottom: 10px; - outline: 1px solid #ccc; + text-align: center; - @include box-shadow(0 1px 2px 1px rgba(0, 0, 0, 0.15)); + img { + padding: 0.3rem; - // placeholder for when no product images - &.placeholder { - opacity: 0.35; + // placeholder for when no product images + &.placeholder { + opacity: 0.35; - @include breakpoint(desktop) { - display: none; + @include breakpoint(desktop) { + display: none; + } + } + + @media only screen and (max-width: 1024px) { + margin: 0 0 0.5rem; } } } @@ -49,10 +53,3 @@ .producer-logo { max-width: 220px; } - -@media only screen and (max-width: 1024px) { - .product-img { - margin-top: 2em; - margin-bottom: 1em; - } -} diff --git a/app/assets/stylesheets/darkswarm/map.css.scss b/app/assets/stylesheets/darkswarm/map.css.scss index b0df5b66da..8f9ee717f9 100644 --- a/app/assets/stylesheets/darkswarm/map.css.scss +++ b/app/assets/stylesheets/darkswarm/map.css.scss @@ -6,6 +6,7 @@ .map-container { width: 100%; + position: relative; map, .angular-google-map-container, google-map, .angular-google-map { display: block; @@ -38,6 +39,30 @@ background: rgba(255, 255, 255, 1); } } + + #open-street-map { + z-index: 1; + } + + #open-street-map--search { + top: 16px; + left: 54px; + width: 50%; + z-index: 1000; + + .autocomplete-input, + .autocomplete-result-list { + border: 2px solid $grey-500; + + &:hover, &:active, &:focus { + border-color: $clr-brick; + } + } + + .autocomplete-result-list { + border-top: 1px dotted $grey-500; + } + } } .map-footer { @@ -63,3 +88,8 @@ left: 0px; } } + +.tabs-content .map-footer { + position: relative; + bottom: 30px; +} diff --git a/app/assets/stylesheets/darkswarm/menu.css.scss b/app/assets/stylesheets/darkswarm/menu.css.scss index abefec7a23..774d2bc146 100644 --- a/app/assets/stylesheets/darkswarm/menu.css.scss +++ b/app/assets/stylesheets/darkswarm/menu.css.scss @@ -11,6 +11,7 @@ nav.top-bar { font-size: 16px; margin-bottom: 0; height: $topbar-height; + z-index: 190; } @media #{$large-only} { @@ -174,7 +175,7 @@ nav.top-bar { height: $mobile-nav-height; position: fixed; width: 100%; - z-index: 1; + z-index: 190; // Above cart sidebar and shaded overlay .cart-span { background-color: #f4704c; @@ -225,14 +226,7 @@ nav.top-bar { .off-canvas-wrap .tab-bar .menu-icon { @include box-shadow(none); -} - -.off-canvas-wrap.move-right .tab-bar .menu-icon span { - box-shadow: 0 0px 0 1px #666, 0 7px 0 1px #666, 0 14px 0 1px #666; -} - -.tab-bar .menu-icon span::after { - box-shadow: 0 0 0 1px black, 0 7px 0 1px black, 0 14px 0 1px black; + text-indent: 0; } .tab-bar .ofn-logo { diff --git a/app/assets/stylesheets/darkswarm/mixins.scss b/app/assets/stylesheets/darkswarm/mixins.scss index 2b38d89dea..41f90679fa 100644 --- a/app/assets/stylesheets/darkswarm/mixins.scss +++ b/app/assets/stylesheets/darkswarm/mixins.scss @@ -5,7 +5,7 @@ // Generic \\ @mixin tiledPane { - background-image: url("/assets/tile-wide.png"); + background-image: image-url("tile-wide.png"); background-color: $brand-colour; background-position: center center; @@ -236,7 +236,7 @@ @mixin producersbg { background-color: lighten($clr-turquoise, 68%); - background-image: url("/assets/producers.svg"); + background-image: image-url("producers.svg"); background-position: center 50px; background-repeat: no-repeat; background-size: 922px 763px; @@ -244,13 +244,13 @@ @mixin hubsbg { background-color: $brand-colour; - background-image: url("/assets/hubs-bg.jpg"); + background-image: image-url("hubs-bg.jpg"); background-position: center center; } @mixin groupsbg { background-color: lighten($clr-brick, 56%); - background-image: url("/assets/groups.svg"); + background-image: image-url("groups.svg"); background-position: center 50px; background-repeat: no-repeat; background-size: 922px 922px; diff --git a/app/assets/stylesheets/darkswarm/modals.css.scss b/app/assets/stylesheets/darkswarm/modals.css.scss index 734d388acf..5f9cebc067 100644 --- a/app/assets/stylesheets/darkswarm/modals.css.scss +++ b/app/assets/stylesheets/darkswarm/modals.css.scss @@ -5,8 +5,6 @@ dialog , .reveal-modal { border: none; outline: none; - padding: 30px 20px 0 20px; - border-bottom: 30px solid white; overflow-y: scroll; overflow-x: hidden; min-height: 260px; @@ -18,23 +16,26 @@ dialog // Reveal.js break point: // @media only screen and (max-width: 40.063em) - // Small - when modal IS full screen + // Small - smaller outside area @media only screen and (max-width: 640px) { - left: 0; - max-height: 100%; - position: absolute !important; - top: 0; + left: 4%; + max-height: 92%; + max-width: 92%; + padding: 15px 0 0; + top: 4%; } - // Medium and up - when modal IS NOT full screen + // Medium and up - larger outside area @media only screen and (min-width: 641px) { + border-bottom: 30px solid $white; max-height: 90%; + padding: 30px 20px 0 20px; top: 5%; } } .reveal-modal-bg { - background-color: rgba(0, 0, 0, 0.85); + background-color: $black; position: fixed; } @@ -58,6 +59,10 @@ dialog dialog .close-reveal-modal , .reveal-modal .close-reveal-modal { @include close-button(0.25rem); + + background-color: $grey-500; + color: $white; + font-size: 1.5rem; right: 0.25rem; } diff --git a/app/assets/stylesheets/darkswarm/page_alert.css.scss b/app/assets/stylesheets/darkswarm/page_alert.css.scss index 4be82c8c2e..08f35944c9 100644 --- a/app/assets/stylesheets/darkswarm/page_alert.css.scss +++ b/app/assets/stylesheets/darkswarm/page_alert.css.scss @@ -14,7 +14,7 @@ $page-alert-height: 55px; border-left: none; border-right: none; background-color: #bbb; - background-image: url("/assets/tile-wide.png"); + background-image: image-url("tile-wide.png"); background-position: center center; padding: 12px 0 8px 0; margin: 0; @@ -55,19 +55,18 @@ $page-alert-height: 55px; .off-canvas-fixed nav.tab-bar, .off-canvas-fixed .page-alert { @include transition(all 1000ms ease-in-out); - - &.move-down { - margin-top: $page-alert-height; - } } .off-canvas-wrap .page-alert { - top: -1 * $page-alert-height; + bottom: -1 * $page-alert-height; + top: unset; z-index: 100; -} -.off-canvas-wrap.move-right .inner-wrap.move-down { - .left-off-canvas-menu { - top: -1 * $page-alert-height; + &.move-up { + bottom: 0; + } + + .alert-box { + border-bottom: 0; } } diff --git a/app/assets/stylesheets/darkswarm/pages/login_modal.css.scss b/app/assets/stylesheets/darkswarm/pages/login_modal.css.scss index e6baba3393..265c74519c 100644 --- a/app/assets/stylesheets/darkswarm/pages/login_modal.css.scss +++ b/app/assets/stylesheets/darkswarm/pages/login_modal.css.scss @@ -23,6 +23,12 @@ text-decoration: underline; } } + + @media only screen and (max-width: 640px) { + .tabbable { + margin: 0 15px; + } + } } @media only screen and (min-width: 1025px) { diff --git a/app/assets/stylesheets/darkswarm/registration.css.scss b/app/assets/stylesheets/darkswarm/registration.css.scss index 1f80038f18..f97f2b9271 100644 --- a/app/assets/stylesheets/darkswarm/registration.css.scss +++ b/app/assets/stylesheets/darkswarm/registration.css.scss @@ -2,6 +2,10 @@ @import "mixins"; #registration-modal { + @media only screen and (max-width: 640px) { + margin: 0 15px; + } + header { text-align: center; diff --git a/app/assets/stylesheets/darkswarm/shop.css.scss b/app/assets/stylesheets/darkswarm/shop.css.scss index 6c477acb48..6f411db6e9 100644 --- a/app/assets/stylesheets/darkswarm/shop.css.scss +++ b/app/assets/stylesheets/darkswarm/shop.css.scss @@ -11,88 +11,7 @@ @import "shop-taxon-flag"; @import "shop-popovers"; -$sidebar-small-width: 75%; -$sidebar-medium-width: 65%; -$sidebar-large-width: 45%; -$sidebar-footer-height: 5em; - .darkswarm { - .shop-filters-sidebar { - display: flex; - flex-direction: column; - height: 100%; - - .background { - position: fixed; - top: 0; - right: 0; - z-index: 200; - height: 100%; - width: 100%; - background-color: $shop-sidebar-overlay; - opacity: 0; - transition: opacity $transition-sidebar; - } - - &.shown { - .background { - opacity: 1; - } - - .sidebar, .sidebar-footer { - margin-right: 0; - } - } - - .sidebar { - position: fixed; - top: 0; - right: 0; - z-index: 210; - height: 100%; - width: $sidebar-large-width; - margin-right: -$sidebar-large-width; - background-color: rgba($white, 0.95); - padding: 1em; - transition: margin $transition-sidebar; - overflow-y: scroll; - - .property-selectors { - margin-bottom: $sidebar-footer-height + 2em; - } - } - - .sidebar-footer { - background-color: $grey-800; - width: $sidebar-large-width; - margin-right: -$sidebar-large-width; - height: $sidebar-footer-height; - position: fixed; - bottom: 0; - right: 0; - transition: margin $transition-sidebar; - padding: 1em; - - button { - width: 48%; - } - } - - @include breakpoint(tablet) { - .sidebar, .sidebar-footer { - width: $sidebar-medium-width; - margin-right: -$sidebar-medium-width; - } - } - - @include breakpoint(mobile) { - .sidebar, .sidebar-footer { - width: $sidebar-small-width; - margin-right: -$sidebar-small-width; - } - } - } - products { display: block; @@ -205,11 +124,13 @@ $sidebar-footer-height: 5em; .open-shop-message { a { - color: #0096ad; + color: $teal-500; - &:hover, &:focus, &:active { + &:hover, + &:focus, + &:active { text-decoration: none; - color: #4aadbd; + color: $teal-400; } } } @@ -231,9 +152,10 @@ $sidebar-footer-height: 5em; } } - .warning-sign { - margin: 0 10px 0 5px; - display: inline-block; +.warning-sign { + margin: 0 10px 0 5px; + display: inline-block; + line-height: 1.9rem; strong { color: $grey-650; @@ -255,3 +177,9 @@ $sidebar-footer-height: 5em; } } } + +.shop-filters-sidebar { + .property-selectors { + margin-bottom: $sidebar-footer-height + 2em; + } +} diff --git a/app/assets/stylesheets/darkswarm/shop_search.css.scss b/app/assets/stylesheets/darkswarm/shop_search.css.scss index cbe0bf6bd4..4b141cd021 100644 --- a/app/assets/stylesheets/darkswarm/shop_search.css.scss +++ b/app/assets/stylesheets/darkswarm/shop_search.css.scss @@ -32,7 +32,7 @@ padding: 0 2.25em 0 2.75em; width: 100%; min-width: 0; - background: $white url("/assets/icn-search-grey.png") 1em center no-repeat; + background: $white image-url("icn-search-grey.png") 1em center no-repeat; font-size: 1rem; // avoid zoom on iphone, see issue #4535 &::placeholder { diff --git a/app/assets/stylesheets/darkswarm/shop_tabs.css.scss b/app/assets/stylesheets/darkswarm/shop_tabs.css.scss index e0ce5cc7b9..66bbb8998e 100644 --- a/app/assets/stylesheets/darkswarm/shop_tabs.css.scss +++ b/app/assets/stylesheets/darkswarm/shop_tabs.css.scss @@ -9,6 +9,7 @@ color: $dark-grey; box-shadow: $distributor-header-shadow; position: relative; + z-index: 10; .columns { display: flex; diff --git a/app/assets/stylesheets/darkswarm/shopping-cart.css.scss b/app/assets/stylesheets/darkswarm/shopping-cart.css.scss deleted file mode 100644 index d00f3915e7..0000000000 --- a/app/assets/stylesheets/darkswarm/shopping-cart.css.scss +++ /dev/null @@ -1,140 +0,0 @@ -@import "mixins"; -@import "branding"; -@import "compass/css3/user-interface"; -@import 'variables'; - -.cart { - @include user-select(none); - - .cart-span, .cart-span a { - display: inline-block; - } - - .cart-span { - float: left; - } - - .joyride-tip-guide { - display: block; - right: 0; - top: $topbar-height; - width: 480px; - - @media screen and (min-width: 641px) { - overflow-y: auto; - max-height: calc(95vh - 55px); - } - - @media screen and (max-width: 640px) { - width: 96%; - } - - .joyride-nub { - right: 22px !important; - left: auto; - } - - table { - width: 100%; - border: none; - border-spacing: 0px; - margin-bottom: 5px; - - tr.total-cart { - color: #fff; - background-color: #424242; - - td { - color: #fff; - } - } - - tr.product-cart { - background-color: #333333; - border-top: 1px solid #424242; - - td { - padding: 4px 12px; - color: #fff; - } - } - } - - .buttons { - margin-bottom: 0.1em; - - .button { - height: auto; - top: 0px; - } - } - } -} - -// Shopping cart -#update-cart { - #errorExplanation { - display: none; - } -} - -#cart-detail { - .cart-item-delete, .bought-item-delete { - a { - font-size: 1.125em; - } - } - - .out-of-stock { - color: $clr-brick; - } - - button, .button { - margin: 0; - } - - .toggle-bought { - cursor: pointer; - } - - tr.bought td { - color: $med-grey; - - h5 { - color: $med-grey; - } - - .already-confirmed { - float: right; - } - } - - input { - &.ng-invalid-stock, &.ng-invalid-number { - border: 1px solid $clr-brick; - } - } -} - -.item-thumb-image { - display: none; - - @media screen and (min-width: 640px) { - display: inline-block; - float: left; - padding-right: 0.5em; - width: 36px; - 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 66d72d6511..d6b0988ad6 100644 --- a/app/assets/stylesheets/darkswarm/ui.css.scss +++ b/app/assets/stylesheets/darkswarm/ui.css.scss @@ -124,7 +124,12 @@ button.success, .button.success { } } -button.large { +a.button.large { + line-height: 2.75em; +} + +button.large, +a.button.large { height: 3em; font-size: 1em; color: $white; @@ -158,3 +163,7 @@ button.large { padding-right: 0; padding-left: 0; } + +.disable-scroll { + overflow: hidden; +} diff --git a/app/assets/stylesheets/darkswarm/variables.css.scss b/app/assets/stylesheets/darkswarm/variables.css.scss index 115212fc76..08930efd76 100644 --- a/app/assets/stylesheets/darkswarm/variables.css.scss +++ b/app/assets/stylesheets/darkswarm/variables.css.scss @@ -33,6 +33,11 @@ $topbar-dropdown-link-bg-hover: $white; $mobile-nav-height: 2.8em; +$sidebar-small-width: 75%; +$sidebar-medium-width: 65%; +$sidebar-large-width: 45%; +$sidebar-footer-height: 5em; + $radius-small: 0.25em; $radius-medium: 0.5em; diff --git a/app/assets/stylesheets/mail/email.css.scss b/app/assets/stylesheets/mail/email.css.scss index bb1006c9ea..dee2738ead 100644 --- a/app/assets/stylesheets/mail/email.css.scss +++ b/app/assets/stylesheets/mail/email.css.scss @@ -68,6 +68,10 @@ table.social { background-color: white !important; border: 1px solid #ebebeb; } + + &.fullwidth { + width: 100%; + } } table.order-summary { diff --git a/app/controllers/admin/bulk_line_items_controller.rb b/app/controllers/admin/bulk_line_items_controller.rb index aa2f28457f..5437be7c45 100644 --- a/app/controllers/admin/bulk_line_items_controller.rb +++ b/app/controllers/admin/bulk_line_items_controller.rb @@ -28,7 +28,7 @@ module Admin # See https://github.com/rails/rails/blob/3-2-stable/activerecord/lib/active_record/locking/pessimistic.rb#L69 # and https://www.postgresql.org/docs/current/static/sql-select.html#SQL-FOR-UPDATE-SHARE order.with_lock do - if @line_item.update_attributes(params[:line_item]) + if @line_item.update_attributes(line_item_params) order.update_distribution_charge! render nothing: true, status: :no_content # No Content, does not trigger ng resource auto-update else @@ -79,6 +79,10 @@ module Admin @line_item.order end + def line_item_params + params.require(:line_item).permit(:price, :quantity, :final_weight_volume) + end + def order_permissions ::Permissions::Order.new(spree_current_user) end diff --git a/app/controllers/admin/column_preferences_controller.rb b/app/controllers/admin/column_preferences_controller.rb index 64c028b104..ee21a14131 100644 --- a/app/controllers/admin/column_preferences_controller.rb +++ b/app/controllers/admin/column_preferences_controller.rb @@ -8,7 +8,6 @@ module Admin @cp_set.collection.each { |cp| authorize! :bulk_update, cp } if @cp_set.save - # Return saved VOs with IDs render json: @cp_set.collection, each_serializer: Api::Admin::ColumnPreferenceSerializer else if @cp_set.errors.present? @@ -21,14 +20,23 @@ module Admin private + def permitted_params + params.permit( + :action_name, + column_preferences: [:id, :user_id, :action_name, :column_name, :name, :visible] + ) + end + def load_collection - collection_hash = Hash[params[:column_preferences].each_with_index.map { |cp, i| [i, cp] }] - collection_hash.select!{ |_i, cp| cp[:action_name] == params[:action_name] } + collection_hash = Hash[permitted_params[:column_preferences]. + each_with_index.map { |cp, i| [i, cp] }] + collection_hash.select!{ |_i, cp| cp[:action_name] == permitted_params[:action_name] } @cp_set = ColumnPreferenceSet.new @column_preferences, collection_attributes: collection_hash end def collection - ColumnPreference.where(user_id: spree_current_user, action_name: params[:action_name]) + ColumnPreference.where(user_id: spree_current_user, + action_name: permitted_params[:action_name]) end def collection_actions diff --git a/app/controllers/admin/contents_controller.rb b/app/controllers/admin/contents_controller.rb index 7443ac6717..1769732ec4 100644 --- a/app/controllers/admin/contents_controller.rb +++ b/app/controllers/admin/contents_controller.rb @@ -32,7 +32,8 @@ module Admin PreferenceSections::GroupSignupPageSection.new, PreferenceSections::MainLinksSection.new, PreferenceSections::FooterAndExternalLinksSection.new, - PreferenceSections::UserGuideSection.new + PreferenceSections::UserGuideSection.new, + PreferenceSections::MapSection.new ] end end diff --git a/app/controllers/admin/customers_controller.rb b/app/controllers/admin/customers_controller.rb index 21942786bd..667c62aad0 100644 --- a/app/controllers/admin/customers_controller.rb +++ b/app/controllers/admin/customers_controller.rb @@ -29,7 +29,7 @@ module Admin end def create - @customer = Customer.new(params[:customer]) + @customer = Customer.new(customer_params) if user_can_create_customer? if @customer.save tag_rule_mapping = TagRule.mapping_for(Enterprise.where(id: @customer.enterprise)) @@ -71,7 +71,7 @@ module Admin def managed_enterprise_id @managed_enterprise_id ||= Enterprise.managed_by(spree_current_user). - select('enterprises.id').find_by_id(params[:enterprise_id]) + select('enterprises.id').find_by(id: params[:enterprise_id]) end def load_managed_shops @@ -87,6 +87,19 @@ module Admin [:subscription] end + def customer_params + params.require(:customer).permit( + :enterprise_id, :name, :email, :code, :tag_list, + ship_address_attributes: PermittedAttributes::Address.attributes, + bill_address_attributes: PermittedAttributes::Address.attributes, + ) + end + + # Used in ResourceController#update + def permitted_resource_params + customer_params + end + def tag_rule_mapping TagRule.mapping_for(Enterprise.where(id: managed_enterprise_id)) end diff --git a/app/controllers/admin/enterprise_fees_controller.rb b/app/controllers/admin/enterprise_fees_controller.rb index f462569c4b..47372fa5f4 100644 --- a/app/controllers/admin/enterprise_fees_controller.rb +++ b/app/controllers/admin/enterprise_fees_controller.rb @@ -51,8 +51,8 @@ module Admin def collection case action when :for_order_cycle - order_cycle = OrderCycle.find_by_id(params[:order_cycle_id]) if params[:order_cycle_id] - coordinator = Enterprise.find_by_id(params[:coordinator_id]) if params[:coordinator_id] + order_cycle = OrderCycle.find_by(id: params[:order_cycle_id]) if params[:order_cycle_id] + coordinator = Enterprise.find_by(id: params[:coordinator_id]) if params[:coordinator_id] order_cycle = OrderCycle.new(coordinator: coordinator) if order_cycle.nil? && coordinator.present? enterprises = OpenFoodNetwork::OrderCyclePermissions.new(spree_current_user, order_cycle).visible_enterprises EnterpriseFee.for_enterprises(enterprises).order('enterprise_id', 'fee_type', 'name') diff --git a/app/controllers/admin/enterprise_groups_controller.rb b/app/controllers/admin/enterprise_groups_controller.rb index 67a7dface3..471d56d5ab 100644 --- a/app/controllers/admin/enterprise_groups_controller.rb +++ b/app/controllers/admin/enterprise_groups_controller.rb @@ -28,7 +28,9 @@ module Admin def build_resource_with_address enterprise_group = build_resource_without_address enterprise_group.address = Spree::Address.new - enterprise_group.address.country = Spree::Country.find_by_id(Spree::Config[:default_country_id]) + enterprise_group.address.country = Spree::Country.find_by( + id: Spree::Config[:default_country_id] + ) enterprise_group end alias_method_chain :build_resource, :address @@ -38,7 +40,7 @@ module Admin # The ! version is important to raise a RecordNotFound error. def find_resource permalink = params[:id] || params[:enterprise_group_id] - EnterpriseGroup.find_by_permalink!(permalink) + EnterpriseGroup.find_by!(permalink: permalink) end private @@ -55,5 +57,13 @@ module Admin def collection EnterpriseGroup.by_position end + + def permitted_resource_params + params.require(:enterprise_group).permit( + :name, :description, :long_description, :on_front_page, :owner_id, :permalink, + :email, :website, :facebook, :instagram, :linkedin, :twitter, + enterprise_ids: [], address_attributes: PermittedAttributes::Address.attributes + ) + end end end diff --git a/app/controllers/admin/enterprise_relationships_controller.rb b/app/controllers/admin/enterprise_relationships_controller.rb index 545f0e429c..3630fa235d 100644 --- a/app/controllers/admin/enterprise_relationships_controller.rb +++ b/app/controllers/admin/enterprise_relationships_controller.rb @@ -11,7 +11,7 @@ module Admin end def create - @enterprise_relationship = EnterpriseRelationship.new params[:enterprise_relationship] + @enterprise_relationship = EnterpriseRelationship.new enterprise_relationship_params if @enterprise_relationship.save render text: Api::Admin::EnterpriseRelationshipSerializer.new(@enterprise_relationship).to_json @@ -25,5 +25,11 @@ module Admin @enterprise_relationship.destroy render nothing: true end + + private + + def enterprise_relationship_params + params.require(:enterprise_relationship).permit(:parent_id, :child_id, permissions_list: []) + end end end diff --git a/app/controllers/admin/enterprise_roles_controller.rb b/app/controllers/admin/enterprise_roles_controller.rb index 98810e2a64..299292238e 100644 --- a/app/controllers/admin/enterprise_roles_controller.rb +++ b/app/controllers/admin/enterprise_roles_controller.rb @@ -7,7 +7,7 @@ module Admin end def create - @enterprise_role = EnterpriseRole.new params[:enterprise_role] + @enterprise_role = EnterpriseRole.new enterprise_role_params if @enterprise_role.save render text: Api::Admin::EnterpriseRoleSerializer.new(@enterprise_role).to_json @@ -22,5 +22,11 @@ module Admin @enterprise_role.destroy render nothing: true end + + private + + def enterprise_role_params + params.require(:enterprise_role).permit(:user_id, :enterprise_id) + end end end diff --git a/app/controllers/admin/enterprises_controller.rb b/app/controllers/admin/enterprises_controller.rb index 6f74043078..8b8901e211 100644 --- a/app/controllers/admin/enterprises_controller.rb +++ b/app/controllers/admin/enterprises_controller.rb @@ -47,7 +47,7 @@ module Admin tag_rules_attributes = params[object_name].delete :tag_rules_attributes update_tag_rules(tag_rules_attributes) if tag_rules_attributes.present? update_enterprise_notifications - if @object.update_attributes(params[object_name]) + if @object.update_attributes(enterprise_params) invoke_callbacks(:update, :after) flash[:success] = flash_message_for(@object, :successfully_updated) respond_with(@object) do |format| @@ -115,7 +115,7 @@ module Admin def build_resource_with_address enterprise = build_resource_without_address enterprise.address ||= Spree::Address.new - enterprise.address.country ||= Spree::Country.find_by_id(Spree::Config[:default_country_id]) + enterprise.address.country ||= Spree::Country.find_by(id: Spree::Config[:default_country_id]) enterprise end alias_method_chain :build_resource, :address @@ -123,7 +123,7 @@ module Admin # Overriding method on Spree's resource controller, # so that resources are found using permalink def find_resource - Enterprise.find_by_permalink(params[:id]) + Enterprise.find_by(permalink: params[:id]) end private @@ -139,8 +139,8 @@ module Admin def collection case action when :for_order_cycle - @order_cycle = OrderCycle.find_by_id(params[:order_cycle_id]) if params[:order_cycle_id] - coordinator = Enterprise.find_by_id(params[:coordinator_id]) if params[:coordinator_id] + @order_cycle = OrderCycle.find_by(id: params[:order_cycle_id]) if params[:order_cycle_id] + coordinator = Enterprise.find_by(id: params[:coordinator_id]) if params[:coordinator_id] @order_cycle = OrderCycle.new(coordinator: coordinator) if @order_cycle.nil? && coordinator.present? enterprises = OpenFoodNetwork::OrderCyclePermissions.new(spree_current_user, @order_cycle) @@ -211,7 +211,8 @@ module Admin # record is persisted. This problem is compounded by the use of calculators. @object.transaction do tag_rules_attributes.select{ |_i, attrs| attrs[:type].present? }.each do |_i, attrs| - rule = @object.tag_rules.find_by_id(attrs.delete(:id)) || attrs[:type].constantize.new(enterprise: @object) + rule = @object.tag_rules.find_by(id: attrs.delete(:id)) || + attrs[:type].constantize.new(enterprise: @object) create_calculator_for(rule, attrs) if rule.type == "TagRule::DiscountOrder" && rule.calculator.nil? rule.update_attributes(attrs) end @@ -234,7 +235,9 @@ module Admin def check_can_change_bulk_sells unless spree_current_user.admin? params[:enterprise_set][:collection_attributes].each do |_i, enterprise_params| - enterprise_params.delete :sells unless spree_current_user == Enterprise.find_by_id(enterprise_params[:id]).owner + unless spree_current_user == Enterprise.find_by(id: enterprise_params[:id]).owner + enterprise_params.delete :sells + end end end end @@ -252,7 +255,7 @@ module Admin def override_sells unless spree_current_user.admin? has_hub = spree_current_user.owned_enterprises.is_hub.any? - new_enterprise_is_producer = Enterprise.new(params[:enterprise]).is_primary_producer + new_enterprise_is_producer = Enterprise.new(enterprise_params).is_primary_producer params[:enterprise][:sells] = has_hub && !new_enterprise_is_producer ? 'any' : 'none' end end @@ -311,5 +314,14 @@ module Admin def ams_prefix_whitelist [:index, :basic] end + + def enterprise_params + PermittedAttributes::Enterprise.new(params).call + end + + # Used in ResourceController#create + def permitted_resource_params + enterprise_params + end end end diff --git a/app/controllers/admin/inventory_items_controller.rb b/app/controllers/admin/inventory_items_controller.rb index 4567c64632..10ffbf1abd 100644 --- a/app/controllers/admin/inventory_items_controller.rb +++ b/app/controllers/admin/inventory_items_controller.rb @@ -14,14 +14,14 @@ module Admin private - # Overriding Spree method to load data from params here so that + # Overriding resource_controller method to load data from params here so that # we can authorise #create using an object with required attributes def build_resource - if parent_data.present? - parent.public_send(controller_name).build - else - model_class.new(params[object_name]) # This line changed - end + model_class.new(permitted_resource_params) + end + + def permitted_resource_params + params.require(:inventory_item).permit(:enterprise_id, :variant_id, :visible) end end end diff --git a/app/controllers/admin/manager_invitations_controller.rb b/app/controllers/admin/manager_invitations_controller.rb index 45898bd5eb..36b1554cf9 100644 --- a/app/controllers/admin/manager_invitations_controller.rb +++ b/app/controllers/admin/manager_invitations_controller.rb @@ -8,7 +8,7 @@ module Admin authorize! :edit, @enterprise - existing_user = Spree::User.find_by_email(@email) + existing_user = Spree::User.find_by(email: @email) if existing_user render json: { errors: t('admin.enterprises.invite_manager.user_already_exists') }, status: :unprocessable_entity diff --git a/app/controllers/admin/order_cycles_controller.rb b/app/controllers/admin/order_cycles_controller.rb index 4a3ad149cb..8b488c8bda 100644 --- a/app/controllers/admin/order_cycles_controller.rb +++ b/app/controllers/admin/order_cycles_controller.rb @@ -40,7 +40,7 @@ module Admin end def create - @order_cycle_form = OrderCycleForm.new(@order_cycle, params, spree_current_user) + @order_cycle_form = OrderCycleForm.new(@order_cycle, order_cycle_params, spree_current_user) if @order_cycle_form.save flash[:notice] = I18n.t(:order_cycles_create_notice) @@ -56,7 +56,7 @@ module Admin end def update - @order_cycle_form = OrderCycleForm.new(@order_cycle, params, spree_current_user) + @order_cycle_form = OrderCycleForm.new(@order_cycle, order_cycle_params, spree_current_user) if @order_cycle_form.save respond_to do |format| @@ -145,7 +145,7 @@ module Admin preload(:schedules). ransack(params[:q]). result. - accessible_by(spree_current_user) + visible_by(spree_current_user) end def load_data_for_index @@ -164,7 +164,7 @@ module Admin def require_coordinator @order_cycle.coordinator = - permitted_coordinating_enterprises_for(@order_cycle).find_by_id(params[:coordinator_id]) + permitted_coordinating_enterprises_for(@order_cycle).find_by(id: params[:coordinator_id]) return if params[:coordinator_id] && @order_cycle.coordinator available_coordinators = permitted_coordinating_enterprises_for(@order_cycle) @@ -235,5 +235,9 @@ module Admin def ams_prefix_whitelist [:basic, :index] end + + def order_cycle_params + PermittedAttributes::OrderCycle.new(params).call + end end end diff --git a/app/controllers/admin/producer_properties_controller.rb b/app/controllers/admin/producer_properties_controller.rb index 7bc021c04e..f83911d6a4 100644 --- a/app/controllers/admin/producer_properties_controller.rb +++ b/app/controllers/admin/producer_properties_controller.rb @@ -11,7 +11,7 @@ module Admin end def load_enterprise - @enterprise = Enterprise.find_by_permalink! params[:enterprise_id] + @enterprise = Enterprise.find_by! permalink: params[:enterprise_id] end def load_properties diff --git a/app/controllers/admin/schedules_controller.rb b/app/controllers/admin/schedules_controller.rb index c568bf0ad7..9532e4db9e 100644 --- a/app/controllers/admin/schedules_controller.rb +++ b/app/controllers/admin/schedules_controller.rb @@ -3,10 +3,11 @@ require 'order_management/subscriptions/proxy_order_syncer' module Admin class SchedulesController < ResourceController - before_filter :check_editable_order_cycle_ids, only: [:create, :update] + before_filter :adapt_params, only: [:update] + before_filter :editable_order_cycle_ids_for_create, only: [:create] + before_filter :editable_order_cycle_ids_for_update, only: [:update] before_filter :check_dependent_subscriptions, only: [:destroy] - create.after :sync_subscriptions - update.after :sync_subscriptions + update.after :sync_subscriptions_for_update respond_to :json @@ -27,6 +28,23 @@ module Admin end end + def create + return respond_with(@schedule) if params[:order_cycle_ids].blank? + + @schedule.attributes = permitted_resource_params + + if @schedule.save + @schedule.order_cycle_ids = params[:order_cycle_ids] + @schedule.save! + + sync_subscriptions_for_create + + flash[:success] = flash_message_for(@schedule, :successfully_created) + end + + respond_with(@schedule) + end + private def collection @@ -48,17 +66,43 @@ module Admin [:index] end - def check_editable_order_cycle_ids + # In this controller, params like params[:name] are moved into + # params[:schedule] becoming params[:schedule][:name]. + # For some reason in rails 4, this is not happening for params[:order_cycle_ids] + # We do it manually in this filter + def adapt_params + params[:schedule] = {} if params[:schedule].blank? + params[:schedule][:order_cycle_ids] = params[:order_cycle_ids] + end + + def editable_order_cycle_ids_for_create + return unless params[:order_cycle_ids] + + @existing_order_cycle_ids = [] + result = editable_order_cycles(params[:order_cycle_ids]) + + params[:order_cycle_ids] = result + end + + def editable_order_cycle_ids_for_update return unless params[:schedule][:order_cycle_ids] - requested = params[:schedule][:order_cycle_ids] - @existing_order_cycle_ids = @schedule.persisted? ? @schedule.order_cycle_ids : [] - permitted = OrderCycle.where(id: params[:schedule][:order_cycle_ids] | @existing_order_cycle_ids).merge(OrderCycle.managed_by(spree_current_user)).pluck(:id) + @existing_order_cycle_ids = @schedule.order_cycle_ids + result = editable_order_cycles(params[:schedule][:order_cycle_ids]) + + params[:schedule][:order_cycle_ids] = result + @schedule.order_cycle_ids = result + end + + def editable_order_cycles(requested) + permitted = OrderCycle + .where(id: params[:order_cycle_ids] | @existing_order_cycle_ids) + .merge(OrderCycle.managed_by(spree_current_user)) + .pluck(:id) result = @existing_order_cycle_ids result |= (requested & permitted) # add any requested & permitted ids result -= ((result & permitted) - requested) # remove any existing and permitted ids that were not specifically requested - params[:schedule][:order_cycle_ids] = result - @object.order_cycle_ids = result + result end def check_dependent_subscriptions @@ -73,9 +117,19 @@ module Admin @permissions = OpenFoodNetwork::Permissions.new(spree_current_user) end - def sync_subscriptions + def sync_subscriptions_for_update return unless params[:schedule][:order_cycle_ids] + sync_subscriptions + end + + def sync_subscriptions_for_create + return unless params[:order_cycle_ids] + + sync_subscriptions + end + + def sync_subscriptions removed_ids = @existing_order_cycle_ids - @schedule.order_cycle_ids new_ids = @schedule.order_cycle_ids - @existing_order_cycle_ids return unless removed_ids.any? || new_ids.any? @@ -84,5 +138,9 @@ module Admin syncer = OrderManagement::Subscriptions::ProxyOrderSyncer.new(subscriptions) syncer.sync! end + + def permitted_resource_params + params.require(:schedule).permit(:id, :name) + end end end diff --git a/app/controllers/admin/stripe_accounts_controller.rb b/app/controllers/admin/stripe_accounts_controller.rb index 54a48206f4..90b4e2c85c 100644 --- a/app/controllers/admin/stripe_accounts_controller.rb +++ b/app/controllers/admin/stripe_accounts_controller.rb @@ -28,7 +28,7 @@ module Admin def status return render json: { status: :stripe_disabled } unless Spree::Config.stripe_connect_enabled - stripe_account = StripeAccount.find_by_enterprise_id(params[:enterprise_id]) + stripe_account = StripeAccount.find_by(enterprise_id: params[:enterprise_id]) return render json: { status: :account_missing } unless stripe_account authorize! :status, stripe_account diff --git a/app/controllers/admin/subscription_line_items_controller.rb b/app/controllers/admin/subscription_line_items_controller.rb index f8e4945c26..c52cca1c3b 100644 --- a/app/controllers/admin/subscription_line_items_controller.rb +++ b/app/controllers/admin/subscription_line_items_controller.rb @@ -11,7 +11,7 @@ module Admin respond_to :json def build - @subscription_line_item.assign_attributes(params[:subscription_line_item]) + @subscription_line_item.assign_attributes(subscription_line_item_params) @subscription_line_item.price_estimate = price_estimate render json: @subscription_line_item, serializer: Api::Admin::SubscriptionLineItemSerializer, shop: @shop, schedule: @schedule @@ -24,10 +24,10 @@ module Admin end def load_build_context - @shop = Enterprise.managed_by(spree_current_user).find_by_id(params[:shop_id]) - @schedule = permissions.editable_schedules.find_by_id(params[:schedule_id]) + @shop = Enterprise.managed_by(spree_current_user).find_by(id: params[:shop_id]) + @schedule = permissions.editable_schedules.find_by(id: params[:schedule_id]) @order_cycle = @schedule.andand.current_or_next_order_cycle - @variant = variant_if_eligible(params[:subscription_line_item][:variant_id]) if @shop.present? + @variant = variant_if_eligible(subscription_line_item_params[:variant_id]) if @shop.present? end def new_actions @@ -56,7 +56,11 @@ module Admin end def variant_if_eligible(variant_id) - OrderManagement::Subscriptions::VariantsList.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 + params.require(:subscription_line_item).permit(:quantity, :variant_id) end end end diff --git a/app/controllers/admin/subscriptions_controller.rb b/app/controllers/admin/subscriptions_controller.rb index 867c9d2351..11163b6830 100644 --- a/app/controllers/admin/subscriptions_controller.rb +++ b/app/controllers/admin/subscriptions_controller.rb @@ -64,7 +64,7 @@ module Admin private def save_form_and_render(render_issues = true) - form = OrderManagement::Subscriptions::Form.new(@subscription, params[:subscription]) + form = OrderManagement::Subscriptions::Form.new(@subscription, subscription_params) unless form.save render json: { errors: form.json_errors }, status: :unprocessable_entity return @@ -148,11 +148,15 @@ module Admin # Overriding Spree method to load data from params here so that # we can authorise #create using an object with required attributes def build_resource - Subscription.new(params[:subscription]) + Subscription.new(subscription_params) end def ams_prefix_whitelist [:index] end + + def subscription_params + PermittedAttributes::Subscription.new(params).call + end end end diff --git a/app/controllers/admin/variant_overrides_controller.rb b/app/controllers/admin/variant_overrides_controller.rb index b644536215..31aff8ce8c 100644 --- a/app/controllers/admin/variant_overrides_controller.rb +++ b/app/controllers/admin/variant_overrides_controller.rb @@ -68,7 +68,7 @@ module Admin end def load_collection - collection_hash = Hash[params[:variant_overrides].each_with_index.map { |vo, i| [i, vo] }] + collection_hash = Hash[variant_overrides_params.each_with_index.map { |vo, i| [i, vo] }] @vo_set = VariantOverrideSet.new @variant_overrides, collection_attributes: collection_hash end @@ -76,6 +76,7 @@ module Admin @variant_overrides = VariantOverride. includes(variant: :product). for_hubs(params[:hub_id] || @hubs). + references(:variant). select { |vo| vo.variant.present? } end @@ -91,5 +92,15 @@ module Admin full_messages.each { |fm| errors.add(:base, fm) } errors end + + def variant_overrides_params + params.require(:variant_overrides).map do |variant_override| + variant_override.permit( + :id, :variant_id, :hub_id, + :price, :count_on_hand, :sku, :on_demand, + :default_stock, :resettable, :tag_list + ) + end + end end end diff --git a/app/controllers/api/base_controller.rb b/app/controllers/api/base_controller.rb index 51b7acbe5c..f591154d4c 100644 --- a/app/controllers/api/base_controller.rb +++ b/app/controllers/api/base_controller.rb @@ -32,6 +32,12 @@ module Api use_renderers :json check_authorization + # Temporary measure to help debugging strong_parameters + rescue_from ActiveModel::ForbiddenAttributesError, with: :print_params + def print_params + raise ActiveModel::ForbiddenAttributesError, params.to_s + end + def set_jsonp_format return unless params[:callback] && request.get? @@ -55,7 +61,7 @@ module Api return end - return if @current_api_user = Spree.user_class.find_by_spree_api_key(api_key.to_s) + return if @current_api_user = Spree.user_class.find_by(spree_api_key: api_key.to_s) invalid_api_key end diff --git a/app/controllers/api/enterprise_attachment_controller.rb b/app/controllers/api/enterprise_attachment_controller.rb index 6178b40104..3f5f61e5dd 100644 --- a/app/controllers/api/enterprise_attachment_controller.rb +++ b/app/controllers/api/enterprise_attachment_controller.rb @@ -1,3 +1,7 @@ +# frozen_string_literal: true + +require 'api/admin/enterprise_serializer' + module Api class EnterpriseAttachmentController < Api::BaseController class MissingImplementationError < StandardError; end @@ -25,7 +29,7 @@ module Api end def load_enterprise - @enterprise = Enterprise.find_by_permalink(params[:enterprise_id].to_s) + @enterprise = Enterprise.find_by(permalink: params[:enterprise_id].to_s) raise UnknownEnterpriseAuthorizationActionError if enterprise_authorize_action.blank? authorize!(enterprise_authorize_action, @enterprise) diff --git a/app/controllers/api/enterprise_fees_controller.rb b/app/controllers/api/enterprise_fees_controller.rb index 208643d7dc..c966efa7cc 100644 --- a/app/controllers/api/enterprise_fees_controller.rb +++ b/app/controllers/api/enterprise_fees_controller.rb @@ -15,7 +15,7 @@ module Api private def enterprise_fee - @enterprise_fee ||= EnterpriseFee.find_by_id params[:id] + @enterprise_fee ||= EnterpriseFee.find_by id: params[:id] end end end diff --git a/app/controllers/api/enterprises_controller.rb b/app/controllers/api/enterprises_controller.rb index a555cb0a86..b4456c5ae4 100644 --- a/app/controllers/api/enterprises_controller.rb +++ b/app/controllers/api/enterprises_controller.rb @@ -1,5 +1,5 @@ module Api - class EnterprisesController < BaseController + class EnterprisesController < Api::BaseController before_filter :override_owner, only: [:create, :update] before_filter :check_type, only: :update before_filter :override_sells, only: [:create, :update] @@ -9,8 +9,12 @@ module Api def create authorize! :create, Enterprise + # params[:user_ids] breaks the enterprise creation + # We remove them from params and save them after creating the enterprise + user_ids = params[:enterprise].delete(:user_ids) @enterprise = Enterprise.new(params[:enterprise]) if @enterprise.save + @enterprise.user_ids = user_ids render text: @enterprise.id, status: :created else invalid_resource!(@enterprise) @@ -18,7 +22,7 @@ module Api end def update - @enterprise = Enterprise.find_by_permalink(params[:id]) || Enterprise.find(params[:id]) + @enterprise = Enterprise.find_by(permalink: params[:id]) || Enterprise.find(params[:id]) authorize! :update, @enterprise if @enterprise.update_attributes(params[:enterprise]) @@ -29,7 +33,7 @@ module Api end def update_image - @enterprise = Enterprise.find_by_permalink(params[:id]) || Enterprise.find(params[:id]) + @enterprise = Enterprise.find_by(permalink: params[:id]) || Enterprise.find(params[:id]) authorize! :update, @enterprise if params[:logo] && @enterprise.update_attributes( logo: params[:logo] ) diff --git a/app/controllers/api/exchange_products_controller.rb b/app/controllers/api/exchange_products_controller.rb index cb28bbbec6..ff9cc1ea46 100644 --- a/app/controllers/api/exchange_products_controller.rb +++ b/app/controllers/api/exchange_products_controller.rb @@ -58,7 +58,7 @@ module Api end def load_data_from_exchange - exchange = Exchange.find_by_id(params[:exchange_id]) + exchange = Exchange.find_by(id: params[:exchange_id]) @order_cycle = exchange.order_cycle @incoming = exchange.incoming @@ -66,10 +66,10 @@ module Api end def load_data_from_other_params - @enterprise = Enterprise.find_by_id(params[:enterprise_id]) + @enterprise = Enterprise.find_by(id: params[:enterprise_id]) if params[:order_cycle_id] - @order_cycle = OrderCycle.find_by_id(params[:order_cycle_id]) + @order_cycle = OrderCycle.find_by(id: params[:order_cycle_id]) elsif !params[:incoming] raise "order_cycle_id is required to list products for new outgoing exchange" end diff --git a/app/controllers/api/order_cycles_controller.rb b/app/controllers/api/order_cycles_controller.rb index 0af9c4936c..77689932e0 100644 --- a/app/controllers/api/order_cycles_controller.rb +++ b/app/controllers/api/order_cycles_controller.rb @@ -81,11 +81,11 @@ module Api end def distributor - @distributor ||= Enterprise.find_by_id(params[:distributor]) + @distributor ||= Enterprise.find_by(id: params[:distributor]) end def order_cycle - @order_cycle ||= OrderCycle.find_by_id(params[:id]) + @order_cycle ||= OrderCycle.find_by(id: params[:id]) end def customer diff --git a/app/controllers/api/products_controller.rb b/app/controllers/api/products_controller.rb index 854d820a47..49246bc624 100644 --- a/app/controllers/api/products_controller.rb +++ b/app/controllers/api/products_controller.rb @@ -92,7 +92,7 @@ module Api private def find_product(id) - product_scope.find_by_permalink!(id.to_s) + product_scope.find_by!(permalink: id.to_s) rescue ActiveRecord::RecordNotFound product_scope.find(id) end @@ -119,7 +119,7 @@ module Api end def paged_products_for_producers(producer_ids) - Spree::Product.scoped. + Spree::Product.where(nil). merge(product_scope). includes(variants: [:product, :default_price, :stock_items]). where(supplier_id: producer_ids). diff --git a/app/controllers/api/shipments_controller.rb b/app/controllers/api/shipments_controller.rb index 4c9bb047eb..d7623da0c7 100644 --- a/app/controllers/api/shipments_controller.rb +++ b/app/controllers/api/shipments_controller.rb @@ -22,7 +22,7 @@ module Api def update authorize! :read, Spree::Shipment - @shipment = @order.shipments.find_by_number!(params[:id]) + @shipment = @order.shipments.find_by!(number: params[:id]) params[:shipment] ||= [] unlock = params[:shipment].delete(:unlock) @@ -82,12 +82,12 @@ module Api private def find_order - @order = Spree::Order.find_by_number!(params[:order_id]) + @order = Spree::Order.find_by!(number: params[:order_id]) authorize! :read, @order end def find_and_update_shipment - @shipment = @order.shipments.find_by_number!(params[:id]) + @shipment = @order.shipments.find_by!(number: params[:id]) @shipment.update_attributes(params[:shipment]) @shipment.reload end diff --git a/app/controllers/api/taxons_controller.rb b/app/controllers/api/taxons_controller.rb index a69642c6e8..68d9a6fdd8 100644 --- a/app/controllers/api/taxons_controller.rb +++ b/app/controllers/api/taxons_controller.rb @@ -26,7 +26,7 @@ module Api authorize! :create, Spree::Taxon @taxon = Spree::Taxon.new(params[:taxon]) @taxon.taxonomy_id = params[:taxonomy_id] - taxonomy = Spree::Taxonomy.find_by_id(params[:taxonomy_id]) + taxonomy = Spree::Taxonomy.find_by(id: params[:taxonomy_id]) if taxonomy.nil? @taxon.errors[:taxonomy_id] = I18n.t(:invalid_taxonomy_id, scope: 'spree.api') diff --git a/app/controllers/api/variants_controller.rb b/app/controllers/api/variants_controller.rb index d6f8f80d5c..f0e31e0035 100644 --- a/app/controllers/api/variants_controller.rb +++ b/app/controllers/api/variants_controller.rb @@ -47,7 +47,7 @@ module Api private def product - @product ||= Spree::Product.find_by_permalink(params[:product_id]) if params[:product_id] + @product ||= Spree::Product.find_by(permalink: params[:product_id]) if params[:product_id] end def scope @@ -58,7 +58,7 @@ module Api @product.variants_including_master end else - variants = Spree::Variant.scoped + variants = Spree::Variant.where(nil) if current_api_user.has_spree_role?("admin") unless params[:show_deleted] variants = Spree::Variant.active diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1a841eae27..5e2777feac 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -10,6 +10,12 @@ class ApplicationController < ActionController::Base include EnterprisesHelper include Spree::AuthenticationHelpers + # Temporary measure to help debugging strong_parameters + rescue_from ActiveModel::ForbiddenAttributesError, with: :print_params + def print_params + raise ActiveModel::ForbiddenAttributesError, params.to_s + end + def redirect_to(options = {}, response_status = {}) ::Rails.logger.error("Redirected by #{begin caller(1).first diff --git a/app/controllers/cart_controller.rb b/app/controllers/cart_controller.rb index c1a77b433b..b2cf8c04b7 100644 --- a/app/controllers/cart_controller.rb +++ b/app/controllers/cart_controller.rb @@ -38,7 +38,7 @@ class CartController < BaseController def check_authorization session[:access_token] ||= params[:token] - order = Spree::Order.find_by_number(params[:id]) || current_order + order = Spree::Order.find_by(number: params[:id]) || current_order if order authorize! :edit, order, session[:access_token] diff --git a/app/controllers/checkout_controller.rb b/app/controllers/checkout_controller.rb index 2798009567..ac3f63e60d 100644 --- a/app/controllers/checkout_controller.rb +++ b/app/controllers/checkout_controller.rb @@ -44,8 +44,8 @@ class CheckoutController < Spree::StoreController end def update - params_adapter = Checkout::FormDataAdapter.new(params, @order, spree_current_user) - return update_failed unless @order.update_attributes(params_adapter.order_params) + params_adapter = Checkout::FormDataAdapter.new(permitted_params, @order, spree_current_user) + return update_failed unless @order.update_attributes(params_adapter.params[:order]) fire_event('spree.checkout.update') @@ -259,4 +259,8 @@ class CheckoutController < Spree::StoreController end end end + + def permitted_params + PermittedAttributes::Checkout.new(params).call + end end diff --git a/app/controllers/enterprises_controller.rb b/app/controllers/enterprises_controller.rb index 2657bf170e..98fe17f0a7 100644 --- a/app/controllers/enterprises_controller.rb +++ b/app/controllers/enterprises_controller.rb @@ -36,7 +36,7 @@ class EnterprisesController < BaseController end def check_permalink - if Enterprise.find_by_permalink params[:permalink] + if Enterprise.find_by permalink: params[:permalink] render(text: params[:permalink], status: :conflict) && return end @@ -51,7 +51,7 @@ class EnterprisesController < BaseController private def set_enterprise - @enterprise = Enterprise.find_by_id(params[:id]) + @enterprise = Enterprise.find_by(id: params[:id]) end def clean_permalink diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index 6dcc582f86..d13876304e 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -4,6 +4,6 @@ class GroupsController < BaseController def show enable_embedded_shopfront @hide_menu = true if @shopfront_layout == 'embedded' - @group = EnterpriseGroup.find_by_permalink(params[:id]) || EnterpriseGroup.find(params[:id]) + @group = EnterpriseGroup.find_by(permalink: params[:id]) || EnterpriseGroup.find(params[:id]) end end diff --git a/app/controllers/line_items_controller.rb b/app/controllers/line_items_controller.rb index b2002b7c54..219b836ab4 100644 --- a/app/controllers/line_items_controller.rb +++ b/app/controllers/line_items_controller.rb @@ -16,7 +16,7 @@ class LineItemsController < BaseController private def load_line_item - @line_item = Spree::LineItem.find_by_id(params[:id]) + @line_item = Spree::LineItem.find_by(id: params[:id]) not_found unless @line_item end diff --git a/app/controllers/shop_controller.rb b/app/controllers/shop_controller.rb index ee304d1f96..7aa5e4e796 100644 --- a/app/controllers/shop_controller.rb +++ b/app/controllers/shop_controller.rb @@ -9,7 +9,7 @@ class ShopController < BaseController def order_cycle if request.post? - if oc = OrderCycle.with_distributor(@distributor).active.find_by_id(params[:order_cycle_id]) + if oc = OrderCycle.with_distributor(@distributor).active.find_by(id: params[:order_cycle_id]) current_order(true).set_order_cycle! oc @current_order_cycle = oc render json: @current_order_cycle, serializer: Api::OrderCycleSerializer diff --git a/app/controllers/spree/admin/adjustments_controller.rb b/app/controllers/spree/admin/adjustments_controller.rb index 07a9207c14..dc9596d242 100644 --- a/app/controllers/spree/admin/adjustments_controller.rb +++ b/app/controllers/spree/admin/adjustments_controller.rb @@ -66,6 +66,12 @@ module Spree def enable_updates @adjustment.close end + + def permitted_resource_params + params.require(:adjustment).permit( + :label, :amount, :included_tax + ) + end end end end diff --git a/app/controllers/spree/admin/countries_controller.rb b/app/controllers/spree/admin/countries_controller.rb index 4314e54b37..dedd9fbdb4 100644 --- a/app/controllers/spree/admin/countries_controller.rb +++ b/app/controllers/spree/admin/countries_controller.rb @@ -1,6 +1,13 @@ module Spree module Admin class CountriesController < ResourceController + protected + + def permitted_resource_params + params.require(:country). + permit(:name, :iso_name, :states_required) + end + def collection super.order(:name) end diff --git a/app/controllers/spree/admin/images_controller.rb b/app/controllers/spree/admin/images_controller.rb index a506a9231d..168f01466d 100644 --- a/app/controllers/spree/admin/images_controller.rb +++ b/app/controllers/spree/admin/images_controller.rb @@ -19,7 +19,7 @@ module Spree end def load_data - @product = Product.find_by_permalink(params[:product_id]) + @product = Product.find_by(permalink: params[:product_id]) @variants = @product.variants.collect do |variant| [variant.options_text, variant.id] end @@ -34,6 +34,12 @@ module Spree def destroy_before @viewable = @image.viewable end + + def permitted_resource_params + params.require(:image).permit( + :attachment, :viewable_id, :alt + ) + end end end end diff --git a/app/controllers/spree/admin/mail_methods_controller.rb b/app/controllers/spree/admin/mail_methods_controller.rb index e95739148d..a21e3afe7d 100644 --- a/app/controllers/spree/admin/mail_methods_controller.rb +++ b/app/controllers/spree/admin/mail_methods_controller.rb @@ -23,7 +23,7 @@ module Spree rescue StandardError => e flash[:error] = Spree.t('admin.mail_methods.testmail.error') % { e: e } ensure - redirect_to edit_admin_mail_method_url + redirect_to edit_admin_mail_methods_url end private diff --git a/app/controllers/spree/admin/orders/customer_details_controller.rb b/app/controllers/spree/admin/orders/customer_details_controller.rb index 2a22c1e086..7503e42833 100644 --- a/app/controllers/spree/admin/orders/customer_details_controller.rb +++ b/app/controllers/spree/admin/orders/customer_details_controller.rb @@ -18,9 +18,9 @@ module Spree end def update - if @order.update_attributes(params[:order]) + if @order.update_attributes(order_params) if params[:guest_checkout] == "false" - @order.associate_user!(Spree.user_class.find_by_email(@order.email)) + @order.associate_user!(Spree.user_class.find_by(email: @order.email)) end AdvanceOrderService.new(@order).call @@ -41,6 +41,15 @@ module Spree private + def order_params + params.require(:order).permit( + :email, + :use_billing, + bill_address_attributes: ::PermittedAttributes::Address.attributes, + ship_address_attributes: ::PermittedAttributes::Address.attributes + ) + end + def load_order @order = Order.find_by_number!(params[:order_id], include: :adjustments) end @@ -57,7 +66,7 @@ module Spree end def set_guest_checkout_status - registered_user = Spree::User.find_by_email(params[:order][:email]) + registered_user = Spree::User.find_by(email: params[:order][:email]) params[:order][:guest_checkout] = registered_user.nil? diff --git a/app/controllers/spree/admin/orders_controller.rb b/app/controllers/spree/admin/orders_controller.rb index 5f8154a355..9625ebe29d 100644 --- a/app/controllers/spree/admin/orders_controller.rb +++ b/app/controllers/spree/admin/orders_controller.rb @@ -44,7 +44,7 @@ module Spree end def update - unless @order.update_attributes(params[:order]) && @order.line_items.present? + unless @order.update_attributes(order_params) && @order.line_items.present? if @order.line_items.empty? @order.errors.add(:line_items, Spree.t('errors.messages.blank')) end @@ -108,6 +108,12 @@ module Spree private + def order_params + return params[:order] if params[:order].blank? + + params.require(:order).permit(:distributor_id, :order_cycle_id) + end + def load_order if params[:id] @order = Order.includes(:adjustments, :shipments, line_items: :adjustments). diff --git a/app/controllers/spree/admin/payment_methods_controller.rb b/app/controllers/spree/admin/payment_methods_controller.rb index c13712b9a1..a142eb6eb1 100644 --- a/app/controllers/spree/admin/payment_methods_controller.rb +++ b/app/controllers/spree/admin/payment_methods_controller.rb @@ -15,7 +15,7 @@ module Spree @payment_method = params[:payment_method]. delete(:type). constantize. - new(params[:payment_method]) + new(payment_method_params) @object = @payment_method invoke_callbacks(:create, :before) @@ -40,15 +40,7 @@ module Spree @payment_method = PaymentMethod.find(params[:id]) end - payment_method_params = params[ActiveModel::Naming.param_key(@payment_method)] || {} - attributes = params[:payment_method].merge(payment_method_params) - attributes.each do |k, _v| - if k.include?("password") && attributes[k].blank? - attributes.delete(k) - end - end - - if @payment_method.update_attributes(attributes) + if @payment_method.update_attributes(params_for_update) invoke_callbacks(:update, :after) flash[:success] = Spree.t(:successfully_updated, resource: Spree.t(:payment_method)) redirect_to edit_admin_payment_method_path(@payment_method) @@ -69,7 +61,7 @@ module Spree model_class.accessible_by(current_ability, action) else - model_class.scoped + model_class.where(nil) end collection = collection.managed_by(spree_current_user).by_name # This line added @@ -100,6 +92,17 @@ module Spree private + def payment_method_params + params.require(:payment_method).permit( + :name, :description, :type, :active, + :environment, :display_on, :tag_list, + :preferred_enterprise_id, :preferred_server, :preferred_login, :preferred_password, + :calculator_type, + :preferred_signature, :preferred_solution, :preferred_landing_page, :preferred_logourl, + :preferred_test_mode, distributor_ids: [] + ) + end + def force_environment params[:payment_method][:environment] = Rails.env unless spree_current_user.admin? end @@ -156,6 +159,21 @@ module Spree def stripe_provider?(provider) provider.name.ends_with?("StripeConnect", "StripeSCA") end + + # Merge payment method params with gateway params like :gateway_stripe_connect + # Also, remove password if present and blank + def params_for_update + gateway_params = params[ActiveModel::Naming.param_key(@payment_method)] || {} + params_for_update = payment_method_params.merge(gateway_params) + + params_for_update.each do |key, _value| + if key.include?("password") && params_for_update[key].blank? + params_for_update.delete(key) + end + end + + params_for_update + end end end end diff --git a/app/controllers/spree/admin/payments_controller.rb b/app/controllers/spree/admin/payments_controller.rb index a239652ed0..ae73760d8d 100644 --- a/app/controllers/spree/admin/payments_controller.rb +++ b/app/controllers/spree/admin/payments_controller.rb @@ -74,7 +74,7 @@ module Spree @payment.payment_method.payment_profiles_supported? && params[:card].present? && (params[:card] != 'new') - @payment.source = CreditCard.find_by_id(params[:card]) + @payment.source = CreditCard.find_by(id: params[:card]) end end @@ -84,7 +84,11 @@ module Spree source_params = params.delete(:payment_source)[params[:payment][:payment_method_id]] params[:payment][:source_attributes] = source_params end - params[:payment] + + params.require(:payment).permit( + :amount, :payment_method_id, + source_attributes: ::PermittedAttributes::PaymentSource.attributes + ) end def load_data diff --git a/app/controllers/spree/admin/products_controller.rb b/app/controllers/spree/admin/products_controller.rb index 0b18072869..a6099cf021 100644 --- a/app/controllers/spree/admin/products_controller.rb +++ b/app/controllers/spree/admin/products_controller.rb @@ -159,11 +159,23 @@ module Spree private - def product_set_from_params(params) - collection_hash = Hash[params[:products].each_with_index.map { |p, i| [i, p] }] + def product_set_from_params(_params) + collection_hash = Hash[products_params.each_with_index.map { |p, i| [i, p] }] Spree::ProductSet.new(collection_attributes: collection_hash) end + def products_params + params.require(:products).map do |product| + product.permit(::PermittedAttributes::Product.attributes) + end + end + + def permitted_resource_params + return params[:product] if params[:product].empty? + + params.require(:product).permit(::PermittedAttributes::Product.attributes) + end + def bulk_index_query(params) params[:filters].to_h.merge(page: params[:page], per_page: params[:per_page]) end diff --git a/app/controllers/spree/admin/properties_controller.rb b/app/controllers/spree/admin/properties_controller.rb index dcccad41f9..fd618f1272 100644 --- a/app/controllers/spree/admin/properties_controller.rb +++ b/app/controllers/spree/admin/properties_controller.rb @@ -1,6 +1,9 @@ module Spree module Admin class PropertiesController < ResourceController + def permitted_resource_params + params.require(:property).permit(:name, :presentation) + end end end end diff --git a/app/controllers/spree/admin/reports_controller.rb b/app/controllers/spree/admin/reports_controller.rb index a931606ed0..d576e048c5 100644 --- a/app/controllers/spree/admin/reports_controller.rb +++ b/app/controllers/spree/admin/reports_controller.rb @@ -238,15 +238,17 @@ module Spree end def suppliers_of_products_distributed_by(distributors) - distributors.map { |d| Spree::Product.in_distributor(d).includes(:supplier).all }. - flatten.map(&:supplier).uniq + supplier_ids = Spree::Product.in_distributors(distributors.select('enterprises.id')). + select('spree_products.supplier_id') + + Enterprise.where(id: supplier_ids) end # Load order cycles the current user has access to def my_order_cycles OrderCycle. active_or_complete. - accessible_by(spree_current_user). + visible_by(spree_current_user). order('orders_close_at DESC') end diff --git a/app/controllers/spree/admin/resource_controller.rb b/app/controllers/spree/admin/resource_controller.rb index d1ce6e8b27..8b7c0cde12 100644 --- a/app/controllers/spree/admin/resource_controller.rb +++ b/app/controllers/spree/admin/resource_controller.rb @@ -28,7 +28,7 @@ module Spree def update invoke_callbacks(:update, :before) - if @object.update_attributes(params[object_name]) + if @object.update_attributes(permitted_resource_params) invoke_callbacks(:update, :after) flash[:success] = flash_message_for(@object, :successfully_updated) respond_with(@object) do |format| @@ -43,7 +43,7 @@ module Spree def create invoke_callbacks(:create, :before) - @object.attributes = params[object_name] + @object.attributes = permitted_resource_params if @object.save invoke_callbacks(:create, :after) flash[:success] = flash_message_for(@object, :successfully_created) @@ -251,6 +251,13 @@ module Spree end end + # Permit specific list of params + # + # Example: params.require(object_name).permit(:name) + def permitted_resource_params + raise "All extending controllers need to override the method permitted_resource_params" + end + def collection_url(options = {}) if parent_data.present? spree.polymorphic_url([:admin, parent, model_class], options) diff --git a/app/controllers/spree/admin/return_authorizations_controller.rb b/app/controllers/spree/admin/return_authorizations_controller.rb index 9696835315..0411cd5b1b 100644 --- a/app/controllers/spree/admin/return_authorizations_controller.rb +++ b/app/controllers/spree/admin/return_authorizations_controller.rb @@ -19,6 +19,11 @@ module Spree @return_authorization.add_variant(variant_id.to_i, qty.to_i) end end + + def permitted_resource_params + params.require(:return_authorization). + permit(:amount, :reason, :stock_location_id) + end end end end diff --git a/app/controllers/spree/admin/search_controller.rb b/app/controllers/spree/admin/search_controller.rb index cc63ae2328..1d0f05fc1f 100644 --- a/app/controllers/spree/admin/search_controller.rb +++ b/app/controllers/spree/admin/search_controller.rb @@ -6,7 +6,7 @@ module Spree respond_to :json def known_users - @users = if exact_match = Spree.user_class.find_by_email(params[:q]) + @users = if exact_match = Spree.user_class.find_by(email: params[:q]) [exact_match] else spree_current_user.known_users.ransack(ransack_hash).result.limit(10) diff --git a/app/controllers/spree/admin/shipping_categories_controller.rb b/app/controllers/spree/admin/shipping_categories_controller.rb index e9d1677027..36c6e27db7 100644 --- a/app/controllers/spree/admin/shipping_categories_controller.rb +++ b/app/controllers/spree/admin/shipping_categories_controller.rb @@ -1,6 +1,12 @@ module Spree module Admin class ShippingCategoriesController < ResourceController + protected + + def permitted_resource_params + params.require(:shipping_category). + permit(:name, :temperature_controlled) + end end end end diff --git a/app/controllers/spree/admin/shipping_methods_controller.rb b/app/controllers/spree/admin/shipping_methods_controller.rb index 902a028b5b..fe3bdb5d86 100644 --- a/app/controllers/spree/admin/shipping_methods_controller.rb +++ b/app/controllers/spree/admin/shipping_methods_controller.rb @@ -81,6 +81,19 @@ module Spree @available_zones = Zone.order(:name) @calculators = ShippingMethod.calculators.sort_by(&:name) end + + def permitted_resource_params + params.require(:shipping_method).permit( + :name, :description, :display_on, + :require_ship_address, :tag_list, :calculator_type, + distributor_ids: [], + calculator_attributes: [ + :id, :preferred_currency, :preferred_amount, :preferred_per_kg, :preferred_flat_percent, + :preferred_first_item, :preferred_additional_item, :preferred_max_items, + :preferred_minimal_amount, :preferred_normal_amount, :preferred_discount_amount + ] + ) + end end end end diff --git a/app/controllers/spree/admin/states_controller.rb b/app/controllers/spree/admin/states_controller.rb index eebbee8d44..91b7672df2 100644 --- a/app/controllers/spree/admin/states_controller.rb +++ b/app/controllers/spree/admin/states_controller.rb @@ -24,6 +24,10 @@ module Spree def load_data @countries = Country.order(:name) end + + def permitted_resource_params + params.require(:state).permit(:name, :abbr) + end end end end diff --git a/app/controllers/spree/admin/tax_categories_controller.rb b/app/controllers/spree/admin/tax_categories_controller.rb index 26cff4479f..e4f7e4bff6 100644 --- a/app/controllers/spree/admin/tax_categories_controller.rb +++ b/app/controllers/spree/admin/tax_categories_controller.rb @@ -14,6 +14,12 @@ module Spree end end end + + private + + def permitted_resource_params + params.require(:tax_category).permit(:name, :description, :is_default) + end end end end diff --git a/app/controllers/spree/admin/tax_rates_controller.rb b/app/controllers/spree/admin/tax_rates_controller.rb index 89d9098849..0f828abfee 100644 --- a/app/controllers/spree/admin/tax_rates_controller.rb +++ b/app/controllers/spree/admin/tax_rates_controller.rb @@ -21,6 +21,13 @@ module Spree def create_after Rails.cache.delete('vat_rates') end + + def permitted_resource_params + params.require(:tax_rate).permit( + :name, :amount, :included_in_price, :zone_id, + :tax_category_id, :show_rate_in_label, :calculator_type + ) + end end end end diff --git a/app/controllers/spree/admin/taxonomies_controller.rb b/app/controllers/spree/admin/taxonomies_controller.rb index cbbf85e212..fb735ec4fa 100644 --- a/app/controllers/spree/admin/taxonomies_controller.rb +++ b/app/controllers/spree/admin/taxonomies_controller.rb @@ -16,6 +16,10 @@ module Spree admin_taxonomies_url end end + + def permitted_resource_params + params.require(:taxonomy).permit(:name) + end end end end diff --git a/app/controllers/spree/admin/taxons_controller.rb b/app/controllers/spree/admin/taxons_controller.rb index 240cb2cd03..fab6eaeb12 100644 --- a/app/controllers/spree/admin/taxons_controller.rb +++ b/app/controllers/spree/admin/taxons_controller.rb @@ -81,7 +81,7 @@ module Spree @update_children = true end - if @taxon.update_attributes(params[:taxon]) + if @taxon.update_attributes(taxon_params) flash[:success] = flash_message_for(@taxon, :successfully_updated) end @@ -105,6 +105,15 @@ module Spree @taxon.destroy respond_with(@taxon) { |format| format.json { render json: '' } } end + + private + + def taxon_params + params.require(:taxon).permit( + :name, :parent_id, :position, :icon, :description, :permalink, + :taxonomy_id, :meta_description, :meta_keywords, :meta_title + ) + end end end end diff --git a/app/controllers/spree/admin/users_controller.rb b/app/controllers/spree/admin/users_controller.rb index e66ec7f4af..d70aaa8d9b 100644 --- a/app/controllers/spree/admin/users_controller.rb +++ b/app/controllers/spree/admin/users_controller.rb @@ -22,7 +22,7 @@ module Spree roles = params[:user].delete("spree_role_ids") end - @user = Spree::User.new(params[:user]) + @user = Spree::User.new(user_params) if @user.save if roles @@ -41,7 +41,7 @@ module Spree roles = params[:user].delete("spree_role_ids") end - if @user.update_attributes(params[:user]) + if @user.update_attributes(user_params) if roles @user.spree_roles = roles.reject(&:blank?).collect{ |r| Spree::Role.find(r) } end @@ -76,7 +76,6 @@ module Spree return @collection if @collection.present? if request.xhr? && params[:q].present? - # Disabling proper nested include here due to rails 3.1 bug @collection = Spree::User. includes(:bill_address, :ship_address). where("spree_users.email #{LIKE} :search @@ -91,7 +90,7 @@ module Spree search: "#{params[:q].strip}%"). limit(params[:limit] || 100) else - @search = Spree::User.registered.ransack(params[:q]) + @search = Spree::User.ransack(params[:q]) @collection = @search. result. page(params[:page]). @@ -131,12 +130,16 @@ module Spree end def load_roles - @roles = Spree::Role.scoped + @roles = Spree::Role.where(nil) end def new_email_unconfirmed? params[:user][:email] != @user.email end + + def user_params + ::PermittedAttributes::User.new(params).call([:enterprise_limit]) + end end end end diff --git a/app/controllers/spree/admin/variants_controller.rb b/app/controllers/spree/admin/variants_controller.rb index 2e95fc0a9b..0936ffd155 100644 --- a/app/controllers/spree/admin/variants_controller.rb +++ b/app/controllers/spree/admin/variants_controller.rb @@ -63,6 +63,14 @@ module Spree end @collection end + + def variant_params + params.require(:variant).permit(::PermittedAttributes::Variant.attributes) + end + + def permitted_resource_params + variant_params + end end end end diff --git a/app/controllers/spree/admin/zones_controller.rb b/app/controllers/spree/admin/zones_controller.rb index 5b5b9d876b..d8bef6a215 100644 --- a/app/controllers/spree/admin/zones_controller.rb +++ b/app/controllers/spree/admin/zones_controller.rb @@ -21,6 +21,17 @@ module Spree @states = State.order(:name) @zones = Zone.order(:name) end + + def permitted_resource_params + params.require(:zone).permit( + :name, :description, :default_tax, :kind, + zone_members_attributes: [:id, :zoneable_id, :zoneable_type, :_destroy] + ) + end + + def location_after_save + edit_object_url(@zone) + end end end end diff --git a/app/controllers/spree/credit_cards_controller.rb b/app/controllers/spree/credit_cards_controller.rb index 81f3828b88..84e4189ef9 100644 --- a/app/controllers/spree/credit_cards_controller.rb +++ b/app/controllers/spree/credit_cards_controller.rb @@ -21,12 +21,12 @@ module Spree end def update - @credit_card = Spree::CreditCard.find_by_id(params[:id]) + @credit_card = Spree::CreditCard.find_by(id: params[:id]) return update_failed unless @credit_card authorize! :update, @credit_card - if @credit_card.update_attributes(params[:credit_card]) + if @credit_card.update_attributes(credit_card_params) render json: @credit_card, serializer: ::Api::CreditCardSerializer, status: :ok else update_failed @@ -36,7 +36,7 @@ module Spree end def destroy - @credit_card = Spree::CreditCard.find_by_id(params[:id]) + @credit_card = Spree::CreditCard.find_by(id: params[:id]) if @credit_card authorize! :destroy, @credit_card destroy_at_stripe @@ -97,5 +97,9 @@ module Spree def update_failed render json: { flash: { error: t(:card_could_not_be_updated) } }, status: :bad_request end + + def credit_card_params + params.require(:credit_card).permit(:is_default, :year, :month) + end end end diff --git a/app/controllers/spree/orders_controller.rb b/app/controllers/spree/orders_controller.rb index ff0a395fc6..9c3889c8df 100644 --- a/app/controllers/spree/orders_controller.rb +++ b/app/controllers/spree/orders_controller.rb @@ -26,7 +26,7 @@ module Spree before_filter :check_at_least_one_line_item, only: :update def show - @order = Spree::Order.find_by_number!(params[:id]) + @order = Spree::Order.find_by!(number: params[:id]) end def empty @@ -39,7 +39,7 @@ module Spree def check_authorization session[:access_token] ||= params[:token] - order = Spree::Order.find_by_number(params[:id]) || current_order + order = Spree::Order.find_by(number: params[:id]) || current_order if order authorize! :edit, order, session[:access_token] @@ -74,7 +74,7 @@ module Spree redirect_to(main_app.root_path) && return end - if @order.update_attributes(params[:order]) + if @order.update_attributes(order_params) discard_empty_line_items with_open_adjustments { update_totals_and_taxes } @@ -133,7 +133,7 @@ module Spree def remove_missing_line_items(attrs) attrs.select do |_i, line_item| - Spree::LineItem.find_by_id(line_item[:id]) + Spree::LineItem.find_by(id: line_item[:id]) end end @@ -149,7 +149,7 @@ module Spree end def cancel - @order = Spree::Order.find_by_number!(params[:id]) + @order = Spree::Order.find_by!(number: params[:id]) authorize! :cancel, @order if @order.cancel @@ -207,7 +207,7 @@ module Spree # If a specific order is requested, return it if it is COMPLETE and # changes are allowed and the user has access. Return nil if not. def changeable_order_from_number - order = Spree::Order.complete.find_by_number(params[:id]) + order = Spree::Order.complete.find_by(number: params[:id]) return nil unless order.andand.changes_allowed? && can?(:update, order) order @@ -224,5 +224,12 @@ module Spree redirect_to order_path(order_to_update) end end + + def order_params + params.require(:order).permit( + :distributor_id, :order_cycle_id, + line_items_attributes: [:id, :quantity] + ) + end end end diff --git a/app/controllers/spree/paypal_controller_decorator.rb b/app/controllers/spree/paypal_controller_decorator.rb index 0c620aeede..a239ca7e0a 100644 --- a/app/controllers/spree/paypal_controller_decorator.rb +++ b/app/controllers/spree/paypal_controller_decorator.rb @@ -2,6 +2,7 @@ Spree::PaypalController.class_eval do before_filter :enable_embedded_shopfront before_filter :destroy_orphaned_paypal_payments, only: :confirm after_filter :reset_order_when_complete, only: :confirm + before_filter :permit_parameters! def cancel flash[:notice] = Spree.t('flash.cancel', scope: 'paypal') @@ -18,6 +19,10 @@ Spree::PaypalController.class_eval do private + def permit_parameters! + params.permit(:token, :payment_method_id, :PayerID) + end + def reset_order_when_complete if current_order.complete? flash[:notice] = t(:order_processed_successfully) diff --git a/app/controllers/spree/users_controller.rb b/app/controllers/spree/users_controller.rb index d6d13f0e48..03aced66c8 100644 --- a/app/controllers/spree/users_controller.rb +++ b/app/controllers/spree/users_controller.rb @@ -20,12 +20,12 @@ module Spree # Endpoint for queries to check if a user is already registered def registered_email - user = Spree.user_class.find_by_email params[:email] + user = Spree.user_class.find_by email: params[:email] render json: { registered: user.present? } end def create - @user = Spree::User.new(params[:user]) + @user = Spree::User.new(user_params) if @user.save if current_order @@ -39,7 +39,7 @@ module Spree end def update - if @user.update_attributes(params[:user]) + if @user.update_attributes(user_params) if params[:user][:password].present? # this logic needed b/c devise wants to log us out after password changes Spree::User.reset_password_by_token(params[:user]) @@ -70,5 +70,9 @@ module Spree def accurate_title Spree.t(:my_account) end + + def user_params + ::PermittedAttributes::User.new(params).call + end end end diff --git a/app/controllers/user_passwords_controller.rb b/app/controllers/user_passwords_controller.rb index 37cceb6bfc..2db2dc81a4 100644 --- a/app/controllers/user_passwords_controller.rb +++ b/app/controllers/user_passwords_controller.rb @@ -34,7 +34,7 @@ class UserPasswordsController < Spree::UserPasswordsController end def user_unconfirmed? - user = Spree::User.find_by_email(params[:spree_user][:email]) + user = Spree::User.find_by(email: params[:spree_user][:email]) user && !user.confirmed? end end diff --git a/app/controllers/user_registrations_controller.rb b/app/controllers/user_registrations_controller.rb index fa6cb32028..2e9870b37e 100644 --- a/app/controllers/user_registrations_controller.rb +++ b/app/controllers/user_registrations_controller.rb @@ -10,7 +10,7 @@ class UserRegistrationsController < Spree::UserRegistrationsController # POST /resource/sign_up def create - @user = build_resource(params[:spree_user]) + @user = build_resource(spree_user_params) @user.locale = I18n.locale.to_s unless resource.save return render_error(@user.errors) @@ -32,6 +32,12 @@ class UserRegistrationsController < Spree::UserRegistrationsController private + def spree_user_params + return params[:spree_user] if params[:spree_user].empty? + + PermittedAttributes::User.new(params, :spree_user).call([:remember_me]) + end + def render_error(errors = {}) clean_up_passwords(resource) respond_to do |format| diff --git a/app/helpers/checkout_helper.rb b/app/helpers/checkout_helper.rb index 4e9ff57a58..c87abd0afb 100644 --- a/app/helpers/checkout_helper.rb +++ b/app/helpers/checkout_helper.rb @@ -44,8 +44,11 @@ module CheckoutHelper end def display_checkout_taxes_hash(order) - order.tax_adjustment_totals.each_with_object({}) do |(tax_rate, tax_amount), hash| - hash[number_to_percentage(tax_rate.amount * 100, precision: 1)] = Spree::Money.new tax_amount, currency: order.currency + totals = OrderTaxAdjustmentsFetcher.new(order).totals + + totals.each_with_object({}) do |(tax_rate, tax_amount), hash| + hash[number_to_percentage(tax_rate.amount * 100, precision: 1)] = + Spree::Money.new tax_amount, currency: order.currency end end diff --git a/app/helpers/injection_helper.rb b/app/helpers/injection_helper.rb index 508a984920..17c122f0a7 100644 --- a/app/helpers/injection_helper.rb +++ b/app/helpers/injection_helper.rb @@ -89,17 +89,21 @@ module InjectionHelper end def inject_taxons - inject_json_ams "taxons", Spree::Taxon.all, Api::TaxonSerializer + inject_json_ams "taxons", Spree::Taxon.all.to_a, Api::TaxonSerializer end def inject_properties - inject_json_ams "properties", Spree::Property.all, Api::PropertySerializer + inject_json_ams "properties", Spree::Property.all.to_a, Api::PropertySerializer end def inject_currency_config inject_json_ams "currencyConfig", {}, Api::CurrencyConfigSerializer end + def inject_open_street_map_config + inject_json_ams "openStreetMapConfig", {}, Api::OpenStreetMapConfigSerializer + end + def inject_spree_api_key render partial: "json/injection_ams", locals: { name: 'spreeApiKey', json: "'#{@spree_api_key}'" } end diff --git a/app/helpers/shop_helper.rb b/app/helpers/shop_helper.rb index a4c89bcd0d..8da650c4ef 100644 --- a/app/helpers/shop_helper.rb +++ b/app/helpers/shop_helper.rb @@ -50,4 +50,13 @@ module ShopHelper def no_open_order_cycles? @no_open_order_cycles ||= @order_cycles&.empty? end + + def show_shopping_cta? + return false if current_page?(main_app.shops_path) && current_distributor.blank? + + return false if current_distributor.present? && + current_page?(main_app.enterprise_shop_path(current_distributor)) + + true + end end diff --git a/app/helpers/spree/reports_helper.rb b/app/helpers/spree/reports_helper.rb index bc75cfb9e8..3f299c8250 100644 --- a/app/helpers/spree/reports_helper.rb +++ b/app/helpers/spree/reports_helper.rb @@ -11,10 +11,13 @@ module Spree end def report_payment_method_options(orders) - orders.map do |o| - pm = o.payments.first.payment_method - [pm.andand.name, pm.andand.id] - end.uniq + orders.map do |order| + payment_method = order.payments.first.andand.payment_method + + next unless payment_method + + [payment_method.name, payment_method.id] + end.compact.uniq end def report_shipping_method_options(orders) diff --git a/app/models/calculator/flat_percent_per_item.rb b/app/models/calculator/flat_percent_per_item.rb index 035dfe09bd..ff6e222e89 100644 --- a/app/models/calculator/flat_percent_per_item.rb +++ b/app/models/calculator/flat_percent_per_item.rb @@ -11,8 +11,6 @@ class Calculator::FlatPercentPerItem < Spree::Calculator preference :flat_percent, :decimal, default: 0 - attr_accessible :preferred_flat_percent - localize_number :preferred_flat_percent def self.description diff --git a/app/models/calculator/weight.rb b/app/models/calculator/weight.rb index 009d6bbf83..bb1f70c030 100644 --- a/app/models/calculator/weight.rb +++ b/app/models/calculator/weight.rb @@ -4,7 +4,6 @@ module Calculator class Weight < Spree::Calculator extend Spree::LocalizedNumber preference :per_kg, :decimal, default: 0.0 - attr_accessible :preferred_per_kg localize_number :preferred_per_kg def self.description diff --git a/app/models/column_preference.rb b/app/models/column_preference.rb index 9007cfca8e..ae5cdd9127 100644 --- a/app/models/column_preference.rb +++ b/app/models/column_preference.rb @@ -3,12 +3,6 @@ require 'open_food_network/column_preference_defaults' class ColumnPreference < ActiveRecord::Base extend OpenFoodNetwork::ColumnPreferenceDefaults - # These are the attributes used to identify a preference - attr_accessible :user_id, :action_name, :column_name - - # These are attributes that need to be mass assignable - attr_accessible :name, :visible - # Non-persisted attributes that only have one # setting (ie. the default) for a given column attr_accessor :name @@ -23,7 +17,7 @@ class ColumnPreference < ActiveRecord::Base default_preferences = __send__("#{action_name}_columns") filter(default_preferences, user, action_name) default_preferences.each_with_object([]) do |(column_name, default_attributes), preferences| - stored_preference = stored_preferences.find_by_column_name(column_name) + stored_preference = stored_preferences.find_by(column_name: column_name) if stored_preference stored_preference.assign_attributes(default_attributes.select{ |k, _v| stored_preference[k].nil? }) preferences << stored_preference diff --git a/app/models/concerns/order_shipment.rb b/app/models/concerns/order_shipment.rb index f03ecd2fcc..1f9c937bb5 100644 --- a/app/models/concerns/order_shipment.rb +++ b/app/models/concerns/order_shipment.rb @@ -35,7 +35,7 @@ module OrderShipment shipment = shipments.first - shipping_rate = shipment.shipping_rates.find_by_shipping_method_id(shipping_method_id) + shipping_rate = shipment.shipping_rates.find_by(shipping_method_id: shipping_method_id) return unless shipping_rate shipment.selected_shipping_rate_id = shipping_rate.id diff --git a/app/models/concerns/variant_stock.rb b/app/models/concerns/variant_stock.rb index dedf667c1b..1fd816bc8c 100644 --- a/app/models/concerns/variant_stock.rb +++ b/app/models/concerns/variant_stock.rb @@ -16,7 +16,6 @@ module VariantStock extend ActiveSupport::Concern included do - attr_accessible :on_hand, :on_demand after_update :save_stock end diff --git a/app/models/content_configuration.rb b/app/models/content_configuration.rb index 9c29a70576..29ab8f3308 100644 --- a/app/models/content_configuration.rb +++ b/app/models/content_configuration.rb @@ -17,6 +17,11 @@ class ContentConfiguration < Spree::Preferences::FileConfiguration preference :home_show_stats, :boolean, default: true has_attached_file :home_hero, default_url: "/assets/home/home.jpg" + # Map + preference :open_street_map_enabled, :boolean, default: false + preference :open_street_map_provider_name, :string, default: "OpenStreetMap.Mapnik" + preference :open_street_map_provider_options, :text, default: "{}" + # Producer sign-up page # All the following defaults using I18n don't work. # https://github.com/openfoodfoundation/openfoodnetwork/issues/3816 diff --git a/app/models/customer.rb b/app/models/customer.rb index 24564888ba..8328aba831 100644 --- a/app/models/customer.rb +++ b/app/models/customer.rb @@ -36,7 +36,7 @@ class Customer < ActiveRecord::Base end def associate_user - self.user = user || Spree::User.find_by_email(email) + self.user = user || Spree::User.find_by(email: email) end def check_for_orders diff --git a/app/models/enterprise.rb b/app/models/enterprise.rb index 8211a17157..0e60be9a14 100644 --- a/app/models/enterprise.rb +++ b/app/models/enterprise.rb @@ -17,8 +17,6 @@ class Enterprise < ActiveRecord::Base self.inheritance_column = nil - acts_as_gmappable process_geocoding: false - has_many :relationships_as_parent, class_name: 'EnterpriseRelationship', foreign_key: 'parent_id', dependent: :destroy @@ -93,9 +91,9 @@ class Enterprise < ActiveRecord::Base validate :enforce_ownership_limit, if: lambda { owner_id_changed? && !owner_id.nil? } before_validation :initialize_permalink, if: lambda { permalink.nil? } - before_validation :ensure_owner_is_manager, if: lambda { owner_id_changed? && !owner_id.nil? } before_validation :set_unused_address_fields after_validation :geocode_address + after_validation :ensure_owner_is_manager, if: lambda { owner_id_changed? && !owner_id.nil? } after_touch :touch_distributors after_create :set_default_contact @@ -120,10 +118,10 @@ class Enterprise < ActiveRecord::Base except(:select). select('DISTINCT enterprises.id') - if ready_enterprises.present? + if ready_enterprises.any? where("enterprises.id NOT IN (?)", ready_enterprises) else - where("TRUE") + where(nil) end } scope :is_primary_producer, -> { where(is_primary_producer: true) } @@ -182,7 +180,7 @@ class Enterprise < ActiveRecord::Base scope :managed_by, lambda { |user| if user.has_spree_role?('admin') - scoped + where(nil) else joins(:enterprise_roles).where('enterprise_roles.user_id = ?', user.id) end diff --git a/app/models/enterprise_fee.rb b/app/models/enterprise_fee.rb index f26fee44eb..bbcafa01dc 100644 --- a/app/models/enterprise_fee.rb +++ b/app/models/enterprise_fee.rb @@ -10,8 +10,6 @@ class EnterpriseFee < ActiveRecord::Base has_many :exchange_fees, dependent: :destroy has_many :exchanges, through: :exchange_fees - attr_accessible :enterprise_id, :fee_type, :name, :tax_category_id, :calculator_type, :inherits_tax_category - FEE_TYPES = %w(packing transport admin sales fundraising).freeze PER_ORDER_CALCULATORS = ['Spree::Calculator::FlatRate', 'Spree::Calculator::FlexiRate', 'Spree::Calculator::PriceSack'].freeze @@ -25,7 +23,7 @@ class EnterpriseFee < ActiveRecord::Base scope :managed_by, lambda { |user| if user.has_spree_role?('admin') - scoped + where(nil) else where('enterprise_id IN (?)', user.enterprises.select(&:id)) end diff --git a/app/models/enterprise_group.rb b/app/models/enterprise_group.rb index 4d8ff217f2..0bf0319bde 100644 --- a/app/models/enterprise_group.rb +++ b/app/models/enterprise_group.rb @@ -21,13 +21,6 @@ class EnterpriseGroup < ActiveRecord::Base before_validation :sanitize_permalink validates :permalink, uniqueness: true, presence: true - attr_accessible :name, :description, :long_description, :on_front_page, :enterprise_ids - attr_accessible :owner_id - attr_accessible :permalink - attr_accessible :logo, :promo_image - attr_accessible :address_attributes - attr_accessible :email, :website, :facebook, :instagram, :linkedin, :twitter - delegate :phone, :address1, :address2, :city, :zipcode, :state, :country, to: :address has_attached_file :logo, @@ -51,7 +44,7 @@ class EnterpriseGroup < ActiveRecord::Base scope :on_front_page, -> { where(on_front_page: true) } scope :managed_by, lambda { |user| if user.has_spree_role?('admin') - scoped + where(nil) else where('owner_id = ?', user.id) end diff --git a/app/models/enterprise_relationship.rb b/app/models/enterprise_relationship.rb index e0b9c62c03..f87eed6214 100644 --- a/app/models/enterprise_relationship.rb +++ b/app/models/enterprise_relationship.rb @@ -74,7 +74,7 @@ class EnterpriseRelationship < ActiveRecord::Base permissions.destroy_all else permissions.where('name NOT IN (?)', perms).destroy_all - perms.map { |name| permissions.find_or_initialize_by_name name } + perms.map { |name| permissions.find_or_initialize_by name: name } end end diff --git a/app/models/exchange.rb b/app/models/exchange.rb index 4531ec042b..01e23405a5 100644 --- a/app/models/exchange.rb +++ b/app/models/exchange.rb @@ -67,7 +67,7 @@ class Exchange < ActiveRecord::Base scope :managed_by, lambda { |user| if user.has_spree_role?('admin') - scoped + where(nil) else joins("LEFT JOIN enterprises senders ON senders.id = exchanges.sender_id"). joins("LEFT JOIN enterprises receivers ON receivers.id = exchanges.receiver_id"). diff --git a/app/models/inventory_item.rb b/app/models/inventory_item.rb index 5e4bb4ef8b..68f491ff6d 100644 --- a/app/models/inventory_item.rb +++ b/app/models/inventory_item.rb @@ -1,6 +1,4 @@ class InventoryItem < ActiveRecord::Base - attr_accessible :enterprise, :enterprise_id, :variant, :variant_id, :visible - belongs_to :enterprise belongs_to :variant, class_name: "Spree::Variant" diff --git a/app/models/order_cycle.rb b/app/models/order_cycle.rb index 7b4d8f2161..2b20033de6 100644 --- a/app/models/order_cycle.rb +++ b/app/models/order_cycle.rb @@ -10,11 +10,11 @@ class OrderCycle < ActiveRecord::Base # These scope names are prepended with "cached_" because there are existing accessor methods # :incoming_exchanges and :outgoing_exchanges. - has_many :cached_incoming_exchanges, conditions: { incoming: true }, class_name: "Exchange" - has_many :cached_outgoing_exchanges, conditions: { incoming: false }, class_name: "Exchange" + has_many :cached_incoming_exchanges, -> { where incoming: true }, class_name: "Exchange" + has_many :cached_outgoing_exchanges, -> { where incoming: false }, class_name: "Exchange" - has_many :suppliers, source: :sender, through: :cached_incoming_exchanges, uniq: true - has_many :distributors, source: :receiver, through: :cached_outgoing_exchanges, uniq: true + has_many :suppliers, -> { uniq }, source: :sender, through: :cached_incoming_exchanges + has_many :distributors, -> { uniq }, source: :receiver, through: :cached_outgoing_exchanges has_many :schedules, through: :order_cycle_schedules has_many :order_cycle_schedules @@ -63,16 +63,16 @@ class OrderCycle < ActiveRecord::Base scope :managed_by, lambda { |user| if user.has_spree_role?('admin') - scoped + where(nil) else - where(coordinator_id: user.enterprises) + where(coordinator_id: user.enterprises.to_a) end } # Return order cycles that user coordinates, sends to or receives from - scope :accessible_by, lambda { |user| + scope :visible_by, lambda { |user| if user.has_spree_role?('admin') - scoped + where(nil) else with_exchanging_enterprises_outer. where('order_cycles.coordinator_id IN (?) OR enterprises.id IN (?)', diff --git a/app/models/preference_sections/map_section.rb b/app/models/preference_sections/map_section.rb new file mode 100644 index 0000000000..cc16939c36 --- /dev/null +++ b/app/models/preference_sections/map_section.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module PreferenceSections + class MapSection + def name + I18n.t('admin.contents.edit.map') + end + + def preferences + [ + :open_street_map_enabled, + :open_street_map_provider_name, + :open_street_map_provider_options + ] + end + end +end diff --git a/app/models/producer_property.rb b/app/models/producer_property.rb index 67e48d34db..75f3d98f17 100644 --- a/app/models/producer_property.rb +++ b/app/models/producer_property.rb @@ -10,7 +10,7 @@ class ProducerProperty < ActiveRecord::Base def property_name=(name) if name.present? - self.property = Spree::Property.find_by_name(name) || + self.property = Spree::Property.find_by(name: name) || Spree::Property.create(name: name, presentation: name) end end diff --git a/app/models/product_import/entry_processor.rb b/app/models/product_import/entry_processor.rb index 3be6dddb31..5d705bd4bb 100644 --- a/app/models/product_import/entry_processor.rb +++ b/app/models/product_import/entry_processor.rb @@ -160,7 +160,9 @@ module ProductImport end product = Spree::Product.new - product.assign_attributes(entry.attributes.except('id', 'on_hand', 'on_demand')) + product.assign_attributes( + entry.assignable_attributes.except('id', 'on_hand', 'on_demand', 'display_name') + ) product.supplier_id = entry.producer_id if product.save diff --git a/app/models/product_import/entry_validator.rb b/app/models/product_import/entry_validator.rb index 475dae953c..fa2380c07b 100644 --- a/app/models/product_import/entry_validator.rb +++ b/app/models/product_import/entry_validator.rb @@ -62,7 +62,11 @@ module ProductImport end def mark_as_new_variant(entry, product_id) - new_variant = Spree::Variant.new(entry.attributes.except('id', 'product_id', 'on_hand', 'on_demand')) + new_variant = Spree::Variant.new( + entry.assignable_attributes.except('id', 'product_id', 'on_hand', 'on_demand', + 'variant_unit', 'variant_unit_name', + 'variant_unit_scale', 'primary_taxon_id') + ) new_variant.save new_variant.on_demand = entry.attributes['on_demand'] if entry.attributes['on_demand'].present? new_variant.on_hand = entry.attributes['on_hand'] if entry.attributes['on_hand'].present? @@ -295,7 +299,9 @@ module ProductImport def mark_as_new_product(entry) new_product = Spree::Product.new - new_product.assign_attributes(entry.attributes.except('id')) + new_product.assign_attributes( + entry.assignable_attributes.except('id', 'on_hand', 'on_demand', 'display_name') + ) new_product.supplier_id = entry.producer_id entry.on_hand = 0 if entry.on_hand.nil? @@ -307,7 +313,10 @@ module ProductImport end def mark_as_existing_variant(entry, existing_variant) - existing_variant.assign_attributes(entry.attributes.except('id', 'product_id')) + existing_variant.assign_attributes( + entry.assignable_attributes.except('id', 'product_id', 'variant_unit', 'variant_unit_name', + 'variant_unit_scale', 'primary_taxon_id') + ) check_on_hand_nil(entry, existing_variant) if existing_variant.valid? diff --git a/app/models/product_import/product_importer.rb b/app/models/product_import/product_importer.rb index 80a9744493..85600d0407 100644 --- a/app/models/product_import/product_importer.rb +++ b/app/models/product_import/product_importer.rb @@ -237,6 +237,19 @@ module ProductImport error_message: e.message)) end [] + rescue CSV::MalformedCSVError => e + add_malformed_csv_error e.message + [] + end + + # This error is raised twice because init_product_importer calls both + # build_entries and buils_all_entries + def add_malformed_csv_error(error_message) + unless errors.added?(:importer, I18n.t('admin.product_import.model.malformed_csv', + error_message: error_message)) + errors.add(:importer, I18n.t('admin.product_import.model.malformed_csv', + error_message: error_message)) + end end def build_entries_in_range diff --git a/app/models/product_import/spreadsheet_entry.rb b/app/models/product_import/spreadsheet_entry.rb index 990124e24b..f9ccac04a5 100644 --- a/app/models/product_import/spreadsheet_entry.rb +++ b/app/models/product_import/spreadsheet_entry.rb @@ -20,6 +20,20 @@ module ProductImport :tax_category_id, :shipping_category_id, :description, :import_date, :enterprise, :enterprise_id + NON_DISPLAY_ATTRIBUTES = ['id', 'product_id', 'unscaled_units', 'variant_id', 'enterprise', + 'enterprise_id', 'producer_id', 'distributor_id', 'primary_taxon', + 'primary_taxon_id', 'category_id', 'shipping_category_id', + 'tax_category_id', 'variant_unit_scale', 'variant_unit', + 'unit_value'].freeze + + NON_PRODUCT_ATTRIBUTES = ['line_number', 'valid', 'errors', 'product_object', + 'product_validations', 'inventory_validations', 'validates_as', + 'save_type', 'on_hand_nil', 'has_overrides'].freeze + + NON_ASSIGNABLE_ATTRIBUTES = ['producer', 'producer_id', 'category', 'shipping_category', + 'tax_category', 'units', 'unscaled_units', 'unit_type', + 'enterprise', 'enterprise_id'].freeze + def initialize(attrs) @validates_as = '' remove_empty_skus attrs @@ -43,7 +57,11 @@ module ProductImport instance_variables.each do |var| attrs[var.to_s.delete("@")] = instance_variable_get(var) end - attrs.except(*non_product_attributes) + attrs.except(*NON_PRODUCT_ATTRIBUTES) + end + + def assignable_attributes + attributes.except(*NON_ASSIGNABLE_ATTRIBUTES) end def displayable_attributes @@ -52,7 +70,7 @@ module ProductImport instance_variables.each do |var| attrs[var.to_s.delete("@")] = instance_variable_get(var) end - attrs.except(*non_product_attributes, *non_display_attributes) + attrs.except(*NON_PRODUCT_ATTRIBUTES, *NON_DISPLAY_ATTRIBUTES) end def invalid_attributes @@ -61,7 +79,7 @@ module ProductImport errors.each do |attr, message| invalid_attrs[attr.to_s] = "#{attr.to_s.capitalize} #{message.first}" end - invalid_attrs.except(*non_product_attributes, *non_display_attributes) + invalid_attrs.except(* NON_PRODUCT_ATTRIBUTES, *NON_DISPLAY_ATTRIBUTES) end private @@ -75,22 +93,9 @@ module ProductImport units.converted_attributes.each do |attr, value| if respond_to?("#{attr}=") - public_send("#{attr}=", value) unless non_product_attributes.include?(attr) + public_send("#{attr}=", value) unless NON_PRODUCT_ATTRIBUTES.include?(attr) end end end - - def non_display_attributes - ['id', 'product_id', 'unscaled_units', 'variant_id', 'enterprise', - 'enterprise_id', 'producer_id', 'distributor_id', 'primary_taxon', - 'primary_taxon_id', 'category_id', 'shipping_category_id', - 'tax_category_id', 'variant_unit_scale', 'variant_unit', 'unit_value'] - end - - def non_product_attributes - ['line_number', 'valid', 'errors', 'product_object', - 'product_validations', 'inventory_validations', 'validates_as', - 'save_type', 'on_hand_nil', 'has_overrides'] - end end end diff --git a/app/models/schedule.rb b/app/models/schedule.rb index 386461ed07..5fe5da3205 100644 --- a/app/models/schedule.rb +++ b/app/models/schedule.rb @@ -3,11 +3,8 @@ class Schedule < ActiveRecord::Base has_many :order_cycles, through: :order_cycle_schedules has_many :order_cycle_schedules, dependent: :destroy - has_many :coordinators, uniq: true, through: :order_cycles - attr_accessible :name, :order_cycle_ids - - validates :order_cycles, presence: true + has_many :coordinators, -> { uniq }, through: :order_cycles scope :with_coordinator, lambda { |enterprise| joins(:order_cycles).where('coordinator_id = ?', enterprise.id).select('DISTINCT schedules.*') } diff --git a/app/models/spree/ability_decorator.rb b/app/models/spree/ability_decorator.rb index f416a9d53f..6eb4727c03 100644 --- a/app/models/spree/ability_decorator.rb +++ b/app/models/spree/ability_decorator.rb @@ -39,7 +39,7 @@ class AbilityDecorator # OR if they manage a producer which is included in any order cycles def can_manage_order_cycles?(user) can_manage_orders?(user) || - OrderCycle.accessible_by(user).any? + OrderCycle.visible_by(user).any? end # Users can manage orders if they have a sells own/any enterprise. @@ -194,7 +194,7 @@ class AbilityDecorator def add_order_cycle_management_abilities(user) can [:admin, :index, :read, :edit, :update, :incoming, :outgoing], OrderCycle do |order_cycle| - OrderCycle.accessible_by(user).include? order_cycle + OrderCycle.visible_by(user).include? order_cycle end can [:admin, :index, :create], Schedule can [:admin, :update, :destroy], Schedule do |schedule| diff --git a/app/models/spree/address_decorator.rb b/app/models/spree/address_decorator.rb index 603423e8d6..a8b1799e54 100644 --- a/app/models/spree/address_decorator.rb +++ b/app/models/spree/address_decorator.rb @@ -1,7 +1,7 @@ Spree::Address.class_eval do include AddressDisplay - has_one :enterprise, dependent: :restrict + has_one :enterprise, dependent: :restrict_with_exception belongs_to :country, class_name: "Spree::Country" after_save :touch_enterprise diff --git a/app/models/spree/adjustment_decorator.rb b/app/models/spree/adjustment_decorator.rb index 2e1dfcebf7..dbbaa6ae95 100644 --- a/app/models/spree/adjustment_decorator.rb +++ b/app/models/spree/adjustment_decorator.rb @@ -9,8 +9,8 @@ module Spree # So we don't need the option `dependent: :destroy` as long as # AdjustmentMetadata has no destroy logic itself. has_one :metadata, class_name: 'AdjustmentMetadata' - belongs_to :tax_rate, foreign_key: 'originator_id', - conditions: "spree_adjustments.originator_type = 'Spree::TaxRate'" + belongs_to :tax_rate, -> { where spree_adjustments: { originator_type: 'Spree::TaxRate' } }, + foreign_key: 'originator_id' scope :enterprise_fee, -> { where(originator_type: 'EnterpriseFee') } scope :admin, -> { where(source_type: nil, originator_type: nil) } @@ -18,14 +18,12 @@ module Spree where(originator_type: 'Spree::TaxRate', adjustable_type: 'Spree::LineItem') } - scope :with_tax, -> { where('spree_adjustments.included_tax > 0') } + scope :with_tax, -> { where('spree_adjustments.included_tax <> 0') } scope :without_tax, -> { where('spree_adjustments.included_tax = 0') } scope :payment_fee, -> { where(AdjustmentScopes::PAYMENT_FEE_SCOPE) } scope :shipping, -> { where(AdjustmentScopes::SHIPPING_SCOPE) } scope :eligible, -> { where(AdjustmentScopes::ELIGIBLE_SCOPE) } - attr_accessible :included_tax - localize_number :amount def set_included_tax!(rate) diff --git a/app/models/spree/app_configuration_decorator.rb b/app/models/spree/app_configuration_decorator.rb index 5b11a0ee61..a039ddbd45 100644 --- a/app/models/spree/app_configuration_decorator.rb +++ b/app/models/spree/app_configuration_decorator.rb @@ -26,6 +26,7 @@ Spree::AppConfiguration.class_eval do preference :bugherd_api_key, :string, default: nil preference :matomo_url, :string, default: nil preference :matomo_site_id, :string, default: nil + preference :matomo_tag_manager_url, :string, default: nil # Invoices & Receipts preference :enable_invoices?, :boolean, default: true diff --git a/app/models/spree/calculator/price_sack_decorator.rb b/app/models/spree/calculator/price_sack_decorator.rb index b474f77861..389649f916 100644 --- a/app/models/spree/calculator/price_sack_decorator.rb +++ b/app/models/spree/calculator/price_sack_decorator.rb @@ -13,7 +13,7 @@ module Spree end def compute(object) - min = preferred_minimal_amount.to_i + min = preferred_minimal_amount.to_f order_amount = line_items_for(object).map { |x| x.price * x.quantity }.sum if order_amount < min diff --git a/app/models/spree/concerns/payment_method_distributors.rb b/app/models/spree/concerns/payment_method_distributors.rb index 0913889a8e..e5d93abd07 100644 --- a/app/models/spree/concerns/payment_method_distributors.rb +++ b/app/models/spree/concerns/payment_method_distributors.rb @@ -8,7 +8,6 @@ module Spree::PaymentMethodDistributors def self.included(base) base.class_eval do - attr_accessible :distributor_ids has_and_belongs_to_many :distributors, join_table: 'distributors_payment_methods', class_name: 'Enterprise', foreign_key: 'payment_method_id', association_foreign_key: 'distributor_id' end end diff --git a/app/models/spree/credit_card_decorator.rb b/app/models/spree/credit_card_decorator.rb index f1f4a5d71c..b8c78f01b7 100644 --- a/app/models/spree/credit_card_decorator.rb +++ b/app/models/spree/credit_card_decorator.rb @@ -1,11 +1,5 @@ Spree::CreditCard.class_eval do - # Allows user to submit these attributes with checkout request - # Required to be able to correctly store details for token-based charges - # Obviously can be removed once we are using strong params - attr_accessible :cc_type, :last_digits - # For holding customer preference in memory - attr_accessible :save_requested_by_customer, :is_default attr_writer :save_requested_by_customer # Should be able to remove once we reach Spree v2.2.0 diff --git a/app/models/spree/gateway/migs.rb b/app/models/spree/gateway/migs.rb index 06f31c48e8..b829062f6e 100644 --- a/app/models/spree/gateway/migs.rb +++ b/app/models/spree/gateway/migs.rb @@ -3,8 +3,6 @@ module Spree preference :login, :string preference :password, :string - attr_accessible :preferred_login, :preferred_password - def provider_class ActiveMerchant::Billing::MigsGateway end diff --git a/app/models/spree/gateway/pin.rb b/app/models/spree/gateway/pin.rb index 127c2adeac..c50a3fa773 100644 --- a/app/models/spree/gateway/pin.rb +++ b/app/models/spree/gateway/pin.rb @@ -2,8 +2,6 @@ module Spree class Gateway::Pin < Gateway preference :api_key, :string - attr_accessible :preferred_api_key - def provider_class ActiveMerchant::Billing::PinGateway end diff --git a/app/models/spree/gateway/stripe_connect.rb b/app/models/spree/gateway/stripe_connect.rb index d1a7a70c2b..3484dc3e4f 100644 --- a/app/models/spree/gateway/stripe_connect.rb +++ b/app/models/spree/gateway/stripe_connect.rb @@ -7,8 +7,6 @@ module Spree validate :ensure_enterprise_selected - attr_accessible :preferred_enterprise_id - def method_type 'stripe' end @@ -22,7 +20,7 @@ module Spree end def stripe_account_id - StripeAccount.find_by_enterprise_id(preferred_enterprise_id).andand.stripe_user_id + StripeAccount.find_by(enterprise_id: preferred_enterprise_id).andand.stripe_user_id end # NOTE: the name of this method is determined by Spree::Payment::Processing diff --git a/app/models/spree/gateway/stripe_sca.rb b/app/models/spree/gateway/stripe_sca.rb index a970aa87ed..5a07fe1b3c 100644 --- a/app/models/spree/gateway/stripe_sca.rb +++ b/app/models/spree/gateway/stripe_sca.rb @@ -14,8 +14,6 @@ module Spree validate :ensure_enterprise_selected - attr_accessible :preferred_enterprise_id - def method_type 'stripe_sca' end diff --git a/app/models/spree/line_item_decorator.rb b/app/models/spree/line_item_decorator.rb index 6f085f30f5..5d22c0fbc4 100644 --- a/app/models/spree/line_item_decorator.rb +++ b/app/models/spree/line_item_decorator.rb @@ -12,10 +12,6 @@ Spree::LineItem.class_eval do # Allows manual skipping of Stock::AvailabilityValidator attr_accessor :skip_stock_check - attr_accessible :max_quantity, :final_weight_volume, :price - attr_accessible :final_weight_volume, :price, as: :api - attr_accessible :skip_stock_check - before_save :calculate_final_weight_volume, if: :quantity_changed?, unless: :final_weight_volume_changed? after_save :update_units @@ -26,7 +22,7 @@ Spree::LineItem.class_eval do # -- Scopes scope :managed_by, lambda { |user| if user.has_spree_role?('admin') - scoped + where(nil) else # Find line items that are from orders distributed by the user or supplied by the user joins(variant: :product). @@ -54,13 +50,13 @@ Spree::LineItem.class_eval do where('order_cycles.id = ?', order_cycle) } - scope :supplied_by, lambda { |enterprise| - joins(:product). - where('spree_products.supplier_id = ?', enterprise) - } + # Here we are simply joining the line item to its variant and product + # We dont use joins here to avoid the default scopes, + # and with that, include deleted variants and deleted products scope :supplied_by_any, lambda { |enterprises| - joins(:product). - where('spree_products.supplier_id IN (?)', enterprises) + product_ids = Spree::Product.unscoped.where(supplier_id: enterprises).select(:id) + variant_ids = Spree::Variant.unscoped.where(product_id: product_ids).select(:id) + where("spree_line_items.variant_id IN (?)", variant_ids) } scope :with_tax, -> { @@ -79,9 +75,12 @@ Spree::LineItem.class_eval do where('spree_adjustments.id IS NULL') } + # Overridden so that LineItems always have access to soft-deleted Variant + # attributes. In some situations, unscoped super will be nil, in these cases + # we fetch the variant using the variant_id. See isssue #4946 for more + # details def variant - # Overridden so that LineItems always have access to soft-deleted Variant attributes - Spree::Variant.unscoped { super } + Spree::Variant.unscoped { super } || Spree::Variant.unscoped.find(variant_id) end def cap_quantity_at_stock! diff --git a/app/models/spree/order_decorator.rb b/app/models/spree/order_decorator.rb index 08c68c6111..a36d8e1312 100644 --- a/app/models/spree/order_decorator.rb +++ b/app/models/spree/order_decorator.rb @@ -21,15 +21,23 @@ Spree::Order.class_eval do # This removes "inverse_of: source" which breaks shipment adjustment calculations # This change is done in Spree 2.1 (see https://github.com/spree/spree/commit/3fa44165c7825f79a2fa4eb79b99dc29944c5d55) # When OFN gets to Spree 2.1, this can be removed - has_many :adjustments, + has_many :adjustments, -> { order "#{Spree::Adjustment.table_name}.created_at ASC" }, as: :adjustable, - dependent: :destroy, - order: "#{Spree::Adjustment.table_name}.created_at ASC" + dependent: :destroy validates :customer, presence: true, if: :require_customer? validate :products_available_from_new_distribution, if: lambda { distributor_id_changed? || order_cycle_id_changed? } validate :disallow_guest_order - attr_accessible :order_cycle_id, :distributor_id, :customer_id + + # The EmailValidator introduced in Spree 2.1 is not working + # So here we remove it and re-introduce the regexp validation rule from Spree 2.0 + _validate_callbacks.each do |callback| + if callback.raw_filter.respond_to? :attributes + callback.raw_filter.attributes.delete :email + end + end + validates :email, presence: true, format: /\A([\w\.%\+\-']+)@([\w\-]+\.)+([\w]{2,})\z/i, + if: :require_email before_validation :associate_customer, unless: :customer_id? before_validation :ensure_customer, unless: :customer_is_valid? @@ -51,7 +59,7 @@ Spree::Order.class_eval do # -- Scopes scope :managed_by, lambda { |user| if user.has_spree_role?('admin') - scoped + where(nil) else # Find orders that are distributed by the user or have products supplied by the user # WARNING: This only filters orders, you'll need to filter line items separately using LineItem.managed_by @@ -65,7 +73,7 @@ Spree::Order.class_eval do scope :distributed_by_user, lambda { |user| if user.has_spree_role?('admin') - scoped + where(nil) else where('spree_orders.distributor_id IN (?)', user.enterprises.select(&:id)) end @@ -193,7 +201,7 @@ Spree::Order.class_eval do Bugsnag.notify(e) do |report| report.add_tab(:order, attributes) report.add_tab(:shipment, shipment.attributes) - report.add_tab(:shipment_in_db, Spree::Shipment.find_by_id(shipment.id).attributes) + report.add_tab(:shipment_in_db, Spree::Shipment.find_by(id: shipment.id).attributes) end end @@ -304,20 +312,12 @@ Spree::Order.class_eval do (adjustments + price_adjustments).sum(&:included_tax) end - def tax_adjustments - adjustments.with_tax + - line_items.includes(:adjustments).map { |li| li.adjustments.with_tax }.flatten - end + def price_adjustments + adjustments = [] - def tax_adjustment_totals - tax_adjustments.each_with_object({}) do |adjustment, hash| - tax_rates = TaxRateFinder.tax_rates_of(adjustment) - tax_rates_hash = Hash[tax_rates.collect do |tax_rate| - tax_amount = tax_rates.one? ? adjustment.included_tax : tax_rate.compute_tax(adjustment.amount) - [tax_rate, tax_amount] - end] - hash.update(tax_rates_hash) { |_tax_rate, amount1, amount2| amount1 + amount2 } - end + line_items.each { |line_item| adjustments.concat line_item.adjustments } + + adjustments end def price_adjustment_totals @@ -394,7 +394,7 @@ Spree::Order.class_eval do def associate_customer return customer if customer.present? - self.customer = Customer.of(distributor).find_by_email(email_for_customer) + self.customer = Customer.of(distributor).find_by(email: email_for_customer) end def ensure_customer diff --git a/app/models/spree/order_updater_decorator.rb b/app/models/spree/order_updater_decorator.rb new file mode 100644 index 0000000000..b227444c8b --- /dev/null +++ b/app/models/spree/order_updater_decorator.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +Spree::OrderUpdater.class_eval do + # Override spree method to make it update all adjustments as in Spree v2.0.4 + def update_shipping_adjustments + order.adjustments.reload.each(&:update!) + end +end diff --git a/app/models/spree/payment_decorator.rb b/app/models/spree/payment_decorator.rb index 5bd3e5b326..ec84a83a83 100644 --- a/app/models/spree/payment_decorator.rb +++ b/app/models/spree/payment_decorator.rb @@ -10,10 +10,13 @@ module Spree after_save :ensure_correct_adjustment, :update_order - attr_accessible :source - localize_number :amount + # We bypass this after_rollback callback that is setup in Spree::Payment + # The issues the callback fixes are not experienced in OFN: + # if a payment fails on checkout the state "failed" is persisted correctly + def persist_invalid; end + def ensure_correct_adjustment revoke_adjustment_eligibility if ['failed', 'invalid'].include?(state) return if adjustment.try(:finalized?) @@ -59,12 +62,12 @@ module Spree record_response(response) if response.success? - self.class.create({ order: order, - source: self, - payment_method: payment_method, - amount: refund_amount.abs * -1, - response_code: response.authorization, - state: 'completed' }, without_protection: true) + self.class.create(order: order, + source: self, + payment_method: payment_method, + amount: refund_amount.abs * -1, + response_code: response.authorization, + state: 'completed') else gateway_error(response) end diff --git a/app/models/spree/payment_method_decorator.rb b/app/models/spree/payment_method_decorator.rb index 6077cbc1c7..3da3919bf0 100644 --- a/app/models/spree/payment_method_decorator.rb +++ b/app/models/spree/payment_method_decorator.rb @@ -8,16 +8,14 @@ Spree::PaymentMethod.class_eval do has_many :credit_cards, class_name: "Spree::CreditCard" # from Spree v.2.3.0 d470b31798f37 - attr_accessible :tag_list - after_initialize :init - validates_with DistributorsValidator + validate :distributor_validation # -- Scopes scope :managed_by, lambda { |user| if user.has_spree_role?('admin') - scoped + where(nil) else joins(:distributors). where('distributors_payment_methods.distributor_id IN (?)', user.enterprises.select(&:id)). @@ -77,4 +75,10 @@ Spree::PaymentMethod.class_eval do name[i..-1] end end + + private + + def distributor_validation + validates_with DistributorsValidator + end end diff --git a/app/models/spree/product_decorator.rb b/app/models/spree/product_decorator.rb index fe20fe5194..602329b5c1 100644 --- a/app/models/spree/product_decorator.rb +++ b/app/models/spree/product_decorator.rb @@ -17,11 +17,6 @@ Spree::Product.class_eval do delegate_belongs_to :master, :unit_value, :unit_description delegate :images_attributes=, :display_as=, to: :master - attr_accessible :supplier_id, :primary_taxon_id, :distributor_ids - attr_accessible :group_buy, :group_buy_unit_size, :unit_description, :notes, :images_attributes, :display_as - attr_accessible :variant_unit, :variant_unit_scale, :variant_unit_name, :unit_value - attr_accessible :inherits_properties, :sku - validates :supplier, presence: true validates :primary_taxon, presence: true validates :tax_category_id, presence: true, if: "Spree::Config.products_require_tax_category" @@ -84,6 +79,12 @@ Spree::Product.class_eval do select('distinct spree_products.*') } + scope :in_distributors, lambda { |distributors| + with_order_cycles_outer. + where('(o_exchanges.incoming = ? AND o_exchanges.receiver_id IN (?))', false, distributors). + uniq + } + # Products supplied by a given enterprise or distributed via that enterprise through an OC scope :in_supplier_or_distributor, lambda { |enterprise| enterprise = enterprise.respond_to?(:id) ? enterprise.id : enterprise.to_i @@ -115,7 +116,7 @@ Spree::Product.class_eval do scope :managed_by, lambda { |user| if user.has_spree_role?('admin') - scoped + where(nil) else where('supplier_id IN (?)', user.enterprises.select("enterprises.id")) end @@ -158,18 +159,6 @@ Spree::Product.class_eval do self.class.in_order_cycle(order_cycle).include? self end - # overriding to check self.on_demand as well - def has_stock? - has_variants? ? variants.any?(&:in_stock?) : (on_demand || master.in_stock?) - end - - def has_stock_for_distribution?(order_cycle, distributor) - # This product has stock for a distribution if it is available on-demand - # or if one of its variants in the distribution is in stock - (!has_variants? && on_demand) || - variants_distributed_by(order_cycle, distributor).any?(&:in_stock?) - end - def variants_distributed_by(order_cycle, distributor) order_cycle.variants_distributed_by(distributor).where(product_id: self) end @@ -184,7 +173,7 @@ Spree::Product.class_eval do option_type_name = "unit_#{variant_unit}" option_type_presentation = variant_unit.capitalize - Spree::OptionType.find_by_name(option_type_name) || + Spree::OptionType.find_by(name: option_type_name) || Spree::OptionType.create!(name: option_type_name, presentation: option_type_presentation) end diff --git a/app/models/spree/property.rb b/app/models/spree/property.rb index a598d1594b..18f2497786 100644 --- a/app/models/spree/property.rb +++ b/app/models/spree/property.rb @@ -4,8 +4,6 @@ module Spree has_many :products, through: :product_properties has_many :producer_properties - attr_accessible :name, :presentation - validates :name, :presentation, presence: true scope :sorted, -> { order(:name) } diff --git a/app/models/spree/shipment_decorator.rb b/app/models/spree/shipment_decorator.rb index b9cb0d07f1..b23bd7266f 100644 --- a/app/models/spree/shipment_decorator.rb +++ b/app/models/spree/shipment_decorator.rb @@ -15,13 +15,14 @@ module Spree end end - # The shipment manifest is built by loading inventory units and variants from the DB - # These variants come unscoped - # So, we need to scope the variants just after the manifest is built - def manifest_with_scoping - manifest_without_scoping.each { |item| scoper.scope(item.variant) } + def manifest + inventory_units.group_by(&:variant).map do |variant, units| + states = {} + units.group_by(&:state).each { |state, iu| states[state] = iu.count } + scoper.scope(variant) + OpenStruct.new(variant: variant, quantity: units.length, states: states) + end end - alias_method_chain :manifest, :scoping def scoper @scoper ||= OpenFoodNetwork::ScopeVariantToHub.new(order.distributor) diff --git a/app/models/spree/shipping_category_decorator.rb b/app/models/spree/shipping_category_decorator.rb deleted file mode 100644 index b78ba3337c..0000000000 --- a/app/models/spree/shipping_category_decorator.rb +++ /dev/null @@ -1,3 +0,0 @@ -Spree::ShippingCategory.class_eval do - attr_accessible :temperature_controlled -end diff --git a/app/models/spree/shipping_method_decorator.rb b/app/models/spree/shipping_method_decorator.rb index ec1b0a8dca..58d42db120 100644 --- a/app/models/spree/shipping_method_decorator.rb +++ b/app/models/spree/shipping_method_decorator.rb @@ -5,14 +5,12 @@ Spree::ShippingMethod.class_eval do has_many :distributors, through: :distributor_shipping_methods, class_name: 'Enterprise', foreign_key: 'distributor_id' after_save :touch_distributors - attr_accessible :distributor_ids, :description - attr_accessible :require_ship_address, :tag_list - validates_with DistributorsValidator + validate :distributor_validation scope :managed_by, lambda { |user| if user.has_spree_role?('admin') - scoped + where(nil) else joins(:distributors). where('distributors_shipping_methods.distributor_id IN (?)', user.enterprises.select(&:id)). @@ -42,7 +40,7 @@ Spree::ShippingMethod.class_eval do select("distributor_id"). select("BOOL_OR(spree_shipping_methods.require_ship_address = 'f') AS pickup"). select("BOOL_OR(spree_shipping_methods.require_ship_address = 't') AS delivery"). - map { |sm| [sm.distributor_id.to_i, { pickup: sm.pickup == 't', delivery: sm.delivery == 't' }] } + map { |sm| [sm.distributor_id.to_i, { pickup: sm.pickup, delivery: sm.delivery }] } ] end @@ -81,6 +79,12 @@ Spree::ShippingMethod.class_eval do private def touch_distributors - distributors.each(&:touch) + distributors.each do |distributor| + distributor.touch if distributor.persisted? + end + end + + def distributor_validation + validates_with DistributorsValidator end end diff --git a/app/models/spree/user.rb b/app/models/spree/user.rb index 63d51f657c..3df57a9cf8 100644 --- a/app/models/spree/user.rb +++ b/app/models/spree/user.rb @@ -10,15 +10,9 @@ module Spree before_validation :set_login before_destroy :check_completed_orders - # Setup accessible (or protected) attributes for your model - attr_accessible :email, :password, :password_confirmation, - :remember_me, :persistence_token, :login - - users_table_name = User.table_name roles_table_name = Role.table_name scope :admin, lambda { includes(:spree_roles).where("#{roles_table_name}.name" => "admin") } - scope :registered, -> { where("#{users_table_name}.email NOT LIKE ?", "%@example.net") } has_many :enterprise_roles, dependent: :destroy has_many :enterprises, through: :enterprise_roles @@ -34,8 +28,6 @@ module Spree accepts_nested_attributes_for :bill_address accepts_nested_attributes_for :ship_address - attr_accessible :enterprise_ids, :enterprise_roles_attributes, :enterprise_limit, - :locale, :bill_address_attributes, :ship_address_attributes after_create :associate_customers validate :limit_owned_enterprises @@ -49,16 +41,6 @@ module Spree class DestroyWithOrdersError < StandardError; end - # Creates an anonymous user. An anonymous user is basically an auto-generated +User+ account - # that is created for the customer behind the scenes and it's transparent to the customer. - # All +Orders+ must have a +User+ so this is necessary when adding to the "cart" (an order) - # and before the customer has a chance to provide an email or to register. - def self.anonymous! - token = User.generate_token(:persistence_token) - User.create(email: "#{token}@example.net", - password: token, password_confirmation: token, persistence_token: token) - end - def self.admin_created? User.admin.count > 0 end @@ -67,10 +49,6 @@ module Spree has_spree_role?('admin') end - def anonymous? - email =~ /@example.net$/ ? true : false - end - def send_reset_password_instructions generate_reset_password_token! UserMailer.reset_password_instructions(id).deliver @@ -81,7 +59,7 @@ module Spree def known_users if admin? - Spree::User.scoped + Spree::User.where(nil) else Spree::User .includes(:enterprises) @@ -92,7 +70,7 @@ module Spree def build_enterprise_roles Enterprise.all.find_each do |enterprise| - unless enterprise_roles.find_by_enterprise_id enterprise.id + unless enterprise_roles.find_by enterprise_id: enterprise.id enterprise_roles.build(enterprise: enterprise) end end @@ -101,7 +79,7 @@ module Spree def customer_of(enterprise) return nil unless enterprise - customers.find_by_enterprise_id(enterprise) + customers.find_by(enterprise_id: enterprise) end def welcome_after_confirm @@ -173,14 +151,6 @@ module Spree SecureRandom.base64(15).tr('+/=', '-_ ').strip.delete("\n") end - # Generate a token by looping and ensuring does not already exist. - def self.generate_token(column) - loop do - token = friendly_token - break token unless find(:first, conditions: { column => token }) - end - end - def limit_owned_enterprises return unless owned_enterprises.size > enterprise_limit diff --git a/app/models/spree/variant_decorator.rb b/app/models/spree/variant_decorator.rb index c23ab202cd..96853a28f2 100644 --- a/app/models/spree/variant_decorator.rb +++ b/app/models/spree/variant_decorator.rb @@ -16,8 +16,6 @@ Spree::Variant.class_eval do has_many :variant_overrides has_many :inventory_items - attr_accessible :unit_value, :unit_description, :images_attributes, - :display_as, :display_name, :import_date accepts_nested_attributes_for :images validates :unit_value, presence: true, if: ->(variant) { diff --git a/app/models/tag_rule.rb b/app/models/tag_rule.rb index fd1e744148..404c449e50 100644 --- a/app/models/tag_rule.rb +++ b/app/models/tag_rule.rb @@ -5,9 +5,6 @@ class TagRule < ActiveRecord::Base validates :enterprise, presence: true - attr_accessible :enterprise, :enterprise_id, :is_default, :priority - attr_accessible :preferred_customer_tags - scope :for, ->(enterprise) { where(enterprise_id: enterprise) } scope :prioritised, -> { order('priority ASC') } diff --git a/app/models/tag_rule/filter_order_cycles.rb b/app/models/tag_rule/filter_order_cycles.rb index de626ac70a..fd467a1658 100644 --- a/app/models/tag_rule/filter_order_cycles.rb +++ b/app/models/tag_rule/filter_order_cycles.rb @@ -2,8 +2,6 @@ class TagRule::FilterOrderCycles < TagRule preference :matched_order_cycles_visibility, :string, default: "visible" preference :exchange_tags, :string, default: "" - attr_accessible :preferred_matched_order_cycles_visibility, :preferred_exchange_tags - def tags_match?(order_cycle) exchange_tags = exchange_for(order_cycle).andand.tag_list || [] preferred_tags = preferred_exchange_tags.split(",") diff --git a/app/models/tag_rule/filter_payment_methods.rb b/app/models/tag_rule/filter_payment_methods.rb index 04a10889e0..11d5b5e737 100644 --- a/app/models/tag_rule/filter_payment_methods.rb +++ b/app/models/tag_rule/filter_payment_methods.rb @@ -2,8 +2,6 @@ class TagRule::FilterPaymentMethods < TagRule preference :matched_payment_methods_visibility, :string, default: "visible" preference :payment_method_tags, :string, default: "" - attr_accessible :preferred_matched_payment_methods_visibility, :preferred_payment_method_tags - def tags_match?(payment_method) payment_method_tags = payment_method.andand.tag_list || [] preferred_tags = preferred_payment_method_tags.split(",") diff --git a/app/models/tag_rule/filter_products.rb b/app/models/tag_rule/filter_products.rb index e1d3865036..40035a21d5 100644 --- a/app/models/tag_rule/filter_products.rb +++ b/app/models/tag_rule/filter_products.rb @@ -3,8 +3,6 @@ class TagRule preference :matched_variants_visibility, :string, default: "visible" preference :variant_tags, :string, default: "" - attr_accessible :preferred_matched_variants_visibility, :preferred_variant_tags - def self.tagged_children_for(product) product["variants"] end diff --git a/app/models/tag_rule/filter_shipping_methods.rb b/app/models/tag_rule/filter_shipping_methods.rb index 2091a14a63..a5de92da8b 100644 --- a/app/models/tag_rule/filter_shipping_methods.rb +++ b/app/models/tag_rule/filter_shipping_methods.rb @@ -2,8 +2,6 @@ class TagRule::FilterShippingMethods < TagRule preference :matched_shipping_methods_visibility, :string, default: "visible" preference :shipping_method_tags, :string, default: "" - attr_accessible :preferred_matched_shipping_methods_visibility, :preferred_shipping_method_tags - def reject_matched? preferred_matched_shipping_methods_visibility != "visible" end diff --git a/app/serializers/api/admin/order_serializer.rb b/app/serializers/api/admin/order_serializer.rb index 29aeee8fff..47fce01441 100644 --- a/app/serializers/api/admin/order_serializer.rb +++ b/app/serializers/api/admin/order_serializer.rb @@ -66,6 +66,6 @@ class Api::Admin::OrderSerializer < ActiveModel::Serializer private def spree_routes_helper - Spree::Core::Engine.routes_url_helpers + Spree::Core::Engine.routes.url_helpers end end diff --git a/app/serializers/api/enterprise_shopfront_list_serializer.rb b/app/serializers/api/enterprise_shopfront_list_serializer.rb index dd83ce4323..0dccfaa1c2 100644 --- a/app/serializers/api/enterprise_shopfront_list_serializer.rb +++ b/app/serializers/api/enterprise_shopfront_list_serializer.rb @@ -13,13 +13,13 @@ module Api def icon icons = { - hub: "/assets/map_005-hub.svg", - hub_profile: "/assets/map_006-hub-profile.svg", - producer_hub: "/assets/map_005-hub.svg", - producer_shop: "/assets/map_003-producer-shop.svg", - producer: "/assets/map_001-producer-only.svg", + hub: "map_005-hub.svg", + hub_profile: "map_006-hub-profile.svg", + producer_hub: "map_005-hub.svg", + producer_shop: "map_003-producer-shop.svg", + producer: "map_001-producer-only.svg", } - icons[enterprise.category] + ImagePathGenerator.call(icons[enterprise.category]) end def icon_font diff --git a/app/serializers/api/open_street_map_config_serializer.rb b/app/serializers/api/open_street_map_config_serializer.rb new file mode 100644 index 0000000000..8c5aec5dbb --- /dev/null +++ b/app/serializers/api/open_street_map_config_serializer.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module Api + class OpenStreetMapConfigSerializer < ActiveModel::Serializer + attributes :open_street_map_enabled, + :open_street_map_provider_name, + :open_street_map_provider_options + + def open_street_map_enabled + ContentConfig.open_street_map_enabled + end + + def open_street_map_provider_name + ContentConfig.open_street_map_provider_name + end + + def open_street_map_provider_options + ContentConfig.open_street_map_provider_options.to_json + end + end +end diff --git a/app/serializers/api/order_serializer.rb b/app/serializers/api/order_serializer.rb index f90f6ef572..cbac0c00b4 100644 --- a/app/serializers/api/order_serializer.rb +++ b/app/serializers/api/order_serializer.rb @@ -42,13 +42,13 @@ module Api end def path - Spree::Core::Engine.routes_url_helpers.order_path(object) + Spree::Core::Engine.routes.url_helpers.order_path(object) end def cancel_path return nil unless object.changes_allowed? - Spree::Core::Engine.routes_url_helpers.cancel_order_path(object) + Spree::Core::Engine.routes.url_helpers.cancel_order_path(object) end def changes_allowed diff --git a/app/serializers/api/product_serializer.rb b/app/serializers/api/product_serializer.rb index 592b67ecdb..733904c5b6 100644 --- a/app/serializers/api/product_serializer.rb +++ b/app/serializers/api/product_serializer.rb @@ -1,4 +1,4 @@ -require 'open_food_network/scope_variant_to_hub' +require "open_food_network/scope_variant_to_hub" class Api::ProductSerializer < ActiveModel::Serializer include ActionView::Helpers::SanitizeHelper @@ -23,7 +23,8 @@ class Api::ProductSerializer < ActiveModel::Serializer # return a sanitized html description def description_html - d = sanitize(object.description, tags: "p, b, strong, em, i, a, u", attributes: "href, target") + d = sanitize(object.description, tags: ["p", "b", "strong", "em", "i", "a", "u"], + attributes: ["href", "target"]) d.to_s.html_safe end diff --git a/app/serializers/api/variant_serializer.rb b/app/serializers/api/variant_serializer.rb index e824db8406..38cc649910 100644 --- a/app/serializers/api/variant_serializer.rb +++ b/app/serializers/api/variant_serializer.rb @@ -3,7 +3,7 @@ class Api::VariantSerializer < ActiveModel::Serializer :options_text, :unit_value, :unit_description, :unit_to_display, :display_as, :display_name, :name_to_display, :price, :on_demand, :on_hand, :fees, :price_with_fees, - :tag_list + :tag_list, :thumb_url delegate :price, to: :object @@ -30,4 +30,12 @@ class Api::VariantSerializer < ActiveModel::Serializer object.tag_list end + + def thumb_url + if object.product.images.present? + object.product.images.first.attachment.url(:mini) + else + "/assets/noimage/mini.png" + end + end end diff --git a/app/services/bulk_invoice_service.rb b/app/services/bulk_invoice_service.rb index 18921bd413..ab69df03ca 100644 --- a/app/services/bulk_invoice_service.rb +++ b/app/services/bulk_invoice_service.rb @@ -7,9 +7,8 @@ class BulkInvoiceService def start_pdf_job(order_ids) pdf = CombinePDF.new - orders = Spree::Order.where(id: order_ids) - orders.each do |order| + orders_from(order_ids).each do |order| invoice = renderer.render_to_string(order) pdf << CombinePDF.parse(invoice) @@ -29,6 +28,10 @@ class BulkInvoiceService private + def orders_from(order_ids) + Spree::Order.where(id: order_ids).order("completed_at DESC") + end + def new_invoice_id Time.zone.now.to_i.to_s end diff --git a/app/services/cache_service.rb b/app/services/cache_service.rb index 1963b2f1dc..dc3a7fac0e 100644 --- a/app/services/cache_service.rb +++ b/app/services/cache_service.rb @@ -37,25 +37,31 @@ class CacheService # Rails' caching in views is called "Fragment Caching" and uses some slightly different logic. # Note: keys supplied here are actually prepended with "views/" under the hood. - def self.ams_all_taxons_key - "inject-all-taxons-#{CacheService.latest_timestamp_by_class(Spree::Taxon)}" + def self.ams_all_taxons + [ + "inject-all-taxons-#{CacheService.latest_timestamp_by_class(Spree::Taxon)}", + { skip_digest: true } + ] end - def self.ams_all_properties_key - "inject-all-properties-#{CacheService.latest_timestamp_by_class(Spree::Property)}" + def self.ams_all_properties + [ + "inject-all-properties-#{CacheService.latest_timestamp_by_class(Spree::Property)}", + { skip_digest: true } + ] end def self.ams_shops [ "shops/index/inject_enterprises", - { expires_in: SHOPS_EXPIRY } + { expires_in: SHOPS_EXPIRY, skip_digest: true } ] end def self.ams_shop(enterprise) [ "enterprises/shop/inject_enterprise_shopfront-#{enterprise.id}", - { expires_in: SHOPS_EXPIRY } + { expires_in: SHOPS_EXPIRY, skip_digest: true } ] end end diff --git a/app/services/checkout/form_data_adapter.rb b/app/services/checkout/form_data_adapter.rb index 8fc10fc4ca..a374444637 100644 --- a/app/services/checkout/form_data_adapter.rb +++ b/app/services/checkout/form_data_adapter.rb @@ -3,7 +3,7 @@ # Adapts checkout form data (params) so that the order can be directly saved to the database module Checkout class FormDataAdapter - attr_reader :shipping_method_id + attr_reader :params, :shipping_method_id def initialize(params, order, current_user) @params = params.dup @@ -19,10 +19,6 @@ module Checkout @shipping_method_id = @params[:order].delete(:shipping_method_id) end - def order_params - @params[:order] - end - private # For payment step, filter order parameters to produce the expected diff --git a/app/services/checkout/paypal_redirect.rb b/app/services/checkout/paypal_redirect.rb index ca7a34172f..9c4b192ac1 100644 --- a/app/services/checkout/paypal_redirect.rb +++ b/app/services/checkout/paypal_redirect.rb @@ -21,7 +21,7 @@ module Checkout private def spree_routes_helper - Spree::Core::Engine.routes_url_helpers + Spree::Core::Engine.routes.url_helpers end end end diff --git a/app/services/default_shipping_category.rb b/app/services/default_shipping_category.rb index 10959de659..8e0a7b90ae 100644 --- a/app/services/default_shipping_category.rb +++ b/app/services/default_shipping_category.rb @@ -8,6 +8,6 @@ class DefaultShippingCategory end def self.find_or_create - Spree::ShippingCategory.find_or_create_by_name(NAME) + Spree::ShippingCategory.find_or_create_by(name: NAME) end end diff --git a/app/services/default_stock_location.rb b/app/services/default_stock_location.rb index dc4499198b..7ec0476321 100644 --- a/app/services/default_stock_location.rb +++ b/app/services/default_stock_location.rb @@ -4,7 +4,7 @@ class DefaultStockLocation NAME = 'default'.freeze def self.create! - country = Spree::Country.find_by_iso(ENV['DEFAULT_COUNTRY_CODE']) + country = Spree::Country.find_by(iso: ENV['DEFAULT_COUNTRY_CODE']) state = country.states.first Spree::StockLocation.create!(name: NAME, country_id: country.id, state_id: state.id, backorderable_default: false) end @@ -14,6 +14,6 @@ class DefaultStockLocation end def self.find_or_create - Spree::StockLocation.find_or_create_by_name(NAME) + Spree::StockLocation.find_or_create_by(name: NAME) end end diff --git a/app/services/embedded_page_service.rb b/app/services/embedded_page_service.rb index 9164ac4d94..f2d6021e20 100644 --- a/app/services/embedded_page_service.rb +++ b/app/services/embedded_page_service.rb @@ -49,7 +49,8 @@ class EmbeddedPageService end def set_response_headers - @response.headers.delete 'X-Frame-Options' + @response.headers.except! 'X-Frame-Options' + @response.default_headers.except! 'X-Frame-Options' @response.headers['Content-Security-Policy'] = "frame-ancestors 'self' #{@embedding_domain}" end diff --git a/app/services/image_path_generator.rb b/app/services/image_path_generator.rb new file mode 100644 index 0000000000..48c9ee93d1 --- /dev/null +++ b/app/services/image_path_generator.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +class ImagePathGenerator + # Since Rails 4 has adjusted the way assets paths are handled, we have to access certain + # asset-based helpers like this when outside of a view or controller context. + # See: https://stackoverflow.com/a/16609815 + def self.call(path) + ActionController::Base.helpers.image_path(path) + end +end diff --git a/app/services/line_item_syncer.rb b/app/services/line_item_syncer.rb index 7771ebf150..e190db0be5 100644 --- a/app/services/line_item_syncer.rb +++ b/app/services/line_item_syncer.rb @@ -21,7 +21,7 @@ class LineItemSyncer def update_item_quantities(order) changed_subscription_line_items.each do |sli| - line_item = order.line_items.find_by_variant_id(sli.variant_id) + line_item = order.line_items.find_by(variant_id: sli.variant_id) if line_item.blank? order_update_issues.add(order, sli.variant.product_and_full_name) diff --git a/app/services/order_adjustments_fetcher.rb b/app/services/order_adjustments_fetcher.rb index dfde72f142..40d78cf6bc 100644 --- a/app/services/order_adjustments_fetcher.rb +++ b/app/services/order_adjustments_fetcher.rb @@ -61,7 +61,7 @@ class OrderAdjustmentsFetcher match_by_scope(adjustment, adjustment_scope) end else - adjustments.scoped.public_send scope + adjustments.where(nil).public_send scope end end diff --git a/app/services/order_cart_reset.rb b/app/services/order_cart_reset.rb index 0c7ba55ca8..4faec18a30 100644 --- a/app/services/order_cart_reset.rb +++ b/app/services/order_cart_reset.rb @@ -4,7 +4,7 @@ class OrderCartReset def initialize(order, distributor_id) @order = order - @distributor ||= Enterprise.is_distributor.find_by_permalink(distributor_id) || + @distributor ||= Enterprise.is_distributor.find_by(permalink: distributor_id) || Enterprise.is_distributor.find(distributor_id) end diff --git a/app/services/order_cycle_form.rb b/app/services/order_cycle_form.rb index 7026d5f5b6..87292a8a0c 100644 --- a/app/services/order_cycle_form.rb +++ b/app/services/order_cycle_form.rb @@ -3,19 +3,22 @@ require 'open_food_network/order_cycle_form_applicator' require 'order_management/subscriptions/proxy_order_syncer' class OrderCycleForm - def initialize(order_cycle, params, user) + def initialize(order_cycle, order_cycle_params, user) @order_cycle = order_cycle - @params = params + @order_cycle_params = order_cycle_params @user = user @permissions = OpenFoodNetwork::Permissions.new(user) + @schedule_ids = order_cycle_params.delete(:schedule_ids) end def save - build_schedule_ids - order_cycle.assign_attributes(params[:order_cycle]) + schedule_ids = build_schedule_ids + order_cycle.assign_attributes(order_cycle_params) return false unless order_cycle.valid? order_cycle.transaction do + order_cycle.save! + order_cycle.schedule_ids = schedule_ids order_cycle.save! apply_exchange_changes sync_subscriptions @@ -27,7 +30,7 @@ class OrderCycleForm private - attr_accessor :order_cycle, :params, :user, :permissions + attr_accessor :order_cycle, :order_cycle_params, :user, :permissions def apply_exchange_changes return if exchanges_unchanged? @@ -37,12 +40,12 @@ class OrderCycleForm def exchanges_unchanged? [:incoming_exchanges, :outgoing_exchanges].all? do |direction| - params[:order_cycle][direction].nil? + order_cycle_params[direction].nil? end end def schedule_ids? - params[:order_cycle][:schedule_ids].present? + @schedule_ids.present? end def build_schedule_ids @@ -51,7 +54,7 @@ class OrderCycleForm result = existing_schedule_ids result |= (requested_schedule_ids & permitted_schedule_ids) # Add permitted and requested result -= ((result & permitted_schedule_ids) - requested_schedule_ids) # Remove permitted but not requested - params[:order_cycle][:schedule_ids] = result + result end def sync_subscriptions @@ -70,7 +73,7 @@ class OrderCycleForm end def requested_schedule_ids - params[:order_cycle][:schedule_ids].map(&:to_i) + @schedule_ids.map(&:to_i) end def permitted_schedule_ids diff --git a/app/services/order_factory.rb b/app/services/order_factory.rb index 1a2aeba1b3..a7845618b0 100644 --- a/app/services/order_factory.rb +++ b/app/services/order_factory.rb @@ -46,7 +46,7 @@ class OrderFactory def build_line_items attrs[:line_items].each do |li| - next unless variant = Spree::Variant.find_by_id(li[:variant_id]) + next unless variant = Spree::Variant.find_by(id: li[:variant_id]) scoper.scope(variant) li[:quantity] = stock_limited_quantity(variant.on_demand, variant.on_hand, li[:quantity]) diff --git a/app/services/order_tax_adjustments_fetcher.rb b/app/services/order_tax_adjustments_fetcher.rb new file mode 100644 index 0000000000..085119172c --- /dev/null +++ b/app/services/order_tax_adjustments_fetcher.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +# This class will be used to get Tax Adjustments related to an order, +# and proceed basic calcultation over them. + +class OrderTaxAdjustmentsFetcher + def initialize(order) + @order = order + end + + def totals + all.each_with_object({}) do |adjustment, hash| + tax_rates_hash = tax_rates_hash(adjustment) + hash.update(tax_rates_hash) { |_tax_rate, amount1, amount2| amount1 + amount2 } + end + end + + private + + attr_reader :order + + def all + Spree::Adjustment + .with_tax + .where(order_adjustments.or(line_item_adjustments)) + .order('created_at ASC') + end + + def order_adjustments + table[:adjustable_id].eq(order.id) + .and(table[:adjustable_type].eq('Spree::Order')) + end + + def line_item_adjustments + table[:adjustable_id].eq(order.line_item_ids.join(',')) + .and(table[:adjustable_type].eq('Spree::LineItem')) + end + + def table + @table ||= Spree::Adjustment.arel_table + end + + def tax_rates_hash(adjustment) + tax_rates = TaxRateFinder.tax_rates_of(adjustment) + + Hash[tax_rates.collect do |tax_rate| + tax_amount = if tax_rates.one? + adjustment.included_tax + else + tax_rate.compute_tax(adjustment.amount) + end + [tax_rate, tax_amount] + end] + end +end diff --git a/app/services/permissions/order.rb b/app/services/permissions/order.rb index ea5c4c2bfa..0059088874 100644 --- a/app/services/permissions/order.rb +++ b/app/services/permissions/order.rb @@ -106,11 +106,9 @@ module Permissions # Any from visible orders, where the product is produced by one of my managed producers def produced_line_items Spree::LineItem.where(order_id: visible_orders.select("DISTINCT spree_orders.id")). - joins(:product). - where(spree_products: - { - supplier_id: @permissions.managed_enterprises.is_primary_producer.select("enterprises.id") - }) + supplied_by_any( + @permissions.managed_enterprises.is_primary_producer.select("enterprises.id") + ) end end end diff --git a/app/services/permitted_attributes/address.rb b/app/services/permitted_attributes/address.rb new file mode 100644 index 0000000000..4c7a538caf --- /dev/null +++ b/app/services/permitted_attributes/address.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +module PermittedAttributes + class Address + def self.attributes + [ + :firstname, :lastname, :address1, :address2, + :city, :country_id, :state_id, :zipcode, + :phone, :state_name, :alternative_phone, :company + ] + end + end +end diff --git a/app/services/permitted_attributes/checkout.rb b/app/services/permitted_attributes/checkout.rb new file mode 100644 index 0000000000..5eb9325f87 --- /dev/null +++ b/app/services/permitted_attributes/checkout.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +module PermittedAttributes + class Checkout + def initialize(params) + @params = params + end + + def call + @params.permit( + order: [ + :email, :special_instructions, + :existing_card_id, :shipping_method_id, + payments_attributes: [ + :payment_method_id, + source_attributes: PermittedAttributes::PaymentSource.attributes + ], + ship_address_attributes: PermittedAttributes::Address.attributes, + bill_address_attributes: PermittedAttributes::Address.attributes + ], + payment_source: PermittedAttributes::PaymentSource.attributes + ) + end + end +end diff --git a/app/services/permitted_attributes/enterprise.rb b/app/services/permitted_attributes/enterprise.rb new file mode 100644 index 0000000000..f02863b2a5 --- /dev/null +++ b/app/services/permitted_attributes/enterprise.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +module PermittedAttributes + class Enterprise + def initialize(params) + @params = params + end + + def call + return @params[:enterprise] if @params[:enterprise].empty? + + @params.require(:enterprise).permit( + basic_permitted_attributes + [ + group_ids: [], user_ids: [], + shipping_method_ids: [], payment_method_ids: [], + address_attributes: PermittedAttributes::Address.attributes, + producer_properties_attributes: [:id, :property_name, :value, :_destroy] + ] + ) + end + + private + + def basic_permitted_attributes + [ + :id, :name, :visible, :permalink, :owner_id, :contact_name, :email_address, :phone, + :is_primary_producer, :sells, :website, :facebook, :instagram, :linkedin, :twitter, + :description, :long_description, :logo, :promo_image, + :allow_guest_orders, :allow_order_changes, :require_login, :enable_subscriptions, + :abn, :acn, :charges_sales_tax, :display_invoice_logo, :invoice_text, + :preferred_product_selection_from_inventory_only, :preferred_shopfront_message, + :preferred_shopfront_closed_message, :preferred_shopfront_taxon_order, + :preferred_shopfront_order_cycle_order + ] + end + end +end diff --git a/app/services/permitted_attributes/order_cycle.rb b/app/services/permitted_attributes/order_cycle.rb new file mode 100644 index 0000000000..6da6175a51 --- /dev/null +++ b/app/services/permitted_attributes/order_cycle.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +module PermittedAttributes + class OrderCycle + def initialize(params) + @params = params + end + + def call + return @params[:order_cycle] if @params[:order_cycle].empty? + + @params.require(:order_cycle).permit( + :name, :orders_open_at, :orders_close_at, :coordinator_id, + incoming_exchanges: permitted_exchange_attributes, + outgoing_exchanges: permitted_exchange_attributes, + schedule_ids: [], coordinator_fee_ids: [] + ) + end + + private + + def permitted_exchange_attributes + [ + :id, :sender_id, :receiver_id, :enterprise_id, :incoming, :active, + :select_all_variants, :receival_instructions, + :pickup_time, :pickup_instructions, + :tag_list, + tags: [:text], + enterprise_fee_ids: [], + variants: permitted_variant_ids + ] + end + + # In rails 5 we will be able to permit random hash keys simply with :variants => {} + # See https://github.com/rails/rails/commit/e86524c0c5a26ceec92895c830d1355ae47a7034 + # + # Until then, we need to create an array of variant IDs in order to permit them + def permitted_variant_ids + variant_ids(@params[:order_cycle][:incoming_exchanges]) + + variant_ids(@params[:order_cycle][:outgoing_exchanges]) + end + + def variant_ids(exchange_params) + return [] unless exchange_params + + exchange_params.map { |exchange| exchange[:variants].map { |key, _value| key } }.flatten + end + end +end diff --git a/app/services/permitted_attributes/payment_source.rb b/app/services/permitted_attributes/payment_source.rb new file mode 100644 index 0000000000..5ecfd2e3c7 --- /dev/null +++ b/app/services/permitted_attributes/payment_source.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module PermittedAttributes + class PaymentSource + def self.attributes + [ + :gateway_payment_profile_id, :cc_type, :last_digits, + :month, :year, :first_name, :last_name, + :number, :verification_value, + :save_requested_by_customer + ] + end + end +end diff --git a/app/services/permitted_attributes/product.rb b/app/services/permitted_attributes/product.rb new file mode 100644 index 0000000000..13ff8d56ef --- /dev/null +++ b/app/services/permitted_attributes/product.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +module PermittedAttributes + class Product + def self.attributes + [ + :id, :name, :description, :supplier_id, :price, :cost_price, :permalink, + :variant_unit, :variant_unit_scale, :unit_value, :unit_description, :variant_unit_name, + :display_as, :sku, :available_on, :group_buy, :group_buy_unit_size, + :taxon_ids, :primary_taxon_id, :tax_category_id, :shipping_category_id, + :meta_keywords, :meta_description, :notes, :inherits_properties, + product_properties_attributes: [:id, :property_name, :value], + variants_attributes: [PermittedAttributes::Variant.attributes], + images_attributes: [:attachment] + ] + end + end +end diff --git a/app/services/permitted_attributes/subscription.rb b/app/services/permitted_attributes/subscription.rb new file mode 100644 index 0000000000..2ab3956fca --- /dev/null +++ b/app/services/permitted_attributes/subscription.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +module PermittedAttributes + class Subscription + def initialize(params) + @params = params + end + + def call + return @params[:subscription] if @params[:subscription].empty? + + @params.require(:subscription).permit(basic_permitted_attributes + other_permitted_attributes) + end + + private + + def basic_permitted_attributes + [ + :id, :shop_id, :schedule_id, :customer_id, + :payment_method_id, :shipping_method_id, + :begins_at, :ends_at, + :canceled_at, :paused_at, + :shipping_fee_estimate, :payment_fee_estimate, + ] + end + + def other_permitted_attributes + [ + subscription_line_items_attributes: [ + :id, :quantity, :variant_id, :price_estimate, :_destroy + ], + bill_address_attributes: PermittedAttributes::Address.attributes, + ship_address_attributes: PermittedAttributes::Address.attributes + ] + end + end +end diff --git a/app/services/permitted_attributes/user.rb b/app/services/permitted_attributes/user.rb new file mode 100644 index 0000000000..4efbf0e3b5 --- /dev/null +++ b/app/services/permitted_attributes/user.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +module PermittedAttributes + class User + def initialize(params, resource_name = :user) + @params = params + @resource_name = resource_name + end + + def call(extra_permitted_attributes = []) + @params.require(@resource_name). + permit(permitted_attributes + extra_permitted_attributes) + end + + private + + def permitted_attributes + [:email, :password, :password_confirmation] + end + end +end diff --git a/app/services/permitted_attributes/variant.rb b/app/services/permitted_attributes/variant.rb new file mode 100644 index 0000000000..a04928af0d --- /dev/null +++ b/app/services/permitted_attributes/variant.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +module PermittedAttributes + class Variant + def self.attributes + [ + :id, :sku, :on_hand, :on_demand, + :cost_price, :price, :unit_value, :unit_description, + :display_name, :display_as, + :weight, :height, :width, :depth + ] + end + end +end diff --git a/app/services/search_orders.rb b/app/services/search_orders.rb index 4ff0f717da..30afb964a7 100644 --- a/app/services/search_orders.rb +++ b/app/services/search_orders.rb @@ -24,13 +24,25 @@ class SearchOrders attr_reader :params, :current_user def fetch_orders - @search = ::Permissions::Order.new(current_user).editable_orders.ransack(params[:q]) + @search = search_query.ransack(params[:q]) return paginated_results if using_pagination? @search.result(distinct: true) end + def search_query + base_query = ::Permissions::Order.new(current_user).editable_orders + return base_query unless params[:shipping_method_id] + + base_query + .joins(shipments: :shipping_rates) + .where(spree_shipping_rates: { + selected: true, + shipping_method_id: params[:shipping_method_id] + }) + end + def paginated_results @search.result(distinct: true) .page(params[:page]) diff --git a/app/views/admin/customers/index.html.haml b/app/views/admin/customers/index.html.haml index 477e609cde..abf39f47d5 100644 --- a/app/views/admin/customers/index.html.haml +++ b/app/views/admin/customers/index.html.haml @@ -35,7 +35,7 @@ .row{ 'ng-if' => 'shop_id && RequestMonitor.loading' } .sixteen.columns.alpha#loading - %img.spinner{ src: "/assets/spinning-circles.svg" } + %img.spinner{ src: image_path("spinning-circles.svg") } %h1 =t :loading_customers diff --git a/app/views/admin/enterprises/_enterprise_user_index.html.haml b/app/views/admin/enterprises/_enterprise_user_index.html.haml index 0afa9317e9..eedfba8d34 100644 --- a/app/views/admin/enterprises/_enterprise_user_index.html.haml +++ b/app/views/admin/enterprises/_enterprise_user_index.html.haml @@ -9,7 +9,7 @@ %columns-dropdown{ action: "#{controller_name}_#{action_name}" } .row{ 'ng-if' => '!loaded' } .sixteen.columns.alpha#loading - %img.spinner{ src: "/assets/spinning-circles.svg" } + %img.spinner{ src: image_path("spinning-circles.svg") } %h1= t('.loading_enterprises') .row{ :class => "sixteen columns alpha", 'ng-show' => 'loaded && filteredEnterprises.length == 0'} %h1#no_results= t('.no_enterprises_found') diff --git a/app/views/admin/enterprises/form/_primary_details.html.haml b/app/views/admin/enterprises/form/_primary_details.html.haml index 30c582f8e2..a6a09106b3 100644 --- a/app/views/admin/enterprises/form/_primary_details.html.haml +++ b/app/views/admin/enterprises/form/_primary_details.html.haml @@ -59,7 +59,7 @@ .six.columns = f.text_field :permalink, { 'ng-model' => "Enterprise.permalink", placeholder: "eg. your-shop-name", 'ng-model-options' => "{ updateOn: 'default blur', debounce: {'default': 300, 'blur': 0} }" } .two.columns.omega - %img.spinner{ src: "/assets/spinning-circles.svg", width: "30px", ng: { show: "checking" } } + %img.spinner{ src: image_path("spinning-circles.svg"), width: "30px", ng: { show: "checking" } } %span{ ng: { class: 'availability.toLowerCase()', hide: "checking" } } {{ availability }} %i{ ng: { class: "{'icon-ok-sign': availability == 'Available', 'icon-remove-sign': availability == 'Unavailable'}" } } diff --git a/app/views/admin/json/_injection_ams.html.haml b/app/views/admin/json/_injection_ams.html.haml index 50a22fa4ce..c95ecf5b03 100644 --- a/app/views/admin/json/_injection_ams.html.haml +++ b/app/views/admin/json/_injection_ams.html.haml @@ -1,2 +1,2 @@ :javascript - angular.module("#{ngModule}").value("#{name.to_s}", #{json}) \ No newline at end of file + angular.module("#{ngModule}").value("#{name.to_s.html_safe}", #{json.html_safe}) \ No newline at end of file diff --git a/app/views/admin/matomo_settings/edit.html.haml b/app/views/admin/matomo_settings/edit.html.haml index 51f553bcff..0c553ae002 100644 --- a/app/views/admin/matomo_settings/edit.html.haml +++ b/app/views/admin/matomo_settings/edit.html.haml @@ -18,6 +18,10 @@ = label_tag(:matomo_site_id, t('.matomo_site_id')) + tag(:br) = preference_field_tag("preferences[#{:matomo_site_id}]", Spree::Config[:matomo_site_id], type: Spree::Config.preference_type(:matomo_site_id)) + .field + = label_tag(:matomo_tag_manager_url, t('.matomo_tag_manager_url')) + tag(:br) + = preference_field_tag("preferences[#{:matomo_tag_manager_url}]", Spree::Config[:matomo_tag_manager_url], type: Spree::Config.preference_type(:matomo_tag_manager_url)) + .warning.note= t('.config_instructions_tag_manager_html') .form-buttons{"data-hook" => "buttons"} = button t(:update), 'icon-refresh' diff --git a/app/views/admin/order_cycles/_loading_flash.html.haml b/app/views/admin/order_cycles/_loading_flash.html.haml index ef810e03d1..05aff6b748 100644 --- a/app/views/admin/order_cycles/_loading_flash.html.haml +++ b/app/views/admin/order_cycles/_loading_flash.html.haml @@ -1,5 +1,5 @@ %div.sixteen.columns.alpha.omega#loading{ ng: { cloak: true, if: 'RequestMonitor.loading' } } - %img.spinner{ src: "/assets/spinning-circles.svg" } + %img.spinner{ src: image_path("spinning-circles.svg") } %h1{ ng: { hide: 'orderCycles.length > 0' } } =t('.loading_order_cycles') %h1{ ng: { show: 'orderCycles.length > 0' } } diff --git a/app/views/admin/subscriptions/_loading_flash.html.haml b/app/views/admin/subscriptions/_loading_flash.html.haml index 59f0cb4e1f..ab37f06a71 100644 --- a/app/views/admin/subscriptions/_loading_flash.html.haml +++ b/app/views/admin/subscriptions/_loading_flash.html.haml @@ -1,3 +1,3 @@ %div.sixteen.columns.alpha.omega#loading{ ng: { cloak: true, if: 'shop_id && RequestMonitor.loading' } } - %img.spinner{ src: "/assets/spinning-circles.svg" } + %img.spinner{ src: image_path("spinning-circles.svg") } %h1= t('.loading') diff --git a/app/views/admin/variant_overrides/_loading_flash.html.haml b/app/views/admin/variant_overrides/_loading_flash.html.haml index 2baa04a473..d9b2bf46bc 100644 --- a/app/views/admin/variant_overrides/_loading_flash.html.haml +++ b/app/views/admin/variant_overrides/_loading_flash.html.haml @@ -1,3 +1,3 @@ %div.sixteen.columns.alpha.omega#loading{ ng: { cloak: true, if: 'hub_id && products.length == 0 && RequestMonitor.loading' } } - %img.spinner{ src: "/assets/spinning-circles.svg" } + %img.spinner{ src: image_path("spinning-circles.svg") } %h1= t('.loading_inventory') diff --git a/app/views/groups/show.html.haml b/app/views/groups/show.html.haml index e8318faef9..4701791daa 100644 --- a/app/views/groups/show.html.haml +++ b/app/views/groups/show.html.haml @@ -6,7 +6,9 @@ = @group.logo.url - content_for :injection_data do + = inject_available_countries = inject_group_enterprises + = inject_open_street_map_config #group-page.row.pad-top.footer-pad{"ng-controller" => "GroupPageCtrl"} .small-12.columns.pad-top @@ -20,7 +22,7 @@ - if @group.logo.present? %img.group-logo{"src" => @group.logo} - else - %img.group-logo{"src" => '/assets/noimage/group.png'} + %img.group-logo{"src" => image_path('noimage/group.png') } %h2.group-name= @group.name %p= @group.description @@ -32,13 +34,8 @@ %tab{heading: t(:label_map), active: "tabs.map.active", select: "select(\'map\')"} - .map-container - %map{"ng-if" => "(isActive(\'/map\') && (mapShowed = true)) || mapShowed"} - %ui-gmap-google-map{options: "map.additional_options", center: "map.center", zoom: "map.zoom", styles: "map.styles", draggable: "true"} - %map-osm-tiles - %map-search - %ui-gmap-markers{models: "mapMarkers", fit: "true", - coords: "'self'", icon: "'icon'", click: "'reveal'"} + %div{"ng-if" => "(isActive(\'/map\') && (mapShowed = true)) || mapShowed"} + = render partial: "shared/map" %tab{heading: t(:groups_about), active: "tabs.about.active", @@ -122,4 +119,4 @@ %span = t 'title' -= render "shared/footer" \ No newline at end of file += render "shared/footer" diff --git a/app/views/home/_tagline.html.haml b/app/views/home/_tagline.html.haml index 7685455b3f..5afa5fe21d 100644 --- a/app/views/home/_tagline.html.haml +++ b/app/views/home/_tagline.html.haml @@ -3,7 +3,7 @@ .small-12.text-center.columns %h1 / TODO: Rohan - logo asset & width is content manageable: - %img{src: "/assets/logo-white-notext.png", title: Spree::Config.site_name} + %img{src: image_path("logo-white-notext.png"), title: Spree::Config.site_name} %br/ %a.button.transparent{href: "/shops"} = t :home_shop diff --git a/app/views/json/_injection_ams.html.haml b/app/views/json/_injection_ams.html.haml index 40635189c8..088e01eb63 100644 --- a/app/views/json/_injection_ams.html.haml +++ b/app/views/json/_injection_ams.html.haml @@ -1,2 +1,2 @@ :javascript - angular.module('Darkswarm').value("#{name.to_s}", #{json}) + angular.module('Darkswarm').value("#{name.to_s.html_safe}", #{json.html_safe}) diff --git a/app/views/layouts/_matomo_tag.html.haml b/app/views/layouts/_matomo_tag.html.haml index aba1b19528..85a4cf47dc 100644 --- a/app/views/layouts/_matomo_tag.html.haml +++ b/app/views/layouts/_matomo_tag.html.haml @@ -1,6 +1,15 @@ + +- if Spree::Config.matomo_tag_manager_url.present? + :javascript + var _mtm = _mtm || []; + _mtm.push({'mtm.startTime': (new Date().getTime()), 'event': 'mtm.Start'}); + var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; + var u="#{Spree::Config.matomo_tag_manager_url}"; + g.type='text/javascript'; g.async=true; g.defer=true; g.src=u; s.parentNode.insertBefore(g,s); + - if Spree::Config.matomo_url.present? :javascript - var _paq = _paq || []; + var _paq = window._paq || []; _paq.push(["setDocumentTitle", document.domain + "/" + document.title]); _paq.push(["setCookieDomain", "*.#{Spree::Config.site_url}"]); _paq.push(["setDomains", ["*.#{Spree::Config.site_url}"]]); @@ -8,8 +17,8 @@ _paq.push(['enableLinkTracking']); (function() { var u="#{Spree::Config.matomo_url}"; - _paq.push(['setTrackerUrl', u+'piwik.php']); + _paq.push(['setTrackerUrl', u+'matomo.php']); _paq.push(['setSiteId', '#{Spree::Config.matomo_site_id}']); var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; - g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'piwik.js'; s.parentNode.insertBefore(g,s); + g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s); })(); diff --git a/app/views/layouts/darkswarm.html.haml b/app/views/layouts/darkswarm.html.haml index 3986d9ace8..f45b157a51 100644 --- a/app/views/layouts/darkswarm.html.haml +++ b/app/views/layouts/darkswarm.html.haml @@ -18,7 +18,7 @@ = stylesheet_link_tag "darkswarm/all" = csrf_meta_tags - %body{class: body_classes, ng: {app: "Darkswarm"}} + %body{class: body_classes, "body-scroll" => true , ng: {app: "Darkswarm"}} / [if lte IE 8] = render partial: "shared/ie_warning" = javascript_include_tag "iehack" @@ -39,7 +39,8 @@ = render "layouts/bugsnag_js" %script{:src => "https://js.stripe.com/v3/", :type => "text/javascript"} - %script{src: "//maps.googleapis.com/maps/api/js?libraries=places,geometry#{ ENV['GOOGLE_MAPS_API_KEY'] ? '&key=' + ENV['GOOGLE_MAPS_API_KEY'] : ''} "} + - if !ContentConfig.open_street_map_enabled + %script{src: "//maps.googleapis.com/maps/api/js?libraries=places,geometry#{ ENV['GOOGLE_MAPS_API_KEY'] ? '&key=' + ENV['GOOGLE_MAPS_API_KEY'] : ''} "} = javascript_include_tag "darkswarm/all" = javascript_include_tag "web/all" = render "layouts/i18n_script" @@ -48,9 +49,9 @@ = inject_current_hub = inject_current_user = inject_rails_flash - - cache CacheService::FragmentCaching.ams_all_taxons_key do + - cache(*CacheService::FragmentCaching.ams_all_taxons) do = inject_taxons - - cache CacheService::FragmentCaching.ams_all_properties_key do + - cache(*CacheService::FragmentCaching.ams_all_properties) do = inject_properties = inject_current_order = inject_currency_config diff --git a/app/views/layouts/registration.html.haml b/app/views/layouts/registration.html.haml index 2902f6683e..ebbcd9fd17 100644 --- a/app/views/layouts/registration.html.haml +++ b/app/views/layouts/registration.html.haml @@ -13,7 +13,7 @@ = stylesheet_link_tag "darkswarm/all" = csrf_meta_tags - %body.off-canvas{"ng-app" => "Darkswarm", style: 'background-image: url("/assets/tile-wide.png")' } + %body.off-canvas{"ng-app" => "Darkswarm", style: "background-image: url(#{image_path('tile-wide.png')})" } / [if lte IE 8] = render partial: "shared/ie_warning" = javascript_include_tag "iehack" diff --git a/app/views/map/index.html.haml b/app/views/map/index.html.haml index 294fa45f8e..741fa67064 100644 --- a/app/views/map/index.html.haml +++ b/app/views/map/index.html.haml @@ -2,15 +2,8 @@ = t :label_map - content_for :injection_data do + = inject_available_countries = inject_enterprise_shopfront_list + = inject_open_street_map_config -.map-container{"fill-vertical" => true} - %map{"ng-controller" => "MapCtrl"} - %ui-gmap-google-map{options: "map.additional_options", center: "map.center", zoom: "map.zoom", styles: "map.styles", draggable: "true"} - %map-osm-tiles - %map-search - %ui-gmap-markers{models: "OfnMap.enterprises", fit: "true", - coords: "'self'", icon: "'icon'", click: "'reveal'"} - -.map-footer - %a{:href => "http://www.openstreetmap.org/copyright"} © OpenStreetMap contributors += render partial: "shared/map" diff --git a/app/views/producers/_fat.html.haml b/app/views/producers/_fat.html.haml index 1526f4f198..9b4e3b68b6 100644 --- a/app/views/producers/_fat.html.haml +++ b/app/views/producers/_fat.html.haml @@ -1,7 +1,7 @@ .row.active_table_row{"ng-if" => "open()", "ng-click" => "toggle($event)", "ng-class" => "{'open' : open()}"} .columns.small-12.fat.text-center{"ng-show" => "open() && shopfront_loading"} %p - %img.spinner.text-center{ src: "/assets/spinning-circles.svg" } + %img.spinner.text-center{ src: image_path("spinning-circles.svg") } .columns.small-12.medium-7.large-7.fat{"ng-show" => "open() && !shopfront_loading"} / Will add in long description available once clean up HTML formatting producer.long_description diff --git a/app/views/registration/steps/_limit_reached.html.haml b/app/views/registration/steps/_limit_reached.html.haml index c8fa25a43c..ba49d0dac3 100644 --- a/app/views/registration/steps/_limit_reached.html.haml +++ b/app/views/registration/steps/_limit_reached.html.haml @@ -6,7 +6,7 @@ %h4= t(".message") .row .small-12.medium-3.large-2.columns.text-right.hide-for-small-only - %img{:src => "/assets/potatoes.png"} + %img{:src => image_path("potatoes.png") } .small-12.medium-9.large-10.columns %p = t(".text") diff --git a/app/views/registration/steps/_logo.html.haml b/app/views/registration/steps/_logo.html.haml index 677653b4bb..4082defaec 100644 --- a/app/views/registration/steps/_logo.html.haml +++ b/app/views/registration/steps/_logo.html.haml @@ -41,6 +41,6 @@ .message{ ng: { hide: "imageSrc() || imageUploader.isUploading" } } = t(".logo_placeholder") .loading{ ng: { hide: "!imageUploader.isUploading" } } - %img.spinner{ src: "/assets/spinning-circles.svg" } + %img.spinner{ src: image_path("spinning-circles.svg") } %br/ = t("registration.steps.images.uploading") diff --git a/app/views/registration/steps/_promo.html.haml b/app/views/registration/steps/_promo.html.haml index 91a8bc9a78..efe29f6994 100644 --- a/app/views/registration/steps/_promo.html.haml +++ b/app/views/registration/steps/_promo.html.haml @@ -39,6 +39,6 @@ .message{ ng: { hide: "imageSrc() || imageUploader.isUploading" } } = t(".promo_image_placeholder") .loading{ ng: { hide: "!imageUploader.isUploading" } } - %img.spinner{ src: "/assets/spinning-circles.svg" } + %img.spinner{ src: image_path("spinning-circles.svg") } %br/ = t("registration.steps.images.uploading") diff --git a/app/views/shared/_footer.html.haml b/app/views/shared/_footer.html.haml index e6374288a5..2ba6278bec 100644 --- a/app/views/shared/_footer.html.haml +++ b/app/views/shared/_footer.html.haml @@ -3,7 +3,7 @@ .row .small-12.columns.text-center .logo - %img{src: "/assets/logo-white-notext.png"} + %img{src: image_path("logo-white-notext.png") } .row .small-12.medium-8.medium-offset-2.columns.text-center .alert-box diff --git a/app/views/shared/_ie_warning.html.haml b/app/views/shared/_ie_warning.html.haml index 2239fa7450..87acc77b4c 100644 --- a/app/views/shared/_ie_warning.html.haml +++ b/app/views/shared/_ie_warning.html.haml @@ -10,17 +10,17 @@ .row .small-4.columns.browserbtn %a.browserlogo{href: "https://www.google.com/intl/en_au/chrome/browser/", target: "_blank"} - %img{src: "assets/browser-logos/chrome.png"} + %img{src: image_path("browser-logos/chrome.png") } %a{href: "https://www.google.com/intl/en_au/chrome/browser/", target: "_blank"} = t :ie_warning_chrome .small-4.columns.browserbtn %a.browserlogo{href: "http://www.mozilla.org/en-US/firefox/new/", target: "_blank"} - %img{src: "assets/browser-logos/firefox.png"} + %img{src: image_path("browser-logos/firefox.png") } %a{href: "http://www.mozilla.org/en-US/firefox/new/", target: "_blank"} = t :ie_warning_firefox .small-4.columns.browserbtn %a.browserlogo{href: "http://windows.microsoft.com/en-AU/internet-explorer/download-ie", target: "_blank"} - %img{src: "assets/browser-logos/internet-explorer.png"} + %img{src: image_path("browser-logos/internet-explorer.png") } %a{href: "http://windows.microsoft.com/en-AU/internet-explorer/download-ie", target: "_blank"} = t :ie_warning_ie .row.ie-msg diff --git a/app/views/shared/_map.html.haml b/app/views/shared/_map.html.haml new file mode 100644 index 0000000000..c7df6d5b2b --- /dev/null +++ b/app/views/shared/_map.html.haml @@ -0,0 +1,19 @@ +- if ContentConfig.open_street_map_enabled + .map-container + %ofn-open-street-map#open-street-map + %div#open-street-map--search + %input.autocomplete-input + %ul.autocomplete-result-list + +- else + .map-container + %map{"ng-controller" => "MapCtrl"} + %ui-gmap-google-map{options: "map.additional_options", center: "map.center", zoom: "map.zoom", + styles: "map.styles", draggable: "true"} + %map-osm-tiles + %map-search + %ui-gmap-markers{models: "OfnMap.enterprises", fit: "true", + coords: "'self'", icon: "'icon'", click: "'reveal'"} + + .map-footer + %a{:href => "http://www.openstreetmap.org/copyright"} © OpenStreetMap contributors diff --git a/app/views/shared/menu/_cart.html.haml b/app/views/shared/menu/_cart.html.haml index be7d5bf5fe..1fd1b06e89 100644 --- a/app/views/shared/menu/_cart.html.haml +++ b/app/views/shared/menu/_cart.html.haml @@ -1,10 +1,8 @@ %span.cart-span{"ng-controller" => "CartCtrl", "ng-class" => "{ dirty: Cart.dirty || Cart.empty(), 'pure-dirty': Cart.dirty }"} - %a#cart.icon{"cart-toggle" => true} + %a#cart.icon{"ng-click" => "toggleCartSidebar()"} %span = t '.cart' %span.count - %img{ src: "/assets/menu/icn-cart.svg" } + %img{ src: image_path("menu/icn-cart.svg") } %span {{ Cart.total_item_count() }} - - = render 'shared/menu/joyride' diff --git a/app/views/shared/menu/_cart_sidebar.html.haml b/app/views/shared/menu/_cart_sidebar.html.haml new file mode 100644 index 0000000000..03c3f52222 --- /dev/null +++ b/app/views/shared/menu/_cart_sidebar.html.haml @@ -0,0 +1,44 @@ +.expanding-sidebar.cart-sidebar{ng: {controller: 'CartCtrl', show: 'showCartSidebar', class: "{'shown': showCartSidebar, 'hidden': !showCartSidebar}"}} + .background{ng: {click: 'toggleCartSidebar()'}} + .sidebar + .cart-header + %span.title{"ng-show" => "Cart.line_items.length == 1"} + = t('.items_in_cart_singular', num: "{{ Cart.total_item_count() }}") + %span.title{"ng-show" => "Cart.line_items.length > 1"} + = t('.items_in_cart_plural', num: "{{ Cart.total_item_count() }}") + %a.close{ng: {click: 'toggleCartSidebar()'}} + = t('.close') + %i.ofn-i_009-close + + .cart-content + %table + %tr.product-cart{"ng-repeat" => "line_item in Cart.line_items", "id" => "cart-variant-{{ line_item.variant.id }}"} + %td.image + %img{'ng-src' => '{{ line_item.variant.thumb_url }}'} + %td + %span {{ line_item.variant.extended_name | truncate: max_characters }} + %br + %span.options-text {{ line_item.variant.options_text | truncate: max_characters }} + %td.text-right + %span.quantity {{ line_item.quantity }} + %td + %span.total-price.right {{ line_item.total_price | localizeCurrency }} + + .cart-empty{"ng-show" => "Cart.line_items.length == 0"} + %p + = t('.cart_empty') + + %a.go-shopping.button.large.bright{ng: {show: "#{show_shopping_cta?}", href: "{{ CurrentHub.hub.id ? '#{main_app.shop_path}' : '#{main_app.shops_path}' }}"}} + = t('.take_me_shopping') + + .sidebar-footer{"ng-show" => "Cart.line_items.length > 0"} + %p.cart-total + %strong + = t 'total' + {{ Cart.total() | localizeCurrency }} + + %div.fullwidth + %a.edit-cart.button.large.dark.left{href: main_app.cart_path, "ng-disabled" => "Cart.dirty || Cart.empty()", "ng-class" => "{ dirty: Cart.dirty }"} + = "{{ Cart.dirty ? '#{t(:cart_updating)}' : (Cart.empty() ? '#{t(:cart_empty)}' : '#{t('.edit_cart')}' ) }}" + %a.checkout.button.large.bright.right{href: main_app.checkout_path, "ng-disabled" => "Cart.dirty || Cart.empty()"} + = t '.checkout' diff --git a/app/views/shared/menu/_joyride.html.haml b/app/views/shared/menu/_joyride.html.haml deleted file mode 100644 index eb1875f383..0000000000 --- a/app/views/shared/menu/_joyride.html.haml +++ /dev/null @@ -1,63 +0,0 @@ -.cart-dropdown.joyride-tip-guide{"ng-class" => "{ in: open }", "ng-show" => "open"} - %span.joyride-nub.top - .joyride-content-wrapper - %h5 - = t 'cart_headline' - .buttons.text-right - %a.button.secondary.tiny.add_to_cart{ href: main_app.cart_path, type: :submit, "ng-disabled" => "Cart.dirty || Cart.empty()", "ng-class" => "{ dirty: Cart.dirty }" } - = "{{ Cart.dirty ? '#{t(:cart_updating)}' : (Cart.empty() ? '#{t(:cart_empty)}' : '#{t(:cart_edit)}' ) }}" - %a.button.primary.tiny{href: main_app.checkout_path, "ng-disabled" => "Cart.dirty || Cart.empty()"} - = t '.checkout' - %table - %tr.product-cart{"ng-repeat" => "line_item in Cart.line_items", "id" => "cart-variant-{{ line_item.variant.id }}"} - %td - %small - %strong - {{ line_item.variant.extended_name }} - %td.text-right - %small - %span.quantity {{ line_item.quantity }} - %i.ofn-i_009-close - %span.price {{ line_item.variant.price_with_fees | localizeCurrency }} - - %td - %small - \= - %strong - .total-price.right {{ line_item.total_price | localizeCurrency }} - - %table{"ng-show" => "Cart.line_items.length > 0"} - %tr.total-cart - %td - %em - = t 'total' - \: - %td.text-right - %strong {{ Cart.total() | localizeCurrency }} - - .buttons.text-right - %a.button.secondary.tiny.add_to_cart{ href: main_app.cart_path, type: :submit, "ng-disabled" => "Cart.dirty || Cart.empty()", "ng-class" => "{ dirty: Cart.dirty }" } - = "{{ Cart.dirty ? '#{t(:cart_updating)}' : (Cart.empty() ? '#{t(:cart_empty)}' : '#{t(:cart_edit)}' ) }}" - %a.button.primary.tiny{href: main_app.checkout_path, "ng-disabled" => "Cart.dirty || Cart.empty()"} - = t '.checkout' - - if order_changes_allowed? - %h5{"ng-if" => "Cart.line_items_finalised.length", style: 'margin-top: 1em'} - = t '.already_ordered_products' - %table - %tr.product-cart{"ng-repeat" => "line_item in Cart.line_items_finalised", - "id" => "cart-variant-{{ line_item.variant.id }}"} - %td - %small - %strong - {{ line_item.variant.extended_name }} - %td.text-right - %small - %span.quantity {{ line_item.quantity }} - %i.ofn-i_009-close - %span.price {{ line_item.variant.price_with_fees | localizeCurrency }} - - %td - %small - \= - %strong - .total-price.right {{ line_item.total_price | localizeCurrency }} \ No newline at end of file diff --git a/app/views/shared/menu/_menu.html.haml b/app/views/shared/menu/_menu.html.haml index 050a3f043e..4559434a8f 100644 --- a/app/views/shared/menu/_menu.html.haml +++ b/app/views/shared/menu/_menu.html.haml @@ -1,4 +1,6 @@ -= render "shared/menu/large_menu" -%ofn-flash -= render "shared/menu/mobile_menu" -= render "shared/menu/offcanvas_menu" +%div{'ng-controller' => 'CartDropdownCtrl'} + = render "shared/menu/large_menu" + %ofn-flash + = render "shared/menu/mobile_menu" + = render "shared/menu/offcanvas_menu" + = render "shared/menu/cart_sidebar" diff --git a/app/views/shared/menu/_mobile_menu.html.haml b/app/views/shared/menu/_mobile_menu.html.haml index c501d7b365..716db01f73 100644 --- a/app/views/shared/menu/_mobile_menu.html.haml +++ b/app/views/shared/menu/_mobile_menu.html.haml @@ -1,7 +1,7 @@ %nav.tab-bar.show-for-medium-down %section.left %a.left-off-canvas-toggle.menu-icon - %span + = image_tag "menu/btn-menu-mobile.png" %section.left .ofn-logo @@ -9,12 +9,12 @@ %img{src: ContentConfig.logo_mobile.url, srcset: ContentConfig.logo_mobile_svg.url, width: "75", height: "26"} %section.right{"ng-cloak" => true} - %span.cart-span{"ng-controller" => "CartCtrl", "ng-class" => "{ dirty: Cart.dirty || Cart.empty(), 'pure-dirty': Cart.dirty }"} - %a.icon{href: main_app.cart_path} + %span.cart-span{"ng-class" => "{ dirty: Cart.dirty || Cart.empty(), 'pure-dirty': Cart.dirty }"} + %a.icon{ng: {click: 'toggleCartSidebar()'}} %span = t '.cart' %span.count - %img{ src: "/assets/menu/icn-cart.svg" } + = image_tag "menu/icn-cart.svg" %span {{ Cart.total_item_count() }} diff --git a/app/views/shared/menu/_signed_in.html.haml b/app/views/shared/menu/_signed_in.html.haml index 269178ffaa..dceb81075a 100644 --- a/app/views/shared/menu/_signed_in.html.haml +++ b/app/views/shared/menu/_signed_in.html.haml @@ -7,7 +7,7 @@ %li.user-menu.has-dropdown.not-click %a{href: "#", class: "top-bar--menu-item-with-icon"} - %img{ src: "/assets/menu/icn-profile.svg" } + %img{ src: image_path("menu/icn-profile.svg") } %span = t '.profile' diff --git a/app/views/shared/menu/_signed_out.html.haml b/app/views/shared/menu/_signed_out.html.haml index fdb827031f..3a886a20e0 100644 --- a/app/views/shared/menu/_signed_out.html.haml +++ b/app/views/shared/menu/_signed_out.html.haml @@ -1,5 +1,5 @@ %li#login-link %a{"auth" => "login"} - %img{ src: "/assets/menu/icn-login.svg" } + %img{ src: image_path("menu/icn-login.svg") } %span = t 'label_login' diff --git a/app/views/shop/products/_form.html.haml b/app/views/shop/products/_form.html.haml index c4e6ea6908..ffbc7bdf25 100644 --- a/app/views/shop/products/_form.html.haml +++ b/app/views/shop/products/_form.html.haml @@ -21,7 +21,7 @@ = t :products_loading .row .small-12.columns.text-center - %img.spinner{ src: "/assets/spinning-circles.svg" } + %img.spinner{ src: image_path("spinning-circles.svg") } .hide-for-medium-down.large-2.columns %h5 @@ -31,7 +31,7 @@ = render partial: "shop/products/filters" - .shop-filters-sidebar.hide-for-large-up{ng: {show: 'showFilterSidebar', class: "{'shown': showFilterSidebar}"}} + .expanding-sidebar.shop-filters-sidebar.hide-for-large-up{ng: {show: 'showFilterSidebar', class: "{'shown': showFilterSidebar}"}} .background{ng: {click: 'toggleFilterSidebar()'}} .sidebar %h5 diff --git a/app/views/shop/products/_searchbar.haml b/app/views/shop/products/_searchbar.haml index fa9fb962a4..f18d9b9382 100644 --- a/app/views/shop/products/_searchbar.haml +++ b/app/views/shop/products/_searchbar.haml @@ -8,7 +8,7 @@ "ng-debounce" => "200", "ofn-disable-enter" => true} %a.clear{type: 'button', ng: {show: 'query', click: 'clearQuery()'}, 'focus-search' => true} - %img{ src: "/assets/icn-close.png" } + = image_tag "icn-close.png" .hide-for-large-up %button{type: 'button', ng: {click: 'toggleFilterSidebar()'}} diff --git a/app/views/shopping_shared/tabs/_shop.html.haml b/app/views/shopping_shared/tabs/_shop.html.haml index 2c23b4e8c1..0a8df040f5 100644 --- a/app/views/shopping_shared/tabs/_shop.html.haml +++ b/app/views/shopping_shared/tabs/_shop.html.haml @@ -4,7 +4,8 @@ - if no_open_order_cycles? = render partial: "shop/messages/closed_shop" - - else = render partial: "shop/messages/select_oc" - = render partial: "shop/products/form" + + -# Rendering the form, even if there are no open OCs, makes display only shops possible + = render partial: "shop/products/form" diff --git a/app/views/shops/_fat.html.haml b/app/views/shops/_fat.html.haml index da9c579454..56772bde40 100644 --- a/app/views/shops/_fat.html.haml +++ b/app/views/shops/_fat.html.haml @@ -1,7 +1,7 @@ .row.active_table_row{"ng-show" => "open()", "ng-click" => "toggle($event)", "ng-class" => "{'open' : open()}"} .columns.small-12.fat.text-center{"ng-show" => "open() && shopfront_loading"} %p - %img.spinner.text-center{ src: "/assets/spinning-circles.svg" } + %img.spinner.text-center{ src: image_path("spinning-circles.svg") } .columns.small-12.medium-6.large-5.fat{"ng-show" => "open() && !shopfront_loading"} %div{"ng-if" => "::hub.taxons"} diff --git a/app/views/shops/_hubs.html.haml b/app/views/shops/_hubs.html.haml index 6c05561da0..1d19839a03 100644 --- a/app/views/shops/_hubs.html.haml +++ b/app/views/shops/_hubs.html.haml @@ -26,7 +26,7 @@ %a{href: "", "ng-click" => "showDistanceMatches()"} = t :hubs_distance_filter, location: "{{ nameMatchesFiltered[0].name }}" .more-controls - %img.spinner.text-center{ng: {show: "closed_shops_loading"}, src: "/assets/spinning-circles.svg" } + %img.spinner.text-center{ng: {show: "closed_shops_loading"}, src: image_path("spinning-circles.svg") } %span{ng: {if: "!show_closed", cloak: true}} %a.button{href: "", ng: {click: "showClosedShops()"}} = t '.show_closed_shops' diff --git a/app/views/spree/admin/adjustments/edit.html.haml b/app/views/spree/admin/adjustments/edit.html.haml index c31dfb145e..756288c4f4 100644 --- a/app/views/spree/admin/adjustments/edit.html.haml +++ b/app/views/spree/admin/adjustments/edit.html.haml @@ -1,4 +1,5 @@ -= render :partial => 'spree/admin/shared/order_tabs', :locals => { :current => 'Adjustments' } += render :partial => 'spree/admin/shared/order_page_title' += render :partial => 'spree/admin/shared/order_tabs', locals: { current: 'Adjustments' } - content_for :page_title do %i.icon-arrow-right diff --git a/app/views/spree/admin/adjustments/index.html.haml b/app/views/spree/admin/adjustments/index.html.haml index 7268441e1e..02433a6e5c 100644 --- a/app/views/spree/admin/adjustments/index.html.haml +++ b/app/views/spree/admin/adjustments/index.html.haml @@ -1,4 +1,5 @@ -= render :partial => 'spree/admin/shared/order_tabs', :locals => { :current => 'Adjustments' } += render partial: 'spree/admin/shared/order_page_title' += render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Adjustments' } - content_for :page_title do %i.icon-arrow-right diff --git a/app/views/spree/admin/adjustments/new.html.haml b/app/views/spree/admin/adjustments/new.html.haml index 3eb6f5c58e..2af33aae54 100644 --- a/app/views/spree/admin/adjustments/new.html.haml +++ b/app/views/spree/admin/adjustments/new.html.haml @@ -1,4 +1,5 @@ -= render :partial => 'spree/admin/shared/order_tabs', :locals => { :current => 'Adjustments' } += render partial: 'spree/admin/shared/order_page_title' += render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Adjustments' } - content_for :page_title do %i.icon-arrow-right diff --git a/app/views/spree/admin/images/index.html.haml b/app/views/spree/admin/images/index.html.haml index 89124383e2..37cc53c70b 100644 --- a/app/views/spree/admin/images/index.html.haml +++ b/app/views/spree/admin/images/index.html.haml @@ -15,15 +15,13 @@ %colgroup %col{ style: "width: 5%" }/ %col{ style: "width: 10%" }/ - - if @product.has_variants? - %col{ style: "width: 25%" }/ + %col{ style: "width: 25%" }/ %col{ style: "width: 45%" }/ %col{ style: "width: 15%" }/ %thead %tr %th{:colspan => "2"}= t('spree.thumbnail') - - if @product.has_variants? - %th= Spree::Variant.model_name.human + %th= Spree::Variant.model_name.human %th= t('spree.alt_text') %th.actions %tbody @@ -35,8 +33,7 @@ %span.handle %td = link_to image_tag(image.attachment.url(:mini)), image.attachment.url(:product) - - if @product.has_variants? - %td= options_text_for(image) + %td= options_text_for(image) %td= image.alt %td.actions = link_to_with_icon 'icon-edit', t('spree.edit'), edit_admin_product_image_url(@product, image), no_text: true, data: { action: 'edit'} diff --git a/app/views/spree/admin/mail_methods/edit.html.haml b/app/views/spree/admin/mail_methods/edit.html.haml index 90938e4542..9e79403270 100644 --- a/app/views/spree/admin/mail_methods/edit.html.haml +++ b/app/views/spree/admin/mail_methods/edit.html.haml @@ -5,11 +5,11 @@ - content_for :page_actions do %li - = link_to_with_icon 'icon-envelope-alt', t("spree.admin.mail_methods.send_testmail"), testmail_admin_mail_method_path, method: :post, title: t("spree.admin.mail_methods.send_testmail"), class: 'send_mail button no-text' + = link_to_with_icon 'icon-envelope-alt', t("spree.admin.mail_methods.send_testmail"), testmail_admin_mail_methods_path, method: :post, title: t("spree.admin.mail_methods.send_testmail"), class: 'send_mail button no-text' = render partial: 'spree/shared/error_messages', locals: { target: @mail_method } -= form_tag admin_mail_method_path, method: :put do |f| += form_tag admin_mail_methods_path, method: :put do |f| %fieldset.no-border-top = render partial: 'form', locals: { f: f } .form-buttons.filter-actions.actions= button t("spree.actions.update"), 'icon-refresh' diff --git a/app/views/spree/admin/orders/_filters.html.haml b/app/views/spree/admin/orders/_filters.html.haml index b41c2d194a..0479e26a62 100644 --- a/app/views/spree/admin/orders/_filters.html.haml +++ b/app/views/spree/admin/orders/_filters.html.haml @@ -1,5 +1,5 @@ %div{"data-hook" => "admin_orders_index_search"} - = form_tag nil, {name: "orders_form", "ng-submit" => "fetchResults()"} do + = form_tag :orders, {name: "orders_form", "ng-submit" => "fetchResults()"} do .field-block.alpha.four.columns .date-range-filter.field = label_tag nil, t(:date_range) @@ -32,6 +32,11 @@ %label = check_box_tag "q[completed_at_not_null]", 1, true, {'ng-model' => 'q.completed_at_not_null'} = t(:show_only_complete_orders) + .field + = label_tag nil, t(:shipping_method) + = select_tag("shipping_method_id", + options_for_select(Spree::ShippingMethod.managed_by(spree_current_user).collect {|s| [t("spree.shipping_method.#{s.name}"), s.id]}), + {include_blank: true, class: 'select2', 'ng-model' => 'shipping_method_id'}) .field-block.alpha.eight.columns = label_tag nil, t(:distributors) = select_tag("q[distributor_id_in]", diff --git a/app/views/spree/admin/orders/bulk_management.html.haml b/app/views/spree/admin/orders/bulk_management.html.haml index 4eb6a67aa0..1053235c67 100644 --- a/app/views/spree/admin/orders/bulk_management.html.haml +++ b/app/views/spree/admin/orders/bulk_management.html.haml @@ -102,7 +102,7 @@ %columns-dropdown{ action: "#{controller_name}_#{action_name}" } %div.sixteen.columns.alpha#loading{ 'ng-if' => 'RequestMonitor.loading' } - %img.spinner{ src: "/assets/spinning-circles.svg" } + %img.spinner{ src: image_path("spinning-circles.svg") } %h1 = t("admin.orders.bulk_management.loading") diff --git a/app/views/spree/admin/orders/customer_details/edit.html.haml b/app/views/spree/admin/orders/customer_details/edit.html.haml index e4fa93ffbb..584c3350b9 100644 --- a/app/views/spree/admin/orders/customer_details/edit.html.haml +++ b/app/views/spree/admin/orders/customer_details/edit.html.haml @@ -1,4 +1,5 @@ -= render :partial => 'spree/admin/shared/order_tabs', :locals => { :current => 'Customer Details' } += render partial: 'spree/admin/shared/order_page_title' += render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Customer Details' } = csrf_meta_tags @@ -9,7 +10,7 @@ - content_for :page_actions do %li= button_link_to Spree.t(:back_to_orders_list), admin_orders_path, :icon => 'icon-arrow-left' -- if @order.cart? +- if @order.cart? || @order.address? #select-customer{"data-hook" => ""} %fieldset.no-border-bottom %legend{:align => "center"}= Spree.t(:customer_search) diff --git a/app/views/spree/admin/orders/edit.html.haml b/app/views/spree/admin/orders/edit.html.haml index 69abbe8f38..d2047e6bf4 100644 --- a/app/views/spree/admin/orders/edit.html.haml +++ b/app/views/spree/admin/orders/edit.html.haml @@ -8,7 +8,8 @@ - if can?(:admin, Spree::Order) %li= button_link_to t(:back_to_orders_list), admin_orders_path, :icon => 'icon-arrow-left' -= render :partial => 'spree/admin/shared/order_tabs', :locals => { :current => 'Order Details' } += render partial: "spree/admin/shared/order_page_title" += render partial: "spree/admin/shared/order_tabs", locals: { current: 'Order Details' } %div{"data-hook" => "admin_order_edit_header"} -# Suppress errors when manually creating a new order - needs to proceed to edit page diff --git a/app/views/spree/admin/orders/index.html.haml b/app/views/spree/admin/orders/index.html.haml index 596cd884c9..d2871fe540 100644 --- a/app/views/spree/admin/orders/index.html.haml +++ b/app/views/spree/admin/orders/index.html.haml @@ -81,7 +81,7 @@ %span{'ng-bind-html' => 'order.display_total'} %td.actions %div.row-loading-icons - %img.spinner{src: "/assets/spinning-circles.svg", ng: {show: 'rowStatus[order.id] == "loading"'} } + %img.spinner{src: image_path("spinning-circles.svg"), ng: {show: 'rowStatus[order.id] == "loading"'} } %i.success.icon-ok-sign{ng: {show: 'rowStatus[order.id] == "success"'} } %i.error.icon-remove-sign.with-tip{ng: {show: 'rowStatus[order.id] == "error"'}, 'ofn-with-tip' => t('.order_not_updated')} %a.icon_link.with-tip.icon-edit.no-text{'ng-href' => '{{order.edit_path}}', 'data-action' => 'edit', 'ofn-with-tip' => t('.edit')} @@ -93,7 +93,7 @@ .orders-loading{'ng-show' => 'RequestMonitor.loading'} .row .small-12.columns.fullwidth.text-center - %img.spinner{ src: "/assets/spinning-circles.svg" } + %img.spinner{ src: image_path("spinning-circles.svg") } .row .small-12.columns.fullwidth.text-center %span= t('.loading') diff --git a/app/views/spree/admin/orders/new.html.haml b/app/views/spree/admin/orders/new.html.haml index 9ec198b2d7..556e464cd4 100644 --- a/app/views/spree/admin/orders/new.html.haml +++ b/app/views/spree/admin/orders/new.html.haml @@ -1,5 +1,7 @@ - content_for :page_title do - = t(:new) + = t(:new_order) + \# + = @order.number - content_for :page_actions do %li= button_link_to t(:back_to_orders_list), spree.admin_orders_path, :icon => 'icon-arrow-left' diff --git a/app/views/spree/admin/orders/set_distribution.html.haml b/app/views/spree/admin/orders/set_distribution.html.haml index f5e259321e..3579619185 100644 --- a/app/views/spree/admin/orders/set_distribution.html.haml +++ b/app/views/spree/admin/orders/set_distribution.html.haml @@ -1,12 +1,14 @@ -- content_for :page_title do - = t(:new) - - content_for :page_actions do %li= button_link_to t(:back_to_orders_list), spree.admin_orders_path, :icon => 'icon-arrow-left' = admin_inject_shops(module: 'admin.orders') = admin_inject_order_cycles +- content_for :page_title do + = t(:new_order) + \# + = @order.number + = render 'spree/admin/shared/order_tabs', :current => 'Order Details' = csrf_meta_tags diff --git a/app/views/spree/admin/payment_methods/_form.html.haml b/app/views/spree/admin/payment_methods/_form.html.haml index 8ab592fd81..7c2e1c4085 100644 --- a/app/views/spree/admin/payment_methods/_form.html.haml +++ b/app/views/spree/admin/payment_methods/_form.html.haml @@ -1,42 +1,44 @@ = admin_inject_payment_method = admin_inject_json_ams_array "admin.paymentMethods", "shops", @hubs, Api::Admin::BasicEnterpriseSerializer -%div.alpha.eleven.columns{ "ng-app" => "admin.paymentMethods", "ng-controller" => "paymentMethodCtrl" } +.alpha.eleven.columns{ "ng-app" => "admin.paymentMethods", "ng-controller" => "paymentMethodCtrl" } + .row + = t '.deactivation_warning' .row .alpha.three.columns - = label_tag nil, t(:name) + = label_tag nil, t('.name') .omega.eight.columns = text_field :payment_method, :name, class: 'fullwidth' .row .alpha.three.columns - = label_tag nil, t(:description) + = label_tag nil, t('.description') .omega.eight.columns = text_area :payment_method, :description, {cols: 60, rows: 6, class: 'fullwidth'} - if spree_current_user.admin? .row .alpha.three.columns - = label_tag nil, t(:environment) + = label_tag nil, t('.environment') .omega.eight.columns = collection_select(:payment_method, :environment, Rails.configuration.database_configuration.keys.sort, :to_s, :titleize, {}, {id: 'gtwy-env', class: 'select2 fullwidth'}) .row .alpha.three.columns - = label_tag nil, t(:display) + = label_tag nil, t('.display') .omega.eight.columns - = select(:payment_method, :display_on, Spree::PaymentMethod::DISPLAY.collect { |display| [t(display), display == :both ? nil : display.to_s] }, {}, {class: 'select2 fullwidth'}) + = select(:payment_method, :display_on, Spree::PaymentMethod::DISPLAY.collect { |display| [t('.' + display.to_s), display == :both ? nil : display.to_s] }, {}, {class: 'select2 fullwidth'}) .row .alpha.three.columns - = label_tag nil, t(:active) + = label_tag nil, t('.active') .two.columns = radio_button :payment_method, :active, true   - = label_tag nil, t(:say_yes) + = label_tag nil, t('.active_yes') .omega.six.columns = radio_button :payment_method, :active, false   - = label_tag nil, t(:say_no) + = label_tag nil, t('.active_no') .row .alpha.three.columns - = label(:payment_method, :tags, t(:tags)) + = label(:payment_method, :tags, t('.tags')) .omega.eight.columns = hidden_field(:payment_method, :tag_list, "ng-value" => "paymentMethod.tag_list") %tags-with-translation#something{ object: "paymentMethod" } diff --git a/app/views/spree/admin/payment_methods/_providers.html.haml b/app/views/spree/admin/payment_methods/_providers.html.haml index 657e21029e..2311eaa78f 100644 --- a/app/views/spree/admin/payment_methods/_providers.html.haml +++ b/app/views/spree/admin/payment_methods/_providers.html.haml @@ -1,7 +1,7 @@ #provider-settings{ ng: { controller: "ProvidersCtrl" } } .row .alpha.three.columns - = label :payment_method, :type, t(:provider) + = label :payment_method, :type, t('.provider') .omega.eight.columns = collection_select(:payment_method, :type, @providers, :to_s, :clean_name, (!@object.persisted? ? { :selected => "Spree::PaymentMethod::Check"} : {}), { class: 'select2 fullwidth', 'provider-prefs-for' => "#{@object.id}"}) diff --git a/app/views/spree/admin/payment_methods/_stripe_connect.html.haml b/app/views/spree/admin/payment_methods/_stripe_connect.html.haml index 0e9ff2f614..4e0c59e94f 100644 --- a/app/views/spree/admin/payment_methods/_stripe_connect.html.haml +++ b/app/views/spree/admin/payment_methods/_stripe_connect.html.haml @@ -11,7 +11,7 @@ placeholder: t(".enterprise_select_placeholder"), data: 'shops', ng: { model: 'paymentMethod.preferred_enterprise_id' } } - else - %strong= Enterprise.find_by_id(@payment_method).andand.name + %strong= Enterprise.find_by(id: @payment_method).andand.name #stripe-account-status{ ng: { show: "paymentMethod.preferred_enterprise_id" } } .alert-box.warning{ ng: { hide: "stripe_account.status" } } diff --git a/app/views/spree/admin/payment_methods/edit.html.haml b/app/views/spree/admin/payment_methods/edit.html.haml index 9d8f6b147d..f1c98aeb43 100644 --- a/app/views/spree/admin/payment_methods/edit.html.haml +++ b/app/views/spree/admin/payment_methods/edit.html.haml @@ -4,7 +4,7 @@ = @payment_method.name - content_for :page_actions do %li - = button_link_to t(:new), spree.new_admin_payment_method_path, icon: 'icon-plus' + = button_link_to t('.new'), spree.new_admin_payment_method_path, icon: 'icon-plus' %li = button_link_to t('.back_to_payment_methods_list'), spree.admin_payment_methods_path, icon: 'icon-arrow-left' = render partial: 'spree/shared/error_messages', locals: { target: @payment_method } diff --git a/app/views/spree/admin/payment_methods/index.html.haml b/app/views/spree/admin/payment_methods/index.html.haml index 4e79bf1c9d..ab1333f2c5 100644 --- a/app/views/spree/admin/payment_methods/index.html.haml +++ b/app/views/spree/admin/payment_methods/index.html.haml @@ -1,9 +1,9 @@ - content_for :page_title do - = Spree.t(:payment_methods) + = t('.payment_methods') - content_for :page_actions do %li - = button_link_to Spree.t(:new_payment_method), new_object_url, icon: 'icon-plus', id: 'admin_new_payment_methods_link' + = button_link_to t('.new_payment_method'), new_object_url, icon: 'icon-plus', id: 'admin_new_payment_methods_link' - if @payment_methods.any? %table#listing_payment_methods.index @@ -17,12 +17,12 @@ %col{style: "width: 11%"} %thead %tr - %th= Spree.t(:name) - %th= t(:products_distributor) - %th= Spree.t(:provider) - %th= Spree.t(:environment) - %th= Spree.t(:display) - %th= Spree.t(:active) + %th= t('.name') + %th= t('.products_distributor') + %th= t('.provider') + %th= t('.environment') + %th= t('.display') + %th= t('.active') %th.actions %tbody - @payment_methods.each do |method| @@ -34,10 +34,10 @@ %br/ %td= method.type %td.align-center= method.environment.to_s.titleize - %td.align-center= method.display_on.blank? ? Spree.t(:both) : Spree.t(method.display_on) - %td.align-center= method.active ? Spree.t(:say_yes) : Spree.t(:say_no) + %td.align-center= method.display_on.blank? ? t('.both') : t('.' + method.display_on.to_s) + %td.align-center= method.active ? t('.active_yes') : t('.active_no') %td.actions = link_to_edit method, no_text: true = link_to_delete method, no_text: true - else - .alpha.twelve.columns.no-objects-found= Spree.t(:no_payment_methods_found) + .alpha.twelve.columns.no-objects-found= t('.no_payment_methods_found') diff --git a/app/views/spree/admin/payments/index.html.haml b/app/views/spree/admin/payments/index.html.haml index 3c62b54843..7fbe76429f 100644 --- a/app/views/spree/admin/payments/index.html.haml +++ b/app/views/spree/admin/payments/index.html.haml @@ -1,3 +1,4 @@ += render partial: 'spree/admin/shared/order_page_title' = render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Payments' } - content_for :page_actions do diff --git a/app/views/spree/admin/payments/new.html.haml b/app/views/spree/admin/payments/new.html.haml index 7c825051ad..710456cc2d 100644 --- a/app/views/spree/admin/payments/new.html.haml +++ b/app/views/spree/admin/payments/new.html.haml @@ -1,3 +1,4 @@ += render partial: 'spree/admin/shared/order_page_title' = render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Payments' } - content_for :page_title do diff --git a/app/views/spree/admin/payments/show.html.haml b/app/views/spree/admin/payments/show.html.haml index 97850cb19a..acbc2d8aaf 100644 --- a/app/views/spree/admin/payments/show.html.haml +++ b/app/views/spree/admin/payments/show.html.haml @@ -1,3 +1,4 @@ += render partial: 'spree/admin/shared/order_page_title' = render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Payments' } - content_for :page_title do diff --git a/app/views/spree/admin/products/_form.html.haml b/app/views/spree/admin/products/_form.html.haml index 616f7977f3..08386e10dd 100644 --- a/app/views/spree/admin/products/_form.html.haml +++ b/app/views/spree/admin/products/_form.html.haml @@ -43,37 +43,6 @@ .clear - - unless @product.has_variants? - = f.field_container :sku do - = f.label :sku, t(:sku) - = f.text_field :sku, :size => 16 - - .alpha.two.columns - = f.field_container :on_hand do - = f.label :on_hand, t(:on_hand) - = f.number_field :on_hand, :min => 0 - .omega.two.columns - = f.field_container :on_demand, :class => ['checkbox'] do - %label - = f.check_box :on_demand - = t(:on_demand) - - .clear - - %ul#shipping_specs - %li#shipping_specs_weight_field.field.alpha.two.columns - = f.label :weight, t(:weight) - = f.text_field :weight, :size => 4 - %li#shipping_specs_height_field.field.omega.two.columns - = f.label :height, t(:height) - = f.text_field :height, :size => 4 - %li#shipping_specs_width_field.field.alpha.two.columns - = f.label :width, t(:width) - = f.text_field :width, :size => 4 - %li#shipping_specs_depth_field.field.omega.two.columns - = f.label :depth, t(:depth) - = f.text_field :depth, :size => 4 - = f.field_container :shipping_categories do = f.label :shipping_category_id, t(:shipping_categories) = f.collection_select(:shipping_category_id, @shipping_categories, :id, :name, { :include_blank => 'None' }, { :class => 'select2' }) diff --git a/app/views/spree/admin/products/index/_indicators.html.haml b/app/views/spree/admin/products/index/_indicators.html.haml index 4c39f9a5d9..930f4b4337 100644 --- a/app/views/spree/admin/products/index/_indicators.html.haml +++ b/app/views/spree/admin/products/index/_indicators.html.haml @@ -1,6 +1,6 @@ %div.sixteen.columns.alpha#loading{ 'ng-if' => 'RequestMonitor.loading' } %br - %img.spinner{ src: "/assets/spinning-circles.svg" } + %img.spinner{ src: image_path("spinning-circles.svg") } %h1= t('.title') %div.sixteen.columns.alpha{ 'ng-show' => '!RequestMonitor.loading && products.length == 0 && query.length==0' } diff --git a/app/views/spree/admin/reports/_link_order.html.haml b/app/views/spree/admin/reports/_link_order.html.haml index 9f0b72b4f7..1efecf6d25 100644 --- a/app/views/spree/admin/reports/_link_order.html.haml +++ b/app/views/spree/admin/reports/_link_order.html.haml @@ -1 +1,2 @@ -%a.edit-order{href: "/admin/orders/#{value}"}= value +- order_number = value += link_to order_number, edit_admin_order_url(order_number), class: 'edit-order' diff --git a/app/views/spree/admin/return_authorizations/edit.html.haml b/app/views/spree/admin/return_authorizations/edit.html.haml index 2847c10965..9f5429640d 100644 --- a/app/views/spree/admin/return_authorizations/edit.html.haml +++ b/app/views/spree/admin/return_authorizations/edit.html.haml @@ -6,6 +6,7 @@ - if @return_authorization.can_cancel? = button_link_to t('actions.cancel'), fire_admin_order_return_authorization_url(@order, @return_authorization, e: 'cancel'), method: :put, data: { confirm: t('.are_you_sure') }, icon: 'icon-remove' += render partial: 'spree/admin/shared/order_page_title' = render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Return Authorizations' } - content_for :page_title do diff --git a/app/views/spree/admin/return_authorizations/index.html.haml b/app/views/spree/admin/return_authorizations/index.html.haml index acf016b50d..bc8ed9dd80 100644 --- a/app/views/spree/admin/return_authorizations/index.html.haml +++ b/app/views/spree/admin/return_authorizations/index.html.haml @@ -1,3 +1,4 @@ += render partial: 'spree/admin/shared/order_page_title' = render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Return Authorizations' } - content_for :page_actions do diff --git a/app/views/spree/admin/return_authorizations/new.html.haml b/app/views/spree/admin/return_authorizations/new.html.haml index 54573f7392..5594288cf3 100644 --- a/app/views/spree/admin/return_authorizations/new.html.haml +++ b/app/views/spree/admin/return_authorizations/new.html.haml @@ -1,3 +1,4 @@ += render partial: 'spree/admin/shared/order_page_title' = render partial: 'spree/admin/shared/order_tabs', locals: { current: 'Return Authorizations' } - content_for :page_title do diff --git a/app/views/spree/admin/shared/_configuration_menu.html.haml b/app/views/spree/admin/shared/_configuration_menu.html.haml index 5810cc97b2..c5f302f0db 100644 --- a/app/views/spree/admin/shared/_configuration_menu.html.haml +++ b/app/views/spree/admin/shared/_configuration_menu.html.haml @@ -6,7 +6,7 @@ %ul.sidebar = configurations_sidebar_menu_item Spree.t(:general_settings), edit_admin_general_settings_path - if Spree::Config[:override_actionmailer_config] - = configurations_sidebar_menu_item Spree.t(:mail_method_settings), edit_admin_mail_method_path + = configurations_sidebar_menu_item Spree.t(:mail_method_settings), edit_admin_mail_methods_path = configurations_sidebar_menu_item Spree.t(:image_settings), edit_admin_image_settings_path = configurations_sidebar_menu_item Spree.t(:tax_categories), admin_tax_categories_path = configurations_sidebar_menu_item Spree.t(:tax_rates), admin_tax_rates_path diff --git a/app/views/spree/admin/shared/_order_page_title.html.haml b/app/views/spree/admin/shared/_order_page_title.html.haml new file mode 100644 index 0000000000..927062d4f7 --- /dev/null +++ b/app/views/spree/admin/shared/_order_page_title.html.haml @@ -0,0 +1,4 @@ +- content_for :page_title do + = t(:order) + \# + = @order.number diff --git a/app/views/spree/admin/shared/_order_tabs.html.haml b/app/views/spree/admin/shared/_order_tabs.html.haml index 89d7299fdc..f96a5dd140 100644 --- a/app/views/spree/admin/shared/_order_tabs.html.haml +++ b/app/views/spree/admin/shared/_order_tabs.html.haml @@ -1,8 +1,3 @@ -- content_for :page_title do - = t(:order) - \# - = @order.number - - if @order.bill_address.present? = @order.bill_address.firstname = @order.bill_address.lastname diff --git a/app/views/spree/admin/shared/_tabs.html.haml b/app/views/spree/admin/shared/_tabs.html.haml index 920480fc8b..e0134ee272 100644 --- a/app/views/spree/admin/shared/_tabs.html.haml +++ b/app/views/spree/admin/shared/_tabs.html.haml @@ -3,7 +3,7 @@ = tab :order_cycles, url: main_app.admin_order_cycles_path, icon: 'icon-refresh' = tab :orders, :subscriptions, :customer_details, :adjustments, :payments, :return_authorizations, url: admin_orders_path('q[s]' => 'completed_at desc'), icon: 'icon-shopping-cart' = tab :reports, icon: 'icon-file' -= tab :general_settings, :mail_method, :image_settings, :tax_categories, :tax_rates, :tax_settings, :zones, :countries, :states, :payment_methods, :taxonomies, :shipping_methods, :shipping_categories, :enterprise_fees, :contents, :invoice_settings, :matomo_settings, :stripe_connect_settings, label: 'configuration', icon: 'icon-wrench', url: edit_admin_general_settings_path += tab :general_settings, :mail_methods, :image_settings, :tax_categories, :tax_rates, :tax_settings, :zones, :countries, :states, :payment_methods, :taxonomies, :shipping_methods, :shipping_categories, :enterprise_fees, :contents, :invoice_settings, :matomo_settings, :stripe_connect_settings, label: 'configuration', icon: 'icon-wrench', url: edit_admin_general_settings_path = tab :enterprises, :enterprise_relationships, url: main_app.admin_enterprises_path = tab :customers, url: main_app.admin_customers_path = tab :enterprise_groups, url: main_app.admin_enterprise_groups_path, label: 'groups' diff --git a/app/views/spree/admin/variants/_autocomplete.js.erb b/app/views/spree/admin/variants/_autocomplete.js.erb index 527b55568c..9e4c29a50a 100644 --- a/app/views/spree/admin/variants/_autocomplete.js.erb +++ b/app/views/spree/admin/variants/_autocomplete.js.erb @@ -4,7 +4,7 @@ {{#if variant.image }} {{ else }} - + {{/if}} @@ -57,7 +57,7 @@ {{else}} - <%= Spree.t(:out_of_stock) %> + <%= t('.out_of_stock') %> 0 {{/if}} diff --git a/app/views/spree/admin/variants/index.html.haml b/app/views/spree/admin/variants/index.html.haml index 199bcc0501..ce9c1edd86 100644 --- a/app/views/spree/admin/variants/index.html.haml +++ b/app/views/spree/admin/variants/index.html.haml @@ -3,40 +3,32 @@ = render partial: 'spree/admin/shared/product_tabs', locals: {current: 'Variants'} #new_variant -- if @variants.any? - %table.index.sortable{"data-sortable-link" => update_positions_admin_product_variants_path(@product)} - %colgroup - %col{style: "width: 5%"}/ - %col{style: "width: 25%"}/ - %col{style: "width: 20%"}/ - %col{style: "width: 20%"}/ - %col{style: "width: 15%"}/ - %col{style: "width: 15%"}/ - %thead - %tr - %th{colspan: "2"}= t('.options') - %th= t('.price') - %th= t('.sku') - %th.actions - %tbody - - @variants.each do |variant| - %tr{id: spree_dom_id(variant), class: cycle('odd', 'even'), style: "#{"color:red;" if variant.deleted? }" } - %td.no-border - %span.handle - %td= variant.full_name - %td.align-center= variant.display_price.to_html - %td.align-center= variant.sku - %td.actions - = link_to_edit(variant, no_text: true) unless variant.deleted? - = link_to_delete(variant, no_text: true) unless variant.deleted? - - unless @product.has_variants? - %tr - %td{colspan: "5"}= t(:none) -- else - .alpha.twelve.columns.no-objects-found - = t('.no_results') - \. +%table.index.sortable{"data-sortable-link" => update_positions_admin_product_variants_path(@product)} + %colgroup + %col{style: "width: 5%"}/ + %col{style: "width: 25%"}/ + %col{style: "width: 20%"}/ + %col{style: "width: 20%"}/ + %col{style: "width: 15%"}/ + %col{style: "width: 15%"}/ + %thead + %tr + %th{colspan: "2"}= t('.options') + %th= t('.price') + %th= t('.sku') + %th.actions + %tbody + - @variants.each do |variant| + %tr{id: spree_dom_id(variant), class: cycle('odd', 'even'), style: "#{"color:red;" if variant.deleted? }" } + %td.no-border + %span.handle + %td= variant.full_name + %td.align-center= variant.display_price.to_html + %td.align-center= variant.sku + %td.actions + = link_to_edit(variant, no_text: true) unless variant.deleted? + = link_to_delete(variant, no_text: true) unless variant.deleted? - if @product.empty_option_values? %p.first_add_option_types.no-objects-found diff --git a/app/views/spree/layouts/_admin_body.html.haml b/app/views/spree/layouts/_admin_body.html.haml index 6fb035c825..d5aa05dbee 100644 --- a/app/views/spree/layouts/_admin_body.html.haml +++ b/app/views/spree/layouts/_admin_body.html.haml @@ -9,12 +9,7 @@ - if flash[:success] .flash.success= flash[:success] - #progress - .wrapper - #spinner - .progress-message - = Spree.t(:loading) - \... + = render partial: "spree/layouts/admin/progress_spinner" %header#header{"data-hook" => ""} .container diff --git a/app/views/spree/layouts/admin/_progress_spinner.html.haml b/app/views/spree/layouts/admin/_progress_spinner.html.haml new file mode 100644 index 0000000000..a28458afad --- /dev/null +++ b/app/views/spree/layouts/admin/_progress_spinner.html.haml @@ -0,0 +1,24 @@ +#progress + / By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL + %svg{:class => "spinner", :viewbox => "0 0 58 58", :xmlns => "http://www.w3.org/2000/svg"} + %g{:fill => "none", "fill-rule" => "evenodd"} + %g{:stroke => "currentColor", "stroke-width" => "1.5", :transform => "translate(2 1)"} + %circle{:cx => "42.601", :cy => "11.462", :fill => "currentColor", "fill-opacity" => "1", :r => "5"} + %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "1;0;0;0;0;0;0;0"} + %circle{:cx => "49.063", :cy => "27.063", :fill => "currentColor", "fill-opacity" => "0", :r => "5"} + %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "0;1;0;0;0;0;0;0"} + %circle{:cx => "42.601", :cy => "42.663", :fill => "currentColor", "fill-opacity" => "0", :r => "5"} + %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "0;0;1;0;0;0;0;0"} + %circle{:cx => "27", :cy => "49.125", :fill => "currentColor", "fill-opacity" => "0", :r => "5"} + %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "0;0;0;1;0;0;0;0"} + %circle{:cx => "11.399", :cy => "42.663", :fill => "currentColor", "fill-opacity" => "0", :r => "5"} + %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "0;0;0;0;1;0;0;0"} + %circle{:cx => "4.938", :cy => "27.063", :fill => "currentColor", "fill-opacity" => "0", :r => "5"} + %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "0;0;0;0;0;1;0;0"} + %circle{:cx => "11.399", :cy => "11.462", :fill => "currentColor", "fill-opacity" => "0", :r => "5"} + %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "0;0;0;0;0;0;1;0"} + %circle{:cx => "27", :cy => "5", :fill => "currentColor", "fill-opacity" => "0", :r => "5"} + %animate{:attributename => "fill-opacity", :begin => "0s", :calcmode => "linear", :dur => "1.3s", :repeatcount => "indefinite", :values => "0;0;0;0;0;0;0;1"} + + = Spree.t(:loading) + \... diff --git a/app/views/spree/layouts/bare_admin.html.haml b/app/views/spree/layouts/bare_admin.html.haml index a6e4c895ba..085f5be86a 100644 --- a/app/views/spree/layouts/bare_admin.html.haml +++ b/app/views/spree/layouts/bare_admin.html.haml @@ -8,12 +8,7 @@ .flash.notice= notice - if flash[:success] .flash.success= flash[:success] - #progress - .wrapper - #spinner - .progress-message - = t(:loading) - \... + = render partial: "spree/layouts/admin/progress_spinner" %header#header{"data-hook" => ""} .container diff --git a/app/views/spree/order_mailer/cancel_email.html.haml b/app/views/spree/order_mailer/cancel_email.html.haml index 47b577e79d..0965d522b8 100755 --- a/app/views/spree/order_mailer/cancel_email.html.haml +++ b/app/views/spree/order_mailer/cancel_email.html.haml @@ -1,11 +1,29 @@ -%h3 - = t(".customer_greeting", name: @order.bill_address.firstname) -%h4 - = t(".instructions") -%span.clear +%table.social.white-bg.fullwidth + %table.column + %tr + %td + %h3 + = t(".customer_greeting", name: @order.bill_address.firstname) + %h4 + = t(".instructions_html", distributor: @order.distributor.name ) + %img{src: "#{@order.distributor.logo.url(:medium)}"} + +%p.callout + = t(".dont_cancel", email: @order.distributor.contact.email) %p   +%h4 + = t(".order_summary_canceled_html", number: @order.number) +%p + = t(".details") -= t(".order_summary_canceled") = render 'order_summary' + +%p + - if @order.paid? + = t(".paid_order", distributor: @order.distributor.name) + - else + = t(".unpaid_order") + = render 'signoff' += render 'shared/mailers/social_and_contact' diff --git a/app/views/spree/orders/form/_cart_links.html.haml b/app/views/spree/orders/form/_cart_links.html.haml index 798a428f7c..89a63d70fd 100644 --- a/app/views/spree/orders/form/_cart_links.html.haml +++ b/app/views/spree/orders/form/_cart_links.html.haml @@ -1,5 +1,5 @@ .row.links{'data-hook' => "cart_buttons"} - %a.continue-shopping.button.large.secondary{href: current_shop_products_path, "ng-disabled" => "#{@insufficient_stock_lines.any?}", "disable-dynamically" => true} + %a.continue-shopping.button.secondary{href: current_shop_products_path, "ng-disabled" => "#{@insufficient_stock_lines.any?}", "disable-dynamically" => true} = t :orders_edit_continue - %a#checkout-link.button.large.primary.right{href: main_app.checkout_path, "ng-disabled" => "#{@insufficient_stock_lines.any?}", "disable-dynamically" => true} + %a#checkout-link.button.primary.right{href: main_app.checkout_path, "ng-disabled" => "#{@insufficient_stock_lines.any?}", "disable-dynamically" => true} = t :orders_edit_checkout diff --git a/app/views/spree/shared/_error_messages.html.haml b/app/views/spree/shared/_error_messages.html.haml index 54fabd313e..b0ced1b317 100644 --- a/app/views/spree/shared/_error_messages.html.haml +++ b/app/views/spree/shared/_error_messages.html.haml @@ -1,10 +1,9 @@ - if target && target.errors.any? #errorExplanation.errorExplanation %h2 - = Spree.t(:errors_prohibited_this_record_from_being_saved, count: target.errors.count) - \: + = t(".errors_prohibited_this_record_from_being_saved", count: target.errors.count) %p - = Spree.t(:there_were_problems_with_the_following_fields) + = t(".there_were_problems_with_the_following_fields") \: %ul - target.errors.full_messages.each do |msg| diff --git a/config/application.rb b/config/application.rb index 2799e52d2f..d48b5d2b8b 100644 --- a/config/application.rb +++ b/config/application.rb @@ -39,7 +39,7 @@ module Openfoodnetwork Spree::Config['checkout_zone'] = ENV['CHECKOUT_ZONE'] Spree::Config['currency'] = ENV['CURRENCY'] if Spree::Country.table_exists? - country = Spree::Country.find_by_iso(ENV['DEFAULT_COUNTRY_CODE']) + country = Spree::Country.find_by(iso: ENV['DEFAULT_COUNTRY_CODE']) Spree::Config['default_country_id'] = country.id if country.present? else Spree::Config['default_country_id'] = 12 # Australia @@ -106,7 +106,7 @@ module Openfoodnetwork #{config.root}/app/jobs ) - config.paths["config/routes"] = %w( + config.paths["config/routes.rb"] = %w( config/routes/api.rb config/routes.rb config/routes/admin.rb @@ -138,9 +138,6 @@ module Openfoodnetwork # Configure the default encoding used in templates for Ruby 1.9. config.encoding = "utf-8" - # Configure sensitive parameters which will be filtered from the log file. - config.filter_parameters += [:password] - # Enable the asset pipeline config.assets.enabled = true @@ -163,6 +160,7 @@ module Openfoodnetwork config.assets.precompile += ['mail/all.css'] config.assets.precompile += ['shared/*'] config.assets.precompile += ['qz/*'] + config.assets.precompile += ['*.jpg', '*.jpeg', '*.png', '*.gif' '*.svg'] config.active_support.escape_html_entities_in_json = true end diff --git a/config/application.yml.example b/config/application.yml.example index 0cbb866279..99b8bf4fe8 100644 --- a/config/application.yml.example +++ b/config/application.yml.example @@ -13,7 +13,7 @@ DEFAULT_COUNTRY_CODE: AU # Locale for translation. LOCALE: en # For multilingual - ENV doesn't have array so pass it as string with commas -AVAILABLE_LOCALES: en,es,en-GB +AVAILABLE_LOCALES: en,es # Spree zone. CHECKOUT_ZONE: Australia # Find currency codes at http://en.wikipedia.org/wiki/ISO_4217. diff --git a/config/environments/development.rb b/config/environments/development.rb index 88714f3f7f..dc7250eb4a 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -13,8 +13,7 @@ Openfoodnetwork::Application.configure do # :file_store is used by default when no cache store is specifically configured. config.cache_store = :memory_store if !!ENV["PROFILE"] - # Log error messages when you accidentally call methods on nil. - config.whiny_nils = true + config.eager_load = false # Show full error reports and disable caching config.consider_all_requests_local = true diff --git a/config/environments/production.rb b/config/environments/production.rb index 94b9418463..9c61ebaab0 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,6 +1,8 @@ Openfoodnetwork::Application.configure do # Settings specified here will take precedence over those in config/application.rb + config.eager_load = true + # Code is not reloaded between requests config.cache_classes = true @@ -33,16 +35,11 @@ Openfoodnetwork::Application.configure do # Use https in email links config.action_mailer.default_url_options = { protocol: 'https' } - # Note: This config no longer works with our new logging strategy - # config.log_level = :debug + # Set log level (default is :debug in Rails 4) + config.log_level = :info - # Configure logging for Rails 3.2: - config.logger = ActiveSupport::TaggedLogging.new(Logger.new(Rails.root.join("log", "#{Rails.env}.log"))) - config.logger.level = Logger::INFO - config.logger.formatter = Logger::Formatter.new - config.logger.datetime_format = "%Y-%m-%d %H:%M:%S" - # Once we get to Rails 4.0, we can replace the above with: - #config.log_formatter = Logger::Formatter.new.tap { |f| f.datetime_format = "%Y-%m-%d %H:%M:%S" } + # Configure logging: + config.log_formatter = Logger::Formatter.new.tap { |f| f.datetime_format = "%Y-%m-%d %H:%M:%S" } # Use a different cache store in production memcached_value_max_megabytes = ENV.fetch("MEMCACHED_VALUE_MAX_MEGABYTES", 1).to_i diff --git a/config/environments/staging.rb b/config/environments/staging.rb index 94b9418463..9c61ebaab0 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -1,6 +1,8 @@ Openfoodnetwork::Application.configure do # Settings specified here will take precedence over those in config/application.rb + config.eager_load = true + # Code is not reloaded between requests config.cache_classes = true @@ -33,16 +35,11 @@ Openfoodnetwork::Application.configure do # Use https in email links config.action_mailer.default_url_options = { protocol: 'https' } - # Note: This config no longer works with our new logging strategy - # config.log_level = :debug + # Set log level (default is :debug in Rails 4) + config.log_level = :info - # Configure logging for Rails 3.2: - config.logger = ActiveSupport::TaggedLogging.new(Logger.new(Rails.root.join("log", "#{Rails.env}.log"))) - config.logger.level = Logger::INFO - config.logger.formatter = Logger::Formatter.new - config.logger.datetime_format = "%Y-%m-%d %H:%M:%S" - # Once we get to Rails 4.0, we can replace the above with: - #config.log_formatter = Logger::Formatter.new.tap { |f| f.datetime_format = "%Y-%m-%d %H:%M:%S" } + # Configure logging: + config.log_formatter = Logger::Formatter.new.tap { |f| f.datetime_format = "%Y-%m-%d %H:%M:%S" } # Use a different cache store in production memcached_value_max_megabytes = ENV.fetch("MEMCACHED_VALUE_MAX_MEGABYTES", 1).to_i diff --git a/config/environments/test.rb b/config/environments/test.rb index 299e2d9c19..f33423acdd 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -5,7 +5,9 @@ Openfoodnetwork::Application.configure do # test suite. You never need to work with it otherwise. Remember that # your test database is "scratch space" for the test suite and is wiped # and recreated between test runs. Don't rely on the data there! - config.cache_classes = true + config.cache_classes = false + + config.eager_load = false # Configure static asset server for tests with Cache-Control for performance config.serve_static_assets = true @@ -14,10 +16,6 @@ Openfoodnetwork::Application.configure do # Separate cache stores when running in parallel config.cache_store = :file_store, Rails.root.join("tmp", "cache", "paralleltests#{ENV['TEST_ENV_NUMBER']}") - - # Log error messages when you accidentally call methods on nil - config.whiny_nils = true - # Show full error reports and disable caching config.consider_all_requests_local = true config.action_controller.perform_caching = false @@ -37,7 +35,7 @@ Openfoodnetwork::Application.configure do # Tests assume English text on the site. config.i18n.default_locale = "en" - config.i18n.available_locales = ['en', 'es'] + config.i18n.available_locales = ['en', 'es', 'pt'] config.i18n.fallbacks = [:en] I18n.locale = config.i18n.locale = config.i18n.default_locale diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 6f0a508ac4..e20b748148 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -65,9 +65,6 @@ Devise.setup do |config| # Range for password length # config.password_length = 6..20 - # Regex to use to validate the email address - config.email_regexp = /^([\w\.%\+\-]+)@([\w\-]+\.)+([\w]{2,})$/i - # ==> Configuration for :timeoutable # The time you want to timeout the user session without activity. After this # time the user will be asked for credentials again. diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb new file mode 100644 index 0000000000..e203fcee0a --- /dev/null +++ b/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,2 @@ +# Configure sensitive parameters which will be filtered from the log file. +Rails.application.config.filter_parameters += [:password] diff --git a/config/initializers/geocoder.rb b/config/initializers/geocoder.rb index 35b5510d5e..67ae27e7e4 100644 --- a/config/initializers/geocoder.rb +++ b/config/initializers/geocoder.rb @@ -1,6 +1,7 @@ # Google requires an API key with a billing account to use their API. # The key is stored in config/application.yml. Geocoder.configure( + lookup: :google, use_https: true, api_key: ENV.fetch('GOOGLE_MAPS_API_KEY', nil) ) diff --git a/config/initializers/paper_trail.rb b/config/initializers/paper_trail.rb index e955bac9be..39a6679176 100644 --- a/config/initializers/paper_trail.rb +++ b/config/initializers/paper_trail.rb @@ -1,7 +1 @@ PaperTrail.config.track_associations = false - -module PaperTrail - class Version < ActiveRecord::Base - attr_accessible :custom_data - end -end diff --git a/config/initializers/rack_rewrite.rb b/config/initializers/rack_rewrite.rb index 98c93a79f3..251330f9d4 100644 --- a/config/initializers/rack_rewrite.rb +++ b/config/initializers/rack_rewrite.rb @@ -1,7 +1,7 @@ module Openfoodnetwork class Application < Rails::Application - config.middleware.insert_before(Rack::Lock, Rack::Rewrite) do - r301 '/admin/products/bulk_edit', '/admin/products' # TODO: Date added 15/06/2018 + config.middleware.insert_before(Rack::Runtime, Rack::Rewrite) do + r301 '/admin/products/bulk_edit', '/admin/products' end end end diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb index 9aac0efd56..b203cf8485 100644 --- a/config/initializers/secret_token.rb +++ b/config/initializers/secret_token.rb @@ -9,3 +9,5 @@ Openfoodnetwork::Application.config.secret_token = if Rails.env.development? or else ENV["SECRET_TOKEN"] end + +Openfoodnetwork::Application.config.secret_key_base = 'ceb1eb86c50285e696f899b2e7ea306d1ec1e81fe5c7af0e5cbc238bebe3fd60f19df7b9076fab836182821ebe14e41b64bdcdb4370520dc5bb711c1bc0ae616' diff --git a/config/initializers/spree.rb b/config/initializers/spree.rb index c2f6a118a1..cc2ff359ba 100644 --- a/config/initializers/spree.rb +++ b/config/initializers/spree.rb @@ -15,7 +15,6 @@ require 'spree/product_filters' # https://github.com/openfoodfoundation/openfoodnetwork/issues/3121 Spree::Gateway.class_eval do acts_as_taggable - attr_accessible :tag_list end require "#{Rails.root}/app/models/spree/payment_method_decorator" diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index 999df20181..c2f744d290 100644 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -7,8 +7,3 @@ ActiveSupport.on_load(:action_controller) do wrap_parameters format: [:json] end - -# Disable root element in JSON by default. -ActiveSupport.on_load(:active_record) do - self.include_root_in_json = false -end diff --git a/config/locales/ar.yml b/config/locales/ar.yml index 537091cb62..9af7be11b0 100644 --- a/config/locales/ar.yml +++ b/config/locales/ar.yml @@ -23,6 +23,8 @@ ar: base: "بطاقة ائتمان" order_cycle: orders_close_at: تاريخ الاغلاق + variant_override: + count_on_hand: "متوفر" errors: models: spree/user: @@ -363,7 +365,6 @@ ar: title: "إعدادات Matomo" matomo_url: "العنوان الالكتروني ل Matomo " matomo_site_id: "معرف موقع Matomo" - info_html: "Matomo هو تحليلات الويب والجوال. يمكنك إما تنصيب Matomo محليًا أو استخدام خدمة استضافة سحابية. انظر matomo.org لمزيد من المعلومات." config_instructions_html: "هنا يمكنك تهيئة تكامل Matomo لشبكة الغذاء المفتوح. يجب أن يشير عنوان الالكتروني URL الخاص بـ Matomo أدناه إلى مثيل Matomo حيث سيتم إرسال معلومات تتبع المستخدم إلى ؛ إذا تم تركه فارغًا ، فسيتم تعطيل تتبع مستخدم Matomo. حقل معرف الموقع ليس إلزاميًا ولكنه مفيد إذا كنت تتعقب أكثر من موقع ويب على مثيل Matomo ؛ يمكن العثور عليه على وحدة تحكم مثيل Matomo." customers: index: @@ -398,6 +399,7 @@ ar: footer_and_external_links: تذييل والروابط الخارجية your_content: المحتوى الخاص بك user_guide: دليل المستخدم + map: خريطة enterprise_fees: index: title: "رسوم الشركة" @@ -2683,6 +2685,7 @@ ar: customer_details: "تفاصيل العميل" adjustments: "التعديلات" payments: "المدفوعات" + return_authorizations: "عودة التراخيص" payment: "دفعة" payment_method: "طريقة الدفع او السداد" shipment: "الشحنة" @@ -2752,6 +2755,8 @@ ar: new_payment: "دفعة جديد" capture: "إلتقاط" void: "فارغ" + login: "تسجيل الدخول" + password: "كلمه السر" configurations: "تهيئة" general_settings: "الاعدادات العامة" site_name: "اسم الموقع" @@ -2816,8 +2821,6 @@ ar: abbreviation: "الاختصار" new_state: "محافظة جديدة" payment_methods: "طرق الدفع" - new_payment_method: "طريقة الدفع الجديدة" - provider: "مزود" taxonomies: "التصنيفات" new_taxonomy: "تصنيف جديد" back_to_taxonomies_list: "العودة إلى قائمة التصنيفات" @@ -3024,10 +3027,23 @@ ar: categories: "التصنيفات" zones: "مناطق" payment_methods: + index: + payment_methods: "طريقة الدفع" + new_payment_method: "طريقة الدفع الجديدة" + name: "الاسم" + products_distributor: "الموزع" + provider: "مزود" + environment: "بيئة" + display: "عرض" + active: "نشط" + both: "على حد سواء" + active_yes: "نعم" + active_no: "لا" new: new_payment_method: "طريقة الدفع الجديدة" back_to_payment_methods_list: "العودة إلى قائمة طرق الدفع" edit: + new: "جديد" editing_payment_method: "تحرير طريقة الدفع" back_to_payment_methods_list: "العودة إلى قائمة طرق الدفع" stripe_connect: @@ -3043,6 +3059,17 @@ ar: account_id: معرف الحساب business_name: الاسم التجاري charges_enabled: تم تمكين الدفع + form: + name: "الاسم" + description: "وصف" + environment: "بيئة" + display: "عرض" + active: "نشط" + active_yes: "نعم" + active_no: "لا" + tags: "الاوسمة" + providers: + provider: "مزود" payments: source_forms: stripe: @@ -3143,6 +3170,7 @@ ar: display_as: "عرض ب" display_name: "اسم العرض" autocomplete: + out_of_stock: "غير متوفر" producer_name: "المنتج" unit: "وحدة" shared: @@ -3207,9 +3235,6 @@ ar: invalid: غير صالحة order_mailer: cancel_email: - customer_greeting: "مرحبًا %{name}!" - instructions: "تم إلغاء طلبك. يرجى الاحتفاظ بمعلومات الإلغاء هذه بسجلاتك." - order_summary_canceled: "ملخص الطلب [ملغى]" subject: "إلغاء الطلب" confirm_email: subject: "تأكيد الطلب" diff --git a/config/locales/ca.yml b/config/locales/ca.yml index 3336807d9e..55204a9c95 100644 --- a/config/locales/ca.yml +++ b/config/locales/ca.yml @@ -23,6 +23,8 @@ ca: base: "Targeta de crèdit" order_cycle: orders_close_at: Data de tancament + variant_override: + count_on_hand: "Disponibles" errors: models: spree/user: @@ -368,8 +370,10 @@ ca: title: "Configuració de Matomo" matomo_url: "URL de Matomo" matomo_site_id: "Identificador de Matomo" - info_html: "Matomo és un analitzador de webs i mòbils. Podeu allotjar Matomo de manera local o utilitzar un servei al núvol. Vegeu matomo.org per obtenir més informació." + matomo_tag_manager_url: "URL de Matomo Tag Manager" + info_html: "Matomo és una aplicació d'analytics web i mòbil. Podeu allotjar Matomo en local o bé utilitzar un servei allotjat al núvol. Consulteu matomo.org per obtenir més informació." config_instructions_html: "Aquí podeu configurar la integració Matomo OFN. L'URL de Matomo que us apareix a continuació ha d'indicar la instància de Matomo en la qual s'enviarà la informació de seguiment de l'usuari; si es deixa buit, el seguiment de l'usuari de Matomo estarà desactivat. El camp d'identificació del lloc no és obligatori, però és útil si fa un seguiment de més d'un lloc web en una sola instància de Matomo; es pot trobar a la consola d'instància de Matomo." + config_instructions_tag_manager_html: "En configurar l'URL de Matomo Tag Manager s'activa Matomo Tag Manager. Aquesta eina us permet configurar esdeveniments d’analítica. L’URL de Matomo Tag Manager es copia de la secció Instal·lar codi de Matomo Tag Manager. Assegureu-vos de seleccionar el contenidor i l’entorn adequats ja que aquestes opcions canvien l’URL." customers: index: new_customer: "Nova consumidora" @@ -403,6 +407,7 @@ ca: footer_and_external_links: Peu de pàgina i enllaços externs your_content: El vostre contingut user_guide: Guia de l'usuari + map: Mapa enterprise_fees: index: title: "Comissions de l'organització" @@ -474,6 +479,7 @@ ca: line_number: "Línia %{number}:" encoding_error: "Comproveu la configuració de l'idioma del vostre fitxer d'origen i assegureu-vos que es desa amb la codificació UTF-8" unexpected_error: "La importació de productes ha detectat un error inesperat mentre obria el fitxer: %{error_message}" + malformed_csv: "La importació de producte ha trobat un CSV mal format: %{error_message}" index: notice: "Avís" beta_notice: "Aquesta funcionalitat continua en fase beta: podeu experimentar alguns errors mentre l'utilitzeu. No dubteu en contactar amb nosaltres." @@ -2743,6 +2749,7 @@ ca: customer_details: "Detalls de la consumidora" adjustments: "Ajustaments" payments: "Pagaments" + return_authorizations: "Autoritzacions de devolució" payment: "Pagament" payment_method: "Mètode de pagament" shipment: "Enviament" @@ -2812,6 +2819,14 @@ ca: new_payment: "Nou pagament" capture: "Captura" void: "Buit" + login: "Inicia sessió" + password: "Contrasenya" + signature: "Signatura" + solution: "Solució" + landing_page: "Pàgina d'inici" + server: "Servidor" + test_mode: "Mode de prova" + logourl: "URL del logo" configurations: "Configuracions" general_settings: "Configuració general" site_name: "Nom del lloc" @@ -2876,8 +2891,6 @@ ca: abbreviation: "Abreviatura" new_state: "Nou estat" payment_methods: "Mètodes de Pagament" - new_payment_method: "Nou mètode de pagament" - provider: "Proveïdor" taxonomies: "Taxonomies" new_taxonomy: "Nova taxonomia" back_to_taxonomies_list: "Torna a la llista de taxonomies" @@ -2930,6 +2943,12 @@ ca: options: "Opcions" actions: update: "Actualitzar" + shared: + error_messages: + errors_prohibited_this_record_from_being_saved: + one: "Un error va prohibir guardar aquest registre:" + other: "%{count} errors han impedit guardar aquest registre:" + there_were_problems_with_the_following_fields: "Hi ha hagut problemes amb els camps següents" errors: messages: blank: "no es pot deixar en blanc" @@ -3089,10 +3108,26 @@ ca: back_end: "Només pàgina administració (back office) " deactivation_warning: "Desactivar un mètode d'enviament pot fer que desaparegui de la teva llista. Pots ocultar-lo de la pàgina de validació de comanda configurant l'opció \"Mostrar\" a \"només a la pàgina d'administració\" (back end)." payment_methods: + index: + payment_methods: "Mètodes de Pagament" + new_payment_method: "Nou mètode de pagament" + name: "Nom" + products_distributor: "Distribuïdora" + provider: "Proveïdor" + environment: "Ambient" + display: "Mostra" + active: "Actiu" + both: "Ambdós" + front_end: "Visible només per al comprador" + back_end: "Només pàgina administració (back office) " + active_yes: "Sí" + active_no: "No" + no_payment_methods_found: "No s'han trobat mètodes de pagament" new: new_payment_method: "Nou mètode de pagament" back_to_payment_methods_list: "Tornar a la llista de mètodes de pagament" edit: + new: "Nou" editing_payment_method: "Edició del mètode de pagament" back_to_payment_methods_list: "Tornar a la llista de mètodes de pagament" stripe_connect: @@ -3108,6 +3143,21 @@ ca: account_id: Identificador del compte business_name: Nom de l'empresa charges_enabled: Càrrecs habilitats + form: + name: "Nom" + description: "Descripció" + environment: "Ambient" + display: "Mostra" + active: "Actiu" + active_yes: "Sí" + active_no: "No" + both: "Ambdues, validació de comanda i administració" + front_end: "Visible només per al comprador" + back_end: "Només pàgina administració (back office) " + tags: "Etiquetes" + deactivation_warning: "Desactivar un mètode de pagament pot fer que el mètode de pagament desapareixi de la vostra llista. De forma alternativa, podeu amagar un mètode de pagament a la pàgina de compra configurant l'opció \"Mostrar\" a \"només a la pàgina d'administració\" (back end)." + providers: + provider: "Proveïdor" payments: source_forms: stripe: @@ -3210,6 +3260,7 @@ ca: display_as_placeholder: 'per exemple. 2 kg' display_name_placeholder: 'per exemple. Tomàquets' autocomplete: + out_of_stock: "Fora d'existència" producer_name: "Productor" unit: "Unitat" shared: @@ -3275,9 +3326,14 @@ ca: invalid: invàlid order_mailer: cancel_email: - customer_greeting: "Hola %{name}!" - instructions: "La teva comanda ha estat anul·lada. Conserva aquesta informació de cancel·lació per als teus registres." - order_summary_canceled: "Resum de comanda [CANCEL·LADA]" + customer_greeting: "Benvolgut/da,%{name}" + instructions_html: "La teva comanda %{distributor} ha estat CANCEL·LADA" + dont_cancel: "Si heu canviat d'opinió o no voleu cancel·lar aquesta comanda, poseu-vos en contacte amb %{email}" + order_summary_canceled_html: "Resum de comanda # %{number} [CANCELAT]" + details: "Aquí teniu els detalls del que vau demanar:" + unpaid_order: "La vostra comanda no s'havia pagat, per la qual cosa no s'ha realitzat cap reemborsament" + paid_order: "La vostra comanda s'havia pagat per la qual cosa %{distributor} ha reemborsat l'import complet" + credit_order: "La vostra comanda s'havia pagat i per tant, s'ha abonat l'import al vostre compte" subject: "Cancel·lació de la comanda" confirm_email: subject: "Confirmació de la comanda" diff --git a/config/locales/de_DE.yml b/config/locales/de_DE.yml index 5ddcdc89a3..94dd643337 100644 --- a/config/locales/de_DE.yml +++ b/config/locales/de_DE.yml @@ -23,6 +23,8 @@ de_DE: base: "Kreditkarte" order_cycle: orders_close_at: Schlussdatum + variant_override: + count_on_hand: "Verfügbar" errors: models: spree/user: @@ -367,7 +369,6 @@ de_DE: title: "Matomo-Einstellungen" matomo_url: "Matomo-URL" matomo_site_id: "Matomo-Site-ID" - info_html: "Matomo ist eine Web- und Mobile Analytics. Sie können Matomo entweder lokal hosten oder einen von der Cloud gehosteten Dienst verwenden. Weitere Informationen finden Sie unter matomo.org ." config_instructions_html: "Hier können Sie die OFN Matomo Integration konfigurieren. Die unten angegebene Matomo-URL sollte auf die Matomo-Instanz verweisen, an die die Benutzerverfolgungsinformationen gesendet werden. Wenn es leer bleibt, wird das Matomo-Benutzer-Tracking deaktiviert. Das Feld Site-ID ist nicht obligatorisch, aber nützlich, wenn Sie mehr als eine Website in einer einzelnen Matomo-Instanz verfolgen. Es kann auf der Matomo-Instanzkonsole gefunden werden." customers: index: @@ -402,6 +403,7 @@ de_DE: footer_and_external_links: Fußzeile und externe Links your_content: Ihr Inhalt user_guide: Benutzerhandbuch + map: Karte enterprise_fees: index: title: "Unternehmensgebühren" @@ -2785,6 +2787,8 @@ de_DE: new_payment: "Neue Zahlung" capture: "Erfassung" void: "Leere" + login: "Anmeldung" + password: "Passwort" configurations: "Konfigurationen" general_settings: "Allgemeine Einstellungen" site_name: "Site-Name" @@ -2849,8 +2853,6 @@ de_DE: abbreviation: "Abkürzung" new_state: "Neuer Staat" payment_methods: "Zahlungsarten" - new_payment_method: "Neue Zahlungsart" - provider: "Anbieter" taxonomies: "Taxonomien" new_taxonomy: "Neue Taxonomie" back_to_taxonomies_list: "Zurück zur Taxonomieliste" @@ -3057,6 +3059,13 @@ de_DE: categories: "Kategorien" zones: "Zonen" payment_methods: + index: + payment_methods: "Zahlungsarten" + name: "Name" + products_distributor: "Verteiler" + both: "Beide" + active_yes: "Ja" + active_no: "Nein" new: new_payment_method: "Neue Zahlungsart" back_to_payment_methods_list: "Zurück zur Liste der Zahlungsmethoden" @@ -3076,6 +3085,12 @@ de_DE: account_id: Konto-ID business_name: Geschäftsname charges_enabled: Gebühren aktiviert + form: + name: "Name" + description: "Beschreibung" + active_yes: "Ja" + active_no: "Nein" + tags: "Stichwörter" payments: source_forms: stripe: @@ -3236,9 +3251,6 @@ de_DE: invalid: ungültig order_mailer: cancel_email: - customer_greeting: "Hallo %{name}!" - instructions: "Ihre Bestellung wurde storniert. Bitte bewahren Sie diese Stornierungsinformationen für Ihre Unterlagen auf." - order_summary_canceled: "Bestellübersicht [STORNIERT]" subject: "Stornierung der Bestellung" confirm_email: subject: "Bestellbestätigung" diff --git a/config/locales/en.yml b/config/locales/en.yml index 1aee3bfa2c..27cf49f93b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -44,6 +44,8 @@ en: base: "Credit Card" order_cycle: orders_close_at: Close date + variant_override: + count_on_hand: "On Hand" errors: models: spree/user: @@ -415,8 +417,10 @@ en: 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." + matomo_tag_manager_url: "Matomo Tag Manager URL" + info_html: "Matomo is a Web and Mobile Analytics application. 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." + config_instructions_tag_manager_html: "Setting the Matomo Tag Manager URL enables Matomo Tag Manager. This tool allows you to set up analytics events. The Matomo Tag Manager URL is copied from the Install Code section of Matomo Tag Manager. Ensure you select the right container and environment as these options change the URL." customers: index: @@ -452,6 +456,7 @@ en: footer_and_external_links: Footer and External Links your_content: Your content user_guide: User Guide + map: Map enterprise_fees: index: @@ -528,6 +533,7 @@ en: 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}" + malformed_csv: "Product Import encountered a malformed CSV: %{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." @@ -1210,13 +1216,18 @@ en: menu: cart: cart: "Cart" + cart_sidebar: + checkout: "Checkout" + edit_cart: "Edit cart" + items_in_cart_singular: "%{num} item in your cart" + items_in_cart_plural: "%{num} items in your cart" + close: "Close" + cart_empty: "Your cart is empty" + take_me_shopping: "Take me shopping!" 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" @@ -2879,6 +2890,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using customer_details: "Customer Details" adjustments: "Adjustments" payments: "Payments" + return_authorizations: "Return Authorizations" payment: "Payment" payment_method: "Payment Method" @@ -2952,6 +2964,14 @@ See the %{link} to find out more about %{sitename}'s features and to start using new_payment: "New Payment" capture: "Capture" void: "Void" + login: "Login" + password: "Password" + signature: "Signature" + solution: "Solution" + landing_page: "Landing Page" + server: "Server" + test_mode: "Test Mode" + logourl: "Logourl" configurations: "Configurations" general_settings: "General Settings" @@ -3025,8 +3045,6 @@ See the %{link} to find out more about %{sitename}'s features and to start using new_state: "New State" payment_methods: "Payment Methods" - new_payment_method: "New Payment Method" - provider: "Provider" taxonomies: "Taxonomies" new_taxonomy: "New Taxonomy" @@ -3089,6 +3107,12 @@ See the %{link} to find out more about %{sitename}'s features and to start using actions: update: "Update" + shared: + error_messages: + errors_prohibited_this_record_from_being_saved: + one: "1 error prohibited this record from being saved:" + other: "%{count} errors prohibited this record from being saved:" + there_were_problems_with_the_following_fields: "There were problems with the following fields" errors: messages: blank: "can't be blank" @@ -3248,10 +3272,26 @@ See the %{link} to find out more about %{sitename}'s features and to start using back_end: "Back office only" deactivation_warning: "De-activating a shipping method can make the shipping method disappear from your list. Alternatively, you can hide a shipping method from the checkout page by setting the option 'Display' to 'back office only'." payment_methods: + index: + payment_methods: "Payment Methods" + new_payment_method: "New Payment Method" + name: "Name" + products_distributor: "Distributor" + provider: "Provider" + environment: "Environment" + display: "Display" + active: "Active" + both: "Both" + front_end: "Checkout only" + back_end: "Back office only" + active_yes: "Yes" + active_no: "No" + no_payment_methods_found: "No payment methods found" new: new_payment_method: "New Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" edit: + new: "New" editing_payment_method: "Editing Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" stripe_connect: @@ -3267,6 +3307,21 @@ See the %{link} to find out more about %{sitename}'s features and to start using account_id: Account ID business_name: Business Name charges_enabled: Charges Enabled + form: + name: "Name" + description: "Description" + environment: "Environment" + display: "Display" + active: "Active" + active_yes: "Yes" + active_no: "No" + both: "Both Checkout and Back office" + front_end: "Checkout only" + back_end: "Back office only" + tags: "Tags" + deactivation_warning: "De-activating a payment method can make the payment method disappear from your list. Alternatively, you can hide a payment method from the checkout page by setting the option 'Display' to 'back office only'." + providers: + provider: "Provider" payments: source_forms: stripe: @@ -3369,6 +3424,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using display_as_placeholder: 'eg. 2 kg' display_name_placeholder: 'eg. Tomatoes' autocomplete: + out_of_stock: "Out of Stock" producer_name: "Producer" unit: "Unit" shared: @@ -3434,9 +3490,14 @@ See the %{link} to find out more about %{sitename}'s features and to start using 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]" + customer_greeting: "Dear %{name}," + instructions_html: "Your order with %{distributor} has been CANCELED. Please retain this cancellation information for your records." + dont_cancel: "If you have changed your mind or don't wish to cancel this order please contact %{email}" + order_summary_canceled_html: "Order Summary #%{number} [CANCELED]" + details: "Here are the details of what you ordered:" + unpaid_order: "Your order was unpaid so no refund has been made" + paid_order: "Your order was paid so %{distributor} has refunded the full amount" + credit_order: "Your order was paid so your account has been credited" subject: "Cancellation of Order" confirm_email: subject: "Order Confirmation" diff --git a/config/locales/en_AU.yml b/config/locales/en_AU.yml index fb801884fe..c940313002 100644 --- a/config/locales/en_AU.yml +++ b/config/locales/en_AU.yml @@ -23,6 +23,8 @@ en_AU: base: "Credit Card" order_cycle: orders_close_at: Close date + variant_override: + count_on_hand: "On Hand" errors: models: spree/user: @@ -359,7 +361,6 @@ en_AU: 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: @@ -394,6 +395,7 @@ en_AU: footer_and_external_links: Footer and External Links your_content: Your content user_guide: User Guide + map: Map enterprise_fees: index: title: "Enterprise Fees" @@ -2634,6 +2636,7 @@ en_AU: customer_details: "Customer Details" adjustments: "Adjustments" payments: "Payments" + return_authorizations: "Return Authorizations" payment: "Payment" payment_method: "Payment Method" shipment: "Shipment" @@ -2703,6 +2706,8 @@ en_AU: new_payment: "New Payment" capture: "Capture" void: "Void" + login: "Login" + password: "Password" configurations: "Configurations" general_settings: "General Settings" site_name: "Site Name" @@ -2767,8 +2772,6 @@ en_AU: abbreviation: "Abbreviation" new_state: "New State" payment_methods: "Payment Methods" - new_payment_method: "New Payment Method" - provider: "Provider" taxonomies: "Taxonomies" new_taxonomy: "New Taxonomy" back_to_taxonomies_list: "Back to Taxonomies List" @@ -2970,10 +2973,23 @@ en_AU: categories: "Categories" zones: "Zones" payment_methods: + index: + payment_methods: "Payment Methods" + new_payment_method: "New Payment Method" + name: "Name" + products_distributor: "Distributor" + provider: "Provider" + environment: "Environment" + display: "Display" + active: "Active" + both: "Both" + active_yes: "Yes" + active_no: "No" new: new_payment_method: "New Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" edit: + new: "New" editing_payment_method: "Editing Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" stripe_connect: @@ -2989,6 +3005,17 @@ en_AU: account_id: Account ID business_name: Business Name charges_enabled: Charges Enabled + form: + name: "Name" + description: "Description" + environment: "Environment" + display: "Display" + active: "Active" + active_yes: "Yes" + active_no: "No" + tags: "Tags" + providers: + provider: "Provider" payments: source_forms: stripe: @@ -3089,6 +3116,7 @@ en_AU: display_as: "Display As" display_name: "Display Name" autocomplete: + out_of_stock: "Out of Stock" producer_name: "Producer" unit: "Unit" shared: @@ -3153,9 +3181,6 @@ en_AU: 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" diff --git a/config/locales/en_BE.yml b/config/locales/en_BE.yml index 963ef29366..4b4d63ac8f 100644 --- a/config/locales/en_BE.yml +++ b/config/locales/en_BE.yml @@ -23,6 +23,8 @@ en_BE: base: "Credit Card" order_cycle: orders_close_at: Close date + variant_override: + count_on_hand: "On Hand" errors: models: spree/user: @@ -354,7 +356,6 @@ en_BE: 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: @@ -389,6 +390,7 @@ en_BE: footer_and_external_links: Footer and External Links your_content: Your content user_guide: User Guide + map: Map enterprise_fees: index: title: "Enterprise Fees" @@ -2658,6 +2660,8 @@ en_BE: new_payment: "New Payment" capture: "Capture" void: "Void" + login: "Login" + password: "Password" configurations: "Configurations" general_settings: "General Settings" site_name: "Site Name" @@ -2722,8 +2726,6 @@ en_BE: abbreviation: "Abbreviation" new_state: "New State" payment_methods: "Payment Methods" - new_payment_method: "New Payment Method" - provider: "Provider" taxonomies: "Taxonomies" new_taxonomy: "New Taxonomy" back_to_taxonomies_list: "Back to Taxonomies List" @@ -2888,10 +2890,23 @@ en_BE: categories: "Categories" zones: "Zones" payment_methods: + index: + payment_methods: "Payment Methods" + new_payment_method: "New Payment Method" + name: "Name" + products_distributor: "Distributor" + provider: "Provider" + environment: "Environment" + display: "Display" + active: "Active" + both: "Both" + active_yes: "Yes" + active_no: "No" new: new_payment_method: "New Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" edit: + new: "New" editing_payment_method: "Editing Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" stripe_connect: @@ -2907,6 +2922,17 @@ en_BE: account_id: Account ID business_name: Business Name charges_enabled: Charges Enabled + form: + name: "Name" + description: "Description" + environment: "Environment" + display: "Display" + active: "Active" + active_yes: "Yes" + active_no: "No" + tags: "Tags" + providers: + provider: "Provider" payments: source_forms: stripe: @@ -2996,6 +3022,7 @@ en_BE: price: "Price" display_as: "Display As" autocomplete: + out_of_stock: "Out of Stock" producer_name: "Producer" unit: "Unit" shared: @@ -3060,9 +3087,6 @@ en_BE: 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" diff --git a/config/locales/en_CA.yml b/config/locales/en_CA.yml index 8071cfb4a9..8af92b5472 100644 --- a/config/locales/en_CA.yml +++ b/config/locales/en_CA.yml @@ -23,6 +23,8 @@ en_CA: base: "Credit Card" order_cycle: orders_close_at: Close date + variant_override: + count_on_hand: "On Hand" errors: models: spree/user: @@ -259,7 +261,7 @@ en_CA: pick_up: Pick up copy: Copy change_my_password: "Change my password" - update_password: "Update passord" + update_password: "Update password" password_confirmation: Password Confirmation reset_password_token: Reset password token expired: has expired, please request a new one @@ -368,8 +370,10 @@ en_CA: 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." + matomo_tag_manager_url: "Matomo Tag Manager URL" + info_html: "Matomo is a Web and Mobile Analytics application. You can either host Matomo on-premises or use a cloud-hosted service. See 1matomo.org1 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." + config_instructions_tag_manager_html: "Setting the Matomo Tag Manager URL enables Matomo Tag Manager. This tool allows you to set up analytics events. The Matomo Tag Manager URL is copied from the Install Code section of Matomo Tag Manager. Ensure you select the right container and environment as these options change the URL." customers: index: new_customer: "New Customer" @@ -403,6 +407,7 @@ en_CA: footer_and_external_links: Footer and External Links your_content: Your content user_guide: User Guide + map: Map enterprise_fees: index: title: "Enterprise Fees" @@ -664,8 +669,8 @@ en_CA: 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... + groups_tip: Select any markets or groups that you are a member of. This will help customers find your enterprise. + groups_placeholder: Start typing to search available markets or groups... primary_producer: Primary Producer? primary_producer_tip: Select 'Producer' if you are a primary producer, grower, maker or designer producer: Producer @@ -1269,7 +1274,7 @@ en_CA: label_map: "Map" label_producer: "Producer" label_producers: "Producers" - label_groups: "Groups" + label_groups: "Markets" label_about: "About" label_connect: "Connect" label_learn: "Learn" @@ -1567,14 +1572,14 @@ en_CA: components_profiles_show: "Show profiles" components_filters_nofilters: "No filters" components_filters_clearfilters: "Clear all filters" - groups_title: Groups + groups_title: Markets groups_headline: 'Markets / 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_text: "Markets 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_producers: "Our vendors" + groups_hubs: "Go Shopping!" groups_contact_web: Contact groups_contact_social: Follow groups_contact_address: Address @@ -2736,6 +2741,7 @@ en_CA: customer_details: "Customer Details" adjustments: "Adjustments" payments: "Payments" + return_authorizations: "Return Authoriations" payment: "Payment" payment_method: "Payment Method" shipment: "Shipment" @@ -2805,6 +2811,14 @@ en_CA: new_payment: "New Payment" capture: "Capture" void: "Void" + login: "Login" + password: "Password" + signature: "Signature" + solution: "Solution" + landing_page: "Landing Page" + server: "Server" + test_mode: "Test Mode" + logourl: "Logourl" configurations: "Configurations" general_settings: "General Settings" site_name: "Site Name" @@ -2869,8 +2883,6 @@ en_CA: abbreviation: "Abbreviation" new_state: "New Province" payment_methods: "Payment Methods" - new_payment_method: "New Payment Method" - provider: "Provider" taxonomies: "Taxonomies" new_taxonomy: "New Taxonomy" back_to_taxonomies_list: "Back to Taxonomies List" @@ -2923,6 +2935,12 @@ en_CA: options: "Options" actions: update: "Update" + shared: + error_messages: + errors_prohibited_this_record_from_being_saved: + one: " 1 errors prohibited this record from being saved:" + other: " %{count}errors prohibited this record from being saved:" + there_were_problems_with_the_following_fields: "There were problems with the following fields" errors: messages: blank: "can't be blank" @@ -3082,10 +3100,26 @@ en_CA: back_end: "Back office only" deactivation_warning: "De-activating a shipping method can make the shipping method disappear from your list. Alternatively, you can hide a shipping method from the checkout page by setting the option 'Display' to 'back office only'." payment_methods: + index: + payment_methods: "Payment Methods" + new_payment_method: "New Payment Method" + name: "Name" + products_distributor: "Distributor" + provider: "Provider" + environment: "Environment" + display: "Display" + active: "Active" + both: "Both" + front_end: "Checkout only" + back_end: "Back office only" + active_yes: "Yes" + active_no: "No" + no_payment_methods_found: "No payment methods found" new: new_payment_method: "New Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" edit: + new: "New" editing_payment_method: "Editing Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" stripe_connect: @@ -3101,6 +3135,21 @@ en_CA: account_id: Account ID business_name: Business Name charges_enabled: Charges Enabled + form: + name: "Name" + description: "Description" + environment: "Environment" + display: "Display" + active: "Active" + active_yes: "Yes" + active_no: "No" + both: "Both Checkout and Back office" + front_end: "Checkout only" + back_end: "Back office only" + tags: "Tags" + deactivation_warning: "De-activating a payment method can make the payment method disappear from your list. Alternatively, you can hide a payment method from the checkout page by setting the option 'Display' to 'back office only'." + providers: + provider: "Provider" payments: source_forms: stripe: @@ -3203,6 +3252,7 @@ en_CA: display_as_placeholder: 'eg. 2 kg' display_name_placeholder: 'eg. Tomatoes' autocomplete: + out_of_stock: "Out of Stock" producer_name: "Producer" unit: "Unit" shared: @@ -3268,9 +3318,14 @@ en_CA: 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]" + customer_greeting: "Dear %{name}," + instructions_html: "Your order with 1%{distributor}1 has been CANCELED. Please retain this cancellation information for your records." + dont_cancel: "If you have changed your mind or don't wish to cancel this order please contact %{email} " + order_summary_canceled_html: "Order Summary #%{number} [CANCELED]" + details: "Here are the details of what you ordered:" + unpaid_order: "Your order was unpaid so no refund has been made" + paid_order: "Your order was paid so %{distributor} has refunded the full amount" + credit_order: "Your order was paid so your account has been credited" subject: "Cancellation of Order" confirm_email: subject: "Order Confirmation" diff --git a/config/locales/en_DE.yml b/config/locales/en_DE.yml index a847a5bf98..3f65f77b11 100644 --- a/config/locales/en_DE.yml +++ b/config/locales/en_DE.yml @@ -23,6 +23,8 @@ en_DE: base: "Credit Card" order_cycle: orders_close_at: Close date + variant_override: + count_on_hand: "On Hand" errors: models: spree/user: @@ -359,7 +361,6 @@ en_DE: 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: @@ -394,6 +395,7 @@ en_DE: footer_and_external_links: Footer and External Links your_content: Your content user_guide: User Guide + map: Map enterprise_fees: index: title: "Enterprise Fees" @@ -2601,6 +2603,7 @@ en_DE: customer_details: "Customer Details" adjustments: "Adjustments" payments: "Payments" + return_authorizations: "Return Authorizations" payment: "Payment" payment_method: "Payment Method" shipment: "Shipment" @@ -2670,6 +2673,8 @@ en_DE: new_payment: "New Payment" capture: "Capture" void: "Void" + login: "Login" + password: "Password" configurations: "Configurations" general_settings: "General Settings" site_name: "Site Name" @@ -2734,8 +2739,6 @@ en_DE: abbreviation: "Abbreviation" new_state: "New State" payment_methods: "Payment Methods" - new_payment_method: "New Payment Method" - provider: "Provider" taxonomies: "Taxonomies" new_taxonomy: "New Taxonomy" back_to_taxonomies_list: "Back to Taxonomies List" @@ -2904,10 +2907,23 @@ en_DE: categories: "Categories" zones: "Zones" payment_methods: + index: + payment_methods: "Payment Methods" + new_payment_method: "New Payment Method" + name: "Name" + products_distributor: "Distributor" + provider: "Provider" + environment: "Environment" + display: "Display" + active: "Active" + both: "Both" + active_yes: "Yes" + active_no: "No" new: new_payment_method: "New Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" edit: + new: "New" editing_payment_method: "Editing Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" stripe_connect: @@ -2923,6 +2939,17 @@ en_DE: account_id: Account ID business_name: Business Name charges_enabled: Charges Enabled + form: + name: "Name" + description: "Description" + environment: "Environment" + display: "Display" + active: "Active" + active_yes: "Yes" + active_no: "No" + tags: "Tags" + providers: + provider: "Provider" payments: source_forms: stripe: @@ -3012,6 +3039,7 @@ en_DE: price: "Price" display_as: "Display As" autocomplete: + out_of_stock: "Out of Stock" producer_name: "Producer" unit: "Unit" shared: @@ -3076,9 +3104,6 @@ en_DE: 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" diff --git a/config/locales/en_FR.yml b/config/locales/en_FR.yml index 267ab53b2a..e1eaf0fd19 100644 --- a/config/locales/en_FR.yml +++ b/config/locales/en_FR.yml @@ -23,6 +23,8 @@ en_FR: base: "Credit Card" order_cycle: orders_close_at: Close date + variant_override: + count_on_hand: "On Hand" errors: models: spree/user: @@ -368,8 +370,10 @@ en_FR: 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." + matomo_tag_manager_url: "Matomo Tag Manager URL" + info_html: "Matomo is a Web and Mobile Analytics application. You can either host Matomo on-premises or use a cloud-hosted service. See matomo.orgfor 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." + config_instructions_tag_manager_html: "Setting the Matomo Tag Manager URL enables Matomo Tag Manager. This tool allows you to set up analytics events. The Matomo Tag Manager URL is copied from the Install Code section of Matomo Tag Manager. Ensure you select the right container and environment as these options change the URL." customers: index: new_customer: "New Customer" @@ -403,6 +407,7 @@ en_FR: footer_and_external_links: Footer and External Links your_content: Your content user_guide: User Guide + map: Map enterprise_fees: index: title: "Enterprise Fees" @@ -474,6 +479,7 @@ en_FR: 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}" + malformed_csv: "Product Import encountered a malformed CSV: %{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." @@ -2737,6 +2743,7 @@ en_FR: customer_details: "Customer Details" adjustments: "Adjustments" payments: "Payments" + return_authorizations: "Return Authorizations" payment: "Payment" payment_method: "Payment Method" shipment: "Shipment" @@ -2806,6 +2813,14 @@ en_FR: new_payment: "New Payment" capture: "Capture" void: "Void" + login: "Login" + password: "Password" + signature: "Signature" + solution: "Solution" + landing_page: "Landing Page" + server: "Server" + test_mode: "Test Mode" + logourl: "Logourl" configurations: "Configurations" general_settings: "General Settings" site_name: "Site Name" @@ -2870,8 +2885,6 @@ en_FR: abbreviation: "Abbreviation" new_state: "New State" payment_methods: "Payment Methods" - new_payment_method: "New Payment Method" - provider: "Provider" taxonomies: "Taxonomies" new_taxonomy: "New Taxonomy" back_to_taxonomies_list: "Back to Taxonomies List" @@ -2924,6 +2937,12 @@ en_FR: options: "Options" actions: update: "Update" + shared: + error_messages: + errors_prohibited_this_record_from_being_saved: + one: "1 error prohibited this record from being saved:" + other: "%{count} errors prohibited this record from being saved:" + there_were_problems_with_the_following_fields: "There were problems with the following fields" errors: messages: blank: "can't be blank" @@ -3083,10 +3102,26 @@ en_FR: back_end: "Back office only" deactivation_warning: "De-activating a shipping method can make the shipping method disappear from your list. Alternatively, you can hide a shipping method from the checkout page by setting the option 'Display' to 'back office only'." payment_methods: + index: + payment_methods: "Payment Methods" + new_payment_method: "New Payment Method" + name: "Name" + products_distributor: "Distributor" + provider: "Provider" + environment: "Environment" + display: "Display" + active: "Active" + both: "Both" + front_end: "Checkout only" + back_end: "Back office only" + active_yes: "Yes" + active_no: "No" + no_payment_methods_found: "No payment methods found" new: new_payment_method: "New Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" edit: + new: "New" editing_payment_method: "Editing Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" stripe_connect: @@ -3102,6 +3137,21 @@ en_FR: account_id: Account ID business_name: Business Name charges_enabled: Charges Enabled + form: + name: "Name" + description: "Description" + environment: "Environment" + display: "Display" + active: "Active" + active_yes: "Yes" + active_no: "No" + both: "Both Checkout and Back office" + front_end: "Checkout only" + back_end: "Back office only" + tags: "Tags" + deactivation_warning: "De-activating a payment method can make the payment method disappear from your list. Alternatively, you can hide a payment method from the checkout page by setting the option 'Display' to 'back office only'." + providers: + provider: "Provider" payments: source_forms: stripe: @@ -3204,6 +3254,7 @@ en_FR: display_as_placeholder: 'eg. 2 kg' display_name_placeholder: 'eg. Tomatoes' autocomplete: + out_of_stock: "Out of Stock" producer_name: "Producer" unit: "Unit" shared: @@ -3269,9 +3320,14 @@ en_FR: 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]" + customer_greeting: "Dear %{name}," + instructions_html: "Your order with%{distributor} has been CANCELED. Please retain this cancellation information for your records" + dont_cancel: "If you have changed your mind or don't wish to cancel this order please contact %{email}" + order_summary_canceled_html: "Order Summary #%{number}[CANCELED]" + details: "Here are the details of what you ordered:" + unpaid_order: "Your order was unpaid so no refund has been made" + paid_order: "Your order was paid so %{distributor} has refunded the full amount" + credit_order: "Your order was paid so your account has been credited" subject: "Cancellation of Order" confirm_email: subject: "Order Confirmation" diff --git a/config/locales/en_GB.yml b/config/locales/en_GB.yml index c20656fd5d..5d928e780f 100644 --- a/config/locales/en_GB.yml +++ b/config/locales/en_GB.yml @@ -23,6 +23,8 @@ en_GB: base: "Credit Card" order_cycle: orders_close_at: Close date + variant_override: + count_on_hand: "In Stock" errors: models: spree/user: @@ -368,7 +370,6 @@ en_GB: 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: @@ -403,6 +404,7 @@ en_GB: footer_and_external_links: Footer and External Links your_content: Your content user_guide: User Guide + map: Map enterprise_fees: index: title: "Enterprise Fees" @@ -2743,6 +2745,7 @@ en_GB: customer_details: "Customer Details" adjustments: "Adjustments" payments: "Payments" + return_authorizations: "Return Authorisations" payment: "Payment" payment_method: "Payment Method" shipment: "Shipment" @@ -2812,6 +2815,8 @@ en_GB: new_payment: "New Payment" capture: "Capture" void: "Void" + login: "Login" + password: "Password" configurations: "Configurations" general_settings: "General Settings" site_name: "Site Name" @@ -2876,8 +2881,6 @@ en_GB: abbreviation: "Abbreviation" new_state: "New County" payment_methods: "Payment Methods" - new_payment_method: "New Payment Method" - provider: "Provider" taxonomies: "Taxonomies" new_taxonomy: "New Taxonomy" back_to_taxonomies_list: "Back to Taxonomies List" @@ -3089,10 +3092,24 @@ en_GB: back_end: "Back office only" deactivation_warning: "De-activating a shipping method can make the shipping method disappear from your list. Alternatively, you can hide a shipping method from the checkout page by setting the option 'Display' to 'back office only'." payment_methods: + index: + payment_methods: "Payment Methods" + new_payment_method: "New Payment Method" + name: "Name" + products_distributor: "Distributor" + provider: "Provider" + environment: "Environment" + display: "Display" + active: "Active" + both: "Both" + back_end: "Back office only" + active_yes: "Yes" + active_no: "No" new: new_payment_method: "New Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" edit: + new: "New" editing_payment_method: "Editing Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" stripe_connect: @@ -3108,6 +3125,19 @@ en_GB: account_id: Account ID business_name: Business Name charges_enabled: Charges Enabled + form: + name: "Name" + description: "Description" + environment: "Environment" + display: "Display" + active: "Active" + active_yes: "Yes" + active_no: "No" + both: "Both Checkout and Back office" + back_end: "Back office only" + tags: "Tags" + providers: + provider: "Provider" payments: source_forms: stripe: @@ -3210,6 +3240,7 @@ en_GB: display_as_placeholder: 'eg. 2 kg' display_name_placeholder: 'eg. Tomatoes' autocomplete: + out_of_stock: "Out of Stock" producer_name: "Producer" unit: "Unit" shared: @@ -3275,9 +3306,6 @@ en_GB: 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" diff --git a/config/locales/en_IE.yml b/config/locales/en_IE.yml index 6970317b5b..e9b243f1e0 100644 --- a/config/locales/en_IE.yml +++ b/config/locales/en_IE.yml @@ -23,6 +23,8 @@ en_IE: base: "Credit Card" order_cycle: orders_close_at: Close date + variant_override: + count_on_hand: "In Stock" errors: models: spree/user: @@ -368,7 +370,6 @@ en_IE: 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: @@ -403,6 +404,7 @@ en_IE: footer_and_external_links: Footer and External Links your_content: Your content user_guide: User Guide + map: Map enterprise_fees: index: title: "Enterprise Fees" @@ -2742,6 +2744,7 @@ en_IE: customer_details: "Customer Details" adjustments: "Adjustments" payments: "Payments" + return_authorizations: "Return Authorisations" payment: "Payment" payment_method: "Payment Method" shipment: "Shipment" @@ -2811,6 +2814,8 @@ en_IE: new_payment: "New Payment" capture: "Capture" void: "Void" + login: "Login" + password: "Password" configurations: "Configurations" general_settings: "General Settings" site_name: "Site Name" @@ -2875,8 +2880,6 @@ en_IE: abbreviation: "Abbreviation" new_state: "New County" payment_methods: "Payment Methods" - new_payment_method: "New Payment Method" - provider: "Provider" taxonomies: "Taxonomies" new_taxonomy: "New Taxonomy" back_to_taxonomies_list: "Back to Taxonomies List" @@ -3083,10 +3086,23 @@ en_IE: categories: "Categories" zones: "Zones" payment_methods: + index: + payment_methods: "Payment Methods" + new_payment_method: "New Payment Method" + name: "Name" + products_distributor: "Distributor" + provider: "Provider" + environment: "Environment" + display: "Display" + active: "Active" + both: "Both" + active_yes: "Yes" + active_no: "No" new: new_payment_method: "New Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" edit: + new: "New" editing_payment_method: "Editing Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" stripe_connect: @@ -3102,6 +3118,17 @@ en_IE: account_id: Account ID business_name: Business Name charges_enabled: Charges Enabled + form: + name: "Name" + description: "Description" + environment: "Environment" + display: "Display" + active: "Active" + active_yes: "Yes" + active_no: "No" + tags: "Tags" + providers: + provider: "Provider" payments: source_forms: stripe: @@ -3204,6 +3231,7 @@ en_IE: display_as_placeholder: 'eg. 2 kg' display_name_placeholder: 'eg. Tomatoes' autocomplete: + out_of_stock: "Out of Stock" producer_name: "Producer" unit: "Unit" shared: @@ -3268,9 +3296,6 @@ en_IE: 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" diff --git a/config/locales/en_NZ.yml b/config/locales/en_NZ.yml index edd74cbdb3..c3ed978054 100644 --- a/config/locales/en_NZ.yml +++ b/config/locales/en_NZ.yml @@ -23,6 +23,8 @@ en_NZ: base: "Credit Card" order_cycle: orders_close_at: Close date + variant_override: + count_on_hand: "On Hand" errors: models: spree/user: @@ -368,8 +370,10 @@ en_NZ: 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." + matomo_tag_manager_url: "Matomo Tag Manager URL" + info_html: "Matomo is a Web and Mobile Analytics application. 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." + config_instructions_tag_manager_html: "Setting the Matomo Tag Manager URL enables Matomo Tag Manager. This tool allows you to set up analytics events. The Matomo Tag Manager URL is copied from the Install Code section of Matomo Tag Manager. Ensure you select the right container and environment as these options change the URL." customers: index: new_customer: "New Customer" @@ -403,6 +407,7 @@ en_NZ: footer_and_external_links: Footer and External Links your_content: Your content user_guide: User Guide + map: Map enterprise_fees: index: title: "Enterprise Fees" @@ -686,6 +691,7 @@ en_NZ: ofn_uid_tip: The unique id used to identify the enterprise on Open Food Network. shipping_methods: name: "Name" + applies: "Active?" manage: "Manage Shipping Methods" create_button: "Create New Shipping Method" create_one_button: "Create One Now" @@ -2736,6 +2742,7 @@ en_NZ: customer_details: "Customer Details" adjustments: "Adjustments" payments: "Payments" + return_authorizations: "Return Authorizations" payment: "Payment" payment_method: "Payment Method" shipment: "Shipment" @@ -2805,6 +2812,14 @@ en_NZ: new_payment: "New Payment" capture: "Capture" void: "Void" + login: "Login" + password: "Password" + signature: "Signature" + solution: "Solution" + landing_page: "Landing Page" + server: "Server" + test_mode: "Test Mode" + logourl: "Logourl" configurations: "Configurations" general_settings: "General Settings" site_name: "Site Name" @@ -2869,8 +2884,6 @@ en_NZ: abbreviation: "Abbreviation" new_state: "New State" payment_methods: "Payment Methods" - new_payment_method: "New Payment Method" - provider: "Provider" taxonomies: "Taxonomies" new_taxonomy: "New Taxonomy" back_to_taxonomies_list: "Back to Taxonomies List" @@ -2923,6 +2936,12 @@ en_NZ: options: "Options" actions: update: "Update" + shared: + error_messages: + errors_prohibited_this_record_from_being_saved: + one: "1 error prohibited this record from being saved:" + other: "%{count} errors prohibited this record from being saved:" + there_were_problems_with_the_following_fields: "There were problems with the following fields" errors: messages: blank: "can't be blank" @@ -3080,11 +3099,28 @@ en_NZ: zones: "Zones" both: "Both Checkout and Back office" back_end: "Back office only" + deactivation_warning: "De-activating a shipping method can make the shipping method disappear from your list. Alternatively, you can hide a shipping method from the checkout page by setting the option 'Display' to 'back office only'." payment_methods: + index: + payment_methods: "Payment Methods" + new_payment_method: "New Payment Method" + name: "Name" + products_distributor: "Distributor" + provider: "Provider" + environment: "Environment" + display: "Display" + active: "Active" + both: "Both" + front_end: "Checkout only" + back_end: "Back office only" + active_yes: "Yes" + active_no: "No" + no_payment_methods_found: "No payment methods found" new: new_payment_method: "New Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" edit: + new: "New" editing_payment_method: "Editing Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" stripe_connect: @@ -3100,6 +3136,21 @@ en_NZ: account_id: Account ID business_name: Business Name charges_enabled: Charges Enabled + form: + name: "Name" + description: "Description" + environment: "Environment" + display: "Display" + active: "Active" + active_yes: "Yes" + active_no: "No" + both: "Both Checkout and Back office" + front_end: "Checkout only" + back_end: "Back office only" + tags: "Tags" + deactivation_warning: "De-activating a payment method can make the payment method disappear from your list. Alternatively, you can hide a payment method from the checkout page by setting the option 'Display' to 'back office only'." + providers: + provider: "Provider" payments: source_forms: stripe: @@ -3202,6 +3253,7 @@ en_NZ: display_as_placeholder: 'eg. 2 kg' display_name_placeholder: 'eg. Tomatoes' autocomplete: + out_of_stock: "Out of Stock" producer_name: "Producer" unit: "Unit" shared: @@ -3239,6 +3291,7 @@ en_NZ: format: '%Y-%m-%d' js_format: 'yy-mm-dd' orders: + error_flash_for_unavailable_items: "An item in your cart has become unavailable. Please update the selected quantities." edit: login_to_view_order: "Please log in to view your order." bought: @@ -3266,9 +3319,14 @@ en_NZ: 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]" + customer_greeting: "Dear %{name}," + instructions_html: "Your order with %{distributor} has been CANCELED. Please retain this cancellation information for your records." + dont_cancel: "If you have changed your mind or don't wish to cancel this order please contact %{email}" + order_summary_canceled_html: "Order Summary #%{number} [CANCELED]" + details: "Here are the details of what you ordered:" + unpaid_order: "Your order was unpaid so no refund has been made" + paid_order: "Your order was paid so %{distributor} has refunded the full amount" + credit_order: "Your order was paid so your account has been credited" subject: "Cancellation of Order" confirm_email: subject: "Order Confirmation" diff --git a/config/locales/en_PH.yml b/config/locales/en_PH.yml index 884b680f84..2ca3436aa6 100644 --- a/config/locales/en_PH.yml +++ b/config/locales/en_PH.yml @@ -23,6 +23,8 @@ en_PH: base: "Credit Card" order_cycle: orders_close_at: Close date + variant_override: + count_on_hand: "On Hand" errors: models: spree/user: @@ -367,7 +369,6 @@ en_PH: 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: @@ -402,6 +403,7 @@ en_PH: footer_and_external_links: Footer and External Links your_content: Your content user_guide: User Guide + map: Map enterprise_fees: index: title: "Enterprise Fees" @@ -2718,6 +2720,7 @@ en_PH: customer_details: "Customer Details" adjustments: "Adjustments" payments: "Payments" + return_authorizations: "Return Authorizations" payment: "Payment" payment_method: "Payment Method" shipment: "Shipment" @@ -2787,6 +2790,8 @@ en_PH: new_payment: "New Payment" capture: "Capture" void: "Void" + login: "Login" + password: "Password" configurations: "Configurations" general_settings: "General Settings" site_name: "Site Name" @@ -2851,8 +2856,6 @@ en_PH: 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" @@ -3059,10 +3062,23 @@ en_PH: categories: "Categories" zones: "Zones" payment_methods: + index: + payment_methods: "Payment Methods" + new_payment_method: "New Payment Method" + name: "Name" + products_distributor: "Distributor" + provider: "Provider" + environment: "Environment" + display: "Display" + active: "Active" + both: "Both" + active_yes: "Yes" + active_no: "No" new: new_payment_method: "New Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" edit: + new: "New" editing_payment_method: "Editing Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" stripe_connect: @@ -3078,6 +3094,17 @@ en_PH: account_id: Account ID business_name: Business Name charges_enabled: Charges Enabled + form: + name: "Name" + description: "Description" + environment: "Environment" + display: "Display" + active: "Active" + active_yes: "Yes" + active_no: "No" + tags: "Tags" + providers: + provider: "Provider" payments: source_forms: stripe: @@ -3178,6 +3205,7 @@ en_PH: display_as: "Display As" display_name: "Display Name" autocomplete: + out_of_stock: "Out of Stock" producer_name: "Producer" unit: "Unit" shared: @@ -3242,9 +3270,6 @@ en_PH: 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" diff --git a/config/locales/en_US.yml b/config/locales/en_US.yml index e3c8f3950d..d21e17ed10 100644 --- a/config/locales/en_US.yml +++ b/config/locales/en_US.yml @@ -23,6 +23,8 @@ en_US: base: "Credit Card" order_cycle: orders_close_at: Close Date + variant_override: + count_on_hand: "On Hand" errors: models: spree/user: @@ -363,7 +365,6 @@ en_US: 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 locally 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: @@ -398,6 +399,7 @@ en_US: footer_and_external_links: Footer and External Links your_content: Your content user_guide: User Guide + map: Map enterprise_fees: index: title: "Enterprise Fees" @@ -2711,6 +2713,7 @@ en_US: customer_details: "Customer Details" adjustments: "Adjustments" payments: "Payments" + return_authorizations: "Return Authorizations" payment: "Payment" payment_method: "Payment Method" shipment: "Shipment" @@ -2780,6 +2783,8 @@ en_US: new_payment: "New Payment" capture: "Capture" void: "Void" + login: "Login" + password: "Password" configurations: "Configurations" general_settings: "General Settings" site_name: "Site Name" @@ -2844,8 +2849,6 @@ en_US: abbreviation: "Abbreviation" new_state: "New State" payment_methods: "Payment Methods" - new_payment_method: "New Payment Method" - provider: "Provider" taxonomies: "Taxonomies" new_taxonomy: "New Taxonomy" back_to_taxonomies_list: "Back to Taxonomies List" @@ -3052,10 +3055,23 @@ en_US: categories: "Categories" zones: "Zones" payment_methods: + index: + payment_methods: "Payment Methods" + new_payment_method: "New Payment Method" + name: "Name" + products_distributor: "Distributor" + provider: "Provider" + environment: "Environment" + display: "Display" + active: "Active" + both: "Both" + active_yes: "Yes" + active_no: "No" new: new_payment_method: "New Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" edit: + new: "New" editing_payment_method: "Editing Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" stripe_connect: @@ -3071,6 +3087,17 @@ en_US: account_id: Account ID business_name: Business Name charges_enabled: Charges Enabled + form: + name: "Name" + description: "Description" + environment: "Environment" + display: "Display" + active: "Active" + active_yes: "Yes" + active_no: "No" + tags: "Tags" + providers: + provider: "Provider" payments: source_forms: stripe: @@ -3170,6 +3197,7 @@ en_US: display_as: "Display As" display_name: "Display Name" autocomplete: + out_of_stock: "Out of Stock" producer_name: "Producer" unit: "Unit" shared: @@ -3234,9 +3262,6 @@ en_US: 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" diff --git a/config/locales/en_ZA.yml b/config/locales/en_ZA.yml index 225939fb6f..b105c0fc11 100644 --- a/config/locales/en_ZA.yml +++ b/config/locales/en_ZA.yml @@ -23,6 +23,8 @@ en_ZA: base: "Credit Card" order_cycle: orders_close_at: Close date + variant_override: + count_on_hand: "In Stock" errors: models: spree/user: @@ -368,7 +370,6 @@ en_ZA: 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: @@ -403,6 +404,7 @@ en_ZA: footer_and_external_links: Footer and External Links your_content: Your content user_guide: User Guide + map: Map enterprise_fees: index: title: "Enterprise Fees" @@ -2732,6 +2734,8 @@ en_ZA: new_payment: "New Payment" capture: "Capture" void: "Void" + login: "Login" + password: "Password" configurations: "Configurations" general_settings: "General Settings" site_name: "Site Name" @@ -2796,8 +2800,6 @@ en_ZA: abbreviation: "Abbreviation" new_state: "New Province" payment_methods: "Payment Methods" - new_payment_method: "New Payment Method" - provider: "Provider" taxonomies: "Taxonomies" new_taxonomy: "New Taxonomy" back_to_taxonomies_list: "Back to Taxonomies List" @@ -2963,10 +2965,23 @@ en_ZA: categories: "Categories" zones: "Zones" payment_methods: + index: + payment_methods: "Payment Methods" + new_payment_method: "New Payment Method" + name: "Name" + products_distributor: "Distributor" + provider: "Provider" + environment: "Environment" + display: "Display" + active: "Active" + both: "Both" + active_yes: "Yes" + active_no: "No" new: new_payment_method: "New Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" edit: + new: "New" editing_payment_method: "Editing Payment Method" back_to_payment_methods_list: "Back To Payment Methods List" stripe_connect: @@ -2982,6 +2997,17 @@ en_ZA: account_id: Account ID business_name: Business Name charges_enabled: Charges Enabled + form: + name: "Name" + description: "Description" + environment: "Environment" + display: "Display" + active: "Active" + active_yes: "Yes" + active_no: "No" + tags: "Tags" + providers: + provider: "Provider" payments: source_forms: stripe: @@ -3072,6 +3098,7 @@ en_ZA: price: "Price" display_as: "Display As" autocomplete: + out_of_stock: "Out of Stock" producer_name: "Producer" unit: "Unit" shared: @@ -3136,9 +3163,6 @@ en_ZA: 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" diff --git a/config/locales/es.yml b/config/locales/es.yml index b04da91a62..aef7d7c62b 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -23,6 +23,8 @@ es: base: "Tarjeta de crédito" order_cycle: orders_close_at: Fecha de cierre + variant_override: + count_on_hand: "Disponibles" errors: models: spree/user: @@ -323,6 +325,7 @@ es: show_n_more: Mostrar %{num} más choose: "Escoger..." please_select: Por favor selecciona ... + column_save_as_default: Guardar por defecto columns: Columnas actions: Acciones viewing: "Viendo: %{current_view_name}" @@ -367,8 +370,10 @@ es: 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." + matomo_tag_manager_url: "URL de Matomo Tag Manager" + info_html: "Matomo es una aplicación de análisis web y móvil. Puede alojar Matomo localmente o utilizar un servicio alojado en la nube. Ver matomo.org para 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." + config_instructions_tag_manager_html: "La configuración de la URL de Matomo Tag Manager habilita Matomo Tag Manager. Esta herramienta le permite configurar eventos analíticos. La URL de Matomo Tag Manager se copia de la sección Código de instalación de Matomo Tag Manager. Asegúrese de seleccionar el contenedor y el entorno correctos, ya que estas opciones cambian la URL." customers: index: new_customer: "Nuevo Consumidor" @@ -402,6 +407,7 @@ es: footer_and_external_links: Pie de página y enlaces externos your_content: Tu contenido user_guide: Manual de Usuario + map: Mapa enterprise_fees: index: title: "Comisiones de la Organización" @@ -473,6 +479,7 @@ es: 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}" + malformed_csv: "La importación de producto encontró un CSV con formato incorrecto: %{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." @@ -686,6 +693,7 @@ es: ofn_uid_tip: La identificación única utilizada para identificar la organización en Open Food Network. shipping_methods: name: "Nombre" + applies: "¿Activo?" manage: "Gestionar métodos de envío" create_button: "Crear nuevo método de envío" create_one_button: "Crear una ahora" @@ -865,6 +873,7 @@ es: incoming: "Entrante" supplier: "Proveedora" products: "Productos" + receival_details: "Detalles de la recepción" fees: "Comisiones" save: "Guardar" save_and_next: "Salvar y continuar" @@ -1174,7 +1183,11 @@ es: signup: "Regístrate" contact: "contactar" require_customer_login: "Sólo las consumidoras aprobadas pueden acceder a esta tienda." + require_login_html: "Si ya eres un cliente aprovado, %{login} o %{signup} para continuar" + require_login_2_html: "¿Quieres comprar en esta tienda? %{contact}%{enterprise}y solicita tu admisión." require_customer_html: "Si desea comenzar a comprar aquí, por favor %{contact} %{enterprise} para preguntar acerca de incorporación." + select_oc: + select_oc_html: "Por favor debes elegir cuando quieres tu pedido, para poder ver qué productos hay disponibles." 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 tu información de pago: %{error}" @@ -1534,12 +1547,17 @@ es: orders_changeable_orders_alert_html: Este pedido ha sido confirmado, pero puede realizar cambios hasta %{oc_close}. products_clear: Limpiar products_showing: "Mostrando:" + products_results_for: "Resultados para" products_or: "o" products_and: "y" + products_filters_in: "en" products_with: con + products_search: "Buscar…" products_filter_by: "Fitrar por" products_filter_selected: "seleccionado" + products_filter_heading: "Filtros" products_filter_clear: "Limpiar" + products_filter_done: "Hecho" products_loading: "Cargando productos..." products_updating_cart: "Actualizando su carrito..." products_cart_empty: "Carrito vacío" @@ -1550,6 +1568,8 @@ es: 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." + products_no_results_html: "Lo sentimos, no se han encontrado resultados para %{query}" + products_clear_search: "Limpiar la búsqueda" 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" @@ -1905,6 +1925,7 @@ es: 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: "Redes de organizaciones" admin_enterprise_groups_name: "Nombre" admin_enterprise_groups_owner: "Propietaria" @@ -2310,6 +2331,10 @@ es: resolve_errors: Resuelve los siguientes errores more_items: "+ %{count} Más" default_card_updated: Tarjeta predeterminada actualizada + cart: + add_to_cart_failed: > + Ha habido un problema al añadir este producto en el carrito. Puede que haya + dejado de estar disponible o que la tinda haya cerrado. admin: enterprise_limit_reached: "Has alcanzado el límite estándar de organizaciones por cuenta. Escriba a %{contact_email} si necesita aumentarlo." modals: @@ -2724,6 +2749,7 @@ es: customer_details: "Detalles de la consumidora" adjustments: "Ajustes" payments: "Pagos" + return_authorizations: "Autorizaciones de devolución" payment: "Pago" payment_method: "Método de pago" shipment: "Envío" @@ -2793,6 +2819,14 @@ es: new_payment: "Nuevo pago" capture: "Captura" void: "Vacío" + login: "Iniciar sesión" + password: "Contraseña" + signature: "Firma" + solution: "Solución" + landing_page: "Página de inicio" + server: "Servidor" + test_mode: "Modo de prueba" + logourl: "URL del logo" configurations: "Configuraciones" general_settings: "Configuración general" site_name: "Nombre del sitio" @@ -2857,8 +2891,6 @@ es: abbreviation: "Abreviatura" new_state: "Nuevo estado" payment_methods: "Métodos de Pago" - new_payment_method: "Nuevo método de pago" - provider: "Proveedor" taxonomies: "Taxonomias" new_taxonomy: "Nueva taxonomía" back_to_taxonomies_list: "Volver a la Lista de Taxonomías" @@ -2911,6 +2943,12 @@ es: options: "Opciones" actions: update: "Actualizar" + shared: + error_messages: + errors_prohibited_this_record_from_being_saved: + one: "1 error prohibió guardar este registro:" + other: "%{count} errores impidieron que se guardara este registro:" + there_were_problems_with_the_following_fields: "Hubo problemas con los siguientes campos" errors: messages: blank: "no puede estar vacío" @@ -3053,6 +3091,8 @@ es: zone: "Zona" calculator: "Calculadora" display: "Mostrar" + both: "Tanto en Hacer pedido como en Administración" + back_end: "Solo en Administración" no_shipping_methods_found: "No se encontraron métodos de envío" new: new_shipping_method: "Nuevo método de envío" @@ -3064,11 +3104,30 @@ es: form: categories: "Categorías" zones: "Zonas" + both: "Tanto en Hacer pedido como en Administración" + back_end: "Solo en Administración" + deactivation_warning: "Desactivar un método de envío puede hacer que el método de envío desaparezca de tu lista. Como alternativa, puedes ocultar el método de envío de la página \"Hacer pedidos\" configurándolo con la opción \"Solo en Administración\" " payment_methods: + index: + payment_methods: "Métodos de Pago" + new_payment_method: "Nuevo método de pago" + name: "Nombre" + products_distributor: "Distribuidora" + provider: "Proveedor" + environment: "Ambiente" + display: "Mostrar" + active: "Activo" + both: "Ambos" + front_end: "Solo visible para el comprador" + back_end: "Solo en Administración" + active_yes: "Sí" + active_no: "No" + no_payment_methods_found: "No se encontraron métodos de pago." new: new_payment_method: "Nuevo método de pago" back_to_payment_methods_list: "Volver a la lista de métodos de pago" edit: + new: "Nuevo" 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: @@ -3084,6 +3143,21 @@ es: account_id: Account ID business_name: Nombre de la Organización charges_enabled: Cargos habilitados + form: + name: "Nombre" + description: "Descripción" + environment: "Ambiente" + display: "Mostrar" + active: "Activo" + active_yes: "Sí" + active_no: "No" + both: "Tanto en Hacer pedido como en Administración" + front_end: "Solo visible para el comprador" + back_end: "Solo en Administración" + tags: "Tags" + deactivation_warning: "La desactivación de un método de pago puede hacer que el método de pago desaparezca de su lista. Alternativamente, puede ocultar un método de pago desde la página de pago configurando la opción 'Mostrar' como 'Solo visible para el administrador'." + providers: + provider: "Proveedor" payments: source_forms: stripe: @@ -3183,7 +3257,10 @@ es: price: "Precio" display_as: "Mostrar como" display_name: "Nombre para mostrar" + display_as_placeholder: 'p. ej. 2 Kg' + display_name_placeholder: 'p. ej. Tomates' autocomplete: + out_of_stock: "Agotado" producer_name: "Productora" unit: "Unidad" shared: @@ -3221,6 +3298,7 @@ es: format: '%Y-%m-%d' js_format: 'yy-mm-dd' orders: + error_flash_for_unavailable_items: "Un artículo de tu carrito ahora no está disponible. Por favor actualiza las cantidades seleccionadas" edit: login_to_view_order: "Por favor inicie sesión para ver su pedido." bought: @@ -3248,9 +3326,14 @@ es: 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]" + customer_greeting: "Hola %{name}" + instructions_html: "Tu pedido con %{distributor} ha sido CANCELADO. Por favor guarda esta información de la cancelación por si es necesaria en el futuro. " + dont_cancel: "Si has cambiado de opinión o no deseas cancelar este pedido, por favor contacta con %{email}" + order_summary_canceled_html: "Resumen del pedido [CANCELADO] %{number} " + details: "Estos son los detalles de su pedido:" + unpaid_order: "Como su pedido no se había pagado, no se ha hecho ninguna devolución." + paid_order: "Su pedido estaba pagado por lo que %{distributor}ha devuelto el importe completo." + credit_order: "Su pedido estaba pagado por lo que se ha abonado en su cuenta." subject: "Cancelación del pedido" confirm_email: subject: "Confirmación del pedido" diff --git a/config/locales/es_CR.yml b/config/locales/es_CR.yml index 660a0744c1..891c34c21b 100644 --- a/config/locales/es_CR.yml +++ b/config/locales/es_CR.yml @@ -23,6 +23,8 @@ es_CR: base: "Tarjeta de crédito" order_cycle: orders_close_at: Fecha de cierre + variant_override: + count_on_hand: "Disponibles" errors: models: spree/user: @@ -368,7 +370,6 @@ es_CR: 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: @@ -403,6 +404,7 @@ es_CR: footer_and_external_links: Pie de página y enlaces externos your_content: Tu contenido user_guide: Manual de usuario + map: Mapa enterprise_fees: index: title: "Comisiones de la organización" @@ -2726,6 +2728,7 @@ es_CR: customer_details: "Detalles del cliente" adjustments: "Ajustes" payments: "Pagos" + return_authorizations: "Autorizaciones de devolución" payment: "Pago" payment_method: "Método de pago" shipment: "Envío" @@ -2795,6 +2798,8 @@ es_CR: new_payment: "Nuevo pago" capture: "Captura" void: "Vacío" + login: "Iniciar sesión" + password: "Contraseña" configurations: "Configuraciones" general_settings: "Configuración general" site_name: "Nombre del sitio" @@ -2859,8 +2864,6 @@ es_CR: 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" @@ -3067,10 +3070,23 @@ es_CR: categories: "Categorías" zones: "Zonas" payment_methods: + index: + payment_methods: "Métodos de pago" + new_payment_method: "Nuevo método de pago" + name: "Nombre" + products_distributor: "Distribuidor" + provider: "Proveedor" + environment: "Ambiente" + display: "Mostrar" + active: "Activo" + both: "Ambos" + active_yes: "Sí" + active_no: "No" new: new_payment_method: "Nuevo método de pago" back_to_payment_methods_list: "Volver a la lista de métodos de pago" edit: + new: "Nuevo" 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: @@ -3086,6 +3102,17 @@ es_CR: account_id: ID de cuenta business_name: Nombre de la organización charges_enabled: Cargos habilitados + form: + name: "Nombre" + description: "Descripción" + environment: "Ambiente" + display: "Mostrar" + active: "Activo" + active_yes: "Sí" + active_no: "No" + tags: "Etiquetas" + providers: + provider: "Proveedor" payments: source_forms: stripe: @@ -3186,6 +3213,7 @@ es_CR: display_as: "Mostrar como" display_name: "Nombre para mostrar" autocomplete: + out_of_stock: "Agotado" producer_name: "Productor" unit: "Unidad" shared: @@ -3250,9 +3278,6 @@ es_CR: 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" diff --git a/config/locales/fil_PH.yml b/config/locales/fil_PH.yml index 25d2da2a32..6bf53bd65f 100644 --- a/config/locales/fil_PH.yml +++ b/config/locales/fil_PH.yml @@ -23,6 +23,8 @@ fil_PH: base: "Credit Card" order_cycle: orders_close_at: petsa ng pagsasara + variant_override: + count_on_hand: "on hand" errors: models: spree/user: @@ -368,7 +370,6 @@ fil_PH: 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: @@ -403,6 +404,7 @@ fil_PH: footer_and_external_links: Footer at panlabas na mga link your_content: ang iyong nilalaman user_guide: gabay sa gumagamit + map: Mapa enterprise_fees: index: title: "fees para sa Enterprise" @@ -521,9 +523,9 @@ fil_PH: validation_overview: pagtingin sa pagpapatunay ng paglipat entries_found: 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 lilikhain + products_to_create: ang mga produkto ay gagawain products_to_update: ang mga produkto ay i-a-update - inventory_to_create: ang imbentaryo ng mga item ay lilikhain + inventory_to_create: ang imbentaryo ng mga item ay gagawain inventory_to_update: ang mga imbentaryong item ay i-a-update products_to_reset: ang mga produkto ay mari-reset ang stock sa zero inventory_to_reset: ang imbentaryo ng mga item ay mari-reset ang stock sa zero @@ -536,7 +538,7 @@ fil_PH: 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 nalikha + products_created: ang mga produkto ay nagawa na products_updated: in-update ang mga produkto inventory_created: ang mga imbentaryo ng item ay nagawa na inventory_updated: inupdate ang mga inimbentaryong item @@ -636,7 +638,7 @@ fil_PH: fee_type: uri ng fee manage_fees: pamahalaan ang fees para sa enterprise no_fees_yet: wala ka pang kahit anong fees para sa enterprise - create_button: lumikha ng isa ngayon + create_button: gumawa ng isa ngayon images: logo: Logo promo_image_placeholder: 'ang larawan na ito ay makikita sa "tungkol sa amin"' @@ -659,8 +661,8 @@ fil_PH: applies: naaangkop? manage: pamahalaan ang mga paraan ng pagbabayad no_method_yet: wala ka pang kahit anong paraan ng pagbabayad. - create_button: lumikha ng bagong paraan ng pagbabayad - create_one_button: lumikha ng isa ngayon + 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 @@ -680,7 +682,7 @@ fil_PH: visible: nakikita not_visible: hindi nakikita permalink: Permalink (walang espasyo) - permalink_tip: "ang permalink na ito ay ginamit para lumikha ng url sa inyong shop: %{link}your-shop-name/shop" + 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 @@ -688,8 +690,8 @@ fil_PH: shipping_methods: name: "pangalan" manage: "pamahalaan ang mga paraan ng pagpapadala" - create_button: "lumikha ng bagong paraan ng pagpapadala" - create_one_button: "lumikha ng isa ngayon" + 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?" @@ -837,7 +839,7 @@ fil_PH: immediate_removal_warning: "ang promo na larawan ay tatanggalin agad pagkatapos mong magkumpirma." welcome: welcome_title: Welcome sa Open Food Network! - welcome_text: matagumpay mong nalikha ang + welcome_text: matagumpay mong nagawa ang next_step: sunod na hakbang choose_starting_point: 'pumili ng package:' profile: 'profile' @@ -850,7 +852,7 @@ fil_PH: loading_order_cycles: NILO-LOAD ANG MGA ORDER CYCLE loading: NILO-LOAD... new: - create: "lumikha" + create: "gumawa" cancel: "kanselahin" back_to_list: "bumalik sa listahan" edit: @@ -970,7 +972,7 @@ fil_PH: has_no_shipping_methods: "%{enterprise}ay walang paraan ng pagpapadala" has_no_enterprise_fees: "%{enterprise}ay walang fees para sa enterpise" enterprise_issues: - create_new: lumikha ng bago + create_new: gumawa ng bago resend_email: ipadala muli ang email has_no_payment_methods: "%{enterprise}ay kasalukuyang walang mga paraan ng pagbabayad" has_no_shipping_methods: "%{enterprise}ay kasalukuyang walang mga paraan ng pagpapadala" @@ -1029,7 +1031,7 @@ fil_PH: subscriptions: subscriptions: mga subscription new: bagong subscription - create: lumikha ng subscription + create: gumawa ng subscription edit: i-edit ang subscription table: edit_subscription: i-edit ang subscription @@ -1046,9 +1048,9 @@ fil_PH: set_up_shipping_and_payment_methods_html: iset-up ang paraan ng%{shipping_link}at%{payment_link} set_up_shipping_and_payment_methods_note_html: tandaan na Cash at Stripe na pamamaraan lamang 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: lumikha ng kahit isang iskedyul + 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. lumikha ng order cycle kung hindi pa ito nagagawa + 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 mong%{reload_this_page_link} reload_this_page: i-reload ang pahina na ito @@ -1098,7 +1100,7 @@ fil_PH: cancel_failure_msg: "paumanhin ngunit hindi naging matagumpay ang pagkansela!" 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 lilikhain para sa customer. sigurado ka bang nais mong ipagpatuloy ang subscription?" + 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 naabisuhang ang order ay magpapatuloy. nais mo bang kanselahin 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." @@ -1421,7 +1423,7 @@ fil_PH: 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_confirmed: "Maraming 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." @@ -1434,9 +1436,9 @@ fil_PH: 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_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_details_html: "narito ang mga detalye ng inyong 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}!" @@ -1452,34 +1454,34 @@ fil_PH: 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_intro_html: "mayroon kang bagong order kasama ang%{distributor}" + email_so_placement_details_html: "narito ang mga detalye ng inyong 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_placement_explainer_html: "ang order na ito ay awtomatikong ginawa 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_contact_distributor_to_change_order_html: "Ang order na ito ay awtomatikong ginawa para sa iyo. Maaari kang gumawa ng mga pagbabago hanggang magsara ang mga order sa%{orders_close_at} sa pamamagitan ng pakikipag-ugnayan 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_so_failed_payment_intro_html: "sinubukan naming iproseso ang isang bayad ngunit nagkaroon ng ilang problema.." + email_so_failed_payment_explainer_html: "ang bayad para sa iyong subscription kasama ang%{distributor} ay hindi nagpatuloy dahil sa problema sa inyong credit card.%{distributor} ay inabisuhan na ukol sa naudlot na bayad na ito." + email_so_failed_payment_details_html: "ito ang mga detalye na ibinigay ng payment gateway kung bakit hindi nagpatuloy ang bayad :" 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_details: mga detalye ng pangongolekta email_shipping_collection_time: "handa para sa koleksyon:" - email_shipping_collection_instructions: "tagubilin sa pangongolekta:" + email_shipping_collection_instructions: "panuto 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_confirmed_email: "maraming 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}" @@ -1487,15 +1489,15 @@ fil_PH: 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." + set_a_password: "pagkatapos 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_greeting: "Minamahal naming" 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_delivery_instructions: "panuto 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_closed_description: "maghintay sa susunod na pagbukas ng cycle( o makipag-uganayan sa amin nang 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..." @@ -1566,10 +1568,10 @@ fil_PH: groups_hubs: "ang aming mga hub" groups_contact_web: Makipag-ugnayan groups_contact_social: sumunod - groups_contact_address: tirahan + groups_contact_address: Address groups_contact_email: i-email kami groups_contact_website: bisitahin ang aming website - groups_contact_facebook: sundan kami sa Facebook + groups_contact_facebook: i-follow 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." @@ -1598,14 +1600,14 @@ fil_PH: producers_filter: i-filter gamit ang producers_filter_type: uri producers_filter_property: ari-arian - producers_title: Producers + producers_title: Mga Producer 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_headline: mga Producer ng pagkain, mas pinalakas. + producers_signup_motivation: Ibenta ang inyong pagkain at magkipag-ugnayan sa iba't ibang mga 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_studies: mga kwento mula sa aming mga producer producers_signup_cta_headline: sumali ngayon! producers_signup_cta_action: sumali ngayon producers_signup_detail: 'ito ang mga detalye:' @@ -1621,14 +1623,14 @@ fil_PH: 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_producers: "Mga Producer" + sell_hubs: "mga Hub" 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_listing_price: "ang pagpapalista sa OFN ay libre. ang pagbubukas at pagpapatakbo ng shop ay libre hanggang sa PHP 5000 na buwanang benta. kung makakabenta ka ng mas marami, maaari kang mamili ng kontribusyon sa komunidad sa pagitan ng 1.5% 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 @@ -1674,7 +1676,7 @@ fil_PH: 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" + order_processed_successfully: "ang inyong order ay matagumpay na naproseso" 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}." @@ -1695,7 +1697,7 @@ fil_PH: 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: "hindi nagtagumpay sa paggawa ng inyong 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?" @@ -1743,7 +1745,7 @@ fil_PH: steps: introduction: registration_greeting: "Kumusta?" - registration_intro: "maaari ka ng lumikha ng profile para sa inyong Producer o Hub" + 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" @@ -1796,7 +1798,7 @@ fil_PH: 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 at/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, retailer, wholesaler o iba pa." - create_profile: "lumikha ng profile" + create_profile: "gumawa ng profile" about: title: "tungkol sa" headline: "binabati kita!" @@ -1821,12 +1823,12 @@ fil_PH: continue: "Magpatuloy" back: "bumalik" logo: - select_logo: "hakbang 1, pumili ng larawan ng 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_label: "pumili ng larawan para sa 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" + review_logo_tip: "Tip: para sa mas maayos na resulta, ang logo ay dapat matakpan 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" @@ -1841,9 +1843,9 @@ fil_PH: 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" + website_placeholder: "hal. openfoodnetwork.ph" facebook: "Facebook" - facebook_placeholder: "hal. www.facebook.com/pangalanngpahina" + facebook_placeholder: "hal. www.facebook.com/PageNameHere" linkedin: "LinkedIn" linkedin_placeholder: "hal. www.linkedin.com/YourNameHere" twitter: "Twitter" @@ -1862,7 +1864,7 @@ fil_PH: action: "pumunta sa dashboard ng Enterprise" back: "bumalik" continue: "Magpatuloy" - action_or: "O" + action_or: "OR" enterprise_limit: Limitasyon ng enterprise shipping_method_destroy_error: "ang paraan ng pagpapadala ay hindi maaaring tanggalin sapagkat ito ay nakasangguni na sa isang order:%{number}." fees: "fees" @@ -1883,7 +1885,7 @@ fil_PH: price_graph: "graph ng presyo" included_tax: "kasamang tax" balance: "Balanse" - transaction: "transaksyon" + transaction: "transaksiyon" transaction_date: "petsa" payment_state: "status ng bayad" shipping_state: "status ng pagpapadala" @@ -1903,23 +1905,23 @@ fil_PH: 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_permits: "pinapayagan" admin_enterprise_relationships_seach_placeholder: "hanapin" admin_enterprise_relationships_button_create: "gumawa" admin_enterprise_relationships_to: "sa" admin_enterprise_groups: "mga grupo ng enterprise" - admin_enterprise_groups_name: "pangalan" + 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_enterprise: "Mga Enterprise" 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_logo: "ito ang logo para sa 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_address1_placeholder: "eg. 123 Kalayaan Street" admin_enterprise_groups_contact_city: "lungsod" - admin_enterprise_groups_contact_city_placeholder: "hal. Northcote" + admin_enterprise_groups_contact_city_placeholder: "hal. Mandaluyong" admin_enterprise_groups_contact_zipcode: "Postcode" admin_enterprise_groups_contact_zipcode_placeholder: "hal. 3070" admin_enterprise_groups_contact_state_id: "Lalawigan" @@ -1946,7 +1948,7 @@ fil_PH: 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" + calculator_settings_warning: "kung papalitan ang uri ng calculator, dapat ay mag-save muna bago maisa-ayos 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)" @@ -1989,7 +1991,7 @@ fil_PH: 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_enterprises_create_new_product: "LUMIKHA 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: "kailangan ng aksyon" @@ -2003,9 +2005,9 @@ fil_PH: 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_admin_single_enterprise_hint: "payo: para mahanap ka ng ibang tao, i-turn on ang visibility sa ilalim ng" + spree_admin_eg_pickup_from_school: "hal. 'Pick-up mula sa Primary School'" + spree_admin_eg_collect_your_order: "hal. 'Kolektahin ang inyong order sa 123 Kapayapaan St., Tobias Fornier, Antique 5716'" 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." @@ -2023,34 +2025,34 @@ fil_PH: 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" + edit_profile_details: "i-edit ang mga detalye ng profile" + edit_profile_details_etc: "palitan ang paglalarawan ng profile, larawan at iba pa" order_cycle: "order cycle" - order_cycles: "order cycles" + order_cycles: "mga order cycle" 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." + enterprise_tos_link_text: "Mga Tuntunin ng Serbisyo." + enterprise_tos_agree: "ako ay sumasang-ayon sa mga tuntunin 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_1: "address" 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_hubs: "Mga Hub" 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_supplier: "Supplier" report_customers_cycle: "order cycle" report_customers_type: "uri ng ulat" report_customers_csv: "i-download bilang csv" @@ -2072,12 +2074,12 @@ fil_PH: report_header_user: User report_header_email: email report_header_status: Status - report_header_comments: mga puna + report_header_comments: mga komento report_header_first_name: Pangalan report_header_last_name: Apelyido report_header_phone: telepono report_header_suburb: lungsod - report_header_address: tirahan + report_header_address: address report_header_billing_address: Billing Address report_header_relationship: relasyon report_header_hub: Hub @@ -2185,7 +2187,7 @@ fil_PH: 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_total_units: kabuuang mga 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})" @@ -2199,7 +2201,7 @@ fil_PH: report_header_total_untaxable_fees: kabuuang fees na untaxable (walang tax) report_header_total_taxable_fees: kabuuang fees na taxable (may kasamang tax) report_header_delivery_shipping_cost: bayad sa pagdeliver ng pinapadala (kasama ang tax) - report_header_transaction_fee: Bayad sa Transaksyon (walang tax) + report_header_transaction_fee: Bayad sa Transaksiyon (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:" @@ -2208,7 +2210,7 @@ fil_PH: account_code: "code ng Account:" equals: "katumbas" contains: "naglalaman" - discount: "Diskwento" + discount: "Diskuwento" filter_products: "i-filter ang mga produkto" delete_product_variant: "ang huling mga variant ay hindi matanggal!" progress: "progreso" @@ -2217,8 +2219,8 @@ fil_PH: 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" + products_unsaved: "ang mga pagbabagong ginawa sa%{n} mga 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" @@ -2244,15 +2246,15 @@ fil_PH: 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_relationship_already_established: "^ang relasyon na iyan 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_name_error: "ay nakuha na. kung ito ay iyong enterprise at nais mong kunin ang pagmamay-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 magmay-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" @@ -2279,11 +2281,11 @@ fil_PH: 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." + enterprise_shop_show_error: "ang shop na hinahanap mo ay wala o hindi aktibo sa OFN. Maaaring tignan ang ibang mga shop." 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_clone_notice: "ang iyong order cyle %{name}ay nakopya na." 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." @@ -2303,7 +2305,7 @@ fil_PH: 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." + oh_no: "paumanhin! 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 @@ -2315,7 +2317,7 @@ fil_PH: 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." + enterprise_limit_reached: "naabot mo na ang pamantayang 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" @@ -2423,7 +2425,7 @@ fil_PH: shop sa Open Food Network. non_producer: Hindi producer non_producer_text1: > - ang mga hindi producer ay hindi gumagawa ng sarili nilang pagkain, nangangahulgang + ang mga hindi producer ay hindi gumagawa ng sarili nilang pagkain, nangangahulugang wala silang kakayahang gumawa ng sariling mga produkto na maibebenta sa Open Food Network. non_producer_text2: > @@ -2431,7 +2433,7 @@ fil_PH: 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 + producer_example: hal. NAGTATANIM, PANADERO, MANGANGALAKAL, YUMAYARI non_producer_desc: Iba pang mga enterprise ng pagkain non_producer_example: hal. Grocery, Food co-ops, Buying groups enterprise_status: @@ -2447,13 +2449,13 @@ fil_PH: 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:" + shipping_method_tagged_bottom: "ay ang mga:" + payment_method_tagged_top: "naka-tag na mga paraan ng pagbabayad" + payment_method_tagged_bottom: "ay ang mga:" order_cycle_tagged_top: "naka-tag na mga Order Cycle" - order_cycle_tagged_bottom: "ay:" + order_cycle_tagged_bottom: "ay ang mga:" inventory_tagged_top: "nakatag- na mga uri ng imbentaryo" - inventory_tagged_bottom: "ay:" + inventory_tagged_bottom: "ay ang mga:" new_tag_rule_dialog: select_rule_type: "pumili ng uri ng panuntunan:" add_rule: "magdagdag ng panuntunan" @@ -2463,12 +2465,12 @@ fil_PH: 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" + compiling_invoices: "tinitipon ang mga invoice" + bulk_invoice_created: "nakagawa ng Bulk invoice" + bulk_invoice_failed: "hindi nagtagumpay sa paggawa ng Bulk invoice" please_wait: "hintayin na maihanda ang PDF bago isara ang modal na ito." order_state: - address: "tirahan" + address: "address" adjustments: "mga pagsasaayos" awaiting_return: "naghihintay ng pagbalik" canceled: "kanselado" @@ -2507,23 +2509,23 @@ fil_PH: 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" + adding_a_new_schedule: "nagdadagdag ng Bagong Iskedyul" + updating_a_schedule: "ina-update ang iskedyul" + create_schedule: "gumawa ng iskedyul" update_schedule: "i-update ang iskedyul" - delete_schedule: "burahin ang iskedyul" + delete_schedule: "tanggalin 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" + name_required_error: "Maglagay ng pangalan 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}" + add_a_new_customer_for: "magdadag ng bagong customer para sa%{shop_name}" customer_placeholder: "customer@example.org" valid_email_error: "maglagay ng valid na email address" subscriptions: @@ -2728,11 +2730,12 @@ fil_PH: 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" + order_details: "mga detalye ng order" + customer_details: "mga detalye ng customer" adjustments: "mga pagsasa-ayos" payments: "mga bayad" - payment: "kabayaran" + return_authorizations: "mga awtorisasyon sa pagbabalik" + payment: "bayad" payment_method: "paraan ng pagbayad" shipment: "kargamento" shipment_inc_vat: "kargamento kasama ang VAT" @@ -2778,7 +2781,7 @@ fil_PH: cannot_set_shipping_method_without_address: "hindi mai-set ang paraan ng pagpapadala 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_details: "mga detalye ng customer" customer_search: "paghanap ng customer" choose_a_customer: "pumili ng customer" account: "Account" @@ -2801,6 +2804,8 @@ fil_PH: new_payment: "Bagong Pagbabayad" capture: "kunan" void: "walang bisa" + login: "Login" + password: "Password" configurations: "mga pagsasaayos" general_settings: "Pangkalahatang Setting" site_name: "Pangalan ng site" @@ -2843,7 +2848,7 @@ fil_PH: tax rate: "rate ng mga tax" new_tax_rate: "bagong rate ng tax" tax_category: "kategorya ng tax" - rate: "rate" + rate: "antas" 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" @@ -2853,7 +2858,7 @@ fil_PH: new_zone: "bagong sona" default_tax: "default na tax" default_tax_zone: "default na sona ng tax" - country_based: "Country Based" + country_based: "nakabase sa bansa" state_based: "Nakabase sa Lalawigan" countries: "Mga Bansa" listing_countries: "Listahan ng mga Bansa" @@ -2865,8 +2870,6 @@ fil_PH: abbreviation: "Pinaikli" new_state: "Bagong Status" 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" @@ -2941,8 +2944,8 @@ fil_PH: configuration: "pagbabago" users: "mga gumagamit" roles: "mga tungkulin" - order_cycles: "order cycles" - enterprises: "enterprises" + order_cycles: "mga order cycle" + enterprises: "mga enterprise" enterprise_relationships: "mga pahintulot" customers: "mga customer" groups: "mga grupo" @@ -3073,10 +3076,23 @@ fil_PH: categories: "mga kategorya" zones: "mga sona" payment_methods: + index: + payment_methods: "Mga Paraan ng Pagbabayad" + new_payment_method: "Bagong Paraan ng pagbabayad" + name: "Pangalan" + products_distributor: "Distributor" + provider: "tagapagbigay ng serbisyo" + environment: "kapaligiran" + display: "Ipakita" + active: "aktibo" + both: "pareho" + active_yes: "Oo" + active_no: "Hindi" new: new_payment_method: "Bagong Paraan ng pagbabayad" back_to_payment_methods_list: "bumalik sa listahan ng mga paraan ng pagbabayad" edit: + new: "Bago" editing_payment_method: "iayos ang paraan ng pagbabayad" back_to_payment_methods_list: "bumalik sa listahan ng mga paraan ng pagbabayad" stripe_connect: @@ -3092,6 +3108,17 @@ fil_PH: account_id: Account ID business_name: pangalan ng negosyo charges_enabled: pinagana ang paniningil + form: + name: "Pangalan" + description: "paglalarawan" + environment: "kapaligiran" + display: "Ipakita" + active: "aktibo" + active_yes: "Oo" + active_no: "Hindi" + tags: "tags" + providers: + provider: "tagapagbigay ng serbisyo" payments: source_forms: stripe: @@ -3192,6 +3219,7 @@ fil_PH: display_as: "Ipakita Bilang" display_name: "Pangalan na nakikita" autocomplete: + out_of_stock: "Walang stock" producer_name: "Producer" unit: "yunit" shared: @@ -3256,9 +3284,6 @@ fil_PH: invalid: invalid order_mailer: cancel_email: - customer_greeting: "hi %{name}!" - instructions: "ang iyong order ay NAKANSELA. Panatilihin ang impormasyon na ito ng kanselasyon para sa inyong talaan." - order_summary_canceled: "Buod ng order [KANSELADO]" subject: "Pagkansela ng order" confirm_email: subject: "Kumpirmasyon ng order" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 9e2bd0597e..1e2e368003 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -23,6 +23,8 @@ fr: base: "Carte de crédit" order_cycle: orders_close_at: Date de fermeture + variant_override: + count_on_hand: "En stock" errors: models: spree/user: @@ -368,8 +370,10 @@ fr: title: "Configuration Matomo" matomo_url: "URL de l'instance sur Matomo" matomo_site_id: "ID de l'instance sur Matomo" - info_html: "Matomo est un outil d'analyse de trafic web (ordinateur et téléphone). Vous pouvez installer vous-même Matomo ou utiliser une version hébergée. Voir matomo.org pour plus d'information." + matomo_tag_manager_url: "URL du Matomo Tag Manager" + info_html: "Matomo est un outil de suivi de traffic et de comportement des utilisateurs. Matomo est open source et validée par la CNIL française car non intrusif dans les données personnelles des utilisateurs. Pour plus d'infos : matomo.org." config_instructions_html: "Pour utiliser Matomo, vous devez configurer l'intégration avec Open Food France. L'URL de l'instance sur Matomo correspond à l'url du site internet visé par le suivi de la navigation utilisateur. Si le champ est vide, Matomo n'effectuera aucune analyse sur ce site. L'ID de l'instance sur Matomo n'est pas obligatoire, mais nécessaire si vous souhaitez analyser plusieurs sites web sur une seule instance Matomo. Cet ID peut être trouvé sur l'espace administrateur Matomo." + config_instructions_tag_manager_html: "Ajouter l'URL du Tag Manager rend actif Matomo Tag Manager. Cet outil vous permet de suivre des évènements en particulier. Pour trouver l'URL rendez-vous sur l' \"Install Code section\" du Tag Manager. Attention à bien copier le bon contener et le bon environnement, car ils font varier l'URL." customers: index: new_customer: "Nouvel acheteur" @@ -403,6 +407,7 @@ fr: footer_and_external_links: Pied de page et Liens Externes your_content: Votre contenu user_guide: Guide utilisateur + map: Carte enterprise_fees: index: title: "Marges et Commissions" @@ -474,6 +479,7 @@ fr: line_number: "Ligne %{number} :" encoding_error: "Veuillez vérifier le paramètre de langue de votre code source et vous assurer qu'il est encodé en UTF-8" unexpected_error: "L'import de fichier produits à rencontré une erreur inconnue à l'ouverture du fichier : %{error_message}" + malformed_csv: "L'outil d'import a rencontré un fichier CSV avec le ou les problèmes suivants : %{error_message}" index: notice: "Notice" beta_notice: "Cette fonctionnalité est en mode bêta : il est possible que vous rencontriez des erreurs en l'utilisant. N'hésitez pas à contacter le support utilisateurs." @@ -2134,7 +2140,7 @@ fr: report_header_customer_code: Code acheteur report_header_product: Produit report_header_product_properties: Propriétés / labels Produits - report_header_quantity: Nb commandé + report_header_quantity: Quantité report_header_max_quantity: Quantité Max report_header_variant: Variante report_header_variant_value: Nb Unités Variante @@ -2193,7 +2199,7 @@ fr: report_header_eft_price: "TEF / Transfert Electronique (%{currency})" report_header_paypal_price: "Paypal (%{currency})" report_header_sku: Référence Produit - report_header_amount: Quantité + report_header_amount: Montant report_header_balance: Solde report_header_total_cost: "Coût Total" report_header_total_ordered: Total Commandé @@ -2477,7 +2483,7 @@ fr: load_more_variants: "Afficher plus de variantes" load_all_variants: "Afficher toutes les variantes" select_all_variants: "Sélectionnez toutes les %{total_number_of_variants} variantes" - variants_loaded: " %{num_of_variants_loaded}sur %{total_number_of_variants} variantes" + variants_loaded: " %{num_of_variants_loaded} sur %{total_number_of_variants} variantes" loading_variants: "Chargement des variantes" tag_rules: shipping_method_tagged_top: "Les méthodes de livraison taguées" @@ -2767,6 +2773,7 @@ fr: customer_details: "Informations acheteur" adjustments: "Ajustements" payments: "Paiements" + return_authorizations: "Autorisations de retours" payment: "Paiement" payment_method: "Méthode de paiement" shipment: "Livraison" @@ -2785,7 +2792,7 @@ fr: new: "Nouveau" start: "Début" end: "Fin" - stop: "Arrêter" + stop: "Fin" first: "Début" previous: "Précédent" last: "Fin" @@ -2836,6 +2843,14 @@ fr: new_payment: "Nouveau paiement" capture: "Payée" void: "Annulé" + login: "Se connecter" + password: "Mot de passe" + signature: "Signature" + solution: "Solution" + landing_page: "Page d'accueil (landing page)" + server: "Serveur" + test_mode: "Mode test" + logourl: "URL du logo" configurations: "Configurations" general_settings: "Configurations générales" site_name: "Nom du site" @@ -2900,8 +2915,6 @@ fr: abbreviation: "Code" new_state: "Nouveau département" payment_methods: "Méthodes de paiement" - new_payment_method: "Nouvelle méthode de paiement" - provider: "Fournisseur" taxonomies: "Taxonomies" new_taxonomy: "Nouvelle taxonomie" back_to_taxonomies_list: "Retour à la liste des taxonomies" @@ -2954,6 +2967,12 @@ fr: options: "Options" actions: update: "Mettre à jour" + shared: + error_messages: + errors_prohibited_this_record_from_being_saved: + one: "1 erreur n'a pas permis de sauvegarder:" + other: "%{count} erreurs ne permettent pas de sauvegarder:" + there_were_problems_with_the_following_fields: "Ils a eu des soucis avec les champs suivants" errors: messages: blank: "Champ obligatoire" @@ -3113,10 +3132,26 @@ fr: back_end: "Visible pour l'administration uniquement" deactivation_warning: "Désactiver une méthode de livraison peut engendre sa disparition de la liste ici. Si vous souhaitez uniquement ne plus l'afficher pour l'acheteur, modifiez-là et utilisez l'option d'affichage \"visible pour l'administrateur uniquement\"." payment_methods: + index: + payment_methods: "Méthodes de paiement" + new_payment_method: "Nouvelle méthode de paiement" + name: "Produit/Variante" + products_distributor: "Distributeur" + provider: "Fournisseur" + environment: "Environnement" + display: "Afficher" + active: "Actif" + both: "Les deux" + front_end: "Visible par l'acheteur uniquement" + back_end: "Visible pour l'administration uniquement" + active_yes: "Oui" + active_no: "Non" + no_payment_methods_found: "Aucune méthode de paiement n'a été trouvée" new: new_payment_method: "Nouvelle méthode de paiement" back_to_payment_methods_list: "Retour à la liste des méthodes de paiement" edit: + new: "Nouveau" editing_payment_method: "Modification de la méthode de paiement" back_to_payment_methods_list: "Retour à la liste des méthodes de paiement" stripe_connect: @@ -3132,6 +3167,21 @@ fr: account_id: Identifiant Compte business_name: Nom de l'entreprise charges_enabled: Frais activés + form: + name: "Produit/Variante" + description: "Description" + environment: "Environnement" + display: "Afficher" + active: "Actif" + active_yes: "Oui" + active_no: "Non" + both: "Visible par l'acheteur sur la boutique" + front_end: "Visible par l'acheteur uniquement" + back_end: "Visible pour l'administration uniquement" + tags: "Tags" + deactivation_warning: "Désactiver une méthode de paiement peut faire disparaitre cette méthode de votre liste. Si vous souhaitez uniquement la rendre invisible par l'acheteur, modifiez la méthode et utilisez l'affichage pour l'administrateur uniquement." + providers: + provider: "Fournisseur" payments: source_forms: stripe: @@ -3234,6 +3284,7 @@ fr: display_as_placeholder: 'ex. 2 kg' display_name_placeholder: 'ex. Tomates' autocomplete: + out_of_stock: "En rupture de stock" producer_name: "Producteur" unit: "Unité" shared: @@ -3299,9 +3350,14 @@ fr: invalid: invalide order_mailer: cancel_email: - customer_greeting: "Bonjour %{name} !" - instructions: "Votre commande a été ANNULÉE. Vous trouverez ci-dessous les informations concernant cette commande. " - order_summary_canceled: "Résumé de la commande [ANNULEE]" + customer_greeting: "Bonjour %{name}," + instructions_html: "Votre commande avec %{distributor}a été annulée. Merci de conserver cet email." + dont_cancel: "Si vous avez changé d'avis ou l'annulation a été réalisée par erreur, merci de contacter %{email}" + order_summary_canceled_html: "[ANNULATION] Commande #%{number}" + details: "Voici le détail des produits commandés:" + unpaid_order: "Votre commande n'avait pas été réglée, aucun remboursement n'a donc été effectué" + paid_order: "Votre commande avait été réglée, ainsi %{distributor}a remboursé la totalité du montant" + credit_order: "Votre commande avait été payée, votre compte a donc été crédité" subject: "Annulation de Commande" confirm_email: subject: "Confirmation de commande" diff --git a/config/locales/fr_BE.yml b/config/locales/fr_BE.yml index ab4a5e02d3..5b2e89defd 100644 --- a/config/locales/fr_BE.yml +++ b/config/locales/fr_BE.yml @@ -9,7 +9,7 @@ fr_BE: shipment_state: Statut livraison completed_at: 'Passée à ' number: N° commande - state: Province + state: Statut de la commande email: Adresse électronique acheteur spree/payment: amount: Montant @@ -23,6 +23,8 @@ fr_BE: base: "Carte de crédit" order_cycle: orders_close_at: Date de fermeture + variant_override: + count_on_hand: "En stock" errors: models: spree/user: @@ -367,7 +369,6 @@ fr_BE: title: "Configuration Matomo" matomo_url: "URL de l'instance sur Matomo" matomo_site_id: "ID de l'instance sur Matomo" - info_html: "Matomo est un outil d'analyse de trafic web (ordinateur et téléphone). Vous pouvez installer vous-même Matomo ou utiliser une version hébergée. Voir matomo.org pour plus d'information." config_instructions_html: "Pour utiliser Matomo, vous devez configurer l'intégration avec Open Food France. L'URL de l'instance sur Matomo correspond à l'url du site internet visé par le suivi de la navigation utilisateur. Si le champ est vide, Matomo n'effectuera aucune analyse sur ce site. L'ID de l'instance sur Matomo n'est pas obligatoire, mais nécessaire si vous souhaitez analyser plusieurs sites web sur une seule instance Matomo. Cet ID peut être trouvé sur l'espace administrateur Matomo." customers: index: @@ -402,6 +403,7 @@ fr_BE: footer_and_external_links: Pied de page et Liens Externes your_content: Votre contenu user_guide: Guide d'utilisation + map: Carte enterprise_fees: index: title: "Marges et Commissions" @@ -1632,7 +1634,7 @@ fr_BE: sell_hubs_detail: "Créer un profil pour votre activité sur OFN en quelques minutes. A tout moment vous pourrez créer un comptoir en ligne pour vendre vos produits en direct aux acheteurs." sell_groups_detail: "Créer un répertoire sur mesure (regroupant différents producteurs et comptoirs) pour votre région ou votre organisation." sell_user_guide: "En savoir plus en explorant le guide d'utilisation." - sell_listing_price: "L'inscription à l'OFN est libre de contribution. Ouvrir et utiliser un comptoir sur OFN vous permet de gagner jusqu'à 500 € de ventes mensuelles, le service est gratuit les 6 premiers mois. Ensuite, une contribution entre 1 à 3% de votre chiffre de vente est demandée." + sell_listing_price: "L'inscription sur la plateforme d'OFN est libre de contribution. Le service est gratuit les 6 premiers mois. Ensuite, une contribution de 2% de votre chiffre de vente est demandée." sell_embed: "D’ici là, vous pouvez également participer au projet. \nSoit en co-créant la communauté belge et en contribuant à l’amélioration des fonctionnalité. Soit en mettant à disposition un local pour faciliter les livraisons ou un lieu pour former les utilisateurs·trices à la plateforme, etc. Soit en soutenant le projet par un don (déductible fiscalement à partir de 40€) à verser sur le compte d'Oxfam-Magasins du monde qui facilite la plateforme :  BE41 0682 2264 2410 – en communication Open Food Network Belgium." sell_ask_services: "Contactez-nous pour en savoir plus." shops_title: Comptoirs @@ -2669,6 +2671,7 @@ fr_BE: customer_details: "Données client·e" adjustments: "Corrections" payments: "Paiements" + return_authorizations: "Autorisations de retour" payment: "Paiement" payment_method: "Méthode de paiement" shipment: "Envoi" @@ -2738,6 +2741,8 @@ fr_BE: new_payment: "Nouveau paiement" capture: "Payée" void: "Vide" + login: "Se connecter" + password: "Mot de passe" configurations: "Configurations" general_settings: "Réglages Généraux" site_name: "Nom du site" @@ -2802,8 +2807,6 @@ fr_BE: abbreviation: "Abréviation" new_state: "Nouvelle Province" payment_methods: "Méthodes de paiement" - new_payment_method: "Nouvelle méthode de paiement" - provider: "Fournisseur" taxonomies: "Taxonomies " new_taxonomy: "Nouvelle taxonomie" back_to_taxonomies_list: "Retour à la liste des taxonomies" @@ -3010,10 +3013,23 @@ fr_BE: categories: "Les catégories" zones: "Zones" payment_methods: + index: + payment_methods: "Méthodes de paiement" + new_payment_method: "Nouvelle méthode de paiement" + name: "Nom" + products_distributor: "Distributeur" + provider: "Fournisseur" + environment: "Environnement" + display: "Ecran" + active: "Actif" + both: "Les deux" + active_yes: "Oui" + active_no: "Non" new: new_payment_method: "Nouvelle méthode de paiement" back_to_payment_methods_list: "Retour à la liste des paiements" edit: + new: "Nouveau" editing_payment_method: "Modification des méthodes de paiement en cours" back_to_payment_methods_list: "Retour à la liste des paiements" stripe_connect: @@ -3029,6 +3045,17 @@ fr_BE: account_id: Identifiant Compte business_name: Nom de l'entreprise charges_enabled: Frais activés + form: + name: "Nom" + description: "Description" + environment: "Environnement" + display: "Ecran" + active: "Actif" + active_yes: "Oui" + active_no: "Non" + tags: "Tags" + providers: + provider: "Fournisseur" payments: source_forms: stripe: @@ -3129,13 +3156,14 @@ fr_BE: display_as: "Unité affichéé" display_name: "Nom d'affichage" autocomplete: + out_of_stock: "Pas en stock" producer_name: "Producteur·trice" unit: "Unité" shared: sortable_header: name: "Nom" number: "N° commande" - state: "Province" + state: "Statut de la commande" payment_state: "Statut du Paiement" shipment_state: "Statut livraison" email: "Email" @@ -3193,9 +3221,6 @@ fr_BE: invalid: invalide order_mailer: cancel_email: - customer_greeting: "Bonjour%{name}! " - instructions: "Votre commande a été ANNULÉE. Veuillez conserver ces informations d'annulation pour vos dossiers." - order_summary_canceled: "Résumé de la commande [ANNULÉE]" subject: "Annulation de Commande" confirm_email: subject: "Confirmation de commande" diff --git a/config/locales/fr_CA.yml b/config/locales/fr_CA.yml index a9cbb2d1e6..78d26c0da0 100644 --- a/config/locales/fr_CA.yml +++ b/config/locales/fr_CA.yml @@ -23,6 +23,8 @@ fr_CA: base: "Carte de crédit" order_cycle: orders_close_at: Date de fermeture + variant_override: + count_on_hand: "En stock" errors: models: spree/user: @@ -31,6 +33,10 @@ fr_CA: taken: "Un compte existe déjà pour cet e-mail. 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: @@ -250,6 +256,7 @@ fr_CA: error: Erreur processing_payment: "Paiement en cours..." no_pending_payments: "Aucun paiement en attente." + invalid_payment_state: "Statut de paiement invalide" filter_results: Filtrer les résultats quantity: Quantité pick_up: Retrait @@ -319,6 +326,7 @@ fr_CA: show_n_more: Montrer %{num} supplémentaires choose: "Choisir..." please_select: Veuillez choisir... + column_save_as_default: Par défaut columns: Colonnes actions: Actions viewing: "Vous regardez: %{current_view_name}" @@ -363,8 +371,10 @@ fr_CA: title: "Configuration Matomo" matomo_url: "URL de l'instance sur Matomo" matomo_site_id: "ID de l'instance sur Matomo" - info_html: "Matomo est un outil d'analyse de trafic web (ordinateur et téléphone). Vous pouvez installer vous-même Matomo ou utiliser une version hébergée. Voir matomo.org pour plus d'information." + matomo_tag_manager_url: "URL du Matomo Tag Manager" + info_html: "Matomo est un outil de suivi de traffic et de comportement des utilisateurs. Matomo est open source et validée par la CNIL française car non intrusif dans les données personnelles des utilisateurs. Pour plus d'infos : 1matomo.org1." config_instructions_html: "Pour utiliser Matomo, vous devez configurer l'intégration avec Open Food France. L'URL de l'instance sur Matomo correspond à l'url du site internet visé par le suivi de la navigation utilisateur. Si le champ est vide, Matomo n'effectuera aucune analyse sur ce site. L'ID de l'instance sur Matomo n'est pas obligatoire, mais nécessaire si vous souhaitez analyser plusieurs sites web sur une seule instance Matomo. Cet ID peut être trouvé sur l'espace administrateur Matomo." + config_instructions_tag_manager_html: "Ajouter l'URL du Tag Manager rend actif Matomo Tag Manager. Cet outil vous permet de suivre des évènements en particulier. Pour trouver l'URL rendez-vous sur l' \"Install Code section\" du Tag Manager. Attention à bien copier le bon contener et le bon environnement, car ils font varier l'URL." customers: index: new_customer: "Nouveau client" @@ -398,6 +408,7 @@ fr_CA: footer_and_external_links: Pied de page et Liens Externes your_content: Votre contenu user_guide: Guide utilisateur + map: Carte enterprise_fees: index: title: "Marges et Commissions" @@ -682,6 +693,7 @@ fr_CA: ofn_uid_tip: L'identifiant unique pour les comptes entreprises sur Open Food Network. shipping_methods: name: "Nom" + applies: "Active ?" manage: "Gérer les méthodes de livraison" create_button: "Créer nouvelle méthode de livraison" create_one_button: "En créer une maintenant" @@ -861,6 +873,7 @@ fr_CA: incoming: "Produits entrants (pouvant être mis en vente par les hubs)" supplier: "Fournisseur" products: "Produits" + receival_details: "Détails livraison" fees: "Commissions" save: "Enregistrer" save_and_next: "Sauvegarder et suivant" @@ -872,6 +885,7 @@ fr_CA: distributor: "Hub-distributeur" products: "Produits" tags: "Tags" + delivery_details: "Détails de livraison" fees: "Commissions" previous: "Précédent" save: "Enregistrer" @@ -1168,7 +1182,11 @@ fr_CA: signup: "inscrivez-vous" contact: "contact" require_customer_login: "Seul les acheteurs autorisés peuvent accéder à cette boutique." + require_login_html: "Si vous êtes déjà autorisé à accéder à la boutique, %{login}ou %{signup}pour continuer." + require_login_2_html: "Vous souhaitez réaliser vos courses ici? Merci de %{contact}%{enterprise} afin d'avoir l'autorisation d'accès à la boutique." require_customer_html: "Si vous voulez demander à y accéder, veuillez %{contact} %{enterprise}." + select_oc: + select_oc_html: "Merci de 1sélectionner une option dans la liste déroulante1, afin de voir quel produits sont disponibles." card_could_not_be_updated: La carte n'a pu être mise à jour card_could_not_be_saved: la carte n'a pas pu être sauvegardée spree_gateway_error_flash_for_checkout: "Il y a eu un problème avec vos informations de paiement : %{error}" @@ -1491,6 +1509,7 @@ fr_CA: shopping_oc_closed_description: "Veuillez attendre l'ouverture du prochain cycle de vente (ou contactez-nous directement 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électionner" shopping_tabs_home: "Accueil" shopping_tabs_shop: "Boutique" shopping_tabs_about: "A propos" @@ -1527,12 +1546,17 @@ fr_CA: orders_changeable_orders_alert_html: Cette commande a été confirmée, mais vous pouvez effectuer des modifications jusqu'à %{oc_close}. products_clear: Effacer products_showing: "Afficher:" + products_results_for: "Résultats pour" products_or: "ou" products_and: "et" + products_filters_in: "dans" products_with: avec + products_search: "Rechercher..." products_filter_by: "Filtrer par" products_filter_selected: "sélectionné" + products_filter_heading: "Filtres" products_filter_clear: "Effacer" + products_filter_done: "Fait" products_loading: "Produits en cours de chargement..." products_updating_cart: "Actualisation du panier..." products_cart_empty: "Panier vide" @@ -1543,6 +1567,8 @@ fr_CA: products_update_error_msg: "Échec de l'enregistrement." products_update_error_data: "Échec de l'enregistrement dû à des données non valides." products_changes_saved: "Modifications enregistrées." + products_no_results_html: "Nous sommes navrés, mais aucun résultat n'a été trouvé pour %{query}" + products_clear_search: "Annuler la recherche" search_no_results_html: "Désolé, aucun résultat pour %{query}. Autre recherche?" components_profiles_popover: "Certaines entreprises ont juste créé leur profil sur Open Food Network mais ne vendent pas via la plateforme. Elles ont peut-être une boutique physique, ou une boutique en ligne sur une autre plateforme." components_profiles_show: "Afficher aussi les profils" @@ -1851,6 +1877,7 @@ fr_CA: 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 vers le tableau de bord" back: "Retour" continue: "Suivant" action_or: "OU" @@ -1897,6 +1924,7 @@ fr_CA: admin_enterprise_relationships_permits: "autorise" admin_enterprise_relationships_seach_placeholder: "Chercher" admin_enterprise_relationships_button_create: "Créer" + admin_enterprise_relationships_to: "à" admin_enterprise_groups: "Groupes d'entreprises" admin_enterprise_groups_name: "Nom" admin_enterprise_groups_owner: "Gérant" @@ -2304,6 +2332,10 @@ fr_CA: resolve_errors: Veuillez corriger les erreurs suivantes more_items: "+ %{count} en plus" default_card_updated: La carte bancaire par défaut a été mise à jour + cart: + add_to_cart_failed: > + Il y a eu un problème lors de l'ajout de votre produit au panier. Peut-être + qu'il n'est plus en stock ou que la boutique sur laquelle vous étiez a fermé. admin: enterprise_limit_reached: "Vous avez atteint le nombre limite d'entreprises autorisées par défaut. Ecrivez à %{contact_email}si vous avez besoin d'augmenter cette limite." modals: @@ -2723,6 +2755,7 @@ fr_CA: customer_details: "Informations acheteur" adjustments: "ajustements" payments: "Paiements" + return_authorizations: "Autorisations de retours" payment: "Paiement" payment_method: "Méthode de paiement" shipment: "Livraison" @@ -2792,6 +2825,14 @@ fr_CA: new_payment: "Nouveau paiement" capture: "Payée" void: "Annulé" + login: "Se connecter" + password: "Mot de passe" + signature: "Signature" + solution: "Solution" + landing_page: "Page d'accueil (landing page)" + server: "Serveur" + test_mode: "Mode test" + logourl: "URL du logo" configurations: "Configurations" general_settings: "Configurations générales" site_name: "Nom du site" @@ -2856,8 +2897,6 @@ fr_CA: abbreviation: "Code" new_state: "Nouveau Région:" payment_methods: "Méthodes de paiement" - new_payment_method: "Nouvelle méthode de paiement" - provider: "Fournisseur" taxonomies: "Taxonomies" new_taxonomy: "Nouvelle taxonomie" back_to_taxonomies_list: "Retour à la liste des taxonomies" @@ -2910,6 +2949,12 @@ fr_CA: options: "Options" actions: update: "Mettre à jour" + shared: + error_messages: + errors_prohibited_this_record_from_being_saved: + one: "1 erreur n'a pas permis de sauvegarder:" + other: "1 %{count} erreurs ne permettent pas de sauvegarder:" + there_were_problems_with_the_following_fields: "Ils a eu des soucis avec les champs suivants" errors: messages: blank: "Champ obligatoire" @@ -3017,6 +3062,8 @@ fr_CA: tax_invoice: "FACTURE" code: "Code" from: "De" + to: "Facturer à" + shipping: "Envoi" form: distribution_fields: title: "Distribution" @@ -3050,6 +3097,8 @@ fr_CA: zone: "Zone" calculator: "Calculateur" display: "Afficher" + both: "Visible par l'acheteur sur la boutique" + back_end: "Visible pour l'administration uniquement" no_shipping_methods_found: "Aucune méthode de livraison trouvée" new: new_shipping_method: "Nouvelle méthode de livraison" @@ -3061,11 +3110,30 @@ fr_CA: form: categories: "Conditions de transport" zones: "Zones" + both: "Visible par l'acheteur sur la boutique" + back_end: "Visible pour l'administration uniquement" + deactivation_warning: "Désactiver une méthode de livraison peut engendre sa disparition de la liste ici. Si vous souhaitez uniquement ne plus l'afficher pour l'acheteur, modifiez-là et utilisez l'option d'affichage \"visible pour l'administrateur uniquement\"." payment_methods: + index: + payment_methods: "Méthodes de paiement" + new_payment_method: "Nouvelle méthode de paiement" + name: "Nom" + products_distributor: "Hub-distributeur" + provider: "Fournisseur" + environment: "Environnement" + display: "Afficher" + active: "Actif" + both: "Les deux" + front_end: "Visible par l'acheteur uniquement" + back_end: "Visible pour l'administration uniquement" + active_yes: "Oui" + active_no: "Non" + no_payment_methods_found: "Aucune méthode de paiement n'a été trouvée" new: new_payment_method: "Nouvelle méthode de paiement" back_to_payment_methods_list: "Retour à la liste des méthodes de paiement" edit: + new: "Nouveau" editing_payment_method: "Modification de la méthode de paiement" back_to_payment_methods_list: "Retour à la liste des méthodes de paiement" stripe_connect: @@ -3081,6 +3149,21 @@ fr_CA: account_id: Identifiant Compte business_name: Nom de l'entreprise charges_enabled: Frais activés + form: + name: "Nom" + description: "Description" + environment: "Environnement" + display: "Afficher" + active: "Actif" + active_yes: "Oui" + active_no: "Non" + both: "Visible par l'acheteur sur la boutique" + front_end: "Visible par l'acheteur uniquement" + back_end: "Visible pour l'administration uniquement" + tags: "Tags" + deactivation_warning: "Désactiver une méthode de paiement peut faire disparaitre cette méthode de votre liste. Si vous souhaitez uniquement la rendre invisible par l'acheteur, modifiez la méthode et utilisez l'affichage pour l'administrateur uniquement." + providers: + provider: "Fournisseur" payments: source_forms: stripe: @@ -3180,7 +3263,10 @@ fr_CA: price: "Prix" display_as: "Afficher comme" display_name: "Nom affiché" + display_as_placeholder: 'ex. 2 kg' + display_name_placeholder: 'ex. Tomates' autocomplete: + out_of_stock: "En rupture de stock" producer_name: "Producteur" unit: "Unité" shared: @@ -3218,6 +3304,7 @@ fr_CA: format: '%Y-%m-%d' js_format: 'yy-mm-dd' orders: + error_flash_for_unavailable_items: "Un élément de votre panier est épuisé. Veuillez mettre à jour les quantités sélectionnées." edit: login_to_view_order: "Veuillez vous connecter pour voir votre commande." bought: @@ -3245,9 +3332,14 @@ fr_CA: invalid: invalide order_mailer: cancel_email: - customer_greeting: "Bonjour %{name}!" - instructions: "Votre commande a été ANNULÉE. Vous trouverez ci-dessous les informations concernant cette commande. " - order_summary_canceled: "Résumé de la commande [ANNULEE]" + customer_greeting: "Bonjour %{name}," + instructions_html: "Votre commande avec 1%{distributor}1a été annulée. Merci de conserver cet email." + dont_cancel: "Si vous avez changé d'avis ou l'annulation a été réalisée par erreur, merci de contacter %{email}" + order_summary_canceled_html: "1[ANNULATION] Commande #%{number}1" + details: "Voici le détail des produits commandés:" + unpaid_order: "Votre commande n'avait pas été réglée, aucun remboursement n'a donc été effectué" + paid_order: "Votre commande avait été réglée, ainsi %{distributor}a remboursé la totalité du montant" + credit_order: "Votre commande avait été payée, votre compte a donc été crédité" subject: "Annulation de Commande" confirm_email: subject: "Confirmation de commande" diff --git a/config/locales/it.yml b/config/locales/it.yml index 70c28a0515..7d0ef72e69 100644 --- a/config/locales/it.yml +++ b/config/locales/it.yml @@ -3,26 +3,28 @@ it: activerecord: attributes: enterprise_fee: - fee_type: Tipo di tariffa + fee_type: Tipo Tariffa spree/order: - payment_state: Stato del pagamento - shipment_state: Stato della spedizione - completed_at: Completo al + payment_state: Stato Pagamento + shipment_state: Stato Spedizione + completed_at: Completato Al number: Numero state: Stato - email: Mail consumatore + email: E-Mail Cliente spree/payment: amount: Quantità spree/product: - primary_taxon: "Categoria prodotto" + primary_taxon: "Categoria Prodotto" supplier: "Fornitore" - shipping_category_id: "Categoria di spedizione" + shipping_category_id: "Categoria Spedizioni" variant_unit: "Unità Variante" variant_unit_name: "Nome Unità Variante" spree/credit_card: base: "Carta di Credito" order_cycle: orders_close_at: Data chiusura + variant_override: + count_on_hand: "Disponibile" errors: models: spree/user: @@ -31,6 +33,10 @@ it: taken: "Esiste già un account con questa email. Ti preghiamo di effettuare il login o impostare una nuova password." spree/order: no_card: Non ci sono carte di credito autorizzate disponibili per l'addebito + spree/credit_card: + attributes: + base: + card_expired: "è scaduto" order_cycle: attributes: orders_close_at: @@ -39,7 +45,7 @@ it: count_on_hand: using_producer_stock_settings_but_count_on_hand_set: "deve restare vuoto perché si stanno utilizzando le impostazioni di magazzino del produttore" on_demand_but_count_on_hand_set: "deve restare vuoto se su richiesta" - limited_stock_but_no_count_on_hand: "Torna alla lista dei pagamenti" + limited_stock_but_no_count_on_hand: "deve essere specificato a causa di una disponibilità limitata" activemodel: attributes: order_management/reports/enterprise_fee_summary/parameters: @@ -47,10 +53,10 @@ it: end_at: "Fine" distributor_ids: "Distributori" producer_ids: "Produttori" - order_cycle_ids: "Cicli di richieste" - enterprise_fee_ids: "Nome commissione" - shipping_method_ids: "Metodi di spedizione" - payment_method_ids: "Metodi di pagamento" + order_cycle_ids: "Cicli di Richieste" + enterprise_fee_ids: "Nomi Tariffe" + shipping_method_ids: "Metodi di Spedizione" + payment_method_ids: "Metodi di Pagamento" errors: messages: inclusion: "non incluso nella lista" @@ -58,7 +64,7 @@ it: order_management/subscriptions/validator: attributes: subscription_line_items: - at_least_one_product: "^Aggiungi almeno un prodotto" + at_least_one_product: "^Per favore aggiungi almeno un prodotto" not_available: "^%{name} non è disponibile nel programma selezionato" ends_at: after_begins_at: "deve essere dopo l'inizio il" @@ -67,28 +73,28 @@ it: schedule: not_coordinated_by_shop: "non è coordinato da %{shop}" payment_method: - not_available_to_shop: "non è disponibile al %{shop}" - invalid_type: "Il metodo dev'essere Cash o Stripe" - charges_not_allowed: "L'addebito su carta di credito non è consentito da questo consumatore" - no_default_card: "Nessuna carta predefinita è consentita per questo consumatore" + not_available_to_shop: "non è disponibile da %{shop}" + invalid_type: "il metodo deve essere Cash o Stripe" + charges_not_allowed: "L'addebito su carta di credito non è consentito per questo cliente" + no_default_card: "^Nessuna carta predefinita è disponibile per questo cliente" shipping_method: not_available_to_shop: "non è disponibile al %{shop}" devise: confirmations: - send_instructions: "A breve riceverai un'email con le istruzioni utili a confermare il tuo account." - failed_to_send: "C'è stato un errore nell'invio della tua mail di conferma." - resend_confirmation_email: "Re-invia la mail di conferma" - confirmed: "Grazie per aver confermato la tua mail! Ora puoi effettuare il log in." + send_instructions: "A breve riceverai una email con le istruzioni per la conferma del tuo account." + failed_to_send: "C'è stato un errore nell'invio dell'email di conferma." + resend_confirmation_email: "Invia di nuovo l'email di conferma." + confirmed: "Grazie per aver confermato la tua email! Ora puoi effettuare il log in." not_confirmed: "Il tuo indirizzo email non può essere confermato. Forse avevi già completato questo passaggio?" user_confirmations: spree_user: - send_instructions: "A breve riceverai un'email con le istruzioni utili a confermare il tuo account." + send_instructions: "A breve riceverai una email con le istruzioni per la conferma del tuo account." confirmation_sent: "Email di conferma inviata" confirmation_not_sent: "Errore invio emai di conferma" user_registrations: spree_user: signed_up_but_unconfirmed: "Abbiamo inviato un link di conferma al tuo indirizzo email. Per favore apri il link per attivare il tuo account." - unknown_error: "Qualcosa è andato storto durante la creazione del tuo account. Controlla il tuo indirizzo e-mail e riprova" + unknown_error: "Qualcosa è andato storto durante la creazione del tuo account. Controlla il tuo indirizzo email e riprova" failure: invalid: | Email o password non valida. @@ -101,29 +107,29 @@ it: spree_user: updated_not_active: "La tua password è stata resettata, ma la tua email non è ancora stata confermata." updated: "La tua password è stata modificata con successo.\nOra sei collegato." - send_instructions: "A breve riceverai un'email con le istruzioni utili a confermare il tuo account." + send_instructions: "A breve riceverai una email con le istruzioni per la conferma del tuo account." models: order_cycle: cloned_order_cycle_name: "COPIA DI %{order_cycle}" validators: date_time_string_validator: - not_string_error: "Deve essere una linea" - invalid_format_error: "Deve essere valido" + not_string_error: "deve essere una stringa" + invalid_format_error: "deve essere valido" integer_array_validator: - not_array_error: "Deve essere una sequenza" - invalid_element_error: "Deve contenere solo numeri interi" + not_array_error: "deve essere un array" + invalid_element_error: "deve contenere solo numeri interi" enterprise_mailer: confirmation_instructions: - subject: "Per favore conferma l'indirizzo email per %{enterprise}" + subject: "Per favore conferma l'indirizzo email di %{enterprise}" welcome: subject: "%{enterprise} è ora su %{sitename}" email_welcome: "Benvenuto" email_registered: "è ora parte di" - email_userguide_html: "La Guida Utente con supporto dettagliato per l'impostazione del tuo Produttore o Hub è qui: %{link}" - userguide: "Guida di Open Food Network" + email_userguide_html: "La Guida Utente con supporto dettagliato per l'impostazione del tuo Produttore o Distributore è qui: %{link}" + userguide: "Guida Utente di Open Food Network" email_admin_html: "Puoi gestire il tuo profilo facendo il log in al link %{link} o cliccando sull'ingranaggio in alto a destra della homepage, e selezionando Amministrazione" - admin_panel: "Pannello di controllo" - email_community_html: "Abbiamo anche un forum on-line per le discussioni della comunità sul software OFN e le sfide uniche legate all'avere un'impresa del cibo. Sei invitato ad unirti. Ci evolviamo in continuo e il tuo contributo in questo forum plasmerà ciò che sarà. %{link}" + admin_panel: "Panello Amministrativo" + email_community_html: "Abbiamo anche un forum per le discussioni comunitarie legate al software di OFN e le sfide uniche legate all'avere un'impresa alimentare. Ti incoraggiamo a farne parte. Siamo in continua evoluzione e il tuo contributo al forum delineerà quello che succederà in futuro. %{link}" join_community: "Unisciti alla community" invite_manager: subject: "%{enterprise} ti a invitato ad essere un referente" @@ -132,35 +138,35 @@ it: subject: "Resoconto degli ordini per %{producer}" shipment_mailer: shipped_email: - dear_customer: "Caro consumatore," + dear_customer: "Caro Cliente," instructions: "Il tuo ordine è stato spedito" - shipment_summary: "Riepilogo della spedizione" - subject: "Avviso di spedizione" - thanks: "Grazie per utilizzare la piattaforma per il tuo commercio" - track_information: "Informazioni di tracciamento" - track_link: "Link del tracciamento" + shipment_summary: "Riepilogo della Spedizione" + subject: "Notifica di Spedizione" + thanks: "Grazie per il tuo lavoro." + track_information: "Informazioni Tracking: %{tracking}" + track_link: "Tracking Link: %{url}" subscription_mailer: placement_summary_email: subject: Riassunto degli ordini più recenti greeting: "Ciao %{name}," - intro: "Qui sotto un riassunto degli ordini appena inviati per%{shop} ," + intro: "Qui sotto un riassunto degli ordini appena inviati per%{shop}," confirmation_summary_email: subject: Riassunto delle richieste recentemente confermate greeting: "Ciao %{name}," intro: "Qui sotto un riassunto delle richieste che hai appena confermato per %{shop}." summary_overview: - total: Un totale di %{count} abbonamenti sono stati contrassegnati per l'elaborazione automatica.. - success_zero: Di questi, nessuno è stato modificato con successo + total: Un totale di %{count} sottoscrizioni sono stati contrassegnati per l'elaborazione automatica. + success_zero: Di questi, nessuno è stato elaborato con successo. success_some: Di questi, %{count} sono stati elaborati con successo. - success_all: Tutti sono stati elaborati con successo. - issues: Qui sotto i dettagli dei problemi incontrati. + success_all: Sono stati elaborati tutti con successo. + issues: Qui sotto i dettagli dei problemi riscontrati. summary_detail: - no_message_provided: 'Nessun messaggio di errore ' + no_message_provided: Nessun messaggio di errore fornito changes: - title: Scorte insufficienti (%{count} gentili richieste) - explainer: Queste gentili richieste sono state elaborate, ma la quantità richiesta di alcuni prodotti non è disponibile + title: Scorte insufficienti (%{count} ordini) + explainer: Questi ordini sono stati processati ma la quantità richiesta di alcuni prodotti non è disponibile empty: - title: Nessuna scorta (%{count} gentili richieste) + title: Nessuna scorta (%{count} ordini) explainer: Queste gentili richieste non sono state confermate perchè alcuni prodotti richiesti non sono disponibili. complete: title: Già elaborate (%{count} gentili richieste) @@ -176,7 +182,7 @@ it: explainer: L'elaborazione automatica di queste gentili richieste non è riuscita per una ragione sconosciuta. Questo non dovrebbe accadere, ti preghiamo di contattarci se visualizzi questo messaggio. home: "OFN" title: Open Food Network - welcome_to: 'Benvenuto a' + welcome_to: 'Benvenuto su ' site_meta_description: "Cominciamo da zero. Con i produttori e gli allevatori pronti a raccontare le loro storie, sinceramente e orgogliosamente. Con i distributori pronti a connettere le persone con i prodotti in modo giusto ed equo. Con i compratori che credono che migliori decisioni per l'acquisto settimanale possano..." search_by_name: Cerca per nome o zona... producers_join: I Produttori sono ora invitati ad unirsi ad Open Food Network @@ -184,12 +190,12 @@ it: print_invoice: "Stampa fattura" print_ticket: "Stampa Biglietto" select_ticket_printer: "Seleziona la stampante per i biglietti" - send_invoice: "Manda fattura" - resend_confirmation: "Rimanda conferma" - view_order: "Vedi l'ordine" - edit_order: "Modifica l'ordine" - ship_order: "Invia l'ordine" - cancel_order: "Cancella l'ordine" + send_invoice: "Invia Fattura" + resend_confirmation: "Rimanda Conferma" + view_order: "Vedi Ordine" + edit_order: "Modifica Ordine" + ship_order: "Invia Ordine" + cancel_order: "Cancella Ordine" confirm_send_invoice: "Una fattura per quest'ordine verrà mandata al cliente. Sei sicuro di voler continuare?" confirm_resend_order_confirmation: "Sei sicuro di voler inviare di nuovo l'email di conferma per l'ordine?" must_have_valid_business_number: "%{enterprise_name} deve avere una partita iva valida per poter emettere fattura." @@ -198,11 +204,11 @@ it: say_no: "No" say_yes: "Sì" ongoing: Attivo - bill_address: Indirizzo di fatturazione - ship_address: Indirizzo di consegna - sort_order_cycles_on_shopfront_by: "Ordina cicli d'ordine in vetrina per" + bill_address: Indirizzo Fatturazione + ship_address: Indirizzo Consegna + sort_order_cycles_on_shopfront_by: "Ordina Cicli Ordine in Vetrina per" required_fields: I campi obbligatori sono contrassegnati con un asterisco - select_continue: Seleziona e continua + select_continue: Seleziona e Continua remove: Rimuovi or: o collapse_all: Riduci tutto @@ -215,7 +221,7 @@ it: edit: Modifica clone: Duplica distributors: Distributori - bulk_order_management: Gestione richieste all'ingrosso + bulk_order_management: Gestione Ordini Massivi enterprises: Aziende enterprise_groups: Gruppi reports: Resoconti @@ -223,15 +229,15 @@ it: import: Importazione spree_products: Prodotti Spree all: Tutti - current: Attuali + current: Correnti available: Disponibile dashboard: Pannello di controllo undefined: non definito unused: non in uso admin_and_handling: Admin profile: Profilo - supplier_only: Solo per i fornitori - has_shopfront: Informazioni di tracciamento + supplier_only: Solo Fornitori + has_shopfront: Ha una Vetrina weight: Peso volume: Volume items: Prodotti @@ -246,26 +252,26 @@ it: blocked_cookies_alert: "Il tuo browser sembra stia bloccando i cookies necessari ad usare questa pagina del negozio. Clicca sotto per consentire i cookies e ricaricare la pagina." allow_cookies: "Accetta i cookies" notes: Note - error: Eorrore + error: Errore processing_payment: "Elaborazione pagamento..." - no_pending_payments: "nessun pagamento in sospeso" - invalid_payment_state: "stato del pagamento non valido" + no_pending_payments: "Nessun pagamento in sospeso" + invalid_payment_state: "Stato del pagamento non valido" filter_results: Filtra i risultati quantity: Quantità pick_up: Ritiro copy: Copia change_my_password: "Cambia la mia password" update_password: "Aggiorna password" - password_confirmation: 'Conferma password ' + password_confirmation: 'Conferma Password ' reset_password_token: Token per il reset della password expired: è scaduto, si prega di richiederne uno nuovo - back_to_payments_list: "Torna alla lista dei pagamenti" - maestro_or_solo_cards: "carte Maestro/Solo" - backordered: "ordini arretrati" + back_to_payments_list: "Torna alla Lista dei Pagamenti" + maestro_or_solo_cards: "Carte Maestro/Solo" + backordered: "Ordini arretrati" on hand: "Disponibile" ship: "Spedizione" actions: - create_and_add_another: "Crea e aggiungi un altro" + create_and_add_another: "Crea e Aggiungi un Altro" create: "Crea" cancel: "Annulla" save: "Salva" @@ -275,7 +281,7 @@ it: admin: begins_at: Inizia a begins_on: Inizia da - customer: Consumatore + customer: Cliente date: Data email: Email ends_at: Termina a @@ -319,6 +325,7 @@ it: show_n_more: Mostra %{num} di più choose: "Scegli..." please_select: Seleziona... + column_save_as_default: Salva Come Predefinito columns: Colonne actions: Azioni viewing: "Vista: %{current_view_name}" @@ -363,11 +370,13 @@ it: title: "Impostazioni Matomo" matomo_url: "URL Matomo" matomo_site_id: "Site ID Matomo" - info_html: "Matomo è una Web and Mobile Analytics. È possibile ospitare Matomo in sede o utilizzare un servizio cloud. Vedi matomo.org per maggiori informazionimatomo.org for more information." + matomo_tag_manager_url: "Matomo Tag Manager URL" + info_html: "Matomo è una applicazione Analitica per Web e Mobile. Puoi ospitare Matomo in locale o utilizzare un servizio ospitato su cloud. Visita matomo.org per maggiori informazioni." config_instructions_html: "Qui è possibile configurare l'integrazione OFN Matomo. L'URL di Matomo qui sotto dovrebbe puntare l'istanza di Matomo a cui saranno inviate le informazioni di monitoraggio dell'utente; se lasciato vuoto, il monitoraggio dell'utente da parte di Matomo sarà disabilitato. Il campo Site ID non è obbligatorio ma è utile se si sta tracciando più di un sito web su una singola istanza di Matomo; si può trovare sulla console dell'istanza di Matomo. " + config_instructions_tag_manager_html: "La configurazione di Matomo Tag Manager URL abilita Matomo Tag Manager. Questo strumento consente di impostare eventi di analisi. Il Matomo Tag Manager URL è copiato dalla sezione Install Code di Matomo Tag Manager. Assicurati di selezionare il giusto container e l'ambiente perché queste opzioni modificano l'URL." customers: index: - new_customer: "Nuovo cliente" + new_customer: "Nuovo Cliente" code: Codice duplicate_code: "Questo codice è già usato." bill_address: "Indirizzo di fatturazione" @@ -385,7 +394,7 @@ it: search_by_email: "Cerca per email/codice..." guest_label: 'Check-out ospite' destroy: - has_associated_orders: 'Cancellazione non riuscita: l''utente ha ordini associati al suo negozio' + has_associated_orders: 'Cancellazione fallita: l''utente ha ordini associati al negozio' contents: edit: title: Contenuto @@ -398,6 +407,7 @@ it: footer_and_external_links: Footer e link esterni your_content: I tuoi contenuti user_guide: Guida per gli utenti + map: Mappa enterprise_fees: index: title: "Tariffe azienda" @@ -439,7 +449,7 @@ it: property_name: "Nome della Proprietà" inherited_property: "Proprietà Ereditata" variants: - infinity: "Infinito..." + infinity: "Infinito" to_order_tip: "Gli articoli messi in ordine non hanno un livello di stock impostato, come ad esempio il Pane fresco su ordinazione." back_to_products_list: "Indietro alla lista dei prodotti" editing_product: "Modifica prodotto" @@ -469,6 +479,7 @@ it: line_number: "Linea %{number}:" encoding_error: "Controlla l'impostazione della lingua del file sorgente e assicurati che sia salvato con la codifica UTF-8." unexpected_error: "L'importazione del prodotto ha incontrato un errore imprevisto durante l'apertura del file:%{error_message}" + malformed_csv: "L'Importazione Prodotti ha incontro un CSV non valido: %{error_message}" index: notice: "Avviso" beta_notice: "Questa opzione è ancora in fase beta: potresti incontrare errori mentre la usi. Per favore non esitare a contattare il servizio di supporto." @@ -608,7 +619,7 @@ it: desc_short: Breve descrizione desc_short_placeholder: Raccontaci la tua attività in una o due frasi desc_long: Chi siamo - desc_long_placeholder: Racconta di te ai consumatori. Questa informazione comparirà nel tuo profilo pubblico. + desc_long_placeholder: Racconta di te ai tuoi clienti. Questa informazione comparirà nel tuo profilo pubblico. business_details: abn: ABN abn_placeholder: es. 99 123 456 789 @@ -660,7 +671,7 @@ it: name: Nome name_placeholder: es. Tartufi Biodinamici Alba groups: Gruppi - groups_tip: Seleziona i gruppi o le regioni di cui sei membro. Questo aiuterà i consumatori a trovare la tua azienda. + groups_tip: Seleziona i gruppi o le regioni di cui sei membro. Questo aiuterà i clienti a trovare la tua azienda. groups_placeholder: 'Inizia a digitare per trovare i gruppi ' primary_producer: Produttore primario? primary_producer_tip: Seleziona "Produttore" se sei un produttore primario di cibo @@ -669,9 +680,9 @@ it: none: Nessuno own: Proprio sells: Vende - sells_tip: "Nessuno - L'azienda non vende direttamente ai consumatori.
Proprio - L'azienda vende i propri prodotti ai consumatori.
Proprio e altrui - L'azienda può vendere prodotti propri o di altre aziende.
" + sells_tip: "Nessuno - L'azienda non vende direttamente ai clienti.
Proprio - L'azienda vende i propri prodotti ai clienti.
Proprio e altrui - L'azienda può vendere prodotti propri o di altre aziende.
" visible_in_search: Visibile nella ricerca? - visible_in_search_tip: Determina se questa azienda sarà visibile ai consumatori quando cercano nel sito. + visible_in_search_tip: Determina se questa azienda sarà visibile ai clienti quando cercano nel sito. visible: Visibile not_visible: Non visibile permalink: Permalink (nessuno spazio) @@ -682,13 +693,14 @@ it: ofn_uid_tip: Il codice univoco utilizzato per identificare l'azienda su OFN shipping_methods: name: "Nome" + applies: "Attivo?" manage: "Gestisci metodi di spedizione" create_button: "Crea un nuovo metodo di consegna" create_one_button: "Crea uno ora" no_method_yet: "Non hai ancora un metodo di consegna" shop_preferences: shopfront_requires_login: "Vetrina visibile pubblicamente?" - shopfront_requires_login_tip: "Scegli se i consumatori devono essere registrati per poter vedere la vetrina o se è visibile a tutti" + shopfront_requires_login_tip: "Scegli se i clienti devono essere registrati per poter vedere la vetrina o se è visibile a tutti." shopfront_requires_login_false: "Pubblica" shopfront_requires_login_true: "Visibile solo agli utenti registrati" recommend_require_login: "Consigliamo di richiedere la registrazione quando si dà la possibilità di modificare gli ordini." @@ -697,7 +709,7 @@ it: allow_guest_orders_false: "Richiedi il login per ordinare" allow_guest_orders_true: "Permetti acquisto come ospite" allow_order_changes: "Modifica gentili richieste" - allow_order_changes_tip: "Permetti ai consumatori di modificare le proprie richieste finché il ciclo di richieste è aperto." + allow_order_changes_tip: "Permetti ai clienti di modificare i propri ordini fino a quando il ciclo degli ordini è aperto." allow_order_changes_false: "Le gentili richieste confermate non possono essere modificate / annullate" allow_order_changes_true: "Gli utenti possono modificare / annullare le gentili richieste mentre il ciclo di richieste è aperto" enable_subscriptions: "Sottoscrizioni" @@ -706,7 +718,7 @@ it: enable_subscriptions_true: "Abilitata" shopfront_message: "Messaggio vetrina" shopfront_message_placeholder: > - Un messaggio opzionale per dare in benvenuto ai clienti e spiegare come + Un messaggio opzionale per dare il benvenuto ai clienti e spiegare come acquistare. Il testo inserito qui verrà mostrato nel tab principale della vetrina. shopfront_message_link_tooltip: "Inserisci / modifica link" @@ -734,7 +746,7 @@ it: title: Collegati con Stripe part1: Stripe è un servizio di elaborazione dei pagamenti che permette ai negozi su OFN di accettare pagamenti con carta di credito da parte dei clienti. part2: Per utilizzare questa funzione, è necessario collegare il proprio account Stripe a OFN. Cliccando su 'Accetto' qui sotto sarai reindirizzato al sito web Stripe dove potrai collegare un account Stripe esistente o crearne uno nuovo se non ne hai già uno. - part3: Questo consentirà alla piattaforma di accettare pagamenti con carta di credito da clienti di tua fiducia. Tieni presente che dovrai mantenere il tuo conto Stripe, pagare la tariffa di Strip e gestire gli eventuali rimborsi e i servizi al cliente. + part3: Questo consentirà alla piattaforma di accettare pagamenti con carta di credito da clienti di tua fiducia. Tieni presente che dovrai mantenere il tuo conto Stripe, pagare la commissione di Stripe e gestire gli eventuali rimborsi e i servizi al cliente. i_agree: Sono d'accordo cancel: Annulla tag_rules: @@ -744,7 +756,7 @@ it: add_new_button: ' + Aggiungi una nuova regola predefinita' no_tags_yet: Nessuna etichetta per questa azienda no_rules_yet: Nessuna regola per questa etichetta - for_customers_tagged: 'Per i clienti etichettati' + for_customers_tagged: 'Per i clienti etichettati:' add_new_rule: '+ Aggiungi una nuova regola' add_new_tag: '+ Aggiungi una nuova tag' users: @@ -788,7 +800,7 @@ it: producer_description_text: Aggiungi i tuoi prodotti, permettendo agli hubs di inserire i tuoi prodotti nei loro negozi. producer_shop: Negozio produttore sell_your_produce: Vendi i tuoi prodotti - producer_shop_description_text: Vendi i tuoi prodotti direttamente ai consumatori tramite la tua propria vetrina su OFN + producer_shop_description_text: Vendi i tuoi prodotti direttamente ai clienti tramite la tua personale vetrina su Open Food Network. producer_shop_description_text2: Un Negozio produttore è solo per i tuoi prodotti. Se vuoi vendere prodotti altrui, seleziona "Hub produttore". producer_hub: Hub produttore producer_hub_text: Vendi prodotti tuoi e di altri @@ -860,6 +872,7 @@ it: incoming: "In arrivo" supplier: "Fornitore" products: "Prodotti" + receival_details: "Dettagli Ricevimento" fees: "Tariffe" save: "Salva" save_and_next: "Salva e continua" @@ -871,6 +884,7 @@ it: distributor: "Distributore" products: "Prodotti" tags: "Tag" + delivery_details: "Dettagli Spedizione" fees: "Tariffe" previous: "Precedente" save: "Salva" @@ -882,7 +896,7 @@ it: incoming: "2. Prodotti in entrata" outgoing: "3. Prodotti in uscita" exchange_form: - pickup_time_tip: Quando gli ordini di questa Lista d'ordine saranno pronti per il cliente + pickup_time_tip: Quando gli ordini di questo ciclo saranno pronti per il cliente pickup_instructions_placeholder: "Istruzioni per la consegna" pickup_instructions_tip: Queste istruzioni saranno visibili agli utenti dopo che hanno completato una gentile richiesta pickup_time_placeholder: "Pronto per (es. Data / Ora)" @@ -934,12 +948,12 @@ it: simple_form: ready_for: Pronto per ready_for_placeholder: Data / Ora - customer_instructions: Istruzioni consumatori + customer_instructions: Istruzioni per i consumatori customer_instructions_placeholder: Note per ritiro / consegna products: Prodotti fees: Tariffe destroy_errors: - orders_present: Questo ciclo di richieste è stato selezionato da un consumatore e non può essere cancellato. Per evitare altri accessi, chiudi il ciclo. + orders_present: Questo ciclo di richieste è stato selezionato da un cliente e non può essere cancellato. Per prevenire altri accessi da parte dei clienti, per favore chiudi il ciclo. schedule_present: Questo ciclo di richieste è connesso a un programma e non può essere cancellato. Puoi eliminare il link o cancellare il programma prima. bulk_update: no_data: mmm, qualcosa è andato storto. Nessun dato per ciclo di richieste trovato. @@ -977,7 +991,7 @@ it: supplier_totals: Totali Ciclo di richieste fornitori supplier_totals_by_distributor: Totali Ciclo di richieste fornitori per distributore totals_by_supplier: Totali Ciclo di richieste fornitori per fornitore - customer_totals: Totali ciclo di richieste consumatori + customer_totals: Ciclo Ordini Cliente Totale all_products: Tutti i prodotti inventory: Inventario (in mano) lettuce_share: LettuceShare @@ -987,7 +1001,7 @@ it: delivery: Rapporto Consegne tax_types: Tipologia tariffe tax_rates: Aliquote d'imposta - pack_by_customer: Smistato dai consumatori + pack_by_customer: Imballato dal Cliente pack_by_supplier: Smistato dai fornitori orders_and_distributors: name: Gentili richieste e distributori @@ -1001,7 +1015,7 @@ it: orders_and_fulfillment: name: Gentili richieste e resoconti di soddifazione customers: - name: Consumatori + name: Clienti products_and_inventory: name: Prodotti e inventario users_and_enterprises: @@ -1038,7 +1052,7 @@ it: enable_subscriptions_step_2: 2. In "Preferenze Negozio", attiva l'opzione Abbonamenti set_up_shipping_and_payment_methods_html: 'Imposta i metodi %{shipping_link} e %{payment_link} ' set_up_shipping_and_payment_methods_note_html: Nota con gli abbonamenti può
essere utilizzato solo il metodo Contanti - ensure_at_least_one_customer_html: 'Assicurati che esista almeno un %{customer_link} ' + ensure_at_least_one_customer_html: Assicurati che almeno un %{customer_link} esista create_at_least_one_schedule: Crea almeno un programma create_at_least_one_schedule_step_1_html: '1. Vai alla pagina %{order_cycles_link} ' create_at_least_one_schedule_step_2: 2. Crea un Ciclo di Richieste se non l'hai già fatto @@ -1064,9 +1078,9 @@ it: invalid_error: Oops! Per favore compila i campi obbligatori... allowed_payment_method_types_tip: Al momento può essere utilizzato solo il metodo di pagamento Contanti credit_card: Carta di Credito - charges_not_allowed: Non sono consentiti Oneri per questo cliente + charges_not_allowed: Non sono consentiti ricarichi per questo cliente no_default_card: Il cliente non ha carte disponibili da caricare - card_ok: il cliente ha una carta disponibile da caricare + card_ok: Il cliente ha una carta disponibile da caricare begins_at_placeholder: "Seleziona una data" ends_at_placeholder: "Facoltativo" loading_flash: @@ -1091,9 +1105,9 @@ it: cancel_failure_msg: "Ci dispiace, eliminazione non riuscita!" confirm_pause_msg: "Sei sicura/o di voler mettere in pausa questo abbonamento?" pause_failure_msg: "Spiacente, pausa fallita!" - confirm_unpause_msg: "Se hai un ciclo di richieste aperto durante questa registrazione, sarà creato un ordine per l'utente registrato. Vuoi annullare la registrazione?" + confirm_unpause_msg: "Se hai aperto un Ciclo d'Ordini durante questa sottoscrizione pianificata, un ordine per l'utente verrà creato per questo cliente. Sei sicuro di voler attivare questa sottoscrizione?" unpause_failure_msg: "Ci dispiace, ripresa non riuscita!" - confirm_cancel_open_orders_msg: "Alcune di queste richieste sono attualmente attive. I consumatori sono già stati avvisati che le richieste verranno soddisfatte. Vuoi eliminare questa/e richiesta/e o mantenerla?" + confirm_cancel_open_orders_msg: "Alcuni ordini per questa sottoscrizione sono attualmente aperti. I clienti sono già stati avvisati che le richieste verranno soddisfatte. Vuoi eliminare questa/e richiesta/e o mantenerle?" resume_canceled_orders_msg: "Alcuni ordini per questo abbonamento possono essere ripresi in questo momento. Puoi riprenderli dal menu a discesa degli ordini." yes_cancel_them: Cancella l'articolo no_keep_them: Tieni l'articolo @@ -1167,8 +1181,12 @@ it: login: "fai il login" signup: "Registrati" contact: "contatto" - require_customer_login: "Solo utenti approvati hanno accesso a questo negozio" + require_customer_login: "Solo clienti approvati hanno accesso a questo negozio" + require_login_html: "Se sei già un cliente approvato, %{login} o %{signup} per procedere." + require_login_2_html: "Vuoi iniziare a acquistare qui? Per favore %{contact}%{enterprise}e chiedi di essere aggiunto." require_customer_html: "Se vuoi iniziare a comprare, per favore %{contact} %{enterprise} per chiedere di raggiungerci." + select_oc: + select_oc_html: "Per favore scegli quando vuoi il tuo ordine , per vedere quali prodotti sono disponibili." card_could_not_be_updated: La Carta non ha potuto essere rinnovata card_could_not_be_saved: La Carta non ha potuto essere salvata spree_gateway_error_flash_for_checkout: "C'è stato un problema con le informazioni sul pagamento: %{error}" @@ -1176,7 +1194,7 @@ it: invoice_column_tax: "IVA" invoice_column_price: "Prezzo" invoice_column_item: "Articolo" - invoice_column_qty: "Qtà." + invoice_column_qty: "Qtà" invoice_column_unit_price_with_taxes: "Prezzo unitario (incl. tasse)" invoice_column_unit_price_without_taxes: "Prezzo unitario (escl. tasse)" invoice_column_price_with_taxes: "Prezzo totale (incl. tasse)" @@ -1392,14 +1410,14 @@ it: order_paid: PAGATO order_not_paid: NON PAGATO order_total: Totale dell'ordine - order_payment: "Pagamento via:" + order_payment: "Pagamento attraverso:" order_billing_address: Indirizzo di fatturazione order_delivery_on: Consegna il order_delivery_address: Indirizzo di consegna order_delivery_time: Tempo di consegna order_special_instructions: "Tue note:" order_pickup_time: Pronto per il ritiro - order_pickup_instructions: Istruzioni per la raccolta + order_pickup_instructions: Istruzioni per la Distribuzione order_produce: Produrre order_total_price: Totale order_includes_tax: (include le tasse) @@ -1425,17 +1443,17 @@ it: email_social: "Connettiti con Noi:" email_contact: "Scrivici:" email_signoff: "Saluti," - email_signature: "Team di %{sitename}" + email_signature: "Il team di %{sitename}" email_confirm_customer_greeting: "Ciao %{name}," email_confirm_customer_intro_html: "Grazie per aver acquistato presso %{distributor}!" - email_confirm_customer_number_html: "Conferma dell'Ordine #%{number}" - email_confirm_customer_details_html: "Qui sono i dettagli del tuo ordine da %{distributor}:" + email_confirm_customer_number_html: "Conferma ordine #%{number}" + email_confirm_customer_details_html: "Ecco i dettagli del tuo ordine da %{distributor}:" email_confirm_customer_signoff: "Cordiali saluti," email_confirm_shop_greeting: "Ciao %{name}," email_confirm_shop_order_html: "Ben fatto! Hai un nuovo ordine per %{distributor}!" - email_confirm_shop_number_html: "Conferma dell'Ordine #%{number}" + email_confirm_shop_number_html: "Conferma ordine #%{number}" email_order_summary_item: "Articolo" - email_order_summary_quantity: "Qtà." + email_order_summary_quantity: "Qtà" email_order_summary_sku: "SKU" email_order_summary_price: "Prezzo" email_order_summary_subtotal: "Subtotale:" @@ -1443,8 +1461,8 @@ it: email_order_summary_includes_tax: "(include le tasse)" email_payment_paid: PAGATO email_payment_not_paid: NON PAGATO - email_payment_summary: Riassunto del pagamento - email_payment_method: "Pagamento via:" + email_payment_summary: Riepilogo di pagamento + email_payment_method: "Pagamento attraverso:" email_so_placement_intro_html: "Hai una nuova gentile richiesta di %{distributor}" email_so_placement_details_html: "Ecco i dettagli della gentile richiesta per %{distributor}:" email_so_placement_changes: "Purtroppo alcuni prodotti richiesti non sono disponibili. Le quantità originali richieste sono barrate qui sotto." @@ -1468,13 +1486,13 @@ it: email_shipping_delivery_address: "Indirizzo di consegna" email_shipping_collection_details: Dettagli della raccolta email_shipping_collection_time: "Pronto per il ritiro:" - email_shipping_collection_instructions: "Istruzioni per la raccolta:" + email_shipping_collection_instructions: "Istruzioni per la distribuzione:" email_special_instructions: "Tue note:" email_signup_greeting: Ciao! - email_signup_welcome: "Benvenuto a %{sitename}!" + email_signup_welcome: "Benvenuto su %{sitename}!" email_signup_confirmed_email: "Grazie di aver confermato la tua mail." email_signup_shop_html: "Puoi effettuare il log in qui: %{link}." - email_signup_text: "Grazie per esserti unito alla rete. Se sei un cliente, non vediamo l'ora di introdurti a molti produttori fantastici, distributori di cibo spettacolari e cibo delizioso! Se sei un produttore o un'impresa del cibo, siamo entusiasti di averti come parte della rete." + email_signup_text: "Grazie per esserti unito alla rete. Se sei un cliente, non vediamo l'ora di introdurti a molti produttori fantastici, distributori di cibo spettacolari e cibo delizioso! Se sei un produttore o un'impresa alimentare, siamo entusiasti di averti come parte della rete." email_signup_help_html: "Accettiamo volentieri tutte le tue domane e i tuoi suggerimenti: puoi usare il bottone Invia Feedback sul sito o scriverci a %{email}" invite_email: greeting: "Ciao!" @@ -1528,12 +1546,17 @@ it: orders_changeable_orders_alert_html: Questa gentile richiesta è stata confermata, ma puoi effettuare modifiche fino a %{oc_close}. products_clear: Pulisci products_showing: "Mostra:" + products_results_for: "Risultati per" products_or: "o" products_and: "e" + products_filters_in: "in" products_with: con + products_search: "Ricerca..." products_filter_by: "Filtra per" products_filter_selected: "selezionato" + products_filter_heading: "Filtri" products_filter_clear: "Pulisci" + products_filter_done: "Fatto" products_loading: "Caricamento prodotti..." products_updating_cart: "Aggiornamento del carrello..." products_cart_empty: "Carrello vuoto" @@ -1544,6 +1567,8 @@ it: products_update_error_msg: "Salvataggio fallito." products_update_error_data: "Salvataggio fallito per dati non validi:" products_changes_saved: "Modifiche salvate." + products_no_results_html: "Mi spiace, nessun risultato per %{query}" + products_clear_search: "Pulisci ricerca" search_no_results_html: "Mi dispiace, nessun risultato per %{query}. Vuoi provare un'altra ricerca?" components_profiles_popover: "I profili non hanno una vetrina su Open Food Network, ma potrebbero avere il proprio negozio fisico o online altrove" components_profiles_show: "Mostra profili" @@ -1653,7 +1678,7 @@ it: orders_oc_expired_text_link: "o vedi gli altri cicli d'ordine disponibili per questo hub" orders_oc_expired_email: "Email:" orders_oc_expired_phone: "Telefono:" - orders_show_title: Conferma dell'ordine + orders_show_title: Conferma Ordine orders_show_time: Ordine pronto orders_show_order_number: "Gentile richiesta #%{number}" orders_show_cancelled: Annullato @@ -1684,7 +1709,7 @@ it: remember_me: Ricordami are_you_sure: "Sei sicuro?" orders_open: Richieste aperte - closing: "In chiusura" + closing: "In chiusura " going_back_to_home_page: "Reindirizzamento alla homepage" creating: In creazione updating: In aggiornamento @@ -1899,6 +1924,7 @@ it: admin_enterprise_relationships_permits: "permessi" admin_enterprise_relationships_seach_placeholder: "Cerca" admin_enterprise_relationships_button_create: "Crea" + admin_enterprise_relationships_to: "a" admin_enterprise_groups: "Gruppi dell'azienda" admin_enterprise_groups_name: "Nome" admin_enterprise_groups_owner: "Proprietario" @@ -1959,7 +1985,7 @@ it: scheduled_for: "Programmato per" customers: "Clienti" please_select_hub: "Seleziona un hub" - loading_customers: "Clienti in caricamento" + loading_customers: "Caricamento Clienti" no_customers_found: "Nessun cliente trovato" go: "Vai" hub: "Distributore" @@ -2109,8 +2135,8 @@ it: report_header_tax_on_fees: "Oneri sulle provvigioni (%{currency_symbol})" report_header_total_tax: "Oneri totali (%{currency_symbol})" report_header_enterprise: Azienda - report_header_customer: Consumatore - report_header_customer_code: Codice cliente + report_header_customer: Cliente + report_header_customer_code: Codice Cliente report_header_product: Prodotto report_header_product_properties: Proprietà prodotto report_header_quantity: Quantità @@ -2154,10 +2180,10 @@ it: report_header_order_id: ID richiesta report_header_item_name: Nome articolo report_header_temp_controlled_items: Articolo a Temperatura Controllata - report_header_customer_name: Nome Consumatore - report_header_customer_email: Email consumatore - report_header_customer_phone: Telefono Consumatore - report_header_customer_city: Città consumatore + report_header_customer_name: Nome Cliente + report_header_customer_email: Email Cliente + report_header_customer_phone: Telefono Cliente + report_header_customer_city: Città Cliente report_header_payment_state: Stato Pagamento report_header_payment_type: Tipo Pagamento report_header_item_price: "Articolo (%{currency})" @@ -2257,12 +2283,12 @@ it: adjustments_tax_rate_error: "^Verificate che l'aliquota d'imposta per questo adeguamento sia corretta." active_distributors_not_ready_for_checkout_message_singular: >- L'hub %{distributor_names} figura in un ciclo di richieste attivo, ma non ha - metodi di consegna e di pagamento validi. Finché non li imposti, i consumatori - non potranno acquistare da questo hub. + metodi di consegna e di pagamento validi. Finché non li imposti, i clienti non + potranno acquistare da questo hub. active_distributors_not_ready_for_checkout_message_plural: >- - Gli hub %{distributor_names}figurano in un ciclo di richieste attivo, ma non - hanno metodi di consegna e di pagamento validi. Finché non li imposti, i consumatori - non potranno acquistare da questi hub. + I distributori %{distributor_names} figurano in un ciclo di richieste attivo, + ma non hanno metodi di consegna e di pagamento validi. Finché non li imposti, + i clienti non potranno acquistare da questi distributori. enterprise_fees_update_notice: Le tariffe della tua azienda sono state aggiornate. enterprise_register_package_error: "Per favore seleziona un pacchetto" enterprise_register_error: "Non abbiamo potuto completare la registrazione per %{enterprise}" @@ -2304,6 +2330,10 @@ it: resolve_errors: 'Per favore risolvi i seguenti errori:' more_items: "+ %{count} ancora" default_card_updated: Carta predefinita aggiornata + cart: + add_to_cart_failed: > + C'è stato un problema nell'aggiungere questo prodotto al carrello. Forse + non é più disponibile o il negozio sta chiudendo. admin: enterprise_limit_reached: "Hai raggiunto il limite standard di aziende per account. Scrivi a %{contact_email} se hai bisogno di aumentarlo." modals: @@ -2315,9 +2345,9 @@ it: title: Regole Tag overview: Panoramica overview_text: > - Le regole per le tag forniscono un modo per definire quali elementi - sono visibili, o a quali utenti. Gli elementi possono essere: metodi - di consegna, metodi di pagamento, prodotti e cicli di richieste. + Le regole per le tag forniscono un modo per descrivere quali elementi + sono visibili, o a quali utenti. Gli elementi possono essere: Metodi + di Consegna, Metodi di Pagamento, Prodotti e Cicli d'Ordine. by_default_rules: "Regole predefinite" by_default_rules_text: > Le regole predefinite ti permettono di nascondere gli elementi affinché @@ -2560,7 +2590,7 @@ it: edit_profile: "modifica profilo" add_products_to_inventory: "aggiungi prodotti all'inventario" resources: - could_not_delete_customer: 'Non è possibile annullare utente' + could_not_delete_customer: 'Non è possibile cancellare il cliente' product_import: confirmation: | Questo imposterà il livello delle scorte a zero su tutti i prodotti per questa @@ -2569,7 +2599,7 @@ it: create_failure: "Impossibile creare il ciclo dell'ordine" update_success: 'Il tuo ciclo di richieste è stato aggiornato' update_failure: "Impossibile aggiornare il ciclo dell'ordine" - no_distributors: Non ci sono distributori in questo ciclo dell'ordine. Questo ciclo dell'ordine non sarà visibile ai consumatori fino a quando non ne verrà aggiunto uno. Vuoi continuare a salvare questo ciclo dell'ordine? + no_distributors: Non ci sono distributori in questo ciclo d'ordine. Questo ciclo d'ordine non sarà visibile ai clienti fino a quando non ne verrà aggiunto uno. Vuoi continuare a salvare questo ciclo d'ordine? enterprises: producer: "Produttore" non_producer: "Non-produttore" @@ -2695,7 +2725,7 @@ it: fee_type: "Tipo di tariffa" enterprise_name: "Proprietario dell'azienda" fee_name: "Nome della tariffa" - customer_name: "Consumatore" + customer_name: "Cliente" fee_placement: "Posizionamento della tariffa" fee_calculated_on_transfer_through_name: "Calcolo della commissione sul trasferimento tramite" tax_category_name: "Categoria d'imposta" @@ -2705,7 +2735,7 @@ it: fee_type: "Tipo di tariffa" enterprise_name: "Proprietario dell'azienda" fee_name: "Nome della tariffa" - customer_name: "Consumatore" + customer_name: "Cliente" fee_placement: "Posizionamento della tariffa" fee_calculated_on_transfer_through_name: "Calcolo della commissione sul trasferimento tramite" tax_category_name: "Categoria d'imposta" @@ -2714,9 +2744,10 @@ it: order: "Gentile Richiesta" distribution: "Distribuzione" order_details: "Dettagli ordine" - customer_details: "Dettagli cliente" + customer_details: "Dettagli Cliente" adjustments: "Regolazioni" payments: "Pagamenti" + return_authorizations: "Authorizationi reso" payment: "Pagamento" payment_method: "Metodo di pagamento" shipment: "Spedizione" @@ -2763,8 +2794,8 @@ it: cannot_set_shipping_method_without_address: "Impossibile impostare il metodo di spedizione finché non vengono forniti i dettagli del cliente." no_tracking_present: "Nessun dettaglio di tracciamento fornito." order_total: "Ordine totale" - customer_details: "Dettagli cliente" - customer_search: "Ricerca clienti" + customer_details: "Dettagli Cliente" + customer_search: "Ricerca Clienti" choose_a_customer: "Scegli un cliente" account: "Account" billing_address: "Indirizzo di fatturazione" @@ -2782,10 +2813,18 @@ it: use_billing_address: "Utilizzare l'indirizzo di fatturazione" adjustments: "Regolazioni" continue: "Continua" - fill_in_customer_info: "Si prega di compilare le informazioni del cliente" + fill_in_customer_info: "Per favore compila le informazioni del cliente" new_payment: "Nuovo pagamento" capture: "Cattura" void: "vuoto" + login: "Login" + password: "Password" + signature: "Firma" + solution: "Soluzione" + landing_page: "Landing Page" + server: "Server" + test_mode: "Modalità di Test" + logourl: "Logourl" configurations: "Configurazioni" general_settings: "Impostazioni generali" site_name: "Nome del sito" @@ -2850,8 +2889,6 @@ it: abbreviation: "Abbreviazione" new_state: "Nuovo stato" payment_methods: "Metodi di pagamento" - new_payment_method: "Nuovo metodo di pagamento" - provider: "Provider" taxonomies: "Tassonomie" new_taxonomy: "Nuova tassonomia" back_to_taxonomies_list: "Torna all'elenco delle tassonomie" @@ -2904,6 +2941,12 @@ it: options: "Opzioni" actions: update: "Aggiorna" + shared: + error_messages: + errors_prohibited_this_record_from_being_saved: + one: "1 errore ha proibito il salvataggio di questo record:" + other: "%{count} errori hanno proibito il salvataggio di questo record:" + there_were_problems_with_the_following_fields: "Si sono verificati problemi con i seguenti campi" errors: messages: blank: "non può essere lasciato vuoto" @@ -2929,7 +2972,7 @@ it: order_cycles: "Cicli di richieste" enterprises: "Aziende" enterprise_relationships: "permessi" - customers: "Consumatori" + customers: "Clienti" groups: "Gruppi" product_properties: index: @@ -3005,12 +3048,13 @@ it: completed_at: "Completo al" number: "Numero" state: "Stato" - email: "Mail consumatore" + email: "E-mail Cliente" invoice: issued_on: "Emesso il" tax_invoice: "FATTURA DELLE TASSE" code: "Codice" from: "Da" + to: "Pagamento a" shipping: "Spedizione" form: distribution_fields: @@ -3030,7 +3074,7 @@ it: other: "Hai il %{count} di prodotti disponibili" order_cycles: order_cycles: "Cicli di richieste" - order_cycles_tip: "I cicli di richieste determinano dove e quando i tuoi prodotti sono disponibili per i consumatori." + order_cycles_tip: "I cicli di richieste determinano dove e quando i tuoi prodotti sono disponibili per i clienti." you_have_active: zero: "Non hai nessun ciclo di richieste attivo." one: "Hai un ciclo di richieste attivo." @@ -3045,6 +3089,8 @@ it: zone: "Zone" calculator: "Calcolatrice" display: "Visualizza" + both: "Entrambi Checkout e Back office" + back_end: "Solo Back office" no_shipping_methods_found: "Nessun metodo di spedizione trovato" new: new_shipping_method: "Nuovo metodo di spedizione" @@ -3056,11 +3102,30 @@ it: form: categories: "categorie" zones: "Zone" + both: "Entrambi Checkout e Back Office" + back_end: "Solo Back office" + deactivation_warning: "Disattivare un metodo di spedizione può far sparire il metodo di spedizione dalla tua lista. Alternativamente, puoi nascondere il metodo di spedizione dalla pagina di checkout impostando l'opzione 'Visualizza' su 'Solo Back office'." payment_methods: + index: + payment_methods: "Metodi di pagamento" + new_payment_method: "Nuovo metodo di pagamento" + name: "Nome" + products_distributor: "Distributore" + provider: "Provider" + environment: "Ambiente" + display: "Visualizza" + active: "Attivo" + both: "Entrambi" + front_end: "Solo checkout" + back_end: "Solo Back office" + active_yes: "Sì" + active_no: "No" + no_payment_methods_found: "Nessun metodo di pagamento trovato" new: new_payment_method: "Nuovo metodo di pagamento" back_to_payment_methods_list: "Torna all'elenco dei metodi di pagamento" edit: + new: "Nuovo" editing_payment_method: "Modifica metodo di pagamento" back_to_payment_methods_list: "Torna all'elenco dei metodi di pagamento" stripe_connect: @@ -3076,6 +3141,21 @@ it: account_id: Account ID business_name: Ragione sociale charges_enabled: Cambi Consentiti + form: + name: "Nome" + description: "Descrizione" + environment: "Ambiente" + display: "Visualizza" + active: "Attivo" + active_yes: "Sì" + active_no: "No" + both: "Entrambi Checkout e Back Office" + front_end: "Solo checkout" + back_end: "Solo Back office" + tags: "Tag" + deactivation_warning: "Disattivare un metodo di pagamento può far sparire il metodo di pagamento dalla tua lista. Alternativamente, puoi nascondere il metodo di pagamento dalla pagina di checkout impostando l'opzione 'Visualizza' su 'Solo Back office'." + providers: + provider: "Provider" payments: source_forms: stripe: @@ -3133,7 +3213,7 @@ it: bulk_coop_supplier_report: 'Totali per fornitore - tabella' bulk_coop_allocation: 'Assegnazione - tabella' bulk_coop_packing_sheets: 'Imballaggio - tabella' - bulk_coop_customer_payments: 'Pagamenti clienti - tabella' + bulk_coop_customer_payments: 'Bulk Co-op - Pagamenti Clienti' users: index: listing_users: "Elenco Utenti" @@ -3175,7 +3255,10 @@ it: price: "Prezzo" display_as: "Visualizza come" display_name: "Nome da visualizzare" + display_as_placeholder: 'es. 2 kg' + display_name_placeholder: 'es. Pomodori' autocomplete: + out_of_stock: "Esaurito" producer_name: "Produttore" unit: "Unità" shared: @@ -3213,6 +3296,7 @@ it: format: '%Y-%m-%d' js_format: 'aa-mm-gg' orders: + error_flash_for_unavailable_items: "Un oggetto nel tuo carrello è diventato non disponibile, Per favore aggiorna le quantità selezionate." edit: login_to_view_order: "Effettua il login per visualizzare il tuo ordine." bought: @@ -3240,12 +3324,17 @@ it: invalid: invalido order_mailer: cancel_email: - customer_greeting: "Ciao %{name}!" - instructions: "Il tuo ordine è stato ANNULLATO. Per favore conserva queste informazioni di cancellazione per i tuoi record." - order_summary_canceled: "Riepilogo dell'ordine [CANCELLATO]" + customer_greeting: "Caro %{name}," + instructions_html: "Il tuo ordine con %{distributor} è stato CANCELLATO. Per favore conserva questa informazione per i tuoi dati." + dont_cancel: "Se hai cambiato idea o non desideri annullare questo ordine, ti preghiamo di contattare%{email}" + order_summary_canceled_html: "Riepilogo Ordine #%{number} [CANCELLATO]" + details: "Qui ci sono i dettagli di quello che hai ordinato:" + unpaid_order: "Il tuo ordine risulta pendente nessun rimborso è stato eseguito" + paid_order: "Il tuo ordine era già stato pagato così %{distributor} ha rimborsato l'intero costo" + credit_order: "Il tuo ordine è stato pagato, quindi il tuo acconto è stato accreditato" subject: "Cancellazione dell'ordine" confirm_email: - subject: "Conferma dell'ordine" + subject: "Conferma Ordine" invoice_email: hi: "Ciao %{name}" invoice_attached_text: 'Aggiunge una fattura per il tuo recente ordine di ' diff --git a/config/locales/nb.yml b/config/locales/nb.yml index f8a72d5423..bf8f4cba79 100644 --- a/config/locales/nb.yml +++ b/config/locales/nb.yml @@ -23,6 +23,8 @@ nb: base: "Kredittkort" order_cycle: orders_close_at: Lukkedato + variant_override: + count_on_hand: "Tilgjengelig" errors: models: spree/user: @@ -368,8 +370,10 @@ nb: title: "Matomo Innstillinger" matomo_url: "Matomo URL" matomo_site_id: "Matomo Site ID" - info_html: "Matomo er en web- og mobilanalyse. Du kan enten hoste Matomo selv eller bruke en skytjeneste. Se matomo.org for mer informasjon." + matomo_tag_manager_url: "Matomo Tag Manager URL" + info_html: "Matomo er en web- og mobilanalyseapplikasjon. Du kan enten sette opp en egen server for Matomo eller bruke en skybasert tjeneste. Se matomo.org for mer informasjon." config_instructions_html: "Her kan du konfigurere OFN-Matomo integrasjonen. URL til Matomo nedenfor skal peke på Matomo-instansen der brukersporingsinformasjonen skal sendes til; Hvis den er tom, blir Matomo-brukersporing deaktivert. Site-ID feltet er ikke obligatorisk, men nyttig hvis du sporer mer enn ett nettsted på en enkelt Matomo-instans; den kan bli funnet på Matomo-konsollen." + config_instructions_tag_manager_html: "Å sette Matomo Tag Manager URL muliggjør Matomo Tag Manager. Dette verktøyet lar deg konfigurere analysehendelser. Matomo Tag Manager URL kopieres fra Installer kode-delen i Matomo Tag Manager. Forsikre deg om at du velger riktig beholder og miljø, da disse alternativene endrer nettadressen." customers: index: new_customer: "Ny kunde" @@ -403,6 +407,7 @@ nb: footer_and_external_links: Footer og eksterne lenker your_content: Ditt innhold user_guide: Brukermanual + map: Kart enterprise_fees: index: title: "Bedriftsavgifter" @@ -474,6 +479,7 @@ nb: line_number: "Linje %{number}:" encoding_error: "Vennligst sjekk språkinnstillingen til kildefilen din og kontroller at den er lagret med UTF-8-koding" unexpected_error: "Produktimport støtte på en uventet feil ved åpning av filen: %{error_message}" + malformed_csv: "Produktimport fant feil i CSV: %{error_message}" index: notice: "Beskjed" beta_notice: "Denne funksjonen er fremdeles i beta: du kan oppleve noen feil mens du bruker den. Ikke nøl med å kontakte support." @@ -686,6 +692,7 @@ nb: ofn_uid_tip: Den unike ID-en som brukes til å identifisere bedriften på Open Food Network. shipping_methods: name: "Navn" + applies: "Aktiv?" manage: "Administrer Leveringsmetoder" create_button: "Opprett Ny Leveringsmetode" create_one_button: "Opprett en nå" @@ -864,6 +871,7 @@ nb: incoming: "Innkommende" supplier: "Leverandør" products: "Produkter" + receival_details: "Mottaksdetaljer" fees: "Avgifter" save: "Lagre" save_and_next: "Lagre og Neste" @@ -1173,7 +1181,11 @@ nb: signup: "melde deg på" contact: "kontakt" require_customer_login: "Kun godkjente kunder kan få tilgang til denne butikken." + require_login_html: "Hvis du allerede er en godkjent kunde kan du fortsette til %{login} eller %{signup}." + require_login_2_html: "Vil du begynne å handle her? Vennligst %{contact} %{enterprise} og spør om å bli med." require_customer_html: "Hvis du vil begynne å handle her, vennligst %{contact} %{enterprise} for å spørre om å bli med." + select_oc: + select_oc_html: "Vennligst velg når du vil ha bestillingen din , for å se hvilke produkter som er tilgjengelige." card_could_not_be_updated: Kortet kunne ikke oppdateres card_could_not_be_saved: kort kunne ikke lagres spree_gateway_error_flash_for_checkout: "Det oppstod et problem med betalingsinformasjonen din: %{error}" @@ -1533,12 +1545,17 @@ nb: orders_changeable_orders_alert_html: Denne bestillingen er bekreftet, men du kan gjøre endringer til %{oc_close}. products_clear: Fjern products_showing: "Viser:" + products_results_for: "Resultater for" products_or: "eller" products_and: "og" + products_filters_in: "i" products_with: med + products_search: "Søk..." products_filter_by: "Filtrer på" products_filter_selected: "valgt" + products_filter_heading: "Filtre" products_filter_clear: "Fjern" + products_filter_done: "Ferdig" products_loading: "Laster produkter..." products_updating_cart: "Oppdaterer handlekurv..." products_cart_empty: "Handlekurv tom" @@ -1549,6 +1566,8 @@ nb: products_update_error_msg: "Lagring mislyktes." products_update_error_data: "Lagring mislyktes på grunn av ugyldige data:" products_changes_saved: "Endringene er lagret." + products_no_results_html: "Beklager, ingen resultater for %{query}" + products_clear_search: "Tøm søk" search_no_results_html: "Beklager, ingen treff på %{query}. Prøv på nytt?" components_profiles_popover: "Profiler har ikke butikk på Open Food Network men kan ha sin egen fysiske butikk eller nettbutikk et annet sted" components_profiles_show: "Vis profiler" @@ -2310,6 +2329,10 @@ nb: resolve_errors: Vennligst løse følgende feil more_items: "+ %{count} Flere" default_card_updated: Standardkort oppdatert + cart: + add_to_cart_failed: > + Det oppsto et problem med å legge dette produktet til handlekurven. Kanskje + den har blitt utilgjengelig eller butikken stenger. admin: enterprise_limit_reached: "Du har nådd standardgrensen for bedrifter per konto. Skriv til %{contact_email} hvis du trenger å øke den." modals: @@ -2719,6 +2742,7 @@ nb: customer_details: "Kundedetaljer" adjustments: "Justeringer" payments: "Betalinger" + return_authorizations: "Returautorisasjoner" payment: "Betaling" payment_method: "Betalingsmetode" shipment: "Leveranse" @@ -2788,6 +2812,14 @@ nb: new_payment: "Ny betaling" capture: "Fang" void: "Ugyldig" + login: "Logg inn" + password: "Passord" + signature: "Signatur" + solution: "Løsning" + landing_page: "Landingsside" + server: "Server" + test_mode: "Testmodus" + logourl: "Logourl" configurations: "Konfigurasjoner" general_settings: "Generelle innstillinger" site_name: "Sidenavn" @@ -2852,8 +2884,6 @@ nb: abbreviation: "Forkortelse" new_state: "Ny Region" payment_methods: "Betalingsmetoder" - new_payment_method: "Ny Betalingsmetode" - provider: "Tilbyder" taxonomies: "Taksonomier" new_taxonomy: "Ny Taksonomi" back_to_taxonomies_list: "Tilbake til Taksonomiliste" @@ -2906,6 +2936,12 @@ nb: options: "Valg" actions: update: "Oppdater" + shared: + error_messages: + errors_prohibited_this_record_from_being_saved: + one: "1 feil forbød å lagre denne posten:" + other: "%{count} feil forbød at denne posten ble lagret:" + there_were_problems_with_the_following_fields: "Det var problemer med følgende felt" errors: messages: blank: "kan ikke være tomt" @@ -3048,6 +3084,8 @@ nb: zone: "Sone" calculator: "Kalkulator" display: "Visning" + both: "Både Utsjekk og Backoffice" + back_end: "Kun backoffice" no_shipping_methods_found: "Ingen leveringsmetoder funnet" new: new_shipping_method: "Ny Leveringsmetode" @@ -3059,11 +3097,30 @@ nb: form: categories: "Kategorier" zones: "Soner" + both: "Både Utsjekk og Backoffice" + back_end: "Kun backoffice" + deactivation_warning: "Ved å deaktivere en leveringsmetode kan den forsvinne fra listen din. Alternativt kan du skjule en leveringsmetode fra kassen ved å sette alternativet 'Vis' til 'Kun backoffice'." payment_methods: + index: + payment_methods: "Betalingsmetoder" + new_payment_method: "Ny Betalingsmetode" + name: "Navn" + products_distributor: "Distributør" + provider: "Tilbyder" + environment: "Miljø" + display: "Visning" + active: "Aktiv" + both: "Begge" + front_end: "Bare Kasse" + back_end: "Kun backoffice" + active_yes: "Ja" + active_no: "Nei" + no_payment_methods_found: "Fant ingen betalingsmetoder" new: new_payment_method: "Ny Betalingsmetode" back_to_payment_methods_list: "Tilbake til listen over betalingsmetoder" edit: + new: "Ny" editing_payment_method: "Redigerer betalingsmetode" back_to_payment_methods_list: "Tilbake til listen over betalingsmetoder" stripe_connect: @@ -3079,6 +3136,21 @@ nb: account_id: Konto-ID business_name: Bedriftsnavn charges_enabled: Avgifter Aktivert + form: + name: "Navn" + description: "Beskrivelse" + environment: "Miljø" + display: "Visning" + active: "Aktiv" + active_yes: "Ja" + active_no: "Nei" + both: "Både Kasse og Backoffice" + front_end: "Kun Kasse" + back_end: "Kun backoffice" + tags: "Merkelapper" + deactivation_warning: "Ved å deaktivere en betalingsmetode kan den forsvinne fra listen din. Alternativt kan du skjule en betalingsmetode fra kassen ved å sette alternativet "Vis" til "Kun Backoffice"." + providers: + provider: "Tilbyder" payments: source_forms: stripe: @@ -3181,6 +3253,7 @@ nb: display_as_placeholder: 'f.eks. 2 kg' display_name_placeholder: 'f.eks. Tomater' autocomplete: + out_of_stock: "Ikke på Lager" producer_name: "Produsent" unit: "Enhet" shared: @@ -3218,6 +3291,7 @@ nb: format: '%Y-%m-%d' js_format: 'yy-mm-dd' orders: + error_flash_for_unavailable_items: "En vare i handlekurven din er blitt utilgjengelig. Oppdater valgte mengder." edit: login_to_view_order: "Vennligst logg inn for å se bestillingen din." bought: @@ -3245,9 +3319,14 @@ nb: invalid: ugyldig order_mailer: cancel_email: - customer_greeting: "Hei %{name}!" - instructions: "Din bestilling har blitt avbrutt. Vennligst behold denne avbestillingsinformasjonen som referanse." - order_summary_canceled: "Bestillingssammendrag [KANSELLERT]" + customer_greeting: "Kjære %{name}," + instructions_html: "Bestillingen din med %{distributor} er AVBRUTT . Vennligst ta vare på denne avbestillingsinformasjonen til senere." + dont_cancel: "Hvis du har ombestemt deg eller ikke ønsker å kansellere denne bestillingen, kan du kontakte %{email}" + order_summary_canceled_html: "Sammendrag Bestilling # %{number} [AVBRUTT]" + details: "Her er detaljene om hva du bestilte:" + unpaid_order: "Bestillingen din var ubetalt, så ingen refusjon har blitt gjort" + paid_order: "Bestillingen din ble betalt, så %{distributor} har refundert hele beløpet" + credit_order: "Bestillingen din ble betalt så kontoen din er kreditert" subject: "Kansellering av bestilling" confirm_email: subject: "Ordrebekreftelse" diff --git a/config/locales/nl_BE.yml b/config/locales/nl_BE.yml index d17754b707..2a80116410 100644 --- a/config/locales/nl_BE.yml +++ b/config/locales/nl_BE.yml @@ -23,6 +23,8 @@ nl_BE: base: "Kredietkaart" order_cycle: orders_close_at: Sluitingsdatum + variant_override: + count_on_hand: "Bij de Hand" errors: models: spree/user: @@ -354,7 +356,6 @@ nl_BE: title: "Matomo instellingen" matomo_url: "Matomo URL" matomo_site_id: "Matomo Site ID" - info_html: "Matomo is een Web en Mobile Analytics. U kunt Matomo on-premises hosten of gebruik maken van een cloud-hosted service. Zie matomo.org voor meer informatie." config_instructions_html: "Hier kunt u de OFN Matomo integratie configureren. De Matomo URL hieronder zou moeten verwijzen naar de Matomo instantie waar de gebruiker tracking informatie naartoe wordt gestuurd; als deze leeg wordt gelaten, wordt Matomo gebruiker tracking uitgeschakeld. Het veld Site ID is niet verplicht, maar handig als je meer dan één website volgt op één Matomo instance; het is te vinden op de Matomo instance console. Vertaald met www.DeepL.com/Translator" customers: index: @@ -389,6 +390,7 @@ nl_BE: footer_and_external_links: Voettekst en externe links your_content: Uw inhoud user_guide: Gebruikershandleiding + map: Kaart enterprise_fees: index: title: "Ondernemingsvergoedingen" @@ -2667,6 +2669,8 @@ nl_BE: new_payment: "Nieuwe betaling" capture: "Capture" void: "leegte" + login: "Log in" + password: "Wachtwoord" configurations: "configuraties " general_settings: "Algemene instellingen" site_name: "Website Naam" @@ -2731,8 +2735,6 @@ nl_BE: abbreviation: "Afkortingen " new_state: "Nieuw Provincie" payment_methods: "Betalingsmethode" - new_payment_method: "Nieuwe betalingswijze" - provider: "Leverancier" taxonomies: "Taxonomies " new_taxonomy: "Nieuwe taxonomie " back_to_taxonomies_list: "Terug naar de lijst Taxonomies" @@ -2897,10 +2899,23 @@ nl_BE: categories: "Categorieën" zones: "Zones " payment_methods: + index: + payment_methods: "Betalingsmethode" + new_payment_method: "Nieuwe betalingswijze" + name: "Naam" + products_distributor: "Distributeur" + provider: "Leverancier" + environment: "Omgeving" + display: "Display" + active: "Aktief" + both: "Beide" + active_yes: "Ya" + active_no: "Néé" new: new_payment_method: "Nieuwe betalingswijze" back_to_payment_methods_list: "Terug naar de lijst van de betalingswijzes" edit: + new: "Nieuw" editing_payment_method: "Wijziging van de betalingswijze" back_to_payment_methods_list: "Terug naar de lijst van de betalingswijzes" stripe_connect: @@ -2916,6 +2931,17 @@ nl_BE: account_id: Account ID business_name: Bedrijfsnaam charges_enabled: Kosten ingeschakeld + form: + name: "Naam" + description: "Beschrijving" + environment: "Omgeving" + display: "Display" + active: "Aktief" + active_yes: "Ya" + active_no: "Néé" + tags: "Tags" + providers: + provider: "Leverancier" payments: source_forms: stripe: @@ -3005,6 +3031,7 @@ nl_BE: price: "Prijs" display_as: "Weergeven als" autocomplete: + out_of_stock: "Geen voorraad" producer_name: "Producent" unit: "Unit" shared: @@ -3069,9 +3096,6 @@ nl_BE: invalid: fout order_mailer: cancel_email: - customer_greeting: "Hello%{name}!" - instructions: "Uw bestelling is GEANNULEERD. Bewaar deze annuleringsinformatie voor uw administratie." - order_summary_canceled: "Overzicht van de bestelling [KANNELD]" subject: "Annulering van de bestelling" confirm_email: subject: "Bestellingsinformatie" diff --git a/config/locales/pt.yml b/config/locales/pt.yml index 2b46b8d146..2e4d9c06de 100644 --- a/config/locales/pt.yml +++ b/config/locales/pt.yml @@ -21,6 +21,8 @@ pt: base: "Cartão de Crédito" order_cycle: orders_close_at: Data de fecho + variant_override: + count_on_hand: "Disponível" errors: models: spree/user: @@ -347,7 +349,6 @@ pt: title: "Configurações Matomo" matomo_url: "URL Matomo" matomo_site_id: "Site ID Matomo" - info_html: "Matomo é uma ferramenta de análise web e mobile. Pode instalar o Matomo no seu servidor ou utilizar um serviço na cloud. Veja matomo.org para mais informações." config_instructions_html: "Aqui pode configurar a integração com Matomo. O URL Matomo em baixo deve apontar para o serviror para onde a informação de tracking de utilizadores será enviada; se deixado vazio, o tracking de utilizadores através do Matomo ficará desactivado. O campo Site ID não é obrigatório mas útil se estive a fazer tracking de mais do que um website numa instância única do Matomo; pode ser encontrado na consola da instância Matomo." customers: index: @@ -382,6 +383,7 @@ pt: footer_and_external_links: Rodapé e Ligações Externas your_content: O seu conteúdo user_guide: Manual do Utilizador + map: Mapa enterprise_fees: index: title: "Taxas de Organização" @@ -2623,6 +2625,8 @@ pt: fill_in_customer_info: "Por favor preencha informação do/a consumidor/a" new_payment: "Novo Pagamento" capture: "Capturar" + login: "Entrar" + password: "Palavra-passe" configurations: "Configurações" general_settings: "Configurações Gerais" site_name: "Nome do Site" @@ -2687,8 +2691,6 @@ pt: abbreviation: "Abreviatura" new_state: "Nova Região" payment_methods: "Métodos de pagamento" - new_payment_method: "Novo Método de Pagamento" - provider: "Fornecedor" taxonomies: "Taxonomias" new_taxonomy: "Nova Taxonomia" back_to_taxonomies_list: "Voltar à Lista de Taxonomias" @@ -2837,10 +2839,22 @@ pt: form: zones: "Zonas" payment_methods: + index: + payment_methods: "Métodos de pagamento" + new_payment_method: "Novo Método de Pagamento" + name: "Nome" + products_distributor: "Distribuidor" + provider: "Fornecedor" + environment: "Ambiente" + display: "Mostrar" + active: "Ativo" + active_yes: "Sim" + active_no: "Não" new: new_payment_method: "Novo Método de Pagamento" back_to_payment_methods_list: "Voltar à Lista de Métodos de Pagamento" edit: + new: "Novo" editing_payment_method: "Editar Método de Pagamento" back_to_payment_methods_list: "Voltar à Lista de Métodos de Pagamento" stripe_connect: @@ -2856,6 +2870,17 @@ pt: account_id: ID de Conta business_name: Nome do Negócio charges_enabled: Taxas activas + form: + name: "Nome" + description: "Descrição" + environment: "Ambiente" + display: "Mostrar" + active: "Ativo" + active_yes: "Sim" + active_no: "Não" + tags: "Etiquetas" + providers: + provider: "Fornecedor" payments: source_forms: stripe: @@ -2943,6 +2968,7 @@ pt: price: "Preço" display_as: "Mostrar como" autocomplete: + out_of_stock: "Sem Stock" producer_name: "Produtor" unit: "Unidade" shared: @@ -3007,9 +3033,6 @@ pt: invalid: inválido order_mailer: cancel_email: - customer_greeting: "Olá %{name}!" - instructions: "A sua encomenda foi cancelada. Para seu registo, por favor guarde esta informação de cancelamento." - order_summary_canceled: "Sumário de Encomenda [CANCELADA]" subject: "Cancelamento de Encomenda" confirm_email: subject: "Confimação de Encomenda" diff --git a/config/locales/pt_BR.yml b/config/locales/pt_BR.yml index 718dd700c5..e2cae6de9f 100644 --- a/config/locales/pt_BR.yml +++ b/config/locales/pt_BR.yml @@ -23,6 +23,8 @@ pt_BR: base: "Cartão de Crédito" order_cycle: orders_close_at: Dia de fechamento + variant_override: + count_on_hand: "Disponível" errors: models: spree/user: @@ -53,7 +55,7 @@ pt_BR: producer_ids: "Produtores" order_cycle_ids: "Ciclos de pedidos" enterprise_fee_ids: "Nomes das taxas" - shipping_method_ids: "Métodos de envio" + shipping_method_ids: "Método de Envio" payment_method_ids: "Métodos de pagamento" errors: messages: @@ -204,7 +206,7 @@ pt_BR: ongoing: Em progresso bill_address: Endereço de Cobrança ship_address: Endereço de Entrega - sort_order_cycles_on_shopfront_by: "Ordenar Ciclo de Pedidos na Loja Virtual Por" + sort_order_cycles_on_shopfront_by: "Ordenar Ciclos de Pedidos na Loja Virtual Por" required_fields: Campos obrigatórios são indicados com um asterisco select_continue: Selecionar e continuar remove: Remover @@ -219,7 +221,7 @@ pt_BR: edit: Editar clone: Cópia distributors: Distribuidores - bulk_order_management: Gerenciamento de Pedidos em Atacado + bulk_order_management: Gestão de Pedidos em Atacado enterprises: Iniciativas enterprise_groups: Grupos reports: Relatórios @@ -303,7 +305,7 @@ pt_BR: shop: Loja sku: SKU status_state: Estado - tags: Etiqueta + tags: Tags variant: Variante weight: Peso volume: Tamanho @@ -329,7 +331,7 @@ pt_BR: viewing: "Visualizando: %{current_view_name}" description: Descrição whats_this: O que é isso? - tag_has_rules: "Regras existentes para essa etiqueta: %{num}" + tag_has_rules: "Regras existentes para essa tag: %{num}" has_one_rule: "possui uma regra" has_n_rules: "tem %{num} regras" unsaved_confirm_leave: "Existem alterações não salvas nesta página. Continuar sem salvar? " @@ -368,7 +370,6 @@ pt_BR: title: "Configurações do Matomo" matomo_url: "Matomo URL" matomo_site_id: "Matomo Site ID" - info_html: "Matomo é uma Web e Mobile Analytics. Você pode hospedar o Matomo localmente ou usar um serviço hospedado na nuvem. Veja matomo.org para mais informações." config_instructions_html: "Aqui você pode configurar a integração do OFN Matomo. O URL do Matomo abaixo deve apontar para a instância do Matomo para onde as informações de rastreamento do usuário serão enviadas; se for deixado em branco, o rastreamento de usuários do Matomo será desativado. O campo ID do site não é obrigatório, mas é útil se você estiver controlando mais de um site em uma única instância do Matomo. ele pode ser encontrado no console da instância Matomo." customers: index: @@ -403,6 +404,7 @@ pt_BR: footer_and_external_links: Rodapé e links externos your_content: Seu conteúdo user_guide: Guia do Usuário + map: Mapa enterprise_fees: index: title: "Taxas da iniciativa" @@ -450,7 +452,7 @@ pt_BR: editing_product: "Editando Produto" tabs: product_details: "Detalhes do Produto" - group_buy_options: "Opções de Grupo de Compras" + group_buy_options: "Opções de Compra em Grupo" images: "Imagens" variants: "Variantes" product_properties: "Propriedades do produto" @@ -583,18 +585,18 @@ pt_BR: order_no: "Pedido nº" order_date: "Concluído em" max: "Máximo" - product_unit: "Produto: unidade" + product_unit: "Produto: Unidade" weight_volume: "Peso/Volume" ask: "Perguntar?" - page_title: "Gestão de Pedidos em Atacado" + page_title: "Gestão de Pedidos em Atacado" actions_delete: "Deletar selecionado" loading: "Carregando pedidos" no_results: "Nenhum pedido encontrado. " - group_buy_unit_size: "Unidade de Medida para Grupo de Compras" + group_buy_unit_size: "Unidade de Medida para Compra em Grupo" 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 " + current_fulfilled_units: "Pedidos / Limite Mínimo (Atual)" + max_fulfilled_units: "Pedidos / Limite Mínimo (Max)" 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 medida" select_variant: "Selecione uma variante" @@ -687,22 +689,22 @@ pt_BR: shipping_methods: name: "Nome" applies: "Ativo?" - manage: "Gerenciar formas de envio" + manage: "Gerenciar métodos de envio" create_button: "Criar nova forma de envio" create_one_button: "Criar um agora" - no_method_yet: "Você ainda não tem nenhuma forma de envio." + no_method_yet: "Você ainda não tem nenhum método de envio." shop_preferences: - shopfront_requires_login: "Loja virtual visível publicamente?" + shopfront_requires_login: "Loja virtual visível ao público?" shopfront_requires_login_tip: "Escolha se os clientes precisarão fazer o login para ver os produtos da loja virtual, ou se eles estarão visíveis para todos." shopfront_requires_login_false: "Publico" shopfront_requires_login_true: "Disponível somente para clientes registrados" recommend_require_login: "Recomendamos pedir login dos usuários quando permitido que pedidos possam ser alterados." - allow_guest_orders: "Pedidos dos convidados" + allow_guest_orders: "Pedidos de convidados" allow_guest_orders_tip: "Permitir o checkout como convidado, ou requisitar um usuário registrado. " allow_guest_orders_false: "Requisitar o login para fazer pedidos" allow_guest_orders_true: "Permitir checkout de convidados" allow_order_changes: "Mudar pedidos" - allow_order_changes_tip: "Permitir que os consumidores mudem seus pedidos enquanto a compra estiver aberta." + allow_order_changes_tip: "Permitir que os consumidores mudem seus pedidos enquanto o ciclo de pedidos estiver aberto." allow_order_changes_false: "Pedidos enviados não podem ser mudados ou cancelados." allow_order_changes_true: "Consumidor pode mudar ou cancelar pedidos enquanto a compra estiver aberta." enable_subscriptions: "Assinaturas" @@ -721,7 +723,7 @@ pt_BR: Uma mensagem que forneça uma explicação detalhada sobre o porque de a loja estar fechada e quando os consumidores podem esperar que abra novamente, a ser exibida quando não houver nenhum ciclo de pedidos ativo. - shopfront_category_ordering: "Organização das Categorias da Loja Virtual" + shopfront_category_ordering: "Organização da Loja Virtual por Categorias" open_date: "Dia de abertura" close_date: "Dia de fechamento" social: @@ -746,11 +748,11 @@ pt_BR: by_default: Por padrão no_rules_yet: Ainda não existe nenhuma regra padrão add_new_button: '+ Adicionar nova regra padrão' - no_tags_yet: Nenhuma etiqueta foi aplicada a esta iniciativa - no_rules_yet: Nenhuma regra foi aplicada a essa etiqueta + no_tags_yet: Nenhuma tag foi aplicada a esta iniciativa + no_rules_yet: Nenhuma regra foi aplicada a essa tag for_customers_tagged: 'Para consumidores marcados:' add_new_rule: '+ Adicionar nova regra' - add_new_tag: '+ Adicionar nova etiqueta' + add_new_tag: '+ Adicionar nova tag' users: email_confirmation_notice_html: "Confirmação de e-mail está pendente. Enviamos um e-mail de confirmação para %{email}." resend: Reenviar @@ -774,8 +776,8 @@ pt_BR: properties: Propriedades payment_methods: Formas de pagamento payment_methods_tip: Essa iniciativa não tem formas de pagamento - shipping_methods: Formas de entrega - shipping_methods_tip: Essa iniciativa não tem formas de entrega + shipping_methods: Métodos de envio + shipping_methods_tip: Essa iniciativa não tem métodos de envio enterprise_fees: Taxas da iniciativa enterprise_fees_tip: Essa iniciativa não tem taxas admin_index: @@ -875,7 +877,7 @@ pt_BR: outgoing: "Saída" distributor: "Distribuidor" products: "Produtos" - tags: "Etiqueta" + tags: "Tag" delivery_details: "Sobre a Entrega" fees: "Taxas" previous: "Anterior" @@ -921,8 +923,8 @@ pt_BR: outgoing: Saída distributor: Distribuidor products: Produtos - tags: Etiquetas - add_a_tag: Adicionar etiqueta + tags: Tags + add_a_tag: Adicionar tag delivery_details: Detalhes de entrega/retirada index: schedule: Cronograma @@ -948,7 +950,7 @@ pt_BR: orders_present: Esse ciclo de pedidos foi selecionado por um cliente e não pode ser excluído. Para impedir que os clientes acessem, feche-o. schedule_present: Esse ciclo de pedidos está vinculado a um cronograma e não pode ser excluído. Desvincule ou exclua o cronograma primeiro. bulk_update: - no_data: Hum, algo deu errado. Não foram encontrados dados do ciclo do pedido. + no_data: Hum, algo deu errado. Não foram encontrados dados do ciclo do pedidos. date_warning: msg: Esse ciclo de pedidos está vinculado a %{n}de pedidos abertos. Alterar essa data agora não afetará nenhum pedido que já tenha sido feito, mas deve ser evitado, se possível. Tem certeza de que deseja continuar? cancel: Cancelar @@ -1080,7 +1082,7 @@ pt_BR: details: Detalhes address: Endereço products: Produtos - no_open_or_upcoming_order_cycle: "Nenhum ciclo de pedido futuro" + no_open_or_upcoming_order_cycle: "Nenhum ciclo de pedidos agendado" products_panel: save: "SALVAR" saving: "SALVANDO" @@ -1145,7 +1147,7 @@ pt_BR: cart: "Carrinho" joyride: checkout: "Fechar pedido agora" - already_ordered_products: "Já pediu neste ciclo de pedido" + already_ordered_products: "Já pediu neste ciclo de pedidos" register_call: selling_on_ofn: "Interessado em registrar a sua iniciativa na Open Food Brasil?" register: "Registre-se aqui" @@ -1248,7 +1250,7 @@ pt_BR: city_placeholder: 'ex: República' postcode: CEP postcode_placeholder: 'ex: 05429-130' - suburb: Bairro + suburb: Cidade state: Estado country: País unauthorized: Não autorizado @@ -1688,11 +1690,11 @@ pt_BR: products_cart_distributor_change: "O distribuidor para este pedido será trocado para %{name} se você adicionar este produto no carrinho." products_cart_distributor_is: "O distribuidor para este pedido é %{name}." products_distributor_error: "Por favor complete seu pedido no %{link} antes de comprar com outro distribuidor." - products_oc: "Ciclo de pedido para seu pedido:" - products_oc_change: "O ciclo de pedido para esse pedido será trocada para %{name} se você adicionar este produto ao carrinho." - products_oc_is: "O ciclo de pedido para este pedido é %{name}." + products_oc: "Ciclo de pedidos para seu pedido:" + products_oc_change: "O ciclo de pedidos para esse pedido será trocado para %{name} se você adicionar este produto ao carrinho." + products_oc_is: "O ciclo de pedidos para este pedido é %{name}." products_oc_error: "Por favor complete seu pedido no %{link} antes de comprar em outro ciclo de pedido." - products_oc_current: "seu ciclo de pedido atual" + products_oc_current: "seu ciclo de pedidos atual" products_max_quantity: Quantidade máxima products_distributor: Distribuidor products_distributor_info: Quando você selecionar um distribuidor para seu pedido, o endereço e data para retirada serão exibidos aqui. @@ -1927,7 +1929,7 @@ pt_BR: admin_enterprise_groups_contact: "Contato" admin_enterprise_groups_contact_phone_placeholder: "ex: 987654321" admin_enterprise_groups_contact_address1_placeholder: "ex: Rua Alta, 123" - admin_enterprise_groups_contact_city: "Bairro" + admin_enterprise_groups_contact_city: "Cidade" admin_enterprise_groups_contact_city_placeholder: "ex: República" admin_enterprise_groups_contact_zipcode: "CEP" admin_enterprise_groups_contact_zipcode_placeholder: "ex: 02341-001" @@ -1961,8 +1963,8 @@ pt_BR: flat_rate_per_order: "Taxa fixa ( por pedido)" flexible_rate: "Tarifa flexível" price_sack: "Preço da saca" - new_order_cycles: "Novo ciclo de pedidos" - new_order_cycle: "Novo ciclo de pedido" + new_order_cycles: "Novos ciclos de pedidos" + new_order_cycle: "Novo ciclo de pedidos" select_a_coordinator_for_your_order_cycle: "Selecione um coordenador para o seu ciclo de pedidos" notify_producers: 'Notificar produtores' edit_order_cycle: "Editar ciclo de pedidos" @@ -1992,7 +1994,7 @@ pt_BR: spree_admin_overview_enterprises_footer: "GERENCIAR MINHAS INICIATIVAS" spree_admin_enterprises_hubs_name: "Nome" spree_admin_enterprises_create_new: "CRIAR NOVA" - spree_admin_enterprises_shipping_methods: "Métodos de entrega" + spree_admin_enterprises_shipping_methods: "Métodos de envio" spree_admin_enterprises_fees: "Taxas da iniciativa" spree_admin_enterprises_none_create_a_new_enterprise: "CRIAR NOVA INICIATIVA" spree_admin_enterprises_none_text: "Você ainda não possui nenhuma iniciativa" @@ -2016,7 +2018,7 @@ pt_BR: spree_admin_eg_pickup_from_school: "ex: 'Buscar na Escola'" spree_admin_eg_collect_your_order: "ex: 'Por favor, colete seu pedido na Rua dos Sonhos, 123, casa 5, Bairro Liberdade" spree_classification_primary_taxon_error: "O táxon %{taxon} é o táxon principal de %{product} e não pode ser excluído" - spree_order_availability_error: "O ciclo do distribuidor ou do pedido não pode fornecer os produtos no seu carrinho" + spree_order_availability_error: "O distribuidor ou o ciclo de pedidos não pode fornecer os produtos no seu carrinho" spree_order_populator_error: "Distribuidor ou ciclo de pedidos não pode fornecer os produtos no seu carrinho. Por favor, escolha outro." spree_order_populator_availability_error: "Esse produto não está disponível no distribuidor escolhido ou no ciclo de pedidos." spree_distributors_error: "Pelo menos uma central deve ser selecionado" @@ -2029,7 +2031,7 @@ pt_BR: manage: "Gerenciar" resend: "Re-enviar" add_and_manage_products: "Adicionar e gerenciar produtos" - add_and_manage_order_cycles: "Adicione e gerenciar ciclos de pedidos" + add_and_manage_order_cycles: "Adicionar e gerenciar ciclos de pedidos" manage_order_cycles: "Gerenciar ciclos de pedidos" manage_products: "Gerenciar produtos" edit_profile_details: "Editar detalhes de perfil " @@ -2085,7 +2087,7 @@ pt_BR: report_header_first_name: Nome report_header_last_name: Sobrenome report_header_phone: Telefone - report_header_suburb: Bairro + report_header_suburb: Cidade report_header_address: Endereço report_header_billing_address: Endereço de cobrança report_header_relationship: Relação @@ -2116,7 +2118,7 @@ pt_BR: report_header_order_number: Número do pedido report_header_date: Data report_header_confirmation_date: Data de Confirmação - report_header_tags: Etiqueta + report_header_tags: Tags report_header_items: Itens report_header_items_total: "Total de itens%{currency_symbol}" report_header_taxable_items_total: "Total de itens tributáveis ​​(%{currency_symbol})" @@ -2143,7 +2145,7 @@ pt_BR: report_header_producer: Produtor report_header_producer_suburb: Subúrbio do produtor report_header_unit: Unidade - report_header_group_buy_unit_quantity: Quantidade da Unidade para Grupo de Compras + report_header_group_buy_unit_quantity: Quantidade da Unidade para Compra em Grupo report_header_cost: Custo report_header_shipping_cost: ' Custo de envio' report_header_curr_cost_per_unit: Custo unitário atual @@ -2159,7 +2161,7 @@ pt_BR: 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: Unidade de Medida para atacado + report_header_bulk_unit_size: Quantidade Mínima para Compra em Atacado report_header_weight: Peso report_header_sum_total: Soma total report_header_date_of_order: Data do pedido @@ -2337,18 +2339,18 @@ pt_BR: overview: Visão geral overview_text: > As regras de tag fornecem uma maneira para descrever quais itens são - visíveis ou não e para quais clientes, como formas de pagamento, formas + visíveis ou não e para quais clientes, como métodos de pagamento, método de entrega, produtos e ciclos de pedidos. by_default_rules: "Regras \"Padrão ...\"" by_default_rules_text: > As regras padrão permitem ocultar itens para que eles não estejam visíveis por padrão. Esse comportamento pode ser substituído por regras não padrão - para clientes com etiquetas específicas. + para clientes com tags específicas. customer_tagged_rules: "Regras de \"Clientes marcados ...\"" customer_tagged_rules_text: > - Ao criar regras relacionadas a uma etiqueta de cliente específica, você - pode substituir o comportamento padrão (seja para mostrar ou para ocultar - itens) para clientes com a etiqueta especificada. + Ao criar regras relacionadas a uma tag de cliente específica, você pode + substituir o comportamento padrão (seja para mostrar ou para ocultar + itens) para clientes com a tagespecificada. panels: save: SALVAR saved: SALVO @@ -2460,7 +2462,7 @@ pt_BR: payment_method_tagged_bottom: "são:" order_cycle_tagged_top: "Ciclos de pedidos marcados" order_cycle_tagged_bottom: "são:" - inventory_tagged_top: "Variantes de inventário marcadas" + inventory_tagged_top: "Variantes do inventário marcadas com tag" inventory_tagged_bottom: "são:" new_tag_rule_dialog: select_rule_type: "Selecione um tipo de regra:" @@ -2525,7 +2527,7 @@ pt_BR: updated_schedule: "Lista atualizada" deleted_schedule: "Lista excluída" name_required_error: "Digite um nome para esta lista" - no_order_cycles_error: "Selecione pelo menos um ciclo de pedido (arraste e solte)" + no_order_cycles_error: "Selecione pelo menos um ciclo de pedidos (arraste e solte)" available: "Disponível" selected: "Selecionado" customers: @@ -2589,9 +2591,9 @@ pt_BR: Isso ajustará o nível de estoque para zero em todos os produtos para esta iniciativa que não está presente no arquivo carregado. order_cycles: - create_failure: "Falha ao criar o ciclo do pedido" + create_failure: "Falha ao criar o ciclo do pedidos" update_success: 'O seu ciclo de pedidos foi atualizado.' - update_failure: "Falha ao atualizar o ciclo do pedido" + update_failure: "Falha ao atualizar o ciclo do pedidos" no_distributors: Não há distribuidores neste ciclo de pedidos. Este ciclo de pedidos não será visível para os clientes até você adicionar um. Você gostaria de continuar salvando esse ciclo de pedidos? enterprises: producer: "Produtor" @@ -2740,6 +2742,7 @@ pt_BR: customer_details: "Detalhes do cliente" adjustments: "Ajustes" payments: "Pagamentos" + return_authorizations: "Autorizações de Retorno" payment: "Pagamento" payment_method: "Método de Pagamento" shipment: "Envio" @@ -2809,6 +2812,8 @@ pt_BR: new_payment: "Novo Pagamento" capture: "Capturar" void: "Vazio" + login: "Login" + password: "Senha" configurations: "Configurações" general_settings: "Configurações Gerais" site_name: "Nome do site" @@ -2873,8 +2878,6 @@ pt_BR: abbreviation: "Abreviação" new_state: "Estado novo" payment_methods: "Métodos de pagamento" - new_payment_method: "Novo método de pagamento" - provider: "Fornecedor" taxonomies: "Taxonomias" new_taxonomy: "Nova taxonomia" back_to_taxonomies_list: "Voltar à lista de taxonomias" @@ -2939,7 +2942,7 @@ pt_BR: tab: dashboard: "Painel" orders: "Encomendas" - bulk_order_management: "Gestão de Pedidos em Atacado" + bulk_order_management: "Gestão de Pedidos em Atacado" subscriptions: "Assinaturas" products: "Produtos" option_types: "Tipos de opção" @@ -3040,7 +3043,7 @@ pt_BR: distribution_fields: title: "Distribuição" distributor: "Distribuidor:" - order_cycle: "Ciclo de pedido:" + order_cycle: "Ciclo de pedidos:" line_item_adjustments: "Ajustes de itens de linha" order_adjustments: "Ajustes de Pedidos" order_total: "total de pedidos" @@ -3057,7 +3060,7 @@ pt_BR: order_cycles_tip: "Os ciclos de pedidos determinam quando e onde seus produtos estão disponíveis para os clientes." you_have_active: zero: "Você não possui ciclos de pedidos ativos." - one: "Você tem um ciclo de pedido ativo." + one: "Você tem um ciclo de pedidos ativo." other: "Você tem %{count} ciclos de pedidos ativos." manage_order_cycles: "GERENCIAR CICLOS DE PEDIDOS" shipping_methods: @@ -3069,6 +3072,8 @@ pt_BR: zone: "Zona" calculator: "Calculadora" display: "Exibição" + both: "Tanto Checkout quanto Área Administrativa" + back_end: "Somente Área Administrativa" no_shipping_methods_found: "Nenhum método de envio encontrado" new: new_shipping_method: "Novo método de envio" @@ -3080,12 +3085,26 @@ pt_BR: form: categories: "Categorias" zones: "Zonas" + both: "Tanto Checkout quanto Área Administrativa" + back_end: "Somente Área Administrativa" deactivation_warning: "Desativar um método de envio pode fazer com que ele desapareça da sua lista. Como alternativa, você pode esconder um método de envio da página de checkout s" payment_methods: + index: + payment_methods: "Métodos de pagamento" + new_payment_method: "Novo método de pagamento" + name: "Nome" + products_distributor: "Distribuidor" + environment: "Ambiente" + display: "Exibição" + both: "Ambos" + back_end: "Somente Área Administrativa" + active_yes: "Sim" + active_no: "Não" new: new_payment_method: "Novo método de pagamento" back_to_payment_methods_list: "Voltar à lista de formas de pagamento" edit: + new: "Novo" editing_payment_method: "Editando método de pagamento" back_to_payment_methods_list: "Voltar à lista de formas de pagamento" stripe_connect: @@ -3101,6 +3120,16 @@ pt_BR: account_id: ID da conta business_name: Nome da iniciativa/negócio charges_enabled: Taxas habilitadas + form: + name: "Nome" + description: "Descrição" + environment: "Ambiente" + display: "Exibição" + active_yes: "Sim" + active_no: "Não" + both: "Tanto Checkout quanto Área Administrativa" + back_end: "Somente Área Administrativa" + tags: "Tags" payments: source_forms: stripe: @@ -3147,8 +3176,8 @@ pt_BR: primary_taxon_form: product_category: Categoria de Produto group_buy_form: - group_buy: "Grupo de Compras?" - bulk_unit_size: Tamanho da unidade em massa + group_buy: "Compra em Grupo?" + bulk_unit_size: Quantidade Mínima para Compra em Atacado display_as: display_as: Mostrar como reports: @@ -3203,6 +3232,7 @@ pt_BR: display_as_placeholder: 'ex. 2 kg' display_name_placeholder: 'ex. Tomates' autocomplete: + out_of_stock: "Sem estoque" producer_name: "Produtor" unit: "Unidade" shared: @@ -3240,10 +3270,11 @@ pt_BR: format: '%A-%m-' js_format: 'aa-mm-dd' orders: + error_flash_for_unavailable_items: "Um item no seu carrinho ficou indisponível. Por favor atualize as quantidades selecionadas. " edit: login_to_view_order: "Faça o login para visualizar seu pedido." bought: - item: "Já pediu neste ciclo de pedido" + item: "Já pediu neste ciclo de pedidos" line_item: insufficient_stock: "Estoque disponível insuficiente, apenas %{on_hand} restante" out_of_stock: "Fora de estoque" @@ -3267,9 +3298,6 @@ pt_BR: invalid: inváliod order_mailer: cancel_email: - customer_greeting: "Oi %{name}!" - instructions: "Seu pedido foi CANCELADO. Guarde essas informações de cancelamento para seus registros." - order_summary_canceled: "Resumo do pedido [CANCELADO]" subject: "Cancelamento do Pedido" confirm_email: subject: "Confimação de Pedido" diff --git a/config/locales/sv.yml b/config/locales/sv.yml index 8bb42e8411..addd879f88 100644 --- a/config/locales/sv.yml +++ b/config/locales/sv.yml @@ -11,6 +11,8 @@ sv: spree/product: supplier: "Leverantör" variant_unit: "Enhet för variant" + variant_override: + count_on_hand: "På lager" errors: models: spree/user: @@ -194,6 +196,7 @@ sv: footer_and_external_links: Sidfot och externa länkar your_content: Ditt innehåll user_guide: Användarinstruktion + map: Karta enterprise_fees: index: title: "Företagsavgifter" @@ -1905,6 +1908,8 @@ sv: update: "Uppdatera" continue: "Fortsätt" capture: "Fånga" + login: "Logga in" + password: "Lösenord" tax rate: "Skattesatser" tax_category: "Skattekategori" tax_settings: "Skatteskalor" @@ -1996,6 +2001,19 @@ sv: name: "Namn" products_distributor: "Distributör" calculator: "Beräkning" + payment_methods: + index: + payment_methods: "Betalningssätt" + name: "Namn" + products_distributor: "Distributör" + active_yes: "Ja" + active_no: "Nej" + form: + name: "Namn" + description: "Beskrivning" + active_yes: "Ja" + active_no: "Nej" + tags: "Taggar" products: new: supplier: "Leverantör" diff --git a/config/locales/tr.yml b/config/locales/tr.yml index f850080a53..f9777fb9cd 100644 --- a/config/locales/tr.yml +++ b/config/locales/tr.yml @@ -23,6 +23,8 @@ tr: base: "Kredi kartı" order_cycle: orders_close_at: BİTİŞ TARİHİ + variant_override: + count_on_hand: "Mevcut" errors: models: spree/user: @@ -181,9 +183,9 @@ tr: home: "AGA" title: Açık Gıda Ağı welcome_to: 'Hoşgeldiniz' - site_meta_description: "Açık Gıda Ağı, bağımsız, 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: Temiz gıda üreticileri! Açık Gıda Ağı sizler için kullanıma açıldı. + site_meta_description: "Açık Gıda Ağı, yerel, bağımsız, 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. Toplum yararına çalışır, iletişim, dürüstlük ve dayanışmayı destekler." + search_by_name: Üretici adına veya konuma göre arama yapın... + producers_join: Bağımsız 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" @@ -368,7 +370,6 @@ tr: title: "Matomo Ayarları" matomo_url: "Matomo URL'si" matomo_site_id: "Matomo Site Kimliği" - info_html: "Matomo bir Web ve Mobil Analitik programıdır. Matomo'yu şirket içinde kullanabilir veya bulutta saklanan bir hizmet olarak kullanabilirsiniz. Daha fazla bilgi için matomo.org adresini ziyaret edin." config_instructions_html: "Burada OFN Matomo entegrasyonunu yapılandırabilirsiniz. Aşağıdaki Matomo URL'si, kullanıcı izleme bilgilerinin gönderileceği Matomo örneğini göstermelidir; boş bırakılırsa Matomo kullanıcı takibi devre dışı bırakılır. Site Kimliği alanı zorunlu değildir, ancak tek bir Matomo örneğinde birden fazla web sitesini izliyorsanız yararlıdır; Matomo örnek konsolunda bulunabilir." customers: index: @@ -387,7 +388,7 @@ tr: edit: 'Düzenle' update_address: 'Adresi Güncelle' confirm_delete: 'Silmek istediğinizden emin misiniz?' - search_by_email: "E-posta / kod ile arama ..." + search_by_email: "E-posta/kod ile arama ..." guest_label: 'Misafir Ödemesi' destroy: has_associated_orders: 'Silme başarısız oldu: müşterinin bağlantılı siparişleri var' @@ -403,6 +404,7 @@ tr: footer_and_external_links: Altbilgi ve Dış Bağlantılar your_content: İçeriğiniz user_guide: Kullanici Kılavuzu + map: HARİTA enterprise_fees: index: title: "İşletme Ücretleri" @@ -612,7 +614,7 @@ tr: about_us: desc_short: Kısa Açıklama desc_short_placeholder: Bir veya iki cümleyle bize işletmenizden bahsedin - desc_long: Hakkımızda + desc_long: HAKKIMIZDA desc_long_placeholder: Müşterilerinize kendinizden bahsedin. Bu bilgiler profilinizde görünür. business_details: abn: VKN/TCKN @@ -686,12 +688,13 @@ tr: ofn_uid_tip: Açık Gıda Ağı'na kayıtlı işletmenize özel tanımlanan kimlik numarası shipping_methods: name: "Ad" + applies: "Aktif?" manage: "Teslimat Yöntemlerini Yönet" create_button: "Yeni Teslimat Yöntemi Oluştur" create_one_button: "Şimdi Oluştur" no_method_yet: "Henüz herhangi bir teslimat yönteminiz yok." shop_preferences: - shopfront_requires_login: "MAĞAZANIZ HARİTADA GÖRÜNÜR OLSUN MU?" + shopfront_requires_login: "MAĞAZANIZ HERKESE AÇIK MI?" shopfront_requires_login_tip: "Mağazanızın yalnızca üyelerinize mi yoksa herkese mi açık olduğunu seçin." shopfront_requires_login_false: "Herkese açık" shopfront_requires_login_true: "Yalnızca kayıtlı müşteriler tarafından görülebilir" @@ -702,8 +705,8 @@ tr: allow_guest_orders_true: "Misafir alışverişine izin ver" allow_order_changes: "Siparişleri düzenle" allow_order_changes_tip: "Sipariş dönemi açık olduğu sürece müşterilerin siparişlerini düzenlemelerine izin verin." - allow_order_changes_false: "Oluşturulan siparişler değiştirilemez / iptal edilemez" - allow_order_changes_true: "Müşteriler sipariş dönemi açıkken siparişleri değiştirebilir / iptal edebilir" + allow_order_changes_false: "Oluşturulan siparişler değiştirilemez/iptal edilemez" + allow_order_changes_true: "Müşteriler sipariş dönemi açıkken siparişleri değiştirebilir/iptal edebilir" enable_subscriptions: "Üyelikler" enable_subscriptions_tip: "Üyelik işlevselliği etkinleştirilsin mi?" enable_subscriptions_false: "Kapalı" @@ -713,7 +716,7 @@ tr: Müşterilerinize merhaba diyebilir, tezgahınız ve alışveriş şartlarınız ile ilgili bilgi verebilirsiniz. Yazdıklarınız, müşteriler mağazanızı ziyaret ettiğinde görünür olacak. - shopfront_message_link_tooltip: "Bağlantı ekle / düzenle" + shopfront_message_link_tooltip: "Bağlantı ekle/düzenle" shopfront_message_link_prompt: "Lütfen eklemek için bir URL girin" shopfront_closed_message: "KAPALI MAĞAZA MESAJI" shopfront_closed_message_placeholder: > @@ -794,7 +797,7 @@ tr: producer_shop_description_text: Açık Gıda Ağı üzerinden açtığınız bireysel mağazanız ile ürünlerinizi doğrudan müşterilere ulaştırabilirsiniz. producer_shop_description_text2: Üretici Tezgahı sadece sizin ürünleriniz içindir. Üretiminiz haricindeki ürünleri satabilmek için lütfen 'Üretici Pazarı' seçeneğini seçin. producer_hub: ÜRETİCİ PAZARI - producer_hub_text: Kendi ürünleriniz ile beraber başkalarından ürünlerini de satın + producer_hub_text: Kendi ürünleriniz ile beraber başkalarının ürünlerini de satın producer_hub_description_text: İşletmeniz, yerel gıda sisteminizin bel kemiğidir. Açık Gıda Ağı'ndaki mağazanız aracılığıyla kendi ürünlerinizi ve çevrenizdeki diğer üreticilerin ürünlerini beraber satabilirsiniz. profile: Yalnızca Profil get_listing: Görünür ol @@ -857,7 +860,7 @@ tr: next: "Sonrakİ" cancel: "İptal et" back_to_list: "Listeye geri dön" - save_and_back_to_list: "Kaydet ve Listeye Dön" + save_and_back_to_list: "KAYDET VE LİSTEYE DÖN" choose_products_from: "Ürünlerİ Buradan SeÇ:" incoming: incoming: "Gelen" @@ -879,7 +882,7 @@ tr: fees: "Ücretler" previous: "Önceki" save: "Kaydet" - save_and_back_to_list: "Kaydet ve Listeye Dön" + save_and_back_to_list: "KAYDET VE LİSTEYE DÖN" cancel: "İptal et" back_to_list: "Listeye geri dön" wizard_progress: @@ -890,7 +893,7 @@ tr: pickup_time_tip: Bu sipariş dönemine ait siparişlerin müşteriler için hazır olma tarihi pickup_instructions_placeholder: "Teslimat Talimatları" pickup_instructions_tip: Bu talimatlar, siparişi tamamladıktan sonra müşterilere iletilir - pickup_time_placeholder: "ŞU TARİHTE HAZIR (örn. Tarİh / Saat)" + pickup_time_placeholder: "Teslimat (örn. Tarih / Saat)" receival_instructions_placeholder: "Teslim Alma talimatları" add_fee: 'Ücret ekle' remove: 'Kaldır' @@ -903,7 +906,7 @@ tr: choose_product_tip: Gelen ve giden ürünleri sadece stokların %{inventory} 'i ile kısıtlayabilirsiniz. preferred_product_selection_from_coordinator_inventory_only_here: Yalnızca Koordinatör Stokları preferred_product_selection_from_coordinator_inventory_only_all: Tüm Mevcut Ürünler - save_reload: Sayfayı Kaydet ve Yeniden Yükle + save_reload: SAYFAYI KAYDET VE YENİDEN YÜKLE coordinator_fees: add: Koordinatör ücreti ekle filters: @@ -922,7 +925,7 @@ tr: products: Ürünler tags: Etiketler add_a_tag: Etiket ekle - delivery_details: Teslimat / Gönderim Bilgileri + delivery_details: Teslimat/Gönderim Bilgileri index: schedule: Takvim schedules: Takvimler @@ -937,8 +940,8 @@ tr: distributors: Dağıtımcılar variants: Varyantlar simple_form: - ready_for: ŞU TARİHTE HAZIR - ready_for_placeholder: Tarih / saat + ready_for: Teslimat + ready_for_placeholder: Tarih/saat customer_instructions: Müşteri talimatları customer_instructions_placeholder: Teslimat / Gönderim Notları products: Ürünler @@ -1147,7 +1150,7 @@ tr: checkout: "Alışverişi Tamamla" already_ordered_products: "Bu sipariş dönemi içinde zaten sipariş verildi" register_call: - selling_on_ofn: "Açık Gıda Ağı'na katılmak ister misiniz?" + selling_on_ofn: "Açık Gıda Ağı üzerinden satış yapmak ister misiniz?" register: "Buradan kaydolun" footer: footer_secure: "Güvenli ve güvenilir." @@ -1156,7 +1159,7 @@ tr: footer_contact_email: "Bize e-posta gönderin" footer_nav_headline: "Gezin" 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ını keşfedin." + footer_join_body: "Açık Gıda Ağı üzerinden ürünlerinizi sergileyin, çevirimiçi mağazanızı oluşturun veya grubunuzu listeleyin." footer_join_cta: "Daha fazlasını anlat!" footer_legal_call: "Okuyun" footer_legal_tos: "Şartlar ve koşullar" @@ -1164,18 +1167,18 @@ tr: footer_legal_text_html: "Açık Gıda Ağı ücretsiz ve açık kaynaklı bir yazılım platformudur. İçeriklerimiz %{content_license} ve kodumuz %{code_license} ile lisanslıdır." footer_data_text_with_privacy_policy_html: "Verilerinize iyi bakıyoruz. Bkz. %{privacy_policy} ve %{cookies_policy}" footer_data_text_without_privacy_policy_html: "Verilerinize iyi bakıyoruz. Bkz. %{cookies_policy}" - footer_data_privacy_policy: "Gizlilik Politikası" - footer_data_cookies_policy: "çerez politikası" + footer_data_privacy_policy: "Gizlilik ve Kişisel Verilerin Korunması Politikası " + footer_data_cookies_policy: "Çerez Politikası" shop: messages: customer_required: - login: "Oturum Aç" + login: "Oturum Aç / Kaydol" signup: "Kaydol" contact: "İLETİŞİM" require_customer_login: "Yalnızca onaylı müşteriler buradan alışveriş yapabilir." require_login_html: "Zaten onaylanmış bir müşteri iseniz, devam etmek için %{login} veya %{signup}" - require_login_2_html: "Buradan alışveriş mi yapmak istiyorsunuz? Lütfen katılmak için %{contact}%{enterprise} ile iletişime geçin!" - require_customer_html: "Buradan alışveriş yapmaya başlamak istiyorsanız, katılmak için lütfen %{contact} %{enterprise} 'a sorun." + require_login_2_html: "Buradan alışveriş mi yapmak istiyorsunuz? Lütfen katılmak için sorun: %{contact}%{enterprise} " + require_customer_html: "Buradan alışveriş yapmaya başlamak istiyorsanız, katılmak için lütfen sorun: %{contact} %{enterprise} " select_oc: select_oc_html: "Hangi ürünlerin uygun olduğunu görmek için lütfen ne zaman için sipariş vermek istediğinizi seçin " card_could_not_be_updated: Kart güncellenemedi @@ -1211,14 +1214,14 @@ tr: menu_2_url: "/map" menu_3_title: "ÜRETİCİLER" menu_3_url: "/producers" - menu_4_title: "Gruplar" + menu_4_title: "GRUPLAR" menu_4_url: "/groups" - menu_5_title: "hakkında" - menu_5_url: "https://acikgida.com" + menu_5_title: "HAKKIMIZDA" + menu_5_url: "https://hakkimizda.acikgida.com" menu_6_title: "Bağlan" - menu_6_url: "https://acikgida.com" + menu_6_url: "https://acikgida.com/connect" menu_7_title: "öğren" - menu_7_url: "https://acikgida.com" + menu_7_url: "https://acikgida.com/learn" logo: "Logo (640x130)" logo_mobile: "Cep telefonu logosu (75x26)" logo_mobile_svg: "Cep Telefonu logo (SVG)" @@ -1233,7 +1236,7 @@ tr: footer_pinterest_url: "Pinterest URL" footer_email: "E-posta" footer_links_md: "Bağlantılar" - footer_about_url: "URL hakkında" + footer_about_url: "HAKKIMIZDA URL" user_guide_link: "Kullanıcı Kılavuzu Linki" name: İSİM first_name: Ad @@ -1268,7 +1271,7 @@ tr: label_producer: "ÜRETİCİ" label_producers: "ÜRETİCİLER" label_groups: "Gruplar" - label_about: "HAKKINDA" + label_about: "HAKKIMIZDA" label_connect: "Bağlan" label_learn: "Öğren" label_blog: "Blog" @@ -1350,45 +1353,45 @@ tr: 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ğı, bağımsız, 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ı' 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_part1: "Açık Gıda Ağı, yerel, bağımsız, 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. 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 cesaretlendirir. Gıda yetiştiriciliği ve satışının kendine özgü ihtiyaçlarını karşılamak için geliştirilmiştir. Temiz gıdaya ulaşım sürecini kolaylaştırır." + brandstory_part3: "Platform üzerinden yalnızca yerel ve bağımsız gıda üreticileri ve dağıtımcıları satış yapabilir. Siz de ürünlerinizi AGA üzerinden oluşturduğunuz tezgah ile doğrudan alıcılara ulaştırabilir, dilerseniz bölgenizdeki diğer üreticiler ile bir araya gelerek kendi ortak 'Üretici Pazarı' veya 'Türetici Pazarı' nızı oluşturabilirsiniz. Bu şekilde çeşitliliği ve bereketi artırır, dayanışmanın getirdiği 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." learn_body: "Adil ve temiz gıda işletmenizi veya topluluğunuzu geliştirmenize yardımcı olacak modelleri, hikayeleri ve kaynakları keşfedin. Dostlardan öğrenmek için eğitim, etkinlikler ve diğer fırsatlara göz atın." learn_cta: "İlham Alın" - connect_body: "Yakınınızdaki adil ve temiz gıda tüccarlarını bulmak için üreticilerin, pazarların ve topluluklarının tümünü gözden geçirin. İşletmenizi veya topluluğunuzu Açık Gıda Ağı üzerinden listeleyin, böylece alıcılar sizi bulabilir. Ortak hareket etmek için diğer hesaplar ile iletişime geçmekten çekinmeyin, birlikte daha güçlüsünüz. Tavsiye almak ve sorunları birlikte çözmek için topluluğa katılın." + connect_body: "Yakınınızdaki adil ve temiz gıda noktalarını bulmak için üreticilerin, pazarların ve topluluklarının tümünü gözden geçirin. İşletmenizi veya topluluğunuzu Açık Gıda Ağı üzerinden listeleyin, böylece alıcılar sizi rahatça bulabilir. Ortak hareket etmek için diğer hesaplar ile iletişime geçmekten çekinmeyin, birlikte daha güçlüsünüz. Tavsiye almak ve sorunları birlikte çözmek için topluluğa katılın." connect_cta: "Keşfedin" system_headline: "Nasıl ç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_step1_text: "Yerel, adil, temiz ve mevsimsel gıda için, bağımsız ve cesur üreticilerimizin mağazalarından alışveriş yapın. Konuma, ürün kategorisine, üretici özelliklerine veya teslimat tercihlerine göre arama yapabilirsiniz. " 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: "3. Teslimat " - system_step3_text: "Seçtiğiniz gıdaya ulaşmak için adresinize teslim edilmesini 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_text: "Gıdanıza ulaşmak için adresinize teslim edilmesini bekleyin. Dilerseniz 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: "GIDA ÜRETİCİLERİ" - stats_shops: "gıda pazarları" - stats_shoppers: "gıda alıcıları" - stats_orders: "GIDA SİPARİŞLERİ" + stats_producers: "ÜRETİCİ" + stats_shops: "MAĞAZA" + stats_shoppers: "TÜRETİCİ" + stats_orders: "ALIŞVERİŞ" checkout_title: Ödeme Yap checkout_now: Alışverişi Tamamla - checkout_order_ready: SİPARİŞ ŞU TARİHTE HAZIR + checkout_order_ready: Sipariş Teslimat checkout_hide: Gizle checkout_expand: genişlet checkout_headline: "Tamam, ödeme yapmaya hazır mısın?" checkout_as_guest: "Misafir olarak ödeme yap" checkout_details: "Bilgilerin" - checkout_billing: "fatura bilgisi" + checkout_billing: "Fatura Bilgisi" checkout_default_bill_address: "Varsayılan fatura adresi olarak kaydet" checkout_shipping: Teslimat bilgileri checkout_default_ship_address: "Varsayılan teslimat adresi olarak kaydet" checkout_method_free: Ücretsiz checkout_address_same: Teslimat adresi fatura adresiyle aynı mı? - checkout_ready_for: "ŞU TARİHTE HAZIR" + checkout_ready_for: "Teslimat:" checkout_instructions: "Yorumlarınız veya özel talimatlarınız var mı?" checkout_payment: Ödeme checkout_send: Şimdi sipariş ver @@ -1407,7 +1410,7 @@ tr: order_delivery_address: Teslimat adresi order_delivery_time: Teslimat zamanı order_special_instructions: "Notların:" - order_pickup_time: TESLİM ALMAK İÇİN HAZIR + order_pickup_time: Teslimat için hazır order_pickup_instructions: Teslim Alma Talimatları order_produce: Üretim order_total_price: Toplam @@ -1476,7 +1479,7 @@ tr: email_shipping_delivery_time: "Teslimat tarihi:" email_shipping_delivery_address: "Teslimat adresi:" email_shipping_collection_details: Teslim Alma Bilgileri - email_shipping_collection_time: "TESLİM ALMAK İÇİN HAZIR" + email_shipping_collection_time: "Teslimat için hazır" email_shipping_collection_instructions: "Teslim Alma talimatları:" email_special_instructions: "Notların:" email_signup_greeting: Merhaba! @@ -1496,13 +1499,13 @@ tr: producer_mail_order_text: "İşte ürünleriniz gelen için siparişlerin bir özeti:" producer_mail_delivery_instructions: "Stok teslimat/gönderim talimatları:" producer_mail_signoff: "En iyi dileklerimle" - shopping_oc_closed: SİPARİŞ KAPANIŞ + shopping_oc_closed: SİPARİŞ DÖNEMİ KAPALI 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_shop: "ALIŞVERİŞ YAP" shopping_tabs_about: "Hakkında" shopping_tabs_contact: "İLETİŞİM" shopping_contact_address: "Adres" @@ -1511,13 +1514,13 @@ tr: shopping_groups_part_of: "şunun parçası:" shopping_producers_of_hub: "%{hub} üreticileri:" enterprises_next_closing: "Bir sonraki sipariş kapanışı" - enterprises_ready_for: "ŞU TARİHTE HAZIR" + enterprises_ready_for: "Teslimat" enterprises_choose: "Siparişinizi ne zaman istediğinizi seçin:" maps_open: "Açık" maps_closed: "Kapalı" hubs_buy: "Neler Bulabilirsiniz:" hubs_shopping_here: "Alışveriş noktası" - hubs_orders_closed: "SİPARİŞ KAPANIŞ" + hubs_orders_closed: "Siparişler kapalı" hubs_profile_only: "Yalnızca profil" hubs_delivery_options: "Teslimat seçenekleri" hubs_pickup: "Teslimat Noktası" @@ -1566,8 +1569,8 @@ tr: components_filters_nofilters: "Filtresiz" components_filters_clearfilters: "Tüm filtreleri temizle" groups_title: Gruplar - groups_headline: Gruplar / bölgeler - groups_text: "Her üretici özeldir ve her işletmenin ortaya koyabileceği farklı bir değer vardır. Üyelerimiz, ürünlerini ve emeklerini, ya da sadece gıdanın ortak değerleri paylaşan üretici, türetici ve dağıtımcı kolektifleridir. Bu bileşenler, adil ve temiz gıdaya ulaşım yollarını kolaylaştırır ve bozulmuş gıda sistemini hep beraber düzeltmemize yardımcı olur." + groups_headline: Gruplar + groups_text: "Her üretici özeldir ve her işletmenin ortaya koyabileceği farklı bir değer vardır. Üyelerimiz, ürünlerini, emeklerini ve gıdanın ortak değerleri paylaşan üretici, türetici ve dağıtımcı kolektifleridir. Bu bileşenler, adil ve temiz gıdaya ulaşım yollarını kolaylaştırır ve bozulmuş gıda sistemini hep beraber düzeltmemize yardımcı olur." groups_search: "İsim veya anahtar kelime ile ara" groups_no_groups: "Grup bulunamadı" groups_about: "Hakkımızda" @@ -1636,10 +1639,10 @@ tr: sell_producers_detail: "AGA üzerinden işletmeniz adına bir profil oluşturun. Dilediğiniz zaman profilinizi bir tezgaha yükseltebilir ve ürünlerinizi müşterilerinize doğrudan satabilirsiniz." 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. 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." + sell_user_guide: "Kullanım kılavuzumuzdan daha fazla bilgi edinin." + sell_listing_price: "AGA üzerinde görünür olmak ücretsizdir. Platform üzerinden satış yapan işletmeler için işlem başına uygulanan ücretlendirme KDV dahil %5'tir. Kar amacı gütmeyen topluluklar, kooperatifler ve ekoloji/gıda temelli dernekler ile çalışan üreticiler karşılıklı dayanışma ve özel fiyatlandırma için iletişime geçebilirler. Fiyatlandırma hakkında bilgi almak için, üst menüdeki Hakkımızda bağlantısını kullanarak Fiyatlandırma bölümünü ziyaret edin." + sell_embed: "Kendi e-ticaret siteniz olsa bile Açık Gıda Ağı size hikayenizi anlatmanız ve ürünlerinizi satmanız için yeni ve farklı bir seçenek sunuyor. Siz de bu ailenin bir parçası olun, hep beraber büyüyelim!" + sell_ask_services: "Detaylar için bizimle iletişime geçin." shops_title: Mağazalar shops_headline: Alışveriş biçim değiştiriyor shops_text: Gıda dönemsel yetiştirilir, dönemsel hasat edilir ve dönemsel sipariş edilir. Aradığınız mağazanın sipariş dönemi kapalı ise kısa süre sonra tekrar kontrol edin. @@ -1656,7 +1659,7 @@ tr: orders_fees: Ücretler ... orders_edit_title: Alışveriş Sepeti orders_edit_headline: Alışveriş sepetiniz - orders_edit_time: SİPARİŞ ŞU TARİHTE HAZIR + orders_edit_time: Sipariş Teslimat orders_edit_continue: Alışverişe devam orders_edit_checkout: Ödeme Yap orders_form_empty_cart: "Sepeti Boşalt" @@ -1699,7 +1702,7 @@ tr: password: Parola remember_me: Beni Hatırla are_you_sure: "Emin misiniz?" - orders_open: 'SİPARİŞ AÇILIŞ:' + orders_open: Siparişler açık closing: "Kapanış" going_back_to_home_page: "Ana sayfaya yönlendiriliyorsunuz.." creating: oluşturuluyor @@ -1712,7 +1715,7 @@ tr: filter_by: "Filtrele" hide_filters: "Filtreleri gizle" one_filter_applied: "1 filtre uygulandı" - x_filters_applied: "filtreler uygulandı" + x_filters_applied: "filtre uygulandı" submitting_order: "Siparişiniz gönderiliyor: lütfen bekleyin" confirm_hub_change: "Emin misiniz? Seçtiğiniz pazar değiştirilecek ve alışveriş sepetinizdeki tüm ürünler kaldırılacak." confirm_oc_change: "Emin misiniz? Seçtiğiniz sipariş dönemi değiştirilecek ve alışveriş sepetinizdeki tüm ürünler kaldırılacak." @@ -1752,14 +1755,14 @@ tr: steps: introduction: registration_greeting: "Merhaba!" - registration_intro: "Şimdi AGA üzerinden bir Üretici veya Türetici profili oluşturabilirsiniz" + registration_intro: "Şimdi AGA üzerinden Üretici veya Türetici profilleri oluşturabilirsiniz" registration_checklist: "Neye ihtiyacım var?" registration_time: "5-10 dakika" registration_enterprise_address: "İşletme adresi" registration_contact_details: "Birincil iletişim bilgileri" registration_logo: "Logo resminiz" registration_promo_image: "Profiliniz için duvar resmi" - registration_about_us: "'Hakkımızda' metni" + registration_about_us: "'Hakkımızda' metni - Hikayeniz" registration_outcome_headline: "Ne kazanacağım?" registration_outcome1_html: "Profiliniz, insanların Açık Gıda Ağı üzerinde sizi bulmasına ve sizinle iletişim kurmasına yardımcı olur." registration_outcome2: "Bu alanı kendinizin, çiftliğinizin ve işletmenizin hikayesini anlatmak, yeni işbirlikleri, yeni bağlantılar kurmak için kullanın. " @@ -1807,7 +1810,7 @@ tr: no_producer_help: "Üretici değilseniz muhtemelen gıdaya ulaşım sağlayan, dağıtım veya satış yapan bir grup ya da işletmesiniz. Bir dükkan, kooperatif, gıda topluluğu, restaurant veya toptancı bile olabilirsiniz. " create_profile: "Profil oluştur" about: - title: "Hakkında" + title: "HAKKIMIZDA" headline: "Güzel!" message: "Şimdi ayrıntıları açıklayalım" success: "Sonunda! %{enterprise} Açık Gıda Ağı'na eklendi" @@ -1912,10 +1915,10 @@ tr: outstanding_balance: "Ödenmemiş bakiye" admin_enterprise_relationships: "İŞLETME İZİNLERİ" admin_enterprise_relationships_everything: "her şey" - admin_enterprise_relationships_permits: "izinler" + admin_enterprise_relationships_permits: "izin veriyor" admin_enterprise_relationships_seach_placeholder: "Ara" admin_enterprise_relationships_button_create: "Oluştur" - admin_enterprise_relationships_to: "'a" + admin_enterprise_relationships_to: "-" admin_enterprise_groups: "İşletme Grupları" admin_enterprise_groups_name: "Ad" admin_enterprise_groups_owner: "Sahip" @@ -1985,7 +1988,7 @@ tr: price: "Fiyat" on_hand: "Mevcut" review: "gözden geçir" - save_changes: "Değişiklikleri Kaydet" + save_changes: "DEĞİŞİKLİKLERİ KAYDET" order_saved: "Sipariş Kaydedildi" no_products: Ürün yok spree_admin_overview_enterprises_header: "İşletmelerim" @@ -2035,13 +2038,13 @@ tr: edit_profile_details: "Profil bilgilerini düzenle" edit_profile_details_etc: "Profil açıklamanızı, resimlerinizi vb. değiştirin." order_cycle: "Sipariş Dönemi" - order_cycles: "Sipariş Dönemleri" + order_cycles: "SİPARİŞ DÖNEMLERİ" enterprise_relationships: "İŞLETME İZİNLERİ" remove_tax: "Vergiyi kaldır" first_name_begins_with: "Adının BAŞ HARFİ" last_name_begins_with: "Soyadının BAŞ HARFİ" enterprise_tos_link: "İşletme Üyelik Sözleşmesi bağlantısı" - enterprise_tos_message: "Amaçlarımızı ve değerlerimizi paylaşan insanlarla çalışmak istiyoruz. Bu nedenle yeni işletmelerden bunu kabul etmesini istiyoruz:" + enterprise_tos_message: "Amaçlarımızı ve değerlerimizi paylaşan insanlarla çalışmak istiyoruz. Yasal zorunluluk gereği de yeni işletmelerden kabul etmesini istiyoruz:" enterprise_tos_link_text: "Üyelik Sözleşmesi" enterprise_tos_agree: "Yukarıdaki Üyelik Sözleşmesini kabul ediyorum" tax_settings: "Vergi Ayarları" @@ -2232,7 +2235,7 @@ tr: user_invited: "%{email} bu işletmeyi yönetmeye davet edildi" add_manager: "Mevcut bir kullanıcıyı ekle" users: "Kullanıcılar" - about: "Hakkında" + about: "HAKKIMIZDA" images: "Görseller" web: "Web" primary_details: "Temel Bilgiler" @@ -2260,7 +2263,7 @@ tr: content_configuration_pricing_table: "(YAPILACAKLAR: Fiyatlandırma tablosu)" content_configuration_case_studies: "(TODO: Vaka çalışmaları)" content_configuration_detail: "(YAPILACAKLAR: Detay)" - enterprise_name_error: "çoktan alındı. İşletme size aitse ve sahiplik talebinde bulunmak istiyorsanız veya bu işletmeyle ticaret yapmak istiyorsanız lütfen %{email} numaralı telefondan bu profilin şu anki yöneticisiyle iletişime geçin." + enterprise_name_error: "çoktan alındı. İşletme size aitse ve sahiplik talebinde bulunmak istiyorsanız veya bu işletmeyle ticaret yapmak istiyorsanız lütfen %{email} üzerinden bu profilin şu anki yöneticisiyle iletişime geçin." enterprise_owner_error: "^ %{email}‘ın daha fazla işletmeye sahip olmasına izin verilmiyor (limit %{enterprise_limit})." enterprise_role_uniqueness_error: "^ Bu rol zaten var." inventory_item_visibility_error: doğru veya yanlış olmalı @@ -2295,7 +2298,7 @@ tr: order_cycles_no_permission_to_coordinate_error: "Hiçbir işletmenizin sipariş dönemini koordine etme izni yok" order_cycles_no_permission_to_create_error: "Bu işletme tarafından koordine edilen bir sipariş dönemi oluşturma izniniz yok" back_to_orders_list: "Sipariş listesine geri dön" - no_orders_found: "Sipariş bulunamadı" + no_orders_found: "SİPARİŞ BULUNAMADI" order_information: "Sipariş Bilgisi" date_completed: "Tamamlanma Tarihi" amount: "Tutar" @@ -2353,7 +2356,7 @@ tr: saved: KAYDEDİLDİ saving: KAYDEDİYOR enterprise_package: - hub_profile: Türetici Pazarı Profili + hub_profile: Pazar Profili hub_profile_cost: "MALİYET: HER ZAMAN ÜCRETSİZ" hub_profile_text1: > İnsanlar Açık Gıda Ağı üzerinden size ulaşabilir. Haritada görünür ve @@ -2368,8 +2371,7 @@ tr: alıcılara ulaştırabilirsiniz. hub_shop_text2: > Pazarlar gerçek anlamı dışında da bir çok şekil alabilir: Gıda kooperatifleri, - gıda toplulukları, haftalık gıda kolisi üyelikleri, alım grupları, dükkanlar - vs. + gıda toplulukları, haftalık gıda kolisi üyelikleri, alım grupları vs. hub_shop_text3: > Kendi ürünlerinizi de satmak isterseniz, işletme bilginizi üretici olarak güncellemelisiniz. @@ -2452,14 +2454,14 @@ tr: variants_loaded: "%{total_number_of_variants} Varyanttan %{num_of_variants_loaded} Tanesi Yüklendi" loading_variants: "Varyantlar Yükleniyor" tag_rules: - shipping_method_tagged_top: "Teslimat yöntemleri etiketlendi" - shipping_method_tagged_bottom: "şunlardır:" - payment_method_tagged_top: "Ödeme yöntemleri etiketleri" - payment_method_tagged_bottom: "şunlardır:" - order_cycle_tagged_top: "Sipariş Dönemleri etiketlendi" - order_cycle_tagged_bottom: "şunlardır:" - inventory_tagged_top: "Stok varyantları etiketlendi" - inventory_tagged_bottom: "şunlardır:" + shipping_method_tagged_top: "Teslimat Yöntemi etiketi" + shipping_method_tagged_bottom: "ise durumu:" + payment_method_tagged_top: "Ödeme Yönteml etiketi" + payment_method_tagged_bottom: "ise durumu:" + order_cycle_tagged_top: "Sipariş Dönemi etiketi" + order_cycle_tagged_bottom: "ise durumu:" + inventory_tagged_top: "Stok varyant etiketi" + inventory_tagged_bottom: "ise durumu:" new_tag_rule_dialog: select_rule_type: "Bir kural türü seçin:" add_rule: "Kural Ekle" @@ -2738,6 +2740,7 @@ tr: customer_details: "Müşteri detayları" adjustments: "Düzeltmeler" payments: "Ödemeler" + return_authorizations: "İade Yetkileri" payment: "Ödeme" payment_method: "Ödeme yöntemi" shipment: "Teslimat" @@ -2748,7 +2751,7 @@ tr: temperature_controlled: "Soğuk Sevkiyat" new_product: "Yeni ürün" administration: "yönetim" - logged_in_as: "olarak giriş yapıldı" + logged_in_as: "Giriş yapıldı" account: "Hesap" logout: "Çıkış Yap" date_range: "Tarih aralığı" @@ -2784,7 +2787,7 @@ tr: cannot_set_shipping_method_without_address: "Müşteri bilgileri girilmeden teslimat yöntemi belirlenemez.." no_tracking_present: "Hiçbir takip detayı sağlanmadı." order_total: "sipariş toplamı" - customer_details: "Müşteri detayları" + customer_details: "MÜŞTERİ DETAYLARI" customer_search: "Müşteri Arama" choose_a_customer: "Bir müşteri seçin" account: "Hesap" @@ -2807,6 +2810,14 @@ tr: new_payment: "Yeni Ödeme" capture: "Tahsilat" void: "Geçersiz" + login: "Oturum aç" + password: "Parola" + signature: "İmza" + solution: "Çözüm" + landing_page: "Ana Sayfa" + server: "Server" + test_mode: "Test Modu" + logourl: "Logourl" configurations: "yapılandırmalar" general_settings: "Genel Ayarlar" site_name: "Site adı" @@ -2871,8 +2882,6 @@ tr: abbreviation: "Kısaltma" new_state: "Yeni Şehir" payment_methods: "Ödeme yöntemleri" - new_payment_method: "Yeni Ödeme Yöntemi" - provider: "Sağlayıcı" taxonomies: "cinsler" new_taxonomy: "Yeni Cins" back_to_taxonomies_list: "Cinsler Listesine Geri Dön" @@ -2886,7 +2895,7 @@ tr: default: "varsayılan" calculator: "Hesaplama" zone: "bölge" - display: "Görüntüle" + display: "GÖSTER" environment: "çevre" active: "Aktif" nore: "Daha fazla" @@ -2925,6 +2934,12 @@ tr: options: "Seçenekler" actions: update: "Güncelle" + shared: + error_messages: + errors_prohibited_this_record_from_being_saved: + one: "1 hata kaydedilmesini engelledi:" + other: "%{count}hata kaydedilmeyi engelledi:" + there_were_problems_with_the_following_fields: "Gösterilen alanlar ile ilgili sorun oluştu:" errors: messages: blank: "boş olamaz" @@ -2936,7 +2951,7 @@ tr: admin: tab: dashboard: "KONTROL PANELİ" - orders: "Siparişler" + orders: "SİPARİŞLER" bulk_order_management: "Toplu Sipariş Yönetimi" subscriptions: "Üyelikler" products: "Ürünler" @@ -2947,7 +2962,7 @@ tr: configuration: "KURULUM" users: "Kullanıcılar" roles: "Roller" - order_cycles: "Sipariş Dönemleri" + order_cycles: "SİPARİŞ DÖNEMLERİ" enterprises: "İşletmeler" enterprise_relationships: "İZİNLER" customers: "Müşteriler" @@ -2975,7 +2990,7 @@ tr: index: new_return_authorization: "Yeni İade Yetkisi" return_authorizations: "İade Yetkileri" - back_to_orders_list: "Siparişler Listesine Geri Dön" + back_to_orders_list: "SİPARİŞLER LİSTESİNE GERİ DÖN" rma_number: "RMA Numarası" status: "Durum" amount: "Miktar" @@ -3004,7 +3019,7 @@ tr: canceled: "İptal edildi" orders: index: - listing_orders: "Siparişler Listeleniyor" + listing_orders: "SİPARİŞLER LİSTELENİYOR" new_order: "Yeni Sipariş" capture: "Tahsilat" ship: "Teslimat" @@ -3016,7 +3031,7 @@ tr: previous: "Önceki" next: "Sonraki" loading: "Yükleniyor" - no_orders_found: "Sipariş Bulunamadı" + no_orders_found: "SİPARİŞ BULUNAMADI" results_found: "%{number} Sonuç bulundu." viewing: "%{start} - %{end} görüntüleniyor." print_invoices: "Faturaları Yazdır" @@ -3051,7 +3066,7 @@ tr: one: "Bir aktif ürününüz var" other: "%{count} aktif ürününüz var" order_cycles: - order_cycles: "Sipariş Dönemleri" + order_cycles: "SİPARİŞ DÖNEMLERİ" order_cycles_tip: "Sipariş dönemleri, ürünlerinizin müşterilere ne zaman ve nerede ulaşacağını belirler." you_have_active: zero: "Aktif sipariş döneminiz yok." @@ -3066,7 +3081,9 @@ tr: products_distributor: "Dağıtımcı" zone: "bölge" calculator: "Hesaplama" - display: "Görüntüle" + display: "GÖSTER" + both: "Ödeme Sayfası ve Panel" + back_end: "Sadece panel" no_shipping_methods_found: "Hiçbir teslimat yöntemi bulunamadı" new: new_shipping_method: "Yeni Teslimat Yöntemi" @@ -3078,11 +3095,30 @@ tr: form: categories: "Kategoriler" zones: "bölgeler" + both: "Ödeme Sayfası ve Panel" + back_end: "Sadece panel" + deactivation_warning: "Bir teslimat yöntemini etkisiz hale getirmek listenizden kaldırılmasına sebep olabilir. Alternatif olarak, ayarlarınızı 'Göster' yerine 'sadece panel' olarak değiştirerek teslimat yöntemini ödeme sayfasında gizleyebilirsiniz." payment_methods: + index: + payment_methods: "ÖDEME YÖNTEMLERİ" + new_payment_method: "Yeni Ödeme Yöntemi" + name: "İSİM" + products_distributor: "Dağıtımcı" + provider: "Sağlayıcı" + environment: "Çevre" + display: "GÖSTER" + active: "Aktif" + both: "Her ikisi de" + front_end: "Sadece Ödeme" + back_end: "Sadece panel" + active_yes: "Evet" + active_no: "Hayır" + no_payment_methods_found: "Ödeme yöntemi bulunamadı" new: new_payment_method: "Yeni Ödeme Yöntemi" back_to_payment_methods_list: "Ödeme Yöntemleri Listesine Geri Dön" edit: + new: "Yeni" editing_payment_method: "Ödeme Yöntemi Düzenleniyor" back_to_payment_methods_list: "Ödeme Yöntemleri Listesine Geri Dön" stripe_connect: @@ -3098,6 +3134,21 @@ tr: account_id: Hesap Kimliği business_name: işletme adı charges_enabled: Masraflar Etkin + form: + name: "İSİM" + description: "Açıklama" + environment: "Çevre" + display: "GÖSTER" + active: "Aktif" + active_yes: "Evet" + active_no: "Hayır" + both: "Ödeme Sayfası ve Panel" + front_end: "Sadece Ödeme" + back_end: "Sadece panel" + tags: "Etiketler" + deactivation_warning: "Bir ödeme yöntemini kaldırmak listenizden silinmesine sebep olabilir. Alternatif olarak, ödeme yöntemi ayarını 'Göster' yerine 'Sadece Panel' olarak değiştirebilirsiniz. " + providers: + provider: "Sağlayıcı" payments: source_forms: stripe: @@ -3200,6 +3251,7 @@ tr: display_as_placeholder: 'örn. 2 kg' display_name_placeholder: 'örn. Domates' autocomplete: + out_of_stock: "Stok tükendi" producer_name: "Üretici" unit: "Birim" shared: @@ -3237,6 +3289,7 @@ tr: format: '% Y-% A-%d' js_format: 'yy-aa-gg' orders: + error_flash_for_unavailable_items: "Sepetinizdeki ürünlerden biri bitti veya azaldı. Lütfen seçili miktarı güncelleyin." edit: login_to_view_order: "Siparişinizi görmek için lütfen giriş yapın." bought: @@ -3264,9 +3317,14 @@ tr: invalid: geçersiz order_mailer: cancel_email: - customer_greeting: "Merhaba %{name}!" - instructions: "Siparişiniz iptal edildi. Lütfen kayıtlarınız için bu iptal bilgilerini saklayın." - order_summary_canceled: "Sipariş Özeti [İPTAL EDİLDİ]" + customer_greeting: "Sevgili %{name}," + instructions_html: "%{distributor} siparişiniz İPTAL EDİLDİ. Lütfen not edin." + dont_cancel: "Eğer fikrinizi değiştirdiyseniz ve siparişi iptal etmek istemiyorsanız lütfen %{email} ile iletişime geçin." + order_summary_canceled_html: "Sipariş Özeti #%{number}(İPTAL EDİLDİ)" + details: "İşte siparişinizin özeti:" + unpaid_order: "Sipariş ödemeniz yapılmadığı için iade işlemi yapılmadı" + paid_order: "Siparişinizin ödemesi yapılmıştı, bu sebeple %{distributor}iade işlemi gerçekleştirdi." + credit_order: "Siparişinizin ödemesi yapılmıştı, bu sebeple hesabınızdan düşüldü." subject: "Sipariş İptali" confirm_email: subject: "Sipariş Onayı" @@ -3311,14 +3369,14 @@ tr: account_settings: Hesap Ayarları show: tabs: - orders: Siparişler + orders: SİPARİŞLER cards: Kredi kartları transactions: İşlemler settings: Hesap ayarları unconfirmed_email: "Bekleyen e-posta onayı: %{unconfirmed_email}. Yeni e-posta onaylandıktan sonra e-posta adresiniz güncellenecektir." orders: - open_orders: Açık Siparişler - past_orders: Geçmiş Siparişler + open_orders: AÇIK SİPARİŞLER + past_orders: GEÇMİŞ SİPARİŞLER transactions: transaction_history: İşlem Geçmişi open_orders: diff --git a/config/routes.rb b/config/routes.rb index fcb633f9e3..877ca407d3 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -24,7 +24,7 @@ Openfoodnetwork::Application.routes.draw do get "/learn", to: redirect("https://openfoodnetwork.org/#{ENV['DEFAULT_COUNTRY_CODE'].andand.downcase}/learn/") get "/cart", :to => "spree/orders#edit", :as => :cart - put "/cart", :to => "spree/orders#update", :as => :update_cart + patch "/cart", :to => "spree/orders#update", :as => :update_cart put "/cart/empty", :to => 'spree/orders#empty', :as => :empty_cart get '/orders/:id/token/:token' => 'spree/orders#show', :as => :token_order diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 3456248e25..931015e302 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -27,7 +27,7 @@ Openfoodnetwork::Application.routes.draw do member do get :welcome - put :register + patch :register end resources :producer_properties do diff --git a/config/routes/spree.rb b/config/routes/spree.rb index fc0de19a10..ca5993aca5 100644 --- a/config/routes/spree.rb +++ b/config/routes/spree.rb @@ -1,5 +1,7 @@ # Overriding Devise routes to use our own controller Spree::Core::Engine.routes.draw do + root to: 'home#index' + devise_for :spree_user, :class_name => 'Spree::User', :controllers => { :sessions => 'spree/user_sessions', @@ -131,7 +133,7 @@ Spree::Core::Engine.routes.draw do # Configuration section resource :general_settings - resource :mail_method, :only => [:edit, :update] do + resource :mail_methods, :only => [:edit, :update] do post :testmail, :on => :collection end diff --git a/db/default/users.rb b/db/default/users.rb index c968ccf778..cc30bb5076 100644 --- a/db/default/users.rb +++ b/db/default/users.rb @@ -52,14 +52,14 @@ def create_admin_user load 'spree/user.rb' - if Spree::User.find_by_email(email) + if Spree::User.find_by(email: email) say "\nWARNING: There is already a user with the email: #{email}, so no account changes were made. If you wish to create an additional admin user, please run rake spree_auth:admin:create again with a different email.\n\n" else admin = Spree::User.new(attributes) admin.skip_confirmation! admin.skip_confirmation_notification! if admin.save - role = Spree::Role.find_or_create_by_name 'admin' + role = Spree::Role.find_or_create_by(name: 'admin') admin.spree_roles << role admin.save say "Done!" diff --git a/db/migrate/20190321203818_add_deleted_at_to_spree_stock_items.rb b/db/migrate/20190321203818_add_deleted_at_to_spree_stock_items.rb new file mode 100644 index 0000000000..3170545118 --- /dev/null +++ b/db/migrate/20190321203818_add_deleted_at_to_spree_stock_items.rb @@ -0,0 +1,5 @@ +class AddDeletedAtToSpreeStockItems < ActiveRecord::Migration + def up + add_column :spree_stock_items, :deleted_at, :datetime + end +end diff --git a/db/schema.rb b/db/schema.rb index 99415dc9fa..e2ec79428a 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -9,11 +9,14 @@ # from scratch. The latter is a flawed and unsustainable approach (the more migrations # you'll amass, the slower it'll run and the greater likelihood for issues). # -# It's strongly recommended to check this file into your version control system. +# It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(:version => 20200508101630) do +ActiveRecord::Schema.define(version: 20200508101630) do - create_table "adjustment_metadata", :force => true do |t| + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + + create_table "adjustment_metadata", force: true do |t| t.integer "adjustment_id" t.integer "enterprise_id" t.string "fee_name" @@ -21,95 +24,95 @@ ActiveRecord::Schema.define(:version => 20200508101630) do t.string "enterprise_role" end - add_index "adjustment_metadata", ["adjustment_id"], :name => "index_adjustment_metadata_on_adjustment_id" - add_index "adjustment_metadata", ["enterprise_id"], :name => "index_adjustment_metadata_on_enterprise_id" + add_index "adjustment_metadata", ["adjustment_id"], name: "index_adjustment_metadata_on_adjustment_id", using: :btree + add_index "adjustment_metadata", ["enterprise_id"], name: "index_adjustment_metadata_on_enterprise_id", using: :btree - create_table "column_preferences", :force => true do |t| - t.integer "user_id", :null => false - t.string "action_name", :null => false - t.string "column_name", :null => false - t.boolean "visible", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "column_preferences", force: true do |t| + t.integer "user_id", null: false + t.string "action_name", null: false + t.string "column_name", null: false + t.boolean "visible", null: false + t.datetime "created_at" + t.datetime "updated_at" end - add_index "column_preferences", ["user_id", "action_name", "column_name"], :name => "index_column_prefs_on_user_id_and_action_name_and_column_name", :unique => true + add_index "column_preferences", ["user_id", "action_name", "column_name"], name: "index_column_prefs_on_user_id_and_action_name_and_column_name", unique: true, using: :btree - create_table "coordinator_fees", :force => true do |t| + create_table "coordinator_fees", force: true do |t| t.integer "order_cycle_id" t.integer "enterprise_fee_id" end - add_index "coordinator_fees", ["enterprise_fee_id"], :name => "index_coordinator_fees_on_enterprise_fee_id" - add_index "coordinator_fees", ["order_cycle_id"], :name => "index_coordinator_fees_on_order_cycle_id" + add_index "coordinator_fees", ["enterprise_fee_id"], name: "index_coordinator_fees_on_enterprise_fee_id", using: :btree + add_index "coordinator_fees", ["order_cycle_id"], name: "index_coordinator_fees_on_order_cycle_id", using: :btree - create_table "customers", :force => true do |t| - t.string "email", :null => false - t.integer "enterprise_id", :null => false + create_table "customers", force: true do |t| + t.string "email", null: false + t.integer "enterprise_id", null: false t.string "code" t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "bill_address_id" t.integer "ship_address_id" t.string "name" - t.boolean "allow_charges", :default => false, :null => false + t.boolean "allow_charges", default: false, null: false end - add_index "customers", ["bill_address_id"], :name => "index_customers_on_bill_address_id" - add_index "customers", ["email"], :name => "index_customers_on_email" - add_index "customers", ["enterprise_id", "code"], :name => "index_customers_on_enterprise_id_and_code", :unique => true - add_index "customers", ["ship_address_id"], :name => "index_customers_on_ship_address_id" - add_index "customers", ["user_id"], :name => "index_customers_on_user_id" + add_index "customers", ["bill_address_id"], name: "index_customers_on_bill_address_id", using: :btree + add_index "customers", ["email"], name: "index_customers_on_email", using: :btree + add_index "customers", ["enterprise_id", "code"], name: "index_customers_on_enterprise_id_and_code", unique: true, using: :btree + add_index "customers", ["ship_address_id"], name: "index_customers_on_ship_address_id", using: :btree + add_index "customers", ["user_id"], name: "index_customers_on_user_id", using: :btree - create_table "delayed_jobs", :force => true do |t| - t.integer "priority", :default => 0, :null => false - t.integer "attempts", :default => 0, :null => false - t.text "handler", :null => false + create_table "delayed_jobs", force: true do |t| + t.integer "priority", default: 0, null: false + t.integer "attempts", default: 0, null: false + t.text "handler", null: false t.text "last_error" t.datetime "run_at" t.datetime "locked_at" t.datetime "failed_at" t.string "locked_by" t.string "queue" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end - add_index "delayed_jobs", ["priority", "run_at"], :name => "delayed_jobs_priority" + add_index "delayed_jobs", ["priority", "run_at"], name: "delayed_jobs_priority", using: :btree - create_table "distributors_payment_methods", :id => false, :force => true do |t| + create_table "distributors_payment_methods", id: false, force: true do |t| t.integer "distributor_id" t.integer "payment_method_id" end - add_index "distributors_payment_methods", ["distributor_id"], :name => "index_distributors_payment_methods_on_distributor_id" - add_index "distributors_payment_methods", ["payment_method_id"], :name => "index_distributors_payment_methods_on_payment_method_id" + add_index "distributors_payment_methods", ["distributor_id"], name: "index_distributors_payment_methods_on_distributor_id", using: :btree + add_index "distributors_payment_methods", ["payment_method_id"], name: "index_distributors_payment_methods_on_payment_method_id", using: :btree - create_table "distributors_shipping_methods", :force => true do |t| + create_table "distributors_shipping_methods", force: true do |t| t.integer "distributor_id" t.integer "shipping_method_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end - add_index "distributors_shipping_methods", ["distributor_id"], :name => "index_distributors_shipping_methods_on_distributor_id" - add_index "distributors_shipping_methods", ["shipping_method_id"], :name => "index_distributors_shipping_methods_on_shipping_method_id" + add_index "distributors_shipping_methods", ["distributor_id"], name: "index_distributors_shipping_methods_on_distributor_id", using: :btree + add_index "distributors_shipping_methods", ["shipping_method_id"], name: "index_distributors_shipping_methods_on_shipping_method_id", using: :btree - create_table "enterprise_fees", :force => true do |t| + create_table "enterprise_fees", force: true do |t| t.integer "enterprise_id" t.string "fee_type" t.string "name" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "tax_category_id" - t.boolean "inherits_tax_category", :default => false, :null => false + t.boolean "inherits_tax_category", default: false, null: false end - add_index "enterprise_fees", ["enterprise_id"], :name => "index_enterprise_fees_on_enterprise_id" - add_index "enterprise_fees", ["tax_category_id"], :name => "index_enterprise_fees_on_tax_category_id" + add_index "enterprise_fees", ["enterprise_id"], name: "index_enterprise_fees_on_enterprise_id", using: :btree + add_index "enterprise_fees", ["tax_category_id"], name: "index_enterprise_fees_on_tax_category_id", using: :btree - create_table "enterprise_groups", :force => true do |t| + create_table "enterprise_groups", force: true do |t| t.string "name" t.boolean "on_front_page" t.integer "position" @@ -124,56 +127,56 @@ ActiveRecord::Schema.define(:version => 20200508101630) do t.integer "logo_file_size" t.datetime "logo_updated_at" t.integer "address_id" - t.string "email", :default => "", :null => false - t.string "website", :default => "", :null => false - t.string "facebook", :default => "", :null => false - t.string "instagram", :default => "", :null => false - t.string "linkedin", :default => "", :null => false - t.string "twitter", :default => "", :null => false + t.string "email", default: "", null: false + t.string "website", default: "", null: false + t.string "facebook", default: "", null: false + t.string "instagram", default: "", null: false + t.string "linkedin", default: "", null: false + t.string "twitter", default: "", null: false t.integer "owner_id" - t.string "permalink", :null => false + t.string "permalink", null: false end - add_index "enterprise_groups", ["address_id"], :name => "index_enterprise_groups_on_address_id" - add_index "enterprise_groups", ["owner_id"], :name => "index_enterprise_groups_on_owner_id" - add_index "enterprise_groups", ["permalink"], :name => "index_enterprise_groups_on_permalink", :unique => true + add_index "enterprise_groups", ["address_id"], name: "index_enterprise_groups_on_address_id", using: :btree + add_index "enterprise_groups", ["owner_id"], name: "index_enterprise_groups_on_owner_id", using: :btree + add_index "enterprise_groups", ["permalink"], name: "index_enterprise_groups_on_permalink", unique: true, using: :btree - create_table "enterprise_groups_enterprises", :id => false, :force => true do |t| + create_table "enterprise_groups_enterprises", id: false, force: true do |t| t.integer "enterprise_group_id" t.integer "enterprise_id" end - add_index "enterprise_groups_enterprises", ["enterprise_group_id"], :name => "index_enterprise_groups_enterprises_on_enterprise_group_id" - add_index "enterprise_groups_enterprises", ["enterprise_id"], :name => "index_enterprise_groups_enterprises_on_enterprise_id" + add_index "enterprise_groups_enterprises", ["enterprise_group_id"], name: "index_enterprise_groups_enterprises_on_enterprise_group_id", using: :btree + add_index "enterprise_groups_enterprises", ["enterprise_id"], name: "index_enterprise_groups_enterprises_on_enterprise_id", using: :btree - create_table "enterprise_relationship_permissions", :force => true do |t| + create_table "enterprise_relationship_permissions", force: true do |t| t.integer "enterprise_relationship_id" - t.string "name", :null => false + t.string "name", null: false end - add_index "enterprise_relationship_permissions", ["enterprise_relationship_id"], :name => "index_erp_on_erid" + add_index "enterprise_relationship_permissions", ["enterprise_relationship_id"], name: "index_erp_on_erid", using: :btree - create_table "enterprise_relationships", :force => true do |t| + create_table "enterprise_relationships", force: true do |t| t.integer "parent_id" t.integer "child_id" end - add_index "enterprise_relationships", ["child_id"], :name => "index_enterprise_relationships_on_child_id" - add_index "enterprise_relationships", ["parent_id", "child_id"], :name => "index_enterprise_relationships_on_parent_id_and_child_id", :unique => true - add_index "enterprise_relationships", ["parent_id"], :name => "index_enterprise_relationships_on_parent_id" + add_index "enterprise_relationships", ["child_id"], name: "index_enterprise_relationships_on_child_id", using: :btree + add_index "enterprise_relationships", ["parent_id", "child_id"], name: "index_enterprise_relationships_on_parent_id_and_child_id", unique: true, using: :btree + add_index "enterprise_relationships", ["parent_id"], name: "index_enterprise_relationships_on_parent_id", using: :btree - create_table "enterprise_roles", :force => true do |t| + create_table "enterprise_roles", force: true do |t| t.integer "user_id" t.integer "enterprise_id" - t.boolean "receives_notifications", :default => false + t.boolean "receives_notifications", default: false end - add_index "enterprise_roles", ["enterprise_id", "user_id"], :name => "index_enterprise_roles_on_enterprise_id_and_user_id", :unique => true - add_index "enterprise_roles", ["enterprise_id"], :name => "index_enterprise_roles_on_enterprise_id" - add_index "enterprise_roles", ["user_id", "enterprise_id"], :name => "index_enterprise_roles_on_user_id_and_enterprise_id", :unique => true - add_index "enterprise_roles", ["user_id"], :name => "index_enterprise_roles_on_user_id" + add_index "enterprise_roles", ["enterprise_id", "user_id"], name: "index_enterprise_roles_on_enterprise_id_and_user_id", unique: true, using: :btree + add_index "enterprise_roles", ["enterprise_id"], name: "index_enterprise_roles_on_enterprise_id", using: :btree + add_index "enterprise_roles", ["user_id", "enterprise_id"], name: "index_enterprise_roles_on_user_id_and_enterprise_id", unique: true, using: :btree + add_index "enterprise_roles", ["user_id"], name: "index_enterprise_roles_on_user_id", using: :btree - create_table "enterprises", :force => true do |t| + create_table "enterprises", force: true do |t| t.string "name" t.text "description" t.text "long_description" @@ -187,8 +190,8 @@ ActiveRecord::Schema.define(:version => 20200508101630) do t.integer "address_id" t.text "pickup_times" t.string "next_collection_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.text "distributor_info" t.string "logo_file_name" t.string "logo_content_type" @@ -198,141 +201,141 @@ ActiveRecord::Schema.define(:version => 20200508101630) do t.string "promo_image_content_type" t.integer "promo_image_file_size" t.datetime "promo_image_updated_at" - t.boolean "visible", :default => true + t.boolean "visible", default: true t.string "facebook" t.string "instagram" t.string "linkedin" - t.integer "owner_id", :null => false - t.string "sells", :default => "none", :null => false - t.boolean "producer_profile_only", :default => false - t.string "permalink", :null => false - t.boolean "charges_sales_tax", :default => false, :null => false + t.integer "owner_id", null: false + t.string "sells", default: "none", null: false + t.boolean "producer_profile_only", default: false + t.string "permalink", null: false + t.boolean "charges_sales_tax", default: false, null: false t.string "email_address" - t.boolean "require_login", :default => false, :null => false - t.boolean "allow_guest_orders", :default => true, :null => false + t.boolean "require_login", default: false, null: false + t.boolean "allow_guest_orders", default: true, null: false t.text "invoice_text" - t.boolean "display_invoice_logo", :default => false - t.boolean "allow_order_changes", :default => false, :null => false - t.boolean "enable_subscriptions", :default => false, :null => false + t.boolean "display_invoice_logo", default: false + t.boolean "allow_order_changes", default: false, null: false + t.boolean "enable_subscriptions", default: false, null: false end - add_index "enterprises", ["address_id"], :name => "index_enterprises_on_address_id" - add_index "enterprises", ["is_primary_producer", "sells"], :name => "index_enterprises_on_is_primary_producer_and_sells" - add_index "enterprises", ["name"], :name => "index_enterprises_on_name", :unique => true - add_index "enterprises", ["owner_id"], :name => "index_enterprises_on_owner_id" - add_index "enterprises", ["permalink"], :name => "index_enterprises_on_permalink", :unique => true - add_index "enterprises", ["sells"], :name => "index_enterprises_on_sells" + add_index "enterprises", ["address_id"], name: "index_enterprises_on_address_id", using: :btree + add_index "enterprises", ["is_primary_producer", "sells"], name: "index_enterprises_on_is_primary_producer_and_sells", using: :btree + add_index "enterprises", ["name"], name: "index_enterprises_on_name", unique: true, using: :btree + add_index "enterprises", ["owner_id"], name: "index_enterprises_on_owner_id", using: :btree + add_index "enterprises", ["permalink"], name: "index_enterprises_on_permalink", unique: true, using: :btree + add_index "enterprises", ["sells"], name: "index_enterprises_on_sells", using: :btree - create_table "exchange_fees", :force => true do |t| + create_table "exchange_fees", force: true do |t| t.integer "exchange_id" t.integer "enterprise_fee_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end - add_index "exchange_fees", ["enterprise_fee_id"], :name => "index_exchange_fees_on_enterprise_fee_id" - add_index "exchange_fees", ["exchange_id"], :name => "index_exchange_fees_on_exchange_id" + add_index "exchange_fees", ["enterprise_fee_id"], name: "index_exchange_fees_on_enterprise_fee_id", using: :btree + add_index "exchange_fees", ["exchange_id"], name: "index_exchange_fees_on_exchange_id", using: :btree - create_table "exchange_variants", :force => true do |t| + create_table "exchange_variants", force: true do |t| t.integer "exchange_id" t.integer "variant_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end - add_index "exchange_variants", ["exchange_id"], :name => "index_exchange_variants_on_exchange_id" - add_index "exchange_variants", ["variant_id"], :name => "index_exchange_variants_on_variant_id" + add_index "exchange_variants", ["exchange_id"], name: "index_exchange_variants_on_exchange_id", using: :btree + add_index "exchange_variants", ["variant_id"], name: "index_exchange_variants_on_variant_id", using: :btree - create_table "exchanges", :force => true do |t| + create_table "exchanges", force: true do |t| t.integer "order_cycle_id" t.integer "sender_id" t.integer "receiver_id" t.text "pickup_time" t.text "pickup_instructions" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.boolean "incoming", :default => false, :null => false + t.datetime "created_at" + t.datetime "updated_at" + t.boolean "incoming", default: false, null: false t.text "receival_instructions" end - add_index "exchanges", ["order_cycle_id"], :name => "index_exchanges_on_order_cycle_id" - add_index "exchanges", ["receiver_id"], :name => "index_exchanges_on_receiver_id" - add_index "exchanges", ["sender_id"], :name => "index_exchanges_on_sender_id" + add_index "exchanges", ["order_cycle_id"], name: "index_exchanges_on_order_cycle_id", using: :btree + add_index "exchanges", ["receiver_id"], name: "index_exchanges_on_receiver_id", using: :btree + add_index "exchanges", ["sender_id"], name: "index_exchanges_on_sender_id", using: :btree - create_table "inventory_items", :force => true do |t| - t.integer "enterprise_id", :null => false - t.integer "variant_id", :null => false - t.boolean "visible", :default => true, :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - end - - add_index "inventory_items", ["enterprise_id", "variant_id"], :name => "index_inventory_items_on_enterprise_id_and_variant_id", :unique => true - - create_table "order_cycle_schedules", :force => true do |t| - t.integer "order_cycle_id", :null => false - t.integer "schedule_id", :null => false + create_table "inventory_items", force: true do |t| + t.integer "enterprise_id", null: false + t.integer "variant_id", null: false + t.boolean "visible", default: true, null: false t.datetime "created_at" t.datetime "updated_at" end - add_index "order_cycle_schedules", ["order_cycle_id"], :name => "index_order_cycle_schedules_on_order_cycle_id" - add_index "order_cycle_schedules", ["schedule_id"], :name => "index_order_cycle_schedules_on_schedule_id" + add_index "inventory_items", ["enterprise_id", "variant_id"], name: "index_inventory_items_on_enterprise_id_and_variant_id", unique: true, using: :btree - create_table "order_cycles", :force => true do |t| + create_table "order_cycle_schedules", force: true do |t| + t.integer "order_cycle_id", null: false + t.integer "schedule_id", null: false + t.datetime "created_at" + t.datetime "updated_at" + end + + add_index "order_cycle_schedules", ["order_cycle_id"], name: "index_order_cycle_schedules_on_order_cycle_id", using: :btree + add_index "order_cycle_schedules", ["schedule_id"], name: "index_order_cycle_schedules_on_schedule_id", using: :btree + + create_table "order_cycles", force: true do |t| t.string "name" t.datetime "orders_open_at" t.datetime "orders_close_at" t.integer "coordinator_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end - create_table "producer_properties", :force => true do |t| + create_table "producer_properties", force: true do |t| t.string "value" t.integer "producer_id" t.integer "property_id" - t.integer "position", :default => 0, :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.integer "position", default: 0, null: false + t.datetime "created_at" + t.datetime "updated_at" end - add_index "producer_properties", ["position"], :name => "index_producer_properties_on_position" - add_index "producer_properties", ["producer_id"], :name => "index_producer_properties_on_producer_id" - add_index "producer_properties", ["property_id"], :name => "index_producer_properties_on_property_id" + add_index "producer_properties", ["position"], name: "index_producer_properties_on_position", using: :btree + add_index "producer_properties", ["producer_id"], name: "index_producer_properties_on_producer_id", using: :btree + add_index "producer_properties", ["property_id"], name: "index_producer_properties_on_property_id", using: :btree - create_table "proxy_orders", :force => true do |t| - t.integer "subscription_id", :null => false + create_table "proxy_orders", force: true do |t| + t.integer "subscription_id", null: false t.integer "order_id" t.datetime "canceled_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "order_cycle_id", :null => false + t.datetime "created_at" + t.datetime "updated_at" + t.integer "order_cycle_id", null: false t.datetime "placed_at" t.datetime "confirmed_at" end - add_index "proxy_orders", ["order_cycle_id", "subscription_id"], :name => "index_proxy_orders_on_order_cycle_id_and_subscription_id", :unique => true - add_index "proxy_orders", ["order_id"], :name => "index_proxy_orders_on_order_id", :unique => true - add_index "proxy_orders", ["subscription_id"], :name => "index_proxy_orders_on_subscription_id" + add_index "proxy_orders", ["order_cycle_id", "subscription_id"], name: "index_proxy_orders_on_order_cycle_id_and_subscription_id", unique: true, using: :btree + add_index "proxy_orders", ["order_id"], name: "index_proxy_orders_on_order_id", unique: true, using: :btree + add_index "proxy_orders", ["subscription_id"], name: "index_proxy_orders_on_subscription_id", using: :btree - create_table "schedules", :force => true do |t| - t.string "name", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "schedules", force: true do |t| + t.string "name", null: false + t.datetime "created_at" + t.datetime "updated_at" end - create_table "sessions", :force => true do |t| - t.string "session_id", :null => false + create_table "sessions", force: true do |t| + t.string "session_id", null: false t.text "data" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end - add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id" - add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at" + add_index "sessions", ["session_id"], name: "index_sessions_on_session_id", using: :btree + add_index "sessions", ["updated_at"], name: "index_sessions_on_updated_at", using: :btree - create_table "spree_activators", :force => true do |t| + create_table "spree_activators", force: true do |t| t.string "description" t.datetime "expires_at" t.datetime "created_at" @@ -342,13 +345,13 @@ ActiveRecord::Schema.define(:version => 20200508101630) do t.string "event_name" t.string "type" t.integer "usage_limit" - t.string "match_policy", :default => "all" + t.string "match_policy", default: "all" t.string "code" - t.boolean "advertise", :default => false + t.boolean "advertise", default: false t.string "path" end - create_table "spree_addresses", :force => true do |t| + create_table "spree_addresses", force: true do |t| t.string "firstname" t.string "lastname" t.string "address1" @@ -360,79 +363,79 @@ ActiveRecord::Schema.define(:version => 20200508101630) do t.string "alternative_phone" t.integer "state_id" t.integer "country_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "company" t.float "latitude" t.float "longitude" end - add_index "spree_addresses", ["firstname"], :name => "index_addresses_on_firstname" - add_index "spree_addresses", ["lastname"], :name => "index_addresses_on_lastname" + add_index "spree_addresses", ["firstname"], name: "index_addresses_on_firstname", using: :btree + add_index "spree_addresses", ["lastname"], name: "index_addresses_on_lastname", using: :btree - create_table "spree_adjustments", :force => true do |t| + create_table "spree_adjustments", force: true do |t| t.integer "source_id" - t.decimal "amount", :precision => 10, :scale => 2 + t.decimal "amount", precision: 10, scale: 2 t.string "label" t.string "source_type" t.integer "adjustable_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.boolean "mandatory" t.integer "originator_id" t.string "originator_type" - t.boolean "eligible", :default => true + t.boolean "eligible", default: true t.string "adjustable_type" - t.decimal "included_tax", :precision => 10, :scale => 2, :default => 0.0, :null => false + t.decimal "included_tax", precision: 10, scale: 2, default: 0.0, null: false t.string "state" end - add_index "spree_adjustments", ["adjustable_id"], :name => "index_adjustments_on_order_id" + add_index "spree_adjustments", ["adjustable_id"], name: "index_adjustments_on_order_id", using: :btree - create_table "spree_assets", :force => true do |t| + create_table "spree_assets", force: true do |t| t.integer "viewable_id" t.integer "attachment_width" t.integer "attachment_height" t.integer "attachment_file_size" t.integer "position" - t.string "viewable_type", :limit => 50 + t.string "viewable_type", limit: 50 t.string "attachment_content_type" t.string "attachment_file_name" - t.string "type", :limit => 75 + 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" + add_index "spree_assets", ["viewable_id"], name: "index_assets_on_viewable_id", using: :btree + add_index "spree_assets", ["viewable_type", "type"], name: "index_assets_on_viewable_type_and_type", using: :btree - create_table "spree_calculators", :force => true do |t| + create_table "spree_calculators", force: true do |t| t.string "type" - t.integer "calculable_id", :null => false - t.string "calculable_type", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.integer "calculable_id", null: false + t.string "calculable_type", null: false + t.datetime "created_at" + t.datetime "updated_at" end - create_table "spree_configurations", :force => true do |t| + create_table "spree_configurations", force: true do |t| t.string "name" - t.string "type", :limit => 50 - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.string "type", limit: 50 + t.datetime "created_at" + t.datetime "updated_at" end - add_index "spree_configurations", ["name", "type"], :name => "index_configurations_on_name_and_type" + add_index "spree_configurations", ["name", "type"], name: "index_configurations_on_name_and_type", using: :btree - create_table "spree_countries", :force => true do |t| + create_table "spree_countries", force: true do |t| t.string "iso_name" t.string "iso" t.string "iso3" t.string "name" t.integer "numcode" - t.boolean "states_required", :default => true + t.boolean "states_required", default: true end - create_table "spree_credit_cards", :force => true do |t| + create_table "spree_credit_cards", force: true do |t| t.string "month" t.string "year" t.string "cc_type" @@ -443,116 +446,116 @@ ActiveRecord::Schema.define(:version => 20200508101630) do t.string "start_year" t.string "issue_number" t.integer "address_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "gateway_customer_profile_id" t.string "gateway_payment_profile_id" t.integer "user_id" t.integer "payment_method_id" - t.boolean "is_default", :default => false + t.boolean "is_default", default: false end - add_index "spree_credit_cards", ["payment_method_id"], :name => "index_spree_credit_cards_on_payment_method_id" - add_index "spree_credit_cards", ["user_id"], :name => "index_spree_credit_cards_on_user_id" + add_index "spree_credit_cards", ["payment_method_id"], name: "index_spree_credit_cards_on_payment_method_id", using: :btree + add_index "spree_credit_cards", ["user_id"], name: "index_spree_credit_cards_on_user_id", using: :btree - create_table "spree_gateways", :force => true do |t| + create_table "spree_gateways", force: true 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.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.boolean "active", default: true + t.string "environment", default: "development" + t.string "server", default: "test" + t.boolean "test_mode", default: true + t.datetime "created_at" + t.datetime "updated_at" end - create_table "spree_inventory_units", :force => true do |t| + create_table "spree_inventory_units", force: true do |t| t.string "state" t.integer "variant_id" t.integer "order_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "shipment_id" t.integer "return_authorization_id" - t.boolean "pending", :default => true + t.boolean "pending", default: true 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" + add_index "spree_inventory_units", ["order_id"], name: "index_inventory_units_on_order_id", using: :btree + add_index "spree_inventory_units", ["shipment_id"], name: "index_inventory_units_on_shipment_id", using: :btree + add_index "spree_inventory_units", ["variant_id"], name: "index_inventory_units_on_variant_id", using: :btree - create_table "spree_line_items", :force => true do |t| + create_table "spree_line_items", force: true do |t| t.integer "order_id" t.integer "variant_id" - t.integer "quantity", :null => false - t.decimal "price", :precision => 8, :scale => 2, :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.integer "quantity", null: false + t.decimal "price", precision: 8, scale: 2, null: false + t.datetime "created_at" + t.datetime "updated_at" t.integer "max_quantity" t.string "currency" - t.decimal "distribution_fee", :precision => 10, :scale => 2 - t.decimal "final_weight_volume", :precision => 10, :scale => 2 - t.decimal "cost_price", :precision => 8, :scale => 2 + t.decimal "distribution_fee", precision: 10, scale: 2 + t.decimal "final_weight_volume", precision: 10, scale: 2 + t.decimal "cost_price", precision: 8, scale: 2 t.integer "tax_category_id" end - add_index "spree_line_items", ["order_id"], :name => "index_line_items_on_order_id" - add_index "spree_line_items", ["variant_id"], :name => "index_line_items_on_variant_id" + add_index "spree_line_items", ["order_id"], name: "index_line_items_on_order_id", using: :btree + add_index "spree_line_items", ["variant_id"], name: "index_line_items_on_variant_id", using: :btree - create_table "spree_log_entries", :force => true do |t| + create_table "spree_log_entries", force: true do |t| t.integer "source_id" t.string "source_type" t.text "details" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end - create_table "spree_option_types", :force => true do |t| - t.string "name", :limit => 100 - t.string "presentation", :limit => 100 - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "position", :default => 0, :null => false + create_table "spree_option_types", force: true do |t| + t.string "name", limit: 100 + t.string "presentation", limit: 100 + t.datetime "created_at" + t.datetime "updated_at" + t.integer "position", default: 0, null: false end - create_table "spree_option_values", :force => true do |t| + create_table "spree_option_values", force: true do |t| t.integer "position" t.string "name" t.string "presentation" t.integer "option_type_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end - create_table "spree_option_values_line_items", :id => false, :force => true do |t| + create_table "spree_option_values_line_items", id: false, force: true do |t| t.integer "line_item_id" t.integer "option_value_id" end - add_index "spree_option_values_line_items", ["line_item_id"], :name => "index_option_values_line_items_on_line_item_id" + add_index "spree_option_values_line_items", ["line_item_id"], name: "index_option_values_line_items_on_line_item_id", using: :btree - create_table "spree_option_values_variants", :id => false, :force => true do |t| + create_table "spree_option_values_variants", id: false, force: true do |t| t.integer "variant_id" t.integer "option_value_id" 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_option_values_variants_on_variant_id" + add_index "spree_option_values_variants", ["variant_id", "option_value_id"], name: "index_option_values_variants_on_variant_id_and_option_value_id", using: :btree + add_index "spree_option_values_variants", ["variant_id"], name: "index_option_values_variants_on_variant_id", using: :btree - create_table "spree_orders", :force => true do |t| - t.string "number", :limit => 15 - t.decimal "item_total", :precision => 10, :scale => 2, :default => 0.0, :null => false - t.decimal "total", :precision => 10, :scale => 2, :default => 0.0, :null => false + create_table "spree_orders", force: true do |t| + t.string "number", limit: 15 + t.decimal "item_total", precision: 10, scale: 2, default: 0.0, null: false + t.decimal "total", precision: 10, scale: 2, default: 0.0, null: false t.string "state" - t.decimal "adjustment_total", :precision => 10, :scale => 2, :default => 0.0, :null => false + t.decimal "adjustment_total", precision: 10, scale: 2, default: 0.0, null: false t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.datetime "completed_at" t.integer "bill_address_id" t.integer "ship_address_id" - t.decimal "payment_total", :precision => 10, :scale => 2, :default => 0.0 + t.decimal "payment_total", precision: 10, scale: 2, default: 0.0 t.string "shipment_state" t.string "payment_state" t.string "email" @@ -565,30 +568,30 @@ ActiveRecord::Schema.define(:version => 20200508101630) do t.integer "created_by_id" end - add_index "spree_orders", ["completed_at", "user_id", "created_by_id", "created_at"], :name => "spree_orders_completed_at_user_id_created_by_id_created_at_idx" - add_index "spree_orders", ["customer_id"], :name => "index_spree_orders_on_customer_id" - add_index "spree_orders", ["distributor_id"], :name => "index_spree_orders_on_distributor_id" - add_index "spree_orders", ["number"], :name => "index_orders_on_number" - add_index "spree_orders", ["order_cycle_id"], :name => "index_spree_orders_on_order_cycle_id" - add_index "spree_orders", ["user_id"], :name => "index_spree_orders_on_user_id" + add_index "spree_orders", ["completed_at", "user_id", "created_by_id", "created_at"], name: "spree_orders_completed_at_user_id_created_by_id_created_at_idx", using: :btree + add_index "spree_orders", ["customer_id"], name: "index_spree_orders_on_customer_id", using: :btree + 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| + create_table "spree_payment_methods", force: true do |t| t.string "type" t.string "name" t.text "description" - t.boolean "active", :default => true - t.string "environment", :default => "development" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.boolean "active", default: true + t.string "environment", default: "development" + t.datetime "created_at" + t.datetime "updated_at" t.datetime "deleted_at" t.string "display_on" end - create_table "spree_payments", :force => true do |t| - t.decimal "amount", :precision => 10, :scale => 2, :default => 0.0, :null => false + create_table "spree_payments", force: true do |t| + t.decimal "amount", precision: 10, scale: 2, default: 0.0, null: false t.integer "order_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "source_id" t.string "source_type" t.integer "payment_method_id" @@ -600,99 +603,99 @@ ActiveRecord::Schema.define(:version => 20200508101630) do t.text "cvv_response_message" end - add_index "spree_payments", ["order_id"], :name => "index_spree_payments_on_order_id" + add_index "spree_payments", ["order_id"], name: "index_spree_payments_on_order_id", using: :btree - create_table "spree_paypal_accounts", :force => true do |t| + create_table "spree_paypal_accounts", force: true do |t| t.string "email" t.string "payer_id" t.string "payer_country" t.string "payer_status" end - create_table "spree_paypal_express_checkouts", :force => true do |t| + create_table "spree_paypal_express_checkouts", force: true do |t| t.string "token" t.string "payer_id" t.string "transaction_id" - t.string "state", :default => "complete" + t.string "state", default: "complete" t.string "refund_transaction_id" t.datetime "refunded_at" t.string "refund_type" t.datetime "created_at" end - add_index "spree_paypal_express_checkouts", ["transaction_id"], :name => "index_spree_paypal_express_checkouts_on_transaction_id" + add_index "spree_paypal_express_checkouts", ["transaction_id"], name: "index_spree_paypal_express_checkouts_on_transaction_id", using: :btree - create_table "spree_pending_promotions", :force => true do |t| + create_table "spree_pending_promotions", force: true do |t| t.integer "user_id" t.integer "promotion_id" end - add_index "spree_pending_promotions", ["promotion_id"], :name => "index_spree_pending_promotions_on_promotion_id" - add_index "spree_pending_promotions", ["user_id"], :name => "index_spree_pending_promotions_on_user_id" + add_index "spree_pending_promotions", ["promotion_id"], name: "index_spree_pending_promotions_on_promotion_id", using: :btree + add_index "spree_pending_promotions", ["user_id"], name: "index_spree_pending_promotions_on_user_id", using: :btree - create_table "spree_preferences", :force => true do |t| + create_table "spree_preferences", force: true do |t| t.text "value" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "key" t.string "value_type" end - add_index "spree_preferences", ["key"], :name => "index_spree_preferences_on_key", :unique => true + add_index "spree_preferences", ["key"], name: "index_spree_preferences_on_key", unique: true, using: :btree - create_table "spree_prices", :force => true do |t| - t.integer "variant_id", :null => false - t.decimal "amount", :precision => 8, :scale => 2 - t.string "currency" + create_table "spree_prices", force: true do |t| + t.integer "variant_id", null: false + t.decimal "amount", precision: 8, scale: 2 + t.string "currency" t.datetime "deleted_at" end - add_index "spree_prices", ["variant_id"], :name => "index_spree_prices_on_variant_id" + add_index "spree_prices", ["variant_id"], name: "index_spree_prices_on_variant_id", using: :btree - create_table "spree_product_groups", :force => true do |t| + create_table "spree_product_groups", force: true do |t| t.string "name" t.string "permalink" t.string "order" end - add_index "spree_product_groups", ["name"], :name => "index_product_groups_on_name" - add_index "spree_product_groups", ["permalink"], :name => "index_product_groups_on_permalink" + add_index "spree_product_groups", ["name"], name: "index_product_groups_on_name", using: :btree + add_index "spree_product_groups", ["permalink"], name: "index_product_groups_on_permalink", using: :btree - create_table "spree_product_groups_products", :id => false, :force => true do |t| + create_table "spree_product_groups_products", id: false, force: true do |t| t.integer "product_id" t.integer "product_group_id" end - create_table "spree_product_option_types", :force => true do |t| + create_table "spree_product_option_types", force: true do |t| t.integer "position" t.integer "product_id" t.integer "option_type_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end - create_table "spree_product_properties", :force => true do |t| + create_table "spree_product_properties", force: true do |t| t.string "value" t.integer "product_id" t.integer "property_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "position", :default => 0 + t.datetime "created_at" + t.datetime "updated_at" + t.integer "position", default: 0 end - add_index "spree_product_properties", ["product_id"], :name => "index_product_properties_on_product_id" + add_index "spree_product_properties", ["product_id"], name: "index_product_properties_on_product_id", using: :btree - create_table "spree_product_scopes", :force => true do |t| + create_table "spree_product_scopes", force: true do |t| t.string "name" t.text "arguments" t.integer "product_group_id" end - add_index "spree_product_scopes", ["name"], :name => "index_product_scopes_on_name" - add_index "spree_product_scopes", ["product_group_id"], :name => "index_product_scopes_on_product_group_id" + add_index "spree_product_scopes", ["name"], name: "index_product_scopes_on_name", using: :btree + add_index "spree_product_scopes", ["product_group_id"], name: "index_product_scopes_on_product_group_id", using: :btree - create_table "spree_products", :force => true do |t| - t.string "name", :default => "", :null => false + create_table "spree_products", force: true do |t| + t.string "name", default: "", null: false t.text "description" t.datetime "available_on" t.datetime "deleted_at" @@ -701,8 +704,8 @@ ActiveRecord::Schema.define(:version => 20200508101630) do t.string "meta_keywords" t.integer "tax_category_id" t.integer "shipping_category_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "supplier_id" t.boolean "group_buy" t.float "group_buy_unit_size" @@ -710,201 +713,202 @@ ActiveRecord::Schema.define(:version => 20200508101630) do t.float "variant_unit_scale" t.string "variant_unit_name" t.text "notes" - t.integer "primary_taxon_id", :null => false - t.boolean "inherits_properties", :default => true, :null => false + t.integer "primary_taxon_id", null: false + t.boolean "inherits_properties", default: true, null: false end - add_index "spree_products", ["available_on"], :name => "index_products_on_available_on" - add_index "spree_products", ["deleted_at"], :name => "index_products_on_deleted_at" - add_index "spree_products", ["name"], :name => "index_products_on_name" - add_index "spree_products", ["permalink"], :name => "index_products_on_permalink" - add_index "spree_products", ["permalink"], :name => "permalink_idx_unique", :unique => true - add_index "spree_products", ["primary_taxon_id"], :name => "index_spree_products_on_primary_taxon_id" - add_index "spree_products", ["supplier_id"], :name => "index_spree_products_on_supplier_id" + add_index "spree_products", ["available_on"], name: "index_products_on_available_on", using: :btree + add_index "spree_products", ["deleted_at"], name: "index_products_on_deleted_at", using: :btree + add_index "spree_products", ["name"], name: "index_products_on_name", using: :btree + 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| + create_table "spree_products_promotion_rules", id: false, force: true do |t| t.integer "product_id" t.integer "promotion_rule_id" 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" + add_index "spree_products_promotion_rules", ["product_id"], name: "index_products_promotion_rules_on_product_id", using: :btree + add_index "spree_products_promotion_rules", ["promotion_rule_id"], name: "index_products_promotion_rules_on_promotion_rule_id", using: :btree - create_table "spree_products_taxons", :force => true do |t| + create_table "spree_products_taxons", force: true do |t| t.integer "product_id" t.integer "taxon_id" end - add_index "spree_products_taxons", ["product_id"], :name => "index_products_taxons_on_product_id" - add_index "spree_products_taxons", ["taxon_id"], :name => "index_products_taxons_on_taxon_id" + add_index "spree_products_taxons", ["product_id"], name: "index_products_taxons_on_product_id", using: :btree + add_index "spree_products_taxons", ["taxon_id"], name: "index_products_taxons_on_taxon_id", using: :btree - create_table "spree_promotion_action_line_items", :force => true do |t| + create_table "spree_promotion_action_line_items", force: true do |t| t.integer "promotion_action_id" t.integer "variant_id" - t.integer "quantity", :default => 1 + t.integer "quantity", default: 1 end - create_table "spree_promotion_actions", :force => true do |t| + create_table "spree_promotion_actions", force: true do |t| t.integer "activator_id" t.integer "position" t.string "type" end - create_table "spree_promotion_rules", :force => true do |t| + create_table "spree_promotion_rules", force: true do |t| t.integer "activator_id" t.integer "user_id" t.integer "product_group_id" t.string "type" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" 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" + add_index "spree_promotion_rules", ["product_group_id"], name: "index_promotion_rules_on_product_group_id", using: :btree + add_index "spree_promotion_rules", ["user_id"], name: "index_promotion_rules_on_user_id", using: :btree - create_table "spree_promotion_rules_users", :id => false, :force => true do |t| + create_table "spree_promotion_rules_users", id: false, force: true do |t| t.integer "user_id" t.integer "promotion_rule_id" 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" + add_index "spree_promotion_rules_users", ["promotion_rule_id"], name: "index_promotion_rules_users_on_promotion_rule_id", using: :btree + add_index "spree_promotion_rules_users", ["user_id"], name: "index_promotion_rules_users_on_user_id", using: :btree - create_table "spree_properties", :force => true do |t| + create_table "spree_properties", force: true do |t| t.string "name" - t.string "presentation", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.string "presentation", null: false + t.datetime "created_at" + t.datetime "updated_at" end - create_table "spree_return_authorizations", :force => true do |t| + create_table "spree_return_authorizations", force: true do |t| t.string "number" t.string "state" - t.decimal "amount", :precision => 10, :scale => 2, :default => 0.0, :null => false + t.decimal "amount", precision: 10, scale: 2, default: 0.0, null: false t.integer "order_id" t.text "reason" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "stock_location_id" end - create_table "spree_roles", :force => true do |t| + create_table "spree_roles", force: true do |t| t.string "name" end - create_table "spree_roles_users", :id => false, :force => true do |t| + create_table "spree_roles_users", id: false, force: true do |t| t.integer "role_id" t.integer "user_id" end - add_index "spree_roles_users", ["role_id"], :name => "index_roles_users_on_role_id" - add_index "spree_roles_users", ["user_id"], :name => "index_roles_users_on_user_id" + add_index "spree_roles_users", ["role_id"], name: "index_roles_users_on_role_id", using: :btree + add_index "spree_roles_users", ["user_id"], name: "index_roles_users_on_user_id", using: :btree - create_table "spree_shipments", :force => true do |t| + create_table "spree_shipments", force: true do |t| t.string "tracking" t.string "number" - t.decimal "cost", :precision => 8, :scale => 2 + t.decimal "cost", precision: 8, scale: 2 t.datetime "shipped_at" t.integer "order_id" t.integer "address_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "state" t.integer "stock_location_id" end - add_index "spree_shipments", ["number"], :name => "index_shipments_on_number" - add_index "spree_shipments", ["order_id"], :name => "index_spree_shipments_on_order_id", :unique => true + add_index "spree_shipments", ["number"], name: "index_shipments_on_number", using: :btree + add_index "spree_shipments", ["order_id"], name: "index_spree_shipments_on_order_id", unique: true, using: :btree - create_table "spree_shipping_categories", :force => true do |t| + create_table "spree_shipping_categories", force: true do |t| t.string "name" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.boolean "temperature_controlled", :default => false, :null => false + t.datetime "created_at" + t.datetime "updated_at" + t.boolean "temperature_controlled", default: false, null: false end - create_table "spree_shipping_method_categories", :force => true do |t| - t.integer "shipping_method_id", :null => false - t.integer "shipping_category_id", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + create_table "spree_shipping_method_categories", force: true do |t| + t.integer "shipping_method_id", null: false + t.integer "shipping_category_id", null: false + t.datetime "created_at" + t.datetime "updated_at" end - add_index "spree_shipping_method_categories", ["shipping_category_id"], :name => "index_spree_shipping_method_categories_on_shipping_category_id" - add_index "spree_shipping_method_categories", ["shipping_method_id"], :name => "index_spree_shipping_method_categories_on_shipping_method_id" + add_index "spree_shipping_method_categories", ["shipping_category_id"], name: "index_spree_shipping_method_categories_on_shipping_category_id", using: :btree + add_index "spree_shipping_method_categories", ["shipping_method_id"], name: "index_spree_shipping_method_categories_on_shipping_method_id", using: :btree - create_table "spree_shipping_methods", :force => true do |t| + create_table "spree_shipping_methods", force: true do |t| t.string "name" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "display_on" t.datetime "deleted_at" - t.boolean "require_ship_address", :default => true + t.boolean "require_ship_address", default: true t.text "description" t.string "tracking_url" end - create_table "spree_shipping_methods_zones", :id => false, :force => true do |t| + create_table "spree_shipping_methods_zones", id: false, force: true do |t| t.integer "shipping_method_id" t.integer "zone_id" end - create_table "spree_shipping_rates", :force => true do |t| + create_table "spree_shipping_rates", force: true do |t| t.integer "shipment_id" t.integer "shipping_method_id" - t.boolean "selected", :default => false - t.decimal "cost", :precision => 8, :scale => 2, :default => 0.0 - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.boolean "selected", default: false + t.decimal "cost", precision: 8, scale: 2, default: 0.0 + t.datetime "created_at" + t.datetime "updated_at" end - add_index "spree_shipping_rates", ["shipment_id", "shipping_method_id"], :name => "spree_shipping_rates_join_index", :unique => true + add_index "spree_shipping_rates", ["shipment_id", "shipping_method_id"], name: "spree_shipping_rates_join_index", unique: true, using: :btree - create_table "spree_skrill_transactions", :force => true do |t| + create_table "spree_skrill_transactions", force: true do |t| t.string "email" t.float "amount" t.string "currency" t.integer "transaction_id" t.integer "customer_id" t.string "payment_type" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end - create_table "spree_state_changes", :force => true do |t| + create_table "spree_state_changes", force: true do |t| t.string "name" t.string "previous_state" t.integer "stateful_id" t.integer "user_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "stateful_type" t.string "next_state" end - create_table "spree_states", :force => true do |t| + create_table "spree_states", force: true do |t| t.string "name" t.string "abbr" t.integer "country_id" end - create_table "spree_stock_items", :force => true do |t| + create_table "spree_stock_items", force: true do |t| t.integer "stock_location_id" t.integer "variant_id" - t.integer "count_on_hand", :default => 0, :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.boolean "backorderable", :default => false + t.integer "count_on_hand", default: 0, null: false + t.datetime "created_at" + t.datetime "updated_at" + t.boolean "backorderable", default: false + t.datetime "deleted_at" end - add_index "spree_stock_items", ["stock_location_id", "variant_id"], :name => "stock_item_by_loc_and_var_id" - add_index "spree_stock_items", ["stock_location_id"], :name => "index_spree_stock_items_on_stock_location_id" - add_index "spree_stock_items", ["variant_id"], :name => "index_spree_stock_items_on_variant_id", :unique => true + add_index "spree_stock_items", ["stock_location_id", "variant_id"], name: "stock_item_by_loc_and_var_id", using: :btree + add_index "spree_stock_items", ["stock_location_id"], name: "index_spree_stock_items_on_stock_location_id", using: :btree + add_index "spree_stock_items", ["variant_id"], name: "index_spree_stock_items_on_variant_id", unique: true, using: :btree - create_table "spree_stock_locations", :force => true do |t| + create_table "spree_stock_locations", force: true do |t| t.string "name" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "address1" t.string "address2" t.string "city" @@ -913,73 +917,73 @@ ActiveRecord::Schema.define(:version => 20200508101630) do t.integer "country_id" t.string "zipcode" t.string "phone" - t.boolean "active", :default => true - t.boolean "backorderable_default", :default => false - t.boolean "propagate_all_variants", :default => true + t.boolean "active", default: true + t.boolean "backorderable_default", default: false + t.boolean "propagate_all_variants", default: true end - create_table "spree_stock_movements", :force => true do |t| + create_table "spree_stock_movements", force: true do |t| t.integer "stock_item_id" - t.integer "quantity", :default => 0 + t.integer "quantity", default: 0 t.string "action" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "originator_id" t.string "originator_type" end - add_index "spree_stock_movements", ["stock_item_id"], :name => "index_spree_stock_movements_on_stock_item_id" + add_index "spree_stock_movements", ["stock_item_id"], name: "index_spree_stock_movements_on_stock_item_id", using: :btree - create_table "spree_stock_transfers", :force => true do |t| + create_table "spree_stock_transfers", force: true do |t| t.string "type" t.string "reference" t.integer "source_location_id" t.integer "destination_location_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.string "number" end - add_index "spree_stock_transfers", ["destination_location_id"], :name => "index_spree_stock_transfers_on_destination_location_id" - add_index "spree_stock_transfers", ["number"], :name => "index_spree_stock_transfers_on_number" - add_index "spree_stock_transfers", ["source_location_id"], :name => "index_spree_stock_transfers_on_source_location_id" + add_index "spree_stock_transfers", ["destination_location_id"], name: "index_spree_stock_transfers_on_destination_location_id", using: :btree + add_index "spree_stock_transfers", ["number"], name: "index_spree_stock_transfers_on_number", using: :btree + add_index "spree_stock_transfers", ["source_location_id"], name: "index_spree_stock_transfers_on_source_location_id", using: :btree - create_table "spree_tax_categories", :force => true do |t| + create_table "spree_tax_categories", force: true do |t| t.string "name" t.string "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.boolean "is_default", :default => false + t.datetime "created_at" + t.datetime "updated_at" + t.boolean "is_default", default: false t.datetime "deleted_at" end - create_table "spree_tax_rates", :force => true do |t| - t.decimal "amount", :precision => 8, :scale => 5 + create_table "spree_tax_rates", force: true do |t| + t.decimal "amount", precision: 8, scale: 5 t.integer "zone_id" t.integer "tax_category_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.boolean "included_in_price", :default => false + t.datetime "created_at" + t.datetime "updated_at" + t.boolean "included_in_price", default: false t.string "name" - t.boolean "show_rate_in_label", :default => true + t.boolean "show_rate_in_label", default: true t.datetime "deleted_at" end - create_table "spree_taxonomies", :force => true do |t| - t.string "name", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "position", :default => 0 + create_table "spree_taxonomies", force: true do |t| + t.string "name", null: false + t.datetime "created_at" + t.datetime "updated_at" + t.integer "position", default: 0 end - create_table "spree_taxons", :force => true do |t| + create_table "spree_taxons", force: true do |t| t.integer "parent_id" - t.integer "position", :default => 0 - t.string "name", :null => false + t.integer "position", default: 0 + t.string "name", null: false t.string "permalink" t.integer "taxonomy_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "lft" t.integer "rgt" t.string "icon_file_name" @@ -992,21 +996,21 @@ ActiveRecord::Schema.define(:version => 20200508101630) do t.string "meta_keywords" 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" + add_index "spree_taxons", ["parent_id"], name: "index_taxons_on_parent_id", using: :btree + add_index "spree_taxons", ["permalink"], name: "index_taxons_on_permalink", using: :btree + add_index "spree_taxons", ["taxonomy_id"], name: "index_taxons_on_taxonomy_id", using: :btree - create_table "spree_tokenized_permissions", :force => true do |t| + create_table "spree_tokenized_permissions", force: true do |t| t.integer "permissable_id" t.string "permissable_type" t.string "token" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end - add_index "spree_tokenized_permissions", ["permissable_id", "permissable_type"], :name => "index_tokenized_name_and_type" + add_index "spree_tokenized_permissions", ["permissable_id", "permissable_type"], name: "index_tokenized_name_and_type", using: :btree - create_table "spree_users", :force => true do |t| + create_table "spree_users", force: true do |t| t.string "encrypted_password" t.string "password_salt" t.string "email" @@ -1014,8 +1018,8 @@ ActiveRecord::Schema.define(:version => 20200508101630) do 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.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" @@ -1024,115 +1028,115 @@ ActiveRecord::Schema.define(:version => 20200508101630) do 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.datetime "created_at" + t.datetime "updated_at" t.string "authentication_token" t.string "unlock_token" t.datetime "locked_at" t.datetime "remember_created_at" - t.string "spree_api_key", :limit => 48 + t.string "spree_api_key", limit: 48 t.datetime "reset_password_sent_at" - t.string "api_key", :limit => 40 - t.integer "enterprise_limit", :default => 5, :null => false - t.string "locale", :limit => 6 + t.string "api_key", limit: 40 + t.integer "enterprise_limit", default: 5, null: false + t.string "locale", limit: 6 t.string "confirmation_token" t.datetime "confirmed_at" t.datetime "confirmation_sent_at" t.string "unconfirmed_email" end - add_index "spree_users", ["confirmation_token"], :name => "index_spree_users_on_confirmation_token", :unique => true - add_index "spree_users", ["email"], :name => "email_idx_unique", :unique => true - add_index "spree_users", ["persistence_token"], :name => "index_users_on_persistence_token" + add_index "spree_users", ["confirmation_token"], name: "index_spree_users_on_confirmation_token", unique: true, using: :btree + add_index "spree_users", ["email"], name: "email_idx_unique", unique: true, using: :btree + add_index "spree_users", ["persistence_token"], name: "index_users_on_persistence_token", using: :btree - create_table "spree_variants", :force => true do |t| - t.string "sku", :default => "", :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 + create_table "spree_variants", force: true do |t| + t.string "sku", default: "", 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.boolean "is_master", default: false t.integer "product_id" - t.decimal "cost_price", :precision => 8, :scale => 2 + t.decimal "cost_price", precision: 8, scale: 2 t.integer "position" t.string "cost_currency" t.float "unit_value" - t.string "unit_description", :default => "" + t.string "unit_description", default: "" t.string "display_name" t.string "display_as" t.datetime "import_date" end - add_index "spree_variants", ["product_id"], :name => "index_variants_on_product_id" - add_index "spree_variants", ["sku"], :name => "index_spree_variants_on_sku" + add_index "spree_variants", ["product_id"], name: "index_variants_on_product_id", using: :btree + add_index "spree_variants", ["sku"], name: "index_spree_variants_on_sku", using: :btree - create_table "spree_zone_members", :force => true do |t| + create_table "spree_zone_members", force: true do |t| t.integer "zoneable_id" t.string "zoneable_type" t.integer "zone_id" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" end - create_table "spree_zones", :force => true do |t| + create_table "spree_zones", force: true do |t| t.string "name" t.string "description" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.boolean "default_tax", :default => false - t.integer "zone_members_count", :default => 0 + t.datetime "created_at" + t.datetime "updated_at" + t.boolean "default_tax", default: false + t.integer "zone_members_count", default: 0 end - create_table "stripe_accounts", :force => true do |t| + create_table "stripe_accounts", force: true do |t| t.string "stripe_user_id" t.string "stripe_publishable_key" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false + t.datetime "created_at" + t.datetime "updated_at" t.integer "enterprise_id" end - add_index "stripe_accounts", ["enterprise_id"], :name => "index_stripe_accounts_on_enterprise_id", :unique => true + add_index "stripe_accounts", ["enterprise_id"], name: "index_stripe_accounts_on_enterprise_id", unique: true, using: :btree - create_table "subscription_line_items", :force => true do |t| - t.integer "subscription_id", :null => false - t.integer "variant_id", :null => false - t.integer "quantity", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.decimal "price_estimate", :precision => 8, :scale => 2 + create_table "subscription_line_items", force: true do |t| + t.integer "subscription_id", null: false + t.integer "variant_id", null: false + t.integer "quantity", null: false + t.datetime "created_at" + t.datetime "updated_at" + t.decimal "price_estimate", precision: 8, scale: 2 end - add_index "subscription_line_items", ["subscription_id"], :name => "index_subscription_line_items_on_subscription_id" - add_index "subscription_line_items", ["variant_id"], :name => "index_subscription_line_items_on_variant_id" + add_index "subscription_line_items", ["subscription_id"], name: "index_subscription_line_items_on_subscription_id", using: :btree + add_index "subscription_line_items", ["variant_id"], name: "index_subscription_line_items_on_variant_id", using: :btree - create_table "subscriptions", :force => true do |t| - t.integer "shop_id", :null => false - t.integer "customer_id", :null => false - t.integer "schedule_id", :null => false - t.integer "payment_method_id", :null => false - t.integer "shipping_method_id", :null => false + create_table "subscriptions", force: true do |t| + t.integer "shop_id", null: false + t.integer "customer_id", null: false + t.integer "schedule_id", null: false + t.integer "payment_method_id", null: false + t.integer "shipping_method_id", null: false t.datetime "begins_at" t.datetime "ends_at" - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.integer "bill_address_id", :null => false - t.integer "ship_address_id", :null => false + t.datetime "created_at" + t.datetime "updated_at" + t.integer "bill_address_id", null: false + t.integer "ship_address_id", null: false t.datetime "canceled_at" t.datetime "paused_at" - t.decimal "shipping_fee_estimate", :precision => 8, :scale => 2 - t.decimal "payment_fee_estimate", :precision => 8, :scale => 2 + t.decimal "shipping_fee_estimate", precision: 8, scale: 2 + t.decimal "payment_fee_estimate", precision: 8, scale: 2 end - add_index "subscriptions", ["bill_address_id"], :name => "index_subscriptions_on_bill_address_id" - add_index "subscriptions", ["customer_id"], :name => "index_subscriptions_on_customer_id" - add_index "subscriptions", ["payment_method_id"], :name => "index_subscriptions_on_payment_method_id" - add_index "subscriptions", ["schedule_id"], :name => "index_subscriptions_on_schedule_id" - add_index "subscriptions", ["ship_address_id"], :name => "index_subscriptions_on_ship_address_id" - add_index "subscriptions", ["shipping_method_id"], :name => "index_subscriptions_on_shipping_method_id" - add_index "subscriptions", ["shop_id"], :name => "index_subscriptions_on_shop_id" + add_index "subscriptions", ["bill_address_id"], name: "index_subscriptions_on_bill_address_id", using: :btree + add_index "subscriptions", ["customer_id"], name: "index_subscriptions_on_customer_id", using: :btree + add_index "subscriptions", ["payment_method_id"], name: "index_subscriptions_on_payment_method_id", using: :btree + add_index "subscriptions", ["schedule_id"], name: "index_subscriptions_on_schedule_id", using: :btree + add_index "subscriptions", ["ship_address_id"], name: "index_subscriptions_on_ship_address_id", using: :btree + add_index "subscriptions", ["shipping_method_id"], name: "index_subscriptions_on_shipping_method_id", using: :btree + add_index "subscriptions", ["shop_id"], name: "index_subscriptions_on_shop_id", using: :btree - create_table "suburbs", :force => true do |t| + create_table "suburbs", force: true do |t| t.string "name" t.string "postcode" t.float "latitude" @@ -1140,39 +1144,39 @@ ActiveRecord::Schema.define(:version => 20200508101630) do t.integer "state_id" end - create_table "tag_rules", :force => true do |t| - t.integer "enterprise_id", :null => false - t.string "type", :null => false - t.datetime "created_at", :null => false - t.datetime "updated_at", :null => false - t.boolean "is_default", :default => false, :null => false - t.integer "priority", :default => 99, :null => false + create_table "tag_rules", force: true do |t| + t.integer "enterprise_id", null: false + t.string "type", null: false + t.datetime "created_at" + t.datetime "updated_at" + t.boolean "is_default", default: false, null: false + t.integer "priority", default: 99, null: false end - create_table "taggings", :force => true do |t| + create_table "taggings", force: true do |t| t.integer "tag_id" t.integer "taggable_id" t.string "taggable_type" t.integer "tagger_id" t.string "tagger_type" - t.string "context", :limit => 128 + t.string "context", limit: 128 t.datetime "created_at" end - add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], :name => "taggings_idx", :unique => true - add_index "taggings", ["taggable_id", "taggable_type", "context"], :name => "index_taggings_on_taggable_id_and_taggable_type_and_context" + add_index "taggings", ["tag_id", "taggable_id", "taggable_type", "context", "tagger_id", "tagger_type"], name: "taggings_idx", unique: true, using: :btree + add_index "taggings", ["taggable_id", "taggable_type", "context"], name: "index_taggings_on_taggable_id_and_taggable_type_and_context", using: :btree - create_table "tags", :force => true do |t| + create_table "tags", force: true do |t| t.string "name" - t.integer "taggings_count", :default => 0 + t.integer "taggings_count", default: 0 end - add_index "tags", ["name"], :name => "index_tags_on_name", :unique => true + add_index "tags", ["name"], name: "index_tags_on_name", unique: true, using: :btree - create_table "variant_overrides", :force => true do |t| - t.integer "variant_id", :null => false - t.integer "hub_id", :null => false - t.decimal "price", :precision => 8, :scale => 2 + create_table "variant_overrides", force: true do |t| + t.integer "variant_id", null: false + t.integer "hub_id", null: false + t.decimal "price", precision: 8, scale: 2 t.integer "count_on_hand" t.integer "default_stock" t.boolean "resettable" @@ -1182,19 +1186,19 @@ ActiveRecord::Schema.define(:version => 20200508101630) do t.datetime "import_date" end - add_index "variant_overrides", ["variant_id", "hub_id"], :name => "index_variant_overrides_on_variant_id_and_hub_id" + add_index "variant_overrides", ["variant_id", "hub_id"], name: "index_variant_overrides_on_variant_id_and_hub_id", using: :btree - create_table "versions", :force => true do |t| - t.string "item_type", :null => false - t.integer "item_id", :null => false - t.string "event", :null => false + create_table "versions", force: true 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" t.text "custom_data" end - add_index "versions", ["item_type", "item_id"], :name => "index_versions_on_item_type_and_item_id" + add_index "versions", ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id", using: :btree add_foreign_key "adjustment_metadata", "enterprises", name: "adjustment_metadata_enterprise_id_fk" add_foreign_key "adjustment_metadata", "spree_adjustments", name: "adjustment_metadata_adjustment_id_fk", column: "adjustment_id", dependent: :delete diff --git a/db/seeds.rb b/db/seeds.rb index e6cac36c2c..9afe88de4b 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -21,13 +21,13 @@ end set_mail_configuration # -- Spree -unless Spree::Country.find_by_iso(ENV['DEFAULT_COUNTRY_CODE']) +unless Spree::Country.find_by(iso: ENV['DEFAULT_COUNTRY_CODE']) puts "[db:seed] Seeding Spree" Spree::Core::Engine.load_seed if defined?(Spree::Core) Spree::Auth::Engine.load_seed if defined?(Spree::Auth) end -country = Spree::Country.find_by_iso(ENV['DEFAULT_COUNTRY_CODE']) +country = Spree::Country.find_by(iso: ENV['DEFAULT_COUNTRY_CODE']) puts "Country is #{country.to_s}" puts "[db:seed] loading states yaml" @@ -40,11 +40,8 @@ puts "[db:seed] Seeding states for " + country.name states.each do |state| puts "State: " + state.to_s - unless Spree::State.find_by_name(state['name']) - Spree::State.create!( - { name: state['name'], abbr: state['abbr'], country: country }, - without_protection: true - ) + unless Spree::State.find_by(name: state['name']) + Spree::State.create!({ name: state['name'], abbr: state['abbr'], country: country }) end end diff --git a/engines/dfc_provider/spec/controllers/dfc_provider/api/products_controller_spec.rb b/engines/dfc_provider/spec/controllers/dfc_provider/api/products_controller_spec.rb index c3f40a16a0..6bbf9a1ab9 100644 --- a/engines/dfc_provider/spec/controllers/dfc_provider/api/products_controller_spec.rb +++ b/engines/dfc_provider/spec/controllers/dfc_provider/api/products_controller_spec.rb @@ -18,7 +18,7 @@ describe DfcProvider::Api::ProductsController, type: :controller do describe('.index') do context 'with authorization token' do before do - request.env['Authorization'] = 'Bearer 123456.abcdef.123456' + request.headers['Authorization'] = 'Bearer 123456.abcdef.123456' end context 'with an authenticated user' do @@ -31,7 +31,7 @@ describe DfcProvider::Api::ProductsController, type: :controller do context 'with an enterprise' do context 'given with an id' do context 'related to the user' do - before { get :index, enterprise_id: 'default' } + before { api_get :index, enterprise_id: 'default' } it 'is successful' do expect(response.status).to eq 200 @@ -47,14 +47,14 @@ describe DfcProvider::Api::ProductsController, type: :controller do let(:enterprise) { create(:enterprise) } it 'returns not_found head' do - get :index, enterprise_id: enterprise.id + api_get :index, enterprise_id: enterprise.id expect(response.status).to eq 404 end end end context 'as default' do - before { get :index, enterprise_id: 'default' } + before { api_get :index, enterprise_id: 'default' } it 'is successful' do expect(response.status).to eq 200 @@ -71,7 +71,7 @@ describe DfcProvider::Api::ProductsController, type: :controller do let(:enterprise) { create(:enterprise) } it 'returns not_found head' do - get :index, enterprise_id: 'default' + api_get :index, enterprise_id: 'default' expect(response.status).to eq 404 end end @@ -83,7 +83,7 @@ describe DfcProvider::Api::ProductsController, type: :controller do .to receive(:process) .and_return(nil) - get :index, enterprise_id: 'default' + api_get :index, enterprise_id: 'default' expect(response.status).to eq 401 end end @@ -91,7 +91,7 @@ describe DfcProvider::Api::ProductsController, type: :controller do context 'without an authorization token' do it 'returns unprocessable_entity head' do - get :index, enterprise_id: enterprise.id + api_get :index, enterprise_id: enterprise.id expect(response.status).to eq 422 end end diff --git a/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/data_representations/coordinator_fee.rb b/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/data_representations/coordinator_fee.rb index 8eb14c44cf..0fda10c2f4 100644 --- a/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/data_representations/coordinator_fee.rb +++ b/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/data_representations/coordinator_fee.rb @@ -19,7 +19,7 @@ module OrderManagement end def inherits_tax_category? - data["enterprise_fee_inherits_tax_category"] == "t" + data["enterprise_fee_inherits_tax_category"] end end end diff --git a/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/permissions.rb b/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/permissions.rb index 2077931627..95ce055f24 100644 --- a/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/permissions.rb +++ b/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/permissions.rb @@ -3,7 +3,7 @@ module OrderManagement module EnterpriseFeeSummary class Permissions < ::Reports::Permissions def allowed_order_cycles - @allowed_order_cycles ||= OrderCycle.accessible_by(user) + @allowed_order_cycles ||= OrderCycle.visible_by(user) end def allowed_distributors diff --git a/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/scope.rb b/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/scope.rb index 96fba8b7a4..d88b5dc2ea 100644 --- a/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/scope.rb +++ b/engines/order_management/app/services/order_management/reports/enterprise_fee_summary/scope.rb @@ -364,7 +364,7 @@ module OrderManagement chain_to_scope do select( <<-JOIN_STRING.strip_heredoc - SUM(spree_adjustments.amount) AS total_amount, + SUM(spree_adjustments.amount)::TEXT AS total_amount, spree_payment_methods.name AS payment_method_name, spree_shipping_methods.name AS shipping_method_name, hubs.name AS hub_name, diff --git a/engines/order_management/app/services/order_management/subscriptions/form.rb b/engines/order_management/app/services/order_management/subscriptions/form.rb index 02994e3b50..2e354835be 100644 --- a/engines/order_management/app/services/order_management/subscriptions/form.rb +++ b/engines/order_management/app/services/order_management/subscriptions/form.rb @@ -5,22 +5,22 @@ require 'order_management/subscriptions/proxy_order_syncer' module OrderManagement module Subscriptions class Form - attr_accessor :subscription, :params, :order_update_issues, + 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, params = {}) + def initialize(subscription, subscription_params = {}) @subscription = subscription - @params = params + @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(params) + subscription.assign_attributes(subscription_params) return false unless valid? subscription.transaction do 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 index b53085f1c1..4f45e7421f 100644 --- 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 @@ -65,7 +65,7 @@ module OrderManagement end def remove_orphaned_proxy_orders! - orphaned_proxy_orders.scoped.delete_all + orphaned_proxy_orders.where(nil).delete_all end # Remove Proxy Orders that have not been placed yet diff --git a/engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/parameters_spec.rb b/engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/parameters_spec.rb index 6fd3c8b9a7..130401cb34 100644 --- a/engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/parameters_spec.rb +++ b/engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/parameters_spec.rb @@ -39,7 +39,7 @@ describe OrderManagement::Reports::EnterpriseFeeSummary::Parameters do end describe "requiring start_at to be before end_at" do - let(:now) { Time.zone.now } + let(:now) { Time.zone.now.utc } it "adds error when start_at is after end_at" do allow(subject).to receive(:start_at) { now.to_s } 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 index 14b5a8c041..75b4e47111 100644 --- a/engines/order_management/spec/services/order_management/subscriptions/count_spec.rb +++ b/engines/order_management/spec/services/order_management/subscriptions/count_spec.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require 'spec_helper' + module OrderManagement module Subscriptions describe Count do 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 index e8fe7bf957..63032465d6 100644 --- a/engines/order_management/spec/services/order_management/subscriptions/estimator_spec.rb +++ b/engines/order_management/spec/services/order_management/subscriptions/estimator_spec.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require 'spec_helper' + module OrderManagement module Subscriptions describe Estimator do 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 index 3e849d5c82..a86dbac0e9 100644 --- a/engines/order_management/spec/services/order_management/subscriptions/form_spec.rb +++ b/engines/order_management/spec/services/order_management/subscriptions/form_spec.rb @@ -105,15 +105,15 @@ module OrderManagement 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) + 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) + 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.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 @@ -124,12 +124,12 @@ module OrderManagement # 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) + 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(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 @@ -139,7 +139,7 @@ module OrderManagement 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) + proxy_order4 = subscription.proxy_orders.find_by(order_cycle_id: order_cycle4.id) expect(proxy_order4).to be nil 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 index 501f6fa67e..8af99f27f5 100644 --- 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 @@ -1,5 +1,7 @@ # frozen_string_literal: true +require 'spec_helper' + module OrderManagement module Subscriptions describe ProxyOrderSyncer do @@ -16,59 +18,57 @@ module OrderManagement 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(:schedule) { create(:schedule, order_cycles: [oc]) } + + let(:closed_oc) { + create(:simple_order_cycle, 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) + create(:simple_order_cycle, + 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) + create(:simple_order_cycle, + 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) + create(:simple_order_cycle, + 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) + create(:simple_order_cycle, + 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) + create(:simple_order_cycle, + 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) + create(:simple_order_cycle, + 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) + build(:subscription, 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) + let(:schedule) { create(:schedule, order_cycles: [oc]) } + let(:subscription) do + build( + :subscription, + begins_at: now + 1.minute, + ends_at: now + 2.minutes, + schedule: schedule + ) end context "and the schedule includes a closed oc (ie. closed before opens_at)" do - let(:oc) { closed_oc } + 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 @@ -76,7 +76,8 @@ module OrderManagement end context "and the schedule includes an open oc that closes before begins_at" do - let(:oc) { open_oc_closes_before_begins_at_oc } + 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 @@ -84,15 +85,19 @@ module OrderManagement end context "and the schedule has an open OC that closes between begins_at and ends_at" do - let(:oc) { open_oc } + let!(:oc) { open_oc } + it "creates a new proxy order for that oc" do + syncer.sync! + expect{ subscription.save! }.to change(ProxyOrder, :count).from(0).to(1) - expect(order_cycles).to include oc + expect(subscription.reload.proxy_orders.map(&:order_cycle)).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 } + 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 @@ -100,23 +105,30 @@ module OrderManagement end context "and the schedule includes upcoming oc that closes on begins_at" do - let(:oc) { upcoming_closes_on_begins_at_oc } + let!(:oc) { upcoming_closes_on_begins_at_oc } + it "creates a new proxy order for that oc" do + syncer.sync! + expect{ subscription.save! }.to change(ProxyOrder, :count).from(0).to(1) - expect(order_cycles).to include oc + expect(subscription.reload.proxy_orders.map(&:order_cycle)).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 } + let!(:oc) { upcoming_closes_on_ends_at_oc } + it "creates a new proxy order for that oc" do + syncer.sync! + expect{ subscription.save! }.to change(ProxyOrder, :count).from(0).to(1) - expect(order_cycles).to include oc + expect(subscription.reload.proxy_orders.map(&:order_cycle)).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 } + 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 @@ -194,6 +206,7 @@ module OrderManagement 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 @@ -202,46 +215,65 @@ module OrderManagement 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 + context 'and the proxy orders are already synced' do + let(:subscription) do + build( + :subscription, + begins_at: now + 1.minute, + ends_at: now + 2.minutes, + schedule: schedule + ) + end + + before { syncer.sync! } + + 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 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 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 @@ -374,8 +406,20 @@ module OrderManagement end context "when a proxy order does not exist" do + let(:schedule) { create(:schedule, order_cycles: [oc]) } + let(:subscription) do + create( + :subscription, + begins_at: now + 1.minute, + ends_at: now + 2.minutes, + schedule: schedule + ) + end + let(:syncer) { ProxyOrderSyncer.new(subscription) } + 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 @@ -384,6 +428,7 @@ module OrderManagement 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 @@ -392,14 +437,16 @@ module OrderManagement 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 + expect(subscription.reload.proxy_orders.map(&:order_cycle)).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 @@ -408,22 +455,25 @@ module OrderManagement 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 + expect(subscription.reload.proxy_orders.map(&:order_cycle)).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 + expect(subscription.reload.proxy_orders.map(&:order_cycle)).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 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 index 5e6360c542..454e2e5ba3 100644 --- a/engines/order_management/spec/services/order_management/subscriptions/summary_spec.rb +++ b/engines/order_management/spec/services/order_management/subscriptions/summary_spec.rb @@ -1,5 +1,7 @@ # frozen_string_literal: true +require 'spec_helper' + module OrderManagement module Subscriptions describe Summary do diff --git a/engines/web/app/assets/stylesheets/web/pages/cookies_policy_modal.css.scss b/engines/web/app/assets/stylesheets/web/pages/cookies_policy_modal.css.scss index 4c3706d8d7..583c10525a 100644 --- a/engines/web/app/assets/stylesheets/web/pages/cookies_policy_modal.css.scss +++ b/engines/web/app/assets/stylesheets/web/pages/cookies_policy_modal.css.scss @@ -4,6 +4,10 @@ background: $cookies-policy-modal-background-color; border-bottom-color: $cookies-policy-modal-border-bottom-color; + @media only screen and (max-width: 640px) { + padding: .9rem; + } + table { width: 100%; diff --git a/lib/open_food_network/order_cycle_form_applicator.rb b/lib/open_food_network/order_cycle_form_applicator.rb index 1abf16f89c..f42fd427a9 100644 --- a/lib/open_food_network/order_cycle_form_applicator.rb +++ b/lib/open_food_network/order_cycle_form_applicator.rb @@ -141,7 +141,8 @@ module OpenFoodNetwork end def find_exchange(sender_id, receiver_id, incoming) - @order_cycle.exchanges.find_by_sender_id_and_receiver_id_and_incoming(sender_id, receiver_id, incoming) + @order_cycle.exchanges. + find_by(sender_id: sender_id, receiver_id: receiver_id, incoming: incoming) end def incoming_exchange_variant_ids(attrs) diff --git a/lib/open_food_network/order_cycle_management_report.rb b/lib/open_food_network/order_cycle_management_report.rb index 49fb2e7365..e1f35eed6a 100644 --- a/lib/open_food_network/order_cycle_management_report.rb +++ b/lib/open_food_network/order_cycle_management_report.rb @@ -69,15 +69,15 @@ module OpenFoodNetwork def payment_method_row(order) ba = order.billing_address - [ba.firstname, - ba.lastname, + [ba.andand.firstname, + ba.andand.lastname, order.distributor.andand.name, customer_code(order.email), order.email, - ba.phone, + ba.andand.phone, order.shipping_method.andand.name, order.payments.first.andand.payment_method.andand.name, - order.payments.first.amount, + order.payments.first.andand.amount, OpenFoodNetwork::UserBalanceCalculator.new(order.email, order.distributor).balance] end @@ -92,7 +92,7 @@ module OpenFoodNetwork sa.phone, order.shipping_method.andand.name, order.payments.first.andand.payment_method.andand.name, - order.payments.first.amount, + order.payments.first.andand.amount, OpenFoodNetwork::UserBalanceCalculator.new(order.email, order.distributor).balance, has_temperature_controlled_items?(order), order.special_instructions] diff --git a/lib/open_food_network/order_cycle_permissions.rb b/lib/open_food_network/order_cycle_permissions.rb index e1d1301e36..0e30993117 100644 --- a/lib/open_food_network/order_cycle_permissions.rb +++ b/lib/open_food_network/order_cycle_permissions.rb @@ -160,7 +160,7 @@ module OpenFoodNetwork end.map(&:id) Spree::Variant.includes(product: :supplier). - select("spree_variants.id, spree_products.supplier_id"). + select("spree_variants.id, spree_variants.product_id, spree_products.supplier_id"). joins(:product).where(spree_products: { supplier_id: valid_suppliers }) end diff --git a/lib/open_food_network/orders_and_fulfillments_report.rb b/lib/open_food_network/orders_and_fulfillments_report.rb index ae359aba19..f386be439a 100644 --- a/lib/open_food_network/orders_and_fulfillments_report.rb +++ b/lib/open_food_network/orders_and_fulfillments_report.rb @@ -46,6 +46,17 @@ module OpenFoodNetwork proc { |line_items| line_items.first.variant.product.name } end + def total_units(line_items) + return " " if not_all_have_unit?(line_items) + + total_units = line_items.sum do |li| + product = li.variant.product + li.quantity * li.unit_value / scale_factor(product) + end + + total_units.round(3) + end + def variant_scoper_for(distributor_id) @variant_scopers_by_distributor_id[distributor_id] ||= OpenFoodNetwork::ScopeVariantToHub.new( @@ -71,17 +82,6 @@ module OpenFoodNetwork end end - def total_units(line_items) - return " " if not_all_have_unit?(line_items) - - total_units = line_items.sum do |li| - product = li.variant.product - li.quantity * li.unit_value / scale_factor(product) - end - - total_units.round(3) - end - def not_all_have_unit?(line_items) line_items.map { |li| li.unit_value.nil? }.any? end diff --git a/lib/open_food_network/payments_report.rb b/lib/open_food_network/payments_report.rb index f9f536171f..3c2fbbd24b 100644 --- a/lib/open_food_network/payments_report.rb +++ b/lib/open_food_network/payments_report.rb @@ -41,7 +41,10 @@ module OpenFoodNetwork return [] unless @render_table orders = search.result - payments = orders.map { |o| o.payments.select(&:completed?) }.flatten # Only select completed payments + payments = orders.includes(:payments).map do |order| + order.payments.select(&:completed?) + end.flatten + case params[:report_type] when "payments_by_payment_type" payments diff --git a/lib/open_food_network/permalink_generator.rb b/lib/open_food_network/permalink_generator.rb index 3c5babc750..c86e6972de 100644 --- a/lib/open_food_network/permalink_generator.rb +++ b/lib/open_food_network/permalink_generator.rb @@ -40,7 +40,7 @@ module PermalinkGenerator if self.class.respond_to?(:with_deleted) self.class.with_deleted else - self.class.scoped + self.class.where(nil) end end end diff --git a/lib/open_food_network/permissions.rb b/lib/open_food_network/permissions.rb index fe132a9be2..8f55de56fe 100644 --- a/lib/open_food_network/permissions.rb +++ b/lib/open_food_network/permissions.rb @@ -147,7 +147,7 @@ module OpenFoodNetwork def managed_and_related_enterprises_granting(permission) if admin? - Enterprise.scoped + Enterprise.where(nil) else Enterprise.where( id: managed_enterprises.select("enterprises.id") | @@ -158,7 +158,7 @@ module OpenFoodNetwork def managed_and_related_enterprises_with(permission) if admin? - Enterprise.scoped + Enterprise.where(nil) else managed_enterprise_ids = managed_enterprises.select("enterprises.id") granting_enterprise_ids = related_enterprises_granting(permission) diff --git a/lib/open_food_network/reports/line_items.rb b/lib/open_food_network/reports/line_items.rb index ce3bc9e97e..93c5fba9de 100644 --- a/lib/open_food_network/reports/line_items.rb +++ b/lib/open_food_network/reports/line_items.rb @@ -19,7 +19,7 @@ module OpenFoodNetwork end if line_item_includes.present? - line_items = line_items.includes(*line_item_includes) + line_items = line_items.includes(*line_item_includes).references(:line_items) end editable_line_items = editable_line_items(line_items) diff --git a/lib/open_food_network/sales_tax_report.rb b/lib/open_food_network/sales_tax_report.rb index 874561c339..458b4523af 100644 --- a/lib/open_food_network/sales_tax_report.rb +++ b/lib/open_food_network/sales_tax_report.rb @@ -49,8 +49,9 @@ module OpenFoodNetwork when "tax_rates" orders.map do |order| [order.number, order.total - order.total_tax] + - relevant_rates.map { |rate| order.tax_adjustment_totals.fetch(rate, 0) } + - [order.total_tax, order.total] + relevant_rates.map { |rate| + OrderTaxAdjustmentsFetcher.new(order).totals.fetch(rate, 0) + } + [order.total_tax, order.total] end else orders.map do |order| @@ -95,7 +96,7 @@ module OpenFoodNetwork end def shipping_cost_for(order) - shipping_cost = order.adjustments.find_by_label("Shipping").andand.amount + shipping_cost = order.adjustments.find_by(label: "Shipping").andand.amount shipping_cost.nil? ? 0.0 : shipping_cost end diff --git a/lib/open_food_network/variant_and_line_item_naming.rb b/lib/open_food_network/variant_and_line_item_naming.rb index 596b93beee..7eed59b892 100644 --- a/lib/open_food_network/variant_and_line_item_naming.rb +++ b/lib/open_food_network/variant_and_line_item_naming.rb @@ -59,7 +59,8 @@ module OpenFoodNetwork option_type = product.variant_unit_option_type if option_type name = option_value_name - ov = Spree::OptionValue.where(option_type_id: option_type, name: name, presentation: name).first || Spree::OptionValue.create!({ option_type: option_type, name: name, presentation: name }, without_protection: true) + ov = Spree::OptionValue.where(option_type_id: option_type, name: name, presentation: name).first || + Spree::OptionValue.create!(option_type: option_type, name: name, presentation: name) option_values << ov end end diff --git a/lib/stripe/account_connector.rb b/lib/stripe/account_connector.rb index 0213479bcb..cb96c0e1d8 100644 --- a/lib/stripe/account_connector.rb +++ b/lib/stripe/account_connector.rb @@ -32,7 +32,7 @@ module Stripe end def enterprise - @enterprise ||= Enterprise.find_by_permalink(state["enterprise_id"]) + @enterprise ||= Enterprise.find_by(permalink: state["enterprise_id"]) end private diff --git a/lib/tasks/sample_data.rake b/lib/tasks/sample_data.rake index bf929281b6..1dcac757c9 100644 --- a/lib/tasks/sample_data.rake +++ b/lib/tasks/sample_data.rake @@ -10,6 +10,7 @@ require "tasks/sample_data/product_factory" require "tasks/sample_data/shipping_method_factory" require "tasks/sample_data/taxon_factory" require "tasks/sample_data/user_factory" +require "tasks/sample_data/order_factory" # The sample data generated by this task is supposed to save some time during # manual testing. It is not meant to be complete, but we try to improve it @@ -49,6 +50,8 @@ namespace :ofn do CustomerFactory.new.create_samples(users) GroupFactory.new.create_samples + + OrderFactory.new.create_samples end def seeded? diff --git a/lib/tasks/sample_data/addressing.rb b/lib/tasks/sample_data/addressing.rb index bc1471e276..c7f651837f 100644 --- a/lib/tasks/sample_data/addressing.rb +++ b/lib/tasks/sample_data/addressing.rb @@ -14,12 +14,12 @@ module Addressing end def zone - zone = Spree::Zone.find_or_create_by_name!(ENV.fetch('CHECKOUT_ZONE')) + zone = Spree::Zone.find_or_create_by!(name: ENV.fetch('CHECKOUT_ZONE')) zone.members.create!(zoneable: country) unless zone.zoneables.include?(country) zone end def country - Spree::Country.find_by_iso(ENV.fetch('DEFAULT_COUNTRY_CODE')) + Spree::Country.find_by(iso: ENV.fetch('DEFAULT_COUNTRY_CODE')) end end diff --git a/lib/tasks/sample_data/customer_factory.rb b/lib/tasks/sample_data/customer_factory.rb index 9a49289e37..c574f3150b 100644 --- a/lib/tasks/sample_data/customer_factory.rb +++ b/lib/tasks/sample_data/customer_factory.rb @@ -6,7 +6,7 @@ class CustomerFactory def create_samples(users) log "Creating customers" jane = users["Jane Customer"] - maryse_shop = Enterprise.find_by_name("Maryse's Private Shop") + maryse_shop = Enterprise.find_by(name: "Maryse's Private Shop") return if Customer.where(user_id: jane, enterprise_id: maryse_shop).exists? log "- #{jane.email}" diff --git a/lib/tasks/sample_data/enterprise_factory.rb b/lib/tasks/sample_data/enterprise_factory.rb index cf5d62db22..296d05cef8 100644 --- a/lib/tasks/sample_data/enterprise_factory.rb +++ b/lib/tasks/sample_data/enterprise_factory.rb @@ -11,7 +11,7 @@ class EnterpriseFactory name = data[:name] log "- #{name}" data[:long_description] = data[:long_description].strip_heredoc.tr("\n", " ") - Enterprise.create_with(data).find_or_create_by_name!(name) + Enterprise.create_with(data).find_or_create_by!(name: name) end end diff --git a/lib/tasks/sample_data/inventory_factory.rb b/lib/tasks/sample_data/inventory_factory.rb index b4147e024d..46a0ce5277 100644 --- a/lib/tasks/sample_data/inventory_factory.rb +++ b/lib/tasks/sample_data/inventory_factory.rb @@ -5,7 +5,7 @@ class InventoryFactory def create_samples(products) log "Creating inventories" - marys_shop = Enterprise.find_by_name("Mary's Online Shop") + marys_shop = Enterprise.find_by(name: "Mary's Online Shop") products.each do |product| create_item(marys_shop, product) end @@ -18,7 +18,7 @@ class InventoryFactory enterprise: shop, variant: product.variants.first, visible: true - ).find_or_create_by_variant_id!(product.variants.first.id) + ).find_or_create_by!(variant_id: product.variants.first.id) create_override(shop, product) end @@ -29,6 +29,6 @@ class InventoryFactory price: 12, on_demand: false, count_on_hand: 5 - ).find_or_create_by_variant_id!(product.variants.first.id) + ).find_or_create_by!(variant_id: product.variants.first.id) end end diff --git a/lib/tasks/sample_data/order_cycle_factory.rb b/lib/tasks/sample_data/order_cycle_factory.rb index 6ba5b8e5ef..7e441ad26f 100644 --- a/lib/tasks/sample_data/order_cycle_factory.rb +++ b/lib/tasks/sample_data/order_cycle_factory.rb @@ -48,7 +48,7 @@ class OrderCycleFactory private def create_order_cycle(name, coordinator_name, supplier_names, distributor_names, data) - coordinator = Enterprise.find_by_name(coordinator_name) + coordinator = Enterprise.find_by(name: coordinator_name) return if OrderCycle.active.where(name: name).exists? log "- #{name}" diff --git a/lib/tasks/sample_data/order_factory.rb b/lib/tasks/sample_data/order_factory.rb new file mode 100644 index 0000000000..bc5c9f3675 --- /dev/null +++ b/lib/tasks/sample_data/order_factory.rb @@ -0,0 +1,86 @@ +# frozen_string_literal: true + +require "tasks/sample_data/logging" +require "tasks/sample_data/addressing" + +class OrderFactory + include Logging + include Addressing + + def create_samples + log "Creating orders" + @order_cycle = OrderCycle.find_by(name: "Fredo's Farm Hub OC") + @distributor = Enterprise.find_by(name: "Fredo's Farm Hub") + @email = "new.customer@example.org" + + log "- cart order" + create_cart_order + + log "- complete order - not paid" + create_complete_order + + log "- complete order - paid" + order = create_complete_order + order.payments.first.capture! + + log "- complete order - delivery" + order = create_complete_order + order.select_shipping_method(delivery_shipping_method_id) + order.save + + log "- complete order - shipped" + order = create_complete_order + order.payments.first.capture! + order.save + order.shipment.reload.ship! + end + + private + + def create_cart_order + order = create_order + order.save + order + end + + def create_complete_order + order = create_cart_order + AdvanceOrderService.new(order).call + order + end + + def create_order + order = Spree::Order.create!( + email: @email, + order_cycle: @order_cycle, + distributor: @distributor, + bill_address: order_address, + ship_address: order_address + ) + order.line_items.create( variant_id: first_variant.id, quantity: 5 ) + order.payments.create(payment_method_id: first_payment_method_id) + order + end + + def first_variant + # First variant on the first outgoing exchange of the OC + @order_cycle.exchanges.outgoing.first.variants.first + end + + def first_payment_method_id + # First payment method of the distributor + @distributor.payment_methods.first.id + end + + def delivery_shipping_method_id + @distributor.shipping_methods.find_by(name: "Home delivery").id + end + + def order_address + address = address("25 Myrtle Street, Bayswater, 3153") + address.firstname = "John" + address.lastname = "Mistery" + address.phone = "0987654321" + address + end +end diff --git a/lib/tasks/sample_data/product_factory.rb b/lib/tasks/sample_data/product_factory.rb index 9d5411bef5..962a7b1891 100644 --- a/lib/tasks/sample_data/product_factory.rb +++ b/lib/tasks/sample_data/product_factory.rb @@ -13,9 +13,9 @@ class ProductFactory private def product_data(enterprises) - vegetables = Spree::Taxon.find_by_name('Vegetables') - fruit = Spree::Taxon.find_by_name('Fruit') - meat = Spree::Taxon.find_by_name('Meat and Fish') + vegetables = Spree::Taxon.find_by(name: 'Vegetables') + fruit = Spree::Taxon.find_by(name: 'Fruit') + meat = Spree::Taxon.find_by(name: 'Meat and Fish') producers = enterprises.select(&:is_primary_producer) distributors = enterprises.select(&:is_distributor) [ @@ -75,14 +75,14 @@ class ProductFactory shipping_category: DefaultShippingCategory.find_or_create, tax_category_id: find_or_create_tax_category.id ) - product = Spree::Product.create_with(params).find_or_create_by_name!(params[:name]) + product = Spree::Product.create_with(params).find_or_create_by!(name: params[:name]) product.variants.first.update_attribute :on_demand, true product end def find_or_create_tax_category tax_category_name = "Tax Category" - tax_category = Spree::TaxCategory.find_by_name(tax_category_name) + tax_category = Spree::TaxCategory.find_by(name: tax_category_name) tax_category ||= Spree::TaxCategory.create!(name: tax_category_name) tax_category end diff --git a/lib/tasks/sample_data/shipping_method_factory.rb b/lib/tasks/sample_data/shipping_method_factory.rb index 7772729a0e..5bfb382318 100644 --- a/lib/tasks/sample_data/shipping_method_factory.rb +++ b/lib/tasks/sample_data/shipping_method_factory.rb @@ -49,7 +49,7 @@ class ShippingMethodFactory params[:distributor_ids] = [enterprise.id] method = enterprise.shipping_methods.new(params) method.zones << zone - method.shipping_categories << Spree::ShippingCategory.find_or_create_by_name('Default') + method.shipping_categories << Spree::ShippingCategory.find_or_create_by(name: 'Default') method.save! method end diff --git a/lib/tasks/sample_data/taxon_factory.rb b/lib/tasks/sample_data/taxon_factory.rb index f6d4bf3945..4c9878af81 100644 --- a/lib/tasks/sample_data/taxon_factory.rb +++ b/lib/tasks/sample_data/taxon_factory.rb @@ -5,7 +5,7 @@ class TaxonFactory def create_samples log "Creating taxonomies:" - taxonomy = Spree::Taxonomy.find_or_create_by_name!('Products') + taxonomy = Spree::Taxonomy.find_or_create_by!(name: 'Products') taxons = ['Vegetables', 'Fruit', 'Oils', 'Preserves and Sauces', 'Dairy', 'Meat and Fish'] taxons.each do |taxon_name| create_taxon(taxonomy, taxon_name) diff --git a/lib/tasks/sample_data/user_factory.rb b/lib/tasks/sample_data/user_factory.rb index 36aae48b37..9b54e26a41 100644 --- a/lib/tasks/sample_data/user_factory.rb +++ b/lib/tasks/sample_data/user_factory.rb @@ -34,7 +34,7 @@ class UserFactory password_confirmation: password, confirmation_sent_at: Time.zone.now, confirmed_at: Time.zone.now - ).find_or_create_by_email!(email) + ).find_or_create_by!(email: email) [name, user] end end diff --git a/spec/controllers/admin/enterprises_controller_spec.rb b/spec/controllers/admin/enterprises_controller_spec.rb index 52f111f17a..a95334d292 100644 --- a/spec/controllers/admin/enterprises_controller_spec.rb +++ b/spec/controllers/admin/enterprises_controller_spec.rb @@ -18,8 +18,8 @@ module Admin before { @request.env['HTTP_REFERER'] = 'http://test.com/' } describe "creating an enterprise" do - let(:country) { Spree::Country.find_by_name 'Australia' } - let(:state) { Spree::State.find_by_name 'Victoria' } + let(:country) { Spree::Country.find_by name: 'Australia' } + let(:state) { Spree::State.find_by name: 'Victoria' } let(:enterprise_params) { { enterprise: { name: 'zzz', permalink: 'zzz', is_primary_producer: '0', address_attributes: { address1: 'a', city: 'a', zipcode: 'a', country_id: country.id, state_id: state.id } } } } it "grants management permission if the current user is an enterprise user" do @@ -27,7 +27,7 @@ module Admin enterprise_params[:enterprise][:owner_id] = distributor_manager spree_put :create, enterprise_params - enterprise = Enterprise.find_by_name 'zzz' + enterprise = Enterprise.find_by name: 'zzz' expect(response).to redirect_to edit_admin_enterprise_path enterprise expect(distributor_manager.enterprise_roles.where(enterprise_id: enterprise).first).to be end @@ -37,7 +37,7 @@ module Admin enterprise_params[:enterprise][:owner_id] = user spree_put :create, enterprise_params - enterprise = Enterprise.find_by_name 'zzz' + enterprise = Enterprise.find_by name: 'zzz' expect(response).to redirect_to edit_admin_enterprise_path enterprise expect(distributor_manager.enterprise_roles.where(enterprise_id: enterprise).first).to be end @@ -50,7 +50,7 @@ module Admin enterprise_params[:enterprise][:owner_id] = distributor_owner spree_put :create, enterprise_params - enterprise = Enterprise.find_by_name 'zzz' + enterprise = Enterprise.find_by name: 'zzz' expect(response).to redirect_to edit_admin_enterprise_path enterprise expect(enterprise.sells).to eq('any') end @@ -61,7 +61,7 @@ module Admin enterprise_params[:enterprise][:is_primary_producer] = '1' spree_put :create, enterprise_params - enterprise = Enterprise.find_by_name 'zzz' + enterprise = Enterprise.find_by name: 'zzz' expect(response).to redirect_to edit_admin_enterprise_path enterprise expect(enterprise.sells).to eq('none') end @@ -74,7 +74,7 @@ module Admin enterprise_params[:enterprise][:sells] = 'none' spree_put :create, enterprise_params - enterprise = Enterprise.find_by_name 'zzz' + enterprise = Enterprise.find_by name: 'zzz' expect(response).to redirect_to edit_admin_enterprise_path enterprise expect(enterprise.sells).to eq('none') end @@ -86,7 +86,7 @@ module Admin enterprise_params[:enterprise][:owner_id] = supplier_manager spree_put :create, enterprise_params - enterprise = Enterprise.find_by_name 'zzz' + enterprise = Enterprise.find_by name: 'zzz' expect(enterprise.sells).to eq('none') end @@ -96,7 +96,7 @@ module Admin enterprise_params[:enterprise][:sells] = 'any' spree_put :create, enterprise_params - enterprise = Enterprise.find_by_name 'zzz' + enterprise = Enterprise.find_by name: 'zzz' expect(enterprise.sells).to eq('any') end end @@ -449,8 +449,8 @@ module Admin before do # As a user with permission allow(controller).to receive_messages spree_current_user: user - allow(OrderCycle).to receive_messages find_by_id: "existing OrderCycle" - allow(Enterprise).to receive_messages find_by_id: "existing Enterprise" + allow(OrderCycle).to receive_messages find_by: "existing OrderCycle" + allow(Enterprise).to receive_messages find_by: "existing Enterprise" allow(OrderCycle).to receive_messages new: "new OrderCycle" allow(OpenFoodNetwork::OrderCyclePermissions).to receive(:new) { permission_mock } diff --git a/spec/controllers/admin/manager_invitations_controller_spec.rb b/spec/controllers/admin/manager_invitations_controller_spec.rb index 7d03361daa..d245f6cf4d 100644 --- a/spec/controllers/admin/manager_invitations_controller_spec.rb +++ b/spec/controllers/admin/manager_invitations_controller_spec.rb @@ -45,7 +45,7 @@ module Admin it "returns the user id" do spree_post :create, email: 'un.registered@email.com', enterprise_id: enterprise.id - new_user = Spree::User.find_by_email('un.registered@email.com') + new_user = Spree::User.find_by(email: 'un.registered@email.com') expect(json_response['user']).to eq new_user.id end end @@ -61,7 +61,7 @@ module Admin it "returns success code" do spree_post :create, email: 'an@email.com', enterprise_id: enterprise.id - new_user = Spree::User.find_by_email('an@email.com') + new_user = Spree::User.find_by(email: 'an@email.com') expect(new_user.reset_password_token).to_not be_nil expect(json_response['user']).to eq new_user.id @@ -77,7 +77,7 @@ module Admin it "returns unauthorized response" do spree_post :create, email: 'another@email.com', enterprise_id: enterprise.id - new_user = Spree::User.find_by_email('another@email.com') + new_user = Spree::User.find_by(email: 'another@email.com') expect(new_user).to be_nil expect(response.status).to eq 302 diff --git a/spec/controllers/admin/order_cycles_controller_spec.rb b/spec/controllers/admin/order_cycles_controller_spec.rb index 67169a1047..2ba98c9f8e 100644 --- a/spec/controllers/admin/order_cycles_controller_spec.rb +++ b/spec/controllers/admin/order_cycles_controller_spec.rb @@ -203,7 +203,7 @@ module Admin context "as a manager of the coordinator" do let(:user) { coordinator.owner } - let(:expected) { [order_cycle, hash_including(order_cycle: allowed.merge(restricted)), user] } + let(:expected) { [order_cycle, allowed.merge(restricted), user] } it "allows me to update exchange information for exchanges, name and dates" do expect(OrderCycleForm).to receive(:new).with(*expected) { form_mock } @@ -213,7 +213,7 @@ module Admin context "as a producer supplying to an order cycle" do let(:user) { producer.owner } - let(:expected) { [order_cycle, hash_including(order_cycle: allowed), user] } + let(:expected) { [order_cycle, allowed, user] } it "allows me to update exchange information for exchanges, but not name or dates" do expect(OrderCycleForm).to receive(:new).with(*expected) { form_mock } @@ -291,7 +291,7 @@ module Admin let(:user) { create_enterprise_user } let(:admin_user) do user = create(:user) - user.spree_roles << Spree::Role.find_or_create_by_name!('admin') + user.spree_roles << Spree::Role.find_or_create_by!(name: 'admin') user end let(:order_cycle) { create(:simple_order_cycle) } @@ -320,7 +320,7 @@ module Admin describe "when an order cycle is deleteable" do it "allows the order_cycle to be destroyed" do spree_get :destroy, id: oc.id - expect(OrderCycle.find_by_id(oc.id)).to be nil + expect(OrderCycle.find_by(id: oc.id)).to be nil end end diff --git a/spec/controllers/admin/schedules_controller_spec.rb b/spec/controllers/admin/schedules_controller_spec.rb index 5f213b4292..99b73f4e03 100644 --- a/spec/controllers/admin/schedules_controller_spec.rb +++ b/spec/controllers/admin/schedules_controller_spec.rb @@ -80,7 +80,7 @@ describe Admin::SchedulesController, type: :controller do it "allows me to add/remove only order cycles I coordinate to/from the schedule" do order_cycle_ids = [coordinated_order_cycle2.id, uncoordinated_order_cycle2.id, uncoordinated_order_cycle3.id] - spree_put :update, format: :json, id: coordinated_schedule.id, schedule: { order_cycle_ids: order_cycle_ids } + spree_put :update, format: :json, id: coordinated_schedule.id, order_cycle_ids: order_cycle_ids expect(assigns(:schedule)).to eq coordinated_schedule # coordinated_order_cycle2 is added, uncoordinated_order_cycle is NOT removed expect(coordinated_schedule.reload.order_cycles).to include coordinated_order_cycle2, uncoordinated_order_cycle, uncoordinated_order_cycle3 @@ -93,9 +93,9 @@ describe Admin::SchedulesController, type: :controller do 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, schedule: { order_cycle_ids: [coordinated_order_cycle.id, coordinated_order_cycle2.id] } - spree_put :update, format: :json, id: coordinated_schedule.id, schedule: { order_cycle_ids: [coordinated_order_cycle.id] } - spree_put :update, format: :json, id: coordinated_schedule.id, schedule: { order_cycle_ids: [coordinated_order_cycle.id] } + spree_put :update, format: :json, id: coordinated_schedule.id, order_cycle_ids: [coordinated_order_cycle.id, coordinated_order_cycle2.id] + spree_put :update, format: :json, id: coordinated_schedule.id, order_cycle_ids: [coordinated_order_cycle.id] + spree_put :update, format: :json, id: coordinated_schedule.id, order_cycle_ids: [coordinated_order_cycle.id] end end @@ -138,7 +138,7 @@ describe Admin::SchedulesController, type: :controller do context "where I manage at least one of the order cycles to be added to the schedules" do before do - params[:schedule].merge!( order_cycle_ids: [coordinated_order_cycle.id, uncoordinated_order_cycle.id] ) + params.merge!( order_cycle_ids: [coordinated_order_cycle.id, uncoordinated_order_cycle.id] ) end it "allows me to create the schedule, adding only order cycles that I manage" do @@ -159,7 +159,7 @@ describe Admin::SchedulesController, type: :controller do context "where I don't manage any of the order cycles to be added to the schedules" do before do - params[:schedule].merge!( order_cycle_ids: [uncoordinated_order_cycle.id] ) + params.merge!( order_cycle_ids: [uncoordinated_order_cycle.id] ) end it "prevents me from creating the schedule" do @@ -171,7 +171,7 @@ describe Admin::SchedulesController, type: :controller do context 'as an admin user' do before do allow(controller).to receive(:spree_current_user) { create(:admin_user) } - params[:schedule].merge!( order_cycle_ids: [coordinated_order_cycle.id, uncoordinated_order_cycle.id] ) + params.merge!( order_cycle_ids: [coordinated_order_cycle.id, uncoordinated_order_cycle.id] ) end it "allows me to create a schedule" do diff --git a/spec/controllers/admin/variant_overrides_controller_spec.rb b/spec/controllers/admin/variant_overrides_controller_spec.rb index 0d721e7d9a..c75a265cd1 100644 --- a/spec/controllers/admin/variant_overrides_controller_spec.rb +++ b/spec/controllers/admin/variant_overrides_controller_spec.rb @@ -65,7 +65,7 @@ describe Admin::VariantOverridesController, type: :controller do it "destroys the variant override" do spree_put :bulk_update, format: format, variant_overrides: variant_override_params - expect(VariantOverride.find_by_id(variant_override.id)).to be_nil + expect(VariantOverride.find_by(id: variant_override.id)).to be_nil end end diff --git a/spec/controllers/api/base_controller_spec.rb b/spec/controllers/api/base_controller_spec.rb index 69db1ece52..d501aa98fb 100644 --- a/spec/controllers/api/base_controller_spec.rb +++ b/spec/controllers/api/base_controller_spec.rb @@ -35,7 +35,7 @@ describe Api::BaseController do context "cannot make a request to the API" do it "with an invalid API key" do - request.env["X-Spree-Token"] = "fake_key" + request.headers["X-Spree-Token"] = "fake_key" get :index, {} expect(json_response).to eq( "error" => "Invalid API key (fake_key) specified." ) expect(response.status).to eq(401) diff --git a/spec/controllers/api/enterprises_controller_spec.rb b/spec/controllers/api/enterprises_controller_spec.rb index 6e716eb5c2..1b3382274e 100644 --- a/spec/controllers/api/enterprises_controller_spec.rb +++ b/spec/controllers/api/enterprises_controller_spec.rb @@ -1,84 +1,93 @@ require 'spec_helper' -module Api - describe EnterprisesController, type: :controller do - include AuthenticationWorkflow - render_views +describe Api::EnterprisesController, type: :controller do + include AuthenticationWorkflow + render_views - let(:enterprise) { create(:distributor_enterprise) } + let(:enterprise) { create(:distributor_enterprise) } - context "as an enterprise owner" do - let(:enterprise_owner) { create_enterprise_user enterprise_limit: 10 } - let!(:enterprise) { create(:distributor_enterprise, owner: enterprise_owner) } + context "as an enterprise owner" do + let(:enterprise_owner) { create_enterprise_user enterprise_limit: 10 } + let!(:enterprise) { create(:distributor_enterprise, owner: enterprise_owner) } - before do - allow(controller).to receive(:spree_current_user) { enterprise_owner } - end + before do + allow(controller).to receive(:spree_current_user) { enterprise_owner } + end - describe "creating an enterprise" do - let(:australia) { Spree::Country.find_by_name('Australia') } - let(:new_enterprise_params) do - { - enterprise: { - name: 'name', contact_name: 'Sheila', address_attributes: { - address1: '123 Abc Street', - city: 'Northcote', - zipcode: '3070', - state_id: australia.states.first, - country_id: australia.id - } - } + describe "creating an enterprise" do + let(:australia) { Spree::Country.find_by(name: 'Australia') } + let(:new_enterprise_params) do + { + name: 'name', contact_name: 'Sheila', address_attributes: { + address1: '123 Abc Street', + city: 'Northcote', + zipcode: '3070', + state_id: australia.states.first.id, + country_id: australia.id } - end + } + end - it "creates as sells=any when it is not a producer" do - spree_post :create, new_enterprise_params - expect(response).to be_success + it "creates as sells=any when it is not a producer" do + api_post :create, { enterprise: new_enterprise_params } + expect(response).to be_success - enterprise = Enterprise.last - expect(enterprise.sells).to eq('any') - end + enterprise = Enterprise.last + expect(enterprise.sells).to eq('any') + end + + it "saves all user ids submitted" do + manager1 = create(:user) + manager2 = create(:user) + api_post :create, { + enterprise: new_enterprise_params. + merge({ user_ids: [enterprise_owner.id, manager1.id, manager2.id] }) + } + expect(response).to be_success + + enterprise = Enterprise.last + expect(enterprise.user_ids).to match_array([enterprise_owner.id, manager1.id, manager2.id]) end end + end - context "as an enterprise manager" do - let(:enterprise_manager) { create_enterprise_user } + context "as an enterprise manager" do + let(:enterprise_manager) { create_enterprise_user } - before do - enterprise_manager.enterprise_roles.build(enterprise: enterprise).save - allow(controller).to receive(:spree_current_user) { enterprise_manager } - end - - describe "submitting a valid image" do - before do - allow(Enterprise) - .to receive(:find_by_permalink).with(enterprise.id.to_s) { enterprise } - allow(enterprise).to receive(:update_attributes).and_return(true) - end - - it "I can update enterprise image" do - spree_post :update_image, logo: 'a logo', id: enterprise.id - expect(response).to be_success - end - end + before do + enterprise_manager.enterprise_roles.build(enterprise: enterprise).save + allow(controller).to receive(:spree_current_user) { enterprise_manager } end - context "as an non-managing user" do - let(:non_managing_user) { create_enterprise_user } - + describe "submitting a valid image" do before do allow(Enterprise) - .to receive(:find_by_permalink).with(enterprise.id.to_s) { enterprise } - allow(controller).to receive(:spree_current_user) { non_managing_user } + .to receive(:find_by).with({ permalink: enterprise.id.to_s }) { enterprise } + allow(enterprise).to receive(:update_attributes).and_return(true) end - describe "submitting a valid image" do - before { allow(enterprise).to receive(:update_attributes).and_return(true) } + it "I can update enterprise image" do + api_post :update_image, logo: 'a logo', id: enterprise.id + expect(response).to be_success + end + end + end - it "I can't update enterprise image" do - spree_post :update_image, logo: 'a logo', id: enterprise.id - assert_unauthorized! - end + context "as an non-managing user" do + let(:non_managing_user) { create_enterprise_user } + + before do + allow(Enterprise) + .to receive(:find_by).with({ permalink: enterprise.id.to_s }) { enterprise } + allow(controller).to receive(:spree_current_user) { non_managing_user } + end + + describe "submitting a valid image" do + before { allow(enterprise).to receive(:update_attributes).and_return(true) } + + it "I can't update enterprise image" do + api_post :update_image, logo: 'a logo', id: enterprise.id + assert_unauthorized! end end end diff --git a/spec/controllers/api/exchange_products_controller_spec.rb b/spec/controllers/api/exchange_products_controller_spec.rb index c39546358b..f94089280c 100644 --- a/spec/controllers/api/exchange_products_controller_spec.rb +++ b/spec/controllers/api/exchange_products_controller_spec.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + require 'spec_helper' module Api @@ -52,7 +54,7 @@ module Api let(:products_relation) { Spree::Product.includes(:variants).where("spree_variants.id": exchange.variants.map(&:id)) } before do - stub_const("Api::ExchangeProductsController::DEFAULT_PER_PAGE", 1) + stub_const("#{Api::ExchangeProductsController}::DEFAULT_PER_PAGE", 1) end describe "when a specific page is requested" do diff --git a/spec/controllers/api/orders_controller_spec.rb b/spec/controllers/api/orders_controller_spec.rb index 5e463fe7a2..69438ec2da 100644 --- a/spec/controllers/api/orders_controller_spec.rb +++ b/spec/controllers/api/orders_controller_spec.rb @@ -165,7 +165,7 @@ module Api before { allow(controller).to receive(:spree_current_user) { admin_user } } it "when no order number is given" do - get :show, id: nil + get :show, id: "" expect(response).to have_http_status(:not_found) end diff --git a/spec/controllers/api/shipments_controller_spec.rb b/spec/controllers/api/shipments_controller_spec.rb index d79eaf0c08..f4dba19f11 100644 --- a/spec/controllers/api/shipments_controller_spec.rb +++ b/spec/controllers/api/shipments_controller_spec.rb @@ -4,8 +4,9 @@ describe Api::ShipmentsController, type: :controller do render_views let!(:shipment) { create(:shipment) } - let!(:attributes) { [:id, :tracking, :number, :cost, :shipped_at, :stock_location_name, :order_id] } - let!(:resource_scoping) { { order_id: shipment.order.to_param, id: shipment.to_param } } + let!(:attributes) do + [:id, :tracking, :number, :cost, :shipped_at, :stock_location_name, :order_id] + end let(:current_api_user) { build(:user) } before do @@ -14,12 +15,12 @@ describe Api::ShipmentsController, type: :controller do context "as a non-admin" do it "cannot make a shipment ready" do - api_put :ready + api_put :ready, order_id: shipment.order.to_param, id: shipment.to_param assert_unauthorized! end it "cannot make a shipment shipped" do - api_put :ship + api_put :ship, order_id: shipment.order.to_param, id: shipment.to_param assert_unauthorized! end end @@ -92,7 +93,7 @@ describe Api::ShipmentsController, type: :controller do it "can make a shipment ready" do allow_any_instance_of(Spree::Order).to receive_messages(paid?: true, complete?: true) - api_put :ready + api_put :ready, order_id: shipment.order.to_param, id: shipment.to_param expect(attributes.all?{ |attr| json_response.key? attr.to_s }).to be_truthy expect(json_response["state"]).to eq("ready") @@ -101,7 +102,7 @@ describe Api::ShipmentsController, type: :controller do it "cannot make a shipment ready if the order is unpaid" do allow_any_instance_of(Spree::Order).to receive_messages(paid?: false) - api_put :ready + api_put :ready, order_id: shipment.order.to_param, id: shipment.to_param expect(json_response["error"]).to eq("Cannot ready shipment.") expect(response.status).to eq(422) @@ -109,21 +110,26 @@ describe Api::ShipmentsController, type: :controller do context 'for completed shipments' do let(:order) { create :completed_order_with_totals } - let!(:resource_scoping) { { order_id: order.to_param, id: order.shipments.first.to_param } } it 'adds a variant to a shipment' do - api_put :add, variant_id: variant.to_param, quantity: 2 + api_put :add, variant_id: variant.to_param, + quantity: 2, + order_id: order.to_param, + id: order.shipments.first.to_param expect(response.status).to eq(200) - expect(order.shipment.reload.inventory_units.select { |h| h['variant_id'] == variant.id }.size).to eq 2 + expect(inventory_units_for(variant).size).to eq 2 end it 'removes a variant from a shipment' do order.contents.add(variant, 2) - api_put :remove, variant_id: variant.to_param, quantity: 1 + api_put :remove, variant_id: variant.to_param, + quantity: 1, + order_id: order.to_param, + id: order.shipments.first.to_param expect(response.status).to eq(200) - expect(order.shipment.reload.inventory_units.select { |h| h['variant_id'] == variant.id }.size).to eq(1) + expect(inventory_units_for(variant).size).to eq(1) end end @@ -140,7 +146,9 @@ describe Api::ShipmentsController, type: :controller do it "can transition a shipment from ready to ship" do shipment.reload - api_put :ship, order_id: shipment.order.to_param, id: shipment.to_param, shipment: { tracking: "123123" } + api_put :ship, order_id: shipment.order.to_param, + id: shipment.to_param, + shipment: { tracking: "123123" } expect(attributes.all?{ |attr| json_response.key? attr.to_s }).to be_truthy expect(json_response["state"]).to eq("shipped") @@ -214,7 +222,7 @@ describe Api::ShipmentsController, type: :controller do end def make_order_contents_fail - expect(Spree::Order).to receive(:find_by_number!) { order } + expect(Spree::Order).to receive(:find_by!).with({ number: order.number }) { order } expect(order).to receive(:contents) { raise error_message } end diff --git a/spec/controllers/api/shops_controller_spec.rb b/spec/controllers/api/shops_controller_spec.rb index 33343e8d84..a90f606f57 100644 --- a/spec/controllers/api/shops_controller_spec.rb +++ b/spec/controllers/api/shops_controller_spec.rb @@ -2,45 +2,43 @@ require 'spec_helper' -module Api - describe ShopsController, type: :controller do - include AuthenticationWorkflow - render_views +describe Api::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) } + 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 } + 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 "#show" do - it "returns shopfront data for an enterprise" do - spree_get :show, id: producer.id + describe "#closed_shops" do + it "returns data for all closed shops" do + spree_get :closed_shops, {} - 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 + expect(json_response).not_to match hub.name - 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 - - response_ids = json_response.map { |shop| shop['id'] } - expect(response_ids).to contain_exactly(closed_hub1.id, closed_hub2.id) - end + response_ids = json_response.map { |shop| shop['id'] } + expect(response_ids).to contain_exactly(closed_hub1.id, closed_hub2.id) end end end diff --git a/spec/controllers/api/variants_controller_spec.rb b/spec/controllers/api/variants_controller_spec.rb index a5c81329dd..c91f25f2ec 100644 --- a/spec/controllers/api/variants_controller_spec.rb +++ b/spec/controllers/api/variants_controller_spec.rb @@ -113,7 +113,6 @@ describe Api::VariantsController, type: :controller do let(:product) { create(:product) } let(:variant) { product.master } - let(:resource_scoping) { { product_id: variant.product.to_param } } context "deleted variants" do before do @@ -121,7 +120,7 @@ describe Api::VariantsController, type: :controller do end it "are visible by admin" do - api_get :index, show_deleted: 1 + api_get :index, show_deleted: 1, product_id: variant.product.to_param expect(json_response.count).to eq(2) end @@ -129,7 +128,7 @@ describe Api::VariantsController, type: :controller do it "can create a new variant" do original_number_of_variants = variant.product.variants.count - api_post :create, variant: { sku: "12345", unit_value: "weight", unit_description: "L" } + api_post :create, variant: { sku: "12345", unit_value: "weight", unit_description: "L" }, product_id: variant.product.to_param expect(attributes.all?{ |attr| json_response.include? attr.to_s }).to eq(true) expect(response.status).to eq(201) diff --git a/spec/controllers/line_items_controller_spec.rb b/spec/controllers/line_items_controller_spec.rb index 31d890a80a..116a05ef2f 100644 --- a/spec/controllers/line_items_controller_spec.rb +++ b/spec/controllers/line_items_controller_spec.rb @@ -41,13 +41,6 @@ describe LineItemsController, type: :controller do before { allow(controller).to receive_messages spree_current_user: item.order.user } - context "without a line item id" do - it "fails and raises an error" do - delete :destroy - expect(response.status).to eq 404 - end - end - context "with a line item id" do let(:params) { { format: :json, id: item } } diff --git a/spec/controllers/spree/admin/countries_controller_spec.rb b/spec/controllers/spree/admin/countries_controller_spec.rb new file mode 100644 index 0000000000..4146a506de --- /dev/null +++ b/spec/controllers/spree/admin/countries_controller_spec.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +require 'spec_helper' + +module Spree + module Admin + describe CountriesController, type: :controller do + include AuthenticationWorkflow + + describe "#update" do + before { login_as_admin } + + it "updates the name of an existing country" do + country = create(:country) + spree_put :update, id: country.id, + country: { name: "Kyrgyzstan" } + + expect(response).to redirect_to spree.admin_countries_url + expect(country.reload.name).to eq "Kyrgyzstan" + end + end + end + end +end diff --git a/spec/controllers/spree/admin/orders_controller_spec.rb b/spec/controllers/spree/admin/orders_controller_spec.rb index aa54f46264..8ab20c385a 100644 --- a/spec/controllers/spree/admin/orders_controller_spec.rb +++ b/spec/controllers/spree/admin/orders_controller_spec.rb @@ -46,6 +46,14 @@ describe Spree::Admin::OrdersController, type: :controller do context "complete order" do let(:order) { create :completed_order_with_totals } + it "does not throw an error if no order object is given in params" do + params = { id: order } + + spree_put :update, params + + expect(response.status).to eq 302 + end + it "updates distribution charges and redirects to order details page" do expect_any_instance_of(Spree::Order).to receive(:update_distribution_charge!) diff --git a/spec/controllers/spree/admin/payment_methods_controller_spec.rb b/spec/controllers/spree/admin/payment_methods_controller_spec.rb index 2a2f03dbcc..ff23298c44 100644 --- a/spec/controllers/spree/admin/payment_methods_controller_spec.rb +++ b/spec/controllers/spree/admin/payment_methods_controller_spec.rb @@ -2,14 +2,13 @@ require 'spec_helper' module Spree class GatewayWithPassword < PaymentMethod - attr_accessible :preferred_password preference :password, :string, default: "password" end describe Admin::PaymentMethodsController, type: :controller do describe "#create and #update" do let!(:enterprise) { create(:distributor_enterprise, owner: user) } - let(:payment_method) { GatewayWithPassword.create!(name: "Bogus", preferred_password: "haxme", distributor_ids: [enterprise.id], preferred_enterprise_id: enterprise.id) } + let(:payment_method) { GatewayWithPassword.create!(name: "Bogus", preferred_password: "haxme", distributor_ids: [enterprise.id]) } let!(:user) { create(:user) } before { allow(controller).to receive(:spree_current_user) { user } } @@ -33,7 +32,7 @@ module Spree it "can create a payment method of a valid type" do expect { - spree_post :create, payment_method: { name: "Test Method", type: "Spree::Gateway::Bogus", distributor_ids: [enterprise.id], preferred_enterprise_id: enterprise.id } + spree_post :create, payment_method: { name: "Test Method", type: "Spree::Gateway::Bogus", distributor_ids: [enterprise.id] } }.to change(Spree::PaymentMethod, :count).by(1) expect(response).to be_redirect @@ -42,7 +41,7 @@ module Spree it "can not create a payment method of an invalid type" do expect { - spree_post :create, payment_method: { name: "Invalid Payment Method", type: "Spree::InvalidType", distributor_ids: [enterprise.id], preferred_enterprise_id: enterprise.id } + spree_post :create, payment_method: { name: "Invalid Payment Method", type: "Spree::InvalidType", distributor_ids: [enterprise.id] } }.to change(Spree::PaymentMethod, :count).by(0) expect(response).to be_redirect diff --git a/spec/controllers/spree/admin/payments_controller_spec.rb b/spec/controllers/spree/admin/payments_controller_spec.rb index 53dd604ebd..aeb9156ef2 100644 --- a/spec/controllers/spree/admin/payments_controller_spec.rb +++ b/spec/controllers/spree/admin/payments_controller_spec.rb @@ -92,11 +92,27 @@ describe Spree::Admin::PaymentsController, type: :controller do 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" + payment.update state: "pending" end allow_any_instance_of(Spree::Payment).to receive(:process!).and_return(true) end + it "makes a payment with the provided card details" do + source_attributes = { + gateway_payment_profile_id: "pm_123", + cc_type: "visa", + last_digits: "4242", + month: "4", + year: "2100" + } + + spree_post :create, payment: params.merge({ source_attributes: source_attributes }), + order_id: order.number + + payment = order.reload.payments.last + expect(payment.source.attributes.transform_keys(&:to_sym)).to include source_attributes + end + it "redirects to list of payments with success flash" do spree_post :create, payment: params, order_id: order.number diff --git a/spec/controllers/spree/admin/reports_controller_spec.rb b/spec/controllers/spree/admin/reports_controller_spec.rb index 9c4e2d65ff..8cfda5fe36 100644 --- a/spec/controllers/spree/admin/reports_controller_spec.rb +++ b/spec/controllers/spree/admin/reports_controller_spec.rb @@ -139,8 +139,8 @@ describe Spree::Admin::ReportsController, type: :controller do spree_get :index report_types = assigns(:reports).keys - expect(report_types).to include "orders_and_fulfillment", "products_and_inventory", "packing" # and others - expect(report_types).to_not include "sales_tax" + expect(report_types).to include :orders_and_fulfillment, :products_and_inventory, :packing # and others + expect(report_types).to_not include :sales_tax end end diff --git a/spec/controllers/spree/admin/return_authorizations_controller_spec.rb b/spec/controllers/spree/admin/return_authorizations_controller_spec.rb new file mode 100644 index 0000000000..6c28642da5 --- /dev/null +++ b/spec/controllers/spree/admin/return_authorizations_controller_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require 'spec_helper' + +module Spree + module Admin + describe ReturnAuthorizationsController, type: :controller do + include AuthenticationWorkflow + + let(:order) do + create(:order, :with_line_item, :completed, + distributor: create(:distributor_enterprise) ) + end + + before do + login_as_admin + + # Pay the order + order.payments.first.complete + order.updater.update_payment_state + + # Ship the order + order.reload.shipment.ship! + end + + it "creates and updates a return authorization" do + # Create return authorization + spree_post :create, order_id: order.number, + return_authorization: { amount: "20.2", reason: "broken" } + + expect(response).to redirect_to spree.admin_order_return_authorizations_url(order.number) + return_authorization = order.return_authorizations.first + expect(return_authorization.amount.to_s).to eq "20.2" + expect(return_authorization.reason.to_s).to eq "broken" + + # Update return authorization + spree_put :update, id: return_authorization.id, + return_authorization: { amount: "10.2", reason: "half broken" } + + expect(response).to redirect_to spree.admin_order_return_authorizations_url(order.number) + return_authorization.reload + expect(return_authorization.amount.to_s).to eq "10.2" + expect(return_authorization.reason.to_s).to eq "half broken" + end + end + end +end diff --git a/spec/controllers/spree/admin/shipping_categories_controller_spec.rb b/spec/controllers/spree/admin/shipping_categories_controller_spec.rb new file mode 100644 index 0000000000..531b175072 --- /dev/null +++ b/spec/controllers/spree/admin/shipping_categories_controller_spec.rb @@ -0,0 +1,32 @@ +# frozen_string_literal: true + +require 'spec_helper' + +module Spree + module Admin + describe ShippingCategoriesController, type: :controller do + include AuthenticationWorkflow + + describe "#create and #update" do + before { login_as_admin } + + it "creates a shipping shipping category" do + expect { + spree_post :create, shipping_category: { name: "Frozen" } + }.to change(Spree::ShippingCategory.all, :count).by(1) + + expect(response).to redirect_to spree.admin_shipping_categories_url + end + + it "updates an existing shipping category" do + shipping_category = create(:shipping_category) + spree_put :update, id: shipping_category.id, + shipping_category: { name: "Super Frozen" } + + expect(response).to redirect_to spree.admin_shipping_categories_url + expect(shipping_category.reload.name).to eq "Super Frozen" + end + end + end + end +end diff --git a/spec/controllers/spree/admin/shipping_methods_controller_spec.rb b/spec/controllers/spree/admin/shipping_methods_controller_spec.rb index d705972c87..531d01c11e 100644 --- a/spec/controllers/spree/admin/shipping_methods_controller_spec.rb +++ b/spec/controllers/spree/admin/shipping_methods_controller_spec.rb @@ -3,29 +3,104 @@ require 'spec_helper' describe Spree::Admin::ShippingMethodsController, type: :controller do include AuthenticationWorkflow - describe "shipping method not referenced by order" do + describe "#update" do let(:shipping_method) { create(:shipping_method) } + let(:params) { + { + id: shipping_method.id, + shipping_method: { + calculator_attributes: { + id: shipping_method.calculator.id + } + } + } + } - scenario "is soft deleted" do - login_as_admin - expect(shipping_method.deleted_at).to be_nil + before { login_as_admin } - spree_delete :destroy, "id" => shipping_method.id + it "updates preferred_amount and preferred_currency of a FlatRate calculator" do + shipping_method.calculator = create(:calculator_flat_rate, calculable: shipping_method) + params[:shipping_method][:calculator_attributes][:preferred_amount] = 123 + params[:shipping_method][:calculator_attributes][:preferred_currency] = "EUR" - expect(shipping_method.reload.deleted_at).not_to be_nil + spree_post :update, params + + expect(shipping_method.reload.calculator.preferred_amount).to eq 123 + expect(shipping_method.reload.calculator.preferred_currency).to eq "EUR" + end + + it "updates preferred_per_kg of a Weight calculator" do + shipping_method.calculator = create(:weight_calculator, calculable: shipping_method) + params[:shipping_method][:calculator_attributes][:preferred_per_kg] = 10 + + spree_post :update, params + + expect(shipping_method.reload.calculator.preferred_per_kg).to eq 10 + end + + it "updates preferred_flat_percent of a FlatPercentPerItem calculator" do + shipping_method.calculator = Calculator::FlatPercentPerItem.new(preferred_flat_percent: 20, + + calculable: shipping_method) + params[:shipping_method][:calculator_attributes][:preferred_flat_percent] = 30 + + spree_post :update, params + + expect(shipping_method.reload.calculator.preferred_flat_percent).to eq 30 + end + + it "updates details of a FlexiRate calculator" do + shipping_method.calculator = Spree::Calculator::FlexiRate.new(calculable: shipping_method) + params[:shipping_method][:calculator_attributes][:preferred_first_item] = 10 + params[:shipping_method][:calculator_attributes][:preferred_additional_item] = 20 + params[:shipping_method][:calculator_attributes][:preferred_max_items] = 30 + + spree_post :update, params + + expect(shipping_method.reload.calculator.preferred_first_item).to eq 10 + expect(shipping_method.reload.calculator.preferred_additional_item).to eq 20 + expect(shipping_method.reload.calculator.preferred_max_items).to eq 30 + end + + it "updates details of a PriceSack calculator" do + shipping_method.calculator = Spree::Calculator::PriceSack.new(calculable: shipping_method) + params[:shipping_method][:calculator_attributes][:preferred_minimal_amount] = 10 + params[:shipping_method][:calculator_attributes][:preferred_normal_amount] = 20 + params[:shipping_method][:calculator_attributes][:preferred_discount_amount] = 30 + + spree_post :update, params + + expect(shipping_method.reload.calculator.preferred_minimal_amount).to eq 10 + expect(shipping_method.reload.calculator.preferred_normal_amount).to eq 20 + expect(shipping_method.reload.calculator.preferred_discount_amount).to eq 30 end end - describe "shipping method referenced by order" do - let(:order) { create(:order_with_line_items) } + describe "#delete" do + describe "shipping method not referenced by order" do + let(:shipping_method) { create(:shipping_method) } - scenario "is not soft deleted" do - login_as_admin - expect(order.shipping_method.deleted_at).to be_nil + scenario "is soft deleted" do + login_as_admin + expect(shipping_method.deleted_at).to be_nil - spree_delete :destroy, "id" => order.shipping_method.id + spree_delete :destroy, "id" => shipping_method.id - expect(order.shipping_method.reload.deleted_at).to be_nil + expect(shipping_method.reload.deleted_at).not_to be_nil + end + end + + describe "shipping method referenced by order" do + let(:order) { create(:order_with_line_items) } + + scenario "is not soft deleted" do + login_as_admin + expect(order.shipping_method.deleted_at).to be_nil + + spree_delete :destroy, "id" => order.shipping_method.id + + expect(order.shipping_method.reload.deleted_at).to be_nil + end end end end diff --git a/spec/controllers/spree/admin/users_controller_spec.rb b/spec/controllers/spree/admin/users_controller_spec.rb index a42630964d..22c0bc71ab 100644 --- a/spec/controllers/spree/admin/users_controller_spec.rb +++ b/spec/controllers/spree/admin/users_controller_spec.rb @@ -13,13 +13,13 @@ describe Spree::Admin::UsersController do end it 'should grant access to users with an admin role' do - user.spree_roles << Spree::Role.find_or_create_by_name('admin') + user.spree_roles << Spree::Role.find_or_create_by(name: 'admin') spree_post :index expect(response).to render_template :index end it "allows admins to update a user's API key" do - user.spree_roles << Spree::Role.find_or_create_by_name('admin') + user.spree_roles << Spree::Role.find_or_create_by(name: 'admin') expect(test_user).to receive(:generate_spree_api_key!).and_return(true) puts user.id puts test_user.id @@ -28,21 +28,21 @@ describe Spree::Admin::UsersController do end it "allows admins to clear a user's API key" do - user.spree_roles << Spree::Role.find_or_create_by_name('admin') + user.spree_roles << Spree::Role.find_or_create_by(name: 'admin') expect(test_user).to receive(:clear_spree_api_key!).and_return(true) spree_put :clear_api_key, id: test_user.id expect(response).to redirect_to(spree.edit_admin_user_path(test_user)) end it 'should deny access to users with an bar role' do - user.spree_roles << Spree::Role.find_or_create_by_name('bar') + user.spree_roles << Spree::Role.find_or_create_by(name: 'bar') Spree::Ability.register_ability(BarAbility) spree_post :index expect(response).to redirect_to('/unauthorized') end it 'should deny access to users with an bar role' do - user.spree_roles << Spree::Role.find_or_create_by_name('bar') + user.spree_roles << Spree::Role.find_or_create_by(name: 'bar') Spree::Ability.register_ability(BarAbility) spree_post :update, id: '9' expect(response).to redirect_to('/unauthorized') diff --git a/spec/factories.rb b/spec/factories.rb index da823a1e48..d13757cb2a 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -28,7 +28,16 @@ FactoryBot.define do factory :schedule, class: Schedule do sequence(:name) { |n| "Schedule #{n}" } - order_cycles { [OrderCycle.first || FactoryBot.create(:simple_order_cycle)] } + + transient do + order_cycles { [OrderCycle.first || create(:simple_order_cycle)] } + end + + before(:create) do |schedule, evaluator| + evaluator.order_cycles.each do |order_cycle| + order_cycle.schedules << schedule + end + end end factory :proxy_order, class: ProxyOrder do @@ -124,7 +133,7 @@ FactoryBot.define do default_tax true after(:create) do |zone| - Spree::ZoneMember.create!(zone: zone, zoneable: Spree::Country.find_by_name('Australia')) + Spree::ZoneMember.create!(zone: zone, zoneable: Spree::Country.find_by(name: 'Australia')) end end @@ -171,8 +180,12 @@ end FactoryBot.modify do factory :address do - state { Spree::State.find_by_name 'Victoria' } - country { Spree::Country.find_by_name 'Australia' || Spree::Country.first } + state { Spree::State.find_by name: 'Victoria' } + country { Spree::Country.find_by name: 'Australia' || Spree::Country.first } + end + + factory :credit_card do + cc_type 'visa' end factory :payment do diff --git a/spec/factories/enterprise_factory.rb b/spec/factories/enterprise_factory.rb index ea93a818aa..5382e0fd94 100644 --- a/spec/factories/enterprise_factory.rb +++ b/spec/factories/enterprise_factory.rb @@ -1,11 +1,24 @@ FactoryBot.define do factory :enterprise, class: Enterprise do + transient do + users [] + logo {} + promo_image {} + end + owner { FactoryBot.create :user } sequence(:name) { |n| "Enterprise #{n}" } sells 'any' description 'enterprise' long_description '

Hello, world!

This is a paragraph.

' address { FactoryBot.create(:address) } + + after(:create) do |enterprise, proxy| + proxy.users.each do |user| + enterprise.users << user unless enterprise.users.include?(user) + end + enterprise.update_attributes logo: proxy.logo, promo_image: proxy.promo_image + end end factory :supplier_enterprise, parent: :enterprise do diff --git a/spec/factories/order_factory.rb b/spec/factories/order_factory.rb index 38f2bc456e..282d4772c1 100644 --- a/spec/factories/order_factory.rb +++ b/spec/factories/order_factory.rb @@ -135,4 +135,8 @@ FactoryBot.modify do end end end + + factory :completed_order_with_totals do + distributor { create(:distributor_enterprise) } + end end diff --git a/spec/factories/shipment_factory.rb b/spec/factories/shipment_factory.rb index aa4002f9c6..75bc54654d 100644 --- a/spec/factories/shipment_factory.rb +++ b/spec/factories/shipment_factory.rb @@ -31,6 +31,6 @@ end FactoryBot.modify do factory :shipment, class: Spree::Shipment do # keeps test shipments unique per order - initialize_with { Spree::Shipment.find_or_create_by_order_id(order.id) } + initialize_with { Spree::Shipment.find_or_create_by(order_id: order.id) } end end diff --git a/spec/factories/subscription_factory.rb b/spec/factories/subscription_factory.rb index 009f9ef802..c10110fe72 100644 --- a/spec/factories/subscription_factory.rb +++ b/spec/factories/subscription_factory.rb @@ -20,9 +20,8 @@ FactoryBot.define do 3, subscription: subscription) subscription.order_cycles.each do |oc| - ex = oc.exchanges.outgoing.find_by_sender_id_and_receiver_id( - subscription.shop_id, subscription.shop_id - ) + ex = oc.exchanges.outgoing.find_by(sender_id: subscription.shop_id, + receiver_id: subscription.shop_id) ex ||= create(:exchange, order_cycle: oc, sender: subscription.shop, receiver: subscription.shop, diff --git a/spec/factories/user_factory.rb b/spec/factories/user_factory.rb index 9e902c202e..5f9a367885 100644 --- a/spec/factories/user_factory.rb +++ b/spec/factories/user_factory.rb @@ -1,5 +1,9 @@ FactoryBot.modify do factory :user do + transient do + enterprises [] + end + confirmation_sent_at '1970-01-01 00:00:00' confirmed_at '1970-01-01 00:00:01' @@ -13,8 +17,10 @@ FactoryBot.modify do end end - after(:create) do |user| + after(:create) do |user, proxy| user.spree_roles.clear # Remove admin role + + user.enterprises << proxy.enterprises end end @@ -23,7 +29,7 @@ FactoryBot.modify do confirmed_at '1970-01-01 00:00:01' after(:create) do |user| - user.spree_roles << Spree::Role.find_or_create_by_name!('admin') + user.spree_roles << Spree::Role.find_or_create_by!(name: 'admin') end end end diff --git a/spec/features/admin/configuration/zones_spec.rb b/spec/features/admin/configuration/zones_spec.rb index 498f910ddf..11b3f92649 100644 --- a/spec/features/admin/configuration/zones_spec.rb +++ b/spec/features/admin/configuration/zones_spec.rb @@ -3,38 +3,55 @@ require 'spec_helper' describe "Zones" do include AuthenticationWorkflow - before(:each) do + before do quick_login_as_admin Spree::Zone.delete_all + end + + scenario "list existing zones" do visit spree.admin_dashboard_path click_link "Configuration" + + create(:zone, name: "eastern", description: "zone is eastern") + create(:zone, name: "western", description: "cool san fran") + click_link "Zones" + + within_row(1) { expect(page).to have_content("eastern") } + within_row(2) { expect(page).to have_content("western") } + + click_link "zones_order_by_description_title" + + within_row(1) { expect(page).to have_content("western") } + within_row(2) { expect(page).to have_content("eastern") } end - context "show" do - it "should display existing zones" do - create(:zone, name: "eastern", description: "zone is eastern") - create(:zone, name: "western", description: "cool san fran") - click_link "Zones" + scenario "create a new zone" do + visit spree.admin_zones_path + click_link "admin_new_zone_link" + expect(page).to have_content("New Zone") - within_row(1) { expect(page).to have_content("eastern") } - within_row(2) { expect(page).to have_content("western") } + fill_in "zone_name", with: "japan" + fill_in "zone_description", with: "japanese time zone" + click_button "Create" - click_link "zones_order_by_description_title" - - within_row(1) { expect(page).to have_content("western") } - within_row(2) { expect(page).to have_content("eastern") } - end + expect(page).to have_content("successfully created!") end - context "create" do - it "should allow an admin to create a new zone" do - click_link "Zones" - click_link "admin_new_zone_link" - expect(page).to have_content("New Zone") - fill_in "zone_name", with: "japan" - fill_in "zone_description", with: "japanese time zone" - click_button "Create" - expect(page).to have_content("successfully created!") - end + scenario "edit existing zone", js: true do + zone = create(:zone_with_member) + visit spree.edit_admin_zone_path(zone.id) + + expect(page).to have_checked_field "country_based" + + # Toggle to state based zone + choose "State Based" + + # click Add State + page.find("#nested-state").click + # select first state available + find('.select2').find(:xpath, 'option[2]').select_option + + click_button "Update" + expect(page).to have_content("successfully updated!") end end diff --git a/spec/features/admin/enterprise_fees_spec.rb b/spec/features/admin/enterprise_fees_spec.rb index 4fc10a1202..a231f272e5 100644 --- a/spec/features/admin/enterprise_fees_spec.rb +++ b/spec/features/admin/enterprise_fees_spec.rb @@ -137,7 +137,7 @@ feature ' # After saving, we should be redirected to the fees for our chosen enterprise expect(page).not_to have_select 'enterprise_fee_set_collection_attributes_1_enterprise_id', selected: 'Second Distributor' - enterprise_fee = EnterpriseFee.find_by_name 'foo' + enterprise_fee = EnterpriseFee.find_by name: 'foo' expect(enterprise_fee.enterprise).to eq(distributor1) end diff --git a/spec/features/admin/enterprise_roles_spec.rb b/spec/features/admin/enterprise_roles_spec.rb index c618064140..ff29207aeb 100644 --- a/spec/features/admin/enterprise_roles_spec.rb +++ b/spec/features/admin/enterprise_roles_spec.rb @@ -159,7 +159,7 @@ feature ' expect(page).not_to have_selector "#invite-manager-modal" expect(page).to have_selector "table.managers" - new_user = Spree::User.find_by_email_and_confirmed_at(new_email, nil) + new_user = Spree::User.find_by(email: new_email, confirmed_at: nil) expect(Enterprise.managed_by(new_user)).to include enterprise within 'table.managers' do diff --git a/spec/features/admin/multilingual_spec.rb b/spec/features/admin/multilingual_spec.rb index 7f86b30e74..90d21d1ecd 100644 --- a/spec/features/admin/multilingual_spec.rb +++ b/spec/features/admin/multilingual_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' feature 'Multilingual', js: true do include AuthenticationWorkflow include WebHelper - let(:admin_role) { Spree::Role.find_or_create_by_name!('admin') } + let(:admin_role) { Spree::Role.find_or_create_by!(name: 'admin') } let(:admin_user) { create(:user) } background do @@ -12,10 +12,10 @@ feature 'Multilingual', js: true do visit spree.admin_dashboard_path end - it 'has two locales available' do + it 'has three locales available' do expect(Rails.application.config.i18n[:default_locale]).to eq 'en' expect(Rails.application.config.i18n[:locale]).to eq 'en' - expect(Rails.application.config.i18n[:available_locales]).to eq ['en', 'es'] + expect(Rails.application.config.i18n[:available_locales]).to eq ['en', 'es', 'pt'] end it 'can switch language by params' do diff --git a/spec/features/admin/order_cycles/complex_creating_specific_time_spec.rb b/spec/features/admin/order_cycles/complex_creating_specific_time_spec.rb new file mode 100644 index 0000000000..69774fb043 --- /dev/null +++ b/spec/features/admin/order_cycles/complex_creating_specific_time_spec.rb @@ -0,0 +1,136 @@ +require 'spec_helper' + +feature ' + As an administrator + I want to create/update complex order cycles with a specific time +', js: true do + include AdminHelper + include AuthenticationWorkflow + include WebHelper + + let(:order_cycle_opening_time) { Time.zone.local(2040, 11, 0o6, 0o6, 0o0, 0o0).strftime("%F %T %z") } + let(:order_cycle_closing_time) { Time.zone.local(2040, 11, 13, 17, 0o0, 0o0).strftime("%F %T %z") } + + scenario "creating an order cycle with full interface", js: true do + # Given coordinating, supplying and distributing enterprises with some products with variants + coordinator = create(:distributor_enterprise, name: 'My coordinator') + supplier = create(:supplier_enterprise, name: 'My supplier') + product = create(:product, supplier: supplier) + v1 = create(:variant, product: product) + v2 = create(:variant, product: product) + distributor = create(:distributor_enterprise, name: 'My distributor', with_payment_and_shipping: true) + + # Relationships required for interface to work + create(:enterprise_relationship, parent: supplier, child: coordinator, permissions_list: [:add_to_order_cycle]) + create(:enterprise_relationship, parent: distributor, child: coordinator, permissions_list: [:add_to_order_cycle]) + create(:enterprise_relationship, parent: supplier, child: distributor, permissions_list: [:add_to_order_cycle]) + + # And some enterprise fees + supplier_fee = create(:enterprise_fee, enterprise: supplier, name: 'Supplier fee') + coordinator_fee = create(:enterprise_fee, enterprise: coordinator, name: 'Coord fee') + distributor_fee = create(:enterprise_fee, enterprise: distributor, name: 'Distributor fee') + + # When I go to the new order cycle page + quick_login_as_admin + visit admin_order_cycles_path + click_link 'New Order Cycle' + + # Select a coordinator since there are two available + select2_select 'My coordinator', from: 'coordinator_id' + click_button "Continue >" + + # I cannot save before filling in the required fields + expect(page).to have_button("Create", disabled: true) + + # The Create button is enabled once Name is entered + fill_in 'order_cycle_name', with: 'Plums & Avos' + expect(page).to have_button("Create", disabled: false) + + # If I fill in the basic fields + fill_in 'order_cycle_orders_open_at', with: order_cycle_opening_time + fill_in 'order_cycle_orders_close_at', with: order_cycle_closing_time + + # And I add a coordinator fee + click_button 'Add coordinator fee' + select 'Coord fee', from: 'order_cycle_coordinator_fee_0_id' + + click_button 'Create' + expect(page).to have_content 'Your order cycle has been created.' + + # I should not be able to add a blank supplier + expect(page).to have_select 'new_supplier_id', selected: '' + expect(page).to have_button 'Add supplier', disabled: true + + # And I add a supplier and some products + select 'My supplier', from: 'new_supplier_id' + click_button 'Add supplier' + fill_in 'order_cycle_incoming_exchange_0_receival_instructions', with: 'receival instructions' + page.find('table.exchanges tr.supplier td.products').click + check "order_cycle_incoming_exchange_0_variants_#{v1.id}" + check "order_cycle_incoming_exchange_0_variants_#{v2.id}" + + # I should not be able to re-add the supplier + expect(page).not_to have_select 'new_supplier_id', with_options: ['My supplier'] + expect(page).to have_button 'Add supplier', disabled: true + expect(page.all("td.supplier_name").map(&:text)).to eq(['My supplier']) + + # And I add a supplier fee + within("tr.supplier-#{supplier.id}") { click_button 'Add fee' } + select 'My supplier', from: 'order_cycle_incoming_exchange_0_enterprise_fees_0_enterprise_id' + select 'Supplier fee', from: 'order_cycle_incoming_exchange_0_enterprise_fees_0_enterprise_fee_id' + + click_button 'Save and Next' + + # And I add a distributor with the same products + select 'My distributor', from: 'new_distributor_id' + click_button 'Add distributor' + + fill_in 'order_cycle_outgoing_exchange_0_pickup_time', with: 'pickup time' + fill_in 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'pickup instructions' + + page.find('table.exchanges tr.distributor td.products').click + check "order_cycle_outgoing_exchange_0_variants_#{v1.id}" + check "order_cycle_outgoing_exchange_0_variants_#{v2.id}" + + page.find('table.exchanges tr.distributor td.tags').click + within ".exchange-tags" do + find(:css, "tags-input .tags input").set "wholesale\n" + end + + # And I add a distributor fee + within("tr.distributor-#{distributor.id}") { click_button 'Add fee' } + select 'My distributor', from: 'order_cycle_outgoing_exchange_0_enterprise_fees_0_enterprise_id' + select 'Distributor fee', from: 'order_cycle_outgoing_exchange_0_enterprise_fees_0_enterprise_fee_id' + + click_button 'Save and Back to List' + + oc = OrderCycle.last + toggle_columns "Producers", "Shops" + + expect(page).to have_input "oc#{oc.id}[name]", value: "Plums & Avos" + expect(page).to have_input "oc#{oc.id}[orders_open_at]", value: order_cycle_opening_time + expect(page).to have_input "oc#{oc.id}[orders_close_at]", value: order_cycle_closing_time + expect(page).to have_content "My coordinator" + + expect(page).to have_selector 'td.producers', text: 'My supplier' + expect(page).to have_selector 'td.shops', text: 'My distributor' + + # And it should have some fees + expect(oc.exchanges.incoming.first.enterprise_fees).to eq([supplier_fee]) + expect(oc.coordinator_fees).to eq([coordinator_fee]) + expect(oc.exchanges.outgoing.first.enterprise_fees).to eq([distributor_fee]) + + # And it should have some variants selected + expect(oc.exchanges.first.variants.count).to eq(2) + expect(oc.exchanges.last.variants.count).to eq(2) + + # And my receival and pickup time and instructions should have been saved + exchange = oc.exchanges.incoming.first + expect(exchange.receival_instructions).to eq('receival instructions') + + exchange = oc.exchanges.outgoing.first + expect(exchange.pickup_time).to eq('pickup time') + expect(exchange.pickup_instructions).to eq('pickup instructions') + expect(exchange.tag_list).to eq(['wholesale']) + end +end diff --git a/spec/features/admin/order_cycles/complex_editing_exchange_same_enterprise_spec.rb b/spec/features/admin/order_cycles/complex_editing_exchange_same_enterprise_spec.rb new file mode 100644 index 0000000000..d6ef3554fa --- /dev/null +++ b/spec/features/admin/order_cycles/complex_editing_exchange_same_enterprise_spec.rb @@ -0,0 +1,33 @@ +require 'spec_helper' + +feature ' + As an administrator + I want to manage complex order cycles +', js: true do + include AdminHelper + include AuthenticationWorkflow + include WebHelper + + scenario "editing an order cycle with an exchange between the same enterprise" do + c = create(:distributor_enterprise, is_primary_producer: true) + + # Given two order cycles, one with a mono-enterprise incoming exchange... + oc_incoming = create(:simple_order_cycle, suppliers: [c], coordinator: c) + + # And the other with a mono-enterprise outgoing exchange + oc_outgoing = create(:simple_order_cycle, coordinator: c, distributors: [c]) + + # When I edit the first order cycle, the exchange should appear as incoming + quick_login_as_admin + visit admin_order_cycle_incoming_path(oc_incoming) + expect(page).to have_selector 'table.exchanges tr.supplier' + visit admin_order_cycle_outgoing_path(oc_incoming) + expect(page).not_to have_selector 'table.exchanges tr.distributor' + + # And when I edit the second order cycle, the exchange should appear as outgoing + visit admin_order_cycle_outgoing_path(oc_outgoing) + expect(page).to have_selector 'table.exchanges tr.distributor' + visit admin_order_cycle_incoming_path(oc_outgoing) + expect(page).not_to have_selector 'table.exchanges tr.supplier' + end +end diff --git a/spec/features/admin/order_cycles/complex_editing_multiple_product_pages_spec.rb b/spec/features/admin/order_cycles/complex_editing_multiple_product_pages_spec.rb new file mode 100644 index 0000000000..5ff181e7f5 --- /dev/null +++ b/spec/features/admin/order_cycles/complex_editing_multiple_product_pages_spec.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +require 'spec_helper' + +feature ' + As an administrator + I want to manage complex order cycles +', js: true do + include AdminHelper + include AuthenticationWorkflow + include WebHelper + + describe "editing an order cycle with multiple pages of products", js: true do + let(:order_cycle) { create(:order_cycle) } + let(:supplier_enterprise) { order_cycle.exchanges.incoming.first.sender } + let!(:new_product) { create(:product, supplier: supplier_enterprise) } + + before do + stub_const("#{Api::ExchangeProductsController}::DEFAULT_PER_PAGE", 1) + + quick_login_as_admin + visit admin_order_cycle_incoming_path(order_cycle) + expect(page).to have_content "1 / 2 selected" + + page.find("tr.supplier-#{supplier_enterprise.id} td.products").click + expect(page).to have_selector ".exchange-product-details" + + expect(page).to have_content "1 of 2 Variants Loaded" + expect(page).to_not have_content new_product.name + end + + scenario "load all products" do + page.find(".exchange-load-all-variants a").click + + expect_all_products_loaded + end + + scenario "select all products" do + # replace with scroll_to method when upgrading to Capybara >= 3.13.0 + checkbox_id = "order_cycle_incoming_exchange_0_select_all_variants" + page.execute_script("document.getElementById('#{checkbox_id}').scrollIntoView()") + check checkbox_id + + expect_all_products_loaded + + expect(page).to have_checked_field "order_cycle_incoming_exchange_0_variants_#{new_product.variants.first.id}", disabled: false + end + + def expect_all_products_loaded + expect(page).to have_content new_product.name.upcase + expect(page).to have_content "2 of 2 Variants Loaded" + end + end +end diff --git a/spec/features/admin/order_cycles/complex_editing_spec.rb b/spec/features/admin/order_cycles/complex_editing_spec.rb new file mode 100644 index 0000000000..0b6b9d8ac0 --- /dev/null +++ b/spec/features/admin/order_cycles/complex_editing_spec.rb @@ -0,0 +1,95 @@ +require 'spec_helper' + +feature ' + As an administrator + I want to manage complex order cycles +', js: true do + include AdminHelper + include AuthenticationWorkflow + include WebHelper + + scenario "editing an order cycle" do + # Given an order cycle with all the settings + oc = create(:order_cycle) + oc.suppliers.first.update_attribute :name, 'AAA' + oc.suppliers.last.update_attribute :name, 'ZZZ' + oc.distributors.first.update_attribute :name, 'AAAA' + oc.distributors.last.update_attribute :name, 'ZZZZ' + + # When I edit it + quick_login_as_admin + visit edit_admin_order_cycle_path(oc) + + wait_for_edit_form_to_load_order_cycle(oc) + + # Then I should see the basic settings + expect(page.find('#order_cycle_name').value).to eq(oc.name) + expect(page.find('#order_cycle_orders_open_at').value).to eq(oc.orders_open_at.to_s) + expect(page.find('#order_cycle_orders_close_at').value).to eq(oc.orders_close_at.to_s) + expect(page).to have_content "COORDINATOR #{oc.coordinator.name}" + + click_button 'Next' + + # And I should see the suppliers + expect(page).to have_selector 'td.supplier_name', text: oc.suppliers.first.name + expect(page).to have_selector 'td.supplier_name', text: oc.suppliers.last.name + + expect(page).to have_field 'order_cycle_incoming_exchange_0_receival_instructions', with: 'instructions 0' + expect(page).to have_field 'order_cycle_incoming_exchange_1_receival_instructions', with: 'instructions 1' + + # And the suppliers should have products + page.all('table.exchanges tbody tr.supplier').each_with_index do |row, i| + row.find('td.products').click + + products_panel = page.all('table.exchanges tr.panel-row .exchange-supplied-products').select(&:visible?).first + expect(products_panel).to have_selector "input[name='order_cycle_incoming_exchange_#{i}_select_all_variants']" + + row.find('td.products').click + end + + # And the suppliers should have fees + supplier = oc.suppliers.min_by(&:name) + expect(page).to have_select 'order_cycle_incoming_exchange_0_enterprise_fees_0_enterprise_id', selected: supplier.name + expect(page).to have_select 'order_cycle_incoming_exchange_0_enterprise_fees_0_enterprise_fee_id', selected: supplier.enterprise_fees.first.name + + supplier = oc.suppliers.max_by(&:name) + expect(page).to have_select 'order_cycle_incoming_exchange_1_enterprise_fees_0_enterprise_id', selected: supplier.name + expect(page).to have_select 'order_cycle_incoming_exchange_1_enterprise_fees_0_enterprise_fee_id', selected: supplier.enterprise_fees.first.name + + click_button 'Next' + + # And I should see the distributors + expect(page).to have_selector 'td.distributor_name', text: oc.distributors.first.name + expect(page).to have_selector 'td.distributor_name', text: oc.distributors.last.name + + expect(page).to have_field 'order_cycle_outgoing_exchange_0_pickup_time', with: 'time 0' + expect(page).to have_field 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'instructions 0' + expect(page).to have_field 'order_cycle_outgoing_exchange_1_pickup_time', with: 'time 1' + expect(page).to have_field 'order_cycle_outgoing_exchange_1_pickup_instructions', with: 'instructions 1' + + # And the distributors should have products + page.all('table.exchanges tbody tr.distributor').each_with_index do |row, i| + row.find('td.products').click + + products_panel = page.all('table.exchanges tr.panel-row .exchange-distributed-products').select(&:visible?).first + expect(products_panel).to have_selector "input[name='order_cycle_outgoing_exchange_#{i}_select_all_variants']" + + row.find('td.products').click + end + + # And the distributors should have fees + distributor = oc.distributors.min_by(&:id) + expect(page).to have_select 'order_cycle_outgoing_exchange_0_enterprise_fees_0_enterprise_id', selected: distributor.name + expect(page).to have_select 'order_cycle_outgoing_exchange_0_enterprise_fees_0_enterprise_fee_id', selected: distributor.enterprise_fees.first.name + + distributor = oc.distributors.max_by(&:id) + expect(page).to have_select 'order_cycle_outgoing_exchange_1_enterprise_fees_0_enterprise_id', selected: distributor.name + expect(page).to have_select 'order_cycle_outgoing_exchange_1_enterprise_fees_0_enterprise_fee_id', selected: distributor.enterprise_fees.first.name + end + + private + + def wait_for_edit_form_to_load_order_cycle(order_cycle) + expect(page).to have_field "order_cycle_name", with: order_cycle.name + end +end diff --git a/spec/features/admin/order_cycles/complex_updating_specific_time_spec.rb b/spec/features/admin/order_cycles/complex_updating_specific_time_spec.rb new file mode 100644 index 0000000000..2e569fc0ce --- /dev/null +++ b/spec/features/admin/order_cycles/complex_updating_specific_time_spec.rb @@ -0,0 +1,166 @@ +require 'spec_helper' + +feature ' + As an administrator + I want to create/update complex order cycles with a specific time +', js: true do + include AdminHelper + include AuthenticationWorkflow + include WebHelper + + let(:order_cycle_opening_time) { Time.zone.local(2040, 11, 0o6, 0o6, 0o0, 0o0).strftime("%F %T %z") } + let(:order_cycle_closing_time) { Time.zone.local(2040, 11, 13, 17, 0o0, 0o0).strftime("%F %T %z") } + + scenario "updating an order cycle", js: true do + # Given an order cycle with all the settings + oc = create(:order_cycle) + initial_variants = oc.variants.sort_by(&:id) + + # And a coordinating, supplying and distributing enterprise with some products with variants + coordinator = oc.coordinator + supplier = create(:supplier_enterprise, name: 'My supplier') + distributor = create(:distributor_enterprise, name: 'My distributor', with_payment_and_shipping: true) + product = create(:product, supplier: supplier) + v1 = create(:variant, product: product) + v2 = create(:variant, product: product) + + # Relationships required for interface to work + create(:enterprise_relationship, parent: supplier, child: coordinator, permissions_list: [:add_to_order_cycle]) + create(:enterprise_relationship, parent: distributor, child: coordinator, permissions_list: [:add_to_order_cycle]) + create(:enterprise_relationship, parent: supplier, child: distributor, permissions_list: [:add_to_order_cycle]) + + # And some enterprise fees + supplier_fee1 = create(:enterprise_fee, enterprise: supplier, name: 'Supplier fee 1') + supplier_fee2 = create(:enterprise_fee, enterprise: supplier, name: 'Supplier fee 2') + coordinator_fee1 = create(:enterprise_fee, enterprise: coordinator, name: 'Coord fee 1') + coordinator_fee2 = create(:enterprise_fee, enterprise: coordinator, name: 'Coord fee 2') + distributor_fee1 = create(:enterprise_fee, enterprise: distributor, name: 'Distributor fee 1') + distributor_fee2 = create(:enterprise_fee, enterprise: distributor, name: 'Distributor fee 2') + + # When I go to its edit page + quick_login_as_admin + visit admin_order_cycles_path + within "tr.order-cycle-#{oc.id}" do + find("a.edit-order-cycle").click + end + + wait_for_edit_form_to_load_order_cycle(oc) + + # And I update it + fill_in 'order_cycle_name', with: 'Plums & Avos' + fill_in 'order_cycle_orders_open_at', with: order_cycle_opening_time + fill_in 'order_cycle_orders_close_at', with: order_cycle_closing_time + + # And I configure some coordinator fees + click_button 'Add coordinator fee' + select 'Coord fee 1', from: 'order_cycle_coordinator_fee_0_id' + click_button 'Add coordinator fee' + click_button 'Add coordinator fee' + click_link 'order_cycle_coordinator_fee_2_remove' + select 'Coord fee 2', from: 'order_cycle_coordinator_fee_1_id' + + click_button 'Save and Next' + expect(page).to have_content 'Your order cycle has been updated.' + + # And I add a supplier and some products + expect(page).to have_selector("table.exchanges tr.supplier") + select 'My supplier', from: 'new_supplier_id' + click_button 'Add supplier' + expect(page).to have_selector("table.exchanges tr.supplier", text: "My supplier") + page.all("table.exchanges tr.supplier td.products").each(&:click) + + expect(page).to have_selector "#order_cycle_incoming_exchange_1_variants_#{initial_variants.last.id}", visible: true + page.find("#order_cycle_incoming_exchange_1_variants_#{initial_variants.last.id}", visible: true).click # uncheck (with visible:true filter) + check "order_cycle_incoming_exchange_2_variants_#{v1.id}" + check "order_cycle_incoming_exchange_2_variants_#{v2.id}" + + # And I configure some supplier fees + within("tr.supplier-#{supplier.id}") { click_button 'Add fee' } + select 'My supplier', from: 'order_cycle_incoming_exchange_2_enterprise_fees_0_enterprise_id' + select 'Supplier fee 1', from: 'order_cycle_incoming_exchange_2_enterprise_fees_0_enterprise_fee_id' + within("tr.supplier-#{supplier.id}") { click_button 'Add fee' } + within("tr.supplier-#{supplier.id}") { click_button 'Add fee' } + click_link 'order_cycle_incoming_exchange_2_enterprise_fees_0_remove' + select 'My supplier', from: 'order_cycle_incoming_exchange_2_enterprise_fees_0_enterprise_id' + select 'Supplier fee 2', from: 'order_cycle_incoming_exchange_2_enterprise_fees_0_enterprise_fee_id' + + click_button 'Save and Next' + + # And I add a distributor and some products + select 'My distributor', from: 'new_distributor_id' + click_button 'Add distributor' + expect(page).to have_field("order_cycle_outgoing_exchange_2_pickup_time") + + fill_in 'order_cycle_outgoing_exchange_0_pickup_time', with: 'New time 0' + fill_in 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'New instructions 0' + fill_in 'order_cycle_outgoing_exchange_1_pickup_time', with: 'New time 1' + fill_in 'order_cycle_outgoing_exchange_1_pickup_instructions', with: 'New instructions 1' + fill_in 'order_cycle_outgoing_exchange_2_pickup_time', with: 'New time 2' + fill_in 'order_cycle_outgoing_exchange_2_pickup_instructions', with: 'New instructions 2' + + page.find("table.exchanges tr.distributor-#{distributor.id} td.tags").click + within ".exchange-tags" do + find(:css, "tags-input .tags input").set "wholesale\n" + end + + exchange_rows = page.all("table.exchanges tbody") + exchange_rows.each do |exchange_row| + exchange_row.find("td.products").click + # Wait for the products panel to be visible. + expect(exchange_row).to have_selector "tr", count: 2 + end + + uncheck "order_cycle_outgoing_exchange_2_variants_#{v1.id}" + check "order_cycle_outgoing_exchange_2_variants_#{v2.id}" + + # And I configure some distributor fees + within("tr.distributor-#{distributor.id}") { click_button 'Add fee' } + select 'My distributor', from: 'order_cycle_outgoing_exchange_2_enterprise_fees_0_enterprise_id' + select 'Distributor fee 1', from: 'order_cycle_outgoing_exchange_2_enterprise_fees_0_enterprise_fee_id' + within("tr.distributor-#{distributor.id}") { click_button 'Add fee' } + within("tr.distributor-#{distributor.id}") { click_button 'Add fee' } + click_link 'order_cycle_outgoing_exchange_2_enterprise_fees_0_remove' + select 'My distributor', from: 'order_cycle_outgoing_exchange_2_enterprise_fees_0_enterprise_id' + select 'Distributor fee 2', from: 'order_cycle_outgoing_exchange_2_enterprise_fees_0_enterprise_fee_id' + + expect(page).to have_selector "#save-bar" + click_button 'Save and Back to List' + + oc = OrderCycle.last + toggle_columns "Producers", "Shops" + + expect(page).to have_input "oc#{oc.id}[name]", value: "Plums & Avos" + expect(page).to have_input "oc#{oc.id}[orders_open_at]", value: order_cycle_opening_time + expect(page).to have_input "oc#{oc.id}[orders_close_at]", value: order_cycle_closing_time + expect(page).to have_content coordinator.name + + expect(page).to have_selector 'td.producers', text: 'My supplier' + expect(page).to have_selector 'td.shops', text: 'My distributor' + + # And my coordinator fees should have been configured + expect(oc.coordinator_fee_ids).to match_array [coordinator_fee1.id, coordinator_fee2.id] + + # And my supplier fees should have been configured + expect(oc.exchanges.incoming.last.enterprise_fee_ids).to eq([supplier_fee2.id]) + + # And my distributor fees should have been configured + expect(oc.exchanges.outgoing.last.enterprise_fee_ids).to eq([distributor_fee2.id]) + + # And my tags should have been save + expect(oc.exchanges.outgoing.last.tag_list).to eq(['wholesale']) + + # And it should have some variants selected + selected_initial_variants = initial_variants.take initial_variants.size - 1 + expect(oc.variants.map(&:id)).to match_array((selected_initial_variants.map(&:id) + [v1.id, v2.id])) + + # And the collection details should have been updated + expect(oc.exchanges.where(pickup_time: 'New time 0', pickup_instructions: 'New instructions 0')).to be_present + expect(oc.exchanges.where(pickup_time: 'New time 1', pickup_instructions: 'New instructions 1')).to be_present + end + + private + + def wait_for_edit_form_to_load_order_cycle(order_cycle) + expect(page).to have_field "order_cycle_name", with: order_cycle.name + end +end diff --git a/spec/features/admin/order_cycles/list_spec.rb b/spec/features/admin/order_cycles/list_spec.rb new file mode 100644 index 0000000000..ba5f2d4048 --- /dev/null +++ b/spec/features/admin/order_cycles/list_spec.rb @@ -0,0 +1,162 @@ +require 'spec_helper' + +feature ' + As an administrator + I want to list and filter order cycles +', js: true do + include AdminHelper + include AuthenticationWorkflow + include WebHelper + + scenario "listing and filtering order cycles" do + # Given some order cycles (created in an arbitrary order) + oc4 = create(:simple_order_cycle, name: 'oc4', + orders_open_at: 2.days.from_now, orders_close_at: 1.month.from_now) + oc2 = create(:simple_order_cycle, name: 'oc2', orders_close_at: 1.month.from_now) + oc6 = create(:simple_order_cycle, name: 'oc6', + orders_open_at: 1.month.ago, orders_close_at: 3.weeks.ago) + oc3 = create(:simple_order_cycle, name: 'oc3', + orders_open_at: 1.day.from_now, orders_close_at: 1.month.from_now) + oc5 = create(:simple_order_cycle, name: 'oc5', + orders_open_at: 1.month.ago, orders_close_at: 2.weeks.ago) + oc1 = create(:order_cycle, name: 'oc1') + oc0 = create(:simple_order_cycle, name: 'oc0', + orders_open_at: nil, orders_close_at: nil) + oc7 = create(:simple_order_cycle, name: 'oc7', + orders_open_at: 2.months.ago, orders_close_at: 5.weeks.ago) + schedule1 = create(:schedule, name: 'Schedule1', order_cycles: [oc1, oc3]) + create(:proxy_order, subscription: create(:subscription, schedule: schedule1), order_cycle: oc1) + + # When I go to the admin order cycles page + login_to_admin_section + click_link 'Order Cycles' + + # Then the order cycles should be ordered correctly + expect(page).to have_selector "#listing_order_cycles tr td:first-child", count: 7 + + order_cycle_names = ["oc0", "oc1", "oc2", "oc3", "oc4", "oc5", "oc6"] + expect(all("#listing_order_cycles tr td:first-child input").map(&:value)).to eq order_cycle_names + + # And the rows should have the correct classes + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}.undated" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}.open" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}.open" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc3.id}.upcoming" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc4.id}.upcoming" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc5.id}.closed" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc6.id}.closed" + + toggle_columns "Producers", "Shops" + + # And I should see all the details for an order cycle + within('table#listing_order_cycles tbody tr:nth-child(2)') do + # Then I should see the basic fields + expect(page).to have_input "oc#{oc1.id}[name]", value: oc1.name + expect(page).to have_input "oc#{oc1.id}[orders_open_at]", value: oc1.orders_open_at + expect(page).to have_input "oc#{oc1.id}[orders_close_at]", value: oc1.orders_close_at + expect(page).to have_content oc1.coordinator.name + + # And I should see the suppliers and distributors + oc1.suppliers.each { |s| expect(page).to have_content s.name } + oc1.distributors.each { |d| expect(page).to have_content d.name } + + # And I should see the number of variants + expect(page).to have_selector 'td.products', text: '2 variants' + end + + # I can load more order_cycles + expect(page).to have_no_selector "#listing_order_cycles tr.order-cycle-#{oc7.id}" + click_button "Show 30 more days" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc7.id}" + + # I can filter order cycle by involved enterprises + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" + select2_select oc1.suppliers.first.name, from: "involving_filter" + expect(page).to have_no_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" + expect(page).to have_no_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" + select2_select "Any Enterprise", from: "involving_filter" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" + + # I can filter order cycles by name + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" + fill_in "query", with: oc0.name + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" + expect(page).to have_no_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" + expect(page).to have_no_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" + fill_in "query", with: '' + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" + + # I can filter order cycle by schedule + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc3.id}" + select2_select schedule1.name, from: "schedule_filter" + expect(page).to have_no_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" + expect(page).to have_no_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc3.id}" + select2_select 'Any Schedule', from: "schedule_filter" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" + expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc3.id}" + + # Attempting to edit dates of an open order cycle with active subscriptions + find("#oc#{oc1.id}_orders_open_at").click + expect(page).to have_selector "#confirm-dialog .message", text: I18n.t('admin.order_cycles.date_warning.msg', n: 1) + end + + describe 'listing order cycles with other locales' do + let!(:oc_pt) { create(:simple_order_cycle, name: 'oc', orders_open_at: '2012-01-01 00:00') } + + around(:each) do |spec| + I18n.locale = :pt + spec.run + I18n.locale = :en + end + + context 'using datepickers' do + it "correctly opens the datepicker and changes the date field" do + quick_login_as_admin + visit admin_order_cycles_path + + within("tr.order-cycle-#{oc_pt.id}") do + expect(find('input.datetimepicker', match: :first).value).to start_with '2012-01-01 00:00' + find('img.ui-datepicker-trigger', match: :first).click + end + + within("#ui-datepicker-div") do + expect(page).to have_selector 'a.ui-state-active', text: '1' + + click_link '30' + find('button.ui-datepicker-close', match: :first).click + end + + within("tr.order-cycle-#{oc_pt.id}") do + expect(find('input.datetimepicker', match: :first).value).to eq '2012-01-30 00:00' + end + end + end + end + + private + + def wait_for_edit_form_to_load_order_cycle(order_cycle) + expect(page).to have_field "order_cycle_name", with: order_cycle.name + end + + def select_incoming_variant(supplier, exchange_no, variant) + page.find("table.exchanges tr.supplier-#{supplier.id} td.products").click + check "order_cycle_incoming_exchange_#{exchange_no}_variants_#{variant.id}" + end +end diff --git a/spec/features/admin/order_cycles_spec.rb b/spec/features/admin/order_cycles/simple_spec.rb similarity index 51% rename from spec/features/admin/order_cycles_spec.rb rename to spec/features/admin/order_cycles/simple_spec.rb index 0da5f07c6d..979dc0be8b 100644 --- a/spec/features/admin/order_cycles_spec.rb +++ b/spec/features/admin/order_cycles/simple_spec.rb @@ -2,570 +2,12 @@ require 'spec_helper' feature ' As an administrator - I want to manage order cycles + I want to manage simple order cycles ', js: true do include AdminHelper include AuthenticationWorkflow include WebHelper - scenario "listing and filtering order cycles" do - # Given some order cycles (created in an arbitrary order) - oc4 = create(:simple_order_cycle, name: 'oc4', - orders_open_at: 2.days.from_now, orders_close_at: 1.month.from_now) - oc2 = create(:simple_order_cycle, name: 'oc2', orders_close_at: 1.month.from_now) - oc6 = create(:simple_order_cycle, name: 'oc6', - orders_open_at: 1.month.ago, orders_close_at: 3.weeks.ago) - oc3 = create(:simple_order_cycle, name: 'oc3', - orders_open_at: 1.day.from_now, orders_close_at: 1.month.from_now) - oc5 = create(:simple_order_cycle, name: 'oc5', - orders_open_at: 1.month.ago, orders_close_at: 2.weeks.ago) - oc1 = create(:order_cycle, name: 'oc1') - oc0 = create(:simple_order_cycle, name: 'oc0', - orders_open_at: nil, orders_close_at: nil) - oc7 = create(:simple_order_cycle, name: 'oc7', - orders_open_at: 2.months.ago, orders_close_at: 5.weeks.ago) - schedule1 = create(:schedule, name: 'Schedule1', order_cycles: [oc1, oc3]) - create(:proxy_order, subscription: create(:subscription, schedule: schedule1), order_cycle: oc1) - - # When I go to the admin order cycles page - login_to_admin_section - click_link 'Order Cycles' - - # Then the order cycles should be ordered correctly - expect(page).to have_selector "#listing_order_cycles tr td:first-child", count: 7 - - order_cycle_names = ["oc0", "oc1", "oc2", "oc3", "oc4", "oc5", "oc6"] - expect(all("#listing_order_cycles tr td:first-child input").map(&:value)).to eq order_cycle_names - - # And the rows should have the correct classes - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}.undated" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}.open" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}.open" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc3.id}.upcoming" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc4.id}.upcoming" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc5.id}.closed" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc6.id}.closed" - - toggle_columns "Producers", "Shops" - - # And I should see all the details for an order cycle - within('table#listing_order_cycles tbody tr:nth-child(2)') do - # Then I should see the basic fields - expect(page).to have_input "oc#{oc1.id}[name]", value: oc1.name - expect(page).to have_input "oc#{oc1.id}[orders_open_at]", value: oc1.orders_open_at - expect(page).to have_input "oc#{oc1.id}[orders_close_at]", value: oc1.orders_close_at - expect(page).to have_content oc1.coordinator.name - - # And I should see the suppliers and distributors - oc1.suppliers.each { |s| expect(page).to have_content s.name } - oc1.distributors.each { |d| expect(page).to have_content d.name } - - # And I should see the number of variants - expect(page).to have_selector 'td.products', text: '2 variants' - end - - # I can load more order_cycles - expect(page).to have_no_selector "#listing_order_cycles tr.order-cycle-#{oc7.id}" - click_button "Show 30 more days" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc7.id}" - - # I can filter order cycle by involved enterprises - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" - select2_select oc1.suppliers.first.name, from: "involving_filter" - expect(page).to have_no_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" - expect(page).to have_no_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" - select2_select "Any Enterprise", from: "involving_filter" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" - - # I can filter order cycles by name - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" - fill_in "query", with: oc0.name - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" - expect(page).to have_no_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" - expect(page).to have_no_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" - fill_in "query", with: '' - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" - - # I can filter order cycle by schedule - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc3.id}" - select2_select schedule1.name, from: "schedule_filter" - expect(page).to have_no_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" - expect(page).to have_no_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc3.id}" - select2_select 'Any Schedule', from: "schedule_filter" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc0.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc1.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc2.id}" - expect(page).to have_selector "#listing_order_cycles tr.order-cycle-#{oc3.id}" - - # Attempting to edit dates of an open order cycle with active subscriptions - find("#oc#{oc1.id}_orders_open_at").click - expect(page).to have_selector "#confirm-dialog .message", text: I18n.t('admin.order_cycles.date_warning.msg', n: 1) - end - - describe 'listing order cycles with other locales' do - let!(:oc_de) { create(:simple_order_cycle, name: 'oc', orders_open_at: '2012-01-01 00:00') } - - around(:each) do |spec| - I18n.locale = :de - spec.run - I18n.locale = :en - end - - context 'using datepickers' do - it "correctly opens the datepicker and changes the date field" do - quick_login_as_admin - visit admin_order_cycles_path - - within("tr.order-cycle-#{oc_de.id}") do - expect(find('input.datetimepicker', match: :first).value).to start_with '2012-01-01 00:00' - find('img.ui-datepicker-trigger', match: :first).click - end - - within("#ui-datepicker-div") do - expect(page).to have_selector 'a.ui-state-active', text: '1' - - click_link '30' - find('button.ui-datepicker-close', match: :first).click - end - - within("tr.order-cycle-#{oc_de.id}") do - expect(find('input.datetimepicker', match: :first).value).to eq '2012-01-30 00:00' - end - end - end - end - - context "with specific time" do - let(:order_cycle_opening_time) { Time.zone.local(2040, 11, 0o6, 0o6, 0o0, 0o0).strftime("%F %T %z") } - let(:order_cycle_closing_time) { Time.zone.local(2040, 11, 13, 17, 0o0, 0o0).strftime("%F %T %z") } - - scenario "creating an order cycle with full interface", js: true do - # Given coordinating, supplying and distributing enterprises with some products with variants - coordinator = create(:distributor_enterprise, name: 'My coordinator') - supplier = create(:supplier_enterprise, name: 'My supplier') - product = create(:product, supplier: supplier) - v1 = create(:variant, product: product) - v2 = create(:variant, product: product) - distributor = create(:distributor_enterprise, name: 'My distributor', with_payment_and_shipping: true) - - # Relationships required for interface to work - create(:enterprise_relationship, parent: supplier, child: coordinator, permissions_list: [:add_to_order_cycle]) - create(:enterprise_relationship, parent: distributor, child: coordinator, permissions_list: [:add_to_order_cycle]) - create(:enterprise_relationship, parent: supplier, child: distributor, permissions_list: [:add_to_order_cycle]) - - # And some enterprise fees - supplier_fee = create(:enterprise_fee, enterprise: supplier, name: 'Supplier fee') - coordinator_fee = create(:enterprise_fee, enterprise: coordinator, name: 'Coord fee') - distributor_fee = create(:enterprise_fee, enterprise: distributor, name: 'Distributor fee') - - # When I go to the new order cycle page - quick_login_as_admin - visit admin_order_cycles_path - click_link 'New Order Cycle' - - # Select a coordinator since there are two available - select2_select 'My coordinator', from: 'coordinator_id' - click_button "Continue >" - - # I cannot save before filling in the required fields - expect(page).to have_button("Create", disabled: true) - - # The Create button is enabled once Name is entered - fill_in 'order_cycle_name', with: 'Plums & Avos' - expect(page).to have_button("Create", disabled: false) - - # If I fill in the basic fields - fill_in 'order_cycle_orders_open_at', with: order_cycle_opening_time - fill_in 'order_cycle_orders_close_at', with: order_cycle_closing_time - - # And I add a coordinator fee - click_button 'Add coordinator fee' - select 'Coord fee', from: 'order_cycle_coordinator_fee_0_id' - - click_button 'Create' - expect(page).to have_content 'Your order cycle has been created.' - - # I should not be able to add a blank supplier - expect(page).to have_select 'new_supplier_id', selected: '' - expect(page).to have_button 'Add supplier', disabled: true - - # And I add a supplier and some products - select 'My supplier', from: 'new_supplier_id' - click_button 'Add supplier' - fill_in 'order_cycle_incoming_exchange_0_receival_instructions', with: 'receival instructions' - page.find('table.exchanges tr.supplier td.products').click - check "order_cycle_incoming_exchange_0_variants_#{v1.id}" - check "order_cycle_incoming_exchange_0_variants_#{v2.id}" - - # I should not be able to re-add the supplier - expect(page).not_to have_select 'new_supplier_id', with_options: ['My supplier'] - expect(page).to have_button 'Add supplier', disabled: true - expect(page.all("td.supplier_name").map(&:text)).to eq(['My supplier']) - - # And I add a supplier fee - within("tr.supplier-#{supplier.id}") { click_button 'Add fee' } - select 'My supplier', from: 'order_cycle_incoming_exchange_0_enterprise_fees_0_enterprise_id' - select 'Supplier fee', from: 'order_cycle_incoming_exchange_0_enterprise_fees_0_enterprise_fee_id' - - click_button 'Save and Next' - - # And I add a distributor with the same products - select 'My distributor', from: 'new_distributor_id' - click_button 'Add distributor' - - fill_in 'order_cycle_outgoing_exchange_0_pickup_time', with: 'pickup time' - fill_in 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'pickup instructions' - - page.find('table.exchanges tr.distributor td.products').click - check "order_cycle_outgoing_exchange_0_variants_#{v1.id}" - check "order_cycle_outgoing_exchange_0_variants_#{v2.id}" - - page.find('table.exchanges tr.distributor td.tags').click - within ".exchange-tags" do - find(:css, "tags-input .tags input").set "wholesale\n" - end - - # And I add a distributor fee - within("tr.distributor-#{distributor.id}") { click_button 'Add fee' } - select 'My distributor', from: 'order_cycle_outgoing_exchange_0_enterprise_fees_0_enterprise_id' - select 'Distributor fee', from: 'order_cycle_outgoing_exchange_0_enterprise_fees_0_enterprise_fee_id' - - click_button 'Save and Back to List' - - oc = OrderCycle.last - toggle_columns "Producers", "Shops" - - expect(page).to have_input "oc#{oc.id}[name]", value: "Plums & Avos" - expect(page).to have_input "oc#{oc.id}[orders_open_at]", value: order_cycle_opening_time - expect(page).to have_input "oc#{oc.id}[orders_close_at]", value: order_cycle_closing_time - expect(page).to have_content "My coordinator" - - expect(page).to have_selector 'td.producers', text: 'My supplier' - expect(page).to have_selector 'td.shops', text: 'My distributor' - - # And it should have some fees - expect(oc.exchanges.incoming.first.enterprise_fees).to eq([supplier_fee]) - expect(oc.coordinator_fees).to eq([coordinator_fee]) - expect(oc.exchanges.outgoing.first.enterprise_fees).to eq([distributor_fee]) - - # And it should have some variants selected - expect(oc.exchanges.first.variants.count).to eq(2) - expect(oc.exchanges.last.variants.count).to eq(2) - - # And my receival and pickup time and instructions should have been saved - exchange = oc.exchanges.incoming.first - expect(exchange.receival_instructions).to eq('receival instructions') - - exchange = oc.exchanges.outgoing.first - expect(exchange.pickup_time).to eq('pickup time') - expect(exchange.pickup_instructions).to eq('pickup instructions') - expect(exchange.tag_list).to eq(['wholesale']) - end - - scenario "updating an order cycle", js: true do - # Given an order cycle with all the settings - oc = create(:order_cycle) - initial_variants = oc.variants.sort_by(&:id) - - # And a coordinating, supplying and distributing enterprise with some products with variants - coordinator = oc.coordinator - supplier = create(:supplier_enterprise, name: 'My supplier') - distributor = create(:distributor_enterprise, name: 'My distributor', with_payment_and_shipping: true) - product = create(:product, supplier: supplier) - v1 = create(:variant, product: product) - v2 = create(:variant, product: product) - - # Relationships required for interface to work - create(:enterprise_relationship, parent: supplier, child: coordinator, permissions_list: [:add_to_order_cycle]) - create(:enterprise_relationship, parent: distributor, child: coordinator, permissions_list: [:add_to_order_cycle]) - create(:enterprise_relationship, parent: supplier, child: distributor, permissions_list: [:add_to_order_cycle]) - - # And some enterprise fees - supplier_fee1 = create(:enterprise_fee, enterprise: supplier, name: 'Supplier fee 1') - supplier_fee2 = create(:enterprise_fee, enterprise: supplier, name: 'Supplier fee 2') - coordinator_fee1 = create(:enterprise_fee, enterprise: coordinator, name: 'Coord fee 1') - coordinator_fee2 = create(:enterprise_fee, enterprise: coordinator, name: 'Coord fee 2') - distributor_fee1 = create(:enterprise_fee, enterprise: distributor, name: 'Distributor fee 1') - distributor_fee2 = create(:enterprise_fee, enterprise: distributor, name: 'Distributor fee 2') - - # When I go to its edit page - quick_login_as_admin - visit admin_order_cycles_path - within "tr.order-cycle-#{oc.id}" do - find("a.edit-order-cycle").click - end - - wait_for_edit_form_to_load_order_cycle(oc) - - # And I update it - fill_in 'order_cycle_name', with: 'Plums & Avos' - fill_in 'order_cycle_orders_open_at', with: order_cycle_opening_time - fill_in 'order_cycle_orders_close_at', with: order_cycle_closing_time - - # And I configure some coordinator fees - click_button 'Add coordinator fee' - select 'Coord fee 1', from: 'order_cycle_coordinator_fee_0_id' - click_button 'Add coordinator fee' - click_button 'Add coordinator fee' - click_link 'order_cycle_coordinator_fee_2_remove' - select 'Coord fee 2', from: 'order_cycle_coordinator_fee_1_id' - - click_button 'Save and Next' - expect(page).to have_content 'Your order cycle has been updated.' - - # And I add a supplier and some products - expect(page).to have_selector("table.exchanges tr.supplier") - select 'My supplier', from: 'new_supplier_id' - click_button 'Add supplier' - expect(page).to have_selector("table.exchanges tr.supplier", text: "My supplier") - page.all("table.exchanges tr.supplier td.products").each(&:click) - - - expect(page).to have_selector "#order_cycle_incoming_exchange_1_variants_#{initial_variants.last.id}", visible: true - page.find("#order_cycle_incoming_exchange_1_variants_#{initial_variants.last.id}", visible: true).click # uncheck (with visible:true filter) - check "order_cycle_incoming_exchange_2_variants_#{v1.id}" - check "order_cycle_incoming_exchange_2_variants_#{v2.id}" - - # And I configure some supplier fees - within("tr.supplier-#{supplier.id}") { click_button 'Add fee' } - select 'My supplier', from: 'order_cycle_incoming_exchange_2_enterprise_fees_0_enterprise_id' - select 'Supplier fee 1', from: 'order_cycle_incoming_exchange_2_enterprise_fees_0_enterprise_fee_id' - within("tr.supplier-#{supplier.id}") { click_button 'Add fee' } - within("tr.supplier-#{supplier.id}") { click_button 'Add fee' } - click_link 'order_cycle_incoming_exchange_2_enterprise_fees_0_remove' - select 'My supplier', from: 'order_cycle_incoming_exchange_2_enterprise_fees_0_enterprise_id' - select 'Supplier fee 2', from: 'order_cycle_incoming_exchange_2_enterprise_fees_0_enterprise_fee_id' - - click_button 'Save and Next' - - # And I add a distributor and some products - select 'My distributor', from: 'new_distributor_id' - click_button 'Add distributor' - expect(page).to have_field("order_cycle_outgoing_exchange_2_pickup_time") - - fill_in 'order_cycle_outgoing_exchange_0_pickup_time', with: 'New time 0' - fill_in 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'New instructions 0' - fill_in 'order_cycle_outgoing_exchange_1_pickup_time', with: 'New time 1' - fill_in 'order_cycle_outgoing_exchange_1_pickup_instructions', with: 'New instructions 1' - fill_in 'order_cycle_outgoing_exchange_2_pickup_time', with: 'New time 2' - fill_in 'order_cycle_outgoing_exchange_2_pickup_instructions', with: 'New instructions 2' - - page.find("table.exchanges tr.distributor-#{distributor.id} td.tags").click - within ".exchange-tags" do - find(:css, "tags-input .tags input").set "wholesale\n" - end - - exchange_rows = page.all("table.exchanges tbody") - exchange_rows.each do |exchange_row| - exchange_row.find("td.products").click - # Wait for the products panel to be visible. - expect(exchange_row).to have_selector "tr", count: 2 - end - - uncheck "order_cycle_outgoing_exchange_2_variants_#{v1.id}" - check "order_cycle_outgoing_exchange_2_variants_#{v2.id}" - - # And I configure some distributor fees - within("tr.distributor-#{distributor.id}") { click_button 'Add fee' } - select 'My distributor', from: 'order_cycle_outgoing_exchange_2_enterprise_fees_0_enterprise_id' - select 'Distributor fee 1', from: 'order_cycle_outgoing_exchange_2_enterprise_fees_0_enterprise_fee_id' - within("tr.distributor-#{distributor.id}") { click_button 'Add fee' } - within("tr.distributor-#{distributor.id}") { click_button 'Add fee' } - click_link 'order_cycle_outgoing_exchange_2_enterprise_fees_0_remove' - select 'My distributor', from: 'order_cycle_outgoing_exchange_2_enterprise_fees_0_enterprise_id' - select 'Distributor fee 2', from: 'order_cycle_outgoing_exchange_2_enterprise_fees_0_enterprise_fee_id' - - expect(page).to have_selector "#save-bar" - click_button 'Save and Back to List' - - oc = OrderCycle.last - toggle_columns "Producers", "Shops" - - expect(page).to have_input "oc#{oc.id}[name]", value: "Plums & Avos" - expect(page).to have_input "oc#{oc.id}[orders_open_at]", value: order_cycle_opening_time - expect(page).to have_input "oc#{oc.id}[orders_close_at]", value: order_cycle_closing_time - expect(page).to have_content coordinator.name - - expect(page).to have_selector 'td.producers', text: 'My supplier' - expect(page).to have_selector 'td.shops', text: 'My distributor' - - # And my coordinator fees should have been configured - expect(oc.coordinator_fee_ids).to match_array [coordinator_fee1.id, coordinator_fee2.id] - - # And my supplier fees should have been configured - expect(oc.exchanges.incoming.last.enterprise_fee_ids).to eq([supplier_fee2.id]) - - # And my distributor fees should have been configured - expect(oc.exchanges.outgoing.last.enterprise_fee_ids).to eq([distributor_fee2.id]) - - # And my tags should have been save - expect(oc.exchanges.outgoing.last.tag_list).to eq(['wholesale']) - - # And it should have some variants selected - selected_initial_variants = initial_variants.take initial_variants.size - 1 - expect(oc.variants.map(&:id)).to match_array((selected_initial_variants.map(&:id) + [v1.id, v2.id])) - - # And the collection details should have been updated - expect(oc.exchanges.where(pickup_time: 'New time 0', pickup_instructions: 'New instructions 0')).to be_present - expect(oc.exchanges.where(pickup_time: 'New time 1', pickup_instructions: 'New instructions 1')).to be_present - end - end - - scenario "editing an order cycle" do - # Given an order cycle with all the settings - oc = create(:order_cycle) - oc.suppliers.first.update_attribute :name, 'AAA' - oc.suppliers.last.update_attribute :name, 'ZZZ' - oc.distributors.first.update_attribute :name, 'AAAA' - oc.distributors.last.update_attribute :name, 'ZZZZ' - - # When I edit it - quick_login_as_admin - visit edit_admin_order_cycle_path(oc) - - wait_for_edit_form_to_load_order_cycle(oc) - - # Then I should see the basic settings - expect(page.find('#order_cycle_name').value).to eq(oc.name) - expect(page.find('#order_cycle_orders_open_at').value).to eq(oc.orders_open_at.to_s) - expect(page.find('#order_cycle_orders_close_at').value).to eq(oc.orders_close_at.to_s) - expect(page).to have_content "COORDINATOR #{oc.coordinator.name}" - - click_button 'Next' - - # And I should see the suppliers - expect(page).to have_selector 'td.supplier_name', text: oc.suppliers.first.name - expect(page).to have_selector 'td.supplier_name', text: oc.suppliers.last.name - - expect(page).to have_field 'order_cycle_incoming_exchange_0_receival_instructions', with: 'instructions 0' - expect(page).to have_field 'order_cycle_incoming_exchange_1_receival_instructions', with: 'instructions 1' - - # And the suppliers should have products - page.all('table.exchanges tbody tr.supplier').each_with_index do |row, i| - row.find('td.products').click - - products_panel = page.all('table.exchanges tr.panel-row .exchange-supplied-products').select(&:visible?).first - expect(products_panel).to have_selector "input[name='order_cycle_incoming_exchange_#{i}_select_all_variants']" - - row.find('td.products').click - end - - # And the suppliers should have fees - supplier = oc.suppliers.min_by(&:name) - expect(page).to have_select 'order_cycle_incoming_exchange_0_enterprise_fees_0_enterprise_id', selected: supplier.name - expect(page).to have_select 'order_cycle_incoming_exchange_0_enterprise_fees_0_enterprise_fee_id', selected: supplier.enterprise_fees.first.name - - supplier = oc.suppliers.max_by(&:name) - expect(page).to have_select 'order_cycle_incoming_exchange_1_enterprise_fees_0_enterprise_id', selected: supplier.name - expect(page).to have_select 'order_cycle_incoming_exchange_1_enterprise_fees_0_enterprise_fee_id', selected: supplier.enterprise_fees.first.name - - click_button 'Next' - - # And I should see the distributors - expect(page).to have_selector 'td.distributor_name', text: oc.distributors.first.name - expect(page).to have_selector 'td.distributor_name', text: oc.distributors.last.name - - expect(page).to have_field 'order_cycle_outgoing_exchange_0_pickup_time', with: 'time 0' - expect(page).to have_field 'order_cycle_outgoing_exchange_0_pickup_instructions', with: 'instructions 0' - expect(page).to have_field 'order_cycle_outgoing_exchange_1_pickup_time', with: 'time 1' - expect(page).to have_field 'order_cycle_outgoing_exchange_1_pickup_instructions', with: 'instructions 1' - - # And the distributors should have products - page.all('table.exchanges tbody tr.distributor').each_with_index do |row, i| - row.find('td.products').click - - products_panel = page.all('table.exchanges tr.panel-row .exchange-distributed-products').select(&:visible?).first - expect(products_panel).to have_selector "input[name='order_cycle_outgoing_exchange_#{i}_select_all_variants']" - - row.find('td.products').click - end - - # And the distributors should have fees - distributor = oc.distributors.min_by(&:id) - expect(page).to have_select 'order_cycle_outgoing_exchange_0_enterprise_fees_0_enterprise_id', selected: distributor.name - expect(page).to have_select 'order_cycle_outgoing_exchange_0_enterprise_fees_0_enterprise_fee_id', selected: distributor.enterprise_fees.first.name - - distributor = oc.distributors.max_by(&:id) - expect(page).to have_select 'order_cycle_outgoing_exchange_1_enterprise_fees_0_enterprise_id', selected: distributor.name - expect(page).to have_select 'order_cycle_outgoing_exchange_1_enterprise_fees_0_enterprise_fee_id', selected: distributor.enterprise_fees.first.name - end - - scenario "editing an order cycle with an exchange between the same enterprise" do - c = create(:distributor_enterprise, is_primary_producer: true) - - # Given two order cycles, one with a mono-enterprise incoming exchange... - oc_incoming = create(:simple_order_cycle, suppliers: [c], coordinator: c) - - # And the other with a mono-enterprise outgoing exchange - oc_outgoing = create(:simple_order_cycle, coordinator: c, distributors: [c]) - - # When I edit the first order cycle, the exchange should appear as incoming - quick_login_as_admin - visit admin_order_cycle_incoming_path(oc_incoming) - expect(page).to have_selector 'table.exchanges tr.supplier' - visit admin_order_cycle_outgoing_path(oc_incoming) - expect(page).not_to have_selector 'table.exchanges tr.distributor' - - # And when I edit the second order cycle, the exchange should appear as outgoing - visit admin_order_cycle_outgoing_path(oc_outgoing) - expect(page).to have_selector 'table.exchanges tr.distributor' - visit admin_order_cycle_incoming_path(oc_outgoing) - expect(page).not_to have_selector 'table.exchanges tr.supplier' - end - - describe "editing an order cycle with multiple pages of products", js: true do - let(:order_cycle) { create(:order_cycle) } - let(:supplier_enterprise) { order_cycle.exchanges.incoming.first.sender } - let!(:new_product) { create(:product, supplier: supplier_enterprise) } - - before do - stub_const("Api::ExchangeProductsController::DEFAULT_PER_PAGE", 1) - - quick_login_as_admin - visit admin_order_cycle_incoming_path(order_cycle) - expect(page).to have_content "1 / 2 selected" - - page.find("tr.supplier-#{supplier_enterprise.id} td.products").click - expect(page).to have_selector ".exchange-product-details" - - expect(page).to have_content "1 of 2 Variants Loaded" - expect(page).to_not have_content new_product.name - end - - scenario "load all products" do - page.find(".exchange-load-all-variants a").click - - expect_all_products_loaded - end - - scenario "select all products" do - check "order_cycle_incoming_exchange_0_select_all_variants" - - expect_all_products_loaded - - expect(page).to have_checked_field "order_cycle_incoming_exchange_0_variants_#{new_product.variants.first.id}", disabled: false - end - - def expect_all_products_loaded - expect(page).to have_content new_product.name.upcase - expect(page).to have_content "2 of 2 Variants Loaded" - end - end - scenario "updating many order cycle opening/closing times at once", js: true do # Given three order cycles oc1 = create(:simple_order_cycle) @@ -787,7 +229,7 @@ feature ' end click_button 'Save and Back to List' - order_cycle = OrderCycle.find_by_name('My order cycle') + order_cycle = OrderCycle.find_by(name: 'My order cycle') expect(page).to have_input "oc#{order_cycle.id}[name]", value: order_cycle.name expect(order_cycle.suppliers).to match_array [supplier_managed, supplier_permitted] @@ -1171,4 +613,4 @@ feature ' page.find("table.exchanges tr.supplier-#{supplier.id} td.products").click check "order_cycle_incoming_exchange_#{exchange_no}_variants_#{variant.id}" end -end +end \ No newline at end of file diff --git a/spec/features/admin/order_spec.rb b/spec/features/admin/order_spec.rb index d9071aff94..934b7f02f9 100644 --- a/spec/features/admin/order_spec.rb +++ b/spec/features/admin/order_spec.rb @@ -158,6 +158,9 @@ feature ' 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' diff --git a/spec/features/admin/payment_method_spec.rb b/spec/features/admin/payment_method_spec.rb index 19ec0d151d..356c450611 100644 --- a/spec/features/admin/payment_method_spec.rb +++ b/spec/features/admin/payment_method_spec.rb @@ -26,7 +26,7 @@ feature ' expect(flash_message).to eq('Payment Method has been successfully created!') - payment_method = Spree::PaymentMethod.find_by_name('Cheque payment method') + payment_method = Spree::PaymentMethod.find_by(name: 'Cheque payment method') expect(payment_method.distributors).to eq([@distributors[0]]) end @@ -108,7 +108,7 @@ feature ' expect(first('tags-input .tag-list ti-tag-item')).to have_content "member" - payment_method = Spree::PaymentMethod.find_by_name('New PM Name') + payment_method = Spree::PaymentMethod.find_by(name: 'New PM Name') expect(payment_method.distributors).to include @distributors[1], @distributors[2] expect(payment_method.distributors).not_to include @distributors[0] expect(payment_method.type).to eq "Spree::Gateway::PayPalExpress" @@ -123,7 +123,7 @@ feature ' expect(page).to have_field 'Password', with: '' expect(first('tags-input .tag-list ti-tag-item')).to have_content "member" - payment_method = Spree::PaymentMethod.find_by_name('New PM Name') + payment_method = Spree::PaymentMethod.find_by(name: 'New PM Name') expect(payment_method.tag_list).to eq ["member"] expect(payment_method.preferences[:login]).to eq 'otherlogin' expect(payment_method.preferences[:password]).to eq 'secret' @@ -168,7 +168,7 @@ feature ' expect(flash_message).to eq('Payment Method has been successfully created!') expect(first('tags-input .tag-list ti-tag-item')).to have_content "local" - payment_method = Spree::PaymentMethod.find_by_name('Cheque payment method') + payment_method = Spree::PaymentMethod.find_by(name: 'Cheque payment method') expect(payment_method.distributors).to eq([distributor1]) expect(payment_method.tag_list).to eq(["local"]) end diff --git a/spec/features/admin/product_import_spec.rb b/spec/features/admin/product_import_spec.rb index b14122ce5d..e12f2db82c 100644 --- a/spec/features/admin/product_import_spec.rb +++ b/spec/features/admin/product_import_spec.rb @@ -60,8 +60,8 @@ feature "Product Import", js: true do expect(page).to have_selector '.created-count', text: '2' expect(page).to have_no_selector '.updated-count' - carrots = Spree::Product.find_by_name('Carrots') - potatoes = Spree::Product.find_by_name('Potatoes') + carrots = Spree::Product.find_by(name: 'Carrots') + potatoes = Spree::Product.find_by(name: 'Potatoes') expect(potatoes.supplier).to eq enterprise expect(potatoes.on_hand).to eq 6 expect(potatoes.price).to eq 6.50 @@ -127,7 +127,7 @@ feature "Product Import", js: true do expect(page).to have_selector '.created-count', text: '1' expect(page).to have_no_selector '.updated-count' - carrots = Spree::Product.find_by_name('Carrots') + carrots = Spree::Product.find_by(name: 'Carrots') expect(carrots.tax_category).to eq tax_category expect(carrots.shipping_category).to eq shipping_category end @@ -150,9 +150,9 @@ feature "Product Import", js: true do save_data - carrots = Spree::Product.find_by_name('Carrots') + carrots = Spree::Product.find_by(name: 'Carrots') expect(carrots.variants.first.import_date).to be_within(1.minute).of Time.zone.now - potatoes = Spree::Product.find_by_name('Potatoes') + potatoes = Spree::Product.find_by(name: 'Potatoes') expect(potatoes.variants.first.import_date).to be_within(1.minute).of Time.zone.now click_link I18n.t('admin.product_import.save_results.view_products') @@ -200,9 +200,9 @@ feature "Product Import", js: true do expect(page).to have_selector '.created-count', text: '1' expect(page).to have_selector '.reset-count', text: '3' - expect(Spree::Product.find_by_name('Carrots').on_hand).to eq 500 - expect(Spree::Product.find_by_name('Cabbage').on_hand).to eq 0 - expect(Spree::Product.find_by_name('Beans').on_hand).to eq 0 + expect(Spree::Product.find_by(name: 'Carrots').on_hand).to eq 500 + expect(Spree::Product.find_by(name: 'Cabbage').on_hand).to eq 0 + expect(Spree::Product.find_by(name: 'Beans').on_hand).to eq 0 end it "can save a new product and variant of that product at the same time, add variant to existing product" do @@ -229,12 +229,12 @@ feature "Product Import", js: true do save_data - small_bag = Spree::Variant.find_by_display_name('Small Bag') + small_bag = Spree::Variant.find_by(display_name: 'Small Bag') expect(small_bag.product.name).to eq 'Potatoes' expect(small_bag.price).to eq 3.50 expect(small_bag.on_hand).to eq 5 - big_bag = Spree::Variant.find_by_display_name('Big Bag') + big_bag = Spree::Variant.find_by(display_name: 'Big Bag') expect(big_bag.product.name).to eq 'Potatoes' expect(big_bag.price).to eq 5.50 expect(big_bag.on_hand).to eq 6 @@ -377,6 +377,24 @@ feature "Product Import", js: true do expect(page).to have_no_selector 'input[type=submit][value="Save"]' File.delete('/tmp/test.csv') end + + it "handles cases where files contain malformed data" do + csv_data = "name,producer,category,on_hand,price,units,unit_type,shipping_category\n" + csv_data += "Malformed \rBrocolli,#{enterprise.name},Vegetables,8,2.50,200,g,#{shipping_category.name}\n" + + File.write('/tmp/test.csv', csv_data) + + visit main_app.admin_product_import_path + attach_file 'file', '/tmp/test.csv' + click_button 'Upload' + + expect(page).to have_no_selector '.create-count' + expect(page).to have_no_selector '.update-count' + expect(page).to have_no_selector 'input[type=submit][value="Save"]' + expect(flash_message).to match(I18n.t('admin.product_import.model.malformed_csv', error_message: "")) + + File.delete('/tmp/test.csv') + end end describe "handling enterprise permissions" do @@ -453,9 +471,9 @@ feature "Product Import", js: true do expect_import_completed # Check that all rows are saved. - expect(producer.supplied_products.find_by_name("Imported Product 10")).to be_present - expect(producer.supplied_products.find_by_name("Imported Product 60")).to be_present - expect(producer.supplied_products.find_by_name("Imported Product 110")).to be_present + expect(producer.supplied_products.find_by(name: "Imported Product 10")).to be_present + expect(producer.supplied_products.find_by(name: "Imported Product 60")).to be_present + expect(producer.supplied_products.find_by(name: "Imported Product 110")).to be_present end end end diff --git a/spec/features/admin/products_spec.rb b/spec/features/admin/products_spec.rb index 54c99ba8ea..b2ef204312 100644 --- a/spec/features/admin/products_spec.rb +++ b/spec/features/admin/products_spec.rb @@ -48,7 +48,7 @@ feature ' expect(current_path).to eq spree.admin_products_path expect(flash_message).to eq('Product "A new product !!!" has been successfully created!') - product = Spree::Product.find_by_name('A new product !!!') + product = Spree::Product.find_by(name: 'A new product !!!') expect(product.supplier).to eq(@supplier) expect(product.variant_unit).to eq('weight') expect(product.variant_unit_scale).to eq(1000) @@ -86,7 +86,7 @@ feature ' click_button 'Create' expect(current_path).to eq spree.admin_products_path - product = Spree::Product.find_by_name('Hot Cakes') + product = Spree::Product.find_by(name: 'Hot Cakes') expect(product.variants.count).to eq(1) variant = product.variants.first expect(variant.on_demand).to be true @@ -131,7 +131,7 @@ feature ' click_button 'Create' expect(flash_message).to eq('Product "A new product !!!" has been successfully created!') - product = Spree::Product.find_by_name('A new product !!!') + product = Spree::Product.find_by(name: 'A new product !!!') expect(product.supplier).to eq(@supplier2) expect(product.tax_category).to be_nil end diff --git a/spec/features/admin/schedules_spec.rb b/spec/features/admin/schedules_spec.rb index c2d5c9e521..f017596e53 100644 --- a/spec/features/admin/schedules_spec.rb +++ b/spec/features/admin/schedules_spec.rb @@ -128,11 +128,11 @@ feature 'Schedules', js: true do expect(page).to have_no_selector "a", text: "Weekly" end - expect(Schedule.find_by_id(weekly_schedule.id)).to be_nil - expect(oc1.schedules).to eq [] - expect(oc2.schedules).to eq [] - expect(oc3.schedules).to eq [] - expect(oc4.schedules).to eq [] + expect(Schedule.find_by(id: weekly_schedule.id)).to be_nil + expect(oc1.reload.schedules).to eq [] + expect(oc2.reload.schedules).to eq [] + expect(oc3.reload.schedules).to eq [] + expect(oc4.reload.schedules).to eq [] end end end diff --git a/spec/features/admin/shipping_methods_spec.rb b/spec/features/admin/shipping_methods_spec.rb index 9a8a822d7f..84de423581 100644 --- a/spec/features/admin/shipping_methods_spec.rb +++ b/spec/features/admin/shipping_methods_spec.rb @@ -36,7 +36,7 @@ feature 'shipping methods' do expect(page).to have_no_button I18n.t("actions.create") # Then the shipping method should have its distributor set - message = "Shipping method \"Carrier Pidgeon\" has been successfully created!" + message = "Shipping Method \"Carrier Pidgeon\" has been successfully created!" expect(page).to have_flash_message message sm = Spree::ShippingMethod.last @@ -49,7 +49,7 @@ feature 'shipping methods' do scenario "deleting a shipping method" do visit_delete spree.admin_shipping_method_path(@shipping_method) - expect(page).to have_content "Shipping method \"#{@shipping_method.name}\" has been successfully removed!" + expect(page).to have_content "Shipping Method \"#{@shipping_method.name}\" has been successfully removed!" expect(Spree::ShippingMethod.where(id: @shipping_method.id)).to be_empty end @@ -126,11 +126,11 @@ feature 'shipping methods' do click_button I18n.t("actions.create") expect(page).to have_content I18n.t('spree.admin.shipping_methods.edit.editing_shipping_method') - expect(flash_message).to eq I18n.t('successfully_created', resource: 'Shipping method "Teleport"') + expect(flash_message).to eq I18n.t('successfully_created', resource: 'Shipping Method "Teleport"') expect(first('tags-input .tag-list ti-tag-item')).to have_content "local" - shipping_method = Spree::ShippingMethod.find_by_name('Teleport') + shipping_method = Spree::ShippingMethod.find_by(name: 'Teleport') expect(shipping_method.distributors).to eq([distributor1]) expect(shipping_method.tag_list).to eq(["local"]) end diff --git a/spec/features/admin/users_spec.rb b/spec/features/admin/users_spec.rb index c89df5380f..b97089a0aa 100644 --- a/spec/features/admin/users_spec.rb +++ b/spec/features/admin/users_spec.rb @@ -73,7 +73,7 @@ feature "Managing users" do end it "should allow to generate, regenarate and clear the user api key", js: true do - user = Spree::User.find_by_email("a@example.com") + user = Spree::User.find_by(email: "a@example.com") expect(page).to have_content "NO KEY" click_button "Generate API key" diff --git a/spec/features/admin/variant_overrides_spec.rb b/spec/features/admin/variant_overrides_spec.rb index 1869133774..5f48c35fd2 100644 --- a/spec/features/admin/variant_overrides_spec.rb +++ b/spec/features/admin/variant_overrides_spec.rb @@ -190,20 +190,24 @@ feature " end end - it "displays an error when unauthorised to access the page" do + xit "displays an error when unauthorised to access the page" do fill_in "variant-overrides-#{variant.id}-price", with: '777.77' fill_in "variant-overrides-#{variant.id}-count_on_hand", with: '123' expect(page).to have_content "Changes to one override remain unsaved." - user.enterprises.clear + # Set a user without suficient permissions + allow_any_instance_of(Spree::Admin::BaseController).to receive(:current_spree_user).and_return(build(:user)) expect do click_button 'Save Changes' + + # We need to wait_until because the save action is not fast enough for the have_content matcher + wait_until { page.find("#status-message").text != "Saving..." } expect(page).to have_content "I couldn't get authorisation to save those changes, so they remain unsaved." end.to change(VariantOverride, :count).by(0) end - it "displays an error when unauthorised to update a particular override" do + xit "displays an error when unauthorised to update a particular override" do fill_in "variant-overrides-#{variant_related.id}-price", with: '777.77' fill_in "variant-overrides-#{variant_related.id}-count_on_hand", with: '123' expect(page).to have_content "Changes to one override remain unsaved." diff --git a/spec/features/consumer/caching/darkwarm_caching_spec.rb b/spec/features/consumer/caching/darkwarm_caching_spec.rb index d32ebb8b9e..55f41aeee1 100644 --- a/spec/features/consumer/caching/darkwarm_caching_spec.rb +++ b/spec/features/consumer/caching/darkwarm_caching_spec.rb @@ -18,8 +18,8 @@ feature "Darkswarm data caching", js: true, caching: true do describe "caching injected taxons and properties" do it "caches taxons and properties" do - expect(Spree::Taxon).to receive(:all) { [taxon] } - expect(Spree::Property).to receive(:all) { [property] } + expect(Spree::Taxon).to receive(:all).at_least(:once).and_call_original + expect(Spree::Property).to receive(:all).at_least(:once).and_call_original visit shops_path @@ -29,14 +29,14 @@ feature "Darkswarm data caching", js: true, caching: true do visit shops_path end - xit "invalidates caches for taxons and properties" do + it "invalidates caches for taxons and properties" do visit shops_path taxon_timestamp1 = CacheService.latest_timestamp_by_class(Spree::Taxon) - expect_cached "views/#{CacheService::FragmentCaching.ams_all_taxons_key}" + expect_cached "views/#{CacheService::FragmentCaching.ams_all_taxons[0]}" property_timestamp1 = CacheService.latest_timestamp_by_class(Spree::Property) - expect_cached "views/#{CacheService::FragmentCaching.ams_all_properties_key}" + expect_cached "views/#{CacheService::FragmentCaching.ams_all_properties[0]}" toggle_filters @@ -45,19 +45,22 @@ feature "Darkswarm data caching", js: true, caching: true do expect(page).to have_content property.presentation end - taxon.update_attributes!(name: "Changed Taxon") - property.update_attributes!(presentation: "Changed Property") + taxon.update!(name: "Changed Taxon") + property.update!(presentation: "Changed Property") # Clear timed shops cache so we can test uncached supplied properties clear_shops_cache visit shops_path + # Wait for /shops page to load properly before checking for new timestamps + expect(page).to_not have_selector ".row.filter-row", visible: true + taxon_timestamp2 = CacheService.latest_timestamp_by_class(Spree::Taxon) - expect_cached "views/#{CacheService::FragmentCaching.ams_all_taxons_key}" + expect_cached "views/#{CacheService::FragmentCaching.ams_all_taxons[0]}" property_timestamp2 = CacheService.latest_timestamp_by_class(Spree::Property) - expect_cached "views/#{CacheService::FragmentCaching.ams_all_properties_key}" + expect_cached "views/#{CacheService::FragmentCaching.ams_all_properties[0]}" expect(taxon_timestamp1).to_not eq taxon_timestamp2 expect(property_timestamp1).to_not eq property_timestamp2 diff --git a/spec/features/consumer/caching/shops_caching_spec.rb b/spec/features/consumer/caching/shops_caching_spec.rb index 654a2f4524..c525e569d9 100644 --- a/spec/features/consumer/caching/shops_caching_spec.rb +++ b/spec/features/consumer/caching/shops_caching_spec.rb @@ -47,8 +47,8 @@ feature "Shops caching", js: true, caching: true do let(:exchange) { order_cycle.exchanges.to_enterprises(distributor).outgoing.first } let(:test_domain) { "#{Capybara.current_session.server.host}:#{Capybara.current_session.server.port}" } - let(:taxons_key) { "views/#{test_domain}/api/order_cycles/#{order_cycle.id}/taxons?distributor=#{distributor.id}" } - let(:properties_key) { "views/#{test_domain}/api/order_cycles/#{order_cycle.id}/properties?distributor=#{distributor.id}" } + let(:taxons_key) { "views/#{test_domain}/api/order_cycles/#{order_cycle.id}/taxons?distributor=#{distributor.id}.json" } + let(:properties_key) { "views/#{test_domain}/api/order_cycles/#{order_cycle.id}/properties?distributor=#{distributor.id}.json" } let(:options) { { expires_in: CacheService::FILTERS_EXPIRY } } before do diff --git a/spec/features/consumer/multilingual_spec.rb b/spec/features/consumer/multilingual_spec.rb index 4bf209361c..3e8a19f4d0 100644 --- a/spec/features/consumer/multilingual_spec.rb +++ b/spec/features/consumer/multilingual_spec.rb @@ -7,10 +7,10 @@ feature 'Multilingual', js: true do include UIComponentHelper include CookieHelper - it 'has two locales available' do + it 'has three locales available' do expect(Rails.application.config.i18n[:default_locale]).to eq 'en' expect(Rails.application.config.i18n[:locale]).to eq 'en' - expect(Rails.application.config.i18n[:available_locales]).to eq ['en', 'es'] + expect(Rails.application.config.i18n[:available_locales]).to eq ['en', 'es', 'pt'] end it '18n-js fallsback to default language' do # in backend it doesn't until we change enforce_available_locales to `true` diff --git a/spec/features/consumer/producers_spec.rb b/spec/features/consumer/producers_spec.rb index d58ebe1397..cf49db00df 100644 --- a/spec/features/consumer/producers_spec.rb +++ b/spec/features/consumer/producers_spec.rb @@ -22,10 +22,6 @@ feature ' let(:shop) { create(:distributor_enterprise) } let!(:er) { create(:enterprise_relationship, parent: shop, child: producer1) } - before :each do - use_api_as_unauthenticated_user - end - before do product1.set_property 'Organic', 'NASAA 12345' product2.set_property 'Biodynamic', 'ABC123' diff --git a/spec/features/consumer/registration_spec.rb b/spec/features/consumer/registration_spec.rb index dc0d42183c..ed0c2f96b1 100644 --- a/spec/features/consumer/registration_spec.rb +++ b/spec/features/consumer/registration_spec.rb @@ -10,9 +10,9 @@ feature "Registration", js: true do before do Spree::Config.enterprises_require_tos = false - albania = Spree::Country.create!({ name: "Albania", iso3: "ALB", iso: "AL", iso_name: "ALBANIA", numcode: "8" }, without_protection: true) - Spree::State.create!({ name: "Berat", abbr: "BRA", country: albania }, without_protection: true) - Spree::Country.create!({ name: "Chad", iso3: "TCD", iso: "TD", iso_name: "CHAD", numcode: "148" }, without_protection: true) + albania = Spree::Country.create!({ name: "Albania", iso3: "ALB", iso: "AL", iso_name: "ALBANIA", numcode: "8" }) + Spree::State.create!({ name: "Berat", abbr: "BRA", country: albania }) + Spree::Country.create!({ name: "Chad", iso3: "TCD", iso: "TD", iso_name: "CHAD", numcode: "148" }) end after do @@ -72,7 +72,7 @@ feature "Registration", js: true do expect(page).to have_content 'Nice one!' # Enterprise should be created - e = Enterprise.find_by_name('My Awesome Enterprise') + e = Enterprise.find_by(name: 'My Awesome Enterprise') expect(e.address.address1).to eq "123 Abc Street" expect(e.sells).to eq "unspecified" expect(e.is_primary_producer).to eq true @@ -124,6 +124,10 @@ feature "Registration", js: true do click_link "Go to Enterprise Dashboard" expect(page).to have_content "CHOOSE YOUR PACKAGE" + + page.find('.full_hub h3').click + click_button "Select and Continue" + expect(page).to have_content "Your profile live" end context "when the user has no more remaining enterprises" do diff --git a/spec/features/consumer/shopping/cart_spec.rb b/spec/features/consumer/shopping/cart_spec.rb index 9068504be6..e7785dcdb4 100644 --- a/spec/features/consumer/shopping/cart_spec.rb +++ b/spec/features/consumer/shopping/cart_spec.rb @@ -282,11 +282,6 @@ feature "full-page cart", js: true do expect(page).to have_no_content item1.variant.name expect(page).to have_content item2.variant.name - # open the dropdown cart and check there as well - find('#cart').click - expect(page).to have_no_content item1.variant.name - expect(page).to have_content item2.variant.name - visit main_app.cart_path find("td.toggle-bought").click diff --git a/spec/features/consumer/shopping/orders_spec.rb b/spec/features/consumer/shopping/orders_spec.rb index b9caaa7e75..2bb40d6dd5 100644 --- a/spec/features/consumer/shopping/orders_spec.rb +++ b/spec/features/consumer/shopping/orders_spec.rb @@ -24,18 +24,21 @@ feature "Order Management", js: true do before do # For some reason, both bill_address and ship_address are not set # automatically. - # - # Also, assigning the shipping_method to a ShippingMethod instance results - # in a SystemStackError. order.update_attributes!( bill_address: bill_address, - ship_address: ship_address, - shipping_method_id: shipping_method.id + ship_address: ship_address ) end context "when checking out as an anonymous guest" do - let(:user) { Spree::User.anonymous! } + let!(:customer) { nil } + let!(:order) do + create(:order_with_credit_payment, + user: nil, + email: "guest@user.com", + distributor: distributor, + order_cycle: order_cycle) + end it "allows the user to see the details" do # Cannot load the page without token @@ -170,7 +173,7 @@ feature "Order Management", js: true do end expect(find(".order-total.grand-total")).to have_content "105.00" - expect(Spree::LineItem.find_by_id(item2.id)).to be nil + expect(Spree::LineItem.find_by(id: item2.id)).to be nil # Cancelling the order accept_alert do diff --git a/spec/features/consumer/shopping/shopping_spec.rb b/spec/features/consumer/shopping/shopping_spec.rb index e1679791d4..b5a0769e8c 100644 --- a/spec/features/consumer/shopping/shopping_spec.rb +++ b/spec/features/consumer/shopping/shopping_spec.rb @@ -105,8 +105,9 @@ feature "As a consumer I want to shop with a distributor", js: true do # -- Cart shows correct price fill_in "variants[#{variant.id}]", with: 1 - show_cart - within("li.cart") { expect(page).to have_content with_currency(1020.99) } + toggle_cart + within(".cart-sidebar") { expect(page).to have_content with_currency(1020.99) } + toggle_cart # -- Changing order cycle accept_alert do @@ -119,8 +120,9 @@ feature "As a consumer I want to shop with a distributor", js: true do # that we are not filling in the quantity on the outgoing row expect(page).not_to have_selector "tr.product-cart" within('product:not(.ng-leave)') { fill_in "variants[#{variant.id}]", with: 1 } - show_cart - within("li.cart") { expect(page).to have_content with_currency(19.99) } + + wait_for_cart + within(".cart-sidebar") { expect(page).to have_content with_currency(19.99) } end describe "declining to clear the cart" do @@ -136,9 +138,9 @@ feature "As a consumer I want to shop with a distributor", js: true do it "leaves the cart untouched when the user declines" do handle_js_confirm(false) do select "frogs", from: "order_cycle_id" - show_cart + toggle_cart expect(page).to have_selector "tr.product-cart" - expect(page).to have_selector 'li.cart', text: '1' + expect(page).to have_selector '.cart-sidebar', text: '1' # The order cycle choice should not have changed expect(page).to have_select 'order_cycle_id', selected: 'turtles' @@ -156,21 +158,6 @@ feature "As a consumer I want to shop with a distributor", js: true do quick_login_as order.user visit shop_path end - - it "shows previous orders if order cycle was selected already" do - select "frogs", from: "order_cycle_id" - expect(page).to have_content "Next order closing in 2 days" - visit shop_path - find("#cart").click - expect(page).to have_text(I18n.t("shared.menu.joyride.already_ordered_products")) - end - - it "shows previous orders after selecting an order cycle" do - select "frogs", from: "order_cycle_id" - expect(page).to have_content "Next order closing in 2 days" - find("#cart").click - expect(page).to have_text(I18n.t("shared.menu.joyride.already_ordered_products")) - end end end end @@ -232,6 +219,28 @@ feature "As a consumer I want to shop with a distributor", js: true do expect(page).not_to have_content variant3.display_name end end + + context "when the distributor has no available payment/shipping methods" do + before do + distributor.update_attributes shipping_methods: [], payment_methods: [] + end + + # Display only shops are a very useful hack that is described in the user guide + it "still renders a display only shop" do + visit shop_path + expect(page).to have_content product.name + + # Add product to cart + fill_in "variants[#{variant.id}]", with: '1' + wait_for_debounce + expect(page).to have_in_cart product.name + wait_until { !cart_dirty } + + # Try to go to cart + visit main_app.cart_path + expect(page).to have_content "The hub you have selected is temporarily closed for orders. Please try again later." + end + end end describe "group buy products" do @@ -294,7 +303,7 @@ feature "As a consumer I want to shop with a distributor", js: true do expect(li.quantity).to eq(1) fill_in "variants[#{variant.id}]", with: '0' - within('li.cart') { expect(page).not_to have_content product.name } + within('.cart-sidebar') { expect(page).not_to have_content product.name } wait_until { !cart_dirty } expect(Spree::LineItem.where(id: li)).to be_empty @@ -463,11 +472,13 @@ feature "As a consumer I want to shop with a distributor", js: true do visit shop_path expect(page).to have_content "Orders are closed" end + it "shows the last order cycle" do oc1 = create(:simple_order_cycle, distributors: [distributor], orders_open_at: 17.days.ago, orders_close_at: 10.days.ago) visit shop_path expect(page).to have_content "The last cycle closed 10 days ago" end + it "shows the next order cycle" do oc1 = create(:simple_order_cycle, distributors: [distributor], orders_open_at: 10.days.from_now, orders_close_at: 17.days.from_now) visit shop_path diff --git a/spec/features/consumer/shopping/variant_overrides_spec.rb b/spec/features/consumer/shopping/variant_overrides_spec.rb index a4279786da..6dfed074a7 100644 --- a/spec/features/consumer/shopping/variant_overrides_spec.rb +++ b/spec/features/consumer/shopping/variant_overrides_spec.rb @@ -67,8 +67,8 @@ feature "shopping with variant overrides defined", js: true do it "shows the correct prices when products are in the cart" do fill_in "variants[#{product1_variant1.id}]", with: "2" - show_cart - wait_until_enabled 'li.cart a.button' + toggle_cart + wait_until_enabled '.cart-sidebar a.edit-cart' visit shop_path expect(page).to have_price with_currency(61.11) end @@ -78,9 +78,8 @@ feature "shopping with variant overrides defined", js: true do it "shows the overridden price with fees in the quick cart" do fill_in "variants[#{product1_variant1.id}]", with: "2" - show_cart + toggle_cart expect(page).to have_selector "#cart-variant-#{product1_variant1.id} .quantity", text: '2' - expect(page).to have_selector "#cart-variant-#{product1_variant1.id} .price", text: with_currency(61.11) expect(page).to have_selector "#cart-variant-#{product1_variant1.id} .total-price", text: with_currency(122.22) end @@ -202,8 +201,8 @@ feature "shopping with variant overrides defined", js: true do end def click_checkout - show_cart - wait_until_enabled 'li.cart a.button' - first(:link, 'Checkout now').click + toggle_cart + wait_until_enabled '.cart-sidebar a.edit-cart' + first(:link, I18n.t('shared.menu.cart_sidebar.checkout')).click end end diff --git a/spec/features/consumer/shops_spec.rb b/spec/features/consumer/shops_spec.rb index 236e556b79..a9c262817c 100644 --- a/spec/features/consumer/shops_spec.rb +++ b/spec/features/consumer/shops_spec.rb @@ -14,10 +14,6 @@ feature 'Shops', js: true do let!(:producer) { create(:supplier_enterprise) } let!(:er) { create(:enterprise_relationship, parent: distributor, child: producer) } - before :each do - use_api_as_unauthenticated_user - end - before do producer.set_producer_property 'Organic', 'NASAA 12345' end diff --git a/spec/helpers/spree/admin/base_helper_spec.rb b/spec/helpers/spree/admin/base_helper_spec.rb index a47b04113f..db15d2a283 100644 --- a/spec/helpers/spree/admin/base_helper_spec.rb +++ b/spec/helpers/spree/admin/base_helper_spec.rb @@ -9,7 +9,7 @@ describe Spree::BaseHelper, type: :helper do subject { helper.link_to_remove_fields(name, form, options) } it 'returns an `a` tag followed by a hidden `input` tag' do - expect(subject).to eq("Hola<input type="hidden" name="_method" value="destroy">") + expect(subject).to eq("Hola<input type="hidden" name="_method" value="destroy">") end end end diff --git a/spec/helpers/spree/admin/reports_helper_spec.rb b/spec/helpers/spree/admin/reports_helper_spec.rb new file mode 100644 index 0000000000..9ef4976750 --- /dev/null +++ b/spec/helpers/spree/admin/reports_helper_spec.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'spec_helper' + + +describe Spree::ReportsHelper, type: :helper do + describe "#report_payment_method_options" do + let(:order_with_payments) { create(:order_ready_to_ship) } + let(:order_without_payments) { create(:order_with_line_items) } + let(:orders) { [order_with_payments, order_without_payments] } + let(:payment_method) { order_with_payments.payments.first.payment_method } + + it "returns payment method select options for given orders" do + select_options = helper.report_payment_method_options([order_with_payments]) + + expect(select_options).to eq [[payment_method.name, payment_method.id]] + end + + it "handles orders that don't have payments, without error" do + select_options = helper.report_payment_method_options(orders) + + expect(select_options).to eq [[payment_method.name, payment_method.id]] + end + end +end diff --git a/spec/javascripts/unit/admin/bulk_product_update_spec.js.coffee b/spec/javascripts/unit/admin/bulk_product_update_spec.js.coffee index 4feff89868..d483bec6a8 100644 --- a/spec/javascripts/unit/admin/bulk_product_update_spec.js.coffee +++ b/spec/javascripts/unit/admin/bulk_product_update_spec.js.coffee @@ -903,8 +903,8 @@ describe "AdminProductEditCtrl", -> $scope.categoryFilter = "6" $scope.resetSelectFilters() expect($scope.query).toBe "" - expect($scope.producerFilter).toBe "0" - expect($scope.categoryFilter).toBe "0" + expect($scope.producerFilter).toBeUndefined + expect($scope.categoryFilter).toBeUndefined describe "converting arrays of objects with ids to an object with ids as keys", -> diff --git a/spec/javascripts/unit/admin/side_menu/services/side_menu.js.coffee b/spec/javascripts/unit/admin/side_menu/services/side_menu.js.coffee index 0840d69c28..74c802c7d4 100644 --- a/spec/javascripts/unit/admin/side_menu/services/side_menu.js.coffee +++ b/spec/javascripts/unit/admin/side_menu/services/side_menu.js.coffee @@ -69,25 +69,3 @@ describe "SideMenu service", -> it "returns null if no items are found", -> SideMenu.items = [ { name: "Name 1"}, { name: "Name 2"} ] expect(SideMenu.find_by_name("Name 3")).toBe null - - describe "hiding an item by name", -> - it "sets visible to false on the response from find_by_name", -> - mockItem = { visible: true } - spyOn(SideMenu, 'find_by_name').and.returnValue mockItem - SideMenu.hide_item_by_name() - expect(mockItem.visible).toBe false - - it "doesn't crash if null is returned from find_by_name", -> - spyOn(SideMenu, 'find_by_name').and.returnValue null - SideMenu.hide_item_by_name() - - describe "showing an item by name", -> - it "sets visible to false on the response from find_by_name", -> - mockItem = { visible: false } - spyOn(SideMenu, 'find_by_name').and.returnValue mockItem - SideMenu.show_item_by_name() - expect(mockItem.visible).toBe true - - it "doesn't crash if null is returned from find_by_name", -> - spyOn(SideMenu, 'find_by_name').and.returnValue null - SideMenu.show_item_by_name() diff --git a/spec/javascripts/unit/darkswarm/services/enterprise_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/enterprise_spec.js.coffee index 82c26397ca..c95fbdf81b 100644 --- a/spec/javascripts/unit/darkswarm/services/enterprise_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/enterprise_spec.js.coffee @@ -1,7 +1,7 @@ describe "Enterprises service", -> Enterprises = $rootScope = null CurrentHubMock = {} - Geo = + GmapsGeo = OK: 'ok' succeed: true geocode: (query, callback) -> @@ -31,7 +31,7 @@ describe "Enterprises service", -> module 'Darkswarm' module ($provide)-> $provide.value "CurrentHub", CurrentHubMock - $provide.value "Geo", Geo + $provide.value "GmapsGeo", GmapsGeo null angular.module('Darkswarm').value('enterprises', enterprises) angular.module('Darkswarm').value('taxons', taxons) @@ -118,12 +118,12 @@ describe "Enterprises service", -> spyOn(Enterprises, "setDistanceFrom") it "calculates distance for all enterprises when geocoding succeeds", -> - Geo.succeed = true + GmapsGeo.succeed = true Enterprises.calculateDistanceGeo('query') expect(Enterprises.setDistanceFrom).toHaveBeenCalledWith("location") it "resets distance when geocoding fails", -> - Geo.succeed = false + GmapsGeo.succeed = false spyOn(Enterprises, "resetDistance") Enterprises.calculateDistanceGeo('query') expect(Enterprises.setDistanceFrom).not.toHaveBeenCalled() diff --git a/spec/javascripts/unit/darkswarm/services/map_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/map_spec.js.coffee index fb4def8342..eed215dbe1 100644 --- a/spec/javascripts/unit/darkswarm/services/map_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/map_spec.js.coffee @@ -1,7 +1,7 @@ describe "Hubs service", -> OfnMap = null CurrentHubMock = {} - Geo = {} + GmapsGeo = {} enterprises = [ { id: 2 @@ -54,7 +54,7 @@ describe "Hubs service", -> angular.module('Darkswarm').value('enterprises', enterprises) module ($provide)-> $provide.value "CurrentHub", CurrentHubMock - $provide.value "Geo", Geo + $provide.value "GmapsGeo", GmapsGeo null inject ($injector)-> OfnMap = $injector.get("OfnMap") diff --git a/spec/javascripts/unit/darkswarm/services/products_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/products_spec.js.coffee index 62c8c0a071..88ff585f00 100644 --- a/spec/javascripts/unit/darkswarm/services/products_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/products_spec.js.coffee @@ -12,7 +12,7 @@ describe 'Products service', -> productWithImage = null properties = null taxons = null - Geo = {} + GmapsGeo = {} endpoint = "/api/order_cycles/1/products?distributor=1" beforeEach -> @@ -53,7 +53,7 @@ describe 'Products service', -> $provide.value "currentOrder", currentOrder $provide.value "taxons", taxons $provide.value "properties", properties - $provide.value "Geo", Geo + $provide.value "GmapsGeo", GmapsGeo $provide.value "OrderCycle", OrderCycle $provide.value "railsFlash", null null diff --git a/spec/javascripts/unit/darkswarm/services/variants_spec.js.coffee b/spec/javascripts/unit/darkswarm/services/variants_spec.js.coffee index 408fecf7ea..2d9d1452f3 100644 --- a/spec/javascripts/unit/darkswarm/services/variants_spec.js.coffee +++ b/spec/javascripts/unit/darkswarm/services/variants_spec.js.coffee @@ -49,25 +49,9 @@ describe 'Variants service', -> variant = {product_name: 'product_name', name_to_display: 'product_name'} expect(Variants.extendedVariantName(variant)).toEqual "product_name" - it "includes the options text even if variant name is same as product", -> - variant = - product_name: 'product_name' - name_to_display: 'product_name' - options_text: 'options_text' - - expect(Variants.extendedVariantName(variant)).toEqual "product_name (options_text)" - describe "when the product name and the variant name differ", -> it "returns a combined name when there is no options text", -> variant = product_name: 'product_name' name_to_display: 'name_to_display' expect(Variants.extendedVariantName(variant)).toEqual "product_name - name_to_display" - - it "returns a combined name when there is some options text", -> - variant = - product_name: 'product_name' - name_to_display: 'name_to_display' - options_text: 'options_text' - - expect(Variants.extendedVariantName(variant)).toEqual "product_name - name_to_display (options_text)" diff --git a/spec/jobs/subscription_placement_job_spec.rb b/spec/jobs/subscription_placement_job_spec.rb index d298726369..e43343e795 100644 --- a/spec/jobs/subscription_placement_job_spec.rb +++ b/spec/jobs/subscription_placement_job_spec.rb @@ -126,7 +126,7 @@ describe SubscriptionPlacementJob do let(:subscription) { create(:subscription, shop: shop, with_items: true) } let(:proxy_order) { create(:proxy_order, subscription: subscription) } let(:oc) { proxy_order.order_cycle } - let(:ex) { oc.exchanges.outgoing.find_by_sender_id_and_receiver_id(shop.id, shop.id) } + let(:ex) { oc.exchanges.outgoing.find_by(sender_id: shop.id, receiver_id: shop.id) } let(:fee) { create(:enterprise_fee, enterprise: shop, fee_type: 'sales', amount: 10) } let!(:exchange_fee) { ExchangeFee.create!(exchange: ex, enterprise_fee: fee) } let!(:order) { proxy_order.initialise_order! } diff --git a/spec/lib/open_food_network/customers_report_spec.rb b/spec/lib/open_food_network/customers_report_spec.rb index 8e73dbee31..5da874773d 100644 --- a/spec/lib/open_food_network/customers_report_spec.rb +++ b/spec/lib/open_food_network/customers_report_spec.rb @@ -6,7 +6,7 @@ module OpenFoodNetwork context "as a site admin" do let(:user) do user = create(:user) - user.spree_roles << Spree::Role.find_or_create_by_name!("admin") + user.spree_roles << Spree::Role.find_or_create_by!(name: 'admin') user end subject { CustomersReport.new user, {}, true } @@ -114,7 +114,7 @@ module OpenFoodNetwork end describe "filtering orders" do - let(:orders) { Spree::Order.scoped } + let(:orders) { Spree::Order.where(nil) } let(:supplier) { create(:supplier_enterprise) } it "returns all orders sans-params" do diff --git a/spec/lib/open_food_network/order_cycle_management_report_spec.rb b/spec/lib/open_food_network/order_cycle_management_report_spec.rb index 6b1f3421c5..8f65a80889 100644 --- a/spec/lib/open_food_network/order_cycle_management_report_spec.rb +++ b/spec/lib/open_food_network/order_cycle_management_report_spec.rb @@ -8,7 +8,7 @@ module OpenFoodNetwork context "as a site admin" do let(:user) do user = create(:user) - user.spree_roles << Spree::Role.find_or_create_by_name!("admin") + user.spree_roles << Spree::Role.find_or_create_by!(name: "admin") user end subject { OrderCycleManagementReport.new user, {}, true } @@ -71,7 +71,7 @@ module OpenFoodNetwork end describe "filtering orders" do - let!(:orders) { Spree::Order.scoped } + let!(:orders) { Spree::Order.where(nil) } let!(:supplier) { create(:supplier_enterprise) } let!(:oc1) { create(:simple_order_cycle) } diff --git a/spec/lib/open_food_network/products_and_inventory_report_spec.rb b/spec/lib/open_food_network/products_and_inventory_report_spec.rb index 3b361f954a..e4d4d27142 100644 --- a/spec/lib/open_food_network/products_and_inventory_report_spec.rb +++ b/spec/lib/open_food_network/products_and_inventory_report_spec.rb @@ -6,7 +6,7 @@ module OpenFoodNetwork context "As a site admin" do let(:user) do user = create(:user) - user.spree_roles << Spree::Role.find_or_create_by_name!("admin") + user.spree_roles << Spree::Role.find_or_create_by!(name: 'admin') user end subject do @@ -96,18 +96,18 @@ module OpenFoodNetwork end describe "Filtering variants" do - let(:variants) { Spree::Variant.scoped.joins(:product).where(is_master: false) } + let(:variants) { Spree::Variant.where(nil).joins(:product).where(is_master: false) } it "should return unfiltered variants sans-params" do product1 = create(:simple_product, supplier: supplier) product2 = create(:simple_product, supplier: supplier) - expect(subject.filter(Spree::Variant.scoped)).to match_array [product1.master, product1.variants.first, product2.master, product2.variants.first] + expect(subject.filter(Spree::Variant.where(nil))).to match_array [product1.master, product1.variants.first, product2.master, product2.variants.first] end it "should filter deleted products" do product1 = create(:simple_product, supplier: supplier) product2 = create(:simple_product, supplier: supplier) product2.destroy - expect(subject.filter(Spree::Variant.scoped)).to match_array [product1.master, product1.variants.first] + expect(subject.filter(Spree::Variant.where(nil))).to match_array [product1.master, product1.variants.first] end describe "based on report type" do it "returns only variants on hand" do @@ -200,9 +200,9 @@ module OpenFoodNetwork # Remove the distribution of one product for one distributor but still # sell it through the other distributor. - order_cycle.exchanges.outgoing.find_by_receiver_id(distributor.id). + order_cycle.exchanges.outgoing.find_by(receiver_id: distributor.id). exchange_variants. - find_by_variant_id(variant_filtered_by_distributor). + find_by(variant_id: variant_filtered_by_distributor). destroy # Make product available to be filtered later. See OC comment above. diff --git a/spec/models/concerns/order_shipment_spec.rb b/spec/models/concerns/order_shipment_spec.rb index 7821d61c81..08c23f76fb 100644 --- a/spec/models/concerns/order_shipment_spec.rb +++ b/spec/models/concerns/order_shipment_spec.rb @@ -41,7 +41,7 @@ describe OrderShipment do it "returns nil for empty shipping_method_id" do empty_shipping_method_id = ' ' - expect(shipment.shipping_rates).to_not receive(:find_by_shipping_method_id).with(empty_shipping_method_id) + expect(shipment.shipping_rates).to_not receive(:find_by).with(shipping_method_id: empty_shipping_method_id) expect(order.select_shipping_method(empty_shipping_method_id)).to be_nil end @@ -50,7 +50,7 @@ describe OrderShipment do context "when shipping_method_id is not valid for the order" do it "returns nil" do invalid_shipping_method_id = order.shipment.shipping_method.id + 1000 - expect(shipment.shipping_rates).to receive(:find_by_shipping_method_id).with(invalid_shipping_method_id) { nil } + expect(shipment.shipping_rates).to receive(:find_by).with(shipping_method_id: invalid_shipping_method_id) { nil } expect(order.select_shipping_method(invalid_shipping_method_id)).to be_nil end diff --git a/spec/models/concerns/product_stock_spec.rb b/spec/models/concerns/product_stock_spec.rb index cf91b4d671..5b5a21efb4 100644 --- a/spec/models/concerns/product_stock_spec.rb +++ b/spec/models/concerns/product_stock_spec.rb @@ -5,7 +5,7 @@ describe ProductStock do context "when product has no variants" do before do - product.variants.first.destroy + product.variants.destroy product.variants.reload end diff --git a/spec/models/enterprise_fee_spec.rb b/spec/models/enterprise_fee_spec.rb index 4c09ccd62c..a422358bb8 100644 --- a/spec/models/enterprise_fee_spec.rb +++ b/spec/models/enterprise_fee_spec.rb @@ -130,7 +130,7 @@ describe EnterpriseFee do source: order, originator: tax_rate, state: 'closed', - label: 'hello' }, without_protection: true) + label: 'hello' }) expect do EnterpriseFee.clear_all_adjustments_on_order order diff --git a/spec/models/order_cycle_spec.rb b/spec/models/order_cycle_spec.rb index 22cfeb2b70..21cad530a9 100644 --- a/spec/models/order_cycle_spec.rb +++ b/spec/models/order_cycle_spec.rb @@ -65,8 +65,8 @@ describe OrderCycle do oc_received = create(:simple_order_cycle, distributors: [e2]) oc_not_accessible = create(:simple_order_cycle, coordinator: e1) - expect(OrderCycle.accessible_by(user)).to include(oc_coordinated, oc_sent, oc_received) - expect(OrderCycle.accessible_by(user)).not_to include(oc_not_accessible) + expect(OrderCycle.visible_by(user)).to include(oc_coordinated, oc_sent, oc_received) + expect(OrderCycle.visible_by(user)).not_to include(oc_not_accessible) end it "finds the most recently closed order cycles" do @@ -421,11 +421,11 @@ describe OrderCycle do let!(:oc3) { create(:simple_order_cycle, orders_close_at: time3, distributors: [e2]) } it "returns the closing time, indexed by enterprise id" do - expect(OrderCycle.earliest_closing_times[e1.id]).to eq(time1) + expect(OrderCycle.earliest_closing_times[e1.id].round).to eq(time1.round) end it "returns the earliest closing time" do - expect(OrderCycle.earliest_closing_times[e2.id]).to eq(time2) + expect(OrderCycle.earliest_closing_times[e2.id].round).to eq(time2.round) end end diff --git a/spec/models/product_importer_spec.rb b/spec/models/product_importer_spec.rb index 705f99d41e..910272f940 100644 --- a/spec/models/product_importer_spec.rb +++ b/spec/models/product_importer_spec.rb @@ -50,11 +50,11 @@ describe ProductImport::ProductImporter do let(:csv_data) { CSV.generate do |csv| csv << ["name", "producer", "category", "on_hand", "price", "units", "unit_type", "variant_unit_name", "on_demand", "shipping_category"] - csv << ["Carrots", "User Enterprise", "Vegetables", "5", "3.20", "500", "g", "", "", shipping_category.name] - csv << ["Potatoes", "User Enterprise", "Vegetables", "6", "6.50", "2", "kg", "", "", shipping_category.name] - csv << ["Pea Soup", "User Enterprise", "Vegetables", "8", "5.50", "750", "ml", "", "0", shipping_category.name] - csv << ["Salad", "User Enterprise", "Vegetables", "7", "4.50", "1", "", "bags", "", shipping_category.name] - csv << ["Hot Cross Buns", "User Enterprise", "Cake", "7", "3.50", "1", "", "buns", "1", shipping_category.name] + csv << ["Carrots", enterprise.name, "Vegetables", "5", "3.20", "500", "g", "", "", shipping_category.name] + csv << ["Potatoes", enterprise.name, "Vegetables", "6", "6.50", "2", "kg", "", "", shipping_category.name] + csv << ["Pea Soup", enterprise.name, "Vegetables", "8", "5.50", "750", "ml", "", "0", shipping_category.name] + csv << ["Salad", enterprise.name, "Vegetables", "7", "4.50", "1", "", "bags", "", shipping_category.name] + csv << ["Hot Cross Buns", enterprise.name, "Cake", "7", "3.50", "1", "", "buns", "1", shipping_category.name] end } let(:importer) { import_data csv_data } @@ -80,7 +80,7 @@ describe ProductImport::ProductImporter do expect(importer.updated_ids).to be_a(Array) expect(importer.updated_ids.count).to eq 5 - carrots = Spree::Product.find_by_name('Carrots') + carrots = Spree::Product.find_by(name: 'Carrots') expect(carrots.supplier).to eq enterprise expect(carrots.on_hand).to eq 5 expect(carrots.price).to eq 3.20 @@ -90,7 +90,7 @@ describe ProductImport::ProductImporter do expect(carrots.on_demand).to_not eq true expect(carrots.variants.first.import_date).to be_within(1.minute).of Time.zone.now - potatoes = Spree::Product.find_by_name('Potatoes') + potatoes = Spree::Product.find_by(name: 'Potatoes') expect(potatoes.supplier).to eq enterprise expect(potatoes.on_hand).to eq 6 expect(potatoes.price).to eq 6.50 @@ -100,7 +100,7 @@ describe ProductImport::ProductImporter do expect(potatoes.on_demand).to_not eq true expect(potatoes.variants.first.import_date).to be_within(1.minute).of Time.zone.now - pea_soup = Spree::Product.find_by_name('Pea Soup') + pea_soup = Spree::Product.find_by(name: 'Pea Soup') expect(pea_soup.supplier).to eq enterprise expect(pea_soup.on_hand).to eq 8 expect(pea_soup.price).to eq 5.50 @@ -110,7 +110,7 @@ describe ProductImport::ProductImporter do expect(pea_soup.on_demand).to_not eq true expect(pea_soup.variants.first.import_date).to be_within(1.minute).of Time.zone.now - salad = Spree::Product.find_by_name('Salad') + salad = Spree::Product.find_by(name: 'Salad') expect(salad.supplier).to eq enterprise expect(salad.on_hand).to eq 7 expect(salad.price).to eq 4.50 @@ -120,7 +120,7 @@ describe ProductImport::ProductImporter do expect(salad.on_demand).to_not eq true expect(salad.variants.first.import_date).to be_within(1.minute).of Time.zone.now - buns = Spree::Product.find_by_name('Hot Cross Buns') + buns = Spree::Product.find_by(name: 'Hot Cross Buns') expect(buns.supplier).to eq enterprise expect(buns.on_hand).to eq 7 expect(buns.price).to eq 3.50 @@ -136,7 +136,7 @@ describe ProductImport::ProductImporter do let(:csv_data) { CSV.generate do |csv| csv << ["name", "producer", "category", "on_hand", "price", "units", "unit_type", "shipping_category"] - csv << ["Good Carrots", "User Enterprise", "Vegetables", "5", "3.20", "500", "g", shipping_category.name] + csv << ["Good Carrots", enterprise.name, "Vegetables", "5", "3.20", "500", "g", shipping_category.name] csv << ["Bad Potatoes", "", "Vegetables", "6", "6.50", "1", "", shipping_category.name] end } @@ -159,13 +159,30 @@ describe ProductImport::ProductImporter do expect(importer.updated_ids).to be_a(Array) expect(importer.updated_ids.count).to eq 1 - carrots = Spree::Product.find_by_name('Good Carrots') + carrots = Spree::Product.find_by(name: 'Good Carrots') expect(carrots.supplier).to eq enterprise expect(carrots.on_hand).to eq 5 expect(carrots.price).to eq 3.20 expect(carrots.variants.first.import_date).to be_within(1.minute).of Time.zone.now - expect(Spree::Product.find_by_name('Bad Potatoes')).to eq nil + expect(Spree::Product.find_by(name: 'Bad Potatoes')).to eq nil + end + end + + describe "when uploading a spreadsheet with some malformed data" do + # Use a simple string as CSV.generate will do some escaping + let(:csv_data) { + csv = "name,producer,category,on_hand,price,units,unit_type,shipping_category\n" + csv += "Good Carrots,#{enterprise.name},Vegetables,5,3.20,500,g,#{shipping_category.name}\n" + csv += "Malformed \rBrocolli,#{enterprise.name},Vegetables,8,2.50,200,g,#{shipping_category.name}\n" + } + let(:importer) { import_data csv_data } + + # an unquoted \n will create a non valid line which will fail entry validation hence why we are only testing with \r + it "should raise an unquoted field error if data include unquoted field with \r character" do + expect(importer.errors.messages.values).to include( + [I18n.t('admin.product_import.model.malformed_csv', error_message: "Unquoted fields do not allow \\r or \\n (line 3).")] + ) end end @@ -173,7 +190,7 @@ describe ProductImport::ProductImporter do let(:csv_data) { CSV.generate do |csv| csv << ["name", "producer", "category", "on_hand", "price", "units", "unit_type", "variant_unit_name", "on_demand", "shipping_category"] - csv << ["Shipping Test", "User Enterprise", "Vegetables", "5", "3.20", "500", "g", "", nil, nil] + csv << ["Shipping Test", enterprise.name, "Vegetables", "5", "3.20", "500", "g", "", nil, nil] end } let(:importer) { import_data csv_data } @@ -191,7 +208,7 @@ describe ProductImport::ProductImporter do CSV.generate do |csv| csv << ["name", "producer", "category", "on_hand", "price", "units", "unit_type"] csv << ["Product 1", "Non-existent Enterprise", "Vegetables", "5", "5.50", "500", "g"] - csv << ["Product 2", "Non-Producer", "Vegetables", "5", "5.50", "500", "g"] + csv << ["Product 2", enterprise4.name, "Vegetables", "5", "5.50", "500", "g"] end } let(:importer) { import_data csv_data } @@ -209,8 +226,8 @@ describe ProductImport::ProductImporter do let(:csv_data) { CSV.generate do |csv| csv << ["name", "producer", "category", "on_hand", "price", "units", "unit_type", "display_name", "shipping_category"] - csv << ["Hypothetical Cake", "Another Enterprise", "Cake", "5", "5.50", "500", "g", "Preexisting Banana", shipping_category.name] - csv << ["Hypothetical Cake", "Another Enterprise", "Cake", "6", "3.50", "500", "g", "Emergent Coffee", shipping_category.name] + csv << ["Hypothetical Cake", enterprise2.name, "Cake", "5", "5.50", "500", "g", "Preexisting Banana", shipping_category.name] + csv << ["Hypothetical Cake", enterprise2.name, "Cake", "6", "3.50", "500", "g", "Emergent Coffee", shipping_category.name] end } let(:importer) { import_data csv_data } @@ -233,13 +250,13 @@ describe ProductImport::ProductImporter do expect(importer.updated_ids).to be_a(Array) expect(importer.updated_ids.count).to eq 2 - added_coffee = Spree::Variant.find_by_display_name('Emergent Coffee') + added_coffee = Spree::Variant.find_by(display_name: 'Emergent Coffee') expect(added_coffee.product.name).to eq 'Hypothetical Cake' expect(added_coffee.price).to eq 3.50 expect(added_coffee.on_hand).to eq 6 expect(added_coffee.import_date).to be_within(1.minute).of Time.zone.now - updated_banana = Spree::Variant.find_by_display_name('Preexisting Banana') + updated_banana = Spree::Variant.find_by(display_name: 'Preexisting Banana') expect(updated_banana.product.name).to eq 'Hypothetical Cake' expect(updated_banana.price).to eq 5.50 expect(updated_banana.on_hand).to eq 5 @@ -251,7 +268,7 @@ describe ProductImport::ProductImporter do let(:csv_data) { CSV.generate do |csv| csv << ["name", "producer", "description", "category", "on_hand", "price", "units", "unit_type", "display_name", "shipping_category"] - csv << ["Hypothetical Cake", "Another Enterprise", "New Description", "Cake", "5", "5.50", "500", "g", "Preexisting Banana", shipping_category.name] + csv << ["Hypothetical Cake", enterprise2.name, "New Description", "Cake", "5", "5.50", "500", "g", "Preexisting Banana", shipping_category.name] end } let(:importer) { import_data csv_data } @@ -270,11 +287,11 @@ describe ProductImport::ProductImporter do let(:csv_data) { CSV.generate do |csv| csv << ["name", "producer", "category", "on_hand", "price", "units", "unit_type", "display_name", "shipping_category"] - csv << ["Potatoes", "User Enterprise", "Vegetables", "5", "3.50", "500", "g", "Small Bag", shipping_category.name] - csv << ["Chives", "User Enterprise", "Vegetables", "6", "4.50", "500", "g", "Bunch", shipping_category.name] - csv << ["Potatoes", "User Enterprise", "Vegetables", "6", "5.50", "2", "kg", "Big Bag", shipping_category.name] - csv << ["Potatoes", "User Enterprise", "Vegetables", "6", "22.00", "10000", "g", "Small Sack", shipping_category.name] - csv << ["Potatoes", "User Enterprise", "Vegetables", "6", "60.00", "30000", "", "Big Sack", shipping_category.name] + csv << ["Potatoes", enterprise.name, "Vegetables", "5", "3.50", "500", "g", "Small Bag", shipping_category.name] + csv << ["Chives", enterprise.name, "Vegetables", "6", "4.50", "500", "g", "Bunch", shipping_category.name] + csv << ["Potatoes", enterprise.name, "Vegetables", "6", "5.50", "2", "kg", "Big Bag", shipping_category.name] + csv << ["Potatoes", enterprise.name, "Vegetables", "6", "22.00", "10000", "g", "Small Sack", shipping_category.name] + csv << ["Potatoes", enterprise.name, "Vegetables", "6", "60.00", "30000", "", "Big Sack", shipping_category.name] end } let(:importer) { import_data csv_data } @@ -295,21 +312,21 @@ describe ProductImport::ProductImporter do expect(importer.updated_ids).to be_a(Array) expect(importer.updated_ids.count).to eq 3 - small_bag = Spree::Variant.find_by_display_name('Small Bag') + small_bag = Spree::Variant.find_by(display_name: 'Small Bag') expect(small_bag.product.name).to eq 'Potatoes' expect(small_bag.price).to eq 3.50 expect(small_bag.on_hand).to eq 5 - big_bag = Spree::Variant.find_by_display_name("Big Bag") + big_bag = Spree::Variant.find_by(display_name: "Big Bag") expect(big_bag).to be_blank - small_sack = Spree::Variant.find_by_display_name("Small Sack") + small_sack = Spree::Variant.find_by(display_name: "Small Sack") expect(small_sack.product.name).to eq "Potatoes" expect(small_sack.price).to eq 22.00 expect(small_sack.on_hand).to eq 6 expect(small_sack.product.id).to eq small_bag.product.id - big_sack = Spree::Variant.find_by_display_name("Big Sack") + big_sack = Spree::Variant.find_by(display_name: "Big Sack") expect(big_sack).to be_blank end end @@ -318,8 +335,8 @@ describe ProductImport::ProductImporter do let(:csv_data) { CSV.generate do |csv| csv << ["name", "producer", "category", "on_hand", "price", "units", "unit_type", "on_demand", "sku", "shipping_category"] - csv << ["Beetroot", "And Another Enterprise", "Vegetables", "5", "3.50", "500", "g", "0", nil, shipping_category.name] - csv << ["Tomato", "And Another Enterprise", "Vegetables", "6", "5.50", "500", "g", "1", "TOMS", shipping_category.name] + csv << ["Beetroot", enterprise3.name, "Vegetables", "5", "3.50", "500", "g", "0", nil, shipping_category.name] + csv << ["Tomato", enterprise3.name, "Vegetables", "6", "5.50", "500", "g", "1", "TOMS", shipping_category.name] end } let(:importer) { import_data csv_data } @@ -342,11 +359,11 @@ describe ProductImport::ProductImporter do expect(importer.updated_ids).to be_a(Array) expect(importer.updated_ids.count).to eq 2 - beetroot = Spree::Product.find_by_name('Beetroot').variants.first + beetroot = Spree::Product.find_by(name: 'Beetroot').variants.first expect(beetroot.price).to eq 3.50 expect(beetroot.on_demand).to_not eq true - tomato = Spree::Product.find_by_name('Tomato').variants.first + tomato = Spree::Product.find_by(name: 'Tomato').variants.first expect(tomato.price).to eq 5.50 expect(tomato.on_demand).to eq true end @@ -356,8 +373,8 @@ describe ProductImport::ProductImporter do let(:csv_data) { CSV.generate do |csv| csv << ["name", "producer", "category", "on_hand", "price", "units", "unit_type"] - csv << ["Beetroot", "And Another Enterprise", "Meat", "5", "3.50", "500", "g"] - csv << ["Tomato", "And Another Enterprise", "Vegetables", "6", "5.50", "500", "Kg"] + csv << ["Beetroot", enterprise3.name, "Meat", "5", "3.50", "500", "g"] + csv << ["Tomato", enterprise3.name, "Vegetables", "6", "5.50", "500", "Kg"] end } let(:importer) { import_data csv_data } @@ -379,11 +396,11 @@ describe ProductImport::ProductImporter do let(:csv_data) { CSV.generate do |csv| csv << ["name", "producer", "category", "description", "on_hand", "price", "units", "unit_type", "display_name", "shipping_category"] - csv << ["Oats", "User Enterprise", "Cereal", "", "50", "3.50", "500", "g", "Rolled Oats", shipping_category.name] # Update - csv << ["Oats", "User Enterprise", "Cereal", "", "80", "3.75", "500", "g", "Flaked Oats", shipping_category.name] # Update - csv << ["Oats", "User Enterprise", "Cereal", "", "60", "5.50", "500", "g", "Magic Oats", shipping_category.name] # Add - csv << ["Oats", "User Enterprise", "Cereal", "", "70", "8.50", "500", "g", "French Oats", shipping_category.name] # Add - csv << ["Oats", "User Enterprise", "Cereal", "", "70", "8.50", "500", "g", "Scottish Oats", shipping_category.name] # Add + csv << ["Oats", enterprise.name, "Cereal", "", "50", "3.50", "500", "g", "Rolled Oats", shipping_category.name] # Update + csv << ["Oats", enterprise.name, "Cereal", "", "80", "3.75", "500", "g", "Flaked Oats", shipping_category.name] # Update + csv << ["Oats", enterprise.name, "Cereal", "", "60", "5.50", "500", "g", "Magic Oats", shipping_category.name] # Add + csv << ["Oats", enterprise.name, "Cereal", "", "70", "8.50", "500", "g", "French Oats", shipping_category.name] # Add + csv << ["Oats", enterprise.name, "Cereal", "", "70", "8.50", "500", "g", "Scottish Oats", shipping_category.name] # Add end } let(:importer) { import_data csv_data } @@ -415,11 +432,11 @@ describe ProductImport::ProductImporter do let(:csv_data) { CSV.generate do |csv| csv << ["name", "producer", "category", "on_hand", "price", "units", "unit_type", "display_name", "shipping_category"] - csv << ["Bag of Oats", "User Enterprise", "Cereal", "60", "5.50", "500", "g", "Magic Oats", shipping_category.name] # Add - csv << ["Bag of Oats", "User Enterprise", "Cereal", "70", "8.50", "500", "g", "French Oats", shipping_category.name] # Add - csv << ["Bag of Oats", "User Enterprise", "Cereal", "80", "9.50", "500", "g", "Organic Oats", shipping_category.name] # Add - csv << ["Bag of Oats", "User Enterprise", "Cereal", "90", "7.50", "500", "g", "Scottish Oats", shipping_category.name] # Add - csv << ["Bag of Oats", "User Enterprise", "Cereal", "30", "6.50", "500", "g", "Breakfast Oats", shipping_category.name] # Add + csv << ["Bag of Oats", enterprise.name, "Cereal", "60", "5.50", "500", "g", "Magic Oats", shipping_category.name] # Add + csv << ["Bag of Oats", enterprise.name, "Cereal", "70", "8.50", "500", "g", "French Oats", shipping_category.name] # Add + csv << ["Bag of Oats", enterprise.name, "Cereal", "80", "9.50", "500", "g", "Organic Oats", shipping_category.name] # Add + csv << ["Bag of Oats", enterprise.name, "Cereal", "90", "7.50", "500", "g", "Scottish Oats", shipping_category.name] # Add + csv << ["Bag of Oats", enterprise.name, "Cereal", "30", "6.50", "500", "g", "Breakfast Oats", shipping_category.name] # Add end } @@ -481,9 +498,9 @@ describe ProductImport::ProductImporter do let(:csv_data) { CSV.generate do |csv| csv << ["name", "distributor", "producer", "on_hand", "price", "units", "unit_type", "variant_unit_name"] - csv << ["Beans", "Another Enterprise", "User Enterprise", "5", "3.20", "500", "g", ""] - csv << ["Sprouts", "Another Enterprise", "User Enterprise", "6", "6.50", "500", "g", ""] - csv << ["Cabbage", "Another Enterprise", "User Enterprise", "2001", "1.50", "1", "", "Whole"] + csv << ["Beans", enterprise2.name, enterprise.name, "5", "3.20", "500", "g", ""] + csv << ["Sprouts", enterprise2.name, enterprise.name, "6", "6.50", "500", "g", ""] + csv << ["Cabbage", enterprise2.name, enterprise.name, "2001", "1.50", "1", "", "Whole"] end } let(:importer) { import_data csv_data, import_into: 'inventories' } @@ -525,7 +542,7 @@ describe ProductImport::ProductImporter do let(:csv_data) { CSV.generate do |csv| csv << ["name", "display_name", "distributor", "producer", "on_hand", "price", "units"] - csv << ["Oats", "Porridge Oats", "Another Enterprise", "User Enterprise", "900", "", "500"] + csv << ["Oats", "Porridge Oats", enterprise2.name, enterprise.name, "900", "", "500"] end } let(:importer) { import_data csv_data, import_into: 'inventories' } @@ -548,7 +565,7 @@ describe ProductImport::ProductImporter do let(:csv_data) { CSV.generate do |csv| csv << ["name", "distributor", "producer", "on_hand", "price", "units", "variant_unit_name"] - csv << ["Cabbage", "Another Enterprise", "User Enterprise", "900", "", "1", "Whole"] + csv << ["Cabbage", enterprise2.name, enterprise.name, "900", "", "1", "Whole"] end } let(:importer) { import_data csv_data, import_into: 'inventories' } @@ -571,8 +588,8 @@ describe ProductImport::ProductImporter do it "only allows product import into enterprises the user is permitted to manage" do csv_data = CSV.generate do |csv| csv << ["name", "producer", "category", "on_hand", "price", "units", "unit_type", "shipping_category"] - csv << ["My Carrots", "User Enterprise", "Vegetables", "5", "3.20", "500", "g", shipping_category.name] - csv << ["Your Potatoes", "Another Enterprise", "Vegetables", "6", "6.50", "1", "kg", shipping_category.name] + csv << ["My Carrots", enterprise.name, "Vegetables", "5", "3.20", "500", "g", shipping_category.name] + csv << ["Your Potatoes", enterprise2.name, "Vegetables", "6", "6.50", "1", "kg", shipping_category.name] end importer = import_data csv_data, import_user: user @@ -589,14 +606,14 @@ describe ProductImport::ProductImporter do expect(importer.updated_ids).to be_a(Array) expect(importer.updated_ids.count).to eq 1 - expect(Spree::Product.find_by_name('My Carrots')).to be_a Spree::Product - expect(Spree::Product.find_by_name('Your Potatoes')).to eq nil + expect(Spree::Product.find_by(name: 'My Carrots')).to be_a Spree::Product + expect(Spree::Product.find_by(name: 'Your Potatoes')).to eq nil end it "allows creating inventories for producers that a user's hub has permission for" do csv_data = CSV.generate do |csv| csv << ["name", "producer", "distributor", "on_hand", "price", "units", "unit_type"] - csv << ["Beans", "User Enterprise", "Another Enterprise", "777", "3.20", "500", "g"] + csv << ["Beans", enterprise.name, enterprise2.name, "777", "3.20", "500", "g"] end importer = import_data csv_data, import_into: 'inventories' @@ -620,8 +637,8 @@ describe ProductImport::ProductImporter do it "does not allow creating inventories for producers that a user's hubs don't have permission for" do csv_data = CSV.generate do |csv| csv << ["name", "producer", "on_hand", "price", "units", "unit_type"] - csv << ["Beans", "User Enterprise", "5", "3.20", "500", "g"] - csv << ["Sprouts", "User Enterprise", "6", "6.50", "500", "g"] + csv << ["Beans", enterprise.name, "5", "3.20", "500", "g"] + csv << ["Sprouts", enterprise.name, "6", "6.50", "500", "g"] end importer = import_data csv_data, import_into: 'inventories' @@ -644,8 +661,8 @@ describe ProductImport::ProductImporter do it "can reset all products for an enterprise that are not present in the uploaded file to zero stock" do csv_data = CSV.generate do |csv| csv << ["name", "producer", "category", "on_hand", "price", "units", "unit_type", "shipping_category"] - csv << ["Carrots", "User Enterprise", "Vegetables", "5", "3.20", "500", "g", shipping_category.name] - csv << ["Beans", "User Enterprise", "Vegetables", "6", "6.50", "500", "g", shipping_category.name] + csv << ["Carrots", enterprise.name, "Vegetables", "5", "3.20", "500", "g", shipping_category.name] + csv << ["Beans", enterprise.name, "Vegetables", "6", "6.50", "500", "g", shipping_category.name] end importer = import_data csv_data, reset_all_absent: true @@ -671,18 +688,18 @@ describe ProductImport::ProductImporter do expect(importer.products_reset_count).to eq 7 - expect(Spree::Product.find_by_name('Carrots').on_hand).to eq 5 # Present in file, added - expect(Spree::Product.find_by_name('Beans').on_hand).to eq 6 # Present in file, updated - expect(Spree::Product.find_by_name('Sprouts').on_hand).to eq 0 # In enterprise, not in file - expect(Spree::Product.find_by_name('Cabbage').on_hand).to eq 0 # In enterprise, not in file - expect(Spree::Product.find_by_name('Lettuce').on_hand).to eq 100 # In different enterprise; unchanged + expect(Spree::Product.find_by(name: 'Carrots').on_hand).to eq 5 # Present in file, added + expect(Spree::Product.find_by(name: 'Beans').on_hand).to eq 6 # Present in file, updated + expect(Spree::Product.find_by(name: 'Sprouts').on_hand).to eq 0 # In enterprise, not in file + expect(Spree::Product.find_by(name: 'Cabbage').on_hand).to eq 0 # In enterprise, not in file + expect(Spree::Product.find_by(name: 'Lettuce').on_hand).to eq 100 # In different enterprise; unchanged end it "can reset all inventory items for an enterprise that are not present in the uploaded file to zero stock" do csv_data = CSV.generate do |csv| csv << ["name", "distributor", "producer", "on_hand", "price", "units", "unit_type"] - csv << ["Beans", "Another Enterprise", "User Enterprise", "6", "3.20", "500", "g"] - csv << ["Sprouts", "Another Enterprise", "User Enterprise", "7", "6.50", "500", "g"] + csv << ["Beans", enterprise2.name, enterprise.name, "6", "3.20", "500", "g"] + csv << ["Sprouts", enterprise2.name, enterprise.name, "7", "6.50", "500", "g"] end importer = import_data csv_data, import_into: 'inventories', reset_all_absent: true diff --git a/spec/models/spree/calculator/price_sack_spec.rb b/spec/models/spree/calculator/price_sack_spec.rb index 921b657f88..05c7a8cb8a 100644 --- a/spec/models/spree/calculator/price_sack_spec.rb +++ b/spec/models/spree/calculator/price_sack_spec.rb @@ -49,6 +49,32 @@ describe Spree::Calculator::PriceSack do end end + context "minimal amount is float" do + before do + calculator.preferred_minimal_amount = 16.5 + calculator.preferred_normal_amount = 5 + calculator.preferred_discount_amount = 1 + line_item.quantity = 2 + end + + context "with price bellow minimal amount" do + let(:price) { 8 } + + it "returns the correct value of cost" do + expect(calculator.compute(line_item)).to eq(5) + end + end + + context "with price above minimal amount" do + let(:price) { 8.5 } + + it "returns the correct value of cost" do + expect(calculator.compute(line_item)).to eq(1) + 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/line_item_spec.rb b/spec/models/spree/line_item_spec.rb index 0578d90017..2b538d2967 100644 --- a/spec/models/spree/line_item_spec.rb +++ b/spec/models/spree/line_item_spec.rb @@ -27,12 +27,8 @@ module Spree let(:oc_order) { create :order_with_totals_and_distribution } - it "finds line items for products supplied by a particular enterprise" do - expect(LineItem.supplied_by(s1)).to eq([li1]) - expect(LineItem.supplied_by(s2)).to eq([li2]) - end - it "finds line items for products supplied by one of a number of enterprises" do + li1; li2 expect(LineItem.supplied_by_any([s1])).to eq([li1]) expect(LineItem.supplied_by_any([s2])).to eq([li2]) expect(LineItem.supplied_by_any([s1, s2])).to match_array [li1, li2] @@ -639,7 +635,7 @@ module Spree describe "deleting unit option values" do let!(:p) { create(:simple_product, variant_unit: 'weight', variant_unit_scale: 1) } - let!(:ot) { Spree::OptionType.find_by_name 'unit_weight' } + let!(:ot) { Spree::OptionType.find_by name: 'unit_weight' } let!(:li) { create(:line_item, product: p) } it "removes option value associations for unit option types" do diff --git a/spec/models/spree/order_spec.rb b/spec/models/spree/order_spec.rb index 1b5d6cdb35..2151634bde 100644 --- a/spec/models/spree/order_spec.rb +++ b/spec/models/spree/order_spec.rb @@ -3,6 +3,42 @@ require 'spec_helper' describe Spree::Order do include OpenFoodNetwork::EmailHelper + describe "email validation" do + let(:order) { build(:order) } + + it "has errors if email is blank" do + order.stub(require_email: true) + order.email = "" + + order.valid? + expect(order.errors[:email]).to eq ["can't be blank", "is invalid"] + end + + it "has errors if email is invalid" do + order.stub(require_email: true) + order.email = "invalid_email" + + order.valid? + expect(order.errors[:email]).to eq ["is invalid"] + end + + it "has errors if email has invalid domain" do + order.stub(require_email: true) + order.email = "single_letter_tld@domain.z" + + order.valid? + expect(order.errors[:email]).to eq ["is invalid"] + end + + it "is valid if email is valid" do + order.stub(require_email: true) + order.email = "a@b.ca" + + order.valid? + expect(order.errors[:email]).to eq [] + end + end + describe "setting variant attributes" do it "sets attributes on line items for variants" do d = create(:distributor_enterprise) @@ -251,70 +287,6 @@ describe Spree::Order do end end - describe "getting a hash of all taxes" do - let(:zone) { create(:zone_with_member) } - let(:coordinator) { create(:distributor_enterprise, charges_sales_tax: true) } - - let(:tax_rate10) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.1, zone: zone) } - let(:tax_rate15) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.15, zone: zone) } - let(:tax_rate20) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.2, zone: zone) } - let(:tax_rate25) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.25, zone: zone) } - let(:tax_category10) { create(:tax_category, tax_rates: [tax_rate10]) } - let(:tax_category15) { create(:tax_category, tax_rates: [tax_rate15]) } - let(:tax_category20) { create(:tax_category, tax_rates: [tax_rate20]) } - let(:tax_category25) { create(:tax_category, tax_rates: [tax_rate25]) } - - let(:variant) { create(:variant, product: create(:product, tax_category: tax_category10)) } - let(:enterprise_fee) { create(:enterprise_fee, enterprise: coordinator, tax_category: tax_category20, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 48.0)) } - let(:additional_adjustment) { create(:adjustment, amount: 50.0, included_tax: tax_rate25.compute_tax(50.0)) } - - let(:order_cycle) { create(:simple_order_cycle, coordinator: coordinator, coordinator_fees: [enterprise_fee], distributors: [coordinator], variants: [variant]) } - let(:line_item) { create(:line_item, variant: variant, price: 44.0) } - let(:order) do - create( - :order, - line_items: [line_item], - bill_address: create(:address), - order_cycle: order_cycle, - distributor: coordinator, - adjustments: [additional_adjustment] - ) - end - - before do - allow(Spree::Config).to receive(:shipment_inc_vat).and_return(true) - allow(Spree::Config).to receive(:shipping_tax_rate).and_return(tax_rate15.amount) - end - - let(:shipping_method) { create(:shipping_method, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 46.0)) } - let!(:shipment) { create(:shipment_with, :shipping_method, shipping_method: shipping_method, order: order) } - - before do - order.create_tax_charge! - order.update_distribution_charge! - end - - it "returns a hash with all 3 taxes" do - expect(order.tax_adjustment_totals.size).to eq(4) - end - - it "contains tax on line_item" do - expect(order.tax_adjustment_totals[tax_rate10]).to eq(4.0) - end - - it "contains tax on shipping_fee" do - expect(order.tax_adjustment_totals[tax_rate15]).to eq(6.0) - end - - it "contains tax on enterprise_fee" do - expect(order.tax_adjustment_totals[tax_rate20]).to eq(8.0) - end - - it "contains tax on order adjustment" do - expect(order.tax_adjustment_totals[tax_rate25]).to eq(10.0) - end - end - describe "setting the distributor" do it "sets the distributor when no order cycle is set" do d = create(:distributor_enterprise) diff --git a/spec/models/spree/product_spec.rb b/spec/models/spree/product_spec.rb index a8c6368a70..4309d105c9 100644 --- a/spec/models/spree/product_spec.rb +++ b/spec/models/spree/product_spec.rb @@ -257,6 +257,37 @@ module Spree end end + describe "in_distributors" do + let!(:distributor1) { create(:distributor_enterprise) } + let!(:distributor2) { create(:distributor_enterprise) } + let!(:product1) { create(:product) } + let!(:product2) { create(:product) } + let!(:product3) { create(:product) } + let!(:product4) { create(:product) } + let!(:order_cycle1) { + create(:order_cycle, distributors: [distributor1], + variants: [product1.variants.first, product2.variants.first]) + } + let!(:order_cycle2) { + create(:order_cycle, distributors: [distributor2], + variants: [product3.variants.first]) + } + + it "returns distributed products for a given Enterprise AR relation" do + distributors = Enterprise.where(id: [distributor1.id, distributor2.id]).to_a + + expect(Product.in_distributors(distributors)).to include product1, product2, product3 + expect(Product.in_distributors(distributors)).to_not include product4 + end + + it "returns distributed products for a given array of enterprise ids" do + distributors_ids = [distributor1.id, distributor2.id] + + expect(Product.in_distributors(distributors_ids)).to include product1, product2, product3 + expect(Product.in_distributors(distributors_ids)).to_not include product4 + end + end + describe "in_supplier_or_distributor" do it "shows products in supplier" do s1 = create(:supplier_enterprise) @@ -450,9 +481,9 @@ module Spree pb = Spree::Property.create! name: 'B', presentation: 'B' pc = Spree::Property.create! name: 'C', presentation: 'C' - product.product_properties.create!({ property_id: pa.id, value: '1', position: 1 }, without_protection: true) - product.product_properties.create!({ property_id: pc.id, value: '3', position: 3 }, without_protection: true) - supplier.producer_properties.create!({ property_id: pb.id, value: '2', position: 2 }, without_protection: true) + product.product_properties.create!({ property_id: pa.id, value: '1', position: 1 }) + product.product_properties.create!({ property_id: pc.id, value: '3', position: 3 }) + supplier.producer_properties.create!({ property_id: pb.id, value: '2', position: 2 }) expect(product.properties_including_inherited).to eq( [{ id: pa.id, name: "A", value: '1' }, @@ -510,7 +541,7 @@ module Spree end it "removes the related option values from all its variants and replaces them" do - ot = Spree::OptionType.find_by_name 'unit_weight' + ot = Spree::OptionType.find_by name: 'unit_weight' v = create(:variant, unit_value: 1, product: p) p.reload @@ -525,7 +556,7 @@ module Spree end it "removes the related option values from its master variant and replaces them" do - ot = Spree::OptionType.find_by_name 'unit_weight' + ot = Spree::OptionType.find_by name: 'unit_weight' p.master.update_attributes!(unit_value: 1) p.reload @@ -579,57 +610,6 @@ module Spree end end - describe "stock filtering" do - it "considers products that are on_demand as being in stock" do - product = create(:simple_product, on_demand: true) - product.master.update_attribute(:on_hand, 0) - expect(product.has_stock?).to eq(true) - end - - describe "finding products in stock for a particular distribution" do - it "returns on-demand products" do - p = create(:simple_product, on_demand: true) - p.variants.first.update_attributes!(on_hand: 0, on_demand: true) - d = create(:distributor_enterprise) - oc = create(:simple_order_cycle, distributors: [d]) - oc.exchanges.outgoing.first.variants << p.variants.first - - expect(p).to have_stock_for_distribution(oc, d) - end - - it "returns products with in-stock variants" do - p = create(:simple_product) - v = create(:variant, product: p) - v.update_attribute(:on_hand, 1) - d = create(:distributor_enterprise) - oc = create(:simple_order_cycle, distributors: [d]) - oc.exchanges.outgoing.first.variants << v - - expect(p).to have_stock_for_distribution(oc, d) - end - - it "returns products with on-demand variants" do - p = create(:simple_product) - v = create(:variant, product: p, on_demand: true) - v.update_attribute(:on_hand, 0) - d = create(:distributor_enterprise) - oc = create(:simple_order_cycle, distributors: [d]) - oc.exchanges.outgoing.first.variants << v - - expect(p).to have_stock_for_distribution(oc, d) - end - - it "does not return products that have stock not in the distribution" do - p = create(:simple_product) - p.master.update_attribute(:on_hand, 1) - d = create(:distributor_enterprise) - oc = create(:simple_order_cycle, distributors: [d]) - - expect(p).not_to have_stock_for_distribution(oc, d) - end - end - end - describe "taxons" do let(:taxon1) { create(:taxon) } let(:taxon2) { create(:taxon) } diff --git a/spec/models/spree/user_spec.rb b/spec/models/spree/user_spec.rb index 7ed818fee2..0a5d8c439b 100644 --- a/spec/models/spree/user_spec.rb +++ b/spec/models/spree/user_spec.rb @@ -190,14 +190,6 @@ describe Spree.user_class do expect(create(:user).admin?).to be_falsey end - context '#create' do - let(:user) { build(:user) } - - it 'should not be anonymous' do - expect(user).not_to be_anonymous - end - end - context '#destroy' do it 'can not delete if it has completed orders' do order = build(:order, completed_at: Time.zone.now) @@ -207,20 +199,4 @@ describe Spree.user_class do expect { user.destroy }.to raise_exception(Spree::User::DestroyWithOrdersError) end end - - context 'anonymous!' do - let(:user) { Spree::User.anonymous! } - - it 'should create a new user' do - expect(user.new_record?).to be_falsey - end - - it 'should create a user with an example.net email' do - expect(user.email).to match(/@example.net$/) - end - - it 'should be anonymous' do - expect(user).to be_anonymous - end - end end diff --git a/spec/models/spree/variant_spec.rb b/spec/models/spree/variant_spec.rb index 39ac4bcead..d4889e6b4f 100644 --- a/spec/models/spree/variant_spec.rb +++ b/spec/models/spree/variant_spec.rb @@ -459,7 +459,7 @@ module Spree describe "deleting unit option values" do before do p = create(:simple_product, variant_unit: 'weight', variant_unit_scale: 1) - ot = Spree::OptionType.find_by_name 'unit_weight' + ot = Spree::OptionType.find_by name: 'unit_weight' @v = create(:variant, product: p) end diff --git a/spec/models/tag_rule/discount_order_spec.rb b/spec/models/tag_rule/discount_order_spec.rb index d4e30a6d95..2a1260f7e3 100644 --- a/spec/models/tag_rule/discount_order_spec.rb +++ b/spec/models/tag_rule/discount_order_spec.rb @@ -31,7 +31,7 @@ describe TagRule::DiscountOrder, type: :model do pending "determining whether a the rule has already been applied to an order" do let!(:order) { create(:order) } - let!(:adjustment) { order.adjustments.create({ amount: 12.34, source: order, originator: tag_rule, label: 'discount' }, without_protection: true) } + let!(:adjustment) { order.adjustments.create({ amount: 12.34, source: order, originator: tag_rule, label: 'discount' }) } before do tag_rule.context = { subject: order } diff --git a/spec/requests/large_request_spec.rb b/spec/requests/large_request_spec.rb index 6e389d5ecb..9a5e668aa7 100644 --- a/spec/requests/large_request_spec.rb +++ b/spec/requests/large_request_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe 'A very large request', type: :request do it 'should not overflow cookies' do - get '/admin', foo: 'x' * ActionDispatch::Cookies::SignedCookieJar::MAX_COOKIE_SIZE + get '/admin', foo: 'x' * ActionDispatch::Cookies::MAX_COOKIE_SIZE expect(response.status).to eq(302) # HTTP status 302 - Found ## Use the newer syntax if rspec gets upgraded # expect(response).to have_http_status(:redirect) diff --git a/spec/services/bulk_invoice_service_spec.rb b/spec/services/bulk_invoice_service_spec.rb index 4056a1b88f..687e680bcc 100644 --- a/spec/services/bulk_invoice_service_spec.rb +++ b/spec/services/bulk_invoice_service_spec.rb @@ -47,4 +47,25 @@ describe BulkInvoiceService do expect(filepath).to eq 'tmp/invoices/1234567.pdf' end end + + describe "#orders_from" do + let(:renderer) { InvoiceRenderer.new } + + before do + allow(InvoiceRenderer).to receive(:new).and_return(renderer) + end + + it "orders with completed desc" do + order_old = create(:order_with_distributor, :completed, completed_at: 2.minutes.ago) + order_oldest = create(:order_with_distributor, :completed, completed_at: 4.minutes.ago) + order_older = create(:order_with_distributor, :completed, completed_at: 3.minutes.ago) + + expect(renderer).to receive(:render_to_string).with(order_old).ordered.and_return("") + expect(renderer).to receive(:render_to_string).with(order_older).ordered.and_return("") + expect(renderer).to receive(:render_to_string).with(order_oldest).ordered.and_return("") + + order_ids = [order_oldest, order_old, order_older].map(&:id) + service.start_pdf_job_without_delay(order_ids) + end + end end diff --git a/spec/services/checkout/form_data_adapter_spec.rb b/spec/services/checkout/form_data_adapter_spec.rb index b1b92b3053..be248a2af0 100644 --- a/spec/services/checkout/form_data_adapter_spec.rb +++ b/spec/services/checkout/form_data_adapter_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' describe Checkout::FormDataAdapter do - describe '#order_params' do + describe '#params' do let(:params) { { order: { order_id: "123" } } } let(:order) { create(:order) } let(:user) { create(:user) } @@ -11,9 +11,7 @@ describe Checkout::FormDataAdapter do let(:adapter) { Checkout::FormDataAdapter.new(params, order, user) } it "returns the :order item in the params provided" do - order_params = adapter.order_params - - expect(order_params).to eq params[:order] + expect(adapter.params[:order]).to eq params[:order] end describe "when payment_attributes are provided" do @@ -25,9 +23,7 @@ describe Checkout::FormDataAdapter do before { params[:payment_source] = { "123" => source_attributes } } it "moves payment source attributes to the order payment attributes" do - order_params = adapter.order_params - - expect(order_params[:payments_attributes]. + expect(adapter.params[:order][:payments_attributes]. first[:source_attributes]).to eq source_attributes end end @@ -36,9 +32,7 @@ describe Checkout::FormDataAdapter do before { order.total = "50.0" } it "sets the payment attributes amount to the order total" do - order_params = adapter.order_params - - expect(order_params[:payments_attributes].first[:amount]).to eq order.total + expect(adapter.params[:order][:payments_attributes].first[:amount]).to eq order.total end end @@ -51,10 +45,8 @@ describe Checkout::FormDataAdapter do before { params[:order][:existing_card_id] = credit_card.id } it "adds card details to payment attributes" do - order_params = adapter.order_params - - expect(order_params[:payments_attributes].first[:source][:id]).to eq credit_card.id - expect(order_params[:payments_attributes]. + expect(adapter.params[:order][:payments_attributes].first[:source][:id]).to eq credit_card.id + expect(adapter.params[:order][:payments_attributes]. first[:source][:last_digits]).to eq credit_card.last_digits end end @@ -63,7 +55,7 @@ describe Checkout::FormDataAdapter do let(:credit_card) { create(:credit_card) } it "raises exception if credit card provided doesnt belong to the current user" do - expect { adapter.order_params }.to raise_error Spree::Core::GatewayError + expect { adapter.params[:order] }.to raise_error Spree::Core::GatewayError end end end diff --git a/spec/services/default_stock_location_spec.rb b/spec/services/default_stock_location_spec.rb index 8d91d7da83..3bd3a1eb26 100644 --- a/spec/services/default_stock_location_spec.rb +++ b/spec/services/default_stock_location_spec.rb @@ -8,13 +8,13 @@ describe DefaultStockLocation do end it 'sets the location in the default country' do - default_country = Spree::Country.find_by_iso(ENV['DEFAULT_COUNTRY_CODE']) + default_country = Spree::Country.find_by(iso: ENV['DEFAULT_COUNTRY_CODE']) stock_location = described_class.create! expect(stock_location.country).to eq(default_country) end it 'sets the first state in the country' do - default_country = Spree::Country.find_by_iso(ENV['DEFAULT_COUNTRY_CODE']) + default_country = Spree::Country.find_by(iso: ENV['DEFAULT_COUNTRY_CODE']) stock_location = described_class.create! expect(stock_location.state).to eq(default_country.states.first) end diff --git a/spec/services/exchange_products_renderer_spec.rb b/spec/services/exchange_products_renderer_spec.rb index 3293d27709..9e93611f7c 100644 --- a/spec/services/exchange_products_renderer_spec.rb +++ b/spec/services/exchange_products_renderer_spec.rb @@ -36,7 +36,7 @@ describe ExchangeProductsRenderer do expect(variants.first.product.supplier.name).to eq exchange.variants.first.product.supplier.name end - describe "when OC is showing only the coordinators inventory" do + xdescribe "when OC is showing only the coordinators inventory" do let(:exchange_with_visible_variant) { order_cycle.exchanges.incoming.second } let(:exchange_with_hidden_variant) { order_cycle.exchanges.incoming.first } let!(:visible_inventory_item) { create(:inventory_item, enterprise: order_cycle.coordinator, variant: exchange_with_visible_variant.variants.first, visible: true) } diff --git a/spec/services/order_cycle_form_spec.rb b/spec/services/order_cycle_form_spec.rb index e4d5d144d1..a085961e26 100644 --- a/spec/services/order_cycle_form_spec.rb +++ b/spec/services/order_cycle_form_spec.rb @@ -1,3 +1,4 @@ +require 'spec_helper' require 'order_management/subscriptions/proxy_order_syncer' describe OrderCycleForm do @@ -8,7 +9,7 @@ describe OrderCycleForm do let(:form) { OrderCycleForm.new(order_cycle, params, shop.owner) } context "when creation is successful" do - let(:params) { { order_cycle: { name: "Test Order Cycle", coordinator_id: shop.id } } } + let(:params) { { name: "Test Order Cycle", coordinator_id: shop.id } } it "returns true" do expect do @@ -18,7 +19,7 @@ describe OrderCycleForm do end context "when creation fails" do - let(:params) { { order_cycle: { name: "Test Order Cycle" } } } + let(:params) { { name: "Test Order Cycle" } } it "returns false" do expect do @@ -34,7 +35,7 @@ describe OrderCycleForm do let(:form) { OrderCycleForm.new(order_cycle, params, shop.owner) } context "when update is successful" do - let(:params) { { order_cycle: { name: "Test Order Cycle", coordinator_id: shop.id } } } + let(:params) { { name: "Test Order Cycle", coordinator_id: shop.id } } it "returns true" do expect do @@ -44,7 +45,7 @@ describe OrderCycleForm do end context "when updating fails" do - let(:params) { { order_cycle: { name: nil } } } + let(:params) { { name: nil } } it "returns false" do expect do @@ -75,7 +76,7 @@ describe OrderCycleForm do end context "and I add an schedule that I own, and remove another that I own" do - let(:params) { { order_cycle: { schedule_ids: [coordinated_schedule2.id] } } } + let(:params) { { schedule_ids: [coordinated_schedule2.id] } } it "associates the order cycle to the schedule" do expect(form.save).to be true @@ -86,7 +87,7 @@ describe OrderCycleForm do end context "and I add a schedule that I don't own" do - let(:params) { { order_cycle: { schedule_ids: [coordinated_schedule.id, uncoordinated_schedule.id] } } } + let(:params) { { schedule_ids: [coordinated_schedule.id, uncoordinated_schedule.id] } } it "ignores the schedule that I don't own" do expect(form.save).to be true @@ -97,7 +98,7 @@ describe OrderCycleForm do end context "when I make no changes to the schedule ids" do - let(:params) { { order_cycle: { schedule_ids: [coordinated_schedule.id] } } } + let(:params) { { schedule_ids: [coordinated_schedule.id] } } it "ignores the schedule that I don't own" do expect(form.save).to be true @@ -113,7 +114,7 @@ describe OrderCycleForm do let(:order_cycle) { create(:simple_order_cycle) } let(:form_applicator_mock) { instance_double(OpenFoodNetwork::OrderCycleFormApplicator) } let(:form) { OrderCycleForm.new(order_cycle, params, user) } - let(:params) { { order_cycle: { name: 'Some new name' } } } + let(:params) { { name: 'Some new name' } } before do allow(OpenFoodNetwork::OrderCycleFormApplicator).to receive(:new) { form_applicator_mock } @@ -122,7 +123,7 @@ describe OrderCycleForm do context "when exchange params are provided" do let(:exchange_params) { { incoming_exchanges: [], outgoing_exchanges: [] } } - before { params[:order_cycle].merge!(exchange_params) } + before { params.merge!(exchange_params) } it "runs the OrderCycleFormApplicator, and saves other changes" do expect(form.save).to be true diff --git a/spec/services/order_factory_spec.rb b/spec/services/order_factory_spec.rb index 85e27881a5..c67cbaaf0e 100644 --- a/spec/services/order_factory_spec.rb +++ b/spec/services/order_factory_spec.rb @@ -149,7 +149,7 @@ describe OrderFactory do end def variant1_line_item - order.line_items.find_by_variant_id(variant1.id) + order.line_items.find_by(variant_id: variant1.id) end end end diff --git a/spec/services/order_syncer_spec.rb b/spec/services/order_syncer_spec.rb index 87f5a8efd3..21790656ad 100644 --- a/spec/services/order_syncer_spec.rb +++ b/spec/services/order_syncer_spec.rb @@ -416,7 +416,7 @@ describe OrderSyncer do line_items = Spree::LineItem.where(order_id: subscription.orders, variant_id: sli.variant_id) expect(line_items.map(&:quantity)).to eq [1] expect(order.reload.total.to_f).to eq 59.97 - line_item = order.line_items.find_by_variant_id(sli.variant_id) + line_item = order.line_items.find_by(variant_id: sli.variant_id) expect(syncer.order_update_issues[order.id]).to include "#{line_item.product.name} - #{line_item.variant.full_name} - Insufficient stock available" end @@ -427,7 +427,7 @@ describe OrderSyncer do expect(syncer.sync!).to be true - line_item = order.line_items.find_by_variant_id(sli.variant_id) + line_item = order.line_items.find_by(variant_id: sli.variant_id) expect(syncer.order_update_issues[order.id]).to include "#{line_item.product.name} - #{line_item.variant.full_name} - Out of Stock" end end @@ -436,7 +436,7 @@ describe OrderSyncer do context "where the quantity of the item on an initialised order has already been changed" do let(:params) { { subscription_line_items_attributes: [{ id: sli.id, quantity: 3 }] } } let(:syncer) { OrderSyncer.new(subscription) } - let(:changed_line_item) { order.line_items.find_by_variant_id(sli.variant_id) } + let(:changed_line_item) { order.line_items.find_by(variant_id: sli.variant_id) } before { variant.update_attribute(:on_hand, 3) } diff --git a/spec/services/order_tax_adjustments_fetcher_spec.rb b/spec/services/order_tax_adjustments_fetcher_spec.rb new file mode 100644 index 0000000000..e56e40d5af --- /dev/null +++ b/spec/services/order_tax_adjustments_fetcher_spec.rb @@ -0,0 +1,69 @@ +require "spec_helper" + +describe OrderTaxAdjustmentsFetcher do + describe "#totals" do + let(:zone) { create(:zone_with_member) } + let(:coordinator) { create(:distributor_enterprise, charges_sales_tax: true) } + + let(:tax_rate10) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.1, zone: zone) } + let(:tax_rate15) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.15, zone: zone) } + let(:tax_rate20) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.2, zone: zone) } + let(:tax_rate25) { create(:tax_rate, included_in_price: true, calculator: Spree::Calculator::DefaultTax.new, amount: 0.25, zone: zone) } + let(:tax_category10) { create(:tax_category, tax_rates: [tax_rate10]) } + let(:tax_category15) { create(:tax_category, tax_rates: [tax_rate15]) } + let(:tax_category20) { create(:tax_category, tax_rates: [tax_rate20]) } + let(:tax_category25) { create(:tax_category, tax_rates: [tax_rate25]) } + + let(:variant) { create(:variant, product: create(:product, tax_category: tax_category10)) } + let(:enterprise_fee) { create(:enterprise_fee, enterprise: coordinator, tax_category: tax_category20, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 48.0)) } + let(:additional_adjustment) { create(:adjustment, amount: 50.0, included_tax: tax_rate25.compute_tax(50.0)) } + + let(:order_cycle) { create(:simple_order_cycle, coordinator: coordinator, coordinator_fees: [enterprise_fee], distributors: [coordinator], variants: [variant]) } + let(:line_item) { create(:line_item, variant: variant, price: 44.0) } + let(:order) do + create( + :order, + line_items: [line_item], + bill_address: create(:address), + order_cycle: order_cycle, + distributor: coordinator, + adjustments: [additional_adjustment] + ) + end + + before do + allow(Spree::Config).to receive(:shipment_inc_vat).and_return(true) + allow(Spree::Config).to receive(:shipping_tax_rate).and_return(tax_rate15.amount) + end + + let(:shipping_method) { create(:shipping_method, calculator: Spree::Calculator::FlatRate.new(preferred_amount: 46.0)) } + let!(:shipment) { create(:shipment_with, :shipping_method, shipping_method: shipping_method, order: order) } + + before do + order.create_tax_charge! + order.update_distribution_charge! + end + + subject { OrderTaxAdjustmentsFetcher.new(order).totals } + + it "returns a hash with all 3 taxes" do + expect(subject.size).to eq(4) + end + + it "contains tax on line_item" do + expect(subject[tax_rate10]).to eq(4.0) + end + + it "contains tax on shipping_fee" do + expect(subject[tax_rate15]).to eq(6.0) + end + + it "contains tax on enterprise_fee" do + expect(subject[tax_rate20]).to eq(8.0) + end + + it "contains tax on order adjustment" do + expect(subject[tax_rate25]).to eq(10.0) + end + end +end diff --git a/spec/services/permitted_attributes/order_cycle_spec.rb b/spec/services/permitted_attributes/order_cycle_spec.rb new file mode 100644 index 0000000000..f91f358aab --- /dev/null +++ b/spec/services/permitted_attributes/order_cycle_spec.rb @@ -0,0 +1,42 @@ +require 'spec_helper' + +module PermittedAttributes + describe OrderCycle do + let(:oc_permitted_attributes) { PermittedAttributes::OrderCycle.new(params) } + + describe "with basic attributes" do + let(:params) { ActionController::Parameters.new(order_cycle: { id: "2", name: "First Order Cycle" } ) } + + it "keeps permitted and removes not permitted" do + permitted_attributes = oc_permitted_attributes.call + + expect(permitted_attributes[:id]).to be nil + expect(permitted_attributes[:name]).to eq "First Order Cycle" + end + end + + describe "nested incoming_exchanges attributes" do + let(:params) { ActionController::Parameters.new(order_cycle: { incoming_exchanges: [{ sender_id: "2", name: "Exchange Name", variants: [] }] } ) } + + it "keeps permitted and removes not permitted" do + permitted_attributes = oc_permitted_attributes.call + + exchange = permitted_attributes[:incoming_exchanges].first + expect(exchange[:name]).to be nil + expect(exchange[:sender_id]).to eq "2" + end + end + + describe "variants inside incoming_exchanges attributes" do + let(:params) { ActionController::Parameters.new(order_cycle: { incoming_exchanges: [{ variants: { "7" => true, "12" => true } }] } ) } + + it "keeps all variant_ids provided" do + permitted_attributes = oc_permitted_attributes.call + + exchange_variants = permitted_attributes[:incoming_exchanges].first[:variants] + expect(exchange_variants["7"]).to be true + expect(exchange_variants["12"]).to be true + end + end + end +end diff --git a/spec/services/permitted_attributes/user_spec.rb b/spec/services/permitted_attributes/user_spec.rb new file mode 100644 index 0000000000..8b98311efa --- /dev/null +++ b/spec/services/permitted_attributes/user_spec.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +require 'spec_helper' + +module PermittedAttributes + describe User do + describe "simple usage" do + let(:user_permitted_attributes) { PermittedAttributes::User.new(params) } + + describe "permits basic attributes" do + let(:params) { + ActionController::Parameters.new(user: { name: "John", + email: "email@example.com" } ) + } + + it "keeps permitted and removes not permitted" do + permitted_attributes = user_permitted_attributes.call + + expect(permitted_attributes[:name]).to be nil + expect(permitted_attributes[:email]).to eq "email@example.com" + end + + it "keeps extra permitted attributes" do + permitted_attributes = user_permitted_attributes.call([:name]) + + expect(permitted_attributes[:name]).to eq "John" + expect(permitted_attributes[:email]).to eq "email@example.com" + end + end + end + + describe "with custom resource_name" do + let(:user_permitted_attributes) { PermittedAttributes::User.new(params, :spree_user) } + let(:params) { + ActionController::Parameters.new(spree_user: { name: "John", + email: "email@example.com" } ) + } + + it "keeps permitted and removes not permitted" do + permitted_attributes = user_permitted_attributes.call + + expect(permitted_attributes[:name]).to be nil + expect(permitted_attributes[:email]).to eq "email@example.com" + end + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e145fa7909..3c60e24f65 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -24,6 +24,14 @@ require 'paper_trail/frameworks/rspec' require 'webdrivers' +require 'shoulda/matchers' +Shoulda::Matchers.configure do |config| + config.integrate do |with| + with.test_framework :rspec + with.library :rails + end +end + # Allow connections to phantomjs/selenium whilst raising errors # when connecting to external sites require 'webmock/rspec' @@ -36,7 +44,6 @@ WebMock.disable_net_connect!( # Requires supporting ruby files with custom matchers and macros, etc, # in spec/support/ and its subdirectories. Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f } -require 'spree/testing_support/controller_requests' require 'spree/testing_support/capybara_ext' require 'spree/api/testing_support/setup' require 'spree/testing_support/authorization_helpers' @@ -148,8 +155,8 @@ RSpec.configure do |config| config.include Spree::UrlHelpers config.include Spree::CheckoutHelpers config.include Spree::MoneyHelper - config.include Spree::TestingSupport::ControllerRequests, type: :controller config.include Spree::TestingSupport::Preferences + config.include ControllerRequestsHelper, type: :controller config.include Devise::TestHelpers, type: :controller config.extend Spree::Api::TestingSupport::Setup, type: :controller config.include OpenFoodNetwork::ApiHelper, type: :controller diff --git a/spec/support/controller_hacks.rb b/spec/support/controller_hacks.rb deleted file mode 100644 index 7645e87372..0000000000 --- a/spec/support/controller_hacks.rb +++ /dev/null @@ -1,34 +0,0 @@ -require 'active_support/all' - -module ControllerHacks - def api_get(action, params = {}, session = nil, flash = nil) - api_process(action, params, session, flash, "GET") - end - - def api_post(action, params = {}, session = nil, flash = nil) - api_process(action, params, session, flash, "POST") - end - - def api_put(action, params = {}, session = nil, flash = nil) - api_process(action, params, session, flash, "PUT") - end - - def api_delete(action, params = {}, session = nil, flash = nil) - api_process(action, params, session, flash, "DELETE") - end - - def api_process(action, params = {}, session = nil, flash = nil, method = "get") - scoping = respond_to?(:resource_scoping) ? resource_scoping : {} - process(action, - params. - merge(scoping). - reverse_merge!(use_route: :spree, format: :json), - session, - flash, - method) - end -end - -RSpec.configure do |config| - config.include ControllerHacks, type: :controller -end diff --git a/spec/support/controller_helper.rb b/spec/support/controller_helper.rb index f49907dbe0..b543555319 100644 --- a/spec/support/controller_helper.rb +++ b/spec/support/controller_helper.rb @@ -3,7 +3,7 @@ module OpenFoodNetwork def login_as_admin @admin_user ||= begin user = create(:user) - user.spree_roles << Spree::Role.find_or_create_by_name!('admin') + user.spree_roles << Spree::Role.find_or_create_by!(name: 'admin') user end diff --git a/spec/support/controller_requests_helper.rb b/spec/support/controller_requests_helper.rb new file mode 100644 index 0000000000..d9dee19e2f --- /dev/null +++ b/spec/support/controller_requests_helper.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require 'active_support/all' + +module ControllerRequestsHelper + def api_get(action, params = {}, session = nil, flash = nil) + process_json_action(action, params, session, flash, "GET") + end + + def api_post(action, params = {}, session = nil, flash = nil) + process_json_action(action, params, session, flash, "POST") + end + + def api_put(action, params = {}, session = nil, flash = nil) + process_json_action(action, params, session, flash, "PUT") + end + + def api_delete(action, params = {}, session = nil, flash = nil) + process_json_action(action, params, session, flash, "DELETE") + end + + def spree_get(action, params = {}, session = nil, flash = nil) + process_action_with_route(action, params, session, flash, "GET") + end + + def spree_post(action, params = {}, session = nil, flash = nil) + process_action_with_route(action, params, session, flash, "POST") + end + + def spree_put(action, params = {}, session = nil, flash = nil) + process_action_with_route(action, params, session, flash, "PUT") + end + + def spree_delete(action, params = {}, session = nil, flash = nil) + process_action_with_route(action, params, session, flash, "DELETE") + end + + private + + def process_json_action(action, params = {}, session = nil, flash = nil, method = "get") + process_action_with_route(action, + params.reverse_merge!(format: :json), + session, + flash, + method) + end + + def process_action_with_route(action, params = {}, session = nil, flash = nil, method = "GET") + process(action, + method, + params.reverse_merge!(use_route: :main_app), + session, + flash) + end +end diff --git a/spec/support/request/authentication_workflow.rb b/spec/support/request/authentication_workflow.rb index fb99f9e6ae..0eb32e3e7a 100644 --- a/spec/support/request/authentication_workflow.rb +++ b/spec/support/request/authentication_workflow.rb @@ -6,7 +6,7 @@ module AuthenticationWorkflow end def quick_login_as_admin - admin_role = Spree::Role.find_or_create_by_name!('admin') + admin_role = Spree::Role.find_or_create_by!(name: 'admin') admin_user = create(:user, password: 'passw0rd', password_confirmation: 'passw0rd', @@ -26,9 +26,14 @@ module AuthenticationWorkflow # TODO: Should probably just rename this to create_user def create_enterprise_user( attrs = {} ) - new_user = create(:user, attrs) - new_user.spree_roles = [] # for some reason unbeknown to me, this new user gets admin permissions by default. + new_user = build(:user, attrs) + new_user.spree_roles = [Spree::Role.find_or_create_by!(name: 'user')] new_user.save + if attrs.has_key? :enterprises + attrs[:enterprises].each do |enterprise| + enterprise.users << new_user + end + end new_user end @@ -42,7 +47,7 @@ module AuthenticationWorkflow end def login_to_consumer_section - user_role = Spree::Role.find_or_create_by_name!('user') + user_role = Spree::Role.find_or_create_by!(name: 'user') user = create_enterprise_user( email: 'someone@ofn.org', password: 'passw0rd', @@ -63,12 +68,6 @@ module AuthenticationWorkflow fill_in "password", with: user.password click_button "Login" end - - def use_api_as_unauthenticated_user - allow_any_instance_of(Api::BaseController).to receive(:spree_current_user) { - Spree::User.anonymous! - } - end end RSpec.configure do |config| diff --git a/spec/support/request/shop_workflow.rb b/spec/support/request/shop_workflow.rb index cde1437b04..e5123715e0 100644 --- a/spec/support/request/shop_workflow.rb +++ b/spec/support/request/shop_workflow.rb @@ -1,17 +1,17 @@ module ShopWorkflow def wait_for_cart first("#cart").click - within '.cart-dropdown' do + within '.cart-sidebar' do expect(page).to_not have_link "Updating cart..." end end def edit_cart wait_for_cart - within '.cart-dropdown' do - expect(page).to have_link "Edit your cart" + within '.cart-sidebar' do + expect(page).to have_link I18n.t('shared.menu.cart_sidebar.edit_cart') end - first("a.add_to_cart").click + first("a.edit-cart").click end def have_price(price) diff --git a/spec/support/request/ui_component_helper.rb b/spec/support/request/ui_component_helper.rb index 277d8ee88c..b23002e3d7 100644 --- a/spec/support/request/ui_component_helper.rb +++ b/spec/support/request/ui_component_helper.rb @@ -59,13 +59,13 @@ module UIComponentHelper end def have_in_cart(name) - show_cart - within "li.cart" do + toggle_cart + within ".cart-sidebar" do have_content name end end - def show_cart + def toggle_cart page.find("#cart").click end diff --git a/spec/support/seeds.rb b/spec/support/seeds.rb index 0a603a03e0..26cc7a46e0 100644 --- a/spec/support/seeds.rb +++ b/spec/support/seeds.rb @@ -5,14 +5,14 @@ # leaves them there when deleting the rest (see spec/spec_helper.rb). # You can add more entries here if you need them for your tests. -if Spree::Country.scoped.empty? - Spree::Country.create!({ "name" => "Australia", "iso3" => "AUS", "iso" => "AU", "iso_name" => "AUSTRALIA", "numcode" => "36" }, without_protection: true) - country = Spree::Country.find_by_name('Australia') - Spree::State.create!({ "name" => "Victoria", "abbr" => "Vic", :country => country }, without_protection: true) - Spree::State.create!({ "name" => "New South Wales", "abbr" => "NSW", :country => country }, without_protection: true) +if Spree::Country.where(nil).empty? + Spree::Country.create!({ "name" => "Australia", "iso3" => "AUS", "iso" => "AU", "iso_name" => "AUSTRALIA", "numcode" => "36" }) + country = Spree::Country.find_by(name: 'Australia') + Spree::State.create!({ "name" => "Victoria", "abbr" => "Vic", :country => country }) + Spree::State.create!({ "name" => "New South Wales", "abbr" => "NSW", :country => country }) end # Since the country seeding differs from other environments, the default # country id has to be updated here. This line can be removed as soon as the # default country id is replaced by something database independent. -Spree::Config.default_country_id = Spree::Country.find_by_name('Australia').id +Spree::Config.default_country_id = Spree::Country.find_by(name: 'Australia').id diff --git a/vendor/assets/javascripts/autocomplete.min.js b/vendor/assets/javascripts/autocomplete.min.js new file mode 100644 index 0000000000..a86832e175 --- /dev/null +++ b/vendor/assets/javascripts/autocomplete.min.js @@ -0,0 +1 @@ +var Autocomplete=function(){"use strict";function t(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function e(t,e){for(var n=0;n0&&void 0!==arguments[0]?arguments[0]:{},a=u.search,l=u.autoSelect,r=void 0!==l&&l,d=u.setValue,c=void 0===d?function(){}:d,h=u.setAttribute,p=void 0===h?function(){}:h,f=u.onUpdate,b=void 0===f?function(){}:f,v=u.onSubmit,g=void 0===v?function(){}:v,L=u.onShow,y=void 0===L?function(){}:L,w=u.onHide,m=void 0===w?function(){}:w,S=u.onLoading,x=void 0===S?function(){}:S,R=u.onLoaded,A=void 0===R?function(){}:R;t(this,e),n(this,"value",""),n(this,"searchCounter",0),n(this,"results",[]),n(this,"selectedIndex",-1),n(this,"handleInput",(function(t){var e=t.target.value;i.updateResults(e),i.value=e})),n(this,"handleKeyDown",(function(t){var e=t.key;switch(e){case"Up":case"Down":case"ArrowUp":case"ArrowDown":var n="ArrowUp"===e||"Up"===e?i.selectedIndex-1:i.selectedIndex+1;t.preventDefault(),i.handleArrows(n);break;case"Tab":i.selectResult();break;case"Enter":var s=i.results[i.selectedIndex];i.selectResult(),i.onSubmit(s);break;case"Esc":case"Escape":i.hideResults(),i.setValue();break;default:return}})),n(this,"handleFocus",(function(t){var e=t.target.value;i.updateResults(e),i.value=e})),n(this,"handleBlur",(function(){i.hideResults()})),n(this,"handleResultMouseDown",(function(t){t.preventDefault()})),n(this,"handleResultClick",(function(t){var e=t.target,n=s(e,"[data-result-index]");if(n){i.selectedIndex=parseInt(n.dataset.resultIndex,10);var o=i.results[i.selectedIndex];i.selectResult(),i.onSubmit(o)}})),n(this,"handleArrows",(function(t){var e=i.results.length;i.selectedIndex=(t%e+e)%e,i.onUpdate(i.results,i.selectedIndex)})),n(this,"selectResult",(function(){var t=i.results[i.selectedIndex];t&&i.setValue(t),i.hideResults()})),n(this,"updateResults",(function(t){var e=++i.searchCounter;i.onLoading(),i.search(t).then((function(t){e===i.searchCounter&&(i.results=t,i.onLoaded(),0!==i.results.length?(i.selectedIndex=i.autoSelect?0:-1,i.onUpdate(i.results,i.selectedIndex),i.showResults()):i.hideResults())}))})),n(this,"showResults",(function(){i.setAttribute("aria-expanded",!0),i.onShow()})),n(this,"hideResults",(function(){i.selectedIndex=-1,i.results=[],i.setAttribute("aria-expanded",!1),i.setAttribute("aria-activedescendant",""),i.onUpdate(i.results,i.selectedIndex),i.onHide()})),n(this,"checkSelectedResultVisible",(function(t){var e=t.querySelector('[data-result-index="'.concat(i.selectedIndex,'"]'));if(e){var n=t.getBoundingClientRect(),s=e.getBoundingClientRect();s.topn.bottom&&(t.scrollTop+=s.bottom-n.bottom)}})),this.search=o(a)?a:function(t){return Promise.resolve(a(t))},this.autoSelect=r,this.setValue=c,this.setAttribute=p,this.onUpdate=b,this.onSubmit=g,this.onShow=y,this.onHide=m,this.onLoading=x,this.onLoaded=A},a=0,l=function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"";return"".concat(t).concat(++a)},r=function(t,e){var n=t.getBoundingClientRect(),i=e.getBoundingClientRect();return n.bottom+i.height>window.innerHeight&&window.innerHeight-n.bottom0?"above":"below"},d=function(t,e,n){var i;return function(){var s=this,o=arguments,u=function(){i=null,n||t.apply(s,o)},a=n&&!i;clearTimeout(i),i=setTimeout(u,e),a&&t.apply(s,o)}},c=function(){function n(e,i,s){t(this,n),this.id="".concat(s,"-result-").concat(e),this.class="".concat(s,"-result"),this["data-result-index"]=e,this.role="option",e===i&&(this["aria-selected"]="true")}var i,s,o;return i=n,(s=[{key:"toString",value:function(){var t=this;return Object.keys(this).reduce((function(e,n){return"".concat(e," ").concat(n,'="').concat(t[n],'"')}),"")}}])&&e(i.prototype,s),o&&e(i,o),n}();return function e(i){var s=this,o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},a=o.search,h=o.onSubmit,p=void 0===h?function(){}:h,f=o.baseClass,b=void 0===f?"autocomplete":f,v=o.autoSelect,g=o.getResultValue,L=void 0===g?function(t){return t}:g,y=o.renderResult,w=o.debounceTime,m=void 0===w?0:w;t(this,e),n(this,"expanded",!1),n(this,"loading",!1),n(this,"position",{}),n(this,"resetPosition",!0),n(this,"initialize",(function(){s.root.style.position="relative",s.input.setAttribute("role","combobox"),s.input.setAttribute("autocomplete","off"),s.input.setAttribute("autocapitalize","off"),s.input.setAttribute("autocorrect","off"),s.input.setAttribute("spellcheck","false"),s.input.setAttribute("aria-autocomplete","list"),s.input.setAttribute("aria-haspopup","listbox"),s.input.setAttribute("aria-expanded","false"),s.resultList.setAttribute("role","listbox"),s.resultList.style.position="absolute",s.resultList.style.zIndex="1",s.resultList.style.width="100%",s.resultList.style.boxSizing="border-box",s.resultList.id||(s.resultList.id=l("".concat(s.baseClass,"-result-list-"))),s.input.setAttribute("aria-owns",s.resultList.id),document.body.addEventListener("click",s.handleDocumentClick),s.input.addEventListener("input",s.core.handleInput),s.input.addEventListener("keydown",s.core.handleKeyDown),s.input.addEventListener("focus",s.core.handleFocus),s.input.addEventListener("blur",s.core.handleBlur),s.resultList.addEventListener("mousedown",s.core.handleResultMouseDown),s.resultList.addEventListener("click",s.core.handleResultClick),s.updateStyle()})),n(this,"setAttribute",(function(t,e){s.input.setAttribute(t,e)})),n(this,"setValue",(function(t){s.input.value=t?s.getResultValue(t):""})),n(this,"renderResult",(function(t,e){return"
  • ").concat(s.getResultValue(t),"
  • ")})),n(this,"handleUpdate",(function(t,e){s.resultList.innerHTML="",t.forEach((function(t,n){var i=new c(n,e,s.baseClass),o=s.renderResult(t,i);"string"==typeof o?s.resultList.insertAdjacentHTML("beforeend",o):s.resultList.insertAdjacentElement("beforeend",o)})),s.input.setAttribute("aria-activedescendant",e>-1?"".concat(s.baseClass,"-result-").concat(e):""),s.resetPosition&&(s.resetPosition=!1,s.position=r(s.input,s.resultList),s.updateStyle()),s.core.checkSelectedResultVisible(s.resultList)})),n(this,"handleShow",(function(){s.expanded=!0,s.updateStyle()})),n(this,"handleHide",(function(){s.expanded=!1,s.resetPosition=!0,s.updateStyle()})),n(this,"handleLoading",(function(){s.loading=!0,s.updateStyle()})),n(this,"handleLoaded",(function(){s.loading=!1,s.updateStyle()})),n(this,"handleDocumentClick",(function(t){s.root.contains(t.target)||s.core.hideResults()})),n(this,"updateStyle",(function(){s.root.dataset.expanded=s.expanded,s.root.dataset.loading=s.loading,s.root.dataset.position=s.position,s.resultList.style.visibility=s.expanded?"visible":"hidden",s.resultList.style.pointerEvents=s.expanded?"auto":"none","below"===s.position?(s.resultList.style.bottom=null,s.resultList.style.top="100%"):(s.resultList.style.top=null,s.resultList.style.bottom="100%")})),this.root="string"==typeof i?document.querySelector(i):i,this.input=this.root.querySelector("input"),this.resultList=this.root.querySelector("ul"),this.baseClass=b,this.getResultValue=L,"function"==typeof y&&(this.renderResult=y);var S=new u({search:a,autoSelect:v,setValue:this.setValue,setAttribute:this.setAttribute,onUpdate:this.handleUpdate,onSubmit:p,onShow:this.handleShow,onHide:this.handleHide,onLoading:this.handleLoading,onLoaded:this.handleLoaded});m>0&&(S.handleInput=d(S.handleInput,m)),this.core=S,this.initialize()}}(); diff --git a/vendor/assets/javascripts/leaflet-1.6.0.js b/vendor/assets/javascripts/leaflet-1.6.0.js new file mode 100644 index 0000000000..bc9ef0f551 --- /dev/null +++ b/vendor/assets/javascripts/leaflet-1.6.0.js @@ -0,0 +1,5 @@ +/* @preserve + * Leaflet 1.6.0+Detached: 0c81bdf904d864fd12a286e3d1979f47aba17991.0c81bdf, a JS library for interactive maps. http://leafletjs.com + * (c) 2010-2019 Vladimir Agafonkin, (c) 2010-2011 CloudMade + */ +!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?i(exports):"function"==typeof define&&define.amd?define(["exports"],i):i(t.L={})}(this,function(t){"use strict";var i=Object.freeze;function h(t){var i,e,n,o;for(e=1,n=arguments.length;e=this.min.x&&e.x<=this.max.x&&i.y>=this.min.y&&e.y<=this.max.y},intersects:function(t){t=R(t);var i=this.min,e=this.max,n=t.min,o=t.max,s=o.x>=i.x&&n.x<=e.x,r=o.y>=i.y&&n.y<=e.y;return s&&r},overlaps:function(t){t=R(t);var i=this.min,e=this.max,n=t.min,o=t.max,s=o.x>i.x&&n.xi.y&&n.y=n.lat&&e.lat<=o.lat&&i.lng>=n.lng&&e.lng<=o.lng},intersects:function(t){t=D(t);var i=this._southWest,e=this._northEast,n=t.getSouthWest(),o=t.getNorthEast(),s=o.lat>=i.lat&&n.lat<=e.lat,r=o.lng>=i.lng&&n.lng<=e.lng;return s&&r},overlaps:function(t){t=D(t);var i=this._southWest,e=this._northEast,n=t.getSouthWest(),o=t.getNorthEast(),s=o.lat>i.lat&&n.lati.lng&&n.lng';var i=t.firstChild;return i.style.behavior="url(#default#VML)",i&&"object"==typeof i.adj}catch(t){return!1}}();function Bt(t){return 0<=navigator.userAgent.toLowerCase().indexOf(t)}var At=(Object.freeze||Object)({ie:it,ielt9:et,edge:nt,webkit:ot,android:st,android23:rt,androidStock:ht,opera:ut,chrome:lt,gecko:ct,safari:_t,phantom:dt,opera12:pt,win:mt,ie3d:ft,webkit3d:gt,gecko3d:vt,any3d:yt,mobile:xt,mobileWebkit:wt,mobileWebkit3d:Pt,msPointer:Lt,pointer:bt,touch:Tt,mobileOpera:zt,mobileGecko:Mt,retina:Ct,passiveEvents:Et,canvas:St,svg:Zt,vml:kt}),It=Lt?"MSPointerDown":"pointerdown",Ot=Lt?"MSPointerMove":"pointermove",Rt=Lt?"MSPointerUp":"pointerup",Nt=Lt?"MSPointerCancel":"pointercancel",Dt=["INPUT","SELECT","OPTION"],jt={},Wt=!1,Ht=0;function Ft(t,i,e,n){return"touchstart"===i?function(t,i,e){var n=a(function(t){if("mouse"!==t.pointerType&&t.MSPOINTER_TYPE_MOUSE&&t.pointerType!==t.MSPOINTER_TYPE_MOUSE){if(!(Dt.indexOf(t.target.tagName)<0))return;ji(t)}Gt(t,i)});t["_leaflet_touchstart"+e]=n,t.addEventListener(It,n,!1),Wt||(document.documentElement.addEventListener(It,Ut,!0),document.documentElement.addEventListener(Ot,Vt,!0),document.documentElement.addEventListener(Rt,qt,!0),document.documentElement.addEventListener(Nt,qt,!0),Wt=!0)}(t,e,n):"touchmove"===i?function(t,i,e){function n(t){(t.pointerType!==t.MSPOINTER_TYPE_MOUSE&&"mouse"!==t.pointerType||0!==t.buttons)&&Gt(t,i)}t["_leaflet_touchmove"+e]=n,t.addEventListener(Ot,n,!1)}(t,e,n):"touchend"===i&&function(t,i,e){function n(t){Gt(t,i)}t["_leaflet_touchend"+e]=n,t.addEventListener(Rt,n,!1),t.addEventListener(Nt,n,!1)}(t,e,n),this}function Ut(t){jt[t.pointerId]=t,Ht++}function Vt(t){jt[t.pointerId]&&(jt[t.pointerId]=t)}function qt(t){delete jt[t.pointerId],Ht--}function Gt(t,i){for(var e in t.touches=[],jt)t.touches.push(jt[e]);t.changedTouches=[t],i(t)}var Kt=Lt?"MSPointerDown":bt?"pointerdown":"touchstart",Yt=Lt?"MSPointerUp":bt?"pointerup":"touchend",Xt="_leaflet_";function Jt(t,o,i){var s,r,a=!1;function e(t){var i;if(bt){if(!nt||"mouse"===t.pointerType)return;i=Ht}else i=t.touches.length;if(!(1this.options.maxZoom)?this.setZoom(t):this},panInsideBounds:function(t,i){this._enforcingBounds=!0;var e=this.getCenter(),n=this._limitCenter(e,this._zoom,D(t));return e.equals(n)||this.panTo(n,i),this._enforcingBounds=!1,this},panInside:function(t,i){var e=I((i=i||{}).paddingTopLeft||i.padding||[0,0]),n=I(i.paddingBottomRight||i.padding||[0,0]),o=this.getCenter(),s=this.project(o),r=this.project(t),a=this.getPixelBounds(),h=a.getSize().divideBy(2),u=R([a.min.add(e),a.max.subtract(n)]);if(!u.contains(r)){this._enforcingBounds=!0;var l=s.subtract(r),c=I(r.x+l.x,r.y+l.y);(r.xu.max.x)&&(c.x=s.x-l.x,0u.max.y)&&(c.y=s.y-l.y,0=this.options.transform3DLimit&&this._resetView(this.getCenter(),this.getZoom())},_findEventTargets:function(t,i){for(var e,n=[],o="mouseout"===i||"mouseover"===i,s=t.target||t.srcElement,r=!1;s;){if((e=this._targets[u(s)])&&("click"===i||"preclick"===i)&&!t._simulated&&this._draggableMoved(e)){r=!0;break}if(e&&e.listens(i,!0)){if(o&&!Yi(s,t))break;if(n.push(e),o)break}if(s===this._container)break;s=s.parentNode}return n.length||r||o||!Yi(s,t)||(n=[this]),n},_handleDOMEvent:function(t){if(this._loaded&&!Ki(t)){var i=t.type;"mousedown"!==i&&"keypress"!==i&&"keyup"!==i&&"keydown"!==i||Mi(t.target||t.srcElement),this._fireDOMEvent(t,i)}},_mouseEvents:["click","dblclick","mouseover","mouseout","contextmenu"],_fireDOMEvent:function(t,i,e){if("click"===t.type){var n=h({},t);n.type="preclick",this._fireDOMEvent(n,n.type,e)}if(!t._stopped&&(e=(e||[]).concat(this._findEventTargets(t,i))).length){var o=e[0];"contextmenu"===i&&o.listens(i,!0)&&ji(t);var s={originalEvent:t};if("keypress"!==t.type&&"keydown"!==t.type&&"keyup"!==t.type){var r=o.getLatLng&&(!o._radius||o._radius<=10);s.containerPoint=r?this.latLngToContainerPoint(o.getLatLng()):this.mouseEventToContainerPoint(t),s.layerPoint=this.containerPointToLayerPoint(s.containerPoint),s.latlng=r?o.getLatLng():this.layerPointToLatLng(s.layerPoint)}for(var a=0;athis.options.zoomAnimationThreshold)return!1;var n=this.getZoomScale(i),o=this._getCenterOffset(t)._divideBy(1-1/n);return!(!0!==e.animate&&!this.getSize().contains(o))&&(M(function(){this._moveStart(!0,!1)._animateZoom(t,i,!0)},this),!0)},_animateZoom:function(t,i,e,n){this._mapPane&&(e&&(this._animatingZoom=!0,this._animateToCenter=t,this._animateToZoom=i,mi(this._mapPane,"leaflet-zoom-anim")),this.fire("zoomanim",{center:t,zoom:i,noUpdate:n}),setTimeout(a(this._onZoomTransitionEnd,this),250))},_onZoomTransitionEnd:function(){this._animatingZoom&&(this._mapPane&&fi(this._mapPane,"leaflet-zoom-anim"),this._animatingZoom=!1,this._move(this._animateToCenter,this._animateToZoom),M(function(){this._moveEnd(!0)},this))}});function Qi(t){return new te(t)}var te=S.extend({options:{position:"topright"},initialize:function(t){p(this,t)},getPosition:function(){return this.options.position},setPosition:function(t){var i=this._map;return i&&i.removeControl(this),this.options.position=t,i&&i.addControl(this),this},getContainer:function(){return this._container},addTo:function(t){this.remove(),this._map=t;var i=this._container=this.onAdd(t),e=this.getPosition(),n=t._controlCorners[e];return mi(i,"leaflet-control"),-1!==e.indexOf("bottom")?n.insertBefore(i,n.firstChild):n.appendChild(i),this._map.on("unload",this.remove,this),this},remove:function(){return this._map&&(li(this._container),this.onRemove&&this.onRemove(this._map),this._map.off("unload",this.remove,this),this._map=null),this},_refocusOnMap:function(t){this._map&&t&&0",n=document.createElement("div");return n.innerHTML=e,n.firstChild},_addItem:function(t){var i,e=document.createElement("label"),n=this._map.hasLayer(t.layer);t.overlay?((i=document.createElement("input")).type="checkbox",i.className="leaflet-control-layers-selector",i.defaultChecked=n):i=this._createRadioElement("leaflet-base-layers_"+u(this),n),this._layerControlInputs.push(i),i.layerId=u(t.layer),ki(i,"click",this._onInputClick,this);var o=document.createElement("span");o.innerHTML=" "+t.name;var s=document.createElement("div");return e.appendChild(s),s.appendChild(i),s.appendChild(o),(t.overlay?this._overlaysList:this._baseLayersList).appendChild(e),this._checkDisabledLayers(),e},_onInputClick:function(){var t,i,e=this._layerControlInputs,n=[],o=[];this._handlingClick=!0;for(var s=e.length-1;0<=s;s--)t=e[s],i=this._getLayer(t.layerId).layer,t.checked?n.push(i):t.checked||o.push(i);for(s=0;si.options.maxZoom},_expandIfNotCollapsed:function(){return this._map&&!this.options.collapsed&&this.expand(),this},_expand:function(){return this.expand()},_collapse:function(){return this.collapse()}}),ee=te.extend({options:{position:"topleft",zoomInText:"+",zoomInTitle:"Zoom in",zoomOutText:"−",zoomOutTitle:"Zoom out"},onAdd:function(t){var i="leaflet-control-zoom",e=ui("div",i+" leaflet-bar"),n=this.options;return this._zoomInButton=this._createButton(n.zoomInText,n.zoomInTitle,i+"-in",e,this._zoomIn),this._zoomOutButton=this._createButton(n.zoomOutText,n.zoomOutTitle,i+"-out",e,this._zoomOut),this._updateDisabled(),t.on("zoomend zoomlevelschange",this._updateDisabled,this),e},onRemove:function(t){t.off("zoomend zoomlevelschange",this._updateDisabled,this)},disable:function(){return this._disabled=!0,this._updateDisabled(),this},enable:function(){return this._disabled=!1,this._updateDisabled(),this},_zoomIn:function(t){!this._disabled&&this._map._zoomthis._map.getMinZoom()&&this._map.zoomOut(this._map.options.zoomDelta*(t.shiftKey?3:1))},_createButton:function(t,i,e,n,o){var s=ui("a",e,n);return s.innerHTML=t,s.href="#",s.title=i,s.setAttribute("role","button"),s.setAttribute("aria-label",i),Di(s),ki(s,"click",Wi),ki(s,"click",o,this),ki(s,"click",this._refocusOnMap,this),s},_updateDisabled:function(){var t=this._map,i="leaflet-disabled";fi(this._zoomInButton,i),fi(this._zoomOutButton,i),!this._disabled&&t._zoom!==t.getMinZoom()||mi(this._zoomOutButton,i),!this._disabled&&t._zoom!==t.getMaxZoom()||mi(this._zoomInButton,i)}});$i.mergeOptions({zoomControl:!0}),$i.addInitHook(function(){this.options.zoomControl&&(this.zoomControl=new ee,this.addControl(this.zoomControl))});var ne=te.extend({options:{position:"bottomleft",maxWidth:100,metric:!0,imperial:!0},onAdd:function(t){var i="leaflet-control-scale",e=ui("div",i),n=this.options;return this._addScales(n,i+"-line",e),t.on(n.updateWhenIdle?"moveend":"move",this._update,this),t.whenReady(this._update,this),e},onRemove:function(t){t.off(this.options.updateWhenIdle?"moveend":"move",this._update,this)},_addScales:function(t,i,e){t.metric&&(this._mScale=ui("div",i,e)),t.imperial&&(this._iScale=ui("div",i,e))},_update:function(){var t=this._map,i=t.getSize().y/2,e=t.distance(t.containerPointToLatLng([0,i]),t.containerPointToLatLng([this.options.maxWidth,i]));this._updateScales(e)},_updateScales:function(t){this.options.metric&&t&&this._updateMetric(t),this.options.imperial&&t&&this._updateImperial(t)},_updateMetric:function(t){var i=this._getRoundNum(t),e=i<1e3?i+" m":i/1e3+" km";this._updateScale(this._mScale,e,i/t)},_updateImperial:function(t){var i,e,n,o=3.2808399*t;5280Leaflet'},initialize:function(t){p(this,t),this._attributions={}},onAdd:function(t){for(var i in(t.attributionControl=this)._container=ui("div","leaflet-control-attribution"),Di(this._container),t._layers)t._layers[i].getAttribution&&this.addAttribution(t._layers[i].getAttribution());return this._update(),this._container},setPrefix:function(t){return this.options.prefix=t,this._update(),this},addAttribution:function(t){return t&&(this._attributions[t]||(this._attributions[t]=0),this._attributions[t]++,this._update()),this},removeAttribution:function(t){return t&&this._attributions[t]&&(this._attributions[t]--,this._update()),this},_update:function(){if(this._map){var t=[];for(var i in this._attributions)this._attributions[i]&&t.push(i);var e=[];this.options.prefix&&e.push(this.options.prefix),t.length&&e.push(t.join(", ")),this._container.innerHTML=e.join(" | ")}}});$i.mergeOptions({attributionControl:!0}),$i.addInitHook(function(){this.options.attributionControl&&(new oe).addTo(this)});te.Layers=ie,te.Zoom=ee,te.Scale=ne,te.Attribution=oe,Qi.layers=function(t,i,e){return new ie(t,i,e)},Qi.zoom=function(t){return new ee(t)},Qi.scale=function(t){return new ne(t)},Qi.attribution=function(t){return new oe(t)};var se=S.extend({initialize:function(t){this._map=t},enable:function(){return this._enabled||(this._enabled=!0,this.addHooks()),this},disable:function(){return this._enabled&&(this._enabled=!1,this.removeHooks()),this},enabled:function(){return!!this._enabled}});se.addTo=function(t,i){return t.addHandler(i,this),this};var re,ae={Events:Z},he=Tt?"touchstart mousedown":"mousedown",ue={mousedown:"mouseup",touchstart:"touchend",pointerdown:"touchend",MSPointerDown:"touchend"},le={mousedown:"mousemove",touchstart:"touchmove",pointerdown:"touchmove",MSPointerDown:"touchmove"},ce=k.extend({options:{clickTolerance:3},initialize:function(t,i,e,n){p(this,n),this._element=t,this._dragStartTarget=i||t,this._preventOutline=e},enable:function(){this._enabled||(ki(this._dragStartTarget,he,this._onDown,this),this._enabled=!0)},disable:function(){this._enabled&&(ce._dragging===this&&this.finishDrag(),Ai(this._dragStartTarget,he,this._onDown,this),this._enabled=!1,this._moved=!1)},_onDown:function(t){if(!t._simulated&&this._enabled&&(this._moved=!1,!pi(this._element,"leaflet-zoom-anim")&&!(ce._dragging||t.shiftKey||1!==t.which&&1!==t.button&&!t.touches||((ce._dragging=this)._preventOutline&&Mi(this._element),Ti(),Qt(),this._moving)))){this.fire("down");var i=t.touches?t.touches[0]:t,e=Ei(this._element);this._startPoint=new B(i.clientX,i.clientY),this._parentScale=Si(e),ki(document,le[t.type],this._onMove,this),ki(document,ue[t.type],this._onUp,this)}},_onMove:function(t){if(!t._simulated&&this._enabled)if(t.touches&&1i.max.x&&(e|=2),t.yi.max.y&&(e|=8),e}function ge(t,i,e,n){var o,s=i.x,r=i.y,a=e.x-s,h=e.y-r,u=a*a+h*h;return 0this._layersMaxZoom&&this.setZoom(this._layersMaxZoom),void 0===this.options.minZoom&&this._layersMinZoom&&this.getZoom()t.y!=n.y>t.y&&t.x<(n.x-e.x)*(t.y-e.y)/(n.y-e.y)+e.x&&(u=!u);return u||je.prototype._containsPoint.call(this,t,!0)}});var He=ke.extend({initialize:function(t,i){p(this,i),this._layers={},t&&this.addData(t)},addData:function(t){var i,e,n,o=v(t)?t:t.features;if(o){for(i=0,e=o.length;iu.x&&(l=s.x+n-u.x+h.x),s.x-l-a.x<0&&(l=s.x-a.x),s.y+e+h.y>u.y&&(c=s.y+e-u.y+h.y),s.y-c-a.y<0&&(c=s.y-a.y),(l||c)&&t.fire("autopanstart").panBy([l,c])}},_onCloseButtonClick:function(t){this._close(),Wi(t)},_getAnchor:function(){return I(this._source&&this._source._getPopupAnchor?this._source._getPopupAnchor():[0,0])}});$i.mergeOptions({closePopupOnClick:!0}),$i.include({openPopup:function(t,i,e){return t instanceof sn||(t=new sn(e).setContent(t)),i&&t.setLatLng(i),this.hasLayer(t)?this:(this._popup&&this._popup.options.autoClose&&this.closePopup(),this._popup=t,this.addLayer(t))},closePopup:function(t){return t&&t!==this._popup||(t=this._popup,this._popup=null),t&&this.removeLayer(t),this}}),Se.include({bindPopup:function(t,i){return t instanceof sn?(p(t,i),(this._popup=t)._source=this):(this._popup&&!i||(this._popup=new sn(i,this)),this._popup.setContent(t)),this._popupHandlersAdded||(this.on({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!0),this},unbindPopup:function(){return this._popup&&(this.off({click:this._openPopup,keypress:this._onKeyPress,remove:this.closePopup,move:this._movePopup}),this._popupHandlersAdded=!1,this._popup=null),this},openPopup:function(t,i){return this._popup&&this._map&&(i=this._popup._prepareOpen(this,t,i),this._map.openPopup(this._popup,i)),this},closePopup:function(){return this._popup&&this._popup._close(),this},togglePopup:function(t){return this._popup&&(this._popup._map?this.closePopup():this.openPopup(t)),this},isPopupOpen:function(){return!!this._popup&&this._popup.isOpen()},setPopupContent:function(t){return this._popup&&this._popup.setContent(t),this},getPopup:function(){return this._popup},_openPopup:function(t){var i=t.layer||t.target;this._popup&&this._map&&(Wi(t),i instanceof Re?this.openPopup(t.layer||t.target,t.latlng):this._map.hasLayer(this._popup)&&this._popup._source===i?this.closePopup():this.openPopup(i,t.latlng))},_movePopup:function(t){this._popup.setLatLng(t.latlng)},_onKeyPress:function(t){13===t.originalEvent.keyCode&&this._openPopup(t)}});var rn=on.extend({options:{pane:"tooltipPane",offset:[0,0],direction:"auto",permanent:!1,sticky:!1,interactive:!1,opacity:.9},onAdd:function(t){on.prototype.onAdd.call(this,t),this.setOpacity(this.options.opacity),t.fire("tooltipopen",{tooltip:this}),this._source&&this._source.fire("tooltipopen",{tooltip:this},!0)},onRemove:function(t){on.prototype.onRemove.call(this,t),t.fire("tooltipclose",{tooltip:this}),this._source&&this._source.fire("tooltipclose",{tooltip:this},!0)},getEvents:function(){var t=on.prototype.getEvents.call(this);return Tt&&!this.options.permanent&&(t.preclick=this._close),t},_close:function(){this._map&&this._map.closeTooltip(this)},_initLayout:function(){var t="leaflet-tooltip "+(this.options.className||"")+" leaflet-zoom-"+(this._zoomAnimated?"animated":"hide");this._contentNode=this._container=ui("div",t)},_updateLayout:function(){},_adjustPan:function(){},_setPosition:function(t){var i=this._map,e=this._container,n=i.latLngToContainerPoint(i.getCenter()),o=i.layerPointToContainerPoint(t),s=this.options.direction,r=e.offsetWidth,a=e.offsetHeight,h=I(this.options.offset),u=this._getAnchor();t="top"===s?t.add(I(-r/2+h.x,-a+h.y+u.y,!0)):"bottom"===s?t.subtract(I(r/2-h.x,-h.y,!0)):"center"===s?t.subtract(I(r/2+h.x,a/2-u.y+h.y,!0)):"right"===s||"auto"===s&&o.xthis.options.maxZoom||ethis.options.maxZoom||void 0!==this.options.minZoom&&oe.max.x)||!i.wrapLat&&(t.ye.max.y))return!1}if(!this.options.bounds)return!0;var n=this._tileCoordsToBounds(t);return D(this.options.bounds).overlaps(n)},_keyToBounds:function(t){return this._tileCoordsToBounds(this._keyToTileCoords(t))},_tileCoordsToNwSe:function(t){var i=this._map,e=this.getTileSize(),n=t.scaleBy(e),o=n.add(e);return[i.unproject(n,t.z),i.unproject(o,t.z)]},_tileCoordsToBounds:function(t){var i=this._tileCoordsToNwSe(t),e=new N(i[0],i[1]);return this.options.noWrap||(e=this._map.wrapLatLngBounds(e)),e},_tileCoordsToKey:function(t){return t.x+":"+t.y+":"+t.z},_keyToTileCoords:function(t){var i=t.split(":"),e=new B(+i[0],+i[1]);return e.z=+i[2],e},_removeTile:function(t){var i=this._tiles[t];i&&(li(i.el),delete this._tiles[t],this.fire("tileunload",{tile:i.el,coords:this._keyToTileCoords(t)}))},_initTile:function(t){mi(t,"leaflet-tile");var i=this.getTileSize();t.style.width=i.x+"px",t.style.height=i.y+"px",t.onselectstart=l,t.onmousemove=l,et&&this.options.opacity<1&&yi(t,this.options.opacity),st&&!rt&&(t.style.WebkitBackfaceVisibility="hidden")},_addTile:function(t,i){var e=this._getTilePos(t),n=this._tileCoordsToKey(t),o=this.createTile(this._wrapCoords(t),a(this._tileReady,this,t));this._initTile(o),this.createTile.length<2&&M(a(this._tileReady,this,t,null,o)),Pi(o,e),this._tiles[n]={el:o,coords:t,current:!0},i.appendChild(o),this.fire("tileloadstart",{tile:o,coords:t})},_tileReady:function(t,i,e){i&&this.fire("tileerror",{error:i,tile:e,coords:t});var n=this._tileCoordsToKey(t);(e=this._tiles[n])&&(e.loaded=+new Date,this._map._fadeAnimated?(yi(e.el,0),C(this._fadeFrame),this._fadeFrame=M(this._updateOpacity,this)):(e.active=!0,this._pruneTiles()),i||(mi(e.el,"leaflet-tile-loaded"),this.fire("tileload",{tile:e.el,coords:t})),this._noTilesToLoad()&&(this._loading=!1,this.fire("load"),et||!this._map._fadeAnimated?M(this._pruneTiles,this):setTimeout(a(this._pruneTiles,this),250)))},_getTilePos:function(t){return t.scaleBy(this.getTileSize()).subtract(this._level.origin)},_wrapCoords:function(t){var i=new B(this._wrapX?r(t.x,this._wrapX):t.x,this._wrapY?r(t.y,this._wrapY):t.y);return i.z=t.z,i},_pxBoundsToTileRange:function(t){var i=this.getTileSize();return new O(t.min.unscaleBy(i).floor(),t.max.unscaleBy(i).ceil().subtract([1,1]))},_noTilesToLoad:function(){for(var t in this._tiles)if(!this._tiles[t].loaded)return!1;return!0}});var un=hn.extend({options:{minZoom:0,maxZoom:18,subdomains:"abc",errorTileUrl:"",zoomOffset:0,tms:!1,zoomReverse:!1,detectRetina:!1,crossOrigin:!1},initialize:function(t,i){this._url=t,(i=p(this,i)).detectRetina&&Ct&&0')}}catch(t){return function(t){return document.createElement("<"+t+' xmlns="urn:schemas-microsoft.com:vml" class="lvml">')}}}(),fn={_initContainer:function(){this._container=ui("div","leaflet-vml-container")},_update:function(){this._map._animatingZoom||(_n.prototype._update.call(this),this.fire("update"))},_initPath:function(t){var i=t._container=mn("shape");mi(i,"leaflet-vml-shape "+(this.options.className||"")),i.coordsize="1 1",t._path=mn("path"),i.appendChild(t._path),this._updateStyle(t),this._layers[u(t)]=t},_addPath:function(t){var i=t._container;this._container.appendChild(i),t.options.interactive&&t.addInteractiveTarget(i)},_removePath:function(t){var i=t._container;li(i),t.removeInteractiveTarget(i),delete this._layers[u(t)]},_updateStyle:function(t){var i=t._stroke,e=t._fill,n=t.options,o=t._container;o.stroked=!!n.stroke,o.filled=!!n.fill,n.stroke?(i||(i=t._stroke=mn("stroke")),o.appendChild(i),i.weight=n.weight+"px",i.color=n.color,i.opacity=n.opacity,n.dashArray?i.dashStyle=v(n.dashArray)?n.dashArray.join(" "):n.dashArray.replace(/( *, *)/g," "):i.dashStyle="",i.endcap=n.lineCap.replace("butt","flat"),i.joinstyle=n.lineJoin):i&&(o.removeChild(i),t._stroke=null),n.fill?(e||(e=t._fill=mn("fill")),o.appendChild(e),e.color=n.fillColor||n.color,e.opacity=n.fillOpacity):e&&(o.removeChild(e),t._fill=null)},_updateCircle:function(t){var i=t._point.round(),e=Math.round(t._radius),n=Math.round(t._radiusY||e);this._setPath(t,t._empty()?"M0 0":"AL "+i.x+","+i.y+" "+e+","+n+" 0,23592600")},_setPath:function(t,i){t._path.v=i},_bringToFront:function(t){_i(t._container)},_bringToBack:function(t){di(t._container)}},gn=kt?mn:$,vn=_n.extend({getEvents:function(){var t=_n.prototype.getEvents.call(this);return t.zoomstart=this._onZoomStart,t},_initContainer:function(){this._container=gn("svg"),this._container.setAttribute("pointer-events","none"),this._rootGroup=gn("g"),this._container.appendChild(this._rootGroup)},_destroyContainer:function(){li(this._container),Ai(this._container),delete this._container,delete this._rootGroup,delete this._svgSize},_onZoomStart:function(){this._update()},_update:function(){if(!this._map._animatingZoom||!this._bounds){_n.prototype._update.call(this);var t=this._bounds,i=t.getSize(),e=this._container;this._svgSize&&this._svgSize.equals(i)||(this._svgSize=i,e.setAttribute("width",i.x),e.setAttribute("height",i.y)),Pi(e,t.min),e.setAttribute("viewBox",[t.min.x,t.min.y,i.x,i.y].join(" ")),this.fire("update")}},_initPath:function(t){var i=t._path=gn("path");t.options.className&&mi(i,t.options.className),t.options.interactive&&mi(i,"leaflet-interactive"),this._updateStyle(t),this._layers[u(t)]=t},_addPath:function(t){this._rootGroup||this._initContainer(),this._rootGroup.appendChild(t._path),t.addInteractiveTarget(t._path)},_removePath:function(t){li(t._path),t.removeInteractiveTarget(t._path),delete this._layers[u(t)]},_updatePath:function(t){t._project(),t._update()},_updateStyle:function(t){var i=t._path,e=t.options;i&&(e.stroke?(i.setAttribute("stroke",e.color),i.setAttribute("stroke-opacity",e.opacity),i.setAttribute("stroke-width",e.weight),i.setAttribute("stroke-linecap",e.lineCap),i.setAttribute("stroke-linejoin",e.lineJoin),e.dashArray?i.setAttribute("stroke-dasharray",e.dashArray):i.removeAttribute("stroke-dasharray"),e.dashOffset?i.setAttribute("stroke-dashoffset",e.dashOffset):i.removeAttribute("stroke-dashoffset")):i.setAttribute("stroke","none"),e.fill?(i.setAttribute("fill",e.fillColor||e.color),i.setAttribute("fill-opacity",e.fillOpacity),i.setAttribute("fill-rule",e.fillRule||"evenodd")):i.setAttribute("fill","none"))},_updatePoly:function(t,i){this._setPath(t,Q(t._parts,i))},_updateCircle:function(t){var i=t._point,e=Math.max(Math.round(t._radius),1),n="a"+e+","+(Math.max(Math.round(t._radiusY),1)||e)+" 0 1,0 ",o=t._empty()?"M0 0":"M"+(i.x-e)+","+i.y+n+2*e+",0 "+n+2*-e+",0 ";this._setPath(t,o)},_setPath:function(t,i){t._path.setAttribute("d",i)},_bringToFront:function(t){_i(t._path)},_bringToBack:function(t){di(t._path)}});function yn(t){return Zt||kt?new vn(t):null}kt&&vn.include(fn),$i.include({getRenderer:function(t){var i=t.options.renderer||this._getPaneRenderer(t.options.pane)||this.options.renderer||this._renderer;return i||(i=this._renderer=this._createRenderer()),this.hasLayer(i)||this.addLayer(i),i},_getPaneRenderer:function(t){if("overlayPane"===t||void 0===t)return!1;var i=this._paneRenderers[t];return void 0===i&&(i=this._createRenderer({pane:t}),this._paneRenderers[t]=i),i},_createRenderer:function(t){return this.options.preferCanvas&&pn(t)||yn(t)}});var xn=We.extend({initialize:function(t,i){We.prototype.initialize.call(this,this._boundsToLatLngs(t),i)},setBounds:function(t){return this.setLatLngs(this._boundsToLatLngs(t))},_boundsToLatLngs:function(t){return[(t=D(t)).getSouthWest(),t.getNorthWest(),t.getNorthEast(),t.getSouthEast()]}});vn.create=gn,vn.pointsToPath=Q,He.geometryToLayer=Fe,He.coordsToLatLng=Ve,He.coordsToLatLngs=qe,He.latLngToCoords=Ge,He.latLngsToCoords=Ke,He.getFeature=Ye,He.asFeature=Xe,$i.mergeOptions({boxZoom:!0});var wn=se.extend({initialize:function(t){this._map=t,this._container=t._container,this._pane=t._panes.overlayPane,this._resetStateTimeout=0,t.on("unload",this._destroy,this)},addHooks:function(){ki(this._container,"mousedown",this._onMouseDown,this)},removeHooks:function(){Ai(this._container,"mousedown",this._onMouseDown,this)},moved:function(){return this._moved},_destroy:function(){li(this._pane),delete this._pane},_resetState:function(){this._resetStateTimeout=0,this._moved=!1},_clearDeferredResetState:function(){0!==this._resetStateTimeout&&(clearTimeout(this._resetStateTimeout),this._resetStateTimeout=0)},_onMouseDown:function(t){if(!t.shiftKey||1!==t.which&&1!==t.button)return!1;this._clearDeferredResetState(),this._resetState(),Qt(),Ti(),this._startPoint=this._map.mouseEventToContainerPoint(t),ki(document,{contextmenu:Wi,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseMove:function(t){this._moved||(this._moved=!0,this._box=ui("div","leaflet-zoom-box",this._container),mi(this._container,"leaflet-crosshair"),this._map.fire("boxzoomstart")),this._point=this._map.mouseEventToContainerPoint(t);var i=new O(this._point,this._startPoint),e=i.getSize();Pi(this._box,i.min),this._box.style.width=e.x+"px",this._box.style.height=e.y+"px"},_finish:function(){this._moved&&(li(this._box),fi(this._container,"leaflet-crosshair")),ti(),zi(),Ai(document,{contextmenu:Wi,mousemove:this._onMouseMove,mouseup:this._onMouseUp,keydown:this._onKeyDown},this)},_onMouseUp:function(t){if((1===t.which||1===t.button)&&(this._finish(),this._moved)){this._clearDeferredResetState(),this._resetStateTimeout=setTimeout(a(this._resetState,this),0);var i=new N(this._map.containerPointToLatLng(this._startPoint),this._map.containerPointToLatLng(this._point));this._map.fitBounds(i).fire("boxzoomend",{boxZoomBounds:i})}},_onKeyDown:function(t){27===t.keyCode&&this._finish()}});$i.addInitHook("addHandler","boxZoom",wn),$i.mergeOptions({doubleClickZoom:!0});var Pn=se.extend({addHooks:function(){this._map.on("dblclick",this._onDoubleClick,this)},removeHooks:function(){this._map.off("dblclick",this._onDoubleClick,this)},_onDoubleClick:function(t){var i=this._map,e=i.getZoom(),n=i.options.zoomDelta,o=t.originalEvent.shiftKey?e-n:e+n;"center"===i.options.doubleClickZoom?i.setZoom(o):i.setZoomAround(t.containerPoint,o)}});$i.addInitHook("addHandler","doubleClickZoom",Pn),$i.mergeOptions({dragging:!0,inertia:!rt,inertiaDeceleration:3400,inertiaMaxSpeed:1/0,easeLinearity:.2,worldCopyJump:!1,maxBoundsViscosity:0});var Ln=se.extend({addHooks:function(){if(!this._draggable){var t=this._map;this._draggable=new ce(t._mapPane,t._container),this._draggable.on({dragstart:this._onDragStart,drag:this._onDrag,dragend:this._onDragEnd},this),this._draggable.on("predrag",this._onPreDragLimit,this),t.options.worldCopyJump&&(this._draggable.on("predrag",this._onPreDragWrap,this),t.on("zoomend",this._onZoomEnd,this),t.whenReady(this._onZoomEnd,this))}mi(this._map._container,"leaflet-grab leaflet-touch-drag"),this._draggable.enable(),this._positions=[],this._times=[]},removeHooks:function(){fi(this._map._container,"leaflet-grab"),fi(this._map._container,"leaflet-touch-drag"),this._draggable.disable()},moved:function(){return this._draggable&&this._draggable._moved},moving:function(){return this._draggable&&this._draggable._moving},_onDragStart:function(){var t=this._map;if(t._stop(),this._map.options.maxBounds&&this._map.options.maxBoundsViscosity){var i=D(this._map.options.maxBounds);this._offsetLimit=R(this._map.latLngToContainerPoint(i.getNorthWest()).multiplyBy(-1),this._map.latLngToContainerPoint(i.getSouthEast()).multiplyBy(-1).add(this._map.getSize())),this._viscosity=Math.min(1,Math.max(0,this._map.options.maxBoundsViscosity))}else this._offsetLimit=null;t.fire("movestart").fire("dragstart"),t.options.inertia&&(this._positions=[],this._times=[])},_onDrag:function(t){if(this._map.options.inertia){var i=this._lastTime=+new Date,e=this._lastPos=this._draggable._absPos||this._draggable._newPos;this._positions.push(e),this._times.push(i),this._prunePositions(i)}this._map.fire("move",t).fire("drag",t)},_prunePositions:function(t){for(;1i.max.x&&(t.x=this._viscousLimit(t.x,i.max.x)),t.y>i.max.y&&(t.y=this._viscousLimit(t.y,i.max.y)),this._draggable._newPos=this._draggable._startPos.add(t)}},_onPreDragWrap:function(){var t=this._worldWidth,i=Math.round(t/2),e=this._initialWorldOffset,n=this._draggable._newPos.x,o=(n-i+e)%t+i-e,s=(n+i+e)%t-i-e,r=Math.abs(o+e)i.getMaxZoom()&&1OpenStreetMap contributors' + }, + variants: { + Mapnik: {}, + DE: { + url: 'https://{s}.tile.openstreetmap.de/tiles/osmde/{z}/{x}/{y}.png', + options: { + maxZoom: 18 + } + }, + CH: { + url: 'https://tile.osm.ch/switzerland/{z}/{x}/{y}.png', + options: { + maxZoom: 18, + bounds: [[45, 5], [48, 11]] + } + }, + France: { + url: 'https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png', + options: { + maxZoom: 20, + attribution: '© Openstreetmap France | {attribution.OpenStreetMap}' + } + }, + HOT: { + url: 'https://{s}.tile.openstreetmap.fr/hot/{z}/{x}/{y}.png', + options: { + attribution: + '{attribution.OpenStreetMap}, ' + + 'Tiles style by Humanitarian OpenStreetMap Team ' + + 'hosted by OpenStreetMap France' + } + }, + BZH: { + url: 'https://tile.openstreetmap.bzh/br/{z}/{x}/{y}.png', + options: { + attribution: '{attribution.OpenStreetMap}, Tiles courtesy of Breton OpenStreetMap Team', + bounds: [[46.2, -5.5], [50, 0.7]] + } + } + } + }, + OpenSeaMap: { + url: 'https://tiles.openseamap.org/seamark/{z}/{x}/{y}.png', + options: { + attribution: 'Map data: © OpenSeaMap contributors' + } + }, + OpenPtMap: { + url: 'http://openptmap.org/tiles/{z}/{x}/{y}.png', + options: { + maxZoom: 17, + attribution: 'Map data: © OpenPtMap contributors' + } + }, + OpenTopoMap: { + url: 'https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', + options: { + maxZoom: 17, + attribution: 'Map data: {attribution.OpenStreetMap}, SRTM | Map style: © OpenTopoMap (CC-BY-SA)' + } + }, + OpenRailwayMap: { + url: 'https://{s}.tiles.openrailwaymap.org/standard/{z}/{x}/{y}.png', + options: { + maxZoom: 19, + attribution: 'Map data: {attribution.OpenStreetMap} | Map style: © OpenRailwayMap (CC-BY-SA)' + } + }, + OpenFireMap: { + url: 'http://openfiremap.org/hytiles/{z}/{x}/{y}.png', + options: { + maxZoom: 19, + attribution: 'Map data: {attribution.OpenStreetMap} | Map style: © OpenFireMap (CC-BY-SA)' + } + }, + SafeCast: { + url: 'https://s3.amazonaws.com/te512.safecast.org/{z}/{x}/{y}.png', + options: { + maxZoom: 16, + attribution: 'Map data: {attribution.OpenStreetMap} | Map style: © SafeCast (CC-BY-SA)' + } + }, + Stadia: { + url: 'https://tiles.stadiamaps.com/tiles/alidade_smooth/{z}/{x}/{y}{r}.png', + options: { + maxZoom: 20, + attribution: '© Stadia Maps, © OpenMapTiles © OpenStreetMap contributors' + }, + variants: { + AlidadeSmooth: { + url: 'https://tiles.stadiamaps.com/tiles/alidade_smooth/{z}/{x}/{y}{r}.png' + }, + AlidadeSmoothDark: { + url: 'https://tiles.stadiamaps.com/tiles/alidade_smooth_dark/{z}/{x}/{y}{r}.png' + }, + OSMBright: { + url: 'https://tiles.stadiamaps.com/tiles/osm_bright/{z}/{x}/{y}{r}.png' + }, + Outdoors: { + url: 'https://tiles.stadiamaps.com/tiles/outdoors/{z}/{x}/{y}{r}.png' + } + } + }, + Thunderforest: { + url: 'https://{s}.tile.thunderforest.com/{variant}/{z}/{x}/{y}.png?apikey={apikey}', + options: { + attribution: + '© Thunderforest, {attribution.OpenStreetMap}', + variant: 'cycle', + apikey: '', + maxZoom: 22 + }, + variants: { + OpenCycleMap: 'cycle', + Transport: { + options: { + variant: 'transport' + } + }, + TransportDark: { + options: { + variant: 'transport-dark' + } + }, + SpinalMap: { + options: { + variant: 'spinal-map' + } + }, + Landscape: 'landscape', + Outdoors: 'outdoors', + Pioneer: 'pioneer', + MobileAtlas: 'mobile-atlas', + Neighbourhood: 'neighbourhood' + } + }, + CyclOSM: { + url: 'https://dev.{s}.tile.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png', + options: { + maxZoom: 20, + attribution: 'CyclOSM | Map data: {attribution.OpenStreetMap}' + } + }, + OpenMapSurfer: { + url: 'https://maps.heigit.org/openmapsurfer/tiles/{variant}/webmercator/{z}/{x}/{y}.png', + options: { + maxZoom: 19, + variant: 'roads', + attribution: 'Imagery from GIScience Research Group @ University of Heidelberg | Map data ' + }, + variants: { + Roads: { + options: { + variant: 'roads', + attribution: '{attribution.OpenMapSurfer}{attribution.OpenStreetMap}' + } + }, + Hybrid: { + options: { + variant: 'hybrid', + attribution: '{attribution.OpenMapSurfer}{attribution.OpenStreetMap}' + } + }, + AdminBounds: { + options: { + variant: 'adminb', + maxZoom: 18, + attribution: '{attribution.OpenMapSurfer}{attribution.OpenStreetMap}' + } + }, + ContourLines: { + options: { + variant: 'asterc', + maxZoom: 18, + minZoom: 13, + attribution: '{attribution.OpenMapSurfer} ASTER GDEM' + } + }, + Hillshade: { + options: { + variant: 'asterh', + maxZoom: 18, + attribution: '{attribution.OpenMapSurfer} ASTER GDEM, SRTM' + } + }, + ElementsAtRisk: { + options: { + variant: 'elements_at_risk', + attribution: '{attribution.OpenMapSurfer}{attribution.OpenStreetMap}' + } + } + } + }, + Hydda: { + url: 'https://{s}.tile.openstreetmap.se/hydda/{variant}/{z}/{x}/{y}.png', + options: { + maxZoom: 18, + variant: 'full', + attribution: 'Tiles courtesy of OpenStreetMap Sweden — Map data {attribution.OpenStreetMap}' + }, + variants: { + Full: 'full', + Base: 'base', + RoadsAndLabels: 'roads_and_labels' + } + }, + MapBox: { + url: 'https://api.tiles.mapbox.com/v4/{id}/{z}/{x}/{y}{r}.png?access_token={accessToken}', + options: { + attribution: + '© Mapbox ' + + '{attribution.OpenStreetMap} ' + + 'Improve this map', + subdomains: 'abcd', + id: 'mapbox.streets', + accessToken: '', + } + }, + Stamen: { + url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/{variant}/{z}/{x}/{y}{r}.{ext}', + options: { + attribution: + 'Map tiles by Stamen Design, ' + + 'CC BY 3.0 — ' + + 'Map data {attribution.OpenStreetMap}', + subdomains: 'abcd', + minZoom: 0, + maxZoom: 20, + variant: 'toner', + ext: 'png' + }, + variants: { + Toner: 'toner', + TonerBackground: 'toner-background', + TonerHybrid: 'toner-hybrid', + TonerLines: 'toner-lines', + TonerLabels: 'toner-labels', + TonerLite: 'toner-lite', + Watercolor: { + url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/{variant}/{z}/{x}/{y}.{ext}', + options: { + variant: 'watercolor', + ext: 'jpg', + minZoom: 1, + maxZoom: 16 + } + }, + Terrain: { + options: { + variant: 'terrain', + minZoom: 0, + maxZoom: 18 + } + }, + TerrainBackground: { + options: { + variant: 'terrain-background', + minZoom: 0, + maxZoom: 18 + } + }, + TerrainLabels: { + options: { + variant: 'terrain-labels', + minZoom: 0, + maxZoom: 18 + } + }, + TopOSMRelief: { + url: 'https://stamen-tiles-{s}.a.ssl.fastly.net/{variant}/{z}/{x}/{y}.{ext}', + options: { + variant: 'toposm-color-relief', + ext: 'jpg', + bounds: [[22, -132], [51, -56]] + } + }, + TopOSMFeatures: { + options: { + variant: 'toposm-features', + bounds: [[22, -132], [51, -56]], + opacity: 0.9 + } + } + } + }, + TomTom: { + url: 'https://{s}.api.tomtom.com/map/1/tile/{variant}/{style}/{z}/{x}/{y}.{ext}?key={apikey}', + options: { + variant: 'basic', + maxZoom: 22, + attribution: + '© 1992 - ' + new Date().getFullYear() + ' TomTom. ', + subdomains: 'abcd', + style: 'main', + ext: 'png', + apikey: '', + }, + variants: { + Basic: 'basic', + Hybrid: 'hybrid', + Labels: 'labels' + } + }, + Esri: { + url: 'https://server.arcgisonline.com/ArcGIS/rest/services/{variant}/MapServer/tile/{z}/{y}/{x}', + options: { + variant: 'World_Street_Map', + attribution: 'Tiles © Esri' + }, + variants: { + WorldStreetMap: { + options: { + attribution: + '{attribution.Esri} — ' + + 'Source: Esri, DeLorme, NAVTEQ, USGS, Intermap, iPC, NRCAN, Esri Japan, METI, Esri China (Hong Kong), Esri (Thailand), TomTom, 2012' + } + }, + DeLorme: { + options: { + variant: 'Specialty/DeLorme_World_Base_Map', + minZoom: 1, + maxZoom: 11, + attribution: '{attribution.Esri} — Copyright: ©2012 DeLorme' + } + }, + WorldTopoMap: { + options: { + variant: 'World_Topo_Map', + attribution: + '{attribution.Esri} — ' + + 'Esri, DeLorme, NAVTEQ, TomTom, Intermap, iPC, USGS, FAO, NPS, NRCAN, GeoBase, Kadaster NL, Ordnance Survey, Esri Japan, METI, Esri China (Hong Kong), and the GIS User Community' + } + }, + WorldImagery: { + options: { + variant: 'World_Imagery', + attribution: + '{attribution.Esri} — ' + + 'Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community' + } + }, + WorldTerrain: { + options: { + variant: 'World_Terrain_Base', + maxZoom: 13, + attribution: + '{attribution.Esri} — ' + + 'Source: USGS, Esri, TANA, DeLorme, and NPS' + } + }, + WorldShadedRelief: { + options: { + variant: 'World_Shaded_Relief', + maxZoom: 13, + attribution: '{attribution.Esri} — Source: Esri' + } + }, + WorldPhysical: { + options: { + variant: 'World_Physical_Map', + maxZoom: 8, + attribution: '{attribution.Esri} — Source: US National Park Service' + } + }, + OceanBasemap: { + options: { + variant: 'Ocean_Basemap', + maxZoom: 13, + attribution: '{attribution.Esri} — Sources: GEBCO, NOAA, CHS, OSU, UNH, CSUMB, National Geographic, DeLorme, NAVTEQ, and Esri' + } + }, + NatGeoWorldMap: { + options: { + variant: 'NatGeo_World_Map', + maxZoom: 16, + attribution: '{attribution.Esri} — National Geographic, Esri, DeLorme, NAVTEQ, UNEP-WCMC, USGS, NASA, ESA, METI, NRCAN, GEBCO, NOAA, iPC' + } + }, + WorldGrayCanvas: { + options: { + variant: 'Canvas/World_Light_Gray_Base', + maxZoom: 16, + attribution: '{attribution.Esri} — Esri, DeLorme, NAVTEQ' + } + } + } + }, + OpenWeatherMap: { + url: 'http://{s}.tile.openweathermap.org/map/{variant}/{z}/{x}/{y}.png?appid={apiKey}', + options: { + maxZoom: 19, + attribution: 'Map data © OpenWeatherMap', + apiKey:'', + opacity: 0.5 + }, + variants: { + Clouds: 'clouds', + CloudsClassic: 'clouds_cls', + Precipitation: 'precipitation', + PrecipitationClassic: 'precipitation_cls', + Rain: 'rain', + RainClassic: 'rain_cls', + Pressure: 'pressure', + PressureContour: 'pressure_cntr', + Wind: 'wind', + Temperature: 'temp', + Snow: 'snow' + } + }, + HERE: { + /* + * HERE maps, formerly Nokia maps. + * These basemaps are free, but you need an api id and app key. Please sign up at + * https://developer.here.com/plans + */ + url: + 'https://{s}.{base}.maps.api.here.com/maptile/2.1/' + + '{type}/{mapID}/{variant}/{z}/{x}/{y}/{size}/{format}?' + + 'app_id={app_id}&app_code={app_code}&lg={language}', + options: { + attribution: + 'Map © 1987-' + new Date().getFullYear() + ' HERE', + subdomains: '1234', + mapID: 'newest', + 'app_id': '', + 'app_code': '', + base: 'base', + variant: 'normal.day', + maxZoom: 20, + type: 'maptile', + language: 'eng', + format: 'png8', + size: '256' + }, + variants: { + normalDay: 'normal.day', + normalDayCustom: 'normal.day.custom', + normalDayGrey: 'normal.day.grey', + normalDayMobile: 'normal.day.mobile', + normalDayGreyMobile: 'normal.day.grey.mobile', + normalDayTransit: 'normal.day.transit', + normalDayTransitMobile: 'normal.day.transit.mobile', + normalDayTraffic: { + options: { + variant: 'normal.traffic.day', + base: 'traffic', + type: 'traffictile' + } + }, + normalNight: 'normal.night', + normalNightMobile: 'normal.night.mobile', + normalNightGrey: 'normal.night.grey', + normalNightGreyMobile: 'normal.night.grey.mobile', + normalNightTransit: 'normal.night.transit', + normalNightTransitMobile: 'normal.night.transit.mobile', + reducedDay: 'reduced.day', + reducedNight: 'reduced.night', + basicMap: { + options: { + type: 'basetile' + } + }, + mapLabels: { + options: { + type: 'labeltile', + format: 'png' + } + }, + trafficFlow: { + options: { + base: 'traffic', + type: 'flowtile' + } + }, + carnavDayGrey: 'carnav.day.grey', + hybridDay: { + options: { + base: 'aerial', + variant: 'hybrid.day' + } + }, + hybridDayMobile: { + options: { + base: 'aerial', + variant: 'hybrid.day.mobile' + } + }, + hybridDayTransit: { + options: { + base: 'aerial', + variant: 'hybrid.day.transit' + } + }, + hybridDayGrey: { + options: { + base: 'aerial', + variant: 'hybrid.grey.day' + } + }, + hybridDayTraffic: { + options: { + variant: 'hybrid.traffic.day', + base: 'traffic', + type: 'traffictile' + } + }, + pedestrianDay: 'pedestrian.day', + pedestrianNight: 'pedestrian.night', + satelliteDay: { + options: { + base: 'aerial', + variant: 'satellite.day' + } + }, + terrainDay: { + options: { + base: 'aerial', + variant: 'terrain.day' + } + }, + terrainDayMobile: { + options: { + base: 'aerial', + variant: 'terrain.day.mobile' + } + } + } + }, + HEREv3: { + /* + * HERE maps API Version 3. + * These basemaps are free, but you need an API key. Please sign up at + * https://developer.here.com/plans + * Version 3 deprecates the app_id and app_code access in favor of apiKey + * + * Supported access methods as of 2019/12/21: + * @see https://developer.here.com/faqs#access-control-1--how-do-you-control-access-to-here-location-services + */ + url: + 'https://{s}.{base}.maps.ls.hereapi.com/maptile/2.1/' + + '{type}/{mapID}/{variant}/{z}/{x}/{y}/{size}/{format}?' + + 'apiKey={apiKey}&lg={language}', + options: { + attribution: + 'Map © 1987-' + new Date().getFullYear() + ' HERE', + subdomains: '1234', + mapID: 'newest', + apiKey: '', + base: 'base', + variant: 'normal.day', + maxZoom: 20, + type: 'maptile', + language: 'eng', + format: 'png8', + size: '256' + }, + variants: { + normalDay: 'normal.day', + normalDayCustom: 'normal.day.custom', + normalDayGrey: 'normal.day.grey', + normalDayMobile: 'normal.day.mobile', + normalDayGreyMobile: 'normal.day.grey.mobile', + normalDayTransit: 'normal.day.transit', + normalDayTransitMobile: 'normal.day.transit.mobile', + normalNight: 'normal.night', + normalNightMobile: 'normal.night.mobile', + normalNightGrey: 'normal.night.grey', + normalNightGreyMobile: 'normal.night.grey.mobile', + normalNightTransit: 'normal.night.transit', + normalNightTransitMobile: 'normal.night.transit.mobile', + reducedDay: 'reduced.day', + reducedNight: 'reduced.night', + basicMap: { + options: { + type: 'basetile' + } + }, + mapLabels: { + options: { + type: 'labeltile', + format: 'png' + } + }, + trafficFlow: { + options: { + base: 'traffic', + type: 'flowtile' + } + }, + carnavDayGrey: 'carnav.day.grey', + hybridDay: { + options: { + base: 'aerial', + variant: 'hybrid.day' + } + }, + hybridDayMobile: { + options: { + base: 'aerial', + variant: 'hybrid.day.mobile' + } + }, + hybridDayTransit: { + options: { + base: 'aerial', + variant: 'hybrid.day.transit' + } + }, + hybridDayGrey: { + options: { + base: 'aerial', + variant: 'hybrid.grey.day' + } + }, + pedestrianDay: 'pedestrian.day', + pedestrianNight: 'pedestrian.night', + satelliteDay: { + options: { + base: 'aerial', + variant: 'satellite.day' + } + }, + terrainDay: { + options: { + base: 'aerial', + variant: 'terrain.day' + } + }, + terrainDayMobile: { + options: { + base: 'aerial', + variant: 'terrain.day.mobile' + } + } + } + }, + FreeMapSK: { + url: 'http://t{s}.freemap.sk/T/{z}/{x}/{y}.jpeg', + options: { + minZoom: 8, + maxZoom: 16, + subdomains: '1234', + bounds: [[47.204642, 15.996093], [49.830896, 22.576904]], + attribution: + '{attribution.OpenStreetMap}, vizualization CC-By-SA 2.0 Freemap.sk' + } + }, + MtbMap: { + url: 'http://tile.mtbmap.cz/mtbmap_tiles/{z}/{x}/{y}.png', + options: { + attribution: + '{attribution.OpenStreetMap} & USGS' + } + }, + CartoDB: { + url: 'https://{s}.basemaps.cartocdn.com/{variant}/{z}/{x}/{y}{r}.png', + options: { + attribution: '{attribution.OpenStreetMap} © CARTO', + subdomains: 'abcd', + maxZoom: 19, + variant: 'light_all' + }, + variants: { + Positron: 'light_all', + PositronNoLabels: 'light_nolabels', + PositronOnlyLabels: 'light_only_labels', + DarkMatter: 'dark_all', + DarkMatterNoLabels: 'dark_nolabels', + DarkMatterOnlyLabels: 'dark_only_labels', + Voyager: 'rastertiles/voyager', + VoyagerNoLabels: 'rastertiles/voyager_nolabels', + VoyagerOnlyLabels: 'rastertiles/voyager_only_labels', + VoyagerLabelsUnder: 'rastertiles/voyager_labels_under' + } + }, + HikeBike: { + url: 'https://tiles.wmflabs.org/{variant}/{z}/{x}/{y}.png', + options: { + maxZoom: 19, + attribution: '{attribution.OpenStreetMap}', + variant: 'hikebike' + }, + variants: { + HikeBike: {}, + HillShading: { + options: { + maxZoom: 15, + variant: 'hillshading' + } + } + } + }, + BasemapAT: { + url: 'https://maps{s}.wien.gv.at/basemap/{variant}/{type}/google3857/{z}/{y}/{x}.{format}', + options: { + maxZoom: 19, + attribution: 'Datenquelle: basemap.at', + subdomains: ['', '1', '2', '3', '4'], + type: 'normal', + format: 'png', + bounds: [[46.358770, 8.782379], [49.037872, 17.189532]], + variant: 'geolandbasemap' + }, + variants: { + basemap: { + options: { + maxZoom: 20, // currently only in Vienna + variant: 'geolandbasemap' + } + }, + grau: 'bmapgrau', + overlay: 'bmapoverlay', + terrain: { + options: { + variant: 'bmapgelaende', + type: 'grau', + format: 'jpeg' + } + }, + surface: { + options: { + variant: 'bmapoberflaeche', + type: 'grau', + format: 'jpeg' + } + }, + highdpi: { + options: { + variant: 'bmaphidpi', + format: 'jpeg' + } + }, + orthofoto: { + options: { + maxZoom: 20, // currently only in Vienna + variant: 'bmaporthofoto30cm', + format: 'jpeg' + } + } + } + }, + nlmaps: { + url: 'https://geodata.nationaalgeoregister.nl/tiles/service/wmts/{variant}/EPSG:3857/{z}/{x}/{y}.png', + options: { + minZoom: 6, + maxZoom: 19, + bounds: [[50.5, 3.25], [54, 7.6]], + attribution: 'Kaartgegevens © Kadaster' + }, + variants: { + 'standaard': 'brtachtergrondkaart', + 'pastel': 'brtachtergrondkaartpastel', + 'grijs': 'brtachtergrondkaartgrijs', + 'luchtfoto': { + 'url': 'https://geodata.nationaalgeoregister.nl/luchtfoto/rgb/wmts/2018_ortho25/EPSG:3857/{z}/{x}/{y}.png', + } + } + }, + NASAGIBS: { + url: 'https://map1.vis.earthdata.nasa.gov/wmts-webmerc/{variant}/default/{time}/{tilematrixset}{maxZoom}/{z}/{y}/{x}.{format}', + options: { + attribution: + 'Imagery provided by services from the Global Imagery Browse Services (GIBS), operated by the NASA/GSFC/Earth Science Data and Information System ' + + '(ESDIS) with funding provided by NASA/HQ.', + bounds: [[-85.0511287776, -179.999999975], [85.0511287776, 179.999999975]], + minZoom: 1, + maxZoom: 9, + format: 'jpg', + time: '', + tilematrixset: 'GoogleMapsCompatible_Level' + }, + variants: { + ModisTerraTrueColorCR: 'MODIS_Terra_CorrectedReflectance_TrueColor', + ModisTerraBands367CR: 'MODIS_Terra_CorrectedReflectance_Bands367', + ViirsEarthAtNight2012: { + options: { + variant: 'VIIRS_CityLights_2012', + maxZoom: 8 + } + }, + ModisTerraLSTDay: { + options: { + variant: 'MODIS_Terra_Land_Surface_Temp_Day', + format: 'png', + maxZoom: 7, + opacity: 0.75 + } + }, + ModisTerraSnowCover: { + options: { + variant: 'MODIS_Terra_Snow_Cover', + format: 'png', + maxZoom: 8, + opacity: 0.75 + } + }, + ModisTerraAOD: { + options: { + variant: 'MODIS_Terra_Aerosol', + format: 'png', + maxZoom: 6, + opacity: 0.75 + } + }, + ModisTerraChlorophyll: { + options: { + variant: 'MODIS_Terra_Chlorophyll_A', + format: 'png', + maxZoom: 7, + opacity: 0.75 + } + } + } + }, + NLS: { + // NLS maps are copyright National library of Scotland. + // http://maps.nls.uk/projects/api/index.html + // Please contact NLS for anything other than non-commercial low volume usage + // + // Map sources: Ordnance Survey 1:1m to 1:63K, 1920s-1940s + // z0-9 - 1:1m + // z10-11 - quarter inch (1:253440) + // z12-18 - one inch (1:63360) + url: 'https://nls-{s}.tileserver.com/nls/{z}/{x}/{y}.jpg', + options: { + attribution: 'National Library of Scotland Historic Maps', + bounds: [[49.6, -12], [61.7, 3]], + minZoom: 1, + maxZoom: 18, + subdomains: '0123', + } + }, + JusticeMap: { + // Justice Map (http://www.justicemap.org/) + // Visualize race and income data for your community, county and country. + // Includes tools for data journalists, bloggers and community activists. + url: 'http://www.justicemap.org/tile/{size}/{variant}/{z}/{x}/{y}.png', + options: { + attribution: 'Justice Map', + // one of 'county', 'tract', 'block' + size: 'county', + // Bounds for USA, including Alaska and Hawaii + bounds: [[14, -180], [72, -56]] + }, + variants: { + income: 'income', + americanIndian: 'indian', + asian: 'asian', + black: 'black', + hispanic: 'hispanic', + multi: 'multi', + nonWhite: 'nonwhite', + white: 'white', + plurality: 'plural' + } + }, + Wikimedia: { + url: 'https://maps.wikimedia.org/osm-intl/{z}/{x}/{y}{r}.png', + options: { + attribution: 'Wikimedia', + minZoom: 1, + maxZoom: 19 + } + }, + GeoportailFrance: { + url: 'https://wxs.ign.fr/{apikey}/geoportail/wmts?REQUEST=GetTile&SERVICE=WMTS&VERSION=1.0.0&STYLE={style}&TILEMATRIXSET=PM&FORMAT={format}&LAYER={variant}&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}', + options: { + attribution: 'Geoportail France', + bounds: [[-75, -180], [81, 180]], + minZoom: 2, + maxZoom: 18, + // Get your own geoportail apikey here : http://professionnels.ign.fr/ign/contrats/ + // NB : 'choisirgeoportail' is a demonstration key that comes with no guarantee + apikey: 'choisirgeoportail', + format: 'image/jpeg', + style : 'normal', + variant: 'GEOGRAPHICALGRIDSYSTEMS.MAPS.SCAN-EXPRESS.STANDARD' + }, + variants: { + parcels: { + options : { + variant: 'CADASTRALPARCELS.PARCELS', + maxZoom: 20, + style : 'bdparcellaire', + format: 'image/png' + } + }, + ignMaps: 'GEOGRAPHICALGRIDSYSTEMS.MAPS', + maps: 'GEOGRAPHICALGRIDSYSTEMS.MAPS.SCAN-EXPRESS.STANDARD', + orthos: { + options: { + maxZoom: 19, + variant: 'ORTHOIMAGERY.ORTHOPHOTOS' + } + } + } + }, + OneMapSG: { + url: 'https://maps-{s}.onemap.sg/v3/{variant}/{z}/{x}/{y}.png', + options: { + variant: 'Default', + minZoom: 11, + maxZoom: 18, + bounds: [[1.56073, 104.11475], [1.16, 103.502]], + attribution: ' New OneMap | Map data © contributors, Singapore Land Authority' + }, + variants: { + Default: 'Default', + Night: 'Night', + Original: 'Original', + Grey: 'Grey', + LandLot: 'LandLot' + } + } + }; + + L.tileLayer.provider = function (provider, options) { + return new L.TileLayer.Provider(provider, options); + }; + + return L; +})); diff --git a/vendor/assets/javascripts/spin.js b/vendor/assets/javascripts/spin.js deleted file mode 100644 index 2a8642f311..0000000000 --- a/vendor/assets/javascripts/spin.js +++ /dev/null @@ -1,319 +0,0 @@ -//fgnass.github.com/spin.js#v1.2.6 -!function(window, document, undefined) { - - /** - * Copyright (c) 2011 Felix Gnass [fgnass at neteye dot de] - * Licensed under the MIT license - */ - - var prefixes = ['webkit', 'Moz', 'ms', 'O'] /* Vendor prefixes */ - , animations = {} /* Animation rules keyed by their name */ - , useCssAnimations - - /** - * Utility function to create elements. If no tag name is given, - * a DIV is created. Optionally properties can be passed. - */ - function createEl(tag, prop) { - var el = document.createElement(tag || 'div') - , n - - for(n in prop) el[n] = prop[n] - return el - } - - /** - * Appends children and returns the parent. - */ - function ins(parent /* child1, child2, ...*/) { - for (var i=1, n=arguments.length; i> 1) : parseInt(o.left, 10) + mid) + 'px', - top: (o.top == 'auto' ? tp.y-ep.y + (target.offsetHeight >> 1) : parseInt(o.top, 10) + mid) + 'px' - }) - } - - el.setAttribute('aria-role', 'progressbar') - self.lines(el, self.opts) - - if (!useCssAnimations) { - // No CSS animation support, use setTimeout() instead - var i = 0 - , fps = o.fps - , f = fps/o.speed - , ostep = (1-o.opacity) / (f*o.trail / 100) - , astep = f/o.lines - - ;(function anim() { - i++; - for (var s=o.lines; s; s--) { - var alpha = Math.max(1-(i+s*astep)%f * ostep, o.opacity) - self.opacity(el, o.lines-s, alpha, o) - } - self.timeout = self.el && setTimeout(anim, ~~(1000/fps)) - })() - } - return self - }, - - stop: function() { - var el = this.el - if (el) { - clearTimeout(this.timeout) - if (el.parentNode) el.parentNode.removeChild(el) - this.el = undefined - } - return this - }, - - lines: function(el, o) { - var i = 0 - , seg - - function fill(color, shadow) { - return css(createEl(), { - position: 'absolute', - width: (o.length+o.width) + 'px', - height: o.width + 'px', - background: color, - boxShadow: shadow, - transformOrigin: 'left', - transform: 'rotate(' + ~~(360/o.lines*i+o.rotate) + 'deg) translate(' + o.radius+'px' +',0)', - borderRadius: (o.corners * o.width>>1) + 'px' - }) - } - - for (; i < o.lines; i++) { - seg = css(createEl(), { - position: 'absolute', - top: 1+~(o.width/2) + 'px', - transform: o.hwaccel ? 'translate3d(0,0,0)' : '', - opacity: o.opacity, - animation: useCssAnimations && addAnimation(o.opacity, o.trail, i, o.lines) + ' ' + 1/o.speed + 's linear infinite' - }) - - if (o.shadow) ins(seg, css(fill('#000', '0 0 4px ' + '#000'), {top: 2+'px'})) - - ins(el, ins(seg, fill(o.color, '0 0 1px rgba(0,0,0,.1)'))) - } - return el - }, - - opacity: function(el, i, val) { - if (i < el.childNodes.length) el.childNodes[i].style.opacity = val - } - - }) - - ///////////////////////////////////////////////////////////////////////// - // VML rendering for IE - ///////////////////////////////////////////////////////////////////////// - - /** - * Check and init VML support - */ - ;(function() { - - function vml(tag, attr) { - return createEl('<' + tag + ' xmlns="urn:schemas-microsoft.com:vml" class="spin-vml">', attr) - } - - var s = css(createEl('group'), {behavior: 'url(#default#VML)'}) - - if (!vendor(s, 'transform') && s.adj) { - - // VML support detected. Insert CSS rule ... - sheet.addRule('.spin-vml', 'behavior:url(#default#VML)') - - Spinner.prototype.lines = function(el, o) { - var r = o.length+o.width - , s = 2*r - - function grp() { - return css( - vml('group', { - coordsize: s + ' ' + s, - coordorigin: -r + ' ' + -r - }), - { width: s, height: s } - ) - } - - var margin = -(o.width+o.length)*2 + 'px' - , g = css(grp(), {position: 'absolute', top: margin, left: margin}) - , i - - function seg(i, dx, filter) { - ins(g, - ins(css(grp(), {rotation: 360 / o.lines * i + 'deg', left: ~~dx}), - ins(css(vml('roundrect', {arcsize: o.corners}), { - width: r, - height: o.width, - left: o.radius, - top: -o.width>>1, - filter: filter - }), - vml('fill', {color: o.color, opacity: o.opacity}), - vml('stroke', {opacity: 0}) // transparent stroke to fix color bleeding upon opacity change - ) - ) - ) - } - - if (o.shadow) - for (i = 1; i <= o.lines; i++) - seg(i, -2, 'progid:DXImageTransform.Microsoft.Blur(pixelradius=2,makeshadow=1,shadowopacity=.3)') - - for (i = 1; i <= o.lines; i++) seg(i) - return ins(el, g) - } - - Spinner.prototype.opacity = function(el, i, val, o) { - var c = el.firstChild - o = o.shadow && o.lines || 0 - if (c && i+o < c.childNodes.length) { - c = c.childNodes[i+o]; c = c && c.firstChild; c = c && c.firstChild - if (c) c.opacity = val - } - } - } - else - useCssAnimations = vendor(s, 'animation') - })() - - if (typeof define == 'function' && define.amd) - define(function() { return Spinner }) - else - window.Spinner = Spinner - -}(window, document) diff --git a/vendor/assets/stylesheets/autocomplete.css b/vendor/assets/stylesheets/autocomplete.css new file mode 100644 index 0000000000..2af8d808ba --- /dev/null +++ b/vendor/assets/stylesheets/autocomplete.css @@ -0,0 +1 @@ +.autocomplete-input{border:1px solid #eee;border-radius:8px;width:100%;padding:12px 12px 12px 48px;box-sizing:border-box;position:relative;font-size:16px;line-height:1.5;flex:1;background-color:#eee;background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjNjY2IiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PGNpcmNsZSBjeD0iMTEiIGN5PSIxMSIgcj0iOCIvPjxwYXRoIGQ9Ik0yMSAyMWwtNC00Ii8+PC9zdmc+");background-repeat:no-repeat;background-position:12px}.autocomplete-input:focus,.autocomplete-input[aria-expanded=true]{border-color:rgba(0,0,0,.12);background-color:#fff;outline:none;box-shadow:0 2px 2px rgba(0,0,0,.16)}[data-position=below] .autocomplete-input[aria-expanded=true]{border-bottom-color:transparent;border-radius:8px 8px 0 0}[data-position=above] .autocomplete-input[aria-expanded=true]{border-top-color:transparent;border-radius:0 0 8px 8px;z-index:2}.autocomplete[data-loading=true]:after{content:"";border:3px solid rgba(0,0,0,.12);border-right-color:rgba(0,0,0,.48);border-radius:100%;width:20px;height:20px;position:absolute;right:12px;top:50%;transform:translateY(-50%);animation:rotate 1s linear infinite}.autocomplete-result-list{margin:0;border:1px solid rgba(0,0,0,.12);padding:0;box-sizing:border-box;max-height:296px;overflow-y:auto;background:#fff;list-style:none;box-shadow:0 2px 2px rgba(0,0,0,.16)}[data-position=below] .autocomplete-result-list{margin-top:-1px;border-top-color:transparent;border-radius:0 0 8px 8px;padding-bottom:8px}[data-position=above] .autocomplete-result-list{margin-bottom:-1px;border-bottom-color:transparent;border-radius:8px 8px 0 0;padding-top:8px}.autocomplete-result{cursor:default;padding:12px 12px 12px 48px;background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjY2NjIiBzdHJva2Utd2lkdGg9IjIiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+PGNpcmNsZSBjeD0iMTEiIGN5PSIxMSIgcj0iOCIvPjxwYXRoIGQ9Ik0yMSAyMWwtNC00Ii8+PC9zdmc+");background-repeat:no-repeat;background-position:12px}.autocomplete-result:hover,.autocomplete-result[aria-selected=true]{background-color:rgba(0,0,0,.06)}@keyframes rotate{0%{transform:translateY(-50%) rotate(0deg)}to{transform:translateY(-50%) rotate(359deg)}} \ No newline at end of file diff --git a/vendor/assets/stylesheets/leaflet.css b/vendor/assets/stylesheets/leaflet.css new file mode 100644 index 0000000000..983d60592b --- /dev/null +++ b/vendor/assets/stylesheets/leaflet.css @@ -0,0 +1,640 @@ +/* required styles */ + +.leaflet-pane, +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow, +.leaflet-tile-container, +.leaflet-pane > svg, +.leaflet-pane > canvas, +.leaflet-zoom-box, +.leaflet-image-layer, +.leaflet-layer { + position: absolute; + left: 0; + top: 0; + } +.leaflet-container { + overflow: hidden; + } +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + -webkit-user-drag: none; + } +/* Prevents IE11 from highlighting tiles in blue */ +.leaflet-tile::selection { + background: transparent; +} +/* Safari renders non-retina tile on retina better with this, but Chrome is worse */ +.leaflet-safari .leaflet-tile { + image-rendering: -webkit-optimize-contrast; + } +/* hack that prevents hw layers "stretching" when loading new tiles */ +.leaflet-safari .leaflet-tile-container { + width: 1600px; + height: 1600px; + -webkit-transform-origin: 0 0; + } +.leaflet-marker-icon, +.leaflet-marker-shadow { + display: block; + } +/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */ +/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */ +.leaflet-container .leaflet-overlay-pane svg, +.leaflet-container .leaflet-marker-pane img, +.leaflet-container .leaflet-shadow-pane img, +.leaflet-container .leaflet-tile-pane img, +.leaflet-container img.leaflet-image-layer, +.leaflet-container .leaflet-tile { + max-width: none !important; + max-height: none !important; + } + +.leaflet-container.leaflet-touch-zoom { + -ms-touch-action: pan-x pan-y; + touch-action: pan-x pan-y; + } +.leaflet-container.leaflet-touch-drag { + -ms-touch-action: pinch-zoom; + /* Fallback for FF which doesn't support pinch-zoom */ + touch-action: none; + touch-action: pinch-zoom; +} +.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom { + -ms-touch-action: none; + touch-action: none; +} +.leaflet-container { + -webkit-tap-highlight-color: transparent; +} +.leaflet-container a { + -webkit-tap-highlight-color: rgba(51, 181, 229, 0.4); +} +.leaflet-tile { + filter: inherit; + visibility: hidden; + } +.leaflet-tile-loaded { + visibility: inherit; + } +.leaflet-zoom-box { + width: 0; + height: 0; + -moz-box-sizing: border-box; + box-sizing: border-box; + z-index: 800; + } +/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */ +.leaflet-overlay-pane svg { + -moz-user-select: none; + } + +.leaflet-pane { z-index: 400; } + +.leaflet-tile-pane { z-index: 200; } +.leaflet-overlay-pane { z-index: 400; } +.leaflet-shadow-pane { z-index: 500; } +.leaflet-marker-pane { z-index: 600; } +.leaflet-tooltip-pane { z-index: 650; } +.leaflet-popup-pane { z-index: 700; } + +.leaflet-map-pane canvas { z-index: 100; } +.leaflet-map-pane svg { z-index: 200; } + +.leaflet-vml-shape { + width: 1px; + height: 1px; + } +.lvml { + behavior: url(#default#VML); + display: inline-block; + position: absolute; + } + + +/* control positioning */ + +.leaflet-control { + position: relative; + z-index: 800; + pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ + pointer-events: auto; + } +.leaflet-top, +.leaflet-bottom { + position: absolute; + z-index: 1000; + pointer-events: none; + } +.leaflet-top { + top: 0; + } +.leaflet-right { + right: 0; + } +.leaflet-bottom { + bottom: 0; + } +.leaflet-left { + left: 0; + } +.leaflet-control { + float: left; + clear: both; + } +.leaflet-right .leaflet-control { + float: right; + } +.leaflet-top .leaflet-control { + margin-top: 10px; + } +.leaflet-bottom .leaflet-control { + margin-bottom: 10px; + } +.leaflet-left .leaflet-control { + margin-left: 10px; + } +.leaflet-right .leaflet-control { + margin-right: 10px; + } + + +/* zoom and fade animations */ + +.leaflet-fade-anim .leaflet-tile { + will-change: opacity; + } +.leaflet-fade-anim .leaflet-popup { + opacity: 0; + -webkit-transition: opacity 0.2s linear; + -moz-transition: opacity 0.2s linear; + transition: opacity 0.2s linear; + } +.leaflet-fade-anim .leaflet-map-pane .leaflet-popup { + opacity: 1; + } +.leaflet-zoom-animated { + -webkit-transform-origin: 0 0; + -ms-transform-origin: 0 0; + transform-origin: 0 0; + } +.leaflet-zoom-anim .leaflet-zoom-animated { + will-change: transform; + } +.leaflet-zoom-anim .leaflet-zoom-animated { + -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1); + -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); + transition: transform 0.25s cubic-bezier(0,0,0.25,1); + } +.leaflet-zoom-anim .leaflet-tile, +.leaflet-pan-anim .leaflet-tile { + -webkit-transition: none; + -moz-transition: none; + transition: none; + } + +.leaflet-zoom-anim .leaflet-zoom-hide { + visibility: hidden; + } + + +/* cursors */ + +.leaflet-interactive { + cursor: pointer; + } +.leaflet-grab { + cursor: -webkit-grab; + cursor: -moz-grab; + cursor: grab; + } +.leaflet-crosshair, +.leaflet-crosshair .leaflet-interactive { + cursor: crosshair; + } +.leaflet-popup-pane, +.leaflet-control { + cursor: auto; + } +.leaflet-dragging .leaflet-grab, +.leaflet-dragging .leaflet-grab .leaflet-interactive, +.leaflet-dragging .leaflet-marker-draggable { + cursor: move; + cursor: -webkit-grabbing; + cursor: -moz-grabbing; + cursor: grabbing; + } + +/* marker & overlays interactivity */ +.leaflet-marker-icon, +.leaflet-marker-shadow, +.leaflet-image-layer, +.leaflet-pane > svg path, +.leaflet-tile-container { + pointer-events: none; + } + +.leaflet-marker-icon.leaflet-interactive, +.leaflet-image-layer.leaflet-interactive, +.leaflet-pane > svg path.leaflet-interactive, +svg.leaflet-image-layer.leaflet-interactive path { + pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ + pointer-events: auto; + } + +/* visual tweaks */ + +.leaflet-container { + background: #ddd; + outline: 0; + } +.leaflet-container a { + color: #0078A8; + } +.leaflet-container a.leaflet-active { + outline: 2px solid orange; + } +.leaflet-zoom-box { + border: 2px dotted #38f; + background: rgba(255,255,255,0.5); + } + + +/* general typography */ +.leaflet-container { + font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif; + } + + +/* general toolbar styles */ + +.leaflet-bar { + box-shadow: 0 1px 5px rgba(0,0,0,0.65); + border-radius: 4px; + } +.leaflet-bar a, +.leaflet-bar a:hover { + background-color: #fff; + border-bottom: 1px solid #ccc; + width: 26px; + height: 26px; + line-height: 26px; + display: block; + text-align: center; + text-decoration: none; + color: black; + } +.leaflet-bar a, +.leaflet-control-layers-toggle { + background-position: 50% 50%; + background-repeat: no-repeat; + display: block; + } +.leaflet-bar a:hover { + background-color: #f4f4f4; + } +.leaflet-bar a:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; + } +.leaflet-bar a:last-child { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom: none; + } +.leaflet-bar a.leaflet-disabled { + cursor: default; + background-color: #f4f4f4; + color: #bbb; + } + +.leaflet-touch .leaflet-bar a { + width: 30px; + height: 30px; + line-height: 30px; + } +.leaflet-touch .leaflet-bar a:first-child { + border-top-left-radius: 2px; + border-top-right-radius: 2px; + } +.leaflet-touch .leaflet-bar a:last-child { + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; + } + +/* zoom control */ + +.leaflet-control-zoom-in, +.leaflet-control-zoom-out { + font: bold 18px 'Lucida Console', Monaco, monospace; + text-indent: 1px; + } + +.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out { + font-size: 22px; + } + + +/* layers control */ + +.leaflet-control-layers { + box-shadow: 0 1px 5px rgba(0,0,0,0.4); + background: #fff; + border-radius: 5px; + } +.leaflet-control-layers-toggle { + background-image: url(images/layers.png); + width: 36px; + height: 36px; + } +.leaflet-retina .leaflet-control-layers-toggle { + background-image: url(images/layers-2x.png); + background-size: 26px 26px; + } +.leaflet-touch .leaflet-control-layers-toggle { + width: 44px; + height: 44px; + } +.leaflet-control-layers .leaflet-control-layers-list, +.leaflet-control-layers-expanded .leaflet-control-layers-toggle { + display: none; + } +.leaflet-control-layers-expanded .leaflet-control-layers-list { + display: block; + position: relative; + } +.leaflet-control-layers-expanded { + padding: 6px 10px 6px 6px; + color: #333; + background: #fff; + } +.leaflet-control-layers-scrollbar { + overflow-y: scroll; + overflow-x: hidden; + padding-right: 5px; + } +.leaflet-control-layers-selector { + margin-top: 2px; + position: relative; + top: 1px; + } +.leaflet-control-layers label { + display: block; + } +.leaflet-control-layers-separator { + height: 0; + border-top: 1px solid #ddd; + margin: 5px -10px 5px -6px; + } + +/* Default icon URLs */ +.leaflet-default-icon-path { + background-image: url(images/marker-icon.png); + } + + +/* attribution and scale controls */ + +.leaflet-container .leaflet-control-attribution { + background: #fff; + background: rgba(255, 255, 255, 0.7); + margin: 0; + } +.leaflet-control-attribution, +.leaflet-control-scale-line { + padding: 0 5px; + color: #333; + } +.leaflet-control-attribution a { + text-decoration: none; + } +.leaflet-control-attribution a:hover { + text-decoration: underline; + } +.leaflet-container .leaflet-control-attribution, +.leaflet-container .leaflet-control-scale { + font-size: 11px; + } +.leaflet-left .leaflet-control-scale { + margin-left: 5px; + } +.leaflet-bottom .leaflet-control-scale { + margin-bottom: 5px; + } +.leaflet-control-scale-line { + border: 2px solid #777; + border-top: none; + line-height: 1.1; + padding: 2px 5px 1px; + font-size: 11px; + white-space: nowrap; + overflow: hidden; + -moz-box-sizing: border-box; + box-sizing: border-box; + + background: #fff; + background: rgba(255, 255, 255, 0.5); + } +.leaflet-control-scale-line:not(:first-child) { + border-top: 2px solid #777; + border-bottom: none; + margin-top: -2px; + } +.leaflet-control-scale-line:not(:first-child):not(:last-child) { + border-bottom: 2px solid #777; + } + +.leaflet-touch .leaflet-control-attribution, +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + box-shadow: none; + } +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + border: 2px solid rgba(0,0,0,0.2); + background-clip: padding-box; + } + + +/* popup */ + +.leaflet-popup { + position: absolute; + text-align: center; + margin-bottom: 20px; + } +.leaflet-popup-content-wrapper { + padding: 1px; + text-align: left; + border-radius: 12px; + } +.leaflet-popup-content { + margin: 13px 19px; + line-height: 1.4; + } +.leaflet-popup-content p { + margin: 18px 0; + } +.leaflet-popup-tip-container { + width: 40px; + height: 20px; + position: absolute; + left: 50%; + margin-left: -20px; + overflow: hidden; + pointer-events: none; + } +.leaflet-popup-tip { + width: 17px; + height: 17px; + padding: 1px; + + margin: -10px auto 0; + + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + transform: rotate(45deg); + } +.leaflet-popup-content-wrapper, +.leaflet-popup-tip { + background: white; + color: #333; + box-shadow: 0 3px 14px rgba(0,0,0,0.4); + } +.leaflet-container a.leaflet-popup-close-button { + position: absolute; + top: 0; + right: 0; + padding: 4px 4px 0 0; + border: none; + text-align: center; + width: 18px; + height: 14px; + font: 16px/14px Tahoma, Verdana, sans-serif; + color: #c3c3c3; + text-decoration: none; + font-weight: bold; + background: transparent; + } +.leaflet-container a.leaflet-popup-close-button:hover { + color: #999; + } +.leaflet-popup-scrolled { + overflow: auto; + border-bottom: 1px solid #ddd; + border-top: 1px solid #ddd; + } + +.leaflet-oldie .leaflet-popup-content-wrapper { + zoom: 1; + } +.leaflet-oldie .leaflet-popup-tip { + width: 24px; + margin: 0 auto; + + -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; + filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678); + } +.leaflet-oldie .leaflet-popup-tip-container { + margin-top: -1px; + } + +.leaflet-oldie .leaflet-control-zoom, +.leaflet-oldie .leaflet-control-layers, +.leaflet-oldie .leaflet-popup-content-wrapper, +.leaflet-oldie .leaflet-popup-tip { + border: 1px solid #999; + } + + +/* div icon */ + +.leaflet-div-icon { + background: #fff; + border: 1px solid #666; + } + + +/* Tooltip */ +/* Base styles for the element that has a tooltip */ +.leaflet-tooltip { + position: absolute; + padding: 6px; + background-color: #fff; + border: 1px solid #fff; + border-radius: 3px; + color: #222; + white-space: nowrap; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + pointer-events: none; + box-shadow: 0 1px 3px rgba(0,0,0,0.4); + } +.leaflet-tooltip.leaflet-clickable { + cursor: pointer; + pointer-events: auto; + } +.leaflet-tooltip-top:before, +.leaflet-tooltip-bottom:before, +.leaflet-tooltip-left:before, +.leaflet-tooltip-right:before { + position: absolute; + pointer-events: none; + border: 6px solid transparent; + background: transparent; + content: ""; + } + +/* Directions */ + +.leaflet-tooltip-bottom { + margin-top: 6px; +} +.leaflet-tooltip-top { + margin-top: -6px; +} +.leaflet-tooltip-bottom:before, +.leaflet-tooltip-top:before { + left: 50%; + margin-left: -6px; + } +.leaflet-tooltip-top:before { + bottom: 0; + margin-bottom: -12px; + border-top-color: #fff; + } +.leaflet-tooltip-bottom:before { + top: 0; + margin-top: -12px; + margin-left: -6px; + border-bottom-color: #fff; + } +.leaflet-tooltip-left { + margin-left: -6px; +} +.leaflet-tooltip-right { + margin-left: 6px; +} +.leaflet-tooltip-left:before, +.leaflet-tooltip-right:before { + top: 50%; + margin-top: -6px; + } +.leaflet-tooltip-left:before { + right: 0; + margin-right: -12px; + border-left-color: #fff; + } +.leaflet-tooltip-right:before { + left: 0; + margin-left: -12px; + border-right-color: #fff; + }