mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-14 18:56:49 +00:00
Compare commits
95 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
20cabe6f12 | ||
|
|
fe849b8dfd | ||
|
|
167b44c30f | ||
|
|
ad247e2116 | ||
|
|
e46875376e | ||
|
|
d7223c508a | ||
|
|
a91a23aa39 | ||
|
|
370f66e36b | ||
|
|
f7cdcf02e0 | ||
|
|
1ee43fb495 | ||
|
|
e139d24639 | ||
|
|
0dfe749496 | ||
|
|
d6eade6fa3 | ||
|
|
109aed684e | ||
|
|
35d76ac991 | ||
|
|
1ab9e9d7a5 | ||
|
|
e5e716e150 | ||
|
|
b6510c3ab6 | ||
|
|
a158a986c6 | ||
|
|
c7643db66f | ||
|
|
eb8c22aa06 | ||
|
|
d0656485d7 | ||
|
|
640cc1b6d3 | ||
|
|
d65d17a9f3 | ||
|
|
bbea00e431 | ||
|
|
3cecba70e8 | ||
|
|
8bbff09066 | ||
|
|
a7a89d7ccb | ||
|
|
3ccf76ff5f | ||
|
|
6004208496 | ||
|
|
3ce9c712cf | ||
|
|
bfb0032fd2 | ||
|
|
fe37516ead | ||
|
|
289b75e143 | ||
|
|
09f0f8c33f | ||
|
|
8bc1718978 | ||
|
|
cbfce69a6d | ||
|
|
4e0ecdd44c | ||
|
|
23ab9a4bed | ||
|
|
f623446e3e | ||
|
|
6944fe1e46 | ||
|
|
7c9e3d7f06 | ||
|
|
bdcadf9fc6 | ||
|
|
9b7139fd45 | ||
|
|
543e275d2e | ||
|
|
560fa6b949 | ||
|
|
dbf34da87b | ||
|
|
d6022062e1 | ||
|
|
b082d3301b | ||
|
|
48cd542138 | ||
|
|
e2d341c9c2 | ||
|
|
89873a2640 | ||
|
|
b4be2cc2d4 | ||
|
|
35f89a9750 | ||
|
|
592a53b6f5 | ||
|
|
eab9d42eb0 | ||
|
|
cf05369ca9 | ||
|
|
a2bc61cb4d | ||
|
|
c5a17bcde0 | ||
|
|
b712ec7f13 | ||
|
|
32a7f13dd2 | ||
|
|
713769b497 | ||
|
|
495de37620 | ||
|
|
05d24cf11a | ||
|
|
edd84530af | ||
|
|
6677543de0 | ||
|
|
30aa31252b | ||
|
|
b83d74a609 | ||
|
|
d31b50be3d | ||
|
|
42e3f2f2f4 | ||
|
|
96737da128 | ||
|
|
7f9f0d840c | ||
|
|
686840e262 | ||
|
|
2377b833ee | ||
|
|
3f3c33bce6 | ||
|
|
e35eff95bb | ||
|
|
de9476a8a5 | ||
|
|
bce41a2247 | ||
|
|
36883bc051 | ||
|
|
50731e929e | ||
|
|
baa09b88f7 | ||
|
|
2f60a85593 | ||
|
|
78cf35807a | ||
|
|
eb85dccac1 | ||
|
|
f32454b404 | ||
|
|
591efecde6 | ||
|
|
24afa21885 | ||
|
|
bdb3dd5aaf | ||
|
|
25fbab2e37 | ||
|
|
4d37aaac64 | ||
|
|
19e28cb14a | ||
|
|
a44a251d96 | ||
|
|
2921ee19e1 | ||
|
|
6796d91a07 | ||
|
|
69afcf7510 |
@@ -110,18 +110,6 @@ Metrics/LineLength:
|
||||
- app/models/variant_override.rb
|
||||
- app/models/variant_override_set.rb
|
||||
- app/overrides/add_enterprise_fees_to_admin_configurations_menu.rb
|
||||
- app/serializers/api/admin/basic_enterprise_serializer.rb
|
||||
- app/serializers/api/admin/enterprise_fee_serializer.rb
|
||||
- app/serializers/api/admin/enterprise_serializer.rb
|
||||
- app/serializers/api/admin/exchange_serializer.rb
|
||||
- app/serializers/api/admin/for_order_cycle/enterprise_serializer.rb
|
||||
- app/serializers/api/admin/index_enterprise_serializer.rb
|
||||
- app/serializers/api/admin/index_order_cycle_serializer.rb
|
||||
- app/serializers/api/admin/line_item_serializer.rb
|
||||
- app/serializers/api/admin/order_cycle_serializer.rb
|
||||
- app/serializers/api/admin/subscription_serializer.rb
|
||||
- app/serializers/api/admin/tag_rule_serializer.rb
|
||||
- app/serializers/api/admin/variant_override_serializer.rb
|
||||
- app/services/cart_service.rb
|
||||
- app/services/default_stock_location.rb
|
||||
- app/services/embedded_page_service.rb
|
||||
@@ -148,7 +136,6 @@ Metrics/LineLength:
|
||||
- lib/open_food_network/order_cycle_form_applicator.rb
|
||||
- lib/open_food_network/order_cycle_management_report.rb
|
||||
- lib/open_food_network/order_grouper.rb
|
||||
- lib/open_food_network/orders_and_fulfillments_report.rb
|
||||
- lib/open_food_network/payments_report.rb
|
||||
- lib/open_food_network/permalink_generator.rb
|
||||
- lib/open_food_network/products_cache.rb
|
||||
@@ -454,7 +441,6 @@ Metrics/AbcSize:
|
||||
- lib/open_food_network/order_cycle_form_applicator.rb
|
||||
- lib/open_food_network/order_cycle_management_report.rb
|
||||
- lib/open_food_network/order_cycle_permissions.rb
|
||||
- lib/open_food_network/orders_and_fulfillments_report.rb
|
||||
- lib/open_food_network/packing_report.rb
|
||||
- lib/open_food_network/payments_report.rb
|
||||
- lib/open_food_network/permissions.rb
|
||||
@@ -532,7 +518,6 @@ Metrics/CyclomaticComplexity:
|
||||
- lib/discourse/single_sign_on.rb
|
||||
- lib/open_food_network/bulk_coop_report.rb
|
||||
- lib/open_food_network/enterprise_issue_validator.rb
|
||||
- lib/open_food_network/orders_and_fulfillments_report.rb
|
||||
- lib/spree/core/controller_helpers/order_decorator.rb
|
||||
- lib/spree/core/controller_helpers/respond_with_decorator.rb
|
||||
- lib/spree/localized_number.rb
|
||||
@@ -557,7 +542,6 @@ Metrics/PerceivedComplexity:
|
||||
- lib/discourse/single_sign_on.rb
|
||||
- lib/open_food_network/bulk_coop_report.rb
|
||||
- lib/open_food_network/enterprise_issue_validator.rb
|
||||
- lib/open_food_network/orders_and_fulfillments_report.rb
|
||||
- lib/spree/core/controller_helpers/order_decorator.rb
|
||||
- lib/spree/core/controller_helpers/respond_with_decorator.rb
|
||||
- lib/spree/localized_number.rb
|
||||
@@ -627,7 +611,6 @@ Metrics/MethodLength:
|
||||
- lib/open_food_network/order_cycle_management_report.rb
|
||||
- lib/open_food_network/order_cycle_permissions.rb
|
||||
- lib/open_food_network/order_grouper.rb
|
||||
- lib/open_food_network/orders_and_fulfillments_report.rb
|
||||
- lib/open_food_network/packing_report.rb
|
||||
- lib/open_food_network/payments_report.rb
|
||||
- lib/open_food_network/permissions.rb
|
||||
@@ -671,7 +654,6 @@ Metrics/ClassLength:
|
||||
- lib/open_food_network/order_cycle_form_applicator.rb
|
||||
- lib/open_food_network/order_cycle_management_report.rb
|
||||
- lib/open_food_network/order_cycle_permissions.rb
|
||||
- lib/open_food_network/orders_and_fulfillments_report.rb
|
||||
- lib/open_food_network/packing_report.rb
|
||||
- lib/open_food_network/payments_report.rb
|
||||
- lib/open_food_network/permissions.rb
|
||||
|
||||
2
Gemfile
2
Gemfile
@@ -39,7 +39,7 @@ gem 'activemerchant', '~> 1.78'
|
||||
gem 'devise', '~> 2.2.5'
|
||||
gem 'devise-encryptable', '0.2.0'
|
||||
gem 'jwt', '~> 2.2'
|
||||
gem 'oauth2', '~> 1.4.1' # Used for Stripe Connect
|
||||
gem 'oauth2', '~> 1.4.2' # Used for Stripe Connect
|
||||
|
||||
gem 'daemons'
|
||||
gem 'delayed_job_active_record'
|
||||
|
||||
42
Gemfile.lock
42
Gemfile.lock
@@ -223,7 +223,7 @@ GEM
|
||||
activerecord (>= 3.2.0, < 5.0)
|
||||
fog (~> 1.0)
|
||||
rails (>= 3.2.0, < 5.0)
|
||||
ddtrace (0.27.0)
|
||||
ddtrace (0.28.0)
|
||||
msgpack
|
||||
debugger-linecache (1.2.0)
|
||||
deface (1.0.2)
|
||||
@@ -491,8 +491,8 @@ GEM
|
||||
newrelic_rpm (3.18.1.330)
|
||||
nokogiri (1.6.8.1)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
oauth2 (1.4.1)
|
||||
faraday (>= 0.8, < 0.16.0)
|
||||
oauth2 (1.4.2)
|
||||
faraday (>= 0.8, < 2.0)
|
||||
jwt (>= 1.0, < 3.0)
|
||||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
@@ -596,29 +596,29 @@ GEM
|
||||
nokogiri
|
||||
roo (>= 2.0.0beta1, < 3)
|
||||
spreadsheet (> 0.9.0)
|
||||
rspec (3.8.0)
|
||||
rspec-core (~> 3.8.0)
|
||||
rspec-expectations (~> 3.8.0)
|
||||
rspec-mocks (~> 3.8.0)
|
||||
rspec-core (3.8.0)
|
||||
rspec-support (~> 3.8.0)
|
||||
rspec-expectations (3.8.2)
|
||||
rspec (3.9.0)
|
||||
rspec-core (~> 3.9.0)
|
||||
rspec-expectations (~> 3.9.0)
|
||||
rspec-mocks (~> 3.9.0)
|
||||
rspec-core (3.9.0)
|
||||
rspec-support (~> 3.9.0)
|
||||
rspec-expectations (3.9.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.8.0)
|
||||
rspec-mocks (3.8.0)
|
||||
rspec-support (~> 3.9.0)
|
||||
rspec-mocks (3.9.0)
|
||||
diff-lcs (>= 1.2.0, < 2.0)
|
||||
rspec-support (~> 3.8.0)
|
||||
rspec-rails (3.8.2)
|
||||
rspec-support (~> 3.9.0)
|
||||
rspec-rails (3.9.0)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
rspec-core (~> 3.8.0)
|
||||
rspec-expectations (~> 3.8.0)
|
||||
rspec-mocks (~> 3.8.0)
|
||||
rspec-support (~> 3.8.0)
|
||||
rspec-core (~> 3.9.0)
|
||||
rspec-expectations (~> 3.9.0)
|
||||
rspec-mocks (~> 3.9.0)
|
||||
rspec-support (~> 3.9.0)
|
||||
rspec-retry (0.6.1)
|
||||
rspec-core (> 3.3)
|
||||
rspec-support (3.8.0)
|
||||
rspec-support (3.9.0)
|
||||
rubocop (0.57.2)
|
||||
jaro_winkler (~> 1.5.1)
|
||||
parallel (~> 1.10)
|
||||
@@ -630,7 +630,7 @@ GEM
|
||||
ruby-ole (1.2.12.1)
|
||||
ruby-progressbar (1.10.1)
|
||||
ruby-rc4 (0.1.5)
|
||||
rubyzip (1.2.2)
|
||||
rubyzip (1.3.0)
|
||||
safe_yaml (1.0.5)
|
||||
sass (3.3.14)
|
||||
sass-rails (3.2.6)
|
||||
@@ -777,7 +777,7 @@ DEPENDENCIES
|
||||
momentjs-rails
|
||||
newrelic_rpm (~> 3.0)
|
||||
nokogiri (>= 1.6.7.1)
|
||||
oauth2 (~> 1.4.1)
|
||||
oauth2 (~> 1.4.2)
|
||||
ofn-qz!
|
||||
oj
|
||||
order_management!
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
module Api
|
||||
class OrdersController < BaseController
|
||||
def show
|
||||
authorize! :read, order
|
||||
render json: order, serializer: Api::OrderDetailedSerializer, current_order: order
|
||||
end
|
||||
|
||||
def index
|
||||
authorize! :admin, Spree::Order
|
||||
|
||||
@@ -19,5 +24,12 @@ module Api
|
||||
each_serializer: Api::Admin::OrderSerializer
|
||||
)
|
||||
end
|
||||
|
||||
def order
|
||||
@order ||= Spree::Order.
|
||||
where(number: params[:id]).
|
||||
includes(line_items: { variant: [:product, :stock_items, :default_price] }).
|
||||
first!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
35
app/controllers/spree/admin/general_settings_controller.rb
Normal file
35
app/controllers/spree/admin/general_settings_controller.rb
Normal file
@@ -0,0 +1,35 @@
|
||||
module Spree
|
||||
module Admin
|
||||
class GeneralSettingsController < Spree::Admin::BaseController
|
||||
def edit
|
||||
@preferences_general = [:site_name, :default_seo_title, :default_meta_keywords,
|
||||
:default_meta_description, :site_url, :bugherd_api_key]
|
||||
@preferences_security = [:allow_ssl_in_production,
|
||||
:allow_ssl_in_staging, :allow_ssl_in_development_and_test,
|
||||
:check_for_spree_alerts]
|
||||
@preferences_currency = [:display_currency, :hide_cents]
|
||||
end
|
||||
|
||||
def update
|
||||
params.each do |name, value|
|
||||
next unless Spree::Config.has_preference? name
|
||||
Spree::Config[name] = value
|
||||
end
|
||||
flash[:success] = Spree.t(:successfully_updated, resource: Spree.t(:general_settings))
|
||||
|
||||
redirect_to edit_admin_general_settings_path
|
||||
end
|
||||
|
||||
def dismiss_alert
|
||||
return unless request.xhr? && params[:alert_id]
|
||||
dismissed = Spree::Config[:dismissed_spree_alerts] || ''
|
||||
Spree::Config.set(dismissed_spree_alerts: dismissed.
|
||||
split(',').
|
||||
push(params[:alert_id]).
|
||||
join(','))
|
||||
filter_dismissed_alerts
|
||||
render nothing: true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,14 +0,0 @@
|
||||
module Spree
|
||||
module Admin
|
||||
GeneralSettingsController.class_eval do
|
||||
end
|
||||
|
||||
module GeneralSettingsEditPreferences
|
||||
def edit
|
||||
super
|
||||
@preferences_general << :bugherd_api_key
|
||||
end
|
||||
end
|
||||
GeneralSettingsController.prepend(GeneralSettingsEditPreferences)
|
||||
end
|
||||
end
|
||||
79
app/controllers/spree/admin/image_settings_controller.rb
Normal file
79
app/controllers/spree/admin/image_settings_controller.rb
Normal file
@@ -0,0 +1,79 @@
|
||||
module Spree
|
||||
module Admin
|
||||
class ImageSettingsController < Spree::Admin::BaseController
|
||||
def edit
|
||||
@styles = ActiveSupport::JSON.decode(Spree::Config[:attachment_styles])
|
||||
@headers = ActiveSupport::JSON.decode(Spree::Config[:s3_headers])
|
||||
end
|
||||
|
||||
def update
|
||||
update_styles(params)
|
||||
update_headers(params) if Spree::Config[:use_s3]
|
||||
|
||||
Spree::Config.set(params[:preferences])
|
||||
update_paperclip_settings
|
||||
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
flash[:success] = Spree.t(:image_settings_updated)
|
||||
redirect_to spree.edit_admin_image_settings_path
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_styles(params)
|
||||
if params[:new_attachment_styles].present?
|
||||
params[:new_attachment_styles].each do |_index, style|
|
||||
params[:attachment_styles][style[:name]] = style[:value] unless style[:value].empty?
|
||||
end
|
||||
end
|
||||
|
||||
styles = params[:attachment_styles]
|
||||
|
||||
Spree::Config[:attachment_styles] = ActiveSupport::JSON.encode(styles) unless styles.nil?
|
||||
end
|
||||
|
||||
def update_headers(params)
|
||||
if params[:new_s3_headers].present?
|
||||
params[:new_s3_headers].each do |_index, header|
|
||||
params[:s3_headers][header[:name]] = header[:value] unless header[:value].empty?
|
||||
end
|
||||
end
|
||||
|
||||
headers = params[:s3_headers]
|
||||
|
||||
Spree::Config[:s3_headers] = ActiveSupport::JSON.encode(headers) unless headers.nil?
|
||||
end
|
||||
|
||||
def update_paperclip_settings
|
||||
if Spree::Config[:use_s3]
|
||||
s3_creds = { access_key_id: Spree::Config[:s3_access_key],
|
||||
secret_access_key: Spree::Config[:s3_secret],
|
||||
bucket: Spree::Config[:s3_bucket] }
|
||||
Spree::Image.attachment_definitions[:attachment][:storage] = :s3
|
||||
Spree::Image.attachment_definitions[:attachment][:s3_credentials] = s3_creds
|
||||
Spree::Image.attachment_definitions[:attachment][:s3_headers] =
|
||||
ActiveSupport::JSON.decode(Spree::Config[:s3_headers])
|
||||
Spree::Image.attachment_definitions[:attachment][:bucket] = Spree::Config[:s3_bucket]
|
||||
else
|
||||
Spree::Image.attachment_definitions[:attachment].delete :storage
|
||||
end
|
||||
|
||||
Spree::Image.attachment_definitions[:attachment][:styles] =
|
||||
ActiveSupport::JSON.decode(Spree::Config[:attachment_styles]).symbolize_keys!
|
||||
Spree::Image.attachment_definitions[:attachment][:path] = Spree::Config[:attachment_path]
|
||||
Spree::Image.attachment_definitions[:attachment][:default_url] =
|
||||
Spree::Config[:attachment_default_url]
|
||||
Spree::Image.attachment_definitions[:attachment][:default_style] =
|
||||
Spree::Config[:attachment_default_style]
|
||||
|
||||
# Spree stores attachent definitions in JSON. This converts the style name and format to
|
||||
# strings. However, when paperclip encounters these, it doesn't recognise the format.
|
||||
# Here we solve that problem by converting format and style name to symbols.
|
||||
Spree::Image.reformat_styles
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,11 +0,0 @@
|
||||
Spree::Admin::ImageSettingsController.class_eval do
|
||||
# Spree stores attachent definitions in JSON. This converts the style name and format to
|
||||
# strings. However, when paperclip encounters these, it doesn't recognise the format.
|
||||
# Here we solve that problem by converting format and style name to symbols.
|
||||
def update_paperclip_settings_with_format_styles
|
||||
update_paperclip_settings_without_format_styles
|
||||
Spree::Image.reformat_styles
|
||||
end
|
||||
|
||||
alias_method_chain :update_paperclip_settings, :format_styles
|
||||
end
|
||||
39
app/controllers/spree/admin/mail_methods_controller.rb
Normal file
39
app/controllers/spree/admin/mail_methods_controller.rb
Normal file
@@ -0,0 +1,39 @@
|
||||
module Spree
|
||||
module Admin
|
||||
class MailMethodsController < Spree::Admin::BaseController
|
||||
after_filter :initialize_mail_settings
|
||||
|
||||
def update
|
||||
if params[:smtp_password].blank?
|
||||
params.delete(:smtp_password)
|
||||
end
|
||||
|
||||
params.each do |name, value|
|
||||
next unless Spree::Config.has_preference? name
|
||||
Spree::Config[name] = value
|
||||
end
|
||||
|
||||
flash[:success] = Spree.t(:successfully_updated, resource: Spree.t(:mail_methods))
|
||||
render :edit
|
||||
end
|
||||
|
||||
def testmail
|
||||
if TestMailer.test_email(try_spree_current_user).deliver
|
||||
flash[:success] = Spree.t('admin.mail_methods.testmail.delivery_success')
|
||||
else
|
||||
flash[:error] = Spree.t('admin.mail_methods.testmail.delivery_error')
|
||||
end
|
||||
rescue StandardError => e
|
||||
flash[:error] = Spree.t('admin.mail_methods.testmail.error') % { e: e }
|
||||
ensure
|
||||
redirect_to edit_admin_mail_method_url
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def initialize_mail_settings
|
||||
Spree::Core::MailSettings.init
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -30,6 +30,11 @@ Spree::Admin::ProductsController.class_eval do
|
||||
@show_latest_import = params[:latest_import] || false
|
||||
end
|
||||
|
||||
def new
|
||||
@object.shipping_category = DefaultShippingCategory.find_or_create
|
||||
super
|
||||
end
|
||||
|
||||
def create
|
||||
delete_stock_params_and_set_after do
|
||||
super
|
||||
@@ -44,8 +49,6 @@ Spree::Admin::ProductsController.class_eval do
|
||||
delete_stock_params_and_set_after do
|
||||
super
|
||||
end
|
||||
|
||||
clear_variants_unit_description if @object.variant_unit == 'items'
|
||||
end
|
||||
|
||||
def bulk_update
|
||||
@@ -190,10 +193,4 @@ Spree::Admin::ProductsController.class_eval do
|
||||
def set_product_master_variant_price_to_zero
|
||||
@product.price = 0 if @product.price.nil?
|
||||
end
|
||||
|
||||
def clear_variants_unit_description
|
||||
@object.variants.each do |variant|
|
||||
variant.update_attribute :unit_description, ''
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -19,6 +19,11 @@ module Spree
|
||||
collection
|
||||
end
|
||||
|
||||
def new
|
||||
@object.shipping_categories = [DefaultShippingCategory.find_or_create]
|
||||
super
|
||||
end
|
||||
|
||||
def destroy
|
||||
# Our reports are not adapted to soft deleted shipping_methods so here we prevent
|
||||
# the deletion (even soft) of shipping_methods that are referenced in orders
|
||||
|
||||
13
app/helpers/spree/admin/general_settings_helper.rb
Normal file
13
app/helpers/spree/admin/general_settings_helper.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
module Spree
|
||||
module Admin
|
||||
module GeneralSettingsHelper
|
||||
def currency_options
|
||||
currencies = ::Money::Currency.table.map do |_code, details|
|
||||
iso = details[:iso_code]
|
||||
[iso, "#{details[:name]} (#{iso})"]
|
||||
end
|
||||
options_from_collection_for_select(currencies, :first, :last, Spree::Config[:currency])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -207,12 +207,15 @@ class AbilityDecorator
|
||||
end
|
||||
|
||||
def add_order_management_abilities(user)
|
||||
# Enterprise User can only access orders that they are a distributor for
|
||||
can [:index, :create], Spree::Order
|
||||
can [:read, :update, :fire, :resend, :invoice, :print, :print_ticket], Spree::Order do |order|
|
||||
# We allow editing orders with a nil distributor as this state occurs
|
||||
# during the order creation process from the admin backend
|
||||
order.distributor.nil? || user.enterprises.include?(order.distributor) || order.order_cycle.andand.coordinated_by?(user)
|
||||
order.distributor.nil? ||
|
||||
# Enterprise User can access orders that they are a distributor for
|
||||
user.enterprises.include?(order.distributor) ||
|
||||
# Enterprise User can access orders that are placed inside a OC they coordinate
|
||||
order.order_cycle.andand.coordinated_by?(user)
|
||||
end
|
||||
can [:admin, :bulk_management, :managed], Spree::Order do
|
||||
user.admin? || user.enterprises.any?(&:is_distributor)
|
||||
|
||||
@@ -4,7 +4,11 @@ class Api::AddressSerializer < ActiveModel::Serializer
|
||||
|
||||
attributes :id, :zipcode, :city, :state_name, :state_id,
|
||||
:phone, :firstname, :lastname, :address1, :address2, :city, :country_id,
|
||||
:zipcode
|
||||
:zipcode, :country_name
|
||||
|
||||
def country_name
|
||||
object.country.andand.name
|
||||
end
|
||||
|
||||
def state_name
|
||||
object.state.andand.abbr
|
||||
|
||||
8
app/serializers/api/adjustment_serializer.rb
Normal file
8
app/serializers/api/adjustment_serializer.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
module Api
|
||||
class AdjustmentSerializer < ActiveModel::Serializer
|
||||
attributes :id, :amount, :label, :eligible,
|
||||
:source_type, :source_id,
|
||||
:adjustable_type, :adjustable_id,
|
||||
:originator_type, :originator_id
|
||||
end
|
||||
end
|
||||
@@ -1,4 +1,4 @@
|
||||
class Api::Admin::BasicEnterpriseSerializer < ActiveModel::Serializer
|
||||
attributes :name, :id, :is_primary_producer, :is_distributor, :sells, :category, :payment_method_ids, :shipping_method_ids
|
||||
attributes :producer_profile_only, :permalink
|
||||
attributes :name, :id, :is_primary_producer, :is_distributor, :sells, :category,
|
||||
:payment_method_ids, :shipping_method_ids, :producer_profile_only, :permalink
|
||||
end
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class Api::Admin::CustomerSerializer < ActiveModel::Serializer
|
||||
attributes :id, :email, :enterprise_id, :user_id, :code, :tags, :tag_list, :name
|
||||
attributes :allow_charges, :default_card_present?
|
||||
attributes :id, :email, :enterprise_id, :user_id, :code, :tags, :tag_list, :name,
|
||||
:allow_charges, :default_card_present?
|
||||
|
||||
has_one :ship_address, serializer: Api::AddressSerializer
|
||||
has_one :bill_address, serializer: Api::AddressSerializer
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class Api::Admin::EnterpriseFeeSerializer < ActiveModel::Serializer
|
||||
attributes :id, :enterprise_id, :fee_type, :name, :tax_category_id, :inherits_tax_category, :calculator_type
|
||||
attributes :enterprise_name, :calculator_description, :calculator_settings
|
||||
attributes :id, :enterprise_id, :fee_type, :name, :tax_category_id, :inherits_tax_category,
|
||||
:calculator_type, :enterprise_name, :calculator_description, :calculator_settings
|
||||
|
||||
def enterprise_name
|
||||
object.enterprise.andand.name
|
||||
@@ -16,7 +16,9 @@ class Api::Admin::EnterpriseFeeSerializer < ActiveModel::Serializer
|
||||
result = nil
|
||||
|
||||
options[:controller].__send__(:with_format, :html) do
|
||||
result = options[:controller].render_to_string partial: 'admin/enterprise_fees/calculator_settings', locals: { enterprise_fee: object }
|
||||
result = options[:controller].
|
||||
render_to_string(partial: 'admin/enterprise_fees/calculator_settings',
|
||||
locals: { enterprise_fee: object })
|
||||
end
|
||||
|
||||
result.gsub('[0]', '[{{ $index }}]').gsub('_0_', '_{{ $index }}_')
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
class Api::Admin::EnterpriseSerializer < ActiveModel::Serializer
|
||||
attributes :name, :id, :is_primary_producer, :is_distributor, :sells, :category, :payment_method_ids, :shipping_method_ids
|
||||
attributes :producer_profile_only, :long_description, :permalink
|
||||
attributes :preferred_shopfront_message, :preferred_shopfront_closed_message, :preferred_shopfront_taxon_order, :preferred_shopfront_order_cycle_order
|
||||
attributes :preferred_product_selection_from_inventory_only
|
||||
attributes :owner, :contact, :users, :tag_groups, :default_tag_group
|
||||
attributes :require_login, :allow_guest_orders, :allow_order_changes
|
||||
attributes :logo, :promo_image
|
||||
attributes :name, :id, :is_primary_producer, :is_distributor, :sells, :category, :permalink,
|
||||
:payment_method_ids, :shipping_method_ids, :producer_profile_only, :long_description,
|
||||
:preferred_shopfront_message, :preferred_shopfront_closed_message,
|
||||
:preferred_shopfront_taxon_order, :preferred_shopfront_order_cycle_order,
|
||||
:preferred_product_selection_from_inventory_only,
|
||||
:owner, :contact, :users, :tag_groups, :default_tag_group,
|
||||
:require_login, :allow_guest_orders, :allow_order_changes,
|
||||
:logo, :promo_image
|
||||
|
||||
has_one :owner, serializer: Api::Admin::UserSerializer
|
||||
has_many :users, serializer: Api::Admin::UserSerializer
|
||||
@@ -21,7 +22,9 @@ class Api::Admin::EnterpriseSerializer < ActiveModel::Serializer
|
||||
|
||||
def tag_groups
|
||||
object.tag_rules.prioritised.reject(&:is_default).each_with_object([]) do |tag_rule, tag_groups|
|
||||
tag_group = find_match(tag_groups, tag_rule.preferred_customer_tags.split(",").map{ |t| { text: t } })
|
||||
tag_group = find_match(tag_groups, tag_rule.preferred_customer_tags.
|
||||
split(",").
|
||||
map{ |t| { text: t } })
|
||||
if tag_group[:rules].empty?
|
||||
tag_groups << tag_group
|
||||
tag_group[:position] = tag_groups.count
|
||||
@@ -32,13 +35,16 @@ class Api::Admin::EnterpriseSerializer < ActiveModel::Serializer
|
||||
|
||||
def default_tag_group
|
||||
default_rules = object.tag_rules.select(&:is_default)
|
||||
serialized_rules = ActiveModel::ArraySerializer.new(default_rules, each_serializer: Api::Admin::TagRuleSerializer)
|
||||
serialized_rules =
|
||||
ActiveModel::ArraySerializer.new(default_rules,
|
||||
each_serializer: Api::Admin::TagRuleSerializer)
|
||||
{ tags: [], rules: serialized_rules }
|
||||
end
|
||||
|
||||
def find_match(tag_groups, tags)
|
||||
tag_groups.each do |tag_group|
|
||||
return tag_group if tag_group[:tags].length == tags.length && (tag_group[:tags] & tags) == tag_group[:tags]
|
||||
return tag_group if tag_group[:tags].length == tags.length &&
|
||||
(tag_group[:tags] & tags) == tag_group[:tags]
|
||||
end
|
||||
{ tags: tags, rules: [] }
|
||||
end
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
class Api::Admin::ExchangeSerializer < ActiveModel::Serializer
|
||||
attributes :id, :sender_id, :receiver_id, :incoming, :variants, :receival_instructions, :pickup_time, :pickup_instructions
|
||||
attributes :tags, :tag_list
|
||||
attributes :id, :sender_id, :receiver_id, :incoming, :variants,
|
||||
:receival_instructions, :pickup_time, :pickup_instructions,
|
||||
:tags, :tag_list
|
||||
|
||||
has_many :enterprise_fees, serializer: Api::Admin::BasicEnterpriseFeeSerializer
|
||||
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
require 'open_food_network/enterprise_issue_validator'
|
||||
|
||||
class Api::Admin::ForOrderCycle::EnterpriseSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name, :managed, :supplied_products
|
||||
attributes :issues_summary_supplier, :issues_summary_distributor
|
||||
attributes :is_primary_producer, :is_distributor, :sells
|
||||
attributes :id, :name, :managed, :supplied_products,
|
||||
:issues_summary_supplier, :issues_summary_distributor,
|
||||
:is_primary_producer, :is_distributor, :sells
|
||||
|
||||
def issues_summary_supplier
|
||||
issues = OpenFoodNetwork::EnterpriseIssueValidator.new(object).issues_summary confirmation_only: true
|
||||
issues =
|
||||
OpenFoodNetwork::EnterpriseIssueValidator.
|
||||
new(object).
|
||||
issues_summary(confirmation_only: true)
|
||||
|
||||
if issues.nil? && products.empty?
|
||||
issues = "no products in inventory"
|
||||
end
|
||||
@@ -23,7 +27,8 @@ class Api::Admin::ForOrderCycle::EnterpriseSerializer < ActiveModel::Serializer
|
||||
|
||||
def supplied_products
|
||||
serializer = Api::Admin::ForOrderCycle::SuppliedProductSerializer
|
||||
ActiveModel::ArraySerializer.new(products, each_serializer: serializer, order_cycle: order_cycle)
|
||||
ActiveModel::ArraySerializer.new(products, each_serializer: serializer,
|
||||
order_cycle: order_cycle)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
require 'open_food_network/enterprise_issue_validator'
|
||||
|
||||
class Api::Admin::IndexEnterpriseSerializer < ActiveModel::Serializer
|
||||
attributes :name, :id, :permalink, :is_primary_producer, :sells, :producer_profile_only, :owned, :edit_path
|
||||
|
||||
attributes :issues, :warnings
|
||||
attributes :name, :id, :permalink, :is_primary_producer, :sells, :producer_profile_only, :owned,
|
||||
:edit_path, :issues, :warnings
|
||||
|
||||
def owned
|
||||
return true if options[:spree_current_user].admin?
|
||||
|
||||
@@ -5,9 +5,9 @@ module Api
|
||||
class IndexOrderCycleSerializer < ActiveModel::Serializer
|
||||
include OrderCyclesHelper
|
||||
|
||||
attributes :id, :name, :orders_open_at, :orders_close_at, :status, :variant_count, :deletable
|
||||
attributes :coordinator, :producers, :shops, :viewing_as_coordinator
|
||||
attributes :edit_path, :clone_path, :delete_path, :subscriptions_count
|
||||
attributes :id, :name, :orders_open_at, :orders_close_at, :status, :variant_count, :deletable,
|
||||
:coordinator, :producers, :shops, :viewing_as_coordinator,
|
||||
:edit_path, :clone_path, :delete_path, :subscriptions_count
|
||||
|
||||
has_many :schedules, serializer: Api::Admin::IdNameSerializer
|
||||
|
||||
@@ -68,7 +68,10 @@ module Api
|
||||
private
|
||||
|
||||
def visible_enterprises
|
||||
@visible_enterprises ||= OpenFoodNetwork::OrderCyclePermissions.new(options[:current_user], object).visible_enterprises
|
||||
@visible_enterprises ||=
|
||||
OpenFoodNetwork::OrderCyclePermissions.
|
||||
new(options[:current_user], object).
|
||||
visible_enterprises
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
class Api::Admin::LineItemSerializer < ActiveModel::Serializer
|
||||
attributes :id, :quantity, :max_quantity, :price, :supplier, :final_weight_volume, :units_product, :units_variant
|
||||
attributes :id, :quantity, :max_quantity, :price, :supplier, :final_weight_volume,
|
||||
:units_product, :units_variant
|
||||
|
||||
has_one :order, serializer: Api::Admin::IdSerializer
|
||||
|
||||
@@ -20,7 +21,8 @@ class Api::Admin::LineItemSerializer < ActiveModel::Serializer
|
||||
end
|
||||
|
||||
def max_quantity
|
||||
return object.quantity unless object.max_quantity.present? && object.max_quantity > object.quantity
|
||||
return object.quantity unless object.max_quantity.present? &&
|
||||
object.max_quantity > object.quantity
|
||||
object.max_quantity
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
require 'open_food_network/order_cycle_permissions'
|
||||
|
||||
class Api::Admin::OrderCycleSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name, :orders_open_at, :orders_close_at, :coordinator_id, :exchanges
|
||||
attributes :editable_variants_for_incoming_exchanges, :editable_variants_for_outgoing_exchanges
|
||||
attributes :visible_variants_for_outgoing_exchanges
|
||||
attributes :viewing_as_coordinator, :schedule_ids, :subscriptions_count
|
||||
attributes :id, :name, :orders_open_at, :orders_close_at, :coordinator_id, :exchanges,
|
||||
:editable_variants_for_incoming_exchanges, :editable_variants_for_outgoing_exchanges,
|
||||
:visible_variants_for_outgoing_exchanges,
|
||||
:viewing_as_coordinator, :schedule_ids, :subscriptions_count
|
||||
|
||||
has_many :coordinator_fees, serializer: Api::IdSerializer
|
||||
|
||||
@@ -25,8 +25,14 @@ class Api::Admin::OrderCycleSerializer < ActiveModel::Serializer
|
||||
end
|
||||
|
||||
def exchanges
|
||||
scoped_exchanges = OpenFoodNetwork::OrderCyclePermissions.new(options[:current_user], object).visible_exchanges.by_enterprise_name
|
||||
ActiveModel::ArraySerializer.new(scoped_exchanges, each_serializer: Api::Admin::ExchangeSerializer, current_user: options[:current_user])
|
||||
scoped_exchanges =
|
||||
OpenFoodNetwork::OrderCyclePermissions.
|
||||
new(options[:current_user], object).
|
||||
visible_exchanges.by_enterprise_name
|
||||
|
||||
ActiveModel::ArraySerializer.
|
||||
new(scoped_exchanges, each_serializer: Api::Admin::ExchangeSerializer,
|
||||
current_user: options[:current_user])
|
||||
end
|
||||
|
||||
def editable_variants_for_incoming_exchanges
|
||||
@@ -66,9 +72,13 @@ class Api::Admin::OrderCycleSerializer < ActiveModel::Serializer
|
||||
# for shops. We need this here to allow hubs to restrict visible variants to only those in
|
||||
# their inventory if they so choose
|
||||
variants = if enterprise.prefers_product_selection_from_inventory_only?
|
||||
permissions.visible_variants_for_outgoing_exchanges_to(enterprise).visible_for(enterprise)
|
||||
permissions.
|
||||
visible_variants_for_outgoing_exchanges_to(enterprise).
|
||||
visible_for(enterprise)
|
||||
else
|
||||
permissions.visible_variants_for_outgoing_exchanges_to(enterprise).not_hidden_for(enterprise)
|
||||
permissions.
|
||||
visible_variants_for_outgoing_exchanges_to(enterprise).
|
||||
not_hidden_for(enterprise)
|
||||
end.pluck(:id)
|
||||
visible[enterprise.id] = variants if variants.any?
|
||||
end
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
class Api::Admin::OrderSerializer < ActiveModel::Serializer
|
||||
attributes :id, :number, :full_name, :email, :phone, :completed_at, :display_total
|
||||
attributes :edit_path, :state, :payment_state, :shipment_state
|
||||
attributes :payments_path, :ship_path, :ready_to_ship, :created_at
|
||||
attributes :distributor_name, :special_instructions, :payment_capture_path
|
||||
attributes :id, :number, :user_id, :full_name, :email, :phone, :completed_at, :display_total,
|
||||
:edit_path, :state, :payment_state, :shipment_state,
|
||||
:payments_path, :ship_path, :ready_to_ship, :created_at,
|
||||
:distributor_name, :special_instructions, :payment_capture_path,
|
||||
:item_total, :adjustment_total, :payment_total, :total
|
||||
|
||||
has_one :distributor, serializer: Api::Admin::IdSerializer
|
||||
has_one :order_cycle, serializer: Api::Admin::IdSerializer
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
module Api
|
||||
module Admin
|
||||
class SubscriptionSerializer < ActiveModel::Serializer
|
||||
attributes :id, :shop_id, :customer_id, :schedule_id, :payment_method_id, :shipping_method_id, :begins_at, :ends_at
|
||||
attributes :customer_email, :schedule_name, :edit_path, :canceled_at, :paused_at, :state
|
||||
attributes :shipping_fee_estimate, :payment_fee_estimate
|
||||
attributes :id, :shop_id, :customer_id, :schedule_id, :payment_method_id, :shipping_method_id,
|
||||
:begins_at, :ends_at,
|
||||
:customer_email, :schedule_name, :edit_path, :canceled_at, :paused_at, :state,
|
||||
:shipping_fee_estimate, :payment_fee_estimate
|
||||
|
||||
has_many :subscription_line_items, serializer: Api::Admin::SubscriptionLineItemSerializer
|
||||
has_many :closed_proxy_orders, serializer: Api::Admin::ProxyOrderSerializer
|
||||
|
||||
@@ -16,7 +16,8 @@ module Api::Admin::TagRule
|
||||
end
|
||||
|
||||
class FilterShippingMethodsSerializer < BaseSerializer
|
||||
attributes :preferred_matched_shipping_methods_visibility, :preferred_shipping_method_tags, :shipping_method_tags
|
||||
attributes :preferred_matched_shipping_methods_visibility, :preferred_shipping_method_tags,
|
||||
:shipping_method_tags
|
||||
|
||||
def shipping_method_tags
|
||||
object.preferred_shipping_method_tags.split(",")
|
||||
@@ -24,7 +25,8 @@ module Api::Admin::TagRule
|
||||
end
|
||||
|
||||
class FilterPaymentMethodsSerializer < BaseSerializer
|
||||
attributes :preferred_matched_payment_methods_visibility, :preferred_payment_method_tags, :payment_method_tags
|
||||
attributes :preferred_matched_payment_methods_visibility, :preferred_payment_method_tags,
|
||||
:payment_method_tags
|
||||
|
||||
def payment_method_tags
|
||||
object.preferred_payment_method_tags.split(",")
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class Api::Admin::VariantOverrideSerializer < ActiveModel::Serializer
|
||||
attributes :id, :hub_id, :variant_id, :sku, :price, :count_on_hand, :on_demand, :default_stock, :resettable
|
||||
attributes :tag_list, :tags, :import_date
|
||||
attributes :id, :hub_id, :variant_id, :sku, :price, :count_on_hand, :on_demand, :default_stock,
|
||||
:resettable, :tag_list, :tags, :import_date
|
||||
|
||||
def tag_list
|
||||
object.tag_list.join(",")
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
class Api::Admin::VariantSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name, :producer_name, :image, :sku, :import_date
|
||||
attributes :options_text, :unit_value, :unit_description, :unit_to_display
|
||||
attributes :display_as, :display_name, :name_to_display
|
||||
attributes :price, :on_demand, :on_hand, :in_stock, :stock_location_id, :stock_location_name
|
||||
attributes :id, :name, :producer_name, :image, :sku, :import_date,
|
||||
:options_text, :unit_value, :unit_description, :unit_to_display,
|
||||
:display_as, :display_name, :name_to_display,
|
||||
:price, :on_demand, :on_hand, :in_stock, :stock_location_id, :stock_location_name
|
||||
|
||||
has_many :variant_overrides
|
||||
|
||||
|
||||
12
app/serializers/api/order_detailed_serializer.rb
Normal file
12
app/serializers/api/order_detailed_serializer.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
module Api
|
||||
class OrderDetailedSerializer < Api::Admin::OrderSerializer
|
||||
has_one :shipping_method, serializer: Api::ShippingMethodSerializer
|
||||
has_one :ship_address, serializer: Api::AddressSerializer
|
||||
has_one :bill_address, serializer: Api::AddressSerializer
|
||||
|
||||
has_many :line_items, serializer: Api::LineItemSerializer
|
||||
has_many :adjustments, serializer: Api::AdjustmentSerializer
|
||||
|
||||
has_many :payments, serializer: Api::PaymentSerializer
|
||||
end
|
||||
end
|
||||
@@ -1,9 +1,9 @@
|
||||
module Api
|
||||
class OrderSerializer < ActiveModel::Serializer
|
||||
attributes :number, :completed_at, :total, :state, :shipment_state, :payment_state
|
||||
attributes :outstanding_balance, :payments, :path, :cancel_path
|
||||
attributes :changes_allowed, :changes_allowed_until, :item_count
|
||||
attributes :shop_id
|
||||
attributes :number, :completed_at, :total, :state, :shipment_state, :payment_state,
|
||||
:outstanding_balance, :payments, :path, :cancel_path,
|
||||
:changes_allowed, :changes_allowed_until, :item_count,
|
||||
:shop_id
|
||||
|
||||
has_many :payments, serializer: Api::PaymentSerializer
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
module Api
|
||||
class PaymentSerializer < ActiveModel::Serializer
|
||||
attributes :amount, :updated_at, :payment_method, :state
|
||||
|
||||
def payment_method
|
||||
object.payment_method.try(:name)
|
||||
end
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
class Api::VariantSerializer < ActiveModel::Serializer
|
||||
attributes :id, :is_master, :product_name, :sku
|
||||
attributes :options_text, :unit_value, :unit_description, :unit_to_display
|
||||
attributes :display_as, :display_name, :name_to_display
|
||||
attributes :price, :on_demand, :on_hand, :fees, :price_with_fees
|
||||
attributes :tag_list
|
||||
attributes :id, :is_master, :product_name, :sku,
|
||||
: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
|
||||
|
||||
delegate :price, to: :object
|
||||
|
||||
|
||||
13
app/services/default_shipping_category.rb
Normal file
13
app/services/default_shipping_category.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
# Encapsulates the concept of default stock location in creation of a product or a shipping method.
|
||||
|
||||
class DefaultShippingCategory
|
||||
NAME = 'Default'.freeze
|
||||
|
||||
def self.create!
|
||||
Spree::ShippingCategory.create!(name: NAME)
|
||||
end
|
||||
|
||||
def self.find_or_create
|
||||
Spree::ShippingCategory.find_or_create_by_name(NAME)
|
||||
end
|
||||
end
|
||||
60
app/views/spree/admin/mail_methods/_form.html.haml
Normal file
60
app/views/spree/admin/mail_methods/_form.html.haml
Normal file
@@ -0,0 +1,60 @@
|
||||
%div
|
||||
.row
|
||||
.alpha.six.columns
|
||||
%fieldset.no-border-bottom
|
||||
%legend{align: "center"}= t("spree.general")
|
||||
.field
|
||||
= preference_field_tag("enable_mail_delivery", Spree::Config[:enable_mail_delivery], type: :boolean)
|
||||
= label_tag :enable_mail_delivery, t("spree.enable_mail_delivery")
|
||||
.field
|
||||
= label_tag :mails_from, t("spree.send_mails_as")
|
||||
%br/
|
||||
= text_field_tag :mails_from, Spree::Config[:mails_from], maxlength: 256, class: 'fullwidth'
|
||||
%br/
|
||||
%span.info
|
||||
= t("spree.smtp_send_all_emails_as_from_following_address")
|
||||
.field
|
||||
= label_tag :mail_bcc, t("spree.send_copy_of_all_mails_to")
|
||||
%br/
|
||||
= text_field_tag :mail_bcc, Spree::Config[:mail_bcc], maxlength: 256, class: 'fullwidth'
|
||||
%br/
|
||||
%span.info
|
||||
= t("spree.smtp_send_copy_to_this_addresses")
|
||||
.field
|
||||
= label_tag :intercept_email, t("spree.intercept_email_address")
|
||||
%br/
|
||||
= text_field_tag :intercept_email, Spree::Config[:intercept_email], maxlength: 256, class: 'fullwidth'
|
||||
%br/
|
||||
%span.info
|
||||
= t("spree.intercept_email_instructions")
|
||||
.six.columns.omega
|
||||
%fieldset.no-border-bottom
|
||||
%legend{align: "center"}= t("spree.smtp")
|
||||
.field
|
||||
= label_tag :mail_domain, t("spree.smtp_domain")
|
||||
%br/
|
||||
= text_field_tag :mail_domain, Spree::Config[:mail_domain], class: 'fullwidth'
|
||||
.field
|
||||
= label_tag :mail_host, t("spree.smtp_mail_host")
|
||||
%br/
|
||||
= text_field_tag :mail_host, Spree::Config[:mail_host], class: 'fullwidth'
|
||||
.field
|
||||
= label_tag :mail_port, t("spree.smtp_port")
|
||||
%br/
|
||||
= text_field_tag :mail_port, Spree::Config[:mail_port], class: 'fullwidth'
|
||||
.field
|
||||
= label_tag :secure_connection_type, t("spree.secure_connection_type")
|
||||
%br/
|
||||
= select_tag(:secure_connection_type, options_from_collection_for_select(Spree::Core::MailSettings::SECURE_CONNECTION_TYPES.map{|w| Spree.t(w.downcase.to_sym, default: w)}, :to_s, :to_s, Spree::Config[:secure_connection_type]), class: 'select2 fullwidth')
|
||||
.field
|
||||
= label_tag :mail_auth_type, t("spree.smtp_authentication_type")
|
||||
%br/
|
||||
= select_tag(:mail_auth_type, options_from_collection_for_select(Spree::Core::MailSettings::MAIL_AUTH.map{|w| Spree.t(w.downcase.to_sym, default: w)}, :to_s, :to_s, Spree::Config[:mail_auth_type]), class: 'select2 fullwidth')
|
||||
.field
|
||||
= label_tag :smtp_username, t("spree.smtp_username")
|
||||
%br/
|
||||
= text_field_tag :smtp_username, Spree::Config[:smtp_username], class: 'fullwidth'
|
||||
.field
|
||||
= label_tag :preferred_smtp_password, t("spree.smtp_password")
|
||||
%br/
|
||||
= password_field_tag :smtp_password, Spree::Config[:smtp_password], class: 'fullwidth'
|
||||
15
app/views/spree/admin/mail_methods/edit.html.haml
Normal file
15
app/views/spree/admin/mail_methods/edit.html.haml
Normal file
@@ -0,0 +1,15 @@
|
||||
= render partial: 'spree/admin/shared/configuration_menu'
|
||||
|
||||
- content_for :page_title do
|
||||
= t("spree.mail_method_settings")
|
||||
|
||||
- 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'
|
||||
|
||||
= render partial: 'spree/shared/error_messages', locals: { target: @mail_method }
|
||||
|
||||
= form_tag admin_mail_method_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'
|
||||
@@ -1,4 +1,4 @@
|
||||
= f.field_container :shipping_categories do
|
||||
= f.label :shipping_category_id, t(:shipping_category)
|
||||
= f.collection_select(:shipping_category_id, Spree::ShippingCategory.all, :id, :name, {:include_blank => true}, {:class => 'select2 fullwidth'})
|
||||
= f.collection_select(:shipping_category_id, Spree::ShippingCategory.all, :id, :name, {:include_blank => false}, {:class => 'select2 fullwidth'})
|
||||
= f.error_message_on :shipping_category_id
|
||||
|
||||
@@ -14,9 +14,9 @@
|
||||
= text_field_tag :unit_value_human, nil, {class: "fullwidth", 'ng-model' => 'unit_value_human', 'ng-change' => 'updateValue()'}
|
||||
= f.text_field :unit_value, {hidden: true, 'ng-value' => 'unit_value'}
|
||||
|
||||
.field
|
||||
= f.label :unit_description, t(:spree_admin_unit_description)
|
||||
= f.text_field :unit_description, class: "fullwidth", placeholder: t('admin.products.unit_name_placeholder')
|
||||
.field
|
||||
= f.label :unit_description, t(:spree_admin_unit_description)
|
||||
= f.text_field :unit_description, class: "fullwidth", placeholder: t('admin.products.unit_name_placeholder')
|
||||
|
||||
%div
|
||||
- @product.option_types.each do |option_type|
|
||||
|
||||
@@ -56,3 +56,5 @@ SMTP_PASSWORD: 'f00d'
|
||||
# STRIPE_INSTANCE_PUBLISHABLE_KEY: "pk_test_xxxx" # This can be a test key or a live key
|
||||
# STRIPE_CLIENT_ID: "ca_xxxx" # This can be a development ID or a production ID
|
||||
# STRIPE_ENDPOINT_SECRET: "whsec_xxxx"
|
||||
|
||||
MEMCACHED_VALUE_MAX_MEGABYTES: 4
|
||||
|
||||
@@ -40,7 +40,9 @@ Openfoodnetwork::Application.configure do
|
||||
# config.logger = SyslogLogger.new
|
||||
|
||||
# Use a different cache store in production
|
||||
config.cache_store = :dalli_store
|
||||
memcached_value_max_megabytes = ENV.fetch("MEMCACHED_VALUE_MAX_MEGABYTES", 1).to_i
|
||||
memcached_value_max_bytes = memcached_value_max_megabytes * 1024 * 1024
|
||||
config.cache_store = :dalli_store, { value_max_bytes: memcached_value_max_bytes }
|
||||
|
||||
# Enable serving of images, stylesheets, and JavaScripts from an asset server
|
||||
# config.action_controller.asset_host = "http://assets.example.com"
|
||||
|
||||
@@ -40,7 +40,9 @@ Openfoodnetwork::Application.configure do
|
||||
# config.logger = SyslogLogger.new
|
||||
|
||||
# Use a different cache store in production
|
||||
config.cache_store = :dalli_store
|
||||
memcached_value_max_megabytes = ENV.fetch("MEMCACHED_VALUE_MAX_MEGABYTES", 1).to_i
|
||||
memcached_value_max_bytes = memcached_value_max_megabytes * 1024 * 1024
|
||||
config.cache_store = :dalli_store, { value_max_bytes: memcached_value_max_bytes }
|
||||
|
||||
# Enable serving of images, stylesheets, and JavaScripts from an asset server
|
||||
# config.action_controller.asset_host = "http://assets.example.com"
|
||||
|
||||
@@ -119,9 +119,9 @@ en_CA:
|
||||
shipment_mailer:
|
||||
shipped_email:
|
||||
dear_customer: "Dear Customer, "
|
||||
instructions: "Your order has been shipped"
|
||||
shipment_summary: "Shipment Summary"
|
||||
subject: "Shipment Notification"
|
||||
instructions: "Your order has been shipped or picked up."
|
||||
shipment_summary: "Shipment/Pick Up Summary"
|
||||
subject: "Shipment/Pick Up Notification"
|
||||
thanks: "Thank you for your business."
|
||||
track_information: "Tracking Information: %{tracking}"
|
||||
track_link: "Tracking Link: %{url}"
|
||||
@@ -311,7 +311,7 @@ en_CA:
|
||||
tag_has_rules: "Existing rules for this tag: %{num}"
|
||||
has_one_rule: "has one rule"
|
||||
has_n_rules: "has %{num} rules"
|
||||
unsaved_confirm_leave: "There are unsaved changed on this page. Continue without saving?"
|
||||
unsaved_confirm_leave: "There are unsaved changes on this page. Continue without saving?"
|
||||
unsaved_changes: "You have unsaved changes"
|
||||
shopfront_settings:
|
||||
embedded_shopfront_settings: "Embedded Shopfront Settings"
|
||||
@@ -608,7 +608,7 @@ en_CA:
|
||||
email_address_placeholder: eg. inquiries@fresh-food.com
|
||||
email_address_tip: "This email address will be displayed in your public profile"
|
||||
phone: Phone
|
||||
phone_placeholder: eg. 98 7654 3210
|
||||
phone_placeholder: eg. 519 885 8888
|
||||
website: Website
|
||||
website_placeholder: eg. www.truffles.com
|
||||
enterprise_fees:
|
||||
@@ -1196,7 +1196,7 @@ en_CA:
|
||||
city: City
|
||||
city_placeholder: eg. Northcote
|
||||
postcode: Postal Code
|
||||
postcode_placeholder: eg. 3070
|
||||
postcode_placeholder: eg. N0B 2L0
|
||||
suburb: City
|
||||
state: Province
|
||||
country: Country
|
||||
@@ -1452,7 +1452,7 @@ en_CA:
|
||||
set_a_password: "You will then be prompted to set a password before you are able to administer the enterprise."
|
||||
mistakenly_sent: "Not sure why you have received this email? Please contact %{owner_email} for more information."
|
||||
producer_mail_greeting: "Dear"
|
||||
producer_mail_text_before: "We now have all the consumer orders for the next food drop."
|
||||
producer_mail_text_before: "We now have all the orders for the next pick-up/delivery."
|
||||
producer_mail_order_text: "Here is a summary of the orders for your products:"
|
||||
producer_mail_delivery_instructions: "Stock pickup/delivery instructions:"
|
||||
producer_mail_signoff: "Thanks and best wishes"
|
||||
@@ -1469,7 +1469,7 @@ en_CA:
|
||||
shopping_producers_of_hub: "%{hub}'s producers:"
|
||||
enterprises_next_closing: "Next order closing"
|
||||
enterprises_ready_for: "Ready for"
|
||||
enterprises_choose: "Choose when you want your order:"
|
||||
enterprises_choose: "Choose from the dropdown:"
|
||||
maps_open: "Open"
|
||||
maps_closed: "Closed"
|
||||
hubs_buy: "Shop for:"
|
||||
@@ -1600,7 +1600,7 @@ en_CA:
|
||||
sell_hubs_detail: "Set up a profile for your food enterprise or organisation on the OFN. At any time you can upgrade your profile to a multi-producer shop."
|
||||
sell_groups_detail: "Set up a tailored directory of enterprises (producers and other food enterprises) for your region or for your organisation."
|
||||
sell_user_guide: "Find out more in our user guide."
|
||||
sell_listing_price: "Listing on the OFN is free. Opening and running a shop on OFN is free up to $500 of monthly sales. If you sell more we will invoice you for 2% of sales to a maximum of $100/month. For more detail on pricing visit the Software Platform section via the About link in the top menu."
|
||||
sell_listing_price: "Listing on the OFN is free. Opening and running a shop on OFN is free up to $500 of monthly sales. If you sell more we will invoice you for 2% of sales to a maximum of $150/month. For more detail on pricing visit the Software Platform section via the About link in the top menu."
|
||||
sell_embed: "We can also embed an OFN shop in your own customised website or build a customised local food network website for your region."
|
||||
sell_ask_services: "Ask us about OFN services."
|
||||
shops_title: Shops
|
||||
@@ -1741,11 +1741,11 @@ en_CA:
|
||||
address1_field_placeholder: "e.g. 123 Cranberry Drive"
|
||||
address1_field_error: "Please enter an address"
|
||||
address2_field: "Address line 2:"
|
||||
suburb_field: "Suburb:"
|
||||
suburb_field_placeholder: "e.g. Northcote"
|
||||
suburb_field_error: "Please enter a suburb"
|
||||
suburb_field: "City/Town"
|
||||
suburb_field_placeholder: "e.g. Kitchener"
|
||||
suburb_field_error: "Please enter a City or Town"
|
||||
postcode_field: "Postal Code"
|
||||
postcode_field_placeholder: "e.g. 3070"
|
||||
postcode_field_placeholder: "e.g. N0B 2L0"
|
||||
postcode_field_error: "Postal Code"
|
||||
state_field: "Province:"
|
||||
state_field_error: "Province required"
|
||||
@@ -1758,7 +1758,7 @@ en_CA:
|
||||
contact_field_placeholder: "Contact Name"
|
||||
contact_field_required: "You need to enter a primary contact."
|
||||
phone_field: "Phone number"
|
||||
phone_field_placeholder: "eg. (03) 1234 5678"
|
||||
phone_field_placeholder: "eg.(519) 885 8888"
|
||||
type:
|
||||
title: "Type"
|
||||
headline: "Last step to add %{enterprise}!"
|
||||
@@ -1782,8 +1782,8 @@ en_CA:
|
||||
enterprise_long_desc_length: "%{num} characters / up to 600 recommended"
|
||||
enterprise_abn: "Business Number"
|
||||
enterprise_abn_placeholder: "Number will show on invoices"
|
||||
enterprise_acn: "Business Number"
|
||||
enterprise_acn_placeholder: "eg. 123 456 789"
|
||||
enterprise_acn: "Additional identifier"
|
||||
enterprise_acn_placeholder: "if entered, will show on invoices"
|
||||
enterprise_tax_required: "You need to make a selection."
|
||||
images:
|
||||
title: "Images"
|
||||
@@ -1887,10 +1887,10 @@ en_CA:
|
||||
admin_enterprise_groups_data_powertip_logo: "This is the logo for the group"
|
||||
admin_enterprise_groups_data_powertip_promo_image: "This image is displayed at the top of the Group profile"
|
||||
admin_enterprise_groups_contact: "Contact"
|
||||
admin_enterprise_groups_contact_phone_placeholder: "eg. 98 7654 3210"
|
||||
admin_enterprise_groups_contact_phone_placeholder: "eg. 519 885 5566"
|
||||
admin_enterprise_groups_contact_address1_placeholder: "eg. 123 High Street"
|
||||
admin_enterprise_groups_contact_city: "Suburb"
|
||||
admin_enterprise_groups_contact_city_placeholder: "eg. Northcote"
|
||||
admin_enterprise_groups_contact_city: "City/Town"
|
||||
admin_enterprise_groups_contact_city_placeholder: "eg. Kitchener"
|
||||
admin_enterprise_groups_contact_zipcode: "Postal Code"
|
||||
admin_enterprise_groups_contact_zipcode_placeholder: "eg. 3070"
|
||||
admin_enterprise_groups_contact_state_id: "Province"
|
||||
@@ -1975,7 +1975,7 @@ en_CA:
|
||||
change_package: "Change Package"
|
||||
spree_admin_single_enterprise_hint: "Hint: To allow people to find you, turn on your visibility under"
|
||||
spree_admin_eg_pickup_from_school: "eg. 'Pick-up from Primary School'"
|
||||
spree_admin_eg_collect_your_order: "eg. 'Please collect your order from 123 Imaginary St, Northcote, 3070'"
|
||||
spree_admin_eg_collect_your_order: "eg. 'Please collect your order from 123 Imaginary St, YourCity'"
|
||||
spree_classification_primary_taxon_error: "Taxon %{taxon} is the primary taxon of %{product} and cannot be deleted"
|
||||
spree_order_availability_error: "Distributor or order cycle cannot supply the products in your cart"
|
||||
spree_order_populator_error: "That distributor or order cycle can't supply all the products in your cart. Please choose another."
|
||||
@@ -2046,7 +2046,7 @@ en_CA:
|
||||
report_header_first_name: First Name
|
||||
report_header_last_name: Last Name
|
||||
report_header_phone: Phone
|
||||
report_header_suburb: Suburb
|
||||
report_header_suburb: City/Town
|
||||
report_header_address: Address
|
||||
report_header_billing_address: Billing Address
|
||||
report_header_relationship: Relationship
|
||||
@@ -2102,7 +2102,7 @@ en_CA:
|
||||
report_header_taxons: Taxons
|
||||
report_header_supplier: Supplier
|
||||
report_header_producer: Producer
|
||||
report_header_producer_suburb: Producer Suburb
|
||||
report_header_producer_suburb: Producer City/Town
|
||||
report_header_unit: Unit
|
||||
report_header_group_buy_unit_quantity: Group Buy Unit Quantity
|
||||
report_header_cost: Cost
|
||||
@@ -2782,6 +2782,7 @@ en_CA:
|
||||
discount_amount: "Discount Amount"
|
||||
email: Email
|
||||
account_updated: "Account updated!"
|
||||
email_updated: "The account will be updated once the new email is confirmed."
|
||||
my_account: "My account"
|
||||
date: "Date"
|
||||
time: "Time"
|
||||
|
||||
@@ -163,7 +163,7 @@ en_GB:
|
||||
home: "OFN"
|
||||
title: Open Food Network
|
||||
welcome_to: 'Welcome to '
|
||||
site_meta_description: "We begin from the ground up. With farmers and growers ready to tell their stories proudly and truly. With distributors ready to connect people with products fairly and honestly. With buyers who believe that better weekly shopping decisions can seriously change the world."
|
||||
site_meta_description: "The Open Food Network software platform allows farmers to sell produce online, at a price that works for them. It has been built specifically for selling food so it can handle tricky measures or stock levels that only food has - a dozen eggs, a bunch of parsley, a whole chicken that varies in weight…"
|
||||
search_by_name: Search by name, town, county or postcode...
|
||||
producers_join: UK producers are now welcome to join Open Food Network UK.
|
||||
charges_sales_tax: Charges VAT?
|
||||
@@ -1302,26 +1302,26 @@ en_GB:
|
||||
cookies_policy_link: "cookies policy"
|
||||
cookies_accept_button: "Accept Cookies"
|
||||
home_shop: Shop Now
|
||||
brandstory_headline: "Re-imagining Local Food"
|
||||
brandstory_intro: "A learning community & tools to support local food systems to thrive"
|
||||
brandstory_part1: "We begin from the ground up. With farmers and growers ready to tell their stories proudly and truly. With distributors ready to connect people with products fairly and honestly. With buyers who believe that better weekly shopping decisions can seriously change the world."
|
||||
brandstory_part2: "Then we need a way to make it real. A way to empower everyone who grows, sells and buys food. A way to tell all the stories, to handle all the logistics. A way to turn transaction into transformation every day."
|
||||
brandstory_part3: "So we build an online marketplace that levels the playing field. It’s transparent, so it creates real relationships. It’s open source, so it’s owned by everyone. It scales to regions and nations, so people start versions across the world."
|
||||
brandstory_part4: "It works everywhere. It changes everything."
|
||||
brandstory_part5_strong: "We call it Open Food Network."
|
||||
brandstory_part6: "We all love food. Now we can love our food system too."
|
||||
brandstory_headline: "Growing Local Food Online"
|
||||
brandstory_intro: "THE online community helping you to build a successful food enterprise"
|
||||
brandstory_part1: "The Open Food Network software platform allows farmers to sell produce online, at a price that works for them. It has been built specifically for selling food so it can handle tricky measures or stock levels that only food has - a dozen eggs, a bunch of parsley, a whole chicken that varies in weight…"
|
||||
brandstory_part2: "Food Producers can create an online shop, collect payments, sell through other shops on the platform and access reduced-rate courier services."
|
||||
brandstory_part3: "Wholesalers can integrate OFN with their existing systems and manage buying groups to supply customers with their produce through our national network of food hubs and shops."
|
||||
brandstory_part4: "Communities can bring together producers in their local area to create virtual farmers’ markets, building a resilient local food economy."
|
||||
brandstory_part5_strong: "And what’s just as important as the software itself are the values which underpin it. "
|
||||
brandstory_part6: "If you sell good food - as a farmer, farmer’s market, food co-op, or food hub- then choose software that aligns with your values to build food systems for people and planet, not profit. By working collectively rather than competitively, we share the costs of developing new software, and we ensure that our project is resilient!"
|
||||
learn_body: "Explore models, stories and resources to support you to develop your fair food business or organisation. Find training, events and other opportunities to learn from peers."
|
||||
learn_cta: "Get Inspired"
|
||||
connect_body: "Search our full directories of producers, hubs and groups to find fair food traders near you. List your business or organisation on the OFN so buyers can find you. Join the community to get advice and solve problems together."
|
||||
connect_cta: "Go Exploring"
|
||||
system_headline: "Shopping - here's how it works."
|
||||
system_step1: "1. Search"
|
||||
system_step1_text: "Search our diverse, independent shops for seasonal local food. Search by neighbourhood and food category, or whether you prefer delivery or pickup."
|
||||
system_step2: "2. Shop"
|
||||
system_step2_text: "Transform your transactions with affordable local food from diverse producers and hubs. Know the stories behind your food and the people who make it!"
|
||||
system_step3: "3. Pick-up / Delivery"
|
||||
system_step3_text: "Hang on for your delivery, or visit your producer or hub for a more personal connection with your food. Food shopping as diverse as nature intended it."
|
||||
cta_headline: "Shopping that makes the world a better place."
|
||||
system_headline: "Selling on OFN - 3 easy steps"
|
||||
system_step1: "1. Create Your Enterprise"
|
||||
system_step1_text: "Set up your enterprise with a name, description, photos, contact details and social media links."
|
||||
system_step2: "2. Add Your Products"
|
||||
system_step2_text: "Add products to your shop - your own and/or from other producers around you. Set images, descriptions, prices, stock levels and flexible weights and measures."
|
||||
system_step3: "3. Plan your Deliveries"
|
||||
system_step3_text: "Set up payment methods. Create multiple pick-up points and delivery details. Create recurring orders and regular distributions."
|
||||
cta_headline: "The sustainable Food Network of the future."
|
||||
cta_label: "I'm Ready"
|
||||
stats_headline: "We're creating a new food system."
|
||||
stats_producers: "food producers"
|
||||
|
||||
@@ -245,6 +245,7 @@ en_US:
|
||||
expired: has expired, please request a new one
|
||||
back_to_payments_list: "Back to Payments List"
|
||||
maestro_or_solo_cards: "Debit cards"
|
||||
backordered: "Backordered"
|
||||
on hand: "On Hand"
|
||||
ship: "Ship"
|
||||
actions:
|
||||
@@ -2629,6 +2630,8 @@ en_US:
|
||||
name_or_sku: "Name or SKU (enter at least first 4 characters of product name)"
|
||||
resend: Resend
|
||||
back_to_orders_list: Back To Orders List
|
||||
return_authorizations: Return Authorizations
|
||||
cannot_create_returns: Cannot create returns as this order has no shipped units.
|
||||
select_stock: "Select stock"
|
||||
location: "Location"
|
||||
count_on_hand: "Count On Hand"
|
||||
@@ -2779,6 +2782,7 @@ en_US:
|
||||
discount_amount: "Discount Amount"
|
||||
email: Email
|
||||
account_updated: "Account updated!"
|
||||
email_updated: "The account will be updated once the new email is confirmed."
|
||||
my_account: "My account"
|
||||
date: "Date"
|
||||
time: "Time"
|
||||
|
||||
@@ -15,7 +15,7 @@ Openfoodnetwork::Application.routes.draw do
|
||||
|
||||
resources :variants, :only => [:index]
|
||||
|
||||
resources :orders, only: [:index] do
|
||||
resources :orders, only: [:index, :show] do
|
||||
get :managed, on: :collection
|
||||
|
||||
resources :shipments, :only => [:create, :update] do
|
||||
|
||||
@@ -90,6 +90,23 @@ Spree::Core::Engine.routes.prepend do
|
||||
end
|
||||
|
||||
# Configuration section
|
||||
resource :general_settings do
|
||||
collection do
|
||||
post :dismiss_alert
|
||||
end
|
||||
end
|
||||
resource :mail_method, :only => [:edit, :update] do
|
||||
post :testmail, :on => :collection
|
||||
end
|
||||
|
||||
resource :image_settings
|
||||
|
||||
resources :zones
|
||||
resources :countries do
|
||||
resources :states
|
||||
end
|
||||
resources :states
|
||||
|
||||
resources :taxonomies do
|
||||
collection do
|
||||
post :update_positions
|
||||
@@ -109,12 +126,6 @@ Spree::Core::Engine.routes.prepend do
|
||||
resources :tax_rates
|
||||
resource :tax_settings
|
||||
resources :tax_categories
|
||||
|
||||
resources :zones
|
||||
resources :countries do
|
||||
resources :states
|
||||
end
|
||||
resources :states
|
||||
end
|
||||
|
||||
resources :orders do
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
class DropOrdersShippingMethodId < ActiveRecord::Migration
|
||||
def up
|
||||
remove_column :spree_orders, :shipping_method_id
|
||||
end
|
||||
|
||||
def down
|
||||
add_column :spree_orders, :shipping_method_id, :integer
|
||||
end
|
||||
end
|
||||
@@ -11,7 +11,7 @@
|
||||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20190918105234) do
|
||||
ActiveRecord::Schema.define(:version => 20190922201034) do
|
||||
|
||||
create_table "adjustment_metadata", :force => true do |t|
|
||||
t.integer "adjustment_id"
|
||||
@@ -563,7 +563,6 @@ ActiveRecord::Schema.define(:version => 20190918105234) do
|
||||
t.integer "bill_address_id"
|
||||
t.integer "ship_address_id"
|
||||
t.decimal "payment_total", :precision => 10, :scale => 2, :default => 0.0
|
||||
t.integer "shipping_method_id"
|
||||
t.string "shipment_state"
|
||||
t.string "payment_state"
|
||||
t.string "email"
|
||||
|
||||
@@ -52,3 +52,4 @@ end
|
||||
require File.join(File.dirname(__FILE__), 'default', 'users')
|
||||
|
||||
DefaultStockLocation.find_or_create
|
||||
DefaultShippingCategory.find_or_create
|
||||
|
||||
@@ -7,6 +7,7 @@ services:
|
||||
environment:
|
||||
POSTGRES_PASSWORD: f00d
|
||||
POSTGRES_USER: ofn
|
||||
POSTGRES_DB: open_food_network_dev
|
||||
volumes:
|
||||
- 'postgres:/var/lib/postgresql/data'
|
||||
web:
|
||||
|
||||
@@ -1,295 +1,55 @@
|
||||
require "open_food_network/reports/line_items"
|
||||
require "open_food_network/orders_and_fulfillments_report/supplier_totals_report"
|
||||
require "open_food_network/orders_and_fulfillments_report/supplier_totals_by_distributor_report"
|
||||
require "open_food_network/orders_and_fulfillments_report/distributor_totals_by_supplier_report"
|
||||
require "open_food_network/orders_and_fulfillments_report/customer_totals_report"
|
||||
require 'open_food_network/orders_and_fulfillments_report/default_report'
|
||||
|
||||
include Spree::ReportsHelper
|
||||
|
||||
module OpenFoodNetwork
|
||||
class OrdersAndFulfillmentsReport
|
||||
attr_reader :params
|
||||
def initialize(permissions, params = {}, render_table = false)
|
||||
@params = params
|
||||
attr_reader :options, :report_type
|
||||
|
||||
delegate :header, :rules, :columns, to: :report
|
||||
|
||||
def initialize(permissions, options = {}, render_table = false)
|
||||
@options = options
|
||||
@report_type = options[:report_type]
|
||||
@permissions = permissions
|
||||
@render_table = render_table
|
||||
end
|
||||
|
||||
def header
|
||||
case params[:report_type]
|
||||
|
||||
when "order_cycle_supplier_totals"
|
||||
[I18n.t(:report_header_producer), I18n.t(:report_header_product), I18n.t(:report_header_variant), I18n.t(:report_header_amount),
|
||||
I18n.t(:report_header_total_units), I18n.t(:report_header_curr_cost_per_unit), I18n.t(:report_header_total_cost),
|
||||
I18n.t(:report_header_status), I18n.t(:report_header_incoming_transport)]
|
||||
when "order_cycle_supplier_totals_by_distributor"
|
||||
[I18n.t(:report_header_producer), I18n.t(:report_header_product), I18n.t(:report_header_variant), I18n.t(:report_header_to_hub),
|
||||
I18n.t(:report_header_amount), I18n.t(:report_header_curr_cost_per_unit), I18n.t(:report_header_total_cost),
|
||||
I18n.t(:report_header_shipping_method)]
|
||||
when "order_cycle_distributor_totals_by_supplier"
|
||||
[I18n.t(:report_header_hub), I18n.t(:report_header_producer), I18n.t(:report_header_product), I18n.t(:report_header_variant),
|
||||
I18n.t(:report_header_amount), I18n.t(:report_header_curr_cost_per_unit), I18n.t(:report_header_total_cost),
|
||||
I18n.t(:report_header_total_shipping_cost), I18n.t(:report_header_shipping_method)]
|
||||
when "order_cycle_customer_totals"
|
||||
[I18n.t(:report_header_hub), I18n.t(:report_header_customer), I18n.t(:report_header_email), I18n.t(:report_header_phone),
|
||||
I18n.t(:report_header_producer), I18n.t(:report_header_product), I18n.t(:report_header_variant), I18n.t(:report_header_amount),
|
||||
I18n.t(:report_header_item_price, currency: currency_symbol),
|
||||
I18n.t(:report_header_item_fees_price, currency: currency_symbol),
|
||||
I18n.t(:report_header_admin_handling_fees, currency: currency_symbol),
|
||||
I18n.t(:report_header_ship_price, currency: currency_symbol),
|
||||
I18n.t(:report_header_pay_fee_price, currency: currency_symbol),
|
||||
I18n.t(:report_header_total_price, currency: currency_symbol),
|
||||
I18n.t(:report_header_paid), I18n.t(:report_header_shipping), I18n.t(:report_header_delivery),
|
||||
I18n.t(:report_header_ship_street), I18n.t(:report_header_ship_street_2), I18n.t(:report_header_ship_city), I18n.t(:report_header_ship_postcode), I18n.t(:report_header_ship_state),
|
||||
I18n.t(:report_header_comments), I18n.t(:report_header_sku),
|
||||
I18n.t(:report_header_order_cycle), I18n.t(:report_header_payment_method), I18n.t(:report_header_customer_code), I18n.t(:report_header_tags),
|
||||
I18n.t(:report_header_billing_street), I18n.t(:report_header_billing_street_2), I18n.t(:report_header_billing_city), I18n.t(:report_header_billing_postcode), I18n.t(:report_header_billing_state),]
|
||||
else
|
||||
DefaultReport.new(self).header
|
||||
end
|
||||
end
|
||||
|
||||
def search
|
||||
Reports::LineItems.search_orders(permissions, params)
|
||||
Reports::LineItems.search_orders(permissions, options)
|
||||
end
|
||||
|
||||
def table_items
|
||||
return [] unless @render_table
|
||||
Reports::LineItems.list(permissions, params)
|
||||
end
|
||||
|
||||
def rules
|
||||
case params[:report_type]
|
||||
when "order_cycle_supplier_totals"
|
||||
[
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.product.supplier },
|
||||
sort_by: proc { |supplier| supplier.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.product },
|
||||
sort_by: proc { |product| product.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.full_name },
|
||||
sort_by: proc { |full_name| full_name }
|
||||
}
|
||||
]
|
||||
when "order_cycle_supplier_totals_by_distributor"
|
||||
[
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.product.supplier },
|
||||
sort_by: proc { |supplier| supplier.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.product },
|
||||
sort_by: proc { |product| product.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.full_name },
|
||||
sort_by: proc { |full_name| full_name },
|
||||
summary_columns: [
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| I18n.t('admin.reports.total') },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |_line_items| "" }
|
||||
]
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.order.distributor },
|
||||
sort_by: proc { |distributor| distributor.name }
|
||||
}
|
||||
]
|
||||
when "order_cycle_distributor_totals_by_supplier"
|
||||
[
|
||||
{
|
||||
group_by: proc { |line_item| line_item.order.distributor },
|
||||
sort_by: proc { |distributor| distributor.name },
|
||||
summary_columns: [
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| I18n.t('admin.reports.total') },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |line_items| line_items.map(&:order).uniq.sum(&:ship_total) },
|
||||
proc { |_line_items| "" }
|
||||
]
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.product.supplier },
|
||||
sort_by: proc { |supplier| supplier.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.product },
|
||||
sort_by: proc { |product| product.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.full_name },
|
||||
sort_by: proc { |full_name| full_name }
|
||||
}
|
||||
]
|
||||
when "order_cycle_customer_totals"
|
||||
[
|
||||
{
|
||||
group_by: proc { |line_item| line_item.order.distributor },
|
||||
sort_by: proc { |distributor| distributor.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.order },
|
||||
sort_by: proc { |order| order.bill_address.full_name_reverse },
|
||||
summary_columns: [
|
||||
proc { |line_items| line_items.first.order.distributor.name },
|
||||
proc { |line_items| line_items.first.order.bill_address.full_name },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| I18n.t('admin.reports.total') },
|
||||
proc { |_line_items| "" },
|
||||
|
||||
proc { |_line_items| "" },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |line_items| line_items.sum(&:amount_with_adjustments) },
|
||||
proc { |line_items| line_items.first.order.admin_and_handling_total },
|
||||
proc { |line_items| line_items.first.order.ship_total },
|
||||
proc { |line_items| line_items.first.order.payment_fee },
|
||||
proc { |line_items| line_items.first.order.total },
|
||||
proc { |line_items| line_items.first.order.paid? ? I18n.t(:yes) : I18n.t(:no) },
|
||||
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
|
||||
proc { |line_items| line_items.first.order.special_instructions },
|
||||
proc { |_line_items| "" },
|
||||
|
||||
proc { |line_items| line_items.first.order.order_cycle.andand.name },
|
||||
proc { |line_items|
|
||||
line_items.first.order.payments.first.andand.payment_method.andand.name
|
||||
},
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" }
|
||||
]
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.product },
|
||||
sort_by: proc { |product| product.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant },
|
||||
sort_by: proc { |variant| variant.full_name }
|
||||
},
|
||||
{
|
||||
group_by: line_item_name,
|
||||
sort_by: proc { |full_name| full_name }
|
||||
}
|
||||
]
|
||||
else
|
||||
DefaultReport.new(self).rules
|
||||
end
|
||||
end
|
||||
|
||||
# Returns a proc for each column displayed in each report type containing
|
||||
# the logic to compute the value for each cell.
|
||||
def columns
|
||||
case params[:report_type]
|
||||
when "order_cycle_supplier_totals"
|
||||
[
|
||||
supplier_name,
|
||||
product_name,
|
||||
line_items_name,
|
||||
proc { |line_items| line_items.sum(&:quantity) },
|
||||
proc { |line_items| total_units(line_items) },
|
||||
proc { |line_items| line_items.first.price },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| I18n.t(:report_header_incoming_transport) }
|
||||
]
|
||||
when "order_cycle_supplier_totals_by_distributor"
|
||||
[
|
||||
supplier_name,
|
||||
proc { |line_items| line_items.first.variant.product.name },
|
||||
proc { |line_items| line_items.first.variant.full_name },
|
||||
proc { |line_items| line_items.first.order.distributor.name },
|
||||
proc { |line_items| line_items.sum(&:quantity) },
|
||||
proc { |line_items| line_items.first.price },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |_line_items| I18n.t(:report_header_shipping_method) }
|
||||
]
|
||||
when "order_cycle_distributor_totals_by_supplier"
|
||||
[proc { |line_items| line_items.first.order.distributor.name },
|
||||
proc { |line_items| line_items.first.variant.product.supplier.name },
|
||||
proc { |line_items| line_items.first.variant.product.name },
|
||||
proc { |line_items| line_items.first.variant.full_name },
|
||||
proc { |line_items| line_items.sum(&:quantity) },
|
||||
proc { |line_items| line_items.first.price },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| I18n.t(:report_header_shipping_method) }]
|
||||
when "order_cycle_customer_totals"
|
||||
rsa = proc { |line_items| line_items.first.order.shipping_method.andand.delivery? }
|
||||
[
|
||||
proc { |line_items| line_items.first.order.distributor.name },
|
||||
proc { |line_items| line_items.first.order.bill_address.firstname + " " + line_items.first.order.bill_address.lastname },
|
||||
proc { |line_items| line_items.first.order.email },
|
||||
proc { |line_items| line_items.first.order.bill_address.phone },
|
||||
proc { |line_items| line_items.first.variant.product.supplier.name },
|
||||
proc { |line_items| line_items.first.variant.product.name },
|
||||
proc { |line_items| line_items.first.variant.full_name },
|
||||
|
||||
proc { |line_items| line_items.sum(&:quantity) },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |line_items| line_items.sum(&:amount_with_adjustments) },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |line_items| line_items.all? { |li| li.order.paid? } ? I18n.t(:yes) : I18n.t(:no) },
|
||||
|
||||
proc { |line_items| line_items.first.order.shipping_method.andand.name },
|
||||
proc { |line_items| rsa.call(line_items) ? I18n.t(:yes) : I18n.t(:no) },
|
||||
|
||||
proc { |line_items| line_items.first.order.ship_address.andand.address1 if rsa.call(line_items) },
|
||||
proc { |line_items| line_items.first.order.ship_address.andand.address2 if rsa.call(line_items) },
|
||||
proc { |line_items| line_items.first.order.ship_address.andand.city if rsa.call(line_items) },
|
||||
proc { |line_items| line_items.first.order.ship_address.andand.zipcode if rsa.call(line_items) },
|
||||
proc { |line_items| line_items.first.order.ship_address.andand.state if rsa.call(line_items) },
|
||||
|
||||
proc { |_line_items| "" },
|
||||
proc { |line_items| line_items.first.variant.sku },
|
||||
|
||||
proc { |line_items| line_items.first.order.order_cycle.andand.name },
|
||||
proc { |line_items| line_items.first.order.payments.first.andand.payment_method.andand.name },
|
||||
proc { |line_items| line_items.first.order.user.andand.customer_of(line_items.first.order.distributor).andand.code },
|
||||
proc { |line_items| line_items.first.order.user.andand.customer_of(line_items.first.order.distributor).andand.tags.andand.join(', ') },
|
||||
|
||||
proc { |line_items| line_items.first.order.bill_address.andand.address1 },
|
||||
proc { |line_items| line_items.first.order.bill_address.andand.address2 },
|
||||
proc { |line_items| line_items.first.order.bill_address.andand.city },
|
||||
proc { |line_items| line_items.first.order.bill_address.andand.zipcode },
|
||||
proc { |line_items| line_items.first.order.bill_address.andand.state }
|
||||
]
|
||||
else
|
||||
DefaultReport.new(self).columns
|
||||
end
|
||||
list_options = options.merge(line_item_includes: report.line_item_includes)
|
||||
Reports::LineItems.list(permissions, list_options)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :permissions
|
||||
|
||||
def report
|
||||
@report ||= report_klass.new(self)
|
||||
end
|
||||
|
||||
def report_klass
|
||||
case report_type
|
||||
when SupplierTotalsReport::REPORT_TYPE then SupplierTotalsReport
|
||||
when SupplierTotalsByDistributorReport::REPORT_TYPE then SupplierTotalsByDistributorReport
|
||||
when DistributorTotalsBySupplierReport::REPORT_TYPE then DistributorTotalsBySupplierReport
|
||||
when CustomerTotalsReport::REPORT_TYPE then CustomerTotalsReport
|
||||
else
|
||||
DefaultReport
|
||||
end
|
||||
end
|
||||
|
||||
def supplier_name
|
||||
proc { |line_items| line_items.first.variant.product.supplier.name }
|
||||
end
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
# rubocop:disable Metrics/ClassLength
|
||||
module OpenFoodNetwork
|
||||
class OrdersAndFulfillmentsReport
|
||||
class CustomerTotalsReport
|
||||
REPORT_TYPE = "order_cycle_customer_totals".freeze
|
||||
|
||||
attr_reader :context
|
||||
|
||||
delegate :line_item_name, to: :context
|
||||
|
||||
def initialize(context)
|
||||
@context = context
|
||||
end
|
||||
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
def header
|
||||
[I18n.t(:report_header_hub), I18n.t(:report_header_customer), I18n.t(:report_header_email),
|
||||
I18n.t(:report_header_phone), I18n.t(:report_header_producer),
|
||||
I18n.t(:report_header_product), I18n.t(:report_header_variant),
|
||||
I18n.t(:report_header_amount),
|
||||
I18n.t(:report_header_item_price, currency: currency_symbol),
|
||||
I18n.t(:report_header_item_fees_price, currency: currency_symbol),
|
||||
I18n.t(:report_header_admin_handling_fees, currency: currency_symbol),
|
||||
I18n.t(:report_header_ship_price, currency: currency_symbol),
|
||||
I18n.t(:report_header_pay_fee_price, currency: currency_symbol),
|
||||
I18n.t(:report_header_total_price, currency: currency_symbol),
|
||||
I18n.t(:report_header_paid), I18n.t(:report_header_shipping),
|
||||
I18n.t(:report_header_delivery), I18n.t(:report_header_ship_street),
|
||||
I18n.t(:report_header_ship_street_2), I18n.t(:report_header_ship_city),
|
||||
I18n.t(:report_header_ship_postcode), I18n.t(:report_header_ship_state),
|
||||
I18n.t(:report_header_comments), I18n.t(:report_header_sku),
|
||||
I18n.t(:report_header_order_cycle), I18n.t(:report_header_payment_method),
|
||||
I18n.t(:report_header_customer_code), I18n.t(:report_header_tags),
|
||||
I18n.t(:report_header_billing_street), I18n.t(:report_header_billing_street_2),
|
||||
I18n.t(:report_header_billing_city), I18n.t(:report_header_billing_postcode),
|
||||
I18n.t(:report_header_billing_state)]
|
||||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
# rubocop:enable Metrics/MethodLength
|
||||
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
def rules
|
||||
[
|
||||
{
|
||||
group_by: proc { |line_item| line_item.order.distributor },
|
||||
sort_by: proc { |distributor| distributor.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.order },
|
||||
sort_by: proc { |order| order.bill_address.full_name_reverse },
|
||||
summary_columns: [
|
||||
proc { |line_items| line_items.first.order.distributor.name },
|
||||
proc { |line_items| line_items.first.order.bill_address.full_name },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| I18n.t('admin.reports.total') },
|
||||
proc { |_line_items| "" },
|
||||
|
||||
proc { |_line_items| "" },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |line_items| line_items.sum(&:amount_with_adjustments) },
|
||||
proc { |line_items| line_items.first.order.admin_and_handling_total },
|
||||
proc { |line_items| line_items.first.order.ship_total },
|
||||
proc { |line_items| line_items.first.order.payment_fee },
|
||||
proc { |line_items| line_items.first.order.total },
|
||||
proc { |line_items| line_items.first.order.paid? ? I18n.t(:yes) : I18n.t(:no) },
|
||||
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
|
||||
proc { |line_items| line_items.first.order.special_instructions },
|
||||
proc { |_line_items| "" },
|
||||
|
||||
proc { |line_items| line_items.first.order.order_cycle.andand.name },
|
||||
proc { |line_items|
|
||||
line_items.first.order.payments.first.andand.payment_method.andand.name
|
||||
},
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" }
|
||||
]
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.product },
|
||||
sort_by: proc { |product| product.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant },
|
||||
sort_by: proc { |variant| variant.full_name }
|
||||
},
|
||||
{
|
||||
group_by: line_item_name,
|
||||
sort_by: proc { |full_name| full_name }
|
||||
}
|
||||
]
|
||||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
# rubocop:enable Metrics/MethodLength
|
||||
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
# rubocop:disable Metrics/CyclomaticComplexity
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
# rubocop:disable Metrics/PerceivedComplexity
|
||||
def columns
|
||||
rsa = proc { |line_items| line_items.first.order.shipping_method.andand.delivery? }
|
||||
[
|
||||
proc { |line_items| line_items.first.order.distributor.name },
|
||||
proc { |line_items|
|
||||
bill_address = line_items.first.order.bill_address
|
||||
bill_address.firstname + " " + bill_address.lastname
|
||||
},
|
||||
proc { |line_items| line_items.first.order.email },
|
||||
proc { |line_items| line_items.first.order.bill_address.phone },
|
||||
proc { |line_items| line_items.first.variant.product.supplier.name },
|
||||
proc { |line_items| line_items.first.variant.product.name },
|
||||
proc { |line_items| line_items.first.variant.full_name },
|
||||
|
||||
proc { |line_items| line_items.sum(&:quantity) },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |line_items| line_items.sum(&:amount_with_adjustments) },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |line_items|
|
||||
line_items.all? { |li| li.order.paid? } ? I18n.t(:yes) : I18n.t(:no)
|
||||
},
|
||||
|
||||
proc { |line_items| line_items.first.order.shipping_method.andand.name },
|
||||
proc { |line_items| rsa.call(line_items) ? I18n.t(:yes) : I18n.t(:no) },
|
||||
|
||||
proc { |line_items|
|
||||
line_items.first.order.ship_address.andand.address1 if rsa.call(line_items)
|
||||
},
|
||||
proc { |line_items|
|
||||
line_items.first.order.ship_address.andand.address2 if rsa.call(line_items)
|
||||
},
|
||||
proc { |line_items|
|
||||
line_items.first.order.ship_address.andand.city if rsa.call(line_items)
|
||||
},
|
||||
proc { |line_items|
|
||||
line_items.first.order.ship_address.andand.zipcode if rsa.call(line_items)
|
||||
},
|
||||
proc { |line_items|
|
||||
line_items.first.order.ship_address.andand.state if rsa.call(line_items)
|
||||
},
|
||||
|
||||
proc { |_line_items| "" },
|
||||
proc { |line_items| line_items.first.variant.sku },
|
||||
|
||||
proc { |line_items| line_items.first.order.order_cycle.andand.name },
|
||||
proc { |line_items|
|
||||
payment = line_items.first.order.payments.first
|
||||
payment.andand.payment_method.andand.name
|
||||
},
|
||||
proc { |line_items|
|
||||
distributor = line_items.first.order.distributor
|
||||
user = line_items.first.order.user
|
||||
user.andand.customer_of(distributor).andand.code
|
||||
},
|
||||
proc { |line_items|
|
||||
distributor = line_items.first.order.distributor
|
||||
user = line_items.first.order.user
|
||||
user.andand.customer_of(distributor).andand.tags.andand.join(', ')
|
||||
},
|
||||
|
||||
proc { |line_items| line_items.first.order.bill_address.andand.address1 },
|
||||
proc { |line_items| line_items.first.order.bill_address.andand.address2 },
|
||||
proc { |line_items| line_items.first.order.bill_address.andand.city },
|
||||
proc { |line_items| line_items.first.order.bill_address.andand.zipcode },
|
||||
proc { |line_items| line_items.first.order.bill_address.andand.state }
|
||||
]
|
||||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
# rubocop:enable Metrics/CyclomaticComplexity
|
||||
# rubocop:enable Metrics/MethodLength
|
||||
# rubocop:enable Metrics/PerceivedComplexity
|
||||
|
||||
def line_item_includes
|
||||
[{ variant: :product, order: [:bill_address, :shipments] }]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
# rubocop:enable Metrics/ClassLength
|
||||
@@ -54,6 +54,10 @@ module OpenFoodNetwork
|
||||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
|
||||
def line_item_includes
|
||||
[]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :context
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
module OpenFoodNetwork
|
||||
class OrdersAndFulfillmentsReport
|
||||
class DistributorTotalsBySupplierReport
|
||||
REPORT_TYPE = "order_cycle_distributor_totals_by_supplier".freeze
|
||||
|
||||
attr_reader :context
|
||||
|
||||
def initialize(context)
|
||||
@context = context
|
||||
end
|
||||
|
||||
def header
|
||||
[I18n.t(:report_header_hub), I18n.t(:report_header_producer),
|
||||
I18n.t(:report_header_product), I18n.t(:report_header_variant),
|
||||
I18n.t(:report_header_amount), I18n.t(:report_header_curr_cost_per_unit),
|
||||
I18n.t(:report_header_total_cost), I18n.t(:report_header_total_shipping_cost),
|
||||
I18n.t(:report_header_shipping_method)]
|
||||
end
|
||||
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
def rules
|
||||
[
|
||||
{
|
||||
group_by: proc { |line_item| line_item.order.distributor },
|
||||
sort_by: proc { |distributor| distributor.name },
|
||||
summary_columns: [
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| I18n.t('admin.reports.total') },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |line_items| line_items.map(&:order).uniq.sum(&:ship_total) },
|
||||
proc { |_line_items| "" }
|
||||
]
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.product.supplier },
|
||||
sort_by: proc { |supplier| supplier.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.product },
|
||||
sort_by: proc { |product| product.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.full_name },
|
||||
sort_by: proc { |full_name| full_name }
|
||||
}
|
||||
]
|
||||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
# rubocop:enable Metrics/MethodLength
|
||||
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
def columns
|
||||
[proc { |line_items| line_items.first.order.distributor.name },
|
||||
proc { |line_items| line_items.first.variant.product.supplier.name },
|
||||
proc { |line_items| line_items.first.variant.product.name },
|
||||
proc { |line_items| line_items.first.variant.full_name },
|
||||
proc { |line_items| line_items.sum(&:quantity) },
|
||||
proc { |line_items| line_items.first.price },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| I18n.t(:report_header_shipping_method) }]
|
||||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
|
||||
def line_item_includes
|
||||
[:order, { variant: :product }]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,76 @@
|
||||
module OpenFoodNetwork
|
||||
class OrdersAndFulfillmentsReport
|
||||
class SupplierTotalsByDistributorReport
|
||||
REPORT_TYPE = "order_cycle_supplier_totals_by_distributor".freeze
|
||||
|
||||
attr_reader :context
|
||||
|
||||
delegate :supplier_name, to: :context
|
||||
|
||||
def initialize(context)
|
||||
@context = context
|
||||
end
|
||||
|
||||
def header
|
||||
[I18n.t(:report_header_producer), I18n.t(:report_header_product),
|
||||
I18n.t(:report_header_variant), I18n.t(:report_header_to_hub),
|
||||
I18n.t(:report_header_amount), I18n.t(:report_header_curr_cost_per_unit),
|
||||
I18n.t(:report_header_total_cost), I18n.t(:report_header_shipping_method)]
|
||||
end
|
||||
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
def rules
|
||||
[
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.product.supplier },
|
||||
sort_by: proc { |supplier| supplier.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.product },
|
||||
sort_by: proc { |product| product.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.full_name },
|
||||
sort_by: proc { |full_name| full_name },
|
||||
summary_columns: [
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| I18n.t('admin.reports.total') },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| "" },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |_line_items| "" }
|
||||
]
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.order.distributor },
|
||||
sort_by: proc { |distributor| distributor.name }
|
||||
}
|
||||
]
|
||||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
# rubocop:enable Metrics/MethodLength
|
||||
|
||||
# rubocop:disable Metrics/AbcSize
|
||||
def columns
|
||||
[
|
||||
supplier_name,
|
||||
proc { |line_items| line_items.first.variant.product.name },
|
||||
proc { |line_items| line_items.first.variant.full_name },
|
||||
proc { |line_items| line_items.first.order.distributor.name },
|
||||
proc { |line_items| line_items.sum(&:quantity) },
|
||||
proc { |line_items| line_items.first.price },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |_line_items| I18n.t(:report_header_shipping_method) }
|
||||
]
|
||||
end
|
||||
# rubocop:enable Metrics/AbcSize
|
||||
|
||||
def line_item_includes
|
||||
[:order, { variant: :product }]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,62 @@
|
||||
module OpenFoodNetwork
|
||||
class OrdersAndFulfillmentsReport
|
||||
class SupplierTotalsReport
|
||||
REPORT_TYPE = "order_cycle_supplier_totals".freeze
|
||||
|
||||
attr_reader :context
|
||||
|
||||
delegate :supplier_name, :product_name, :line_items_name, :total_units, to: :context
|
||||
|
||||
def initialize(context)
|
||||
@context = context
|
||||
end
|
||||
|
||||
def header
|
||||
[I18n.t(:report_header_producer), I18n.t(:report_header_product),
|
||||
I18n.t(:report_header_variant), I18n.t(:report_header_amount),
|
||||
I18n.t(:report_header_total_units), I18n.t(:report_header_curr_cost_per_unit),
|
||||
I18n.t(:report_header_total_cost), I18n.t(:report_header_status),
|
||||
I18n.t(:report_header_incoming_transport)]
|
||||
end
|
||||
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
def rules
|
||||
[
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.product.supplier },
|
||||
sort_by: proc { |supplier| supplier.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.product },
|
||||
sort_by: proc { |product| product.name }
|
||||
},
|
||||
{
|
||||
group_by: proc { |line_item| line_item.variant.full_name },
|
||||
sort_by: proc { |full_name| full_name }
|
||||
}
|
||||
]
|
||||
end
|
||||
# rubocop:enable Metrics/MethodLength
|
||||
|
||||
# rubocop:disable Metrics/MethodLength
|
||||
def columns
|
||||
[
|
||||
supplier_name,
|
||||
product_name,
|
||||
line_items_name,
|
||||
proc { |line_items| line_items.sum(&:quantity) },
|
||||
proc { |line_items| total_units(line_items) },
|
||||
proc { |line_items| line_items.first.price },
|
||||
proc { |line_items| line_items.sum(&:amount) },
|
||||
proc { |_line_items| "" },
|
||||
proc { |_line_items| I18n.t(:report_header_incoming_transport) }
|
||||
]
|
||||
end
|
||||
# rubocop:enable Metrics/MethodLength
|
||||
|
||||
def line_item_includes
|
||||
[{ variant: { product: :supplier } }]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -65,7 +65,11 @@ module OpenFoodNetwork
|
||||
def filter_to_order_cycle(variants)
|
||||
if params[:order_cycle_id].to_i > 0
|
||||
order_cycle = OrderCycle.find params[:order_cycle_id]
|
||||
variants.where(id: order_cycle.variants)
|
||||
variant_ids = Exchange.in_order_cycle(order_cycle).
|
||||
joins("INNER JOIN exchange_variants ON exchanges.id = exchange_variants.exchange_id").
|
||||
select("DISTINCT exchange_variants.variant_id")
|
||||
|
||||
variants.where("spree_variants.id IN (#{variant_ids.to_sql})")
|
||||
else
|
||||
variants
|
||||
end
|
||||
|
||||
@@ -12,6 +12,10 @@ module OpenFoodNetwork
|
||||
line_items = permissions.visible_line_items.merge(Spree::LineItem.where(order_id: orders))
|
||||
line_items = line_items.supplied_by_any(params[:supplier_id_in]) if params[:supplier_id_in].present?
|
||||
|
||||
if params[:line_item_includes].present?
|
||||
line_items = line_items.includes(*params[:line_item_includes])
|
||||
end
|
||||
|
||||
hidden_line_items = line_items_with_hidden_details(permissions, line_items)
|
||||
|
||||
line_items.select{ |li|
|
||||
|
||||
@@ -72,7 +72,7 @@ class ProductFactory
|
||||
variant_unit: "weight",
|
||||
variant_unit_scale: 1,
|
||||
unit_value: 1,
|
||||
shipping_category: Spree::ShippingCategory.find_or_create_by_name('Default')
|
||||
shipping_category: DefaultShippingCategory.find_or_create
|
||||
)
|
||||
product = Spree::Product.create_with(params).find_or_create_by_name!(params[:name])
|
||||
product.variants.first.update_attribute :on_demand, true
|
||||
|
||||
@@ -5,13 +5,17 @@ module Api
|
||||
include AuthenticationWorkflow
|
||||
render_views
|
||||
|
||||
let!(:regular_user) { create(:user) }
|
||||
let!(:admin_user) { create(:admin_user) }
|
||||
|
||||
let!(:distributor) { create(:distributor_enterprise) }
|
||||
let!(:coordinator) { create(:distributor_enterprise) }
|
||||
let!(:order_cycle) { create(:simple_order_cycle, coordinator: coordinator) }
|
||||
|
||||
describe '#index' do
|
||||
let!(:distributor) { create(:distributor_enterprise) }
|
||||
let!(:distributor2) { create(:distributor_enterprise) }
|
||||
let!(:supplier) { create(:supplier_enterprise) }
|
||||
let!(:coordinator) { create(:distributor_enterprise) }
|
||||
let!(:coordinator2) { create(:distributor_enterprise) }
|
||||
let!(:order_cycle) { create(:simple_order_cycle, coordinator: coordinator) }
|
||||
let!(:supplier) { create(:supplier_enterprise) }
|
||||
let!(:order_cycle2) { create(:simple_order_cycle, coordinator: coordinator2) }
|
||||
let!(:order1) do
|
||||
create(:order, order_cycle: order_cycle, state: 'complete', completed_at: Time.zone.now,
|
||||
@@ -45,8 +49,6 @@ module Api
|
||||
create(:line_item_with_shipment, order: order3,
|
||||
product: create(:product, supplier: supplier))
|
||||
end
|
||||
let!(:regular_user) { create(:user) }
|
||||
let!(:admin_user) { create(:admin_user) }
|
||||
|
||||
context 'as a regular user' do
|
||||
before do
|
||||
@@ -156,6 +158,110 @@ module Api
|
||||
end
|
||||
end
|
||||
|
||||
describe "#show" do
|
||||
let!(:order) { create(:completed_order_with_totals, order_cycle: order_cycle, distributor: distributor ) }
|
||||
|
||||
context "Resource not found" do
|
||||
before { allow(controller).to receive(:spree_current_user) { admin_user } }
|
||||
|
||||
it "when no order number is given" do
|
||||
get :show, id: nil
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
|
||||
it "when order number given is not in the systen" do
|
||||
get :show, id: "X1321313232"
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
end
|
||||
|
||||
context "access" do
|
||||
it "returns unauthorized, as a regular user" do
|
||||
allow(controller).to receive(:spree_current_user) { regular_user }
|
||||
get :show, id: order.number
|
||||
assert_unauthorized!
|
||||
end
|
||||
|
||||
it "returns the order, as an admin user" do
|
||||
allow(controller).to receive(:spree_current_user) { admin_user }
|
||||
get :show, id: order.number
|
||||
expect_order
|
||||
end
|
||||
|
||||
it "returns the order, as the order distributor owner" do
|
||||
allow(controller).to receive(:spree_current_user) { order.distributor.owner }
|
||||
get :show, id: order.number
|
||||
expect_order
|
||||
end
|
||||
|
||||
it "returns unauthorized, as the order product's supplier owner" do
|
||||
allow(controller).to receive(:spree_current_user) { order.line_items.first.variant.product.supplier.owner }
|
||||
get :show, id: order.number
|
||||
assert_unauthorized!
|
||||
end
|
||||
|
||||
it "returns the order, as the Order Cycle coorinator owner" do
|
||||
allow(controller).to receive(:spree_current_user) { order.order_cycle.coordinator.owner }
|
||||
get :show, id: order.number
|
||||
expect_order
|
||||
end
|
||||
end
|
||||
|
||||
context "as distributor owner" do
|
||||
let!(:order) { create(:completed_order_with_fees, order_cycle: order_cycle, distributor: distributor ) }
|
||||
|
||||
before { allow(controller).to receive(:spree_current_user) { order.distributor.owner } }
|
||||
|
||||
it "can view an order not in a standard state" do
|
||||
order.update_attributes(completed_at: nil, state: 'shipped')
|
||||
get :show, id: order.number
|
||||
expect_order
|
||||
end
|
||||
|
||||
it "can view an order with weight calculator (this validates case where options[current_order] is nil on the shipping method serializer)" do
|
||||
order.shipping_method.update_attribute(:calculator, create(:weight_calculator, calculable: order))
|
||||
allow(controller).to receive(:current_order).and_return order
|
||||
get :show, id: order.number
|
||||
expect_order
|
||||
end
|
||||
|
||||
it "returns an order with all required fields" do
|
||||
get :show, id: order.number
|
||||
|
||||
expect_order
|
||||
expect(json_response.symbolize_keys.keys).to include(*order_detailed_attributes)
|
||||
|
||||
expect(json_response[:bill_address]).to include(
|
||||
'address1' => order.bill_address.address1,
|
||||
'lastname' => order.bill_address.lastname
|
||||
)
|
||||
expect(json_response[:ship_address]).to include(
|
||||
'address1' => order.ship_address.address1,
|
||||
'lastname' => order.ship_address.lastname
|
||||
)
|
||||
expect(json_response[:shipping_method][:name]).to eq order.shipping_method.name
|
||||
|
||||
expect(json_response[:adjustments].first).to include(
|
||||
'label' => "Transaction fee",
|
||||
'amount' => order.adjustments.payment_fee.first.amount.to_s
|
||||
)
|
||||
expect(json_response[:adjustments].second).to include(
|
||||
'label' => "Shipping",
|
||||
'amount' => order.adjustments.shipping.first.amount.to_s
|
||||
)
|
||||
|
||||
expect(json_response[:payments].first[:amount]).to eq order.payments.first.amount.to_s
|
||||
expect(json_response[:line_items].size).to eq order.line_items.size
|
||||
expect(json_response[:line_items].first[:variant][:product_name]). to eq order.line_items.first.variant.product.name
|
||||
end
|
||||
end
|
||||
|
||||
def expect_order
|
||||
expect(response.status).to eq 200
|
||||
expect(json_response[:number]).to eq order.number
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def serialized_orders(orders)
|
||||
@@ -181,5 +287,12 @@ module Api
|
||||
:distributor_name, :special_instructions, :payment_capture_path
|
||||
]
|
||||
end
|
||||
|
||||
def order_detailed_attributes
|
||||
[
|
||||
:number, :item_total, :total, :state, :adjustment_total, :payment_total,
|
||||
:completed_at, :shipment_state, :payment_state, :email, :special_instructions
|
||||
]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Spree::Admin::ImageSettingsController do
|
||||
include AuthenticationWorkflow
|
||||
|
||||
before { login_as_admin }
|
||||
|
||||
context "updating image settings" do
|
||||
it "should be able to update paperclip settings" do
|
||||
spree_put :update, preferences: { "attachment_path" => "foo/bar",
|
||||
"attachment_default_url" => "baz/bar" }
|
||||
|
||||
expect(Spree::Config[:attachment_path]).to eq("foo/bar")
|
||||
expect(Spree::Config[:attachment_default_url]).to eq("baz/bar")
|
||||
end
|
||||
|
||||
context "paperclip styles" do
|
||||
it "should be able to update the paperclip styles" do
|
||||
spree_put :update, "attachment_styles" => { "thumb" => "25x25>" }
|
||||
updated_styles = ActiveSupport::JSON.decode(Spree::Config[:attachment_styles])
|
||||
expect(updated_styles["thumb"]).to eq("25x25>")
|
||||
end
|
||||
|
||||
it "should be able to add a new style" do
|
||||
spree_put :update, "attachment_styles" => {},
|
||||
"new_attachment_styles" => { "1" => { "name" => "jumbo",
|
||||
"value" => "2000x2000>" } }
|
||||
styles = ActiveSupport::JSON.decode(Spree::Config[:attachment_styles])
|
||||
expect(styles["jumbo"]).to eq("2000x2000>")
|
||||
end
|
||||
end
|
||||
|
||||
context "amazon s3" do
|
||||
after(:all) do
|
||||
Spree::Image.attachment_definitions[:attachment].delete :storage
|
||||
end
|
||||
|
||||
it "should be able to update s3 settings" do
|
||||
spree_put :update, preferences:
|
||||
{
|
||||
"use_s3" => "1",
|
||||
"s3_access_key" => "a_valid_key",
|
||||
"s3_secret" => "a_secret",
|
||||
"s3_bucket" => "some_bucket"
|
||||
}
|
||||
expect(Spree::Config[:use_s3]).to be_truthy
|
||||
expect(Spree::Config[:s3_access_key]).to eq("a_valid_key")
|
||||
expect(Spree::Config[:s3_secret]).to eq("a_secret")
|
||||
expect(Spree::Config[:s3_bucket]).to eq("some_bucket")
|
||||
end
|
||||
|
||||
context "headers" do
|
||||
before(:each) { Spree::Config[:use_s3] = true }
|
||||
|
||||
it "should be able to update the s3 headers" do
|
||||
spree_put :update, "preferences" => { "use_s3" => "1" },
|
||||
"s3_headers" => { "Cache-Control" => "max-age=1111" }
|
||||
headers = ActiveSupport::JSON.decode(Spree::Config[:s3_headers])
|
||||
expect(headers["Cache-Control"]).to eq("max-age=1111")
|
||||
end
|
||||
|
||||
it "should be able to add a new header" do
|
||||
spree_put :update, "s3_headers" => {},
|
||||
"new_s3_headers" => { "1" => { "name" => "Charset",
|
||||
"value" => "utf-8" } }
|
||||
headers = ActiveSupport::JSON.decode(Spree::Config[:s3_headers])
|
||||
expect(headers["Charset"]).to eq("utf-8")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
30
spec/controllers/spree/admin/mail_methods_controller_spec.rb
Normal file
30
spec/controllers/spree/admin/mail_methods_controller_spec.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Spree::Admin::MailMethodsController do
|
||||
include AuthenticationWorkflow
|
||||
|
||||
before { login_as_admin }
|
||||
|
||||
context "#update" do
|
||||
it "should reinitialize the mail settings" do
|
||||
expect(Spree::Core::MailSettings).to receive(:init)
|
||||
spree_put :update, enable_mail_delivery: "1", mails_from: "spree@example.com"
|
||||
end
|
||||
end
|
||||
|
||||
it "can trigger testmail" do
|
||||
request.env["HTTP_REFERER"] = "/"
|
||||
user = double('User', email: 'user@spree.com',
|
||||
spree_api_key: 'fake',
|
||||
id: nil,
|
||||
owned_groups: nil)
|
||||
allow(user).to receive_messages(enterprises: [create(:enterprise)], has_spree_role?: true)
|
||||
allow(controller).to receive_messages(try_spree_current_user: user)
|
||||
Spree::Config[:enable_mail_delivery] = "1"
|
||||
ActionMailer::Base.perform_deliveries = true
|
||||
|
||||
expect {
|
||||
spree_post :testmail
|
||||
}.to change { ActionMailer::Base.deliveries.size }.by(1)
|
||||
end
|
||||
end
|
||||
@@ -194,19 +194,6 @@ describe Spree::Admin::ProductsController, type: :controller do
|
||||
end
|
||||
end
|
||||
|
||||
describe "product variant unit is items" do
|
||||
it "clears unit description of all variants of the product" do
|
||||
product.variants.first.update_attribute :unit_description, "grams"
|
||||
spree_put :update,
|
||||
id: product,
|
||||
product: {
|
||||
variant_unit: "items",
|
||||
variant_unit_name: "bag"
|
||||
}
|
||||
expect(product.reload.variants.first.unit_description).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
describe "product properties" do
|
||||
context "as an enterprise user" do
|
||||
let!(:property) { create(:property, name: "A nice name") }
|
||||
|
||||
@@ -194,4 +194,9 @@ FactoryBot.modify do
|
||||
# sets the default value for variant.on_demand
|
||||
backorderable_default false
|
||||
end
|
||||
|
||||
factory :shipping_category, class: Spree::ShippingCategory do
|
||||
initialize_with { DefaultShippingCategory.find_or_create }
|
||||
transient { name 'Default' }
|
||||
end
|
||||
end
|
||||
|
||||
38
spec/features/admin/configuration/general_settings_spec.rb
Normal file
38
spec/features/admin/configuration/general_settings_spec.rb
Normal file
@@ -0,0 +1,38 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "General Settings" do
|
||||
include AuthenticationWorkflow
|
||||
|
||||
before(:each) do
|
||||
quick_login_as_admin
|
||||
visit spree.admin_path
|
||||
click_link "Configuration"
|
||||
click_link "General Settings"
|
||||
end
|
||||
|
||||
context "visiting general settings (admin)" do
|
||||
it "should have the right content" do
|
||||
expect(page).to have_content("General Settings")
|
||||
expect(find("#site_name").value).to eq("Spree Demo Site")
|
||||
expect(find("#site_url").value).to eq("demo.spreecommerce.com")
|
||||
end
|
||||
end
|
||||
|
||||
context "editing general settings (admin)" do
|
||||
it "should be able to update the site name" do
|
||||
fill_in "site_name", with: "Spree Demo Site99"
|
||||
click_button "Update"
|
||||
|
||||
assert_successful_update_message(:general_settings)
|
||||
|
||||
expect(find("#site_name").value).to eq("Spree Demo Site99")
|
||||
end
|
||||
|
||||
def assert_successful_update_message(resource)
|
||||
flash = Spree.t(:successfully_updated, resource: Spree.t(resource))
|
||||
within("[class='flash success']") do
|
||||
expect(page).to have_content(flash)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
40
spec/features/admin/configuration/image_settings_spec.rb
Normal file
40
spec/features/admin/configuration/image_settings_spec.rb
Normal file
@@ -0,0 +1,40 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "image settings" do
|
||||
include AuthenticationWorkflow
|
||||
|
||||
before do
|
||||
quick_login_as_admin
|
||||
visit spree.admin_path
|
||||
click_link "Configuration"
|
||||
click_link "Image Settings"
|
||||
end
|
||||
|
||||
# Regression test for #2344
|
||||
it "can update attachment_url" do
|
||||
fill_in "Attachments URL", with: "foobar"
|
||||
fill_in "Attachments Default URL", with: "barfoo"
|
||||
fill_in "Attachments Path", with: "spec/dummy/tmp/bfaoro"
|
||||
click_button "Update"
|
||||
|
||||
expect(Spree::Config[:attachment_url]).to eq("foobar")
|
||||
expect(Spree::Config[:attachment_default_url]).to eq("barfoo")
|
||||
expect(Spree::Config[:attachment_path]).to eq("spec/dummy/tmp/bfaoro")
|
||||
end
|
||||
|
||||
# Regression test for #3069
|
||||
context "updates style configs and uploads products" do
|
||||
let!(:product) { create(:product) }
|
||||
let(:file_path) { Rails.root + "spec/support/fixtures/thinking-cat.jpg" }
|
||||
|
||||
it "still uploads image gracefully" do
|
||||
click_button "Update"
|
||||
|
||||
visit spree.new_admin_product_image_path(product)
|
||||
attach_file('image_attachment', file_path)
|
||||
expect {
|
||||
click_on "Update"
|
||||
}.to_not raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
32
spec/features/admin/configuration/mail_methods_spec.rb
Normal file
32
spec/features/admin/configuration/mail_methods_spec.rb
Normal file
@@ -0,0 +1,32 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "Mail Methods" do
|
||||
include AuthenticationWorkflow
|
||||
|
||||
before(:each) do
|
||||
quick_login_as_admin
|
||||
visit spree.admin_path
|
||||
click_link "Configuration"
|
||||
end
|
||||
|
||||
context "edit" do
|
||||
before(:each) do
|
||||
click_link "Mail Method Settings"
|
||||
end
|
||||
|
||||
it "should be able to edit mail method settings" do
|
||||
fill_in "mail_bcc", with: "spree@example.com99"
|
||||
click_button "Update"
|
||||
expect(page).to have_content("successfully updated!")
|
||||
end
|
||||
|
||||
# Regression test for #2094
|
||||
it "does not clear password if not provided" do
|
||||
Spree::Config[:smtp_password] = "haxme"
|
||||
click_button "Update"
|
||||
expect(page).to have_content("successfully updated!")
|
||||
|
||||
expect(Spree::Config[:smtp_password]).not_to be_blank
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -9,7 +9,7 @@ feature '
|
||||
|
||||
let!(:taxon) { create(:taxon) }
|
||||
let!(:stock_location) { create(:stock_location, backorderable_default: false) }
|
||||
let!(:shipping_category) { create(:shipping_category, name: 'Test Shipping Category') }
|
||||
let!(:shipping_category) { DefaultShippingCategory.find_or_create }
|
||||
|
||||
background do
|
||||
@supplier = create(:supplier_enterprise, name: 'New supplier')
|
||||
@@ -32,6 +32,8 @@ feature '
|
||||
click_link 'Products'
|
||||
click_link 'New Product'
|
||||
|
||||
expect(find_field('product_shipping_category_id').text).to eq(shipping_category.name)
|
||||
|
||||
select 'New supplier', from: 'product_supplier_id'
|
||||
fill_in 'product_name', with: 'A new product !!!'
|
||||
select "Weight (kg)", from: 'product_variant_unit_with_scale'
|
||||
@@ -40,7 +42,6 @@ feature '
|
||||
fill_in 'product_price', with: '19.99'
|
||||
fill_in 'product_on_hand', with: 5
|
||||
select 'Test Tax Category', from: 'product_tax_category_id'
|
||||
select 'Test Shipping Category', from: 'product_shipping_category_id'
|
||||
page.find("div[id^='taTextElement']").native.send_keys('A description...')
|
||||
|
||||
click_button 'Create'
|
||||
@@ -80,7 +81,6 @@ feature '
|
||||
fill_in 'product_on_hand', with: 0
|
||||
check 'product_on_demand'
|
||||
select 'Test Tax Category', from: 'product_tax_category_id'
|
||||
select 'Test Shipping Category', from: 'product_shipping_category_id'
|
||||
page.find("div[id^='taTextElement']").native.send_keys('In demand, and on_demand! The hottest cakes in town.')
|
||||
|
||||
click_button 'Create'
|
||||
@@ -122,7 +122,6 @@ feature '
|
||||
select 'Weight (g)', from: 'product_variant_unit_with_scale'
|
||||
fill_in 'product_unit_value_with_description', with: '500'
|
||||
select taxon.name, from: "product_primary_taxon_id"
|
||||
select 'Test Shipping Category', from: 'product_shipping_category_id'
|
||||
select 'None', from: "product_tax_category_id"
|
||||
|
||||
# Should only have suppliers listed which the user can manage
|
||||
|
||||
@@ -75,6 +75,7 @@ feature 'shipping methods' do
|
||||
let(:sm1) { create(:shipping_method, name: 'One', distributors: [distributor1]) }
|
||||
let(:sm2) { create(:shipping_method, name: 'Two', distributors: [distributor1, distributor2]) }
|
||||
let(:sm3) { create(:shipping_method, name: 'Three', distributors: [distributor3]) }
|
||||
let(:shipping_category) { create(:shipping_category) }
|
||||
|
||||
before(:each) do
|
||||
enterprise_user.enterprise_roles.build(enterprise: distributor1).save
|
||||
@@ -97,10 +98,12 @@ feature 'shipping methods' do
|
||||
expect(page).to have_css 'div#shipping_method_zones_field'
|
||||
expect(page).to have_field 'shipping_method_require_ship_address_true', checked: true
|
||||
|
||||
# Auto-check default shipping category
|
||||
expect(page).to have_field shipping_category.name, checked: true
|
||||
|
||||
fill_in 'shipping_method_name', with: 'Teleport'
|
||||
|
||||
check "shipping_method_distributor_ids_#{distributor1.id}"
|
||||
check "shipping_method_shipping_categories_"
|
||||
find(:css, "tags-input .tags input").set "local\n"
|
||||
within(".tags .tag-list") do
|
||||
expect(page).to have_css '.tag-item', text: "local"
|
||||
|
||||
@@ -9,11 +9,11 @@ feature '
|
||||
|
||||
scenario "creating a new variant" do
|
||||
# Given a product with a unit-related option type
|
||||
p = create(:simple_product, variant_unit: "weight", variant_unit_scale: "1")
|
||||
product = create(:simple_product, variant_unit: "weight", variant_unit_scale: "1")
|
||||
|
||||
# When I create a variant on the product
|
||||
login_to_admin_section
|
||||
visit spree.admin_product_variants_path p
|
||||
visit spree.admin_product_variants_path product
|
||||
click_link 'New Variant'
|
||||
|
||||
fill_in 'unit_value_human', with: '1'
|
||||
@@ -21,40 +21,58 @@ feature '
|
||||
click_button 'Create'
|
||||
|
||||
# Then the variant should have been created
|
||||
expect(page).to have_content "Variant \"#{p.name}\" has been successfully created!"
|
||||
expect(page).to have_content "Variant \"#{product.name}\" has been successfully created!"
|
||||
end
|
||||
|
||||
scenario "editing unit value and description for a variant", js: true do
|
||||
# Given a product with unit-related option types, with a variant
|
||||
p = create(:simple_product, variant_unit: "weight", variant_unit_scale: "1")
|
||||
v = p.variants.first
|
||||
v.update_attributes( unit_value: 1, unit_description: 'foo' )
|
||||
describe "editing unit value and description for a variant", js: true do
|
||||
scenario "when variant_unit is weight" do
|
||||
# Given a product with unit-related option types, with a variant
|
||||
product = create(:simple_product, variant_unit: "weight", variant_unit_scale: "1")
|
||||
variant = product.variants.first
|
||||
variant.update_attributes( unit_value: 1, unit_description: 'foo' )
|
||||
|
||||
# And the product has option types for the unit-related and non-unit-related option values
|
||||
p.option_types << v.option_values.first.option_type
|
||||
# And the product has option types for the unit-related and non-unit-related option values
|
||||
product.option_types << variant.option_values.first.option_type
|
||||
|
||||
# When I view the variant
|
||||
login_to_admin_section
|
||||
visit spree.admin_product_variants_path p
|
||||
page.find('table.index .icon-edit').click
|
||||
# When I view the variant
|
||||
login_to_admin_section
|
||||
visit spree.admin_product_variants_path product
|
||||
page.find('table.index .icon-edit').click
|
||||
|
||||
# Then I should not see a traditional option value field for the unit-related option value
|
||||
expect(page).to have_no_selector "div[data-hook='presentation'] input"
|
||||
# Then I should not see a traditional option value field for the unit-related option value
|
||||
expect(page).to have_no_selector "div[data-hook='presentation'] input"
|
||||
|
||||
# And I should see unit value and description fields for the unit-related option value
|
||||
expect(page).to have_field "unit_value_human", with: "1"
|
||||
expect(page).to have_field "variant_unit_description", with: "foo"
|
||||
# And I should see unit value and description fields for the unit-related option value
|
||||
expect(page).to have_field "unit_value_human", with: "1"
|
||||
expect(page).to have_field "variant_unit_description", with: "foo"
|
||||
|
||||
# When I update the fields and save the variant
|
||||
fill_in "unit_value_human", with: "123"
|
||||
fill_in "variant_unit_description", with: "bar"
|
||||
click_button 'Update'
|
||||
expect(page).to have_content %(Variant "#{p.name}" has been successfully updated!)
|
||||
# When I update the fields and save the variant
|
||||
fill_in "unit_value_human", with: "123"
|
||||
fill_in "variant_unit_description", with: "bar"
|
||||
click_button 'Update'
|
||||
expect(page).to have_content %(Variant "#{product.name}" has been successfully updated!)
|
||||
|
||||
# Then the unit value and description should have been saved
|
||||
v.reload
|
||||
expect(v.unit_value).to eq(123)
|
||||
expect(v.unit_description).to eq('bar')
|
||||
# Then the unit value and description should have been saved
|
||||
expect(variant.reload.unit_value).to eq(123)
|
||||
expect(variant.unit_description).to eq('bar')
|
||||
end
|
||||
|
||||
scenario "can update unit_description when variant_unit is items" do
|
||||
product = create(:simple_product, variant_unit: "items", variant_unit_name: "bunches")
|
||||
variant = product.variants.first
|
||||
variant.update_attributes(unit_description: 'foo')
|
||||
|
||||
login_to_admin_section
|
||||
visit spree.edit_admin_product_variant_path(product, variant)
|
||||
|
||||
expect(page).to_not have_field "unit_value_human"
|
||||
expect(page).to have_field "variant_unit_description", with: "foo"
|
||||
|
||||
fill_in "variant_unit_description", with: "bar"
|
||||
click_button 'Update'
|
||||
expect(page).to have_content %(Variant "#{product.name}" has been successfully updated!)
|
||||
expect(variant.reload.unit_description).to eq('bar')
|
||||
end
|
||||
end
|
||||
|
||||
describe "editing on hand and on demand values", js: true do
|
||||
@@ -99,31 +117,29 @@ feature '
|
||||
end
|
||||
|
||||
it "soft-deletes variants", js: true do
|
||||
p = create(:simple_product)
|
||||
v = create(:variant, product: p)
|
||||
product = create(:simple_product)
|
||||
variant = create(:variant, product: product)
|
||||
|
||||
login_to_admin_section
|
||||
visit spree.admin_product_variants_path p
|
||||
visit spree.admin_product_variants_path product
|
||||
|
||||
within "tr#spree_variant_#{v.id}" do
|
||||
within "tr#spree_variant_#{variant.id}" do
|
||||
accept_alert do
|
||||
page.find('a.delete-resource').click
|
||||
end
|
||||
end
|
||||
|
||||
expect(page).not_to have_selector "tr#spree_variant_#{v.id}"
|
||||
|
||||
v.reload
|
||||
expect(v.deleted_at).not_to be_nil
|
||||
expect(page).not_to have_selector "tr#spree_variant_#{variant.id}"
|
||||
expect(variant.reload.deleted_at).not_to be_nil
|
||||
end
|
||||
|
||||
scenario "editing display name for a variant", js: true do
|
||||
p = create(:simple_product)
|
||||
v = p.variants.first
|
||||
product = create(:simple_product)
|
||||
variant = product.variants.first
|
||||
|
||||
# When I view the variant
|
||||
login_to_admin_section
|
||||
visit spree.admin_product_variants_path p
|
||||
visit spree.admin_product_variants_path product
|
||||
page.find('table.index .icon-edit').click
|
||||
|
||||
# It should allow the display name to be changed
|
||||
@@ -134,11 +150,10 @@ feature '
|
||||
fill_in "variant_display_name", with: "Display Name"
|
||||
fill_in "variant_display_as", with: "Display As This"
|
||||
click_button 'Update'
|
||||
expect(page).to have_content %(Variant "#{p.name}" has been successfully updated!)
|
||||
expect(page).to have_content %(Variant "#{product.name}" has been successfully updated!)
|
||||
|
||||
# Then the displayed values should have been saved
|
||||
v.reload
|
||||
expect(v.display_name).to eq("Display Name")
|
||||
expect(v.display_as).to eq("Display As This")
|
||||
expect(variant.reload.display_name).to eq("Display Name")
|
||||
expect(variant.display_as).to eq("Display As This")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::CustomerTotalsReport do
|
||||
let!(:distributor) { create(:distributor_enterprise) }
|
||||
|
||||
let!(:customer) { create(:customer, enterprise: distributor) }
|
||||
|
||||
let!(:order) do
|
||||
create(:completed_order_with_totals, line_items_count: 1, user: customer.user,
|
||||
customer: customer, distributor: distributor)
|
||||
end
|
||||
|
||||
let(:current_user) { distributor.owner }
|
||||
let(:permissions) { OpenFoodNetwork::Permissions.new(current_user) }
|
||||
|
||||
let(:report) do
|
||||
report_options = { report_type: described_class::REPORT_TYPE }
|
||||
OpenFoodNetwork::OrdersAndFulfillmentsReport.new(permissions, report_options, true)
|
||||
end
|
||||
|
||||
let(:report_table) do
|
||||
OpenFoodNetwork::OrderGrouper.new(report.rules, report.columns).table(report.table_items)
|
||||
end
|
||||
|
||||
it "generates the report" do
|
||||
expect(report_table.length).to eq(2)
|
||||
end
|
||||
|
||||
it "has a line item row" do
|
||||
distributor_name_field = report_table.first[0]
|
||||
expect(distributor_name_field).to eq distributor.name
|
||||
|
||||
customer_name_field = report_table.first[1]
|
||||
expect(customer_name_field).to eq order.bill_address.full_name
|
||||
|
||||
total_field = report_table.last[5]
|
||||
expect(total_field).to eq I18n.t("admin.reports.total")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,37 @@
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::DistributorTotalsBySupplierReport do
|
||||
let!(:distributor) { create(:distributor_enterprise) }
|
||||
|
||||
let!(:order) do
|
||||
create(:completed_order_with_totals, line_items_count: 1, distributor: distributor)
|
||||
end
|
||||
|
||||
let(:current_user) { distributor.owner }
|
||||
let(:permissions) { OpenFoodNetwork::Permissions.new(current_user) }
|
||||
|
||||
let(:report) do
|
||||
report_options = { report_type: described_class::REPORT_TYPE }
|
||||
OpenFoodNetwork::OrdersAndFulfillmentsReport.new(permissions, report_options, true)
|
||||
end
|
||||
|
||||
let(:report_table) do
|
||||
OpenFoodNetwork::OrderGrouper.new(report.rules, report.columns).table(report.table_items)
|
||||
end
|
||||
|
||||
it "generates the report" do
|
||||
expect(report_table.length).to eq(2)
|
||||
end
|
||||
|
||||
it "has a variant row under the distributor" do
|
||||
distributor_name_field = report_table.first[0]
|
||||
expect(distributor_name_field).to eq distributor.name
|
||||
|
||||
supplier = order.line_items.first.variant.product.supplier
|
||||
supplier_name_field = report_table.first[1]
|
||||
expect(supplier_name_field).to eq supplier.name
|
||||
|
||||
total_field = report_table.last[1]
|
||||
expect(total_field).to eq I18n.t("admin.reports.total")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,37 @@
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::SupplierTotalsByDistributorReport do
|
||||
let!(:distributor) { create(:distributor_enterprise) }
|
||||
|
||||
let!(:order) do
|
||||
create(:completed_order_with_totals, line_items_count: 1, distributor: distributor)
|
||||
end
|
||||
|
||||
let(:current_user) { distributor.owner }
|
||||
let(:permissions) { OpenFoodNetwork::Permissions.new(current_user) }
|
||||
|
||||
let(:report) do
|
||||
report_options = { report_type: described_class::REPORT_TYPE }
|
||||
OpenFoodNetwork::OrdersAndFulfillmentsReport.new(permissions, report_options, true)
|
||||
end
|
||||
|
||||
let(:report_table) do
|
||||
OpenFoodNetwork::OrderGrouper.new(report.rules, report.columns).table(report.table_items)
|
||||
end
|
||||
|
||||
it "generates the report" do
|
||||
expect(report_table.length).to eq(2)
|
||||
end
|
||||
|
||||
it "has a variant row under the distributor" do
|
||||
supplier = order.line_items.first.variant.product.supplier
|
||||
supplier_name_field = report_table.first[0]
|
||||
expect(supplier_name_field).to eq supplier.name
|
||||
|
||||
distributor_name_field = report_table.first[3]
|
||||
expect(distributor_name_field).to eq distributor.name
|
||||
|
||||
total_field = report_table.last[3]
|
||||
expect(total_field).to eq I18n.t("admin.reports.total")
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,31 @@
|
||||
require "spec_helper"
|
||||
|
||||
RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::SupplierTotalsReport do
|
||||
let!(:distributor) { create(:distributor_enterprise) }
|
||||
|
||||
let!(:order) do
|
||||
create(:completed_order_with_totals, line_items_count: 1, distributor: distributor)
|
||||
end
|
||||
|
||||
let(:current_user) { distributor.owner }
|
||||
let(:permissions) { OpenFoodNetwork::Permissions.new(current_user) }
|
||||
|
||||
let(:report) do
|
||||
report_options = { report_type: described_class::REPORT_TYPE }
|
||||
OpenFoodNetwork::OrdersAndFulfillmentsReport.new(permissions, report_options, true)
|
||||
end
|
||||
|
||||
let(:report_table) do
|
||||
OpenFoodNetwork::OrderGrouper.new(report.rules, report.columns).table(report.table_items)
|
||||
end
|
||||
|
||||
it "generates the report" do
|
||||
expect(report_table.length).to eq(1)
|
||||
end
|
||||
|
||||
it "has a variant row" do
|
||||
supplier = order.line_items.first.variant.product.supplier
|
||||
supplier_name_field = report_table.first[0]
|
||||
expect(supplier_name_field).to eq supplier.name
|
||||
end
|
||||
end
|
||||
@@ -171,10 +171,48 @@ module OpenFoodNetwork
|
||||
end
|
||||
|
||||
it "should do all the filters at once" do
|
||||
# The following data ensures that this spec fails if any of the
|
||||
# filters fail. It's testing the filters are not impacting each other.
|
||||
distributor = create(:distributor_enterprise)
|
||||
product1 = create(:simple_product, supplier: supplier)
|
||||
product2 = create(:simple_product, supplier: supplier)
|
||||
order_cycle = create(:simple_order_cycle, suppliers: [supplier], distributors: [distributor], variants: [product1.variants.first])
|
||||
other_distributor = create(:distributor_enterprise)
|
||||
other_supplier = create(:supplier_enterprise)
|
||||
not_filtered_variant = create(:simple_product, supplier: supplier).variants.first
|
||||
variant_filtered_by_order_cycle = create(:simple_product, supplier: supplier).variants.first
|
||||
variant_filtered_by_distributor = create(:simple_product, supplier: supplier).variants.first
|
||||
variant_filtered_by_supplier = create(:simple_product, supplier: other_supplier).variants.first
|
||||
variant_filtered_by_stock = create(:simple_product, supplier: supplier, on_hand: 0).variants.first
|
||||
|
||||
# This OC contains all products except the one that should be filtered
|
||||
# by order cycle. We create a separate OC further down to proof that
|
||||
# the product is passing all other filters.
|
||||
order_cycle = create(
|
||||
:simple_order_cycle,
|
||||
suppliers: [supplier, other_supplier],
|
||||
distributors: [distributor, other_distributor],
|
||||
variants: [
|
||||
not_filtered_variant,
|
||||
variant_filtered_by_distributor,
|
||||
variant_filtered_by_supplier,
|
||||
variant_filtered_by_stock
|
||||
]
|
||||
)
|
||||
|
||||
# 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).
|
||||
exchange_variants.
|
||||
find_by_variant_id(variant_filtered_by_distributor).
|
||||
destroy
|
||||
|
||||
# Make product available to be filtered later. See OC comment above.
|
||||
create(
|
||||
:simple_order_cycle,
|
||||
suppliers: [supplier],
|
||||
distributors: [distributor, other_distributor],
|
||||
variants: [
|
||||
variant_filtered_by_order_cycle
|
||||
]
|
||||
)
|
||||
|
||||
allow(subject).to receive(:params).and_return(
|
||||
order_cycle_id: order_cycle.id,
|
||||
@@ -182,7 +220,11 @@ module OpenFoodNetwork
|
||||
distributor_id: distributor.id,
|
||||
report_type: 'inventory'
|
||||
)
|
||||
subject.filter(variants)
|
||||
|
||||
expect(subject.filter(variants)).to match_array [not_filtered_variant]
|
||||
|
||||
# And it integrates with the ordering of the `variants` method.
|
||||
expect(subject.variants).to match_array [not_filtered_variant]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ module Stock
|
||||
describe '#shipping_categories' do
|
||||
it "returns shipping categories that are not shipping categories of the order's products" do
|
||||
package
|
||||
other_shipping_category = create(:shipping_category)
|
||||
other_shipping_category = Spree::ShippingCategory.create(name: "Custom")
|
||||
|
||||
expect(package.shipping_categories).to eq [shipping_method1.shipping_categories.first,
|
||||
other_shipping_category]
|
||||
|
||||
38
spec/services/default_shipping_category_spec.rb
Normal file
38
spec/services/default_shipping_category_spec.rb
Normal file
@@ -0,0 +1,38 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe DefaultShippingCategory do
|
||||
describe '.create!' do
|
||||
it "names the location 'Default'" do
|
||||
shipping_category = described_class.create!
|
||||
expect(shipping_category.name).to eq 'Default'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'find_or_create' do
|
||||
context 'when a Default category already exists' do
|
||||
let!(:category) do
|
||||
Spree::ShippingCategory.create!(name: 'Default')
|
||||
end
|
||||
|
||||
it 'returns the category' do
|
||||
expect(described_class.find_or_create).to eq category
|
||||
end
|
||||
|
||||
it 'does not create another category' do
|
||||
expect { described_class.find_or_create }.not_to change(Spree::ShippingCategory, :count)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when a Default category does not exist' do
|
||||
it 'returns the category' do
|
||||
category = described_class.find_or_create
|
||||
expect(category.name).to eq 'Default'
|
||||
end
|
||||
|
||||
it 'does not create another category' do
|
||||
expect { described_class.find_or_create }
|
||||
.to change(Spree::ShippingCategory, :count).from(0).to(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user