mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-12 18:36:49 +00:00
Compare commits
54 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b17d3e447c | ||
|
|
2ae4234015 | ||
|
|
20874dec98 | ||
|
|
288cd367bc | ||
|
|
68902021ab | ||
|
|
7f9c578fca | ||
|
|
782c9150a2 | ||
|
|
447b040020 | ||
|
|
6bdb89d090 | ||
|
|
a63531c8c2 | ||
|
|
de2a15e3e1 | ||
|
|
e5f5d42d59 | ||
|
|
f23de206d9 | ||
|
|
729bcdf291 | ||
|
|
62d0ce290a | ||
|
|
96ead52fcc | ||
|
|
ff708952ab | ||
|
|
2daa49406a | ||
|
|
125bc3d14b | ||
|
|
02300d6bb6 | ||
|
|
aba3968bca | ||
|
|
23c4298519 | ||
|
|
d7047bb4cc | ||
|
|
1ce029d8e4 | ||
|
|
eb7d20d74d | ||
|
|
c4ba1e6616 | ||
|
|
f97ccb4203 | ||
|
|
df8283661d | ||
|
|
d9ee56b4a5 | ||
|
|
2230a1f179 | ||
|
|
a9c8d9f304 | ||
|
|
a7644f8e8b | ||
|
|
5dd2737811 | ||
|
|
d9b534b829 | ||
|
|
a78768c291 | ||
|
|
b9a7ff903f | ||
|
|
fc6b61fc87 | ||
|
|
131772f7b2 | ||
|
|
440e776e3a | ||
|
|
56b9c28955 | ||
|
|
c34942dbf0 | ||
|
|
12906d1e13 | ||
|
|
103bc50bdc | ||
|
|
b6cccc2e1d | ||
|
|
918e583d01 | ||
|
|
7b8ccccdc3 | ||
|
|
0cae069769 | ||
|
|
b99383185b | ||
|
|
66485e2e16 | ||
|
|
c1b60d88d6 | ||
|
|
08e23023b3 | ||
|
|
c83dac58a3 | ||
|
|
e5ca8b0ee1 | ||
|
|
cf8d9c6d07 |
@@ -119,7 +119,6 @@ Layout/LineLength:
|
||||
- 'spec/controllers/admin/bulk_line_items_controller_spec.rb'
|
||||
- 'spec/controllers/admin/column_preferences_controller_spec.rb'
|
||||
- 'spec/controllers/admin/enterprises_controller_spec.rb'
|
||||
- 'spec/controllers/admin/manager_invitations_controller_spec.rb'
|
||||
- 'spec/controllers/admin/order_cycles_controller_spec.rb'
|
||||
- 'spec/controllers/admin/schedules_controller_spec.rb'
|
||||
- 'spec/controllers/admin/stripe_accounts_controller_spec.rb'
|
||||
|
||||
20
Gemfile.lock
20
Gemfile.lock
@@ -231,10 +231,10 @@ GEM
|
||||
database_cleaner-core (~> 2.0.0)
|
||||
database_cleaner-core (2.0.1)
|
||||
date (3.3.3)
|
||||
ddtrace (1.9.0)
|
||||
ddtrace (1.10.1)
|
||||
debase-ruby_core_source (>= 0.10.16, <= 3.2.0)
|
||||
libdatadog (~> 1.0.1.1.0)
|
||||
libddwaf (~> 1.5.1.0.0)
|
||||
libdatadog (~> 2.0.0.1.0)
|
||||
libddwaf (~> 1.6.2.0.0)
|
||||
msgpack
|
||||
debase-ruby_core_source (3.2.0)
|
||||
debug (1.7.1)
|
||||
@@ -373,8 +373,8 @@ GEM
|
||||
addressable (~> 2.7)
|
||||
letter_opener (1.8.1)
|
||||
launchy (>= 2.2, < 3)
|
||||
libdatadog (1.0.1.1.0)
|
||||
libddwaf (1.5.1.0.0)
|
||||
libdatadog (2.0.0.1.0)
|
||||
libddwaf (1.6.2.0.0)
|
||||
ffi (~> 1.0)
|
||||
libv8-node (16.10.0.0)
|
||||
listen (3.8.0)
|
||||
@@ -407,7 +407,7 @@ GEM
|
||||
money (~> 6.12)
|
||||
money (6.16.0)
|
||||
i18n (>= 0.6.4, <= 2)
|
||||
msgpack (1.6.0)
|
||||
msgpack (1.6.1)
|
||||
multi_json (1.15.0)
|
||||
multi_xml (0.6.0)
|
||||
net-imap (0.3.4)
|
||||
@@ -459,7 +459,7 @@ GEM
|
||||
parallel (1.22.1)
|
||||
paranoia (2.6.1)
|
||||
activerecord (>= 5.1, < 7.1)
|
||||
parser (3.2.1.0)
|
||||
parser (3.2.1.1)
|
||||
ast (~> 2.4.1)
|
||||
paypal-sdk-core (0.3.4)
|
||||
multi_json (~> 1.0)
|
||||
@@ -482,7 +482,7 @@ GEM
|
||||
nio4r (~> 2.0)
|
||||
raabro (1.4.0)
|
||||
racc (1.6.2)
|
||||
rack (2.2.6.2)
|
||||
rack (2.2.6.3)
|
||||
rack-mini-profiler (2.3.4)
|
||||
rack (>= 1.2.0)
|
||||
rack-oauth2 (1.21.3)
|
||||
@@ -605,7 +605,7 @@ GEM
|
||||
rswag-ui (2.8.0)
|
||||
actionpack (>= 3.1, < 7.1)
|
||||
railties (>= 3.1, < 7.1)
|
||||
rubocop (1.47.0)
|
||||
rubocop (1.48.1)
|
||||
json (~> 2.3)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.2.0.0)
|
||||
@@ -623,7 +623,7 @@ GEM
|
||||
rubocop (>= 1.33.0, < 2.0)
|
||||
ruby-graphviz (1.2.5)
|
||||
rexml
|
||||
ruby-progressbar (1.12.0)
|
||||
ruby-progressbar (1.13.0)
|
||||
ruby-rc4 (0.1.5)
|
||||
ruby-vips (2.1.4)
|
||||
ffi (~> 1.12)
|
||||
|
||||
@@ -55,19 +55,6 @@ angular.module("admin.enterprises")
|
||||
else
|
||||
alert ("#{manager.email}" + " " + t("is_already_manager"))
|
||||
|
||||
$scope.inviteManager = ->
|
||||
$scope.invite_errors = $scope.invite_success = null
|
||||
email = $scope.newUser
|
||||
|
||||
$http.post("/admin/manager_invitations", {email: email, enterprise_id: $scope.Enterprise.id}).then (response)->
|
||||
$scope.addManager({id: response.data.user, email: email})
|
||||
$scope.invite_success = t('user_invited', email: email)
|
||||
.catch (response) ->
|
||||
$scope.invite_errors = response.data.errors
|
||||
|
||||
$scope.resetModal = ->
|
||||
$scope.newUser = $scope.invite_errors = $scope.invite_success = null
|
||||
|
||||
$scope.removeLogo = ->
|
||||
$scope.performEnterpriseAction("removeLogo", "immediate_logo_removal_warning", "removed_logo_successfully")
|
||||
|
||||
|
||||
@@ -150,6 +150,10 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
else
|
||||
Promise.all(LineItems.delete(item) for item in items).then(-> $scope.refreshData())
|
||||
, "js.admin.deleting_item_will_cancel_order")
|
||||
else
|
||||
ofnDeleteLineItemsAlert(() ->
|
||||
Promise.all(LineItems.delete(item) for item in lineItemsToDelete).then(-> $scope.refreshData())
|
||||
, lineItemsToDelete.length)
|
||||
|
||||
$scope.allBoxesChecked = ->
|
||||
checkedCount = $scope.filteredLineItems.reduce (count,lineItem) ->
|
||||
|
||||
@@ -250,6 +250,18 @@ ofnCancelOrderAlert = function(callback, i18nKey) {
|
||||
$('#custom-confirm').show();
|
||||
}
|
||||
|
||||
ofnDeleteLineItemsAlert = function(callback, count) {
|
||||
$('#custom-confirm .message').html(`${t("js.admin.orders.delete_line_items_html", {count: count})}`);
|
||||
$('#custom-confirm button.confirm').click(() => {
|
||||
$('#custom-confirm').hide();
|
||||
callback();
|
||||
});
|
||||
$('#custom-confirm button.cancel').click(() => {
|
||||
$('#custom-confirm').hide();
|
||||
});
|
||||
$('#custom-confirm').show();
|
||||
}
|
||||
|
||||
ofnConfirm = function(callback) {
|
||||
$('#custom-confirm .message').html(
|
||||
` ${t("are_you_sure")}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
angular.module("admin.utils", ["templates", "ngSanitize"]).config ($httpProvider) ->
|
||||
angular.module("admin.utils", ["templates", "ngSanitize"]).config ($httpProvider, $locationProvider) ->
|
||||
$locationProvider.hashPrefix('')
|
||||
$httpProvider.defaults.headers.common["Accept"] = "application/json, text/javascript, */*"
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class ManagerInvitationsController < Spree::Admin::BaseController
|
||||
authorize_resource class: false
|
||||
|
||||
def create
|
||||
@email = params[:email]
|
||||
@enterprise = Enterprise.find(params[:enterprise_id])
|
||||
|
||||
authorize! :edit, @enterprise
|
||||
|
||||
existing_user = Spree::User.find_by(email: @email)
|
||||
|
||||
if existing_user
|
||||
render json: { errors: t('admin.enterprises.invite_manager.user_already_exists') },
|
||||
status: :unprocessable_entity
|
||||
return
|
||||
end
|
||||
|
||||
new_user = create_new_manager
|
||||
|
||||
if new_user
|
||||
render json: { user: new_user.id }, status: :ok
|
||||
else
|
||||
render json: { errors: t('admin.enterprises.invite_manager.error') },
|
||||
status: :internal_server_error
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_new_manager
|
||||
password = Devise.friendly_token
|
||||
new_user = Spree::User.create(email: @email, unconfirmed_email: @email, password: password)
|
||||
new_user.reset_password_token = Devise.friendly_token
|
||||
# Same time as used in Devise's lib/devise/models/recoverable.rb.
|
||||
new_user.reset_password_sent_at = Time.now.utc
|
||||
new_user.save!
|
||||
|
||||
@enterprise.users << new_user
|
||||
EnterpriseMailer.manager_invitation(@enterprise, new_user).deliver_later
|
||||
|
||||
new_user
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -100,10 +100,13 @@ module Admin
|
||||
order_cycle.schedules.each do |schedule|
|
||||
Subscription.where(schedule_id: schedule.id).each do |subscription|
|
||||
shop = Enterprise.managed_by(spree_current_user).find_by(id: subscription.shop_id)
|
||||
fee_calculator = OpenFoodNetwork::EnterpriseFeeCalculator.new(shop, order_cycle)
|
||||
subscription.subscription_line_items.nil_price_estimate.each do |line_item|
|
||||
variant = OrderManagement::Subscriptions::
|
||||
VariantsList.eligible_variants(shop).find_by(id: line_item.variant_id)
|
||||
fee_calculator = OpenFoodNetwork::EnterpriseFeeCalculator.new(shop, order_cycle)
|
||||
# If the variant is not available in the shop, the price estimate will be nil
|
||||
next if variant.nil?
|
||||
|
||||
price = variant.price + fee_calculator.indexed_fees_for(variant)
|
||||
line_item.update_column(:price_estimate, price)
|
||||
end
|
||||
|
||||
21
app/controllers/concerns/manager_invitations.rb
Normal file
21
app/controllers/concerns/manager_invitations.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module ManagerInvitations
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def create_new_manager(email, enterprise)
|
||||
password = Devise.friendly_token
|
||||
new_user = Spree::User.create(email: email, unconfirmed_email: email, password: password)
|
||||
new_user.reset_password_token = Devise.friendly_token
|
||||
# Same time as used in Devise's lib/devise/models/recoverable.rb.
|
||||
new_user.reset_password_sent_at = Time.now.utc
|
||||
new_user.save
|
||||
|
||||
return new_user unless new_user.valid? # Return early if user is invalid.
|
||||
|
||||
enterprise.users << new_user
|
||||
EnterpriseMailer.manager_invitation(@enterprise, new_user).deliver_later
|
||||
|
||||
new_user
|
||||
end
|
||||
end
|
||||
@@ -141,6 +141,10 @@ class SplitCheckoutController < ::BaseController
|
||||
def update_order
|
||||
return if params[:confirm_order] || @order.errors.any?
|
||||
|
||||
# If we have "pick up" shipping method (require_ship_address is set to false), use the
|
||||
# distributor address as shipping address
|
||||
use_shipping_address_from_distributor if shipping_method_ship_address_not_required?
|
||||
|
||||
@order.select_shipping_method(params[:shipping_method_id])
|
||||
@order.update(order_params)
|
||||
@order.updater.update_totals_and_states
|
||||
@@ -150,6 +154,29 @@ class SplitCheckoutController < ::BaseController
|
||||
@order.errors.empty?
|
||||
end
|
||||
|
||||
def use_shipping_address_from_distributor
|
||||
@order.ship_address = @order.address_from_distributor
|
||||
|
||||
# Add the missing data
|
||||
bill_address = params[:order][:bill_address_attributes]
|
||||
@order.ship_address.firstname = bill_address[:firstname]
|
||||
@order.ship_address.lastname = bill_address[:lastname]
|
||||
@order.ship_address.phone = bill_address[:phone]
|
||||
|
||||
# Remove shipping address from parameter so we don't override the address we just set
|
||||
params[:order].delete(:ship_address_attributes)
|
||||
end
|
||||
|
||||
def shipping_method_ship_address_not_required?
|
||||
selected_shipping_method = allowed_shipping_methods&.select do |sm|
|
||||
sm.id.to_s == params[:shipping_method_id]
|
||||
end
|
||||
|
||||
return false if selected_shipping_method.empty?
|
||||
|
||||
selected_shipping_method.first.require_ship_address == false
|
||||
end
|
||||
|
||||
def summary_step?
|
||||
params[:step] == "summary"
|
||||
end
|
||||
|
||||
@@ -271,10 +271,16 @@ module ProductImport
|
||||
end
|
||||
|
||||
def entry_matches_existing_variant?(entry, existing_variant)
|
||||
existing_variant.display_name == entry.display_name &&
|
||||
display_name_are_the_same?(entry, existing_variant) &&
|
||||
existing_variant.unit_value == entry.unit_value.to_f
|
||||
end
|
||||
|
||||
def display_name_are_the_same?(entry, existing_variant)
|
||||
return true if entry.display_name.blank? && existing_variant.display_name.blank?
|
||||
|
||||
existing_variant.display_name == entry.display_name
|
||||
end
|
||||
|
||||
def category_validation(entry)
|
||||
category_name = entry.category
|
||||
|
||||
|
||||
@@ -23,4 +23,8 @@ class ApplicationReflex < StimulusReflex::Reflex
|
||||
def current_ability
|
||||
Spree::Ability.new(current_user)
|
||||
end
|
||||
|
||||
def with_locale(&block)
|
||||
I18n.with_locale(current_user.locale, &block)
|
||||
end
|
||||
end
|
||||
|
||||
43
app/reflexes/invite_manager_reflex.rb
Normal file
43
app/reflexes/invite_manager_reflex.rb
Normal file
@@ -0,0 +1,43 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class InviteManagerReflex < ApplicationReflex
|
||||
include ManagerInvitations
|
||||
|
||||
def invite
|
||||
email = params[:email]
|
||||
enterprise = Enterprise.find(params[:enterprise_id])
|
||||
|
||||
authorize! :edit, enterprise
|
||||
|
||||
existing_user = Spree::User.find_by(email: email)
|
||||
|
||||
locals = { error: nil, success: nil, email: email, enterprise: enterprise }
|
||||
|
||||
if existing_user
|
||||
locals[:error] = I18n.t('admin.enterprises.invite_manager.user_already_exists')
|
||||
|
||||
return_morph(locals)
|
||||
return
|
||||
end
|
||||
|
||||
new_user = create_new_manager(email, enterprise)
|
||||
|
||||
if new_user.valid?
|
||||
locals[:success] = true
|
||||
else
|
||||
locals[:error] = new_user.errors.full_messages.to_sentence ||
|
||||
I18n.t('admin.enterprises.invite_manager.error')
|
||||
end
|
||||
|
||||
return_morph(locals)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def return_morph(locals)
|
||||
morph "#add_manager_modal",
|
||||
with_locale {
|
||||
render(partial: "admin/enterprises/form/add_new_unregistered_manager", locals: locals)
|
||||
}
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,22 @@
|
||||
%div#add_manager_modal
|
||||
%form{ "data-reflex": "submit->InviteManager#invite", "data-reflex-serialize-form": true }
|
||||
.margin-bottom-30.text-center
|
||||
.text-big
|
||||
= t('js.admin.modals.invite_title')
|
||||
|
||||
- if success
|
||||
%p.alert-box.ok= t('user_invited', email: email)
|
||||
|
||||
- if error
|
||||
%p.alert-box.error= error
|
||||
|
||||
= text_field_tag :email, nil, class: 'fullwidth margin-bottom-20'
|
||||
= hidden_field_tag :enterprise_id, @enterprise&.id || enterprise.id
|
||||
|
||||
.modal-actions
|
||||
- if success
|
||||
%input{ class: "button icon-plus secondary", type: 'button', value: t('js.admin.modals.close'), "data-action": "click->help-modal#close" }
|
||||
- else
|
||||
%input{ class: "button icon-plus secondary", type: 'button', value: t('js.admin.modals.cancel'), "data-action": "click->help-modal#close" }
|
||||
= submit_tag "#{t('js.admin.modals.invite')}"
|
||||
|
||||
@@ -6,8 +6,7 @@
|
||||
=f.label :owner_id, t('.owner')
|
||||
- if full_permissions
|
||||
%span.required *
|
||||
%div{'ofn-with-tip' => t('.owner_tip')}
|
||||
%a= t('admin.whats_this')
|
||||
= render partial: 'admin/shared/tooltip', locals: {tooltip_text: t('.owner_tip')}
|
||||
.eight.columns.omega
|
||||
- if full_permissions
|
||||
= f.hidden_field :owner_id, class: "select2 fullwidth", 'user-select' => 'Enterprise.owner', 'ng-model' => 'Enterprise.owner'
|
||||
@@ -19,8 +18,7 @@
|
||||
=f.label :user_ids, t('.notifications')
|
||||
- if full_permissions
|
||||
%span.required *
|
||||
%div{'ofn-with-tip' => t('.contact_tip')}
|
||||
%a= t('admin.whats_this')
|
||||
= render partial: 'admin/shared/tooltip', locals: {tooltip_text: t('.contact_tip')}
|
||||
.eight.columns.omega
|
||||
- if full_permissions
|
||||
%select.select2.fullwidth{id: 'receives_notifications_dropdown', name: 'receives_notifications', ng: {model: 'receivesNotifications', init: "receivesNotifications = '#{@enterprise.contact.id}'"}}
|
||||
@@ -34,8 +32,7 @@
|
||||
=f.label :user_ids, t('.managers')
|
||||
- if full_permissions
|
||||
%span.required *
|
||||
%div{'ofn-with-tip' => t('.managers_tip')}
|
||||
%a= t('admin.whats_this')
|
||||
= render partial: 'admin/shared/tooltip', locals: {tooltip_text: t('.managers_tip')}
|
||||
.eight.columns.omega
|
||||
- if full_permissions
|
||||
%table.managers
|
||||
@@ -66,8 +63,7 @@
|
||||
.three.columns.alpha
|
||||
%label
|
||||
= t('.invite_manager')
|
||||
%div{'ofn-with-tip' => t('.invite_manager_tip')}
|
||||
%a= t('admin.whats_this')
|
||||
= render partial: 'admin/shared/tooltip', locals: {tooltip_text: t('.invite_manager_tip')}
|
||||
.eight.columns.omega
|
||||
.row
|
||||
%a.button{ "data-controller": "help-modal-link", "data-action": "click->help-modal-link#open", "data-help-modal-link-target-value": "invite-manager-modal" }
|
||||
@@ -76,22 +72,4 @@
|
||||
-# add to admin footer to avoid nesting invitation form inside enterprise form
|
||||
- content_for :admin_footer do
|
||||
= render HelpModalComponent.new(id: "invite-manager-modal", close_button: false) do
|
||||
%div{ng: {app: 'admin.enterprises', controller: 'enterpriseCtrl'}}
|
||||
|
||||
.margin-bottom-30.text-center
|
||||
.text-big
|
||||
= t('js.admin.modals.invite_title')
|
||||
|
||||
%p.alert-box.ok{ng: {show: 'invite_success'}}
|
||||
{{invite_success}}
|
||||
|
||||
%p.alert-box.error{ng: {show: 'invite_errors'}}
|
||||
{{invite_errors}}
|
||||
|
||||
%input#invite_email.fullwidth.margin-bottom-20{ng: {model: 'newUser'}}
|
||||
|
||||
.margin-bottom-20.text-center
|
||||
%button.text-center.margin-top-10{ng: {show: '!invite_success', click: 'inviteManager()'}}
|
||||
= t('js.admin.modals.invite')
|
||||
%button.text-center.margin-top-10{"data-action": "click->help-modal#close", ng: {show: 'invite_success', click: 'resetModal();'}}
|
||||
= t('js.admin.modals.close')
|
||||
= render partial: 'admin/enterprises/form/add_new_unregistered_manager', locals: { error: nil, success: nil }
|
||||
|
||||
@@ -34,6 +34,10 @@
|
||||
= @order.bill_address.zipcode
|
||||
%div
|
||||
= @order.bill_address.country
|
||||
- if @order.special_instructions.present?
|
||||
%br
|
||||
%em
|
||||
= @order.special_instructions
|
||||
- if @order.shipping_method.description.present?
|
||||
%div
|
||||
.summary-subtitle
|
||||
|
||||
@@ -29,5 +29,5 @@
|
||||
- if spree_current_user
|
||||
.checkout-input
|
||||
= check_box_tag "order[payments_attributes][][source_attributes][save_requested_by_customer]", 1, false
|
||||
= label :save_requested_by_customer, t('split_checkout.step2.form.stripe.save_card'), { for: "save_requested_by_customer" }
|
||||
= label_tag :order_payments_attributes__source_attributes_save_requested_by_customer, t('split_checkout.step2.form.stripe.save_card')
|
||||
|
||||
@@ -240,6 +240,7 @@ module Openfoodnetwork
|
||||
config.generators.template_engine = :haml
|
||||
|
||||
Rails.application.routes.default_url_options[:host] = ENV["SITE_URL"]
|
||||
DfcProvider::Engine.routes.default_url_options[:host] = ENV["SITE_URL"]
|
||||
|
||||
Rails.autoloaders.main.ignore(Rails.root.join('app/webpacker'))
|
||||
|
||||
|
||||
@@ -3253,6 +3253,9 @@ See the %{link} to find out more about %{sitename}'s features and to start using
|
||||
cancel_the_order_send_cancelation_email: "Send a cancellation email to the customer"
|
||||
restock_item: "Restock Items: return this item to stock"
|
||||
restock_items: "Restock Items: return all items to stock"
|
||||
delete_line_items_html:
|
||||
one: "This will delete one line item from the order.<br />Are you sure you want to proceed?"
|
||||
other: "This will delete %{count} line items from the order.<br />Are you sure you want to proceed?"
|
||||
resend_user_email_confirmation:
|
||||
resend: "Resend"
|
||||
sending: "Resend..."
|
||||
|
||||
@@ -1124,8 +1124,8 @@ hu:
|
||||
back_to_list: "Vissza a listához"
|
||||
save_and_back_to_list: "Mentés és Vissza a listához"
|
||||
choose_products_from: "Válasszon termékeket a következők közül:"
|
||||
re_notify_producers: Értesítse újra a gyártókat
|
||||
notify_producers_tip: Ez minden gyártónak e-mailt küld a rendeléseik listájával.
|
||||
re_notify_producers: Értesítse újra a termelőket
|
||||
notify_producers_tip: Ez minden termelőnak e-mailt küld a rendeléseik listájával.
|
||||
incoming:
|
||||
incoming: "Beérkező"
|
||||
supplier: "Termelő"
|
||||
@@ -1246,7 +1246,7 @@ hu:
|
||||
closed: zárva
|
||||
producer_properties:
|
||||
index:
|
||||
title: A gyártó tulajdonságai
|
||||
title: A termelő tulajdonságai
|
||||
proxy_orders:
|
||||
cancel:
|
||||
could_not_cancel_the_order: A rendelést nem lehetett törölni
|
||||
@@ -2088,7 +2088,7 @@ hu:
|
||||
producers_signup_motivation: Adja el ételeit, és mesélje el történeteit változatos új piacokon. Takarítson meg időt és pénzt minden rezsinél. Kockázat nélkül támogatjuk az innovációt. Kiegyenlítettük a játékteret.
|
||||
producers_signup_send: Csatlakozz most
|
||||
producers_signup_enterprise: Vállalkozási fiókok
|
||||
producers_signup_studies: Gyártóink történetei.
|
||||
producers_signup_studies: Termelőink történetei.
|
||||
producers_signup_cta_headline: Csatlakozz most!
|
||||
producers_signup_cta_action: Csatlakozz most
|
||||
producers_signup_detail: Itt a részlet.
|
||||
@@ -2454,12 +2454,12 @@ hu:
|
||||
new_order_cycle: "Új rendelési ciklus"
|
||||
new_order_cycle_tooltip: "Nyissa meg az üzletet egy bizonyos ideig"
|
||||
select_a_coordinator_for_your_order_cycle: "Válasszon koordinátort a rendelési ciklushoz"
|
||||
notify_producers: 'Értesítse a gyártókat'
|
||||
notify_producers: 'Értesítse a termelőket'
|
||||
edit_order_cycle: "Rendelési ciklus szerkesztése"
|
||||
roles: "Szerepek"
|
||||
update: "Frissítés"
|
||||
delete: Töröl
|
||||
add_producer_property: "Gyártói tulajdon hozzáadása"
|
||||
add_producer_property: "Termelői tulajdonság hozzáadása"
|
||||
in_progress: "Folyamatban"
|
||||
started_at: "-kor kezdődött"
|
||||
queued: "Sorban"
|
||||
|
||||
@@ -6,9 +6,22 @@ it:
|
||||
spree/shipping_method: Metodo di spedizione
|
||||
attributes:
|
||||
spree/order/ship_address:
|
||||
address1: "Dati di consegna - Indirizzo"
|
||||
address2: "Dati di consegna - continuazione indirizzo"
|
||||
city: "Dati di consegna - città"
|
||||
country: "Dati di consegna - nazione"
|
||||
phone: "Numero di telefono"
|
||||
firstname: "Nome"
|
||||
lastname: "Cognome"
|
||||
zipcode: "Dati di consegna - CAP"
|
||||
spree/order/bill_address:
|
||||
address1: "Dati di fatturazione - indirizzo"
|
||||
zipcode: "Dati di fatturazione - CAP"
|
||||
city: "Dati di fatturazione - città"
|
||||
country: "Dati di fatturazione - nazione"
|
||||
firstname: "Dati di fatturazione - nome"
|
||||
lastname: "Dati di fatturazione - cognome"
|
||||
phone: Telefono
|
||||
spree/user:
|
||||
password: "Password"
|
||||
password_confirmation: "Conferma password"
|
||||
@@ -1311,6 +1324,7 @@ it:
|
||||
total_by_customer: Totale Per Consumatore
|
||||
total_by_supplier: Totale Per Fornitore
|
||||
supplier_totals: Totali Ciclo di richieste fornitori
|
||||
percentage: "%{value} %"
|
||||
supplier_totals_by_distributor: Totali Ciclo di richieste fornitori per distributore
|
||||
totals_by_supplier: Totali Ciclo di richieste fornitori per fornitore
|
||||
customer_totals: Ciclo Ordini Cliente Totale
|
||||
@@ -1321,6 +1335,8 @@ it:
|
||||
addresses: Indirizzi
|
||||
payment_methods: Rapporto Metodi di pagamento
|
||||
delivery: Rapporto Consegne
|
||||
sales_tax_totals_by_producer: Totali tasse vendita per produttore
|
||||
sales_tax_totals_by_order: Totali tasse vendita per ordine
|
||||
tax_types: Tipologia tariffe
|
||||
tax_rates: Aliquote IVA
|
||||
pack_by_customer: Imballato dal Cliente
|
||||
@@ -1582,7 +1598,7 @@ it:
|
||||
require_login_2_html: "Vuoi iniziare a acquistare qui? Per favore %{contact} %{enterprise} e chiedi di essere aggiunto."
|
||||
require_customer_html: "Se vuoi iniziare a comprare, per favore %{contact} %{enterprise} per chiedere di aggiungerti ai clienti."
|
||||
select_oc:
|
||||
select_oc_html: "Per vedere i prodotti disponibili,<span class='highlighted'>scegli la data di consegna</span> dal riquadro in alto a destra."
|
||||
select_oc_html: "Per vedere i prodotti disponibili, <span class='highlighted'>scegli la data di consegna</span> dal riquadro in alto a destra."
|
||||
products:
|
||||
summary:
|
||||
bulk: "Volume"
|
||||
@@ -1618,7 +1634,7 @@ it:
|
||||
menu_4_title: "Reti"
|
||||
menu_4_url: "/groups"
|
||||
menu_5_title: "Chi siamo"
|
||||
menu_5_url: "https://about.openfoodnetwork.org.au/"
|
||||
menu_5_url: "https://www.openfooditalia.org/"
|
||||
menu_6_title: "Blog"
|
||||
menu_6_url: "https://apropos.openfoodfrance.org/blog/"
|
||||
menu_7_title: "Support"
|
||||
@@ -1861,10 +1877,13 @@ it:
|
||||
title: Dettagli della consegna
|
||||
edit: Modifica
|
||||
address: Indirizzo di consegna
|
||||
instructions: Istruzioni
|
||||
payment_method:
|
||||
title: Metodo di pagamento
|
||||
edit: Modifica
|
||||
instructions: Istruzioni
|
||||
order:
|
||||
title: Dettagli ordine
|
||||
edit: Modifica
|
||||
terms_and_conditions:
|
||||
message_html: "Accetto i %{terms_and_conditions_link} del venditore."
|
||||
@@ -1877,6 +1896,7 @@ it:
|
||||
submit: Completa ordine
|
||||
cancel: Torna al metodo di pagamento
|
||||
errors:
|
||||
saving_failed: "Salvataggio fallito, per favore controlla i campi evidenziati. %{messages}"
|
||||
terms_not_accepted: Per favore accetta i Termini e Condizioni
|
||||
required: Il campo non può essere lasciato vuoto
|
||||
invalid_number: "Per favore inserisci un numero di telefono valido"
|
||||
@@ -2659,6 +2679,7 @@ it:
|
||||
report_header_tax_on_delivery: "Oneri sulla consegna (%{currency_symbol})"
|
||||
report_header_tax_on_fees: "Oneri sulle provvigioni (%{currency_symbol})"
|
||||
report_header_tax_category: "Categoria d'imposta"
|
||||
report_header_tax_rate_name: "Nome tassa"
|
||||
report_header_tax_rate: "Aliquota d'imposta"
|
||||
report_header_total_tax: "Oneri totali (%{currency_symbol})"
|
||||
report_header_total_excl_tax: "Totale imponibile (%{currency_symbol})"
|
||||
@@ -2682,6 +2703,7 @@ it:
|
||||
report_header_supplier: Fornitore
|
||||
report_header_producer: Produttore
|
||||
report_header_producer_suburb: Comune produttore
|
||||
report_header_producer_tax_status: Stato tassa produttore
|
||||
report_header_producer_charges_sales_tax?: Partita IVA / Codice fiscale
|
||||
report_header_unit: Unità
|
||||
report_header_group_buy_unit_quantity: Raggruppare per quantità di unità
|
||||
@@ -2698,6 +2720,7 @@ it:
|
||||
report_header_distributor_address: Indirizzo distributore
|
||||
report_header_distributor_city: Città distributore
|
||||
report_header_distributor_postcode: CAP distributore
|
||||
report_header_distributor_tax_status: Stato tassa distributore
|
||||
report_header_delivery_address: Indirizzo consegna
|
||||
report_header_delivery_postcode: CAP consegna
|
||||
report_header_bulk_unit_size: Quantità minima per Acquisto di Gruppo
|
||||
@@ -2787,7 +2810,7 @@ it:
|
||||
shipping: "Spedizione"
|
||||
shipping_methods: "Metodi di Spedizione"
|
||||
payment_methods: "Metodi di pagamento"
|
||||
payment_method_fee: "Imposta di transizione"
|
||||
payment_method_fee: "Imposta di transazione"
|
||||
payment_processing_failed: "Non è stato possibile elaborare il pagamento, per favore controlla i dettagli che hai inserito"
|
||||
payment_method_not_supported: "Questo metodo di pagamento non è supportato. Per favore scegline un altro."
|
||||
payment_updated: "Pagamento aggiornato"
|
||||
@@ -2879,6 +2902,7 @@ it:
|
||||
deleting_item_will_cancel_order: "Questa operazione risulterà in una o più gentili richieste vuote che saranno cancellate. Desideri proseguire?"
|
||||
modals:
|
||||
got_it: "Capito"
|
||||
confirm: "Conferma"
|
||||
close: "Ok"
|
||||
continue: "Continua"
|
||||
cancel: "Annulla"
|
||||
@@ -3429,6 +3453,8 @@ it:
|
||||
server_error: "Errore Server"
|
||||
shipping_method_names:
|
||||
UPS Ground: "UPS Ground"
|
||||
pick_up: "Ritiro in azienda"
|
||||
delivery: "Firmato, sigillato, consegnato"
|
||||
start_date: "Data inizio"
|
||||
successfully_removed: "Rimosso con successo"
|
||||
taxonomy_edit: "Modifica tassonomia"
|
||||
@@ -3513,6 +3539,7 @@ it:
|
||||
display_currency: "Visualizza valuta"
|
||||
choose_currency: "Scegli Valuta"
|
||||
mail_method_settings: "Impostazioni del metodo di posta"
|
||||
mail_settings_notice_html: "<b>Le modifiche efettuate saranno temporanee</b> solo per il debugging, potrebbero essere invertite in futuro. <br>Modifiche permanenti possono essere effettuate modificando i dati nascosti dell'istanza utilizzando <a href='https://github.com/openfoodfoundation/ofn-install'>intallazione ofn </a>. Contatta il team globale OFN per maggiori dettagli. "
|
||||
general: "Generale"
|
||||
enable_mail_delivery: "Abilita recapito posta"
|
||||
send_mails_as: "Invia mail come"
|
||||
|
||||
@@ -42,8 +42,6 @@ Openfoodnetwork::Application.routes.draw do
|
||||
resources :tag_rules, only: [:destroy]
|
||||
end
|
||||
|
||||
resources :manager_invitations, only: [:create]
|
||||
|
||||
resources :enterprise_relationships
|
||||
resources :enterprise_roles
|
||||
|
||||
|
||||
@@ -6,10 +6,6 @@ module DfcProvider
|
||||
class BaseSerializer < ActiveModel::Serializer
|
||||
private
|
||||
|
||||
def host
|
||||
Rails.application.routes.default_url_options[:host]
|
||||
end
|
||||
|
||||
def dfc_provider_routes
|
||||
DfcProvider::Engine.routes.url_helpers
|
||||
end
|
||||
|
||||
@@ -17,7 +17,6 @@ module DfcProvider
|
||||
dfc_provider_routes.enterprise_catalog_item_url(
|
||||
enterprise_id: object.product.supplier_id,
|
||||
id: object.id,
|
||||
host: host
|
||||
)
|
||||
end
|
||||
|
||||
@@ -44,7 +43,6 @@ module DfcProvider
|
||||
dfc_provider_routes.enterprise_supplied_product_url(
|
||||
enterprise_id: object.product.supplier_id,
|
||||
id: object.id,
|
||||
host: host
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,7 +18,6 @@ module DfcProvider
|
||||
def id
|
||||
dfc_provider_routes.enterprise_url(
|
||||
id: object.id,
|
||||
host: host
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ module DfcProvider
|
||||
def id
|
||||
dfc_provider_routes.person_url(
|
||||
id: object.id,
|
||||
host: host
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ module DfcProvider
|
||||
dfc_provider_routes.enterprise_supplied_product_url(
|
||||
enterprise_id: object.product.supplier_id,
|
||||
id: object.id,
|
||||
host: host
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/preset-env": "^7.18.2",
|
||||
"@floating-ui/dom": "^1.2.1",
|
||||
"@floating-ui/dom": "^1.2.4",
|
||||
"@hotwired/turbo": "^7.3.0",
|
||||
"@rails/webpacker": "5.4.4",
|
||||
"babel-loader": "^8.2.3",
|
||||
|
||||
@@ -1,89 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
module Admin
|
||||
describe ManagerInvitationsController, type: :controller do
|
||||
include OpenFoodNetwork::EmailHelper
|
||||
|
||||
let!(:enterprise_owner) { create(:user) }
|
||||
let!(:other_enterprise_user) { create(:user) }
|
||||
let!(:existing_user) { create(:user) }
|
||||
let!(:enterprise) { create(:enterprise, owner: enterprise_owner ) }
|
||||
let!(:enterprise2) { create(:enterprise, owner: other_enterprise_user ) }
|
||||
let(:admin) { create(:admin_user) }
|
||||
|
||||
describe "#create" do
|
||||
context "when given email matches an existing user" do
|
||||
before do
|
||||
allow(controller).to receive_messages spree_current_user: admin
|
||||
end
|
||||
|
||||
it "returns an error" do
|
||||
spree_post :create, email: existing_user.email, enterprise_id: enterprise.id
|
||||
|
||||
expect(response.status).to eq 422
|
||||
expect(json_response['errors']).to eq 'User already exists'
|
||||
end
|
||||
end
|
||||
|
||||
context "signing up a new user" do
|
||||
let(:mail_mock) { double(:mailer, deliver_later: true) }
|
||||
|
||||
before do
|
||||
allow(EnterpriseMailer).to receive(:manager_invitation).
|
||||
with(enterprise, kind_of(Spree::User)) { mail_mock }
|
||||
|
||||
allow(controller).to receive_messages spree_current_user: admin
|
||||
end
|
||||
|
||||
it 'enqueues an invitation email' do
|
||||
expect(mail_mock).to receive(:deliver_later)
|
||||
|
||||
spree_post :create, email: 'un.registered@email.com', enterprise_id: enterprise.id
|
||||
end
|
||||
|
||||
it "returns the user id" do
|
||||
spree_post :create, email: 'un.registered@email.com', enterprise_id: enterprise.id
|
||||
|
||||
new_user = Spree::User.find_by(email: 'un.registered@email.com')
|
||||
expect(json_response['user']).to eq new_user.id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "with enterprise permissions" do
|
||||
context "as user with proper enterprise permissions" do
|
||||
before do
|
||||
setup_email
|
||||
allow(controller).to receive_messages spree_current_user: enterprise_owner
|
||||
end
|
||||
|
||||
it "returns success code" do
|
||||
spree_post :create, email: 'an@email.com', enterprise_id: enterprise.id
|
||||
|
||||
new_user = Spree::User.find_by(email: 'an@email.com')
|
||||
|
||||
expect(new_user.reset_password_token).to_not be_nil
|
||||
expect(json_response['user']).to eq new_user.id
|
||||
expect(response.status).to eq 200
|
||||
end
|
||||
end
|
||||
|
||||
context "as another enterprise user without permissions for this enterprise" do
|
||||
before do
|
||||
allow(controller).to receive_messages spree_current_user: other_enterprise_user
|
||||
end
|
||||
|
||||
it "returns unauthorized response" do
|
||||
spree_post :create, email: 'another@email.com', enterprise_id: enterprise.id
|
||||
|
||||
new_user = Spree::User.find_by(email: 'another@email.com')
|
||||
|
||||
expect(new_user).to be_nil
|
||||
expect(response.status).to eq 302
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -212,6 +212,34 @@ module Admin
|
||||
before { controller_login_as_enterprise_user([coordinator]) }
|
||||
let(:params) { { format: :json, id: order_cycle.id, order_cycle: {} } }
|
||||
|
||||
context "when order cycle has subscriptions" do
|
||||
let(:coordinator) { order_cycle.coordinator }
|
||||
let(:producer) { create(:supplier_enterprise) }
|
||||
let!(:schedule) { create(:schedule, order_cycles: [order_cycle]) }
|
||||
let!(:p) { create(:product) }
|
||||
let!(:v) { p.variants.first }
|
||||
let!(:incoming_exchange) {
|
||||
create(:exchange, order_cycle: order_cycle, sender: producer, receiver: coordinator,
|
||||
incoming: true, variants: [v])
|
||||
}
|
||||
let!(:outgoing_exchange) {
|
||||
create(:exchange, order_cycle: order_cycle, sender: coordinator, receiver: coordinator,
|
||||
incoming: false, variants: [v])
|
||||
}
|
||||
let!(:subscription) { create(:subscription, shop: coordinator, schedule: schedule) }
|
||||
let!(:subscription_line_item) { create(:subscription_line_item, subscription: subscription, variant: v) }
|
||||
|
||||
before do
|
||||
allow(form_mock).to receive(:save) { true }
|
||||
v.destroy
|
||||
end
|
||||
|
||||
it "can update order cycle even if the variant has been deleted" do
|
||||
spree_put :update, { format: :json, id: order_cycle.id, order_cycle: {} }
|
||||
expect(response.status).to eq 200
|
||||
end
|
||||
end
|
||||
|
||||
context "when updating succeeds" do
|
||||
before { allow(form_mock).to receive(:save) { true } }
|
||||
|
||||
|
||||
5
spec/fixtures/reports/sales_tax_by_order/sales_tax_by_order.csv
vendored
Normal file
5
spec/fixtures/reports/sales_tax_by_order/sales_tax_by_order.csv
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
Distributor,Order Cycle,Order number,Tax Category,Tax Rate Name,Tax Rate,Total excl. tax ($),Tax,Total incl. tax ($),First Name,Last Name,Code,Email
|
||||
Distributor,oc1,ORDER_NUMBER_1,tax_category,State,0.015,115.0,1.73,116.73,cfname,clname,ABC123,order1@example.com
|
||||
Distributor,oc1,ORDER_NUMBER_1,tax_category,Country,0.025,115.0,2.88,117.88,cfname,clname,ABC123,order1@example.com
|
||||
Distributor,oc1,ORDER_NUMBER_2,tax_category,State,0.015,215.0,3.23,218.23,c2fname,c2lname,DEF456,order2@example.com
|
||||
Distributor,oc1,ORDER_NUMBER_2,tax_category,Country,0.025,215.0,5.38,220.38,c2fname,c2lname,DEF456,order2@example.com
|
||||
|
BIN
spec/fixtures/reports/sales_tax_by_order/sales_tax_by_order.xlsx
vendored
Normal file
BIN
spec/fixtures/reports/sales_tax_by_order/sales_tax_by_order.xlsx
vendored
Normal file
Binary file not shown.
@@ -5,7 +5,7 @@ require 'spec_helper'
|
||||
describe Enterprise do
|
||||
context "key-based caching invalidation" do
|
||||
describe "is touched when a(n)" do
|
||||
let(:enterprise) { create(:distributor_enterprise, updated_at: Time.zone.now - 1.week) }
|
||||
let(:enterprise) { create(:distributor_enterprise) }
|
||||
let(:taxon) { create(:taxon) }
|
||||
let(:supplier2) { create(:supplier_enterprise) }
|
||||
|
||||
@@ -22,30 +22,26 @@ describe Enterprise do
|
||||
|
||||
it "touches enterprise when a classification on that product changes" do
|
||||
expect {
|
||||
classification.save!
|
||||
enterprise.reload
|
||||
}.to change { enterprise.updated_at }
|
||||
later { classification.touch }
|
||||
}.to change { enterprise.reload.updated_at }
|
||||
end
|
||||
|
||||
it "touches enterprise when a property on that product changes" do
|
||||
expect {
|
||||
property.save!
|
||||
enterprise.reload
|
||||
}.to change { enterprise.updated_at }
|
||||
later { property.touch }
|
||||
}.to change { enterprise.reload.updated_at }
|
||||
end
|
||||
|
||||
it "touches enterprise when a producer property on that product changes" do
|
||||
expect {
|
||||
producer_property.save!
|
||||
enterprise.reload
|
||||
}.to change { enterprise.updated_at }
|
||||
later { producer_property.touch }
|
||||
}.to change { enterprise.reload.updated_at }
|
||||
end
|
||||
|
||||
it "touches enterprise when the supplier of a product changes" do
|
||||
expect {
|
||||
product.update!(supplier: supplier2)
|
||||
enterprise.reload
|
||||
}.to change { enterprise.updated_at }
|
||||
later { product.update!(supplier: supplier2) }
|
||||
}.to change { enterprise.reload.updated_at }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -70,45 +66,39 @@ describe Enterprise do
|
||||
|
||||
it "touches enterprise when a classification on that product changes" do
|
||||
expect {
|
||||
classification.save!
|
||||
enterprise.reload
|
||||
}.to change { enterprise.updated_at }
|
||||
later { classification.touch }
|
||||
}.to change { enterprise.reload.updated_at }
|
||||
end
|
||||
|
||||
it "touches enterprise when a property on that product changes" do
|
||||
expect {
|
||||
property.save!
|
||||
enterprise.reload
|
||||
}.to change { enterprise.updated_at }
|
||||
later { property.touch }
|
||||
}.to change { enterprise.reload.updated_at }
|
||||
end
|
||||
|
||||
it "touches enterprise when a producer property on that product changes" do
|
||||
expect {
|
||||
producer_property.save!
|
||||
enterprise.reload
|
||||
}.to change { enterprise.updated_at }
|
||||
later { producer_property.touch }
|
||||
}.to change { enterprise.reload.updated_at }
|
||||
end
|
||||
|
||||
it "touches enterprise when the supplier of a product changes" do
|
||||
expect {
|
||||
product.update!(supplier: supplier2)
|
||||
enterprise.reload
|
||||
}.to change { enterprise.updated_at }
|
||||
later { product.update!(supplier: supplier2) }
|
||||
}.to change { enterprise.reload.updated_at }
|
||||
end
|
||||
|
||||
it "touches enterprise when a relevant exchange is updated" do
|
||||
expect {
|
||||
oc.exchanges.first.update!(updated_at: Time.zone.now)
|
||||
enterprise.reload
|
||||
}.to change { enterprise.updated_at }
|
||||
later { oc.exchanges.first.update!(updated_at: Time.zone.now) }
|
||||
}.to change { enterprise.reload.updated_at }
|
||||
end
|
||||
end
|
||||
|
||||
it "touches enterprise when the product's variant is added to order cycle" do
|
||||
expect {
|
||||
oc
|
||||
enterprise.reload
|
||||
}.to change { enterprise.updated_at }
|
||||
later { oc }
|
||||
}.to change { enterprise.reload.updated_at }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -118,9 +108,8 @@ describe Enterprise do
|
||||
|
||||
it "touches enterprise when enterprise relationship is updated" do
|
||||
expect {
|
||||
er.save!
|
||||
enterprise.reload
|
||||
}.to change { enterprise.updated_at }
|
||||
later { er.touch }
|
||||
}.to change { enterprise.reload.updated_at }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -133,25 +122,26 @@ describe Enterprise do
|
||||
|
||||
it "touches enterprise when distributor_shipping_method is updated" do
|
||||
expect {
|
||||
enterprise.distributor_shipping_methods.first.save!
|
||||
enterprise.reload
|
||||
}.to change { enterprise.updated_at }
|
||||
later { enterprise.distributor_shipping_methods.first.touch }
|
||||
}.to change { enterprise.reload.updated_at }
|
||||
end
|
||||
|
||||
it "touches enterprise when shipping method is updated" do
|
||||
expect {
|
||||
sm.save!
|
||||
enterprise.reload
|
||||
}.to change { enterprise.updated_at }
|
||||
later { sm.save! }
|
||||
}.to change { enterprise.reload.updated_at }
|
||||
end
|
||||
end
|
||||
|
||||
it "touches enterprise when address is updated" do
|
||||
expect {
|
||||
enterprise.address.save!
|
||||
enterprise.reload
|
||||
}.to change { enterprise.updated_at }
|
||||
later { enterprise.address.save! }
|
||||
}.to change { enterprise.reload.updated_at }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def later(&block)
|
||||
Timecop.travel(1.day.from_now, &block)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -43,6 +43,10 @@ describe ProductImport::ProductImporter do
|
||||
create(:variant, product_id: product.id, price: '8.50', on_hand: '100', unit_value: '500',
|
||||
display_name: 'Preexisting Banana')
|
||||
}
|
||||
let!(:variant_with_empty_display_name) {
|
||||
create(:variant, product_id: product.id, price: '8.50', on_hand: '100', unit_value: '500',
|
||||
display_name: '')
|
||||
}
|
||||
let!(:product2) {
|
||||
create(:simple_product, supplier: enterprise, on_hand: '100', name: 'Beans', unit_value: '500',
|
||||
primary_taxon_id: category.id, description: nil)
|
||||
@@ -377,6 +381,28 @@ describe ProductImport::ProductImporter do
|
||||
end
|
||||
end
|
||||
|
||||
describe "updating variant having an nil display name with CSV with empty display name" do
|
||||
let(:csv_data) {
|
||||
CSV.generate do |csv|
|
||||
csv << ["name", "producer", "category", "on_hand", "price", "units", "unit_type",
|
||||
"display_name", "shipping_category"]
|
||||
csv << ["Hypothetical Cake", enterprise2.name, "Cake", "5", "5.50", "1", "g",
|
||||
"", shipping_category.name]
|
||||
end
|
||||
}
|
||||
let(:importer) { import_data csv_data }
|
||||
|
||||
it "consider both existing and imported as the same and should be then updated" do
|
||||
importer.validate_entries
|
||||
entries = JSON.parse(importer.entries_json)
|
||||
|
||||
expect(filter('valid', entries)).to eq 1
|
||||
expect(filter('invalid', entries)).to eq 0
|
||||
expect(filter('create_product', entries)).to eq 0
|
||||
expect(filter('update_product', entries)).to eq 1
|
||||
end
|
||||
end
|
||||
|
||||
describe "adding new product and sub-variant at the same time" do
|
||||
let(:csv_data) {
|
||||
CSV.generate do |csv|
|
||||
|
||||
@@ -309,7 +309,7 @@ module Spree
|
||||
it "defaults available_on to now" do
|
||||
Timecop.freeze do
|
||||
product = Product.new
|
||||
expect(product.available_on).to eq(Time.zone.now)
|
||||
expect(product.available_on).to be_within(0.000001).of(Time.zone.now)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -271,7 +271,7 @@ describe OrderCycleForm do
|
||||
create(:admin_user)
|
||||
)
|
||||
|
||||
expect{ form.save }.to change{ order_cycle.distributor_payment_methods.pluck(:id) }
|
||||
expect{ form.save }.to change{ order_cycle.distributor_payment_methods.pluck(:id).sort }
|
||||
.from([distributor_payment_method, distributor_payment_method2])
|
||||
.to([distributor_payment_method2])
|
||||
end
|
||||
@@ -288,8 +288,10 @@ describe OrderCycleForm do
|
||||
distributor.users.first
|
||||
)
|
||||
|
||||
expect{ form.save }.to change{ order_cycle.distributor_payment_methods.pluck(:id) }
|
||||
.from([distributor_payment_method, distributor_payment_method2])
|
||||
expect{ form.save }.to change{
|
||||
order_cycle.distributor_payment_methods.pluck(:id).sort
|
||||
}
|
||||
.from([distributor_payment_method, distributor_payment_method2].sort)
|
||||
.to([distributor_payment_method])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -737,6 +737,7 @@ describe '
|
||||
completed_at: Time.zone.now )
|
||||
}
|
||||
let!(:li1) { create(:line_item_with_shipment, order: o1 ) }
|
||||
let!(:li11) { create(:line_item_with_shipment, order: o1 ) }
|
||||
let!(:li2) { create(:line_item_with_shipment, order: o2 ) }
|
||||
|
||||
before :each do
|
||||
@@ -770,27 +771,58 @@ describe '
|
||||
end
|
||||
|
||||
context "performing actions" do
|
||||
it "deletes selected items" do
|
||||
expect(page).to have_selector "tr#li_#{li1.id}"
|
||||
expect(page).to have_selector "tr#li_#{li2.id}"
|
||||
within("tr#li_#{li2.id} td.bulk") do
|
||||
check "bulk"
|
||||
context "deletes selected items" do
|
||||
it "displays a confirmation dialog when deleting one or more items leads to order cancelation" do
|
||||
expect(page).to have_selector "tr#li_#{li1.id}"
|
||||
expect(page).to have_selector "tr#li_#{li11.id}"
|
||||
within("tr#li_#{li1.id} td.bulk") do
|
||||
check "bulk"
|
||||
end
|
||||
within("tr#li_#{li11.id} td.bulk") do
|
||||
check "bulk"
|
||||
end
|
||||
|
||||
find("div#bulk-actions-dropdown").click
|
||||
find("div#bulk-actions-dropdown div.menu_item", text: "Delete Selected" ).click
|
||||
|
||||
expect(page).to have_content "This operation will result in one or more empty orders, which will be cancelled. Do you wish to proceed?"
|
||||
|
||||
expect do
|
||||
within(".modal") do
|
||||
check("send_cancellation_email")
|
||||
click_on("OK")
|
||||
end
|
||||
# order 1 should be canceled
|
||||
expect(page).to have_no_selector "tr#li_#{li1.id}"
|
||||
expect(page).to have_no_selector "tr#li_#{li11.id}"
|
||||
expect(o1.reload.state).to eq("canceled")
|
||||
# order 2 should not be canceled
|
||||
expect(page).to have_selector "tr#li_#{li2.id}"
|
||||
expect(o2.reload.state).to eq("complete")
|
||||
end.to have_enqueued_mail(Spree::OrderMailer, :cancel_email)
|
||||
end
|
||||
|
||||
find("div#bulk-actions-dropdown").click
|
||||
find("div#bulk-actions-dropdown div.menu_item", text: "Delete Selected" ).click
|
||||
|
||||
expect(page).to have_content "This operation will result in one or more empty orders, which will be cancelled. Do you wish to proceed?"
|
||||
|
||||
expect do
|
||||
within(".modal") do
|
||||
check("send_cancellation_email")
|
||||
click_on("OK")
|
||||
end
|
||||
it "deletes one line item should show modal confirmation about this line item deletion and not about order cancelation" do
|
||||
expect(page).to have_selector "tr#li_#{li1.id}"
|
||||
expect(page).to have_no_selector "tr#li_#{li2.id}"
|
||||
expect(o2.reload.state).to eq("canceled")
|
||||
end.to have_enqueued_mail(Spree::OrderMailer, :cancel_email)
|
||||
within("tr#li_#{li1.id} td.bulk") do
|
||||
check "bulk"
|
||||
end
|
||||
|
||||
find("div#bulk-actions-dropdown").click
|
||||
find("div#bulk-actions-dropdown div.menu_item", text: "Delete Selected" ).click
|
||||
|
||||
within ".modal" do
|
||||
expect(page).to have_content "This will delete one line item from the order. Are you sure you want to proceed?"
|
||||
click_on "OK"
|
||||
end
|
||||
|
||||
expect(page).to have_content "Loading orders"
|
||||
|
||||
expect(page).to have_no_selector ".modal"
|
||||
expect(page).to have_no_selector "tr#li_#{li1.id}"
|
||||
expect(page).to have_selector "tr#li_#{li11.id}"
|
||||
expect(o1.reload.state).to eq("complete")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -532,5 +532,57 @@ describe '
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "check users tab" do
|
||||
before do
|
||||
login_as_admin_and_visit edit_admin_enterprise_path(distributor1)
|
||||
within ".side_menu" do
|
||||
click_link 'Users'
|
||||
end
|
||||
end
|
||||
|
||||
context "invite user as manager" do
|
||||
before do
|
||||
expect(page).to have_selector('a', text: /Add an unregistered user/i)
|
||||
page.find('a', text: /Add an unregistered user/i).click
|
||||
end
|
||||
|
||||
it "shows an error message if the email is invalid" do
|
||||
within ".reveal-modal" do
|
||||
expect(page).to have_content "Invite an unregistered user"
|
||||
fill_in "email", with: "invalid_email"
|
||||
|
||||
expect do
|
||||
click_button "Invite"
|
||||
expect(page).to have_content "Email is invalid"
|
||||
end.to_not enqueue_job ActionMailer::MailDeliveryJob
|
||||
end
|
||||
end
|
||||
|
||||
it "shows an error message if the email is already linked to an existing user" do
|
||||
within ".reveal-modal" do
|
||||
expect(page).to have_content "Invite an unregistered user"
|
||||
fill_in "email", with: distributor1.owner.email
|
||||
|
||||
expect do
|
||||
click_button "Invite"
|
||||
expect(page).to have_content "User already exists"
|
||||
end.to_not enqueue_job ActionMailer::MailDeliveryJob
|
||||
end
|
||||
end
|
||||
|
||||
it "finally, can invite unregistered users" do
|
||||
within ".reveal-modal" do
|
||||
expect(page).to have_content "Invite an unregistered user"
|
||||
fill_in "email", with: "email@email.com"
|
||||
|
||||
expect do
|
||||
click_button "Invite"
|
||||
expect(page).to have_content "email@email.com has been invited to manage this enterprise"
|
||||
end.to enqueue_job(ActionMailer::MailDeliveryJob).exactly(:twice)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -105,7 +105,7 @@ describe "Sales Tax Totals By order" do
|
||||
it "generates the report" do
|
||||
login_as admin
|
||||
visit admin_reports_path
|
||||
click_on I18n.t("admin.reports.sales_tax_totals_by_order")
|
||||
click_on "Sales Tax Totals By Order"
|
||||
|
||||
expect(page).to have_button("Go")
|
||||
click_on "Go"
|
||||
@@ -167,7 +167,7 @@ describe "Sales Tax Totals By order" do
|
||||
it "generates the report" do
|
||||
login_as admin
|
||||
visit admin_reports_path
|
||||
click_on I18n.t("admin.reports.sales_tax_totals_by_order")
|
||||
click_on "Sales Tax Totals By Order"
|
||||
|
||||
expect(page).to have_button("Go")
|
||||
click_on "Go"
|
||||
@@ -335,7 +335,7 @@ describe "Sales Tax Totals By order" do
|
||||
|
||||
login_as admin
|
||||
visit admin_reports_path
|
||||
click_on I18n.t("admin.reports.sales_tax_totals_by_order")
|
||||
click_on "Sales Tax Totals By Order"
|
||||
end
|
||||
|
||||
it "should load all the orders" do
|
||||
@@ -423,5 +423,58 @@ describe "Sales Tax Totals By order" do
|
||||
expect(page.find("table.report__table tbody").text).to have_content(customer2_summary_row)
|
||||
expect(page).to have_selector(table_raw_selector, count: 6)
|
||||
end
|
||||
|
||||
describe "downloading" do
|
||||
context "csv files" do
|
||||
let(:report_file_csv) do
|
||||
CSV.read("spec/fixtures/reports/sales_tax_by_order/sales_tax_by_order.csv")
|
||||
end
|
||||
|
||||
it 'downloads the file' do
|
||||
expect(downloaded_filenames.length).to eq(0) # downloads folder should be empty
|
||||
select "CSV", from: "report_format"
|
||||
click_on "Go"
|
||||
wait_for_download
|
||||
expect(downloaded_filenames.length).to eq(1) # downloads folder should contain 1 file
|
||||
expect(downloaded_filename).to match(/.*\.csv/)
|
||||
expect(CSV.read(downloaded_filename)).to eq(report_file_csv)
|
||||
end
|
||||
end
|
||||
|
||||
context "xlsx files" do
|
||||
let(:report_file_xlsx) do
|
||||
File.open("spec/fixtures/reports/sales_tax_by_order/sales_tax_by_order.xlsx")
|
||||
end
|
||||
|
||||
it 'downloads the file' do
|
||||
expect(downloaded_filenames.length).to eq(0) # downloads folder should be empty
|
||||
select "Spreadsheet", from: "report_format"
|
||||
find("#display_summary_row").uncheck
|
||||
click_on "Go"
|
||||
wait_for_download
|
||||
expect(downloaded_filenames.length).to eq(1) # downloads folder should contain 1 file
|
||||
expect(downloaded_filename).to match(/.*\.xlsx/)
|
||||
downloaded_content = extract_xlsx_rows(downloaded_filename, 1..5)
|
||||
fixture_content = extract_xlsx_rows(report_file_xlsx, 1..5)
|
||||
expect(downloaded_content).to eq(fixture_content)
|
||||
end
|
||||
|
||||
def extract_xlsx_rows(file, range)
|
||||
xlsx = Roo::Excelx.new(file)
|
||||
range.map { |i| xlsx.row(i) }
|
||||
end
|
||||
end
|
||||
|
||||
context "pdf files" do
|
||||
it 'downloads the file' do
|
||||
expect(downloaded_filenames.length).to eq(0) # downloads folder should be empty
|
||||
select "PDF", from: "report_format"
|
||||
click_on "Go"
|
||||
wait_for_download
|
||||
expect(downloaded_filenames.length).to eq(1) # downloads folder should contain 1 file
|
||||
expect(downloaded_filename).to match(/.*\.pdf/)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -458,6 +458,19 @@ describe "As a consumer, I want to checkout my order" do
|
||||
fill_notes("SpEcIaL NoTeS")
|
||||
proceed_to_payment
|
||||
end
|
||||
|
||||
context 'when the user has no shipping address' do
|
||||
before do
|
||||
# Hack so we can have "Shipping address same as billing address?" unticked
|
||||
choose free_shipping_with_required_address.name
|
||||
uncheck "Shipping address same as billing address?"
|
||||
choose free_shipping_without_required_address.name
|
||||
end
|
||||
|
||||
it "redirects the user to the Payment Method step" do
|
||||
proceed_to_payment
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "selecting a delivery method with a shipping fee" do
|
||||
@@ -793,6 +806,17 @@ describe "As a consumer, I want to checkout my order" do
|
||||
create(:order_ready_for_confirmation, distributor: distributor)
|
||||
}
|
||||
|
||||
describe "with an order with special instructions" do
|
||||
before do
|
||||
order.update_attribute(:special_instructions, "Please deliver on Tuesday")
|
||||
visit checkout_step_path(:summary)
|
||||
end
|
||||
|
||||
it "displays the special instructions" do
|
||||
expect(page).to have_content "Please deliver on Tuesday"
|
||||
end
|
||||
end
|
||||
|
||||
describe "completing the checkout" do
|
||||
it "keeps the distributor selected for the current user after completion" do
|
||||
visit checkout_step_path(:summary)
|
||||
|
||||
18
yarn.lock
18
yarn.lock
@@ -1397,17 +1397,17 @@
|
||||
resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7"
|
||||
integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==
|
||||
|
||||
"@floating-ui/core@^1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.2.1.tgz#074182a1d277f94569c50a6b456e62585d463c8e"
|
||||
integrity sha512-LSqwPZkK3rYfD7GKoIeExXOyYx6Q1O4iqZWwIehDNuv3Dv425FIAE8PRwtAx1imEolFTHgBEcoFHm9MDnYgPCg==
|
||||
"@floating-ui/core@^1.2.3":
|
||||
version "1.2.3"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.2.3.tgz#327a2c11e6570b7d64368ad74a3ac12786c9f751"
|
||||
integrity sha512-upVRtrNZuYNsw+EoxkiBFRPROnU8UTy/u/dZ9U0W14BlemPYODwhhxYXSR2Y9xOnvr1XtptJRWx7gL8Te1qaog==
|
||||
|
||||
"@floating-ui/dom@^1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.2.1.tgz#8f93906e1a3b9f606ce78afb058e874344dcbe07"
|
||||
integrity sha512-Rt45SmRiV8eU+xXSB9t0uMYiQ/ZWGE/jumse2o3i5RGlyvcbqOF4q+1qBnzLE2kZ5JGhq0iMkcGXUKbFe7MpTA==
|
||||
"@floating-ui/dom@^1.2.4":
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.2.4.tgz#e2eb2674f57fc182c425587e48ea43e336f4b8f8"
|
||||
integrity sha512-4+k+BLhtWj+peCU60gp0+rHeR8+Ohqx6kjJf/lHMnJ8JD5Qj6jytcq1+SZzRwD7rvHKRhR7TDiWWddrNrfwQLg==
|
||||
dependencies:
|
||||
"@floating-ui/core" "^1.2.1"
|
||||
"@floating-ui/core" "^1.2.3"
|
||||
|
||||
"@hotwired/stimulus-webpack-helpers@^1.0.0":
|
||||
version "1.0.1"
|
||||
|
||||
Reference in New Issue
Block a user