mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-21 05:09:15 +00:00
Merge branch 'master' into 2-0-stable-jan-8th
This commit is contained in:
@@ -13,6 +13,11 @@ angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl",
|
||||
$scope.RequestMonitor = RequestMonitor
|
||||
$scope.selectView = Views.selectView
|
||||
$scope.currentView = -> Views.currentView
|
||||
$scope.onDemandOptions = [
|
||||
{ description: t('js.variant_overrides.on_demand.use_producer_settings'), value: null },
|
||||
{ description: t('js.variant_overrides.on_demand.yes'), value: true },
|
||||
{ description: t('js.variant_overrides.on_demand.no'), value: false }
|
||||
]
|
||||
|
||||
$scope.views = Views.setViews
|
||||
inventory: { name: t('js.variant_overrides.inventory_products'), visible: true }
|
||||
@@ -105,3 +110,35 @@ angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl",
|
||||
StatusMessage.display 'success', t('js.variant_overrides.stock_reset')
|
||||
.error (data, status) ->
|
||||
$timeout -> StatusMessage.display 'failure', $scope.updateError(data, status)
|
||||
|
||||
# Variant override count_on_hand field placeholder logic:
|
||||
# on_demand true -- Show "On Demand"
|
||||
# on_demand false -- Show empty value to be set by the user
|
||||
# on_demand nil -- Show producer on_hand value
|
||||
$scope.countOnHandPlaceholder = (variant, hubId) ->
|
||||
variantOverride = $scope.variantOverrides[hubId][variant.id]
|
||||
|
||||
if variantOverride.on_demand
|
||||
t('js.variants.on_demand.yes')
|
||||
else if variantOverride.on_demand == false
|
||||
''
|
||||
else
|
||||
variant.on_hand
|
||||
|
||||
# This method should only be used when the variant override on_demand is changed.
|
||||
#
|
||||
# Change the count_on_hand value to a suggested value.
|
||||
$scope.updateCountOnHand = (variant, hubId) ->
|
||||
variantOverride = $scope.variantOverrides[hubId][variant.id]
|
||||
|
||||
suggested = $scope.countOnHandSuggestion(variant, hubId)
|
||||
return if suggested == variantOverride.count_on_hand
|
||||
variantOverride.count_on_hand = suggested
|
||||
DirtyVariantOverrides.set hubId, variant.id, variantOverride.id, 'count_on_hand', suggested
|
||||
|
||||
# Suggest producer count_on_hand if variant has limited stock and variant override forces limited
|
||||
# stock. Otherwise, clear whatever value is set.
|
||||
$scope.countOnHandSuggestion = (variant, hubId) ->
|
||||
variantOverride = $scope.variantOverrides[hubId][variant.id]
|
||||
return null unless !variant.on_demand && variantOverride.on_demand == false
|
||||
variant.on_hand
|
||||
|
||||
10
app/assets/stylesheets/admin/components/input.css.scss
Normal file
10
app/assets/stylesheets/admin/components/input.css.scss
Normal file
@@ -0,0 +1,10 @@
|
||||
@import '../../darkswarm/branding';
|
||||
|
||||
.container {
|
||||
input {
|
||||
&[readonly] {
|
||||
background-color: $disabled-light;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,25 +5,29 @@ class UserRegistrationsController < Spree::UserRegistrationsController
|
||||
|
||||
before_filter :set_checkout_redirect, only: :create
|
||||
|
||||
include I18nHelper
|
||||
before_filter :set_locale
|
||||
|
||||
# POST /resource/sign_up
|
||||
def create
|
||||
@user = build_resource(params[:spree_user])
|
||||
if resource.save
|
||||
session[:spree_user_signup] = true
|
||||
session[:confirmation_return_url] = params[:return_url]
|
||||
associate_user
|
||||
@user.locale = I18n.locale.to_s
|
||||
unless resource.save
|
||||
return render_error(@user.errors)
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
set_flash_message(:success, :signed_up_but_unconfirmed)
|
||||
redirect_to after_sign_in_path_for(@user)
|
||||
end
|
||||
format.js do
|
||||
render json: { email: @user.email }
|
||||
end
|
||||
session[:spree_user_signup] = true
|
||||
session[:confirmation_return_url] = params[:return_url]
|
||||
associate_user
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
set_flash_message(:success, :signed_up_but_unconfirmed)
|
||||
redirect_to after_sign_in_path_for(@user)
|
||||
end
|
||||
format.js do
|
||||
render json: { email: @user.email }
|
||||
end
|
||||
else
|
||||
render_error(@user.errors)
|
||||
end
|
||||
rescue StandardError => error
|
||||
OpenFoodNetwork::ErrorLogger.notify(error)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module I18nHelper
|
||||
def set_locale
|
||||
# Save a given locale
|
||||
if params[:locale] && Rails.application.config.i18n.available_locales.include?(params[:locale])
|
||||
if params[:locale] && available_locale?(params[:locale])
|
||||
spree_current_user.update_attributes!(locale: params[:locale]) if spree_current_user
|
||||
cookies[:locale] = params[:locale]
|
||||
end
|
||||
@@ -13,4 +13,20 @@ module I18nHelper
|
||||
|
||||
I18n.locale = spree_current_user.andand.locale || cookies[:locale] || I18n.default_locale
|
||||
end
|
||||
|
||||
def valid_locale(user)
|
||||
if user.present? &&
|
||||
user.locale.present? &&
|
||||
available_locale?(user.locale)
|
||||
user.locale
|
||||
else
|
||||
I18n.default_locale
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def available_locale?(locale)
|
||||
Rails.application.config.i18n.available_locales.include?(locale)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
require 'devise/mailers/helpers'
|
||||
class EnterpriseMailer < Spree::BaseMailer
|
||||
include Devise::Mailers::Helpers
|
||||
include I18nHelper
|
||||
|
||||
def welcome(enterprise)
|
||||
@enterprise = enterprise
|
||||
subject = t('enterprise_mailer.welcome.subject',
|
||||
enterprise: @enterprise.name,
|
||||
sitename: Spree::Config[:site_name])
|
||||
mail(:to => enterprise.contact.email,
|
||||
:from => from_address,
|
||||
:subject => subject)
|
||||
I18n.with_locale valid_locale(@enterprise.owner) do
|
||||
subject = t('enterprise_mailer.welcome.subject',
|
||||
enterprise: @enterprise.name,
|
||||
sitename: Spree::Config[:site_name])
|
||||
mail(:to => enterprise.contact.email,
|
||||
:from => from_address,
|
||||
:subject => subject)
|
||||
end
|
||||
end
|
||||
|
||||
def manager_invitation(enterprise, user)
|
||||
@@ -17,11 +20,12 @@ class EnterpriseMailer < Spree::BaseMailer
|
||||
@instance = Spree::Config[:site_name]
|
||||
@instance_email = from_address
|
||||
|
||||
subject = t('enterprise_mailer.invite_manager.subject', enterprise: @enterprise.name)
|
||||
|
||||
mail(to: user.email,
|
||||
from: from_address,
|
||||
subject: subject)
|
||||
I18n.with_locale valid_locale(@enterprise.owner) do
|
||||
subject = t('enterprise_mailer.invite_manager.subject', enterprise: @enterprise.name)
|
||||
mail(to: user.email,
|
||||
from: from_address,
|
||||
subject: subject)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
class ProducerMailer < Spree::BaseMailer
|
||||
include I18nHelper
|
||||
|
||||
def order_cycle_report(producer, order_cycle)
|
||||
@producer = producer
|
||||
@@ -10,9 +11,11 @@ class ProducerMailer < Spree::BaseMailer
|
||||
@total = total_from_line_items(line_items)
|
||||
@tax_total = tax_total_from_line_items(line_items)
|
||||
|
||||
subject = "[#{Spree::Config.site_name}] #{I18n.t('producer_mailer.order_cycle.subject', producer: producer.name)}"
|
||||
I18n.with_locale valid_locale(@producer.owner) do
|
||||
order_cycle_subject = I18n.t('producer_mailer.order_cycle.subject', producer: producer.name)
|
||||
subject = "[#{Spree::Config.site_name}] #{order_cycle_subject}"
|
||||
|
||||
if has_orders?(order_cycle, producer)
|
||||
return unless has_orders?(order_cycle, producer)
|
||||
mail(
|
||||
to: @producer.contact.email,
|
||||
from: from_address,
|
||||
@@ -23,7 +26,6 @@ class ProducerMailer < Spree::BaseMailer
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def has_orders?(order_cycle, producer)
|
||||
|
||||
@@ -2,32 +2,47 @@ Spree::OrderMailer.class_eval do
|
||||
helper HtmlHelper
|
||||
helper CheckoutHelper
|
||||
helper SpreeCurrencyHelper
|
||||
include I18nHelper
|
||||
|
||||
def cancel_email(order_or_order_id, resend = false)
|
||||
@order = find_order(order_or_order_id)
|
||||
I18n.with_locale valid_locale(@order.user) do
|
||||
mail(to: order.email,
|
||||
from: from_address,
|
||||
subject: mail_subject(t('order_mailer.cancel_email.subject'), resend))
|
||||
end
|
||||
end
|
||||
|
||||
def confirm_email_for_customer(order_or_order_id, resend = false)
|
||||
@order = find_order(order_or_order_id)
|
||||
subject = build_subject(t('order_mailer.confirm_email.subject'), resend)
|
||||
mail(:to => @order.email,
|
||||
:from => from_address,
|
||||
:subject => subject,
|
||||
:reply_to => @order.distributor.contact.email)
|
||||
I18n.with_locale valid_locale(@order.user) do
|
||||
subject = mail_subject(t('order_mailer.confirm_email.subject'), resend)
|
||||
mail(:to => @order.email,
|
||||
:from => from_address,
|
||||
:subject => subject,
|
||||
:reply_to => @order.distributor.contact.email)
|
||||
end
|
||||
end
|
||||
|
||||
def confirm_email_for_shop(order_or_order_id, resend = false)
|
||||
@order = find_order(order_or_order_id)
|
||||
subject = build_subject(t('order_mailer.confirm_email.subject'), resend)
|
||||
mail(:to => @order.distributor.contact.email,
|
||||
:from => from_address,
|
||||
:subject => subject)
|
||||
I18n.with_locale valid_locale(@order.user) do
|
||||
subject = mail_subject(t('order_mailer.confirm_email.subject'), resend)
|
||||
mail(:to => @order.distributor.contact.email,
|
||||
:from => from_address,
|
||||
:subject => subject)
|
||||
end
|
||||
end
|
||||
|
||||
def invoice_email(order_or_order_id, pdf)
|
||||
@order = find_order(order_or_order_id)
|
||||
subject = build_subject(t(:invoice))
|
||||
attachments["invoice-#{@order.number}.pdf"] = pdf if pdf.present?
|
||||
mail(:to => @order.email,
|
||||
:from => from_address,
|
||||
:subject => subject,
|
||||
:reply_to => @order.distributor.contact.email)
|
||||
attach_file("invoice-#{@order.number}.pdf", pdf)
|
||||
I18n.with_locale valid_locale(@order.user) do
|
||||
mail(to: @order.email,
|
||||
from: from_address,
|
||||
subject: mail_subject(t(:invoice), false),
|
||||
reply_to: @order.distributor.contact.email)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
@@ -37,8 +52,12 @@ Spree::OrderMailer.class_eval do
|
||||
order_or_order_id.respond_to?(:id) ? order_or_order_id : Spree::Order.find(order_or_order_id)
|
||||
end
|
||||
|
||||
def build_subject( subject_text, resend = false )
|
||||
subject = (resend ? "[#{t(:resend).upcase}] " : "")
|
||||
subject += "#{Spree::Config[:site_name]} #{subject_text} ##{@order.number}"
|
||||
def mail_subject(base_subject, resend)
|
||||
resend_prefix = (resend ? "[#{t(:resend).upcase}] " : '')
|
||||
"#{resend_prefix}#{Spree::Config[:site_name]} #{base_subject} ##{@order.number}"
|
||||
end
|
||||
|
||||
def attach_file(filename, file)
|
||||
attachments[filename] = file if file.present?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
Spree::UserMailer.class_eval do
|
||||
include I18nHelper
|
||||
|
||||
def signup_confirmation(user)
|
||||
@user = user
|
||||
mail(:to => user.email, :from => from_address,
|
||||
:subject => t(:welcome_to) + Spree::Config[:site_name])
|
||||
I18n.with_locale valid_locale(@user) do
|
||||
mail(:to => user.email, :from => from_address,
|
||||
:subject => t(:welcome_to) + Spree::Config[:site_name])
|
||||
end
|
||||
end
|
||||
|
||||
# Overriding `Spree::UserMailer.confirmation_instructions` which is
|
||||
@@ -12,10 +16,12 @@ Spree::UserMailer.class_eval do
|
||||
@instance = Spree::Config[:site_name]
|
||||
@contact = ContentConfig.footer_email
|
||||
|
||||
subject = t('spree.user_mailer.confirmation_instructions.subject')
|
||||
mail(to: confirmation_email_address,
|
||||
from: from_address,
|
||||
subject: subject)
|
||||
I18n.with_locale valid_locale(@user) do
|
||||
subject = t('spree.user_mailer.confirmation_instructions.subject')
|
||||
mail(to: confirmation_email_address,
|
||||
from: from_address,
|
||||
subject: subject)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
class SubscriptionMailer < Spree::BaseMailer
|
||||
helper CheckoutHelper
|
||||
helper ShopMailHelper
|
||||
include I18nHelper
|
||||
|
||||
def confirmation_email(order)
|
||||
@type = 'confirmation'
|
||||
@@ -46,10 +47,13 @@ class SubscriptionMailer < Spree::BaseMailer
|
||||
private
|
||||
|
||||
def send_mail(order)
|
||||
subject = "#{Spree::Config[:site_name]} #{t('order_mailer.confirm_email.subject')} ##{order.number}"
|
||||
mail(to: order.email,
|
||||
from: from_address,
|
||||
subject: subject,
|
||||
reply_to: order.distributor.contact.email)
|
||||
I18n.with_locale valid_locale(order.user) do
|
||||
confirm_email_subject = t('order_mailer.confirm_email.subject')
|
||||
subject = "#{Spree::Config[:site_name]} #{confirm_email_subject} ##{order.number}"
|
||||
mail(to: order.email,
|
||||
from: from_address,
|
||||
subject: subject,
|
||||
reply_to: order.distributor.contact.email)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
41
app/models/concerns/stock_settings_override_validation.rb
Normal file
41
app/models/concerns/stock_settings_override_validation.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
module StockSettingsOverrideValidation
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
before_validation :require_compatible_on_demand_and_count_on_hand
|
||||
end
|
||||
|
||||
def require_compatible_on_demand_and_count_on_hand
|
||||
disallow_count_on_hand_if_using_producer_stock_settings
|
||||
disallow_count_on_hand_if_on_demand
|
||||
require_count_on_hand_if_limited_stock
|
||||
end
|
||||
|
||||
def disallow_count_on_hand_if_using_producer_stock_settings
|
||||
return unless on_demand.nil? && count_on_hand.present?
|
||||
|
||||
error_message = I18n.t("count_on_hand.using_producer_stock_settings_but_count_on_hand_set",
|
||||
scope: i18n_scope_for_stock_settings_override_validation_error)
|
||||
errors.add(:count_on_hand, error_message)
|
||||
end
|
||||
|
||||
def disallow_count_on_hand_if_on_demand
|
||||
return unless on_demand? && count_on_hand.present?
|
||||
|
||||
error_message = I18n.t("count_on_hand.on_demand_but_count_on_hand_set",
|
||||
scope: i18n_scope_for_stock_settings_override_validation_error)
|
||||
errors.add(:count_on_hand, error_message)
|
||||
end
|
||||
|
||||
def require_count_on_hand_if_limited_stock
|
||||
return unless on_demand == false && count_on_hand.blank?
|
||||
|
||||
error_message = I18n.t("count_on_hand.limited_stock_but_no_count_on_hand",
|
||||
scope: i18n_scope_for_stock_settings_override_validation_error)
|
||||
errors.add(:count_on_hand, error_message)
|
||||
end
|
||||
|
||||
def i18n_scope_for_stock_settings_override_validation_error
|
||||
"activerecord.errors.models.#{self.class.name.underscore}"
|
||||
end
|
||||
end
|
||||
@@ -68,6 +68,18 @@ module ProductImport
|
||||
|
||||
private
|
||||
|
||||
def find_or_initialize_variant_override(entry, existing_variant)
|
||||
existing_variant_override = VariantOverride.where(
|
||||
variant_id: existing_variant.id,
|
||||
hub_id: entry.enterprise_id
|
||||
).first
|
||||
|
||||
existing_variant_override || VariantOverride.new(
|
||||
variant_id: existing_variant.id,
|
||||
hub_id: entry.enterprise_id
|
||||
)
|
||||
end
|
||||
|
||||
def enterprise_validation(entry)
|
||||
return if name_presence_error entry
|
||||
return if enterprise_not_found_error entry
|
||||
@@ -310,21 +322,12 @@ module ProductImport
|
||||
end
|
||||
|
||||
def create_inventory_item(entry, existing_variant)
|
||||
existing_variant_override = VariantOverride.where(
|
||||
variant_id: existing_variant.id,
|
||||
hub_id: entry.enterprise_id
|
||||
).first
|
||||
find_or_initialize_variant_override(entry, existing_variant).tap do |variant_override|
|
||||
check_variant_override_stock_settings(entry, variant_override)
|
||||
|
||||
variant_override = existing_variant_override || VariantOverride.new(
|
||||
variant_id: existing_variant.id,
|
||||
hub_id: entry.enterprise_id
|
||||
)
|
||||
|
||||
variant_override.assign_attributes(count_on_hand: entry.on_hand, import_date: @import_time)
|
||||
check_on_hand_nil(entry, variant_override)
|
||||
variant_override.assign_attributes(entry.attributes.slice('price', 'on_demand'))
|
||||
|
||||
variant_override
|
||||
variant_override.assign_attributes(import_date: @import_time)
|
||||
variant_override.assign_attributes(entry.attributes.slice('price', 'on_demand'))
|
||||
end
|
||||
end
|
||||
|
||||
def mark_as_inventory_item(entry, variant_override)
|
||||
@@ -355,5 +358,11 @@ module ProductImport
|
||||
object.count_on_hand = 0 if object.respond_to?(:count_on_hand)
|
||||
entry.on_hand_nil = true
|
||||
end
|
||||
|
||||
def check_variant_override_stock_settings(entry, object)
|
||||
object.count_on_hand = entry.on_hand.presence
|
||||
object.on_demand = object.count_on_hand.blank? if entry.on_demand.blank?
|
||||
entry.on_hand_nil = object.count_on_hand.blank?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
class VariantOverride < ActiveRecord::Base
|
||||
extend Spree::LocalizedNumber
|
||||
include StockSettingsOverrideValidation
|
||||
|
||||
acts_as_taggable
|
||||
|
||||
@@ -58,7 +59,7 @@ class VariantOverride < ActiveRecord::Base
|
||||
def reset_stock!
|
||||
if resettable
|
||||
if default_stock?
|
||||
self.attributes = { count_on_hand: default_stock }
|
||||
self.attributes = { on_demand: false, count_on_hand: default_stock }
|
||||
save
|
||||
else
|
||||
Bugsnag.notify RuntimeError.new "Attempting to reset stock level for a variant with no default stock level."
|
||||
|
||||
@@ -2,17 +2,17 @@
|
||||
.alpha.three.columns
|
||||
= f.label :facebook, 'Facebook'
|
||||
.omega.eight.columns
|
||||
= f.text_field :facebook
|
||||
= f.text_field :facebook, { placeholder: t('.facebook_placeholder') }
|
||||
.row
|
||||
.alpha.three.columns
|
||||
= f.label :instagram, 'Instagram'
|
||||
.omega.eight.columns
|
||||
= f.text_field :instagram
|
||||
= f.text_field :instagram, { placeholder: t('.instagram_placeholder') }
|
||||
.row
|
||||
.alpha.three.columns
|
||||
= f.label :linkedin, 'LinkedIn'
|
||||
.omega.eight.columns
|
||||
= f.text_field :linkedin
|
||||
= f.text_field :linkedin, { placeholder: t('.linkedin_placeholder') }
|
||||
.row
|
||||
.alpha.three.columns
|
||||
= f.label :twitter
|
||||
|
||||
@@ -8,9 +8,9 @@
|
||||
%td.price{ ng: { show: 'columns.price.visible' } }
|
||||
%input{name: 'variant-overrides-{{ variant.id }}-price', type: 'text', ng: {model: 'variantOverrides[hub_id][variant.id].price'}, placeholder: '{{ variant.price }}', 'ofn-track-variant-override' => 'price'}
|
||||
%td.on_hand{ ng: { show: 'columns.on_hand.visible' } }
|
||||
%input{name: 'variant-overrides-{{ variant.id }}-count_on_hand', type: 'text', ng: {model: 'variantOverrides[hub_id][variant.id].count_on_hand'}, placeholder: '{{ variant.on_hand }}', 'ofn-track-variant-override' => 'count_on_hand'}
|
||||
%input{name: 'variant-overrides-{{ variant.id }}-count_on_hand', type: 'text', ng: { model: 'variantOverrides[hub_id][variant.id].count_on_hand', readonly: 'variantOverrides[hub_id][variant.id].on_demand != false' }, placeholder: '{{ countOnHandPlaceholder(variant, hub_id) }}', 'ofn-track-variant-override' => 'count_on_hand'}
|
||||
%td.on_demand{ ng: { show: 'columns.on_demand.visible' } }
|
||||
%input.field{ :type => 'checkbox', name: 'variant-overrides-{{ variant.id }}-on_demand', ng: { model: 'variantOverrides[hub_id][variant.id].on_demand' }, 'ofn-track-variant-override' => 'on_demand' }
|
||||
%select{ name: 'variant-overrides-{{ variant.id }}-on_demand', ng: { model: 'variantOverrides[hub_id][variant.id].on_demand', change: 'updateCountOnHand(variant, hub_id)', options: 'option.value as option.description for option in onDemandOptions' }, 'ofn-track-variant-override' => 'on_demand' }
|
||||
%td.reset{ ng: { show: 'columns.reset.visible' } }
|
||||
%input{name: 'variant-overrides-{{ variant.id }}-resettable', type: 'checkbox', ng: {model: 'variantOverrides[hub_id][variant.id].resettable'}, placeholder: '{{ variant.resettable }}', 'ofn-track-variant-override' => 'resettable'}
|
||||
%td.reset{ ng: { show: 'columns.reset.visible' } }
|
||||
@@ -24,4 +24,4 @@
|
||||
%button.icon-remove.fullwidth{ :type => 'button', ng: { click: "setVisibility(hub_id,variant.id,false)" } }
|
||||
= t('admin.variant_overrides.index.hide')
|
||||
%td.import_date{ ng: { show: 'columns.import_date.visible' } }
|
||||
%span {{variantOverrides[hub_id][variant.id].import_date | date:"MMMM dd, yyyy HH:mm"}}
|
||||
%span {{variantOverrides[hub_id][variant.id].import_date | date:"MMMM dd, yyyy HH:mm"}}
|
||||
|
||||
Reference in New Issue
Block a user