Compare commits

...

54 Commits

Author SHA1 Message Date
Jean-Baptiste Bellet
b17d3e447c Avoid using exception but simply errors attribute contained in object 2023-03-14 15:56:16 +01:00
Jean-Baptiste Bellet
2ae4234015 Sort each array to ensure the order
and then expect the right values.
2023-03-14 09:38:31 +01:00
binarygit
20874dec98 Replace angular for when adding a new unregistered manager to an enterprise
Co-Authored-By: David Cook <david@redcliffs.net>
2023-03-14 09:37:57 +01:00
Jean-Baptiste Bellet
288cd367bc Add I18N to all reflexes 2023-03-13 21:12:00 +01:00
Jean-Baptiste Bellet
68902021ab Delete manager invitation controller 2023-03-13 21:12:00 +01:00
Jean-Baptiste Bellet
7f9c578fca Create a concern for manager invitations
Can be used elsewhere
2023-03-13 21:12:00 +01:00
Jean-Baptiste Bellet
782c9150a2 Move $locationProvider configuration to another file
Actually the `config()` method of `admin_ofn` file did not run on `/admin/enterprises/*` pages for an unknown reason

Now those two files have the same configuration
2023-03-13 21:12:00 +01:00
binarygit
447b040020 Replace what's this tooltips
There are tooltips here that don't have a what's this?
There are many angular directives/methods being used that I haven't
looked into
Every select box is using select2
2023-03-13 21:12:00 +01:00
jibees
6bdb89d090 Merge pull request #10551 from openfoodfoundation/dependabot/bundler/rubocop-1.48.1
Bump rubocop from 1.48.0 to 1.48.1
2023-03-13 16:16:56 +01:00
jibees
a63531c8c2 Merge pull request #10549 from openfoodfoundation/dependabot/bundler/ddtrace-1.10.1
Bump ddtrace from 1.10.0 to 1.10.1
2023-03-13 16:15:06 +01:00
jibees
de2a15e3e1 Merge pull request #10548 from openfoodfoundation/dependabot/npm_and_yarn/floating-ui/dom-1.2.4
Bump @floating-ui/dom from 1.2.3 to 1.2.4
2023-03-13 16:14:00 +01:00
dependabot[bot]
e5f5d42d59 Bump rubocop from 1.48.0 to 1.48.1
Bumps [rubocop](https://github.com/rubocop/rubocop) from 1.48.0 to 1.48.1.
- [Release notes](https://github.com/rubocop/rubocop/releases)
- [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop/compare/v1.48.0...v1.48.1)

---
updated-dependencies:
- dependency-name: rubocop
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-13 10:05:22 +00:00
dependabot[bot]
f23de206d9 Bump ddtrace from 1.10.0 to 1.10.1
Bumps [ddtrace](https://github.com/DataDog/dd-trace-rb) from 1.10.0 to 1.10.1.
- [Release notes](https://github.com/DataDog/dd-trace-rb/releases)
- [Changelog](https://github.com/DataDog/dd-trace-rb/blob/master/CHANGELOG.md)
- [Commits](https://github.com/DataDog/dd-trace-rb/compare/v1.10.0...v1.10.1)

---
updated-dependencies:
- dependency-name: ddtrace
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-13 10:03:01 +00:00
dependabot[bot]
729bcdf291 Bump @floating-ui/dom from 1.2.3 to 1.2.4
Bumps [@floating-ui/dom](https://github.com/floating-ui/floating-ui/tree/HEAD/packages/dom) from 1.2.3 to 1.2.4.
- [Release notes](https://github.com/floating-ui/floating-ui/releases)
- [Commits](https://github.com/floating-ui/floating-ui/commits/@floating-ui/dom@1.2.4/packages/dom)

---
updated-dependencies:
- dependency-name: "@floating-ui/dom"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-13 09:58:49 +00:00
Maikel Linke
62d0ce290a Update translations 2023-03-10 11:42:36 +11:00
jibees
96ead52fcc Merge pull request #10536 from openfoodfoundation/dependabot/bundler/rack-2.2.6.3
Bump rack from 2.2.6.2 to 2.2.6.3
2023-03-09 14:55:19 +01:00
dependabot[bot]
ff708952ab Bump rack from 2.2.6.2 to 2.2.6.3
Bumps [rack](https://github.com/rack/rack) from 2.2.6.2 to 2.2.6.3.
- [Release notes](https://github.com/rack/rack/releases)
- [Changelog](https://github.com/rack/rack/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rack/rack/compare/v2.2.6.2...v2.2.6.3)

---
updated-dependencies:
- dependency-name: rack
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-09 02:40:19 +00:00
Konrad
2daa49406a Merge pull request #10506 from jibees/9868-product-import-empty-variant-names-recorded-differently-leads-to-variant-duplication
Product import: consider `display_name` with `null` or `empty` as value as equal
2023-03-08 16:58:32 +01:00
Konrad
125bc3d14b Merge pull request #10514 from jibees/9292-changes-to-incomingoutgoing-products-lists-triggering-failed-to-update-order-cycle-error
Do not update `estimate_price` of a variant that is not available for the shop on OrderCycle update
2023-03-08 15:45:11 +01:00
Rachel Arnould
02300d6bb6 Merge pull request #10496 from rioug/10479-split-checkout-fix-user-blocked-at-step1
[split checkout] Fix bug preventing user from reaching payment step
2023-03-08 15:44:50 +01:00
Rachel Arnould
aba3968bca Merge pull request #10447 from jibees/9148-no-bulk-delete-possible-on-bom-when-orders-have-multiple-items
Admin, BOM: can bulk delete line items of an order
2023-03-08 14:56:25 +01:00
Gaetan Craig-Riou
23c4298519 Fix bug when in specific scenario user couldn't proceed to payment step
When using a "pick up" shipping method, with a user who doesn't have a shipping address it was impossible to proceed to the payment step because shipping address was invalid.

To fix this, we ensure that "ship_address_same_as_billing" parameter is set to true when using a "pick up" shipping method.

use distributor address when shipping method doesn't require a ship address ; in doing this we follow the same logic as the legacy checkout
2023-03-08 10:49:37 +01:00
Rachel Arnould
d7047bb4cc Merge pull request #10513 from jibees/10505-add-shopper-comment-to-order-detail-summary
SplitCheckout: Display special_instructions of the order as emphasized text if present on summary page
2023-03-08 10:30:40 +01:00
Rachel Arnould
1ce029d8e4 Merge pull request #10497 from jibees/10495-split-checkout-label-of-checkbox-save-card-for-future-use-is-clickable-but-not-active
SplitCheckout: Make label clickable to check/uncheck checkbox on step 2
2023-03-08 10:20:00 +01:00
jibees
eb7d20d74d Merge pull request #10530 from mkllnk/flaky-service-spec
Stabilise spec with deterministic order
2023-03-08 09:04:29 +01:00
Maikel Linke
c4ba1e6616 Stabilise spec with deterministic order
The ids were returned in random order before.
2023-03-08 13:14:40 +11:00
Maikel
f97ccb4203 Merge pull request #10525 from openfoodfoundation/dependabot/bundler/ddtrace-1.10.0
Bump ddtrace from 1.9.0 to 1.10.0
2023-03-08 12:09:04 +11:00
Maikel
df8283661d Merge pull request #10487 from mkllnk/time-spec
Prepare caching spec for Rails 7
2023-03-08 11:37:44 +11:00
Maikel
d9ee56b4a5 Merge pull request #10524 from mkllnk/dfc-urls
Configure host for dfc_provider engine globally
2023-03-08 11:13:48 +11:00
dependabot[bot]
2230a1f179 Bump ddtrace from 1.9.0 to 1.10.0
Bumps [ddtrace](https://github.com/DataDog/dd-trace-rb) from 1.9.0 to 1.10.0.
- [Release notes](https://github.com/DataDog/dd-trace-rb/releases)
- [Changelog](https://github.com/DataDog/dd-trace-rb/blob/master/CHANGELOG.md)
- [Commits](https://github.com/DataDog/dd-trace-rb/compare/v1.9.0...v1.10.0)

---
updated-dependencies:
- dependency-name: ddtrace
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-07 09:58:38 +00:00
Maikel Linke
a9c8d9f304 Configure host for dfc_provider engine globally
Passing the parameter all the time was pretty inconvenient.
2023-03-07 16:39:02 +11:00
Jean-Baptiste Bellet
a7644f8e8b Update spec: can edit OC even if variant in subscription has been deleted 2023-03-06 17:12:09 +01:00
jibees
5dd2737811 Merge pull request #10517 from openfoodfoundation/dependabot/bundler/rubocop-1.48.0
Bump rubocop from 1.47.0 to 1.48.0
2023-03-06 15:23:25 +01:00
Jean-Baptiste Bellet
d9b534b829 + update spec as well 2023-03-06 14:52:32 +01:00
dependabot[bot]
a78768c291 Bump rubocop from 1.47.0 to 1.48.0
Bumps [rubocop](https://github.com/rubocop/rubocop) from 1.47.0 to 1.48.0.
- [Release notes](https://github.com/rubocop/rubocop/releases)
- [Changelog](https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop/rubocop/compare/v1.47.0...v1.48.0)

---
updated-dependencies:
- dependency-name: rubocop
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-06 10:02:43 +00:00
Maikel
b9a7ff903f Merge pull request #10494 from filipefurtad0/test_xlsx_reports
Adds coverage for CSV and XLSX file download
2023-03-06 15:00:56 +11:00
Maikel
fc6b61fc87 Merge pull request #10503 from openfoodfoundation/dependabot/npm_and_yarn/floating-ui/dom-1.2.3
Bump @floating-ui/dom from 1.2.1 to 1.2.3
2023-03-06 11:52:38 +11:00
Jean-Baptiste Bellet
131772f7b2 Variant can be "not available": next and don't update its estimate price 2023-03-03 15:07:10 +01:00
Jean-Baptiste Bellet
440e776e3a fee_calculator can be retrieved outside subscription_line_items iteration 2023-03-03 15:05:07 +01:00
filipefurtad0
56b9c28955 Splits test cases into respective context blocks
Reduces code
2023-03-03 11:39:03 +00:00
Jean-Baptiste Bellet
c34942dbf0 Display special_instructions of order as emphasized text if present
+ update spec as well
2023-03-03 11:12:11 +01:00
Maikel Linke
12906d1e13 Explicitely touch instead of noop save
When calling `save!` without changing any attributes then Rails doesn't
always touch other records because nothing changed. So I changed the
spec to `touch` explicitely and it turns out that everything passes.

Tada, our code seems correct and it was only the spec which seemed
broken in Rails 7.
2023-03-03 12:51:12 +11:00
Maikel Linke
103bc50bdc Make spec robust on very fast computers
I didn't observe it but if the spec code would run within the same
millisecond then we wouldn't be able to observe a change to
`updated_at`. Time travel solves this potential problem.
2023-03-03 12:51:12 +11:00
Maikel Linke
b6cccc2e1d Mark broken specs, possible broken caching
I found this because Rails 7 converts timestamps to database precision
straight away. While we may have some broken logic in the code, most of
these cases may just be broken spec code. Watch this space.
2023-03-03 12:34:55 +11:00
Maikel Linke
918e583d01 Account for Rails 7 rounding in time spec
Storing a timestamp to the database has less accuracy than a Ruby Time
object. So `updated_at` changes after being written and loaded from the
database. Rails 7 accounts for that by rounding it in the model already
before it's written to the database. That made one spec fail.
2023-03-03 12:34:55 +11:00
Jean-Baptiste Bellet
7b8ccccdc3 display_name can actually be null or empty: consider them as equal 2023-03-02 17:15:57 +01:00
dependabot[bot]
0cae069769 Bump @floating-ui/dom from 1.2.1 to 1.2.3
Bumps [@floating-ui/dom](https://github.com/floating-ui/floating-ui/tree/HEAD/packages/dom) from 1.2.1 to 1.2.3.
- [Release notes](https://github.com/floating-ui/floating-ui/releases)
- [Commits](https://github.com/floating-ui/floating-ui/commits/@floating-ui/dom@1.2.3/packages/dom)

---
updated-dependencies:
- dependency-name: "@floating-ui/dom"
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-03-02 12:45:36 +00:00
filipefurtad0
b99383185b Adds coverage for PDF file download 2023-03-01 14:32:35 +00:00
filipefurtad0
66485e2e16 Adds coverage for XLSX file download 2023-03-01 14:32:35 +00:00
filipefurtad0
c1b60d88d6 Adds coverage for CSV file download 2023-03-01 14:32:28 +00:00
Jean-Baptiste Bellet
08e23023b3 Make label clickable to check/uncheck checkbox 2023-03-01 08:46:33 +01:00
Jean-Baptiste Bellet
c83dac58a3 Confirm line items deletion that doesn't trigger an order cancelation 2023-02-27 11:09:59 +01:00
Jean-Baptiste Bellet
e5ca8b0ee1 Delete selected line items even if does not lead to order cancellation 2023-02-15 11:49:53 +01:00
Jean-Baptiste Bellet
cf8d9c6d07 Improve spec when deleting all items of an order
- Order1 has two line items
 - Check other Order2 does not change its state
 - Prepare context for the second spec: delete one line item of an order that does not trigger any order cancellation
2023-02-15 11:38:04 +01:00
41 changed files with 496 additions and 289 deletions

View File

@@ -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'

View File

@@ -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)

View File

@@ -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")

View File

@@ -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) ->

View File

@@ -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")}

View File

@@ -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, */*"

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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')}"

View File

@@ -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 }

View File

@@ -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

View File

@@ -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')

View File

@@ -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'))

View File

@@ -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..."

View File

@@ -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"

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -18,7 +18,6 @@ module DfcProvider
def id
dfc_provider_routes.enterprise_url(
id: object.id,
host: host
)
end

View File

@@ -30,7 +30,6 @@ module DfcProvider
def id
dfc_provider_routes.person_url(
id: object.id,
host: host
)
end

View File

@@ -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

View File

@@ -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",

View File

@@ -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

View File

@@ -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 } }

View 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
1 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
2 Distributor oc1 ORDER_NUMBER_1 tax_category State 0.015 115.0 1.73 116.73 cfname clname ABC123 order1@example.com
3 Distributor oc1 ORDER_NUMBER_1 tax_category Country 0.025 115.0 2.88 117.88 cfname clname ABC123 order1@example.com
4 Distributor oc1 ORDER_NUMBER_2 tax_category State 0.015 215.0 3.23 218.23 c2fname c2lname DEF456 order2@example.com
5 Distributor oc1 ORDER_NUMBER_2 tax_category Country 0.025 215.0 5.38 220.38 c2fname c2lname DEF456 order2@example.com

Binary file not shown.

View File

@@ -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

View File

@@ -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|

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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)

View File

@@ -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"