diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 76ce58fccf..0b39580760 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -9,6 +9,7 @@ assignees: '' ## Description + ## Expected Behavior @@ -22,6 +23,8 @@ assignees: '' ## Steps to Reproduce + + 1. 2. @@ -29,13 +32,11 @@ assignees: '' 4. ## Animated Gif/Screenshot - - - -## Context - + + +## Workaround + ## Severity diff --git a/.github/ISSUE_TEMPLATE/story-template.md b/.github/ISSUE_TEMPLATE/story-template.md index f3bfa62f54..d3c25f0e53 100644 --- a/.github/ISSUE_TEMPLATE/story-template.md +++ b/.github/ISSUE_TEMPLATE/story-template.md @@ -14,5 +14,12 @@ assignees: '' **- I want to be able to do:** (specify the desired behavior) (Link to others issues or resources to provide context > only if really necessary). --> -## Acceptance Criteria - +## Acceptance Criteria & Tests + + + +1. +2. +3. +4. diff --git a/Gemfile.lock b/Gemfile.lock index 69b1249374..e87ae408f1 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -703,7 +703,7 @@ GEM nokogiri (~> 1.6) rubyzip (~> 1.0) selenium-webdriver (~> 3.0) - webmock (3.7.5) + webmock (3.7.6) addressable (>= 2.3.6) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) diff --git a/app/controllers/spree/admin/users_controller.rb b/app/controllers/spree/admin/users_controller.rb index 17ab1d041d..d941785f01 100644 --- a/app/controllers/spree/admin/users_controller.rb +++ b/app/controllers/spree/admin/users_controller.rb @@ -46,7 +46,12 @@ module Spree @user.spree_roles = roles.reject(&:blank?).collect{ |r| Spree::Role.find(r) } end - flash.now[:success] = Spree.t(:account_updated) + message = if new_email_unconfirmed? + Spree.t(:email_updated) + else + Spree.t(:account_updated) + end + flash.now[:success] = message end render :edit end @@ -126,6 +131,10 @@ module Spree def load_roles @roles = Spree::Role.scoped end + + def new_email_unconfirmed? + params[:user][:email] != @user.email + end end end end diff --git a/app/models/concerns/variant_stock.rb b/app/models/concerns/variant_stock.rb index 150d8d05c3..1cc0ec4e04 100644 --- a/app/models/concerns/variant_stock.rb +++ b/app/models/concerns/variant_stock.rb @@ -29,25 +29,16 @@ module VariantStock end # Sets the stock level of the variant. - # This will only work if `track_inventory_levels` config is set - # and if there is a stock item for the variant. + # This will only work if there is a stock item for the variant. # - # @raise [StandardError] when the track_inventory_levels config key is not set - # and when the variant has no stock item + # @raise [StandardError] when the variant has no stock item def on_hand=(new_level) - error = 'Cannot set on_hand value when Spree::Config[:track_inventory_levels] is false' - raise error unless Spree::Config.track_inventory_levels - raise_error_if_no_stock_item_available overwrite_stock_levels(new_level) end # Checks whether this variant is produced on demand. - # - # In Spree 2.0 this attribute is removed in favour of - # track_inventory_levels only. It was initially introduced in - # https://github.com/openfoodfoundation/spree/commit/20b5ad9835dca7f41a40ad16c7b45f987eea6dcc def on_demand # A variant that has not been saved yet, doesn't have a stock item # This provides a default value for variant.on_demand using Spree::StockLocation.backorderable_default @@ -81,8 +72,6 @@ module VariantStock # Here we depend only on variant.total_on_hand and variant.on_demand. # This way, variant_overrides only need to override variant.total_on_hand and variant.on_demand. def can_supply?(quantity) - return true unless Spree::Config[:track_inventory_levels] - on_demand || total_on_hand >= quantity end diff --git a/app/models/spree/shipment_decorator.rb b/app/models/spree/shipment_decorator.rb index 735fdb64cd..be80102e5a 100644 --- a/app/models/spree/shipment_decorator.rb +++ b/app/models/spree/shipment_decorator.rb @@ -32,7 +32,7 @@ module Spree # NOTE: This is an override of spree's method, needed to allow orders # without line items (ie. user invoices) to not have inventory units def require_inventory - return false unless Spree::Config[:track_inventory_levels] && line_items.count > 0 # This line altered + return false unless line_items.count > 0 # This line altered order.completed? && !order.canceled? end end diff --git a/app/models/subscription_line_item.rb b/app/models/subscription_line_item.rb index 38f2694be0..d7d96fedc5 100644 --- a/app/models/subscription_line_item.rb +++ b/app/models/subscription_line_item.rb @@ -10,6 +10,11 @@ class SubscriptionLineItem < ActiveRecord::Base (price_estimate || 0) * (quantity || 0) end + # Ensure SubscriptionLineItem always has access to soft-deleted Variant attribute + def variant + Spree::Variant.unscoped { super } + end + # Used to calculators to estimate fees alias_method :amount, :total_estimate diff --git a/app/overrides/spree/layouts/admin/add_app_wrapper.html.erb.deface b/app/overrides/spree/layouts/admin/add_app_wrapper.html.erb.deface deleted file mode 100644 index 9c5e6fcd80..0000000000 --- a/app/overrides/spree/layouts/admin/add_app_wrapper.html.erb.deface +++ /dev/null @@ -1,5 +0,0 @@ - - -
> - <%= render_original %> -
diff --git a/app/services/subscription_validator.rb b/app/services/subscription_validator.rb index 051033dd9f..1ca035dfc7 100644 --- a/app/services/subscription_validator.rb +++ b/app/services/subscription_validator.rb @@ -9,8 +9,8 @@ class SubscriptionValidator attr_reader :subscription - validates_presence_of :shop, :customer, :schedule, :shipping_method, :payment_method - validates_presence_of :bill_address, :ship_address, :begins_at + validates :shop, :customer, :schedule, :shipping_method, :payment_method, presence: true + validates :bill_address, :ship_address, :begins_at, presence: true validate :shipping_method_allowed? validate :payment_method_allowed? validate :payment_method_type_allowed? diff --git a/app/views/admin/customers/index.html.haml b/app/views/admin/customers/index.html.haml index 6477357d63..477e609cde 100644 --- a/app/views/admin/customers/index.html.haml +++ b/app/views/admin/customers/index.html.haml @@ -2,8 +2,8 @@ %h1.page-title =t :customers -- content_for :app_wrapper_attrs do - = "ng-app='admin.customers'" +- content_for :main_ng_app_name do + = "admin.customers" - content_for :page_actions do %li diff --git a/app/views/admin/enterprises/edit.html.haml b/app/views/admin/enterprises/edit.html.haml index 61c26b5428..0e6a9162b8 100644 --- a/app/views/admin/enterprises/edit.html.haml +++ b/app/views/admin/enterprises/edit.html.haml @@ -4,8 +4,8 @@ = t('.editing') = @enterprise.name -- content_for :app_wrapper_attrs do - = "ng-app='admin.enterprises'" +- content_for :main_ng_app_name do + = "admin.enterprises" - content_for :page_actions do %li= select :enterprise, :id, options_for_select(editable_enterprises.collect {|e| [e.name, e.id, {:'data-url' => "#{main_app.edit_admin_enterprise_path(e.permalink)}", :'ng-selected' => "selected==#{e.id}"}]}, @enterprise.id ), {}, {:'enterprise-switcher' => '', 'data-initial' => "#{@enterprise.id}", :'ng-init' => "selected='#{@enterprise.id}'", :'ng-model' => 'selected', :id => 'enterprise_switcher', :class => 'select2'} diff --git a/app/views/admin/enterprises/index.html.haml b/app/views/admin/enterprises/index.html.haml index 8ced7bd769..499f8f9db6 100644 --- a/app/views/admin/enterprises/index.html.haml +++ b/app/views/admin/enterprises/index.html.haml @@ -1,8 +1,8 @@ - content_for :page_title do = t('.title') -- content_for :app_wrapper_attrs do - = "ng-app='admin.enterprises'" +- content_for :main_ng_app_name do + = "admin.enterprises" - content_for :page_actions do = render 'admin/shared/user_guide_link' diff --git a/app/views/admin/enterprises/new.html.haml b/app/views/admin/enterprises/new.html.haml index dd830054f5..ec54e17900 100644 --- a/app/views/admin/enterprises/new.html.haml +++ b/app/views/admin/enterprises/new.html.haml @@ -6,8 +6,8 @@ - content_for :page_actions do %li= button_link_to t('.back_link'), main_app.admin_enterprises_path, icon: 'icon-arrow-left' -- content_for :app_wrapper_attrs do - = "ng-app='admin.enterprises'" +- content_for :main_ng_app_name do + = "admin.enterprises" = admin_inject_available_countries(module: 'admin.enterprises') = admin_inject_json "admin.enterprises", "defaultCountryID", Spree::Config[:default_country_id] diff --git a/app/views/admin/order_cycles/index.html.haml b/app/views/admin/order_cycles/index.html.haml index 81cb437940..266d4c36d9 100644 --- a/app/views/admin/order_cycles/index.html.haml +++ b/app/views/admin/order_cycles/index.html.haml @@ -1,8 +1,8 @@ = content_for :page_title do = t :admin_order_cycles -- content_for :app_wrapper_attrs do - = "ng-app='admin.orderCycles'" +- content_for :main_ng_app_name do + = "admin.orderCycles" = content_for :page_actions do - if subscriptions_enabled? diff --git a/app/views/admin/subscriptions/index.html.haml b/app/views/admin/subscriptions/index.html.haml index 096e745627..4dd37c4f75 100644 --- a/app/views/admin/subscriptions/index.html.haml +++ b/app/views/admin/subscriptions/index.html.haml @@ -1,8 +1,8 @@ - content_for :page_title do = t('admin.subscriptions.subscriptions') -- content_for :app_wrapper_attrs do - = "ng-app='admin.subscriptions'" +- content_for :main_ng_app_name do + = "admin.subscriptions" - content_for :page_actions do %li diff --git a/app/views/spree/admin/orders/bulk_management.html.haml b/app/views/spree/admin/orders/bulk_management.html.haml index 1d2b5ed70d..1fc72e9a9b 100644 --- a/app/views/spree/admin/orders/bulk_management.html.haml +++ b/app/views/spree/admin/orders/bulk_management.html.haml @@ -1,5 +1,5 @@ -- content_for :app_wrapper_attrs do - = "ng-app='admin.lineItems'" +- content_for :main_ng_app_name do + = "admin.lineItems" - content_for :page_title do %h1.page-title 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 36ecdb70a0..e4fa93ffbb 100644 --- a/app/views/spree/admin/orders/customer_details/edit.html.haml +++ b/app/views/spree/admin/orders/customer_details/edit.html.haml @@ -13,8 +13,8 @@ #select-customer{"data-hook" => ""} %fieldset.no-border-bottom %legend{:align => "center"}= Spree.t(:customer_search) - - content_for :app_wrapper_attrs do - = 'ng-app=admin.orders' + - content_for :main_ng_app_name do + = "admin.orders" = hidden_field_tag :customer_search_override, nil, distributor_id: @order.distributor_id, :class => 'fullwidth title customer-search-override' = render :partial => "spree/admin/orders/customer_details/autocomplete", :formats => :js diff --git a/app/views/spree/admin/orders/index.html.haml b/app/views/spree/admin/orders/index.html.haml index 3f1e087b6e..07c3acd836 100644 --- a/app/views/spree/admin/orders/index.html.haml +++ b/app/views/spree/admin/orders/index.html.haml @@ -7,8 +7,11 @@ = render partial: 'spree/admin/shared/order_sub_menu' -- content_for :app_wrapper_attrs do - = "ng-app='admin.orders' ng-controller='ordersCtrl'" +- content_for :main_ng_app_name do + = "admin.orders" + +- content_for :main_ng_ctrl_name do + = "ordersCtrl" - content_for :table_filter_title do = t(:search) diff --git a/app/views/spree/admin/products/_form.html.haml b/app/views/spree/admin/products/_form.html.haml index 0104afceba..cbc7718325 100644 --- a/app/views/spree/admin/products/_form.html.haml +++ b/app/views/spree/admin/products/_form.html.haml @@ -53,18 +53,17 @@ = f.label :sku, t(:sku) = f.text_field :sku, :size => 16 - - if Spree::Config[:track_inventory_levels] - .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) + .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 + .clear %ul#shipping_specs %li#shipping_specs_weight_field.field.alpha.two.columns diff --git a/app/views/spree/admin/variants/_form.html.haml b/app/views/spree/admin/variants/_form.html.haml index 00c4b01bfe..acc9c56314 100644 --- a/app/views/spree/admin/variants/_form.html.haml +++ b/app/views/spree/admin/variants/_form.html.haml @@ -38,18 +38,17 @@ = f.label :cost_price, Spree.t(:cost_price) = f.text_field :cost_price, value: number_to_currency(@variant.cost_price, unit: ''), class: 'fullwidth' - - if Spree::Config[:track_inventory_levels] - %div{ 'set-on-demand' => '' } - .field.checkbox - %label - = f.check_box :on_demand - = t(:on_demand) - %div{'ofn-with-tip' => t('admin.products.variants.to_order_tip')} - %a= t('admin.whats_this') - .field - = f.label :on_hand, t(:on_hand) - .fullwidth - = f.text_field :on_hand + %div{ 'set-on-demand' => '' } + .field.checkbox + %label + = f.check_box :on_demand + = t(:on_demand) + %div{'ofn-with-tip' => t('admin.products.variants.to_order_tip')} + %a= t('admin.whats_this') + .field + = f.label :on_hand, t(:on_hand) + .fullwidth + = f.text_field :on_hand .right.six.columns.omega.label-block - if @product.variant_unit != 'weight' diff --git a/app/views/spree/layouts/_admin_body.html.haml b/app/views/spree/layouts/_admin_body.html.haml new file mode 100644 index 0000000000..a51fc57755 --- /dev/null +++ b/app/views/spree/layouts/_admin_body.html.haml @@ -0,0 +1,78 @@ += admin_inject_currency_config += render "layouts/i18n_script" + +#wrapper{"data-hook" => ""} + - if flash[:error] + .flash.error= flash[:error] + - if notice + .flash.notice= notice + - if flash[:success] + .flash.success= flash[:success] + + #progress + .wrapper + #spinner + .progress-message + = Spree.t(:loading) + \... + + = render :partial => 'spree/admin/shared/alert', :collection => session[:alerts] + + %header#header{"data-hook" => ""} + .container + %figure.columns.five{"data-hook" => "logo-wrapper"} + = link_to image_tag(Spree::Config[:admin_interface_logo], :id => 'logo'), spree.admin_path + %nav.columns.eleven{"data-hook" => "admin_login_navigation_bar"} + = render :partial => 'spree/layouts/admin/login_nav' + + %nav#admin-menu{"data-hook" => ""} + .container + .sixteen.columns.main-menu-wrapper + %ul.inline-menu.fullwidth-menu{"data-hook" => "admin_tabs"} + = render :partial => 'spree/admin/shared/tabs' + + - if content_for?(:sub_menu) + %nav#sub-menu{"data-hook" => ""} + .container + .sixteen.columns + = yield :sub_menu + + - if content_for?(:page_title) || content_for?(:page_actions) + #content-header{"data-hook" => ""} + .container + .sixteen.columns + .block-table + - if content_for?(:page_title) + .table-cell + %h1{:class => "page-title"}= yield :page_title + - if content_for?(:page_actions) + .page-actions.table-cell.toolbar{"data-hook" => "toolbar"} + %ul.inline-menu + = yield :page_actions + + .container + .row + - content_class = content_for?(:sidebar) ? "with-sidebar" : "" + #content{:class => content_class, "data-hook" => ""} + - if content_for?(:table_filter) + - table_filter_class = content_for?(:sidebar) ? 'twelve columns' : 'sixteen columns' + #table-filter{:class => table_filter_class, "data-hook" => ""} + %fieldset + %legend{:align => "center"}= yield :table_filter_title + = yield :table_filter + - div_class = content_for?(:sidebar) ? 'twelve columns' : 'sixteen columns' + %div{:class => div_class} + = yield + - if content_for?(:sidebar) + %aside#sidebar.four.columns{"data-hook" => ""} + - if content_for?(:sidebar_title) + %h5.sidebar-title + %span= yield :sidebar_title + = yield :sidebar + +%div{"data-hook" => "admin_footer_scripts"} + += render 'spree/shared/google_analytics' + +%script + = raw "Spree.api_key = \"#{try_spree_current_user.try(:spree_api_key).to_s}\";" diff --git a/app/views/spree/layouts/admin.html.haml b/app/views/spree/layouts/admin.html.haml index cdf4fbda02..530b83bdb5 100644 --- a/app/views/spree/layouts/admin.html.haml +++ b/app/views/spree/layouts/admin.html.haml @@ -4,81 +4,12 @@ = render :partial => 'spree/admin/shared/head' %body.admin - = admin_inject_currency_config - = render "layouts/i18n_script" - - #wrapper{"data-hook" => ""} - - if flash[:error] - .flash.error= flash[:error] - - if notice - .flash.notice= notice - - if flash[:success] - .flash.success= flash[:success] - - #progress - .wrapper - #spinner - .progress-message - = Spree.t(:loading) - \... - - = render :partial => 'spree/admin/shared/alert', :collection => session[:alerts] - - %header#header{"data-hook" => ""} - .container - %figure.columns.five{"data-hook" => "logo-wrapper"} - = link_to image_tag(Spree::Config[:admin_interface_logo], :id => 'logo'), spree.admin_path - %nav.columns.eleven{"data-hook" => "admin_login_navigation_bar"} - = render :partial => 'spree/layouts/admin/login_nav' - - %nav#admin-menu{"data-hook" => ""} - .container - .sixteen.columns.main-menu-wrapper - %ul.inline-menu.fullwidth-menu{"data-hook" => "admin_tabs"} - = render :partial => 'spree/admin/shared/tabs' - - - if content_for?(:sub_menu) - %nav#sub-menu{"data-hook" => ""} - .container - .sixteen.columns - = yield :sub_menu - - - if content_for?(:page_title) || content_for?(:page_actions) - #content-header{"data-hook" => ""} - .container - .sixteen.columns - .block-table - - if content_for?(:page_title) - .table-cell - %h1{:class => "page-title"}= yield :page_title - - if content_for?(:page_actions) - .page-actions.table-cell.toolbar{"data-hook" => "toolbar"} - %ul.inline-menu - = yield :page_actions - - .container - .row - - content_class = content_for?(:sidebar) ? "with-sidebar" : "" - #content{:class => content_class, "data-hook" => ""} - - if content_for?(:table_filter) - - table_filter_class = content_for?(:sidebar) ? 'twelve columns' : 'sixteen columns' - #table-filter{:class => table_filter_class, "data-hook" => ""} - %fieldset - %legend{:align => "center"}= yield :table_filter_title - = yield :table_filter - - div_class = content_for?(:sidebar) ? 'twelve columns' : 'sixteen columns' - %div{:class => div_class} - = yield - - if content_for?(:sidebar) - %aside#sidebar.four.columns{"data-hook" => ""} - - if content_for?(:sidebar_title) - %h5.sidebar-title - %span= yield :sidebar_title - = yield :sidebar - - %div{"data-hook" => "admin_footer_scripts"} - - = render 'spree/shared/google_analytics' - - %script - = raw "Spree.api_key = \"#{try_spree_current_user.try(:spree_api_key).to_s}\";" + - if content_for?(:main_ng_app_name) + - if content_for?(:main_ng_ctrl_name) + %div{ "ng-app" => yield(:main_ng_app_name).strip.html_safe, "ng-controller" => yield(:main_ng_ctrl_name).strip.html_safe } + = render :partial => 'spree/layouts/admin_body' + - else + %div{ "ng-app" => yield(:main_ng_app_name).strip.html_safe } + = render :partial => 'spree/layouts/admin_body' + - else + = render :partial => 'spree/layouts/admin_body' diff --git a/app/views/spree/users/_cards.html.haml b/app/views/spree/users/_cards.html.haml index 6f7d13a06a..103bff8578 100644 --- a/app/views/spree/users/_cards.html.haml +++ b/app/views/spree/users/_cards.html.haml @@ -16,7 +16,7 @@ .small-12.medium-6.columns .new_card{ ng: { show: 'CreditCard.visible', class: '{visible: CreditCard.visible}' } } - %h3= t(:add_a_new_card) + %h3= t(:add_new_credit_card) = render 'new_card_form' .authorised_shops{ ng: { controller: 'AuthorisedShopsCtrl', hide: 'CreditCard.visible' } } %h3 diff --git a/config/initializers/datadog.rb b/config/initializers/datadog.rb index 4029ebb6d0..8494343f93 100644 --- a/config/initializers/datadog.rb +++ b/config/initializers/datadog.rb @@ -2,5 +2,6 @@ if ENV['DATADOG_RAILS_APM'] Datadog.configure do |c| c.use :rails, service_name: 'rails' c.use :delayed_job, service_name: 'delayed_job' + c.analytics_enabled = true end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 9348cd9138..b595cb9da0 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2943,6 +2943,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using email: Email # TODO: remove 'account_updated' key once we get to Spree 2.0 account_updated: "Account updated!" + email_updated: "The account will be updated once the new email is confirmed." my_account: "My account" date: "Date" time: "Time" diff --git a/config/locales/en_NZ.yml b/config/locales/en_NZ.yml index 52333ba4b8..8ae72e408a 100644 --- a/config/locales/en_NZ.yml +++ b/config/locales/en_NZ.yml @@ -595,7 +595,7 @@ en_NZ: desc_long_placeholder: Tell customers about yourself. This information appears on your public profile. business_details: abn: 'IRD number ' - abn_placeholder: eg. 99 123 456 789 + abn_placeholder: eg. 99 -99-99 acn: NZBN acn_placeholder: eg. 123 456 789 display_invoice_logo: Display logo in invoices @@ -1162,7 +1162,7 @@ en_NZ: menu_4_title: "Groups" menu_4_url: "/groups" menu_5_title: "About" - menu_5_url: "https://about.openfoodnetwork.org.nz/" + menu_5_url: "https://openfoodnetwork.nz/" menu_6_title: "Connect" menu_6_url: "https://openfoodnetwork.org/nz/connect/" menu_7_title: "Learn" @@ -1530,11 +1530,11 @@ en_NZ: groups_signup_intro: "We're an amazing platform for collaborative marketing, the easiest way for your members and stakeholders to reach new markets. We're non-profit, affordable, and simple." groups_signup_email: Email us groups_signup_motivation1: We transform food systems fairly. - groups_signup_motivation2: It's why we get out of bed every day. We're a global non-profit, based on open source code. We play fair. You can always trust us. - groups_signup_motivation3: We know you have big ideas, and we want to help. We'll share our knowledge, networks and resources. We know that isolation doesn't create change, so we'll partner with you. + groups_signup_motivation2:

It's why we get out of bed every day. We're a global non-profit, based on open source code. We play fair. You can always trust us.

+ groups_signup_motivation3:

We know you have big ideas, and we want to help. We'll share our knowledge, networks and resources. We know that isolation doesn't create change, so we'll partner with you.

groups_signup_motivation4: We meet you where you are. - groups_signup_motivation5: You might be an alliance of food hubs, producers, or distributors, and an industry body, or a local government. - groups_signup_motivation6: Whatever your role in your local food movement, we're ready to help. However you come to wonder what Open Food Network would look like or is doing in your part of the world, let's start the conversation. + groups_signup_motivation5:

You might be an alliance of food hubs, producers, or distributors, and an industry body, or a local government.

+ groups_signup_motivation6:

Whatever your role in your local food movement, we're ready to help. However you come to wonder what Open Food Network would look like or is doing in your part of the world, let's start the conversation.

groups_signup_motivation7: We make food movements make more sense. groups_signup_motivation8: You need to activate and enable your networks, we offer a platform for conversation and action. You need real engagement. We’ll help reach all the players, all the stakeholders, all the sectors. groups_signup_motivation9: You need resourcing. We’ll bring all our experience to bear. You need cooperation. We’ll better connect you to a global network of peers. @@ -1599,7 +1599,7 @@ en_NZ: sell_hubs_detail: "Set up a profile for your food enterprise or organisation on the OFN. At any time you can upgrade your profile to a multi-producer shop." sell_groups_detail: "Set up a tailored directory of enterprises (producers and other food enterprises) for your region or for your organisation." sell_user_guide: "Find out more in our user guide." - sell_listing_price: "\nWe, the organisers pay 2% of what remains after deductions to the global OFN." + sell_listing_price: "Listing on OFN incurs a nominal monthly charge and if you sell products we ask for a small percentage of your sales. For details see the About tab in the menu\nYour money pays for the server and admin costs and the contribution NZ pays to the global OFN organisation.\n\nYou can always chose to support the development of OFN by increasing the amount you pay." sell_embed: "We can also embed an OFN shop in your own customised website or build a customised local food network website for your region." sell_ask_services: "Ask us about OFN services." shops_title: Shops @@ -2310,13 +2310,13 @@ en_NZ: saving: SAVING enterprise_package: hub_profile: Hub Profile - hub_profile_cost: "COST: ALWAYS FREE" + hub_profile_cost: "COST: See About in the menu" hub_profile_text1: > People can find and contact you on the Open Food Network. Your enterprise will be visible on the map, and will be searchable in listings. hub_profile_text2: > Having a profile, and making connections within your local food system - through the Open Food Network will always be free. + through the Open Food Network will always be simple. hub_shop: Hub Shop hub_shop_text1: > Your enterprise is the backbone of your local food system. You aggregate @@ -2336,7 +2336,7 @@ en_NZ: Click on an option to see more detailed information about each package, and hit the red SAVE button when you are done! profile_only: Profile Only - profile_only_cost: "COST: ALWAYS FREE" + profile_only_cost: "COST: See About in the menu" profile_only_text1: > A profile makes you visible and contactable to others and is a way to share your story. @@ -2367,7 +2367,7 @@ en_NZ: so no matter your situation, we want to provide the tools you need to run your organisation or local food business. get_listing: Get a listing - always_free: ALWAYS FREE + always_free: See About in the menu sell_produce_others: Sell produce from others sell_own_produce: Sell your own produce sell_both: Sell produce from self and others @@ -2556,7 +2556,7 @@ en_NZ: action_login: "Log in now." producers: signup: - start_free_profile: "Start with a free profile, and expand when you're ready!" + start_free_profile: "Start with a basic profile, and expand when you're ready!" order_management: reports: enterprise_fee_summary: @@ -3087,7 +3087,7 @@ en_NZ: If you did make this request just click the link below: issue_text: | If the above URL does not work try copying and pasting it into your browser. - If you continue to have problems please feel free to contact us. + If you continue to have problems please contact us. confirmation_instructions: subject: Please confirm your OFN account users: diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 8ff691604b..561f960fdb 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -769,26 +769,20 @@ fr: producer_profile: Profil simple connect_ofn: Pour apparaître sur la carte et la liste des producteurs always_free: ' ' - producer_description_text: 'Votre profil sera visible sur la carte, et depuis le menu “producteurs”. - - Nous vous invitons à renseigner votre profil de la façon la plus complète possible. Un profil complet et avec des images attire plus ! Vous pourrez mettre des liens pour rediriger les visiteurs vers votre site internet ou espace de vente en ligne le cas échéant. - - Vous pourrez renseigner votre catalogue produits et le partager avec les circuits courts qui souhaitent vendre vos produits dans leur boutique sur Open Food France.' + producer_description_text: Nous vous invitons à renseigner votre profil de la façon la plus complète possible. Un profil complet et avec des images attire plus ! Vous pourrez mettre des liens pour rediriger les visiteurs vers votre site internet ou espace de vente en ligne le cas échéant. Vous pourrez renseigner votre catalogue produits et le partager avec les circuits courts qui souhaitent vendre vos produits dans leur boutique sur Open Food France. producer_shop: Boutique Producteur - sell_your_produce: Pour vendre vos produits via Open Food France - producer_shop_description_text: 'Vous pourrez paramétrer votre boutique en ligne pour l’adapter à vos besoins : méthodes de paiement et livraison proposées à vos acheteurs, produits à mettre en vente parmi ceux de votre catalogue, rythmes de commande et livraison, etc. ' - producer_shop_description_text2: "Vous pourrez renseigner votre catalogue produits et le partager avec d’autres circuits courts qui souhaitent vendre vos produits dans leur boutique sur Open Food France.\nATTENTION : \n- Si vous vendez via un autre outil en ligne, et n’envisagez pas d’utiliser Open Food France pour organiser vos ventes / commandes, choisissiez le type de profil “profil simple”.\n- Si vous fournissez un circuit court utilisant Open Food France pour vendre, mais ne vendez pas vous-même en direct sur Open Food France, choisissez le type de profil “profil simple”." + sell_your_produce: Pour vendre vos produits + producer_shop_description_text: Vous pourrez paramétrer votre boutique en ligne selon votre fonctionnement, et partager votre catalogue produits avec d’autres circuits courts souhaitant les distribuer dans leur boutique. + producer_shop_description_text2: 'ATTENTION : Si vous vendez via un autre outil en ligne, et n’envisagez pas d’utiliser Open Food France pour cet usage, choisissiez “profil simple”. De même, si vous fournissez un circuit court utilisant Open Food France pour vendre, mais ne vendez pas vous-même en direct sur Open Food France, choisissez “profil simple”.' producer_hub: Boutique multi-producteurs - producer_hub_text: Pour vendre vos produits ainsi que ceux d’autres producteurs via Open Food France - producer_hub_description_text: "Vous pourrez paramétrer votre boutique en ligne pour l’adapter à vos besoins : méthodes de paiement et livraison proposées à vos acheteurs,produits à mettre en vente parmi ceux votre catalogue et ceux des autres producteurs, rythmes de commande et livraison, etc. \nVous pourrez renseigner votre catalogue produits et le partager avec d’autres circuits courts qui souhaitent vendre vos produits dans leur boutique sur Open Food France.\nATTENTION : \n- Si vous vendez via un autre outil en ligne, et n’envisagez pas d’utiliser Open Food France pour organiser vos ventes / commandes, choisissiez le type de profil “profil simple”.\n- Si vous fournissez un circuit court utilisant Open Food France pour vendre, mais ne vendez pas vous-même en direct sur Open Food France, choisissez le type de profil “profil simple”." + producer_hub_text: Pour vendre vos produits ainsi que ceux d’autres producteurs + producer_hub_description_text: 'Vous pourrez paramétrer votre boutique en ligne selon votre fonctionnement, vendre les produits d''autres producteurs, et partager votre catalogue produits avec d’autres circuits courts souhaitant les distribuer dans leur boutique. ATTENTION : Si vous vendez via un autre outil en ligne, et n’envisagez pas d’utiliser Open Food France pour cet usage, choisissiez “profil simple”. De même, si vous fournissez un circuit court utilisant Open Food France pour vendre, mais ne vendez pas vous-même en direct sur Open Food France, choisissez “profil simple”.' profile: Profil simple get_listing: Pour apparaître sur la carte - profile_description_text: 'Votre profil sera visible sur la carte. - - Nous vous invitons à renseigner votre profil de la façon la plus complète possible. Un profil complet et avec des images attire plus ! Vous pourrez mettre des liens pour rediriger les visiteurs vers votre site internet ou espace de vente en ligne le cas échéant.' + profile_description_text: Nous vous invitons à renseigner votre profil de la façon la plus complète possible. Un profil complet et avec des images attire plus ! Vous pourrez mettre des liens pour rediriger les visiteurs vers votre site internet ou espace de vente en ligne le cas échéant. hub_shop: Boutique multi-producteurs - hub_shop_text: Pour vendre des produits de différents fournisseurs via Open Food France - hub_shop_description_text: "Vous pourrez paramétrer votre boutique en ligne pour l’adapter à vos besoins : méthodes de paiement et livraison proposées à vos acheteurs, produits à mettre en vente parmi les catalogues de vos fournisseurs, rythmes de commande et livraison, etc. \nATTENTION : Si vous vendez via un autre outil en ligne, et n’envisagez pas d’utiliser Open Food France pour organiser vos ventes / commandes, choisissiez le type de profil “profil simple”." + hub_shop_text: Pour vendre des produits de différents fournisseurs + hub_shop_description_text: 'Vous pourrez paramétrer votre boutique en ligne selon votre fonctionnement, et y proposer les produits de multiples producteurs. ATTENTION : Si vous vendez via un autre outil en ligne, et n’envisagez pas d’utiliser Open Food France pour cet usage, choisissiez “profil simple”.' choose_option: Veuilliez choisir l'une des options ci-dessus. change_now: Changer enterprise_user_index: @@ -1449,14 +1443,14 @@ fr: email_signup_welcome: "Bienvenue sur %{sitename} !" email_signup_confirmed_email: "Merci d'avoir confirmé votre email." email_signup_shop_html: "Vous pouvez maintenant vous connecter sur %{link}." - email_signup_text: "> Si vous organisez un circuit court de distribution, ou fournissez des produits à un circuit court, n’hésitez pas à nous contacter à info@openfoodfrance.org. Nous sommes là pour vous accompagner dans la création de votre profil et espace de vente / commande en ligne.\n> Si vous achetez via un circuit court utilisant Open Food France, connectez-vous avant de passer commande pour que vos informations personnelles et de facturation soient gardées en mémoire. Cela vous évitera de les ressaisir à chaque commande ! Pour toute question, contactez en direct votre circuit court." + email_signup_text: "Si vous organisez / fournissez un circuit court, n’hésitez pas à nous contacter à info@openfoodfrance.org, nous sommes là pour vous accompagner dans la création de votre espace de vente / commande en ligne. Si vous achetez via un circuit court utilisant Open Food France, connectez-vous avant de passer commande pour que vos informations personnelles soient gardées en mémoire, cela vous évitera de les ressaisir à chaque commande ! " email_signup_help_html: "Des retours à nous faire quant à votre utilisation de la plateforme ? Écrivez-nous à info@openfoodfrance.org." invite_email: greeting: "Bonjour !" invited_to_manage: "Vous avez été invité(e) à gérer %{enterprise} sur %{instance}." confirm_your_email: "Vous avez reçu ou allez recevoir prochainement un email avec un lien de validation. Vous n'aurez pas accès au profil de l'entreprise %{enterprise} avant d'avoir cliqué sur ce lien." set_a_password: "Vous serez ensuite invité(e) à choisir un mot de passe avant de pouvoir accéder et gérer le profil de l'entreprise." - mistakenly_sent: "Vous ne savez pas pourquoi vous recevez cet email? Veuillez contacter %{owner_email} pour plus d'informations." + mistakenly_sent: "Vous ne savez pas pourquoi vous recevez cet email ? Veuillez contacter %{owner_email} pour plus d'informations." producer_mail_greeting: "Cher(ère)" producer_mail_text_before: "Nous avons reçu toutes les commandes pour la prochaine livraison." producer_mail_order_text: "Voilà la liste et les quantités des produits commandés vous concernant:" @@ -1759,7 +1753,7 @@ fr: country_field_error: "Veuillez saisir une Pays" contact: title: "Contact" - who_is_managing_enterprise: "Qui gère %{enterprise}?" + who_is_managing_enterprise: "Qui gère %{enterprise} ?" contact_field: "Personne référente" contact_field_placeholder: "Nom du contact principal" contact_field_required: "Vous devez saisir une personne référente" @@ -1767,7 +1761,7 @@ fr: phone_field_placeholder: "ex : 06 24 53 26 53" type: title: "Catégorie" - headline: "Dernière étape pour ajouter %{enterprise} !" + headline: "Dites-nous en un peu plus sur %{enterprise}" question: "Etes-vous un producteur ?" yes_producer: "Oui, je suis un producteur" no_producer: "Non, je ne suis pas un producteur" @@ -2401,9 +2395,9 @@ fr: choisissez le type de profil “profil simple”. get_listing: Pour apparaître sur la carte always_free: ' ' - sell_produce_others: Pour vendre des produits de différents fournisseurs via Open Food France - sell_own_produce: Pour vendre vos produits via Open Food France - sell_both: Pour vendre vos produits ainsi que ceux d’autres producteurs via Open Food France + sell_produce_others: Pour vendre des produits de différents fournisseurs + sell_own_produce: Pour vendre vos produits + sell_both: Pour vendre vos produits ainsi que ceux d’autres producteurs enterprise_producer: producer: Producteur producer_text1: > diff --git a/config/locales/fr_BE.yml b/config/locales/fr_BE.yml index dc7e4fb24b..54efce7adc 100644 --- a/config/locales/fr_BE.yml +++ b/config/locales/fr_BE.yml @@ -1449,8 +1449,8 @@ fr_BE: producer_mail_order_text: "Voilà la liste et les quantités des produits commandés vous concernant:" producer_mail_delivery_instructions: "Modalités de livraison des produits:" producer_mail_signoff: "Merci et belle fin de journée!" - shopping_oc_closed: La boutique est actuellement fermée - 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_closed: Le comptoir est actuellement fermé + shopping_oc_closed_description: "Veuillez attendre l'ouverture du prochain cycle de vente (ou contactez directement le comptoir pour voir si nous pouvons accepter une commande tardive)." shopping_oc_last_closed: "Le dernier cycle de vente s'est terminé il y a %{distance_of_time}" shopping_oc_next_open: "Le prochain cycle de vente ouvrira dans %{distance_of_time}" shopping_tabs_about: "A propos de %{distributor}" diff --git a/config/locales/pt_BR.yml b/config/locales/pt_BR.yml index d73da59bdf..4423327754 100644 --- a/config/locales/pt_BR.yml +++ b/config/locales/pt_BR.yml @@ -1154,13 +1154,13 @@ pt_BR: ticket_column_unit_price: "Preço Unitário" ticket_column_total_price: "Preço Total" menu_1_title: "Lojas" - menu_1_url: "/ lojas" + menu_1_url: "/shops" menu_2_title: "Mapa" - menu_2_url: "/mapa" + menu_2_url: "/map" menu_3_title: "Produtores" - menu_3_url: "/ produtores" + menu_3_url: "/producers" menu_4_title: "Grupos" - menu_4_url: "/ grupos" + menu_4_url: "/groups" menu_5_title: "Sobre" menu_5_url: "https://sobre.openfoodnetwork.org.br/" menu_6_title: "Conectar" diff --git a/spec/features/admin/users_spec.rb b/spec/features/admin/users_spec.rb index d58ba686a6..4ab504c5a4 100644 --- a/spec/features/admin/users_spec.rb +++ b/spec/features/admin/users_spec.rb @@ -64,6 +64,13 @@ feature "Managing users" do expect(page).to have_content("Account updated") end + + it "should let me edit the user email" do + fill_in "Email", with: "newemail@example.org" + click_button "Update" + + expect(page).to have_content("The account will be updated once the new email is confirmed.") + end end end diff --git a/spec/models/concerns/variant_stock_spec.rb b/spec/models/concerns/variant_stock_spec.rb index 489737ec18..e417e3a203 100644 --- a/spec/models/concerns/variant_stock_spec.rb +++ b/spec/models/concerns/variant_stock_spec.rb @@ -45,33 +45,14 @@ describe VariantStock do end describe '#on_hand=' do - context 'when track_inventory_levels is set' do - before do - allow(Spree::Config) - .to receive(:track_inventory_levels) { true } - end - - it 'sets the new level as the stock item\'s count_on_hand' do - variant.on_hand = 3 - unique_stock_item = variant.stock_items.first - expect(unique_stock_item.count_on_hand).to eq(3) - end - - context 'when the variant has no stock item' do - let(:variant) { build(:variant) } - - it 'raises' do - expect { variant.on_hand = 3 } - .to raise_error(StandardError) - end - end + it 'sets the new level as the stock item\'s count_on_hand' do + variant.on_hand = 3 + unique_stock_item = variant.stock_items.first + expect(unique_stock_item.count_on_hand).to eq(3) end - context 'when track_inventory_levels is not set' do - before do - allow(Spree::Config) - .to receive(:track_inventory_levels) { false } - end + context 'when the variant has no stock item' do + let(:variant) { build(:variant) } it 'raises' do expect { variant.on_hand = 3 } diff --git a/spec/serializers/api/admin/subscription_line_item_serializer_spec.rb b/spec/serializers/api/admin/subscription_line_item_serializer_spec.rb new file mode 100644 index 0000000000..5542c5d482 --- /dev/null +++ b/spec/serializers/api/admin/subscription_line_item_serializer_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +module Api + module Admin + describe SubscriptionLineItemSerializer do + let(:subscription_line_item) { create(:subscription_line_item) } + + it "serializes a subscription line item with the product name" do + serializer = described_class.new(subscription_line_item) + + expect(serializer.to_json).to match subscription_line_item.variant.product.name + end + + context "when the variant of the subscription line item is soft deleted" do + it "serializers the subscription line item with the product name" do + subscription_line_item.variant.update_attribute :deleted_at, Time.zone.now + + serializer = described_class.new(subscription_line_item.reload) + + expect(serializer.to_json).to match subscription_line_item.variant.product.name + end + end + end + end +end