Compare commits

...

80 Commits

Author SHA1 Message Date
Luis Ramos
9fd8613107 Update all locales with the latest Transifex translations 2020-08-21 14:56:26 +01:00
Luis Ramos
bea8c2035f Merge pull request #5909 from openfoodfoundation/transifex
Transifex
2020-08-21 14:54:49 +01:00
Luis Ramos
e616e32bbc Merge pull request #5931 from Matt-Yorkley/customer-totals-fees
Customer totals fee calculations
2020-08-21 14:09:00 +01:00
Luis Ramos
19b5a004dd Merge pull request #5877 from Matt-Yorkley/bugsnagger
BugsnagJS checkout errors
2020-08-21 14:01:48 +01:00
Luis Ramos
4a5a6a2242 Merge pull request #5906 from Matt-Yorkley/checkout_flash_errors
Fix flash error issues in checkout requests
2020-08-21 13:03:30 +01:00
Luis Ramos
d1b60e3778 Merge pull request #5905 from mkllnk/lost-decorators
Load previously lost decorator code and don't delete orders
2020-08-21 12:34:37 +01:00
Maikel
31fe8850b5 Merge pull request #5913 from openfoodfoundation/luisramos0-patch-1
Remove spree upgrade section from the PR template ❤️
2020-08-21 16:35:09 +10:00
Maikel
0309a20cb1 Merge pull request #5904 from Matt-Yorkley/favicon
Fix broken favicon path
2020-08-21 14:05:00 +10:00
Matt-Yorkley
9d772dbcc9 Merge pull request #5935 from luisramos0/fix_build
Fix master build - fix mail interceptor spec
2020-08-20 18:15:37 +02:00
Luis Ramos
0abcbc7b8f Fix specs in mail interceptor spec
This was due to an incompatibility between two recent PRs: 5763 and
5733. PR 5733 did not take into account 5763 (the confirm email method was removed) and so the specs introduced
were broken.
2020-08-20 12:52:54 +01:00
Matt-Yorkley
3badaa07d2 Fix adjustment calculations; only "eligible" adjustments should be regarded as applied to an order.
When an order is submitted and the payment fails, the failed payment's adjustments (payment fees) are set to `eligible: false` to indicate they do not apply. These should not be counted as being included in an order's adjustments.
2020-08-19 22:50:37 +01:00
Matt-Yorkley
977ab26b00 Add failing spec for payment fee calculation in customer totals report 2020-08-19 22:50:35 +01:00
Luis Ramos
d6160b5759 Merge pull request #5758 from luisramos0/order_updater
Bring Order Updater from spree_core
2020-08-19 20:47:27 +01:00
Luis Ramos
40d4ed2c95 Merge pull request #5733 from luisramos0/base_ctrl
Move lib/spree to OFN
2020-08-19 18:35:17 +01:00
Luis Ramos
72f5b1b251 Revert "Remove unreachable order recovery code"
This reverts commit 355c5f5c55.

This code is necessary to preserver cart contents across logins on
different browser sessions.
2020-08-19 17:36:36 +01:00
Luis Ramos
eb2d8e65ed Merge pull request #5910 from Matt-Yorkley/silky-mooth-sidebar-scrolling-for-danni
Add scrolling animate on sidebar hide
2020-08-19 11:47:39 +01:00
Maikel Linke
355c5f5c55 Remove unreachable order recovery code
Every page load creates a cart order if none is present. So when a user
logs in, they always have an order stored in their session. And
therefore, we never got to recover an old order.

We could have fixed the code to restore old orders. But as far as I can
tell, order recovery hasn't been working for years and I couldn't find
any issue requesting this feature.

If we wanted to implement order recovery, it should probably be designed
more carefully and included in the `current_order` method.
2020-08-19 12:06:58 +10:00
Maikel Linke
bb3f958dd2 Remove redundant includes 2020-08-19 10:37:18 +10:00
Luis Ramos
b367d4328e Remove spree upgrade section from the PR template ❤️ 2020-08-17 18:28:23 +01:00
Matt-Yorkley
ed346b3b54 Add scrolling animate on sidebar hide 2020-08-17 13:41:06 +01:00
Matt-Yorkley
290120d015 Fix broken favicon path
Ensures the non-fingerprinted version of the favicon will be used directly from `/public/favicon.ico`. Needed after recent changes to the Rails asset pipeline.
2020-08-17 11:59:22 +01:00
Matt-Yorkley
0fd163602d Rename method for clarity 2020-08-17 11:17:42 +01:00
Transifex-Openfoodnetwork
4c3a3d5d1a Updating translations for config/locales/en_GB.yml 2020-08-17 18:19:09 +10:00
Luis Ramos
9771fd7f13 Merge pull request #5902 from openfoodfoundation/dependabot/bundler/bugsnag-6.16.0
Bump bugsnag from 6.15.0 to 6.16.0
2020-08-16 16:19:36 +01:00
Luis Ramos
6a61bf7656 Merge pull request #5898 from mkllnk/remove-diffy
Remove unused dependency diffy
2020-08-16 16:04:42 +01:00
Luis Ramos
9754d8d754 Merge pull request #5616 from openfoodfoundation/dependabot/bundler/paper_trail-7.1.3
Bump paper_trail from 5.2.3 to 7.1.3
2020-08-15 21:53:33 +01:00
Matt-Yorkley
ce5bcaaa20 Explicitly notify Bugsnag on checkout failure 2020-08-14 18:06:30 +01:00
Matt-Yorkley
de22ad0000 Fix flash error issues in checkout requests 2020-08-14 12:41:56 +01:00
Maikel Linke
23706ec1d6 Load our version of the Spree environment
We didn't actually change any logic in our version of the Spree
environment file but if we do that in the future, we want to be sure
that it takes effect. Our file was ignored and not loaded before.
2020-08-14 15:38:10 +10:00
Maikel Linke
c3e0f45f1a Remove unused Report class from lib
Also removing related unused classes and their specs.
2020-08-14 15:38:10 +10:00
Maikel Linke
0a1947ae34 Remove unused module from lib
I was looking for library files that may be used but are not loaded.
I would then add the missing `require` statements. But I found that this
module isn't used any more.

Usage removed in:
310d1b3726
2020-08-14 15:38:10 +10:00
Maikel Linke
b79c568b08 Load our spree overrides instead of the originals
We changed some of Spree's logic and want to use that. And once we
remove the spree_core gem, we need to load those files before using
them.
2020-08-14 15:38:00 +10:00
Maikel Linke
e8139d3948 Keep old incomplete (cart) orders
We used to delete old cart orders so that they wouldn't re-appear after
a successful checkout of another order. Keeping them ensures that we
don't remove an order that is still used by another device. It also
makes sure that we keep references of failed payments.
2020-08-14 10:02:48 +10:00
Maikel Linke
5761014205 Restore Spree customisations for controllers 2020-08-13 16:59:15 +10:00
Maikel Linke
90bf4f312b Document and spec current controller behaviour
When we imported and merged Spree's controller modules with our
decorators, Rails started using Spree's original code again.

This was first included in v3.2.0 and deployed on 28 July 2020.
2020-08-13 16:59:15 +10:00
Maikel Linke
63a9765fea Update rubocop todo lists 2020-08-13 16:33:47 +10:00
dependabot-preview[bot]
5c6cb4840e Bump bugsnag from 6.15.0 to 6.16.0
Bumps [bugsnag](https://github.com/bugsnag/bugsnag-ruby) from 6.15.0 to 6.16.0.
- [Release notes](https://github.com/bugsnag/bugsnag-ruby/releases)
- [Changelog](https://github.com/bugsnag/bugsnag-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bugsnag/bugsnag-ruby/compare/v6.15.0...v6.16.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-13 01:56:14 +00:00
Maikel Linke
99ca0adf64 Remove unused dependency diffy
It was used to show differences in the product cache. But we removed the
cache in ab330e882e and the gem hasn't
been used since.
2020-08-12 13:10:51 +10:00
Matt-Yorkley
1123e08a98 Update BugsnagJS to latest version and update initialization syntax 2020-08-07 12:59:33 +01:00
dependabot-preview[bot]
18cb0e0980 Bump paper_trail from 5.2.3 to 7.1.3
Bumps [paper_trail](https://github.com/airblade/paper_trail) from 5.2.3 to 7.1.3.
- [Release notes](https://github.com/airblade/paper_trail/releases)
- [Changelog](https://github.com/paper-trail-gem/paper_trail/blob/master/CHANGELOG.md)
- [Commits](https://github.com/airblade/paper_trail/compare/v5.2.3...v7.1.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-30 16:56:15 +00:00
Pau Perez
be3a10b2b1 Fix some easy rubocop issues 2020-07-28 19:01:14 +02:00
Luis Ramos
ebf9be41bb Transpec specs 2020-07-11 17:02:03 +01:00
Luis Ramos
95ffff5087 Fix specs brought from spree 2020-07-11 16:59:35 +01:00
Luis Ramos
03bb1f053a Fix easy rubocop issues 2020-07-11 16:43:42 +01:00
Luis Ramos
2e3702550d Bring a number of files from spree_core needed in OFN 2020-07-11 16:09:13 +01:00
Luis Ramos
56b83b6bb5 Fix easy rubocop issues 2020-07-11 15:56:08 +01:00
Luis Ramos
e367cbd1e6 Fix one rubocop issues and add the remaining to the manual todo 2020-07-11 15:53:06 +01:00
Luis Ramos
bdf9c1e405 Simplify update_shipment_state based on the fact there's only one shipment per order in OFN 2020-07-11 15:53:06 +01:00
Luis Ramos
2070cfd5bb Fix easy rubocop issues 2020-07-11 15:44:23 +01:00
Luis Ramos
8001e63f77 Unnest OrderManagement::Order declaration in two module declaration 2020-07-11 15:44:23 +01:00
Luis Ramos
aed384183b Move Spree::OrderUpdater to OrderManagement engine 2020-07-11 15:44:23 +01:00
Luis Ramos
e453b130e4 Bring core/lib/spree/core/ext/active_record.rb to OFN and add it to Spree::Order, the only place where it is used 2020-07-11 15:44:23 +01:00
Luis Ramos
7e355a3248 Remove hash rockets 2020-07-11 15:44:23 +01:00
Luis Ramos
a8a81f8023 Merge and fix OrderUpdater spec with Spree::OrderUpdater spec 2020-07-11 15:44:23 +01:00
Luis Ramos
d4c48e2b94 Merge OrderUpdate Delegator into Spree::OrderUpdater 2020-07-11 15:44:23 +01:00
Luis Ramos
872cfcfc58 Remove unused promotions code 2020-07-11 15:44:23 +01:00
Luis Ramos
5b3fbe0aed Merge decorator OrderUpdater 2020-07-11 15:44:23 +01:00
Luis Ramos
ebeeeb7ed3 Fix easy rubocop issues 2020-07-11 15:44:23 +01:00
Luis Ramos
a929d82580 Transpec order_updater_spec 2020-07-11 15:44:23 +01:00
Luis Ramos
1f39731068 Modernize and fix spec brought from spree 2020-07-11 15:44:23 +01:00
Luis Ramos
d2f0d96174 Bring Spree::OrderUpdater spec 2020-07-11 15:44:23 +01:00
Luis Ramos
7218bb0c7d Bring Spree::OrderUpdater from spree 2020-07-11 15:44:23 +01:00
Luis Ramos
58da11fde7 Bring Environment Calculators and Environment Extension from spree_core 2020-07-11 15:43:20 +01:00
Luis Ramos
2c65cea911 Fix easy rubocop issues 2020-07-11 15:41:26 +01:00
Luis Ramos
95698fac37 Bring responder from spree_core 2020-07-11 15:41:26 +01:00
Luis Ramos
7b30008e8b Run transpec 2020-07-11 15:41:26 +01:00
Luis Ramos
50e6ce92b3 Fix easy rubocop issues 2020-07-11 15:41:26 +01:00
Luis Ramos
a78d615936 Bring money_spec from spree_core 2020-07-11 15:41:26 +01:00
Luis Ramos
cd8355ea66 Bring money.rb from spree 2020-07-11 15:41:26 +01:00
Luis Ramos
724a88344e Run transpec 2020-07-11 15:41:26 +01:00
Luis Ramos
9a09f420c1 Modernize spec 2020-07-11 15:41:26 +01:00
Luis Ramos
12a5a266fd Fix easy rubocop issues 2020-07-11 15:41:26 +01:00
Luis Ramos
efeda61e40 Bring i18n.rb from spree 2020-07-11 15:41:26 +01:00
Luis Ramos
38c5a9e105 Remove coupon applicator, it's not used in ofn 2020-07-11 15:41:26 +01:00
Luis Ramos
89e5221dc5 Fix easy rubocop issues 2020-07-11 15:41:26 +01:00
Luis Ramos
c75341838e Bring core.rb from spree_core 2020-07-11 15:41:26 +01:00
Luis Ramos
84d7538b1b Bring i18n code from spree 2020-07-11 15:41:26 +01:00
Luis Ramos
388d575cc8 Remove strong parameters and search helpers, they are not used in OFN 2020-07-11 15:41:26 +01:00
Luis Ramos
fdd21d7d7d Fix easy rubocop issues 2020-07-11 15:41:26 +01:00
Luis Ramos
ab67a4f80c Bring base controller from spree 2020-07-11 15:41:26 +01:00
68 changed files with 2340 additions and 531 deletions

View File

@@ -23,10 +23,6 @@ The categories are based on https://keepachangelog.com/en/1.0.0/. -->
Changelog Category: Added | Changed | Deprecated | Removed | Fixed | Security
#### How is this related to the Spree upgrade?
<!-- Any known conflicts with the Spree Upgrade?
Explain them or remove this section. -->
#### Discourse thread

View File

@@ -321,6 +321,15 @@ Layout/LineLength:
- spec/support/request/shop_workflow.rb
- spec/support/request/web_helper.rb
- spec/support/seeds.rb
- engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb
- spec/controllers/base_controller2_spec.rb
- spec/features/consumer/caching/darkswarm_caching_spec.rb
- spec/models/calculator/flexi_rate_spec.rb
- spec/models/calculator/price_sack_spec.rb
- spec/models/spree/stock_item_spec.rb
- spec/requests/api/orders_spec.rb
- spec/swagger_helper.rb
- spec/views/spree/admin/payment_methods/index.html.haml_spec.rb
Metrics/AbcSize:
Max: 15
@@ -399,6 +408,7 @@ Metrics/AbcSize:
- app/services/create_order_cycle.rb
- app/services/order_cycle_form.rb
- app/services/order_syncer.rb
- engines/order_management/app/services/order_management/order/updater.rb
- engines/order_management/app/services/order_management/stock/estimator.rb
- engines/order_management/app/services/order_management/stock/package.rb
- engines/order_management/app/services/order_management/stock/packer.rb
@@ -444,6 +454,11 @@ Metrics/AbcSize:
- spec/models/product_importer_spec.rb
- spec/services/order_checkout_restart_spec.rb
- spec/support/performance_helper.rb
- app/controllers/application_controller.rb
- app/models/spree/order/checkout.rb
- app/models/spree/payment/processing.rb
- app/models/spree/payment.rb
- engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb
Metrics/BlockLength:
Max: 25
@@ -482,6 +497,10 @@ Metrics/BlockLength:
- spec/support/delayed_job_helper.rb
- spec/support/matchers/select2_matchers.rb
- spec/support/matchers/table_matchers.rb
- app/models/spree/order/checkout.rb
- app/models/spree/payment/processing.rb
- spec/requests/api/orders_spec.rb
- spec/swagger_helper.rb
Metrics/CyclomaticComplexity:
Max: 6
@@ -513,6 +532,9 @@ Metrics/CyclomaticComplexity:
- lib/spree/core/controller_helpers/ssl.rb
- lib/spree/localized_number.rb
- spec/models/product_importer_spec.rb
- app/models/spree/order/checkout.rb
- app/models/spree/payment.rb
- engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb
Metrics/PerceivedComplexity:
Max: 7
@@ -539,6 +561,8 @@ Metrics/PerceivedComplexity:
- lib/spree/core/controller_helpers/ssl.rb
- lib/spree/localized_number.rb
- spec/models/product_importer_spec.rb
- app/models/spree/order/checkout.rb
- engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb
Metrics/MethodLength:
Max: 10
@@ -601,6 +625,7 @@ Metrics/MethodLength:
- app/serializers/api/cached_enterprise_serializer.rb
- app/services/order_cycle_form.rb
- app/services/permitted_attributes/checkout.rb
- engines/order_management/app/services/order_management/order/updater.rb
- engines/order_management/app/services/order_management/reports/enterprise_fee_summary/scope.rb
- engines/order_management/app/services/order_management/stock/estimator.rb
- engines/order_management/app/services/order_management/stock/package.rb
@@ -645,6 +670,11 @@ Metrics/MethodLength:
- spec/features/consumer/shopping/variant_overrides_spec.rb
- spec/models/product_importer_spec.rb
- spec/support/request/authentication_helper.rb
- app/models/spree/order/checkout.rb
- app/models/spree/payment/processing.rb
- engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_allocation_report.rb
- engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb
- engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_supplier_report.rb
Metrics/ClassLength:
Max: 100
@@ -674,6 +704,7 @@ Metrics/ClassLength:
- app/serializers/api/cached_enterprise_serializer.rb
- app/serializers/api/enterprise_shopfront_serializer.rb
- app/services/cart_service.rb
- engines/order_management/app/services/order_management/order/updater.rb
- engines/order_management/app/services/order_management/reports/enterprise_fee_summary/scope.rb
- lib/active_merchant/billing/gateways/stripe_payment_intents.rb
- lib/open_food_network/bulk_coop_report.rb
@@ -686,6 +717,8 @@ Metrics/ClassLength:
- lib/open_food_network/permissions.rb
- lib/open_food_network/users_and_enterprises_report.rb
- lib/open_food_network/xero_invoices_report.rb
- app/models/spree/payment.rb
- engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb
Metrics/ModuleLength:
Max: 100
@@ -694,6 +727,7 @@ Metrics/ModuleLength:
- app/helpers/injection_helper.rb
- app/helpers/spree/admin/base_helper.rb
- app/helpers/spree/admin/navigation_helper.rb
- engines/order_management/spec/services/order_management/order/updater_spec.rb
- engines/order_management/spec/services/order_management/stock/package_spec.rb
- engines/order_management/spec/services/order_management/subscriptions/estimator_spec.rb
- engines/order_management/spec/services/order_management/subscriptions/form_spec.rb
@@ -728,6 +762,8 @@ Metrics/ModuleLength:
- spec/models/spree/variant_spec.rb
- spec/services/permissions/order_spec.rb
- spec/support/request/web_helper.rb
- app/models/spree/order/checkout.rb
- app/models/spree/payment/processing.rb
Metrics/ParameterLists:
Max: 5
@@ -736,3 +772,8 @@ Metrics/ParameterLists:
- app/models/product_import/entry_processor.rb
- lib/open_food_network/xero_invoices_report.rb
- spec/features/admin/reports_spec.rb
Lint/UselessAssignment:
Exclude:
- 'spec/**/*'
- 'lib/spree/core/controller_helpers/common.rb'

View File

@@ -1,79 +1,214 @@
# This configuration was generated by
# `rubocop --auto-gen-config --exclude-limit 1400`
# on 2020-06-22 13:28:10 +0100 using RuboCop version 0.81.0.
# on 2020-08-13 16:05:53 +1000 using RuboCop version 0.81.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.
# Offense count: 139
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: with_first_argument, with_fixed_indentation
Layout/ArgumentAlignment:
Exclude:
- 'spec/models/spree/order/checkout_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyleAlignWith.
# SupportedStylesAlignWith: either, start_of_block, start_of_line
Layout/BlockAlignment:
Exclude:
- 'spec/models/spree/order/checkout_spec.rb'
# Offense count: 2
# Cop supports --auto-correct.
Layout/EmptyLines:
Exclude:
- 'spec/models/spree/payment_spec.rb'
# Offense count: 3
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: empty_lines, no_empty_lines
Layout/EmptyLinesAroundBlockBody:
Exclude:
- 'spec/models/spree/payment_spec.rb'
# Offense count: 3
# Cop supports --auto-correct.
# Configuration parameters: AllowForAlignment, AllowBeforeTrailingComments, ForceEqualSignAlignment.
Layout/ExtraSpacing:
Exclude:
- 'spec/models/spree/payment_spec.rb'
- 'spec/requests/api/orders_spec.rb'
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: special_inside_parentheses, consistent, align_brackets
Layout/FirstArrayElementIndentation:
Exclude:
- 'spec/views/spree/admin/payment_methods/index.html.haml_spec.rb'
# Offense count: 3
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: special_inside_parentheses, consistent, align_braces
Layout/FirstHashElementIndentation:
Exclude:
- 'spec/models/spree/payment_spec.rb'
- 'spec/swagger_helper.rb'
# Offense count: 5
# Cop supports --auto-correct.
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
# SupportedHashRocketStyles: key, separator, table
# SupportedColonStyles: key, separator, table
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
Layout/HashAlignment:
Exclude:
- 'spec/models/spree/payment_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: normal, indented_internal_methods
Layout/IndentationConsistency:
Exclude:
- 'spec/models/spree/order/checkout_spec.rb'
# Offense count: 26
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https
Layout/LineLength:
Max: 268
Max: 409
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: symmetrical, new_line, same_line
Layout/MultilineHashBraceLayout:
Exclude:
- 'spec/models/spree/payment_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: AllowForAlignment, EnforcedStyleForExponentOperator.
# SupportedStylesForExponentOperator: space, no_space
Layout/SpaceAroundOperators:
Exclude:
- 'spec/models/spree/payment_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces, SpaceBeforeBlockParameters.
# SupportedStyles: space, no_space
# SupportedStylesForEmptyBraces: space, no_space
Layout/SpaceInsideBlockBraces:
Exclude:
- 'spec/models/spree/payment_spec.rb'
# Offense count: 11
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, EnforcedStyleForEmptyBraces.
# SupportedStyles: space, no_space, compact
# SupportedStylesForEmptyBraces: space, no_space
Layout/SpaceInsideHashLiteralBraces:
Exclude:
- 'spec/models/spree/payment_spec.rb'
- 'spec/requests/api/orders_spec.rb'
- 'spec/services/checkout/form_data_adapter_spec.rb'
- 'spec/services/user_locale_setter_spec.rb'
# Offense count: 6
# Cop supports --auto-correct.
# Configuration parameters: AllowInHeredoc.
Layout/TrailingWhitespace:
Exclude:
- 'spec/controllers/base_controller2_spec.rb'
- 'spec/features/consumer/shopping/shopping_spec.rb'
- 'spec/requests/api/orders_spec.rb'
# Offense count: 2
Lint/DuplicateMethods:
Exclude:
- 'lib/discourse/single_sign_on.rb'
# Offense count: 9
# Offense count: 8
Lint/IneffectiveAccessModifier:
Exclude:
- 'app/models/column_preference.rb'
- 'app/models/spree/user.rb'
- 'app/services/mail_configuration.rb'
- 'lib/open_food_network/feature_toggle.rb'
- 'spec/lib/open_food_network/reports/report_spec.rb'
# Offense count: 5
# Offense count: 4
# Cop supports --auto-correct.
# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods.
Lint/UnusedMethodArgument:
Exclude:
- 'spec/views/spree/admin/payment_methods/index.html.haml_spec.rb'
# Offense count: 3
# Configuration parameters: ContextCreatingMethods, MethodCreatingMethods.
Lint/UselessAccessModifier:
Exclude:
- 'app/models/column_preference.rb'
- 'app/services/mail_configuration.rb'
- 'lib/open_food_network/feature_toggle.rb'
- 'lib/open_food_network/reports/bulk_coop_report.rb'
- 'spec/lib/open_food_network/reports/report_spec.rb'
# Offense count: 6
# Configuration parameters: IgnoredMethods.
Metrics/AbcSize:
Max: 37
# Offense count: 1
Lint/UselessAssignment:
Exclude:
- 'spec/**/*'
- 'lib/spree/core/controller_helpers/common.rb'
# Offense count: 19
# Configuration parameters: IgnoredMethods.
Metrics/AbcSize:
Max: 126
# Offense count: 7
# Configuration parameters: CountComments, ExcludedMethods.
# ExcludedMethods: refine
Metrics/BlockLength:
Max: 27
Max: 102
# Offense count: 1
# Offense count: 2
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 101
Max: 231
# Offense count: 1
# Offense count: 3
# Configuration parameters: IgnoredMethods.
Metrics/CyclomaticComplexity:
Max: 7
Max: 23
# Offense count: 6
# Offense count: 19
# Configuration parameters: CountComments, ExcludedMethods.
Metrics/MethodLength:
Max: 20
Max: 140
# Offense count: 1
# Offense count: 2
# Configuration parameters: CountComments.
Metrics/ModuleLength:
Max: 121
Max: 208
# Offense count: 8
# Offense count: 2
# Configuration parameters: IgnoredMethods.
Metrics/PerceivedComplexity:
Max: 24
# Offense count: 9
Naming/AccessorMethodName:
Exclude:
- 'app/controllers/spree/admin/taxonomies_controller.rb'
- 'app/models/spree/adjustment_decorator.rb'
- 'app/models/spree/order_decorator.rb'
- 'lib/spree/core/controller_helpers/common.rb'
- 'spec/support/request/shop_workflow.rb'
- 'spec/support/request/web_helper.rb'
@@ -117,6 +252,15 @@ Naming/PredicateName:
- 'lib/open_food_network/packing_report.rb'
- 'lib/tasks/data.rake'
# Offense count: 7
# Cop supports --auto-correct.
Rails/ActiveRecordAliases:
Exclude:
- 'spec/controllers/line_items_controller_spec.rb'
- 'spec/controllers/spree/orders_controller_spec.rb'
- 'spec/features/consumer/shopping/orders_spec.rb'
- 'spec/requests/api/orders_spec.rb'
# Offense count: 1
# Configuration parameters: EnforcedStyle.
# SupportedStyles: strict, flexible
@@ -124,6 +268,13 @@ Rails/Date:
Exclude:
- 'app/models/order_cycle.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforceForPrefixed.
Rails/Delegate:
Exclude:
- 'engines/order_management/app/services/order_management/reports/bulk_coop/renderers/html_renderer.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: Whitelist.
@@ -150,7 +301,7 @@ Rails/FilePath:
- 'spec/serializers/api/admin/enterprise_serializer_spec.rb'
- 'spec/support/downloads_helper.rb'
# Offense count: 7
# Offense count: 9
# Cop supports --auto-correct.
# Configuration parameters: Include.
# Include: app/models/**/*.rb
@@ -160,15 +311,17 @@ Rails/FindBy:
- 'app/models/product_import/entry_processor.rb'
- 'app/models/product_import/entry_validator.rb'
- 'app/models/product_import/spreadsheet_data.rb'
- 'app/models/spree/shipment.rb'
- 'app/models/spree/user.rb'
# Offense count: 1
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/FindEach:
Exclude:
- 'app/models/spree/order_decorator.rb'
- 'app/models/spree/shipment.rb'
# Offense count: 5
# Configuration parameters: Include.
@@ -180,7 +333,7 @@ Rails/HasAndBelongsToMany:
- 'app/models/spree/concerns/payment_method_distributors.rb'
- 'app/models/spree/line_item_decorator.rb'
# Offense count: 25
# Offense count: 26
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/HasManyOrHasOneDependent:
@@ -192,6 +345,7 @@ Rails/HasManyOrHasOneDependent:
- 'app/models/spree/order_decorator.rb'
- 'app/models/spree/payment_method_decorator.rb'
- 'app/models/spree/property.rb'
- 'app/models/spree/shipment.rb'
- 'app/models/spree/shipping_method_decorator.rb'
- 'app/models/spree/user.rb'
- 'app/models/spree/variant_decorator.rb'
@@ -268,7 +422,7 @@ Rails/ReflectionClassName:
- 'app/models/enterprise_role.rb'
- 'app/models/subscription.rb'
# Offense count: 227
# Offense count: 233
# Configuration parameters: Blacklist, Whitelist.
# Blacklist: decrement!, decrement_counter, increment!, increment_counter, toggle!, touch, update_all, update_attribute, update_column, update_columns, update_counters
Rails/SkipsModelValidations:
@@ -287,7 +441,8 @@ Rails/SkipsModelValidations:
- 'app/models/spree/address_decorator.rb'
- 'app/models/spree/credit_card_decorator.rb'
- 'app/models/spree/order_decorator.rb'
- 'app/models/spree/payment_decorator.rb'
- 'app/models/spree/payment.rb'
- 'app/models/spree/shipment.rb'
- 'app/models/spree/shipping_method_decorator.rb'
- 'app/models/subscription.rb'
- 'app/models/variant_override.rb'
@@ -355,27 +510,22 @@ Rails/SkipsModelValidations:
- 'spec/support/request/shop_workflow.rb'
- 'spec/views/spree/shared/_order_details.html.haml_spec.rb'
# Offense count: 2
# Offense count: 3
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/UniqueValidationWithoutIndex:
Exclude:
- 'app/models/customer.rb'
- 'app/models/exchange.rb'
# Offense count: 2
# Configuration parameters: Include.
# Include: app/models/**/*.rb
Rails/UniqueValidationWithoutIndex:
Exclude:
- 'app/models/spree/stock_item.rb'
# Offense count: 1
# Offense count: 2
# Configuration parameters: Environments.
# Environments: development, test, production
Rails/UnknownEnv:
Exclude:
- 'app/models/spree/app_configuration_decorator.rb'
- 'lib/spree/core/controller_helpers/ssl.rb'
# Offense count: 2
Style/CaseEquality:
@@ -383,7 +533,7 @@ Style/CaseEquality:
- 'app/helpers/angular_form_helper.rb'
- 'spec/models/spree/payment_spec.rb'
# Offense count: 75
# Offense count: 71
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, EnforcedStyle.
# SupportedStyles: nested, compact
@@ -447,20 +597,10 @@ Style/ClassAndModuleChildren:
- 'app/serializers/api/property_serializer.rb'
- 'app/serializers/api/shipping_method_serializer.rb'
- 'app/serializers/api/state_serializer.rb'
- 'app/serializers/api/taxon_image_serializer.rb'
- 'app/serializers/api/taxon_serializer.rb'
- 'app/serializers/api/variant_serializer.rb'
- 'lib/open_food_network/locking.rb'
- 'lib/open_food_network/reports/bulk_coop_allocation_report.rb'
- 'lib/open_food_network/reports/bulk_coop_report.rb'
- 'lib/open_food_network/reports/bulk_coop_supplier_report.rb'
- 'lib/open_food_network/reports/report.rb'
- 'lib/open_food_network/reports/row.rb'
- 'lib/open_food_network/reports/rule.rb'
- 'spec/controllers/spree/admin/base_controller_spec.rb'
- 'spec/lib/open_food_network/reports/report_spec.rb'
- 'spec/lib/open_food_network/reports/row_spec.rb'
- 'spec/lib/open_food_network/reports/rule_spec.rb'
# Offense count: 2
Style/ClassVars:
@@ -475,7 +615,7 @@ Style/FormatStringToken:
- 'lib/open_food_network/sales_tax_report.rb'
- 'spec/features/admin/bulk_order_management_spec.rb'
# Offense count: 874
# Offense count: 847
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: always, always_true, never
@@ -569,7 +709,6 @@ Style/FrozenStringLiteralComment:
- 'app/controllers/spree/admin/variants_controller.rb'
- 'app/controllers/spree/admin/zones_controller.rb'
- 'app/controllers/spree/credit_cards_controller.rb'
- 'app/controllers/spree/home_controller.rb'
- 'app/controllers/spree/orders_controller.rb'
- 'app/controllers/spree/store_controller.rb'
- 'app/controllers/spree/user_passwords_controller.rb'
@@ -624,8 +763,6 @@ Style/FrozenStringLiteralComment:
- 'app/jobs/subscription_placement_job.rb'
- 'app/jobs/welcome_enterprise_job.rb'
- 'app/mailers/enterprise_mailer.rb'
- 'app/mailers/spree/base_mailer_decorator.rb'
- 'app/mailers/spree/order_mailer_decorator.rb'
- 'app/mailers/spree/user_mailer.rb'
- 'app/mailers/subscription_mailer.rb'
- 'app/models/adjustment_metadata.rb'
@@ -684,12 +821,6 @@ Style/FrozenStringLiteralComment:
- 'app/models/spree/address_decorator.rb'
- 'app/models/spree/adjustment_decorator.rb'
- 'app/models/spree/app_configuration_decorator.rb'
- 'app/models/spree/calculator/default_tax_decorator.rb'
- 'app/models/spree/calculator/flat_percent_item_total_decorator.rb'
- 'app/models/spree/calculator/flat_rate_decorator.rb'
- 'app/models/spree/calculator/flexi_rate_decorator.rb'
- 'app/models/spree/calculator/per_item_decorator.rb'
- 'app/models/spree/calculator/price_sack_decorator.rb'
- 'app/models/spree/calculator_decorator.rb'
- 'app/models/spree/classification_decorator.rb'
- 'app/models/spree/concerns/payment_method_distributors.rb'
@@ -702,7 +833,6 @@ Style/FrozenStringLiteralComment:
- 'app/models/spree/line_item_decorator.rb'
- 'app/models/spree/option_type_decorator.rb'
- 'app/models/spree/order_decorator.rb'
- 'app/models/spree/payment_decorator.rb'
- 'app/models/spree/payment_method_decorator.rb'
- 'app/models/spree/preferences/file_configuration.rb'
- 'app/models/spree/price_decorator.rb'
@@ -711,15 +841,12 @@ Style/FrozenStringLiteralComment:
- 'app/models/spree/product_property_decorator.rb'
- 'app/models/spree/product_set.rb'
- 'app/models/spree/property.rb'
- 'app/models/spree/shipment_decorator.rb'
- 'app/models/spree/shipping_method_decorator.rb'
- 'app/models/spree/stock/availability_validator_decorator.rb'
- 'app/models/spree/stock_location_decorator.rb'
- 'app/models/spree/tax_rate_decorator.rb'
- 'app/models/spree/taxon_decorator.rb'
- 'app/models/spree/user.rb'
- 'app/models/spree/variant_decorator.rb'
- 'app/models/stock/package.rb'
- 'app/models/stripe_account.rb'
- 'app/models/subscription.rb'
- 'app/models/subscription_line_item.rb'
@@ -803,7 +930,6 @@ Style/FrozenStringLiteralComment:
- 'app/serializers/api/shipping_method_serializer.rb'
- 'app/serializers/api/shop_for_orders_serializer.rb'
- 'app/serializers/api/state_serializer.rb'
- 'app/serializers/api/taxon_image_serializer.rb'
- 'app/serializers/api/taxon_jstree_attribute_serializer.rb'
- 'app/serializers/api/taxon_jstree_serializer.rb'
- 'app/serializers/api/taxon_serializer.rb'
@@ -811,7 +937,6 @@ Style/FrozenStringLiteralComment:
- 'app/serializers/api/user_serializer.rb'
- 'app/serializers/api/variant_serializer.rb'
- 'app/services/action_callbacks.rb'
- 'app/services/advance_order_service.rb'
- 'app/services/bulk_invoice_service.rb'
- 'app/services/cart_service.rb'
- 'app/services/create_order_cycle.rb'
@@ -831,6 +956,7 @@ Style/FrozenStringLiteralComment:
- 'app/services/order_factory.rb'
- 'app/services/order_syncer.rb'
- 'app/services/order_update_issues.rb'
- 'app/services/order_workflow.rb'
- 'app/services/permissions/order.rb'
- 'app/services/product_tag_rules_filterer.rb'
- 'app/services/products_renderer.rb'
@@ -893,7 +1019,6 @@ Style/FrozenStringLiteralComment:
- 'lib/discourse/single_sign_on.rb'
- 'lib/open_food_network/address_finder.rb'
- 'lib/open_food_network/available_payment_method_filter.rb'
- 'lib/open_food_network/bulk_coop_report.rb'
- 'lib/open_food_network/column_preference_defaults.rb'
- 'lib/open_food_network/customers_report.rb'
- 'lib/open_food_network/enterprise_fee_applicator.rb'
@@ -906,7 +1031,6 @@ Style/FrozenStringLiteralComment:
- 'lib/open_food_network/i18n_config.rb'
- 'lib/open_food_network/lettuce_share_report.rb'
- 'lib/open_food_network/locking.rb'
- 'lib/open_food_network/model_class_from_controller_name.rb'
- 'lib/open_food_network/order_and_distributor_report.rb'
- 'lib/open_food_network/order_cycle_form_applicator.rb'
- 'lib/open_food_network/order_cycle_management_report.rb'
@@ -928,14 +1052,8 @@ Style/FrozenStringLiteralComment:
- 'lib/open_food_network/property_merge.rb'
- 'lib/open_food_network/rack_request_blocker.rb'
- 'lib/open_food_network/referer_parser.rb'
- 'lib/open_food_network/reports/bulk_coop_allocation_report.rb'
- 'lib/open_food_network/reports/bulk_coop_report.rb'
- 'lib/open_food_network/reports/bulk_coop_supplier_report.rb'
- 'lib/open_food_network/reports/line_items.rb'
- 'lib/open_food_network/reports/list.rb'
- 'lib/open_food_network/reports/report.rb'
- 'lib/open_food_network/reports/row.rb'
- 'lib/open_food_network/reports/rule.rb'
- 'lib/open_food_network/sales_tax_report.rb'
- 'lib/open_food_network/scope_product_to_hub.rb'
- 'lib/open_food_network/scope_variant_to_hub.rb'
@@ -949,9 +1067,6 @@ Style/FrozenStringLiteralComment:
- 'lib/spree/api/controller_setup.rb'
- 'lib/spree/api/testing_support/setup.rb'
- 'lib/spree/authentication_helpers.rb'
- 'lib/spree/core/controller_helpers/auth_decorator.rb'
- 'lib/spree/core/controller_helpers/order_decorator.rb'
- 'lib/spree/core/controller_helpers/respond_with_decorator.rb'
- 'lib/spree/localized_number.rb'
- 'lib/spree/money_decorator.rb'
- 'lib/spree/product_filters.rb'
@@ -980,7 +1095,6 @@ Style/FrozenStringLiteralComment:
- 'lib/tasks/sample_data/user_factory.rb'
- 'lib/tasks/specs.rake'
- 'lib/tasks/users.rake'
- 'spec/config/application_spec.rb'
- 'spec/controllers/admin/bulk_line_items_controller_spec.rb'
- 'spec/controllers/admin/column_preferences_controller_spec.rb'
- 'spec/controllers/admin/customers_controller_spec.rb'
@@ -1011,9 +1125,9 @@ Style/FrozenStringLiteralComment:
- 'spec/controllers/api/taxonomies_controller_spec.rb'
- 'spec/controllers/api/taxons_controller_spec.rb'
- 'spec/controllers/api/variants_controller_spec.rb'
- 'spec/controllers/base_controller2_spec.rb'
- 'spec/controllers/base_controller_spec.rb'
- 'spec/controllers/cart_controller_spec.rb'
- 'spec/controllers/checkout_controller_concurrency_spec.rb'
- 'spec/controllers/checkout_controller_spec.rb'
- 'spec/controllers/enterprises_controller_spec.rb'
- 'spec/controllers/groups_controller_spec.rb'
@@ -1030,7 +1144,6 @@ Style/FrozenStringLiteralComment:
- 'spec/controllers/spree/admin/orders_controller_spec.rb'
- 'spec/controllers/spree/admin/overview_controller_spec.rb'
- 'spec/controllers/spree/admin/payment_methods_controller_spec.rb'
- 'spec/controllers/spree/admin/payments_controller_spec.rb'
- 'spec/controllers/spree/admin/products_controller_spec.rb'
- 'spec/controllers/spree/admin/reports_controller_spec.rb'
- 'spec/controllers/spree/admin/search_controller_spec.rb'
@@ -1039,7 +1152,6 @@ Style/FrozenStringLiteralComment:
- 'spec/controllers/spree/admin/variants_controller_spec.rb'
- 'spec/controllers/spree/credit_cards_controller_spec.rb'
- 'spec/controllers/spree/orders_controller_spec.rb'
- 'spec/controllers/spree/store_controller_spec.rb'
- 'spec/controllers/spree/user_sessions_controller_spec.rb'
- 'spec/controllers/spree/users_controller_spec.rb'
- 'spec/controllers/stripe/callbacks_controller_spec.rb'
@@ -1147,7 +1259,6 @@ Style/FrozenStringLiteralComment:
- 'spec/jobs/subscription_placement_job_spec.rb'
- 'spec/jobs/welcome_enterprise_job_spec.rb'
- 'spec/lib/open_food_network/address_finder_spec.rb'
- 'spec/lib/open_food_network/bulk_coop_report_spec.rb'
- 'spec/lib/open_food_network/customers_report_spec.rb'
- 'spec/lib/open_food_network/enterprise_fee_applicator_spec.rb'
- 'spec/lib/open_food_network/enterprise_fee_calculator_spec.rb'
@@ -1173,9 +1284,6 @@ Style/FrozenStringLiteralComment:
- 'spec/lib/open_food_network/products_and_inventory_report_spec.rb'
- 'spec/lib/open_food_network/property_merge_spec.rb'
- 'spec/lib/open_food_network/referer_parser_spec.rb'
- 'spec/lib/open_food_network/reports/report_spec.rb'
- 'spec/lib/open_food_network/reports/row_spec.rb'
- 'spec/lib/open_food_network/reports/rule_spec.rb'
- 'spec/lib/open_food_network/sales_tax_report_spec.rb'
- 'spec/lib/open_food_network/scope_variant_to_hub_spec.rb'
- 'spec/lib/open_food_network/scope_variants_to_search_spec.rb'
@@ -1190,12 +1298,16 @@ Style/FrozenStringLiteralComment:
- 'spec/lib/tasks/enterprises_rake_spec.rb'
- 'spec/lib/tasks/users_rake_spec.rb'
- 'spec/mailers/enterprise_mailer_spec.rb'
- 'spec/mailers/order_mailer_spec.rb'
- 'spec/mailers/producer_mailer_spec.rb'
- 'spec/mailers/subscription_mailer_spec.rb'
- 'spec/mailers/user_mailer_spec.rb'
- 'spec/models/adjustment_metadata_spec.rb'
- 'spec/models/calculator/flat_percent_item_total_spec.rb'
- 'spec/models/calculator/flat_percent_per_item_spec.rb'
- 'spec/models/calculator/flat_rate_spec.rb'
- 'spec/models/calculator/flexi_rate_spec.rb'
- 'spec/models/calculator/per_item_spec.rb'
- 'spec/models/calculator/price_sack_spec.rb'
- 'spec/models/calculator/weight_spec.rb'
- 'spec/models/column_preference_spec.rb'
- 'spec/models/concerns/order_shipment_spec.rb'
@@ -1221,11 +1333,6 @@ Style/FrozenStringLiteralComment:
- 'spec/models/spree/ability_spec.rb'
- 'spec/models/spree/addresses_spec.rb'
- 'spec/models/spree/adjustment_spec.rb'
- 'spec/models/spree/calculator/flat_percent_item_total_spec.rb'
- 'spec/models/spree/calculator/flat_rate_spec.rb'
- 'spec/models/spree/calculator/flexi_rate_spec.rb'
- 'spec/models/spree/calculator/per_item_spec.rb'
- 'spec/models/spree/calculator/price_sack_spec.rb'
- 'spec/models/spree/calculator_spec.rb'
- 'spec/models/spree/classification_spec.rb'
- 'spec/models/spree/credit_card_spec.rb'
@@ -1240,14 +1347,12 @@ Style/FrozenStringLiteralComment:
- 'spec/models/spree/price_spec.rb'
- 'spec/models/spree/product_set_spec.rb'
- 'spec/models/spree/product_spec.rb'
- 'spec/models/spree/shipment_spec.rb'
- 'spec/models/spree/shipping_method_spec.rb'
- 'spec/models/spree/stock/availability_validator_spec.rb'
- 'spec/models/spree/tax_rate_spec.rb'
- 'spec/models/spree/taxon_spec.rb'
- 'spec/models/spree/user_spec.rb'
- 'spec/models/spree/variant_spec.rb'
- 'spec/models/stock/package_spec.rb'
- 'spec/models/stripe_account_spec.rb'
- 'spec/models/subscription_line_item_spec.rb'
- 'spec/models/subscription_spec.rb'
@@ -1289,7 +1394,6 @@ Style/FrozenStringLiteralComment:
- 'spec/serializers/api/product_serializer_spec.rb'
- 'spec/serializers/api/shipping_method_serializer_spec.rb'
- 'spec/serializers/api/variant_serializer_spec.rb'
- 'spec/services/advance_order_service_spec.rb'
- 'spec/services/bulk_invoice_service_spec.rb'
- 'spec/services/cart_service_spec.rb'
- 'spec/services/default_shipping_category_spec.rb'
@@ -1305,6 +1409,7 @@ Style/FrozenStringLiteralComment:
- 'spec/services/order_cycle_warning_spec.rb'
- 'spec/services/order_factory_spec.rb'
- 'spec/services/order_syncer_spec.rb'
- 'spec/services/order_workflow_spec.rb'
- 'spec/services/permissions/order_spec.rb'
- 'spec/services/product_tag_rules_filterer_spec.rb'
- 'spec/services/products_renderer_spec.rb'
@@ -1355,8 +1460,9 @@ Style/FrozenStringLiteralComment:
- 'spec/validators/integer_array_validator_spec.rb'
- 'spec/views/spree/admin/orders/edit.html.haml_spec.rb'
- 'spec/views/spree/admin/orders/index.html.haml_spec.rb'
- 'spec/views/spree/admin/payment_methods/index.html.haml_spec.rb'
# Offense count: 51
# Offense count: 48
# Configuration parameters: MinBodyLength.
Style/GuardClause:
Exclude:
@@ -1376,32 +1482,35 @@ Style/GuardClause:
- 'app/models/spree/order_decorator.rb'
- 'app/models/spree/price_decorator.rb'
- 'app/models/spree/product_decorator.rb'
- 'app/services/advance_order_service.rb'
- 'app/services/order_syncer.rb'
- 'lib/discourse/single_sign_on.rb'
- 'lib/open_food_network/order_cycle_form_applicator.rb'
- 'lib/open_food_network/rack_request_blocker.rb'
- 'lib/open_food_network/variant_and_line_item_naming.rb'
- 'lib/spree/core/controller_helpers/order_decorator.rb'
- 'lib/spree/core/controller_helpers/respond_with_decorator.rb'
- 'spec/support/delayed_job_helper.rb'
- 'spec/support/request/distribution_helper.rb'
- 'spec/support/request/shop_workflow.rb'
# Offense count: 54
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
Style/HashSyntax:
Exclude:
- 'spec/models/spree/payment_spec.rb'
# Offense count: 1
Style/MissingRespondToMissing:
Exclude:
- 'app/helpers/application_helper.rb'
# Offense count: 4
# Offense count: 2
Style/MixinUsage:
Exclude:
- 'lib/open_food_network/orders_and_fulfillments_report.rb'
- 'spec/lib/open_food_network/bulk_coop_report_spec.rb'
- 'spec/lib/open_food_network/order_cycle_management_report_spec.rb'
- 'spec/lib/open_food_network/packing_report_spec.rb'
# Offense count: 41
# Offense count: 39
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods.
# SupportedStyles: predicate, comparison
@@ -1416,11 +1525,9 @@ Style/NumericPredicate:
- 'app/models/product_import/product_importer.rb'
- 'app/models/product_import/spreadsheet_entry.rb'
- 'app/models/spree/adjustment_decorator.rb'
- 'app/models/spree/calculator/flexi_rate_decorator.rb'
- 'app/models/spree/gateway/stripe_connect.rb'
- 'app/models/spree/line_item_decorator.rb'
- 'app/models/spree/order_decorator.rb'
- 'app/models/spree/shipment_decorator.rb'
- 'app/models/spree/user.rb'
- 'app/models/variant_override.rb'
- 'app/services/cart_service.rb'
@@ -1433,6 +1540,22 @@ Style/NumericPredicate:
- 'lib/spree/money_decorator.rb'
- 'lib/tasks/sample_data.rake'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: compact, exploded
Style/RaiseArgs:
Exclude:
- 'spec/controllers/checkout_controller_spec.rb'
# Offense count: 1
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, AllowInnerSlashes.
# SupportedStyles: slashes, percent_r, mixed
Style/RegexpLiteral:
Exclude:
- 'lib/spree/core/controller_helpers/auth.rb'
# Offense count: 231
Style/Send:
Exclude:

View File

@@ -86,12 +86,11 @@ gem 'acts-as-taggable-on', '~> 4.0'
gem 'angularjs-file-upload-rails', '~> 2.4.1'
gem 'custom_error_message', github: 'jeremydurham/custom-err-msg'
gem 'dalli'
gem 'diffy'
gem 'figaro'
gem 'geocoder'
gem 'gmaps4rails'
gem 'oj'
gem 'paper_trail', '~> 5.2.3'
gem 'paper_trail', '~> 7.1.3'
gem 'paperclip', '~> 3.4.1'
gem 'rack-rewrite'
gem 'rack-ssl', require: 'rack/ssl'

View File

@@ -148,7 +148,7 @@ GEM
nokogiri (>= 1.4.4)
uuidtools (~> 2.1)
bcrypt (3.1.13)
bugsnag (6.15.0)
bugsnag (6.16.0)
concurrent-ruby (~> 1.0)
builder (3.1.4)
byebug (11.0.1)
@@ -192,7 +192,7 @@ GEM
compass (~> 1.0.0)
sass-rails (< 5.1)
sprockets (< 4.0)
concurrent-ruby (1.1.6)
concurrent-ruby (1.1.7)
crack (0.4.3)
safe_yaml (~> 1.0.0)
css_parser (1.7.1)
@@ -229,7 +229,6 @@ GEM
devise-token_authenticatable (0.4.10)
devise (>= 3.5.2, < 4.0.0)
diff-lcs (1.3)
diffy (3.3.0)
docile (1.3.2)
dry-inflector (0.1.2)
erubis (2.7.0)
@@ -483,8 +482,8 @@ GEM
oj (3.10.8)
optimist (3.0.0)
orm_adapter (0.5.0)
paper_trail (5.2.3)
activerecord (>= 3.0, < 6.0)
paper_trail (7.1.3)
activerecord (>= 4.0, < 5.2)
request_store (~> 1.1)
paperclip (3.4.2)
activemodel (>= 3.0.0)
@@ -555,7 +554,7 @@ GEM
nokogiri (~> 1.5)
optimist (~> 3.0)
redcarpet (3.5.0)
request_store (1.4.1)
request_store (1.5.0)
rack (>= 1.4)
responders (1.1.2)
railties (>= 3.2, < 4.2)
@@ -743,7 +742,6 @@ DEPENDENCIES
devise-encryptable
devise-token_authenticatable (~> 0.4.10)
dfc_provider!
diffy
eventmachine (>= 1.2.3)
factory_bot_rails (= 4.10.0)
ffaker (~> 1.16)
@@ -777,7 +775,7 @@ DEPENDENCIES
ofn-qz!
oj
order_management!
paper_trail (~> 5.2.3)
paper_trail (~> 7.1.3)
paperclip (~> 3.4.1)
paranoia (~> 2.0)
pg (~> 0.21.0)

View File

@@ -24,7 +24,8 @@ Darkswarm.factory 'Checkout', ($injector, CurrentOrder, ShippingMethods, StripeE
try
@loadFlash(error: t("checkout.failed")) # inform the user about the unexpected error
finally
throw error # generate a BugsnagJS alert
Bugsnag.notify(error)
throw error
handle_checkout_error_response: (response) =>
throw response unless response.data?

View File

@@ -16,12 +16,14 @@
width: 100%;
background-color: $shop-sidebar-overlay;
opacity: 0;
transition: opacity $transition-sidebar;
visibility: hidden;
transition: all $transition-sidebar;
}
&.shown {
.background {
opacity: 1;
visibility: visible;
}
.sidebar,

View File

@@ -1,5 +1,6 @@
# Base controller for OFN's API
require_dependency 'spree/api/controller_setup'
require "spree/core/controller_helpers/ssl"
module Api
class BaseController < ActionController::Metal

View File

@@ -1,8 +1,10 @@
require 'spree/core/controller_helpers/auth'
require 'spree/core/controller_helpers/common'
require 'spree/core/controller_helpers/order'
require 'spree/core/controller_helpers/respond_with'
require 'open_food_network/tag_rule_applicator'
class BaseController < ApplicationController
include Spree::Core::ControllerHelpers
include Spree::Core::ControllerHelpers::Auth
include Spree::Core::ControllerHelpers::Common
include Spree::Core::ControllerHelpers::Order

View File

@@ -235,6 +235,7 @@ class CheckoutController < Spree::StoreController
render :edit
end
format.json do
discard_flash_errors
render json: { errors: @order.errors, flash: flash.to_hash }.to_json, status: :bad_request
end
end
@@ -248,4 +249,11 @@ class CheckoutController < Spree::StoreController
def permitted_params
PermittedAttributes::Checkout.new(params).call
end
def discard_flash_errors
# Marks flash errors for deletion after the current action has completed.
# This ensures flash errors generated during XHR requests are not persisted in the
# session for longer than expected.
flash.discard(:error)
end
end

View File

@@ -0,0 +1,16 @@
# frozen_string_literal: true
require 'cancan'
module Spree
class BaseController < ApplicationController
include Spree::Core::ControllerHelpers::Auth
include Spree::Core::ControllerHelpers::RespondWith
include Spree::Core::ControllerHelpers::SSL
include Spree::Core::ControllerHelpers::Common
respond_to :html
end
end
require 'spree/i18n/initializer'

View File

@@ -1,3 +1,10 @@
# frozen_string_literal: true
require "spree/core/controller_helpers/auth"
require "spree/core/controller_helpers/common"
require "spree/core/controller_helpers/order"
require "spree/core/controller_helpers/ssl"
module Spree
class UserPasswordsController < Devise::PasswordsController
helper 'spree/base', 'spree/store'

View File

@@ -1,3 +1,10 @@
# frozen_string_literal: true
require "spree/core/controller_helpers/auth"
require "spree/core/controller_helpers/common"
require "spree/core/controller_helpers/order"
require "spree/core/controller_helpers/ssl"
module Spree
class UserRegistrationsController < Devise::RegistrationsController
helper 'spree/base', 'spree/store'

View File

@@ -1,3 +1,10 @@
# frozen_string_literal: true
require "spree/core/controller_helpers/auth"
require "spree/core/controller_helpers/common"
require "spree/core/controller_helpers/order"
require "spree/core/controller_helpers/ssl"
module Spree
class UserSessionsController < Devise::SessionsController
helper 'spree/base', 'spree/store'

View File

@@ -1,92 +0,0 @@
require 'delegate'
class OrderUpdater < SimpleDelegator
# TODO: This logic adapted from Spree 2.4, remove when we get there
# Handles state updating in a much more logical way than < 2.4
# Specifically, doesn't depend on payments.last to determine payment state
# Also swapped: == 0 for .zero?, .size == 0 for empty? and .size > 0 for !empty?
# See:
# https://github.com/spree/spree/commit/38b8456183d11fc1e00e395e7c9154c76ef65b85
# https://github.com/spree/spree/commit/7b264acff7824f5b3dc6651c106631d8f30b147a
def update_payment_state
last_payment_state = order.payment_state
order.payment_state = infer_payment_state
track_payment_state_change(last_payment_state)
order.payment_state
end
def before_save_hook
shipping_address_from_distributor
end
# Sets the distributor's address as shipping address of the order for those
# shipments using a shipping method that doesn't require address, such us
# a pickup.
def shipping_address_from_distributor
return if order.shipping_method.blank? || order.shipping_method.require_ship_address
order.ship_address = order.address_from_distributor
end
private
def infer_payment_state
if failed_payments?
'failed'
elsif canceled_and_not_paid_for?
'void'
else
infer_payment_state_from_balance
end
end
def infer_payment_state_from_balance
# This part added so that we don't need to override
# order.outstanding_balance
balance = order.outstanding_balance
balance = -1 * order.payment_total if canceled_and_paid_for?
infer_state(balance)
end
def infer_state(balance)
if balance > 0
'balance_due'
elsif balance < 0
'credit_owed'
elsif balance.zero?
'paid'
end
end
# Tracks the state transition through a state_change for this order. It
# does so until the last state is reached. That is, when the infered next
# state is the same as the order has now.
#
# @param last_payment_state [String]
def track_payment_state_change(last_payment_state)
return if last_payment_state == order.payment_state
order.state_changed('payment')
end
# Taken from order.outstanding_balance in Spree 2.4
# See: https://github.com/spree/spree/commit/7b264acff7824f5b3dc6651c106631d8f30b147a
def canceled_and_paid_for?
order.canceled? && paid?
end
def canceled_and_not_paid_for?
order.state == 'canceled' && order.payment_total.zero?
end
def paid?
payments.present? && !payments.completed.empty?
end
def failed_payments?
payments.present? && payments.valid.empty?
end
end

View File

@@ -89,6 +89,10 @@ Spree::Order.class_eval do
where("state != ?", state)
}
def updater
@updater ||= OrderManagement::Order::Updater.new(self)
end
def create_proposed_shipments
adjustments.shipping.delete_all
shipments.destroy_all
@@ -374,6 +378,13 @@ Spree::Order.class_eval do
address
end
# Update attributes of a record in the database without callbacks, validations etc.
# This was originally an extension to ActiveRecord in Spree but only used for Spree::Order
def update_attributes_without_callbacks(attributes)
assign_attributes(attributes)
Spree::Order.where(id: id).update_all(attributes)
end
private
def adjustments_fetcher

View File

@@ -1,8 +0,0 @@
# frozen_string_literal: true
Spree::OrderUpdater.class_eval do
# Override spree method to make it update all adjustments as in Spree v2.0.4
def update_shipping_adjustments
order.adjustments.reload.each(&:update!)
end
end

View File

@@ -57,11 +57,12 @@ class OrderAdjustmentsFetcher
if adjustments_eager_loaded?
adjustment_scope = public_send("#{scope}_scope")
# Adjustments are already loaded here, this block is using `Array#select`
adjustments.select do |adjustment|
match_by_scope(adjustment, adjustment_scope)
match_by_scope(adjustment, adjustment_scope) && match_by_scope(adjustment, eligible_scope)
end
else
adjustments.where(nil).public_send scope
adjustments.where(nil).eligible.public_send scope
end
end

View File

@@ -1,10 +1,8 @@
- bugsnag_js_key = ENV['BUGSNAG_JS_KEY'] || ENV['BUGSNAG_API_KEY']
- if bugsnag_js_key.present?
%script{src: "//d2wy8f7a9ursnm.cloudfront.net/v6/bugsnag.min.js"}
%script{src: "//d2wy8f7a9ursnm.cloudfront.net/v7/bugsnag.min.js"}
:javascript
window.bugsnagClient = bugsnag({
Bugsnag.start({
apiKey: "#{bugsnag_js_key}",
beforeSend: function (report) {
report.app.releaseStage = "#{Rails.env}"
}
});
releaseStage: "#{Rails.env}"
})

View File

@@ -9,7 +9,7 @@
%meta{name: "robots", content: "noindex"}
%title= content_for?(:title) ? "#{yield(:title)} - #{t(:title)}".html_safe : "#{t(:welcome_to)} #{t(:title)}"
- if Rails.env.production?
= favicon_link_tag
= favicon_link_tag "/favicon.ico"
- else
= favicon_link_tag "/favicon-staging.ico"
%link{href: "https://fonts.googleapis.com/css?family=Roboto:400,300italic,400italic,300,700,700italic|Oswald:300,400,700", rel: "stylesheet", type: "text/css"}

View File

@@ -5,7 +5,7 @@
%title= content_for?(:title) ? "#{yield(:title)} - #{Spree::Config[:site_name]}" : "#{t(:welcome_to)} #{Spree::Config[:site_name]}"
- if Rails.env.production?
= favicon_link_tag
= favicon_link_tag "/favicon.ico"
- else
= favicon_link_tag "/favicon-staging.ico"
%link{href: "https://fonts.googleapis.com/css?family=Roboto:400,300italic,400italic,300,700,700italic|Oswald:300,400,700", rel: "stylesheet", type: "text/css"}

View File

@@ -1,4 +1,4 @@
.expanding-sidebar.cart-sidebar{ng: {controller: 'CartCtrl', show: 'showCartSidebar', class: "{'shown': showCartSidebar, 'hidden': !showCartSidebar}"}}
.expanding-sidebar.cart-sidebar{ng: {controller: 'CartCtrl', class: "{'shown': showCartSidebar}"}}
.background{ng: {click: 'toggleCartSidebar()'}}
.sidebar
.cart-header

View File

@@ -6,6 +6,7 @@
# In order to initialize a setting do:
# config.setting_name = 'new value'
require "spree/core/environment"
require 'spree/product_filters'
# Due to a bug in ActiveRecord we need to load the tagging code in Gateway which
@@ -30,8 +31,6 @@ Spree.config do |config|
config.auto_capture = true
#config.override_actionmailer_config = false
config.order_updater_decorator = OrderUpdater
# S3 settings
config.s3_bucket = ENV['S3_BUCKET'] if ENV['S3_BUCKET']
config.s3_access_key = ENV['S3_ACCESS_KEY'] if ENV['S3_ACCESS_KEY']

View File

@@ -14,6 +14,7 @@ en_GB:
spree/payment:
amount: Amount
state: State
source: Source
spree/product:
primary_taxon: "Product Category"
supplier: "Supplier"
@@ -272,6 +273,9 @@ en_GB:
on hand: "In Stock"
ship: "Ship"
shipping_category: "Shipping Category"
height: "Height"
width: "Width"
depth: "Depth"
actions:
create_and_add_another: "Create and Add Another"
create: "Create"
@@ -1967,6 +1971,7 @@ en_GB:
supplier: "Supplier"
product_name: "Product Name"
product_description: "Product Description"
permalink: "Permalink"
shipping_categories: "Shipping Categories"
units: "Unit Size"
coordinator: "Coordinator"
@@ -2064,6 +2069,7 @@ en_GB:
remove_tax: "Remove tax"
first_name_begins_with: "First name begins with"
last_name_begins_with: "Surname begins with"
shipping_method: "Shipping method"
new_order: "New Order"
enterprise_tos_link: "Enterprise Terms of Service link"
enterprise_tos_message: "We want to work with people that share our aims and values. As such we ask new enterprises to agree to our "
@@ -3183,6 +3189,8 @@ en_GB:
stripe:
error_saving_payment: Error saving payment
submitting_payment: Submitting payment...
paypal:
no_payment_via_admin_backend: Paypal payments cannot be captured in the Backoffice
products:
image_upload_error: "The product image was not recognised. Please upload an image in PNG or JPG format."
new:
@@ -3381,6 +3389,11 @@ en_GB:
thanks: "Thank you for your order with us."
track_information: "Tracking Information: %{tracking}"
track_link: "Tracking Link: %{url}"
test_mailer:
test_email:
greeting: "Congratulations!"
message: "If you have received this email, then your email settings are correct."
subject: "Test Mail"
order_state:
address: address
adjustments: adjustments

View File

@@ -32,7 +32,7 @@ en_US:
spree/user:
attributes:
email:
taken: "There's already an account registered for this email. Please login to reset your password."
taken: "There's already an account registered for this email. Please login or reset your password."
spree/order:
no_card: There are no authorized credit cards available to charge
spree/credit_card:

View File

@@ -14,6 +14,7 @@ pt_BR:
spree/payment:
amount: Montante
state: Estado
source: Origem
spree/product:
primary_taxon: "Categoria de Produto"
supplier: "Fornecedor"
@@ -272,6 +273,9 @@ pt_BR:
on hand: "Disponível"
ship: "Envio"
shipping_category: "Tipos de Frete"
height: "Altura"
width: "Largura"
depth: "Profundidade"
actions:
create_and_add_another: "Criar e adicionar outro"
create: "Criar"
@@ -1013,7 +1017,7 @@ pt_BR:
name: Relatórios de pagamento
description: Relatórios para pagamentos
orders_and_fulfillment:
name: Relatórios de pedidos e de satisfação
name: Relatórios de pedidos e fechamento
customers:
name: Clientes
products_and_inventory:
@@ -1036,6 +1040,9 @@ pt_BR:
subscriptions:
index:
title: "Assinaturas"
new: "Nova Assinatura"
new:
title: "Nova Assinatura"
edit:
title: "Editar assinatura"
table:
@@ -1060,6 +1067,8 @@ pt_BR:
create_at_least_one_schedule_step_3: 3. Clique em "Novo cronograma" e preencha o formulário
once_you_are_done_you_can_html: Quando terminar, você pode %{reload_this_page_link}
reload_this_page: recarregar esta página
form:
create: "Criar Assinatura"
steps:
details: 1. Detalhes Básicos
address: 2. Endereço
@@ -1206,14 +1215,14 @@ pt_BR:
invoice_column_price_without_taxes: "Preço total (sem taxas)"
invoice_column_tax_rate: "Taxa de imposto"
invoice_tax_total: "Total de Imposto sobre Bens e Serviços"
tax_invoice: "NOTA FISCAL"
tax_invoice: "FATURA"
tax_total: "Total de imposto (%{rate}):"
total_excl_tax: "Total (sem imposto):"
total_incl_tax: "Total (com imposto):"
abn: "CNPJ"
acn: "CNPJ:"
invoice_issued_on: "Nota fiscal emitida em:"
order_number: "Número da nota fiscal:"
invoice_issued_on: "Fatura emitida em:"
order_number: "Número da fatura:"
date_of_transaction: "Dia da transação:"
ticket_column_qty: "Qtd"
ticket_column_item: "Ítem"
@@ -1526,7 +1535,7 @@ pt_BR:
shopping_contact_social: "Seguir"
shopping_groups_part_of: "é parte de:"
shopping_producers_of_hub: "produtores de %{hub}:"
enterprises_next_closing: "Próximo fechamento de pedido"
enterprises_next_closing: "Próximo fechamento"
enterprises_ready_for: "Pronto para"
enterprises_choose: "Escolha para quando você quer seu pedido:"
maps_open: "Aberto"
@@ -1960,6 +1969,7 @@ pt_BR:
supplier: "Fornecedor"
product_name: "Nome do Produto"
product_description: "Descrição do Produto"
permalink: "Permalink"
shipping_categories: "Categorias de Remessa"
units: "Unidade de medida"
coordinator: "Coordenador"
@@ -2057,6 +2067,7 @@ pt_BR:
remove_tax: "Remover taxa"
first_name_begins_with: "O primeiro nome começa com"
last_name_begins_with: "O sobrenome começa com"
shipping_method: "Método de Envio"
new_order: "Novo Pedido"
enterprise_tos_link: "Link de Termos de Serviço da iniciativa"
enterprise_tos_message: "Queremos trabalhar com pessoas que compartilham nossos objetivos e valores. Como tal, pedimos às novas iniciativas que concordem com nossos"
@@ -3065,7 +3076,7 @@ pt_BR:
email: "Email do cliente"
invoice:
issued_on: "Emitida em"
tax_invoice: "NOTA FISCAL"
tax_invoice: "FATURA"
code: "Código"
from: "De"
to: "Informações de cobrança"
@@ -3373,6 +3384,11 @@ pt_BR:
thanks: "Agradeço pelos seus serviços."
track_information: "Informações de rastreamento: %{tracking}"
track_link: "Link de rastreamento: %{url}"
test_mailer:
test_email:
greeting: "Parabéns!"
message: "Se você recebeu este email, então as suas configurações de email estão corretas."
subject: "Email Teste"
order_state:
address: endereço
adjustments: ajustes

View File

@@ -1885,7 +1885,7 @@ tr:
twitter: "Twitter"
twitter_placeholder: "Örn. @twitter_ciftlik"
instagram: "Instagram"
instagram_placeholder: "Örn. @instagram_ciftlik"
instagram_placeholder: "Örn. instagram_ciftlik"
limit_reached:
headline: "Hayır!"
message: "Sınıra ulaştınız!"

View File

@@ -0,0 +1,184 @@
# frozen_string_literal: true
module OrderManagement
module Order
class Updater
attr_reader :order
delegate :payments, :line_items, :adjustments, :shipments, :update_hooks, to: :order
def initialize(order)
@order = order
end
# This is a multi-purpose method for processing logic related to changes in the Order.
# It is meant to be called from various observers so that the Order is aware of changes
# that affect totals and other values stored in the Order.
#
# This method should never do anything to the Order that results in a save call on the
# object with callbacks (otherwise you will end up in an infinite recursion as the
# associations try to save and then in turn try to call +update!+ again.)
def update
update_totals
if order.completed?
update_payment_state
# give each of the shipments a chance to update themselves
shipments.each { |shipment| shipment.update!(order) }
update_shipment_state
end
update_all_adjustments
# update totals a second time in case updated adjustments have an effect on the total
update_totals
order.update_attributes_without_callbacks(
payment_state: order.payment_state,
shipment_state: order.shipment_state,
item_total: order.item_total,
adjustment_total: order.adjustment_total,
payment_total: order.payment_total,
total: order.total
)
run_hooks
end
def run_hooks
update_hooks.each { |hook| order.__send__(hook) }
end
# Updates the following Order total values:
#
# - payment_total - total value of all finalized Payments (excludes non-finalized Payments)
# - item_total - total value of all LineItems
# - adjustment_total - total value of all adjustments
# - total - order total, it's the equivalent to item_total plus adjustment_total
def update_totals
order.payment_total = payments.completed.map(&:amount).sum
order.item_total = line_items.map(&:amount).sum
order.adjustment_total = adjustments.eligible.map(&:amount).sum
order.total = order.item_total + order.adjustment_total
end
# Updates the +shipment_state+ attribute according to the following logic:
#
# - shipped - when the order shipment is in the "shipped" state
# - ready - when the order shipment is in the "ready" state
# - backorder - when there is backordered inventory associated with an order
# - pending - when the shipment is in the "pending" state
#
# The +shipment_state+ value helps with reporting, etc. since it provides a quick and easy way
# to locate Orders needing attention.
def update_shipment_state
order.shipment_state = if order.shipment&.backordered?
'backorder'
else
# It returns nil if there is no shipment
order.shipment&.state
end
order.state_changed('shipment')
end
# Updates the +payment_state+ attribute according to the following logic:
#
# - paid - when +payment_total+ is equal to +total+
# - balance_due - when +payment_total+ is less than +total+
# - credit_owed - when +payment_total+ is greater than +total+
# - failed - when most recent payment is in the failed state
#
# The +payment_state+ value helps with reporting, etc. since it provides a quick and easy way
# to locate Orders needing attention.
def update_payment_state
last_payment_state = order.payment_state
order.payment_state = infer_payment_state
track_payment_state_change(last_payment_state)
order.payment_state
end
def update_all_adjustments
order.adjustments.reload.each(&:update!)
end
def before_save_hook
shipping_address_from_distributor
end
# Sets the distributor's address as shipping address of the order for those
# shipments using a shipping method that doesn't require address, such us
# a pickup.
def shipping_address_from_distributor
return if order.shipping_method.blank? || order.shipping_method.require_ship_address
order.ship_address = order.address_from_distributor
end
private
def round_money(value)
(value * 100).round / 100.0
end
def infer_payment_state
if failed_payments?
'failed'
elsif canceled_and_not_paid_for?
'void'
else
infer_payment_state_from_balance
end
end
def infer_payment_state_from_balance
# This part added so that we don't need to override
# order.outstanding_balance
balance = order.outstanding_balance
balance = -1 * order.payment_total if canceled_and_paid_for?
infer_state(balance)
end
def infer_state(balance)
if balance.positive?
'balance_due'
elsif balance.negative?
'credit_owed'
elsif balance.zero?
'paid'
end
end
# Tracks the state transition through a state_change for this order. It
# does so until the last state is reached. That is, when the infered next
# state is the same as the order has now.
#
# @param last_payment_state [String]
def track_payment_state_change(last_payment_state)
return if last_payment_state == order.payment_state
order.state_changed('payment')
end
# Taken from order.outstanding_balance in Spree 2.4
# See: https://github.com/spree/spree/commit/7b264acff7824f5b3dc6651c106631d8f30b147a
def canceled_and_paid_for?
order.canceled? && paid?
end
def canceled_and_not_paid_for?
order.state == 'canceled' && order.payment_total.zero?
end
def paid?
payments.present? && !payments.completed.empty?
end
def failed_payments?
payments.present? && payments.valid.empty?
end
end
end
end

View File

@@ -0,0 +1,275 @@
# frozen_string_literal: true
require 'spec_helper'
module OrderManagement
module Order
describe Updater do
let(:order) { build(:order) }
let(:updater) { OrderManagement::Order::Updater.new(order) }
before { allow(order).to receive(:backordered?) { false } }
it "updates totals" do
payments = [double(amount: 5), double(amount: 5)]
allow(order).to receive_message_chain(:payments, :completed).and_return(payments)
line_items = [double(amount: 10), double(amount: 20)]
allow(order).to receive_messages line_items: line_items
adjustments = [double(amount: 10), double(amount: -20)]
allow(order).to receive_message_chain(:adjustments, :eligible).and_return(adjustments)
updater.update_totals
expect(order.payment_total).to eq 10
expect(order.item_total).to eq 30
expect(order.adjustment_total).to eq(-10)
expect(order.total).to eq 20
end
context "updating shipment state" do
let(:shipment) { build(:shipment) }
before do
allow(order).to receive(:shipments).and_return([shipment])
end
it "is backordered" do
allow(shipment).to receive(:backordered?) { true }
updater.update_shipment_state
expect(order.shipment_state).to eq 'backorder'
end
it "is nil" do
allow(shipment).to receive(:state).and_return(nil)
updater.update_shipment_state
expect(order.shipment_state).to be_nil
end
["shipped", "ready", "pending"].each do |state|
it "is #{state}" do
allow(shipment).to receive(:state).and_return(state)
updater.update_shipment_state
expect(order.shipment_state).to eq state.to_s
end
end
end
it "state change" do
order = create(:order)
order.shipment_state = 'shipped'
state_changes = double
allow(order).to receive(:state_changes) { state_changes }
expect(state_changes).to receive(:create).with(
previous_state: nil,
next_state: 'shipped',
name: 'shipment',
user_id: order.user_id
)
order.state_changed('shipment')
end
context "completed order" do
before { allow(order).to receive(:completed?) { true } }
it "updates payment state" do
expect(updater).to receive(:update_payment_state)
updater.update
end
it "updates shipment state" do
expect(updater).to receive(:update_shipment_state)
updater.update
end
it "updates the order shipment" do
shipment = build(:shipment)
allow(order).to receive_messages shipments: [shipment]
expect(shipment).to receive(:update!).with(order)
updater.update
end
end
context "incompleted order" do
before { allow(order).to receive_messages completed?: false }
it "doesnt update payment state" do
expect(updater).not_to receive(:update_payment_state)
updater.update
end
it "doesnt update shipment state" do
expect(updater).not_to receive(:update_shipment_state)
updater.update
end
it "doesnt update the order shipment" do
shipment = build(:shipment)
allow(order).to receive_messages shipments: [shipment]
expect(shipment).not_to receive(:update!).with(order)
updater.update
end
end
it "updates totals twice" do
expect(updater).to receive(:update_totals).twice
updater.update
end
it "updates all adjustments" do
expect(updater).to receive(:update_all_adjustments)
updater.update
end
it "is failed if no valid payments" do
allow(order).to receive_message_chain(:payments, :valid, :empty?).and_return(true)
updater.update_payment_state
expect(order.payment_state).to eq('failed')
end
context "payment total is greater than order total" do
it "is credit_owed" do
order.payment_total = 2
order.total = 1
expect {
updater.update_payment_state
}.to change { order.payment_state }.to 'credit_owed'
end
end
context "order total is greater than payment total" do
it "is credit_owed" do
order.payment_total = 1
order.total = 2
expect {
updater.update_payment_state
}.to change { order.payment_state }.to 'balance_due'
end
end
context "order total equals payment total" do
it "is paid" do
order.payment_total = 30
order.total = 30
expect {
updater.update_payment_state
}.to change { order.payment_state }.to 'paid'
end
end
context "order is canceled" do
before do
order.state = 'canceled'
end
context "and is still unpaid" do
it "is void" do
order.payment_total = 0
order.total = 30
expect {
updater.update_payment_state
}.to change { order.payment_state }.to 'void'
end
end
context "and is paid" do
it "is credit_owed" do
order.payment_total = 30
order.total = 30
allow(order).to receive_message_chain(:payments, :valid, :empty?).and_return(false)
allow(order).to receive_message_chain(:payments, :completed, :empty?).and_return(false)
expect {
updater.update_payment_state
}.to change { order.payment_state }.to 'credit_owed'
end
end
context "and payment is refunded" do
it "is void" do
order.payment_total = 0
order.total = 30
allow(order).to receive_message_chain(:payments, :valid, :empty?).and_return(false)
allow(order).to receive_message_chain(:payments, :completed, :empty?).and_return(false)
expect {
updater.update_payment_state
}.to change { order.payment_state }.to 'void'
end
end
end
context 'when the set payment_state does not match the last payment_state' do
before { order.payment_state = 'previous_to_paid' }
context 'and the order is being updated' do
before { allow(order).to receive(:persisted?) { true } }
it 'creates a new state_change for the order' do
expect { updater.update_payment_state }
.to change { order.state_changes.size }.by(1)
end
end
context 'and the order is being created' do
before { allow(order).to receive(:persisted?) { false } }
it 'creates a new state_change for the order' do
expect { updater.update_payment_state }
.not_to change { order.state_changes.size }
end
end
end
context 'when the set payment_state matches the last payment_state' do
before { order.payment_state = 'paid' }
it 'does not create any state_change' do
expect { updater.update_payment_state }
.not_to change { order.state_changes.size }
end
end
context '#before_save_hook' do
let(:distributor) { build(:distributor_enterprise) }
let(:shipment) {
create(:shipment_with, :shipping_method, shipping_method: shipping_method)
}
before do
order.distributor = distributor
order.shipments = [shipment]
end
context 'when shipping method is pickup' do
let(:shipping_method) { create(:shipping_method_with, :pickup) }
let(:address) { build(:address, firstname: 'joe') }
before { distributor.address = address }
it "populates the shipping address from distributor" do
updater.before_save_hook
expect(order.ship_address.address1).to eq(distributor.address.address1)
end
end
context 'when shipping_method is delivery' do
let(:shipping_method) { create(:shipping_method_with, :delivery) }
let(:address) { build(:address, firstname: 'will') }
before { order.ship_address = address }
it "does not populate the shipping address from distributor" do
updater.before_save_hook
expect(order.ship_address.firstname).to eq("will")
end
end
end
end
end
end

View File

@@ -113,7 +113,6 @@
"spec/models/subscription_line_item_spec.rb": 0.021193265914916992,
"spec/controllers/api/statuses_controller_spec.rb": 0.02451467514038086,
"spec/lib/open_food_network/referer_parser_spec.rb": 0.015799283981323242,
"spec/lib/open_food_network/reports/rule_spec.rb": 0.01628732681274414,
"spec/helpers/serializer_helper_spec.rb": 0.004682064056396484,
"spec/jobs/heartbeat_job_spec.rb": 0.013271570205688477,
"spec/services/mail_configuration_spec.rb": 0.01050567626953125,
@@ -246,7 +245,6 @@
"spec/validators/integer_array_validator_spec.rb": 0.04994392395019531,
"spec/validators/date_time_string_validator_spec.rb": 0.05316734313964844,
"spec/models/product_import/reset_absent_spec.rb": 0.04071307182312012,
"spec/lib/open_food_network/reports/report_spec.rb": 0.04329681396484375,
"spec/jobs/confirm_signup_job_spec.rb": 0.03060293197631836,
"spec/services/order_cycle_distributed_variants_spec.rb": 0.02808237075805664,
"spec/lib/open_food_network/feature_toggle_spec.rb": 0.0240786075592041,
@@ -255,7 +253,6 @@
"spec/models/spree/calculator/flat_rate_spec.rb": 0.014808177947998047,
"spec/models/spree/image_spec.rb": 0.014715909957885742,
"spec/helpers/spree/admin/base_helper_spec.rb": 0.008042573928833008,
"spec/lib/open_food_network/reports/row_spec.rb": 0.005358695983886719,
"engines/order_management/spec/controllers/order_management/reports/enterprise_fee_summaries_controller_spec.rb": 0.7100100517272949,
"engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/parameters_spec.rb": 4.190261602401733,
"engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/report_data/enterprise_fee_type_total_spec.rb": 0.006247282028198242,

View File

@@ -1,8 +0,0 @@
module OpenFoodNetwork
module ModelClassFromControllerName
# Equivalent to CanCan's "authorize_resource :class => false" (see https://github.com/ryanb/cancan/blob/master/lib/cancan/controller_resource.rb#L146)
def model_class
self.class.to_s.sub("Controller", "").underscore.split('/').last.singularize.to_sym
end
end
end

View File

@@ -1,35 +0,0 @@
require 'open_food_network/reports/row'
require 'open_food_network/reports/rule'
module OpenFoodNetwork::Reports
class Report
class_attribute :_header, :_columns, :_rules_head
# -- API
def header
_header
end
def columns
_columns.to_a
end
def rules
# Flatten linked list and return as hashes
rules = []
rule = _rules_head
while rule
rules << rule
rule = rule.next
end
rules.map(&:to_h)
end
# -- DSL
def self.header(*columns)
self._header = columns
end
end
end

View File

@@ -1,15 +0,0 @@
module OpenFoodNetwork::Reports
class Row
def initialize
@columns = []
end
def column(&block)
@columns << block
end
def to_a
@columns
end
end
end

View File

@@ -1,21 +0,0 @@
require 'open_food_network/reports/row'
module OpenFoodNetwork::Reports
class Rule
attr_reader :next
def group(&block)
@group = block
end
def sort(&block)
@sort = block
end
def to_h
h = { group_by: @group, sort_by: @sort }
h[:summary_columns] = @summary_row.to_a if @summary_row
h
end
end
end

58
lib/spree/core.rb Normal file
View File

@@ -0,0 +1,58 @@
# frozen_string_literal: true
require 'rails/all'
require 'active_merchant'
require 'acts_as_list'
require 'awesome_nested_set'
require 'cancan'
require 'kaminari'
require 'mail'
require 'paperclip'
require 'paranoia'
require 'ransack'
require 'state_machine'
module Spree
mattr_accessor :user_class
def self.user_class
if @@user_class.is_a?(Class)
raise "Spree.user_class MUST be a String object, not a Class object."
end
return unless @@user_class.is_a?(String)
@@user_class.constantize
end
# Used to configure Spree.
#
# Example:
#
# Spree.config do |config|
# config.site_name = "An awesome Spree site"
# end
#
# This method is defined within the core gem on purpose.
# Some people may only wish to use the Core part of Spree.
def self.config
yield(Spree::Config)
end
end
require 'spree/core/version'
require 'spree/core/engine'
require 'spree/i18n'
require 'spree/money'
require 'spree/core/delegate_belongs_to'
require 'spree/core/ext/active_record'
require 'spree/core/permalinks'
require 'spree/core/token_resource'
require 'spree/core/calculated_adjustments'
require 'spree/core/product_duplicator'
ActiveRecord::Base.class_eval do
include CollectiveIdea::Acts::NestedSet
end

View File

@@ -0,0 +1,81 @@
# frozen_string_literal: true
module Spree
module Core
module CalculatedAdjustments
def self.included(klass)
klass.class_eval do
has_one :calculator, class_name: "Spree::Calculator", as: :calculable, dependent: :destroy
accepts_nested_attributes_for :calculator
validates :calculator, presence: true
def self.calculators
spree_calculators.__send__(model_name_without_spree_namespace)
end
def calculator_type
calculator.class.to_s if calculator
end
def calculator_type=(calculator_type)
klass = calculator_type.constantize if calculator_type
self.calculator = klass.new if klass && !calculator.is_a?(klass)
end
# Creates a new adjustment for the target object
# (which is any class that has_many :adjustments) and sets amount based on the
# calculator as applied to the given calculable (Order, LineItems[], Shipment, etc.)
# By default the adjustment will not be considered mandatory
def create_adjustment(label, target, calculable, mandatory = false, state = "closed")
# Adjustment calculations done on Spree::Shipment objects MUST
# be done on their to_package'd variants instead
# It's only the package that contains the correct information.
# See https://github.com/spree/spree_active_shipping/pull/96 et. al
old_calculable = calculable
calculable = calculable.to_package if calculable.is_a?(Spree::Shipment)
amount = compute_amount(calculable)
return if amount.zero? && !mandatory
target.adjustments.create(
amount: amount,
source: old_calculable,
originator: self,
label: label,
mandatory: mandatory,
state: state
)
end
# Updates the amount of the adjustment using our Calculator and
# calling the +compute+ method with the +calculable+
# referenced passed to the method.
def update_adjustment(adjustment, calculable)
# Adjustment calculations done on Spree::Shipment objects MUST
# be done on their to_package'd variants instead
# It's only the package that contains the correct information.
# See https://github.com/spree/spree_active_shipping/pull/96 et. al
calculable = calculable.to_package if calculable.is_a?(Spree::Shipment)
adjustment.update_column(:amount, compute_amount(calculable))
end
# Calculate the amount to be used when creating an adjustment
# NOTE: May be overriden by classes where this module is included into.
# Such as Spree::Promotion::Action::CreateAdjustment.
def compute_amount(calculable)
calculator.compute(calculable)
end
def self.model_name_without_spree_namespace
to_s.tableize.gsub('/', '_').sub('spree_', '')
end
private_class_method :model_name_without_spree_namespace
def self.spree_calculators
Rails.application.config.spree.calculators
end
private_class_method :spree_calculators
end
end
end
end
end

View File

@@ -68,8 +68,7 @@ module Spree
session[:guest_token] = nil
end
# Do not attempt to merge incomplete and current orders.
# Instead, destroy the incomplete orders.
# Recover incomplete orders from other sessions after logging in.
def set_current_order
return unless (user = spree_current_user)
@@ -77,11 +76,10 @@ module Spree
if session[:order_id].nil? && last_incomplete_order
session[:order_id] = last_incomplete_order.id
elsif current_order(true) &&
last_incomplete_order &&
current_order != last_incomplete_order
last_incomplete_order.destroy
end
# Load current order and create a new one if necessary.
current_order(true)
end
def current_currency

View File

@@ -0,0 +1,94 @@
# frozen_string_literal: true
##
# Creates methods on object which delegate to an association proxy.
# see delegate_belongs_to for two uses
#
# Todo - integrate with ActiveRecord::Dirty to make sure changes to delegate object are noticed
# Should do
# class User < ActiveRecord::Base; delegate_belongs_to :contact, :firstname; end
# class Contact < ActiveRecord::Base; end
# u = User.first
# u.changed? # => false
# u.firstname = 'Bobby'
# u.changed? # => true
#
# Right now the second call to changed? would return false
#
# Todo - add has_one support. fairly straightforward addition
##
module DelegateBelongsTo
extend ActiveSupport::Concern
module ClassMethods
@@default_rejected_delegate_columns = ['created_at', 'created_on', 'updated_at',
'updated_on', 'lock_version', 'type', 'id',
'position', 'parent_id', 'lft', 'rgt']
mattr_accessor :default_rejected_delegate_columns
##
# Creates methods for accessing and setting attributes on an association. Uses same
# default list of attributes as delegates_to_association.
# delegate_belongs_to :contact
# delegate_belongs_to :contact, [:defaults] ## same as above, and useless
# delegate_belongs_to :contact, [:defaults, :address, :fullname], :class_name => 'VCard'
##
def delegate_belongs_to(association, *attrs)
opts = attrs.extract_options!
initialize_association :belongs_to, association, opts
attrs = get_association_column_names(association) if attrs.empty?
attrs.concat get_association_column_names(association) if attrs.delete :defaults
attrs.each do |attr|
class_def attr do |*args|
if args.empty?
__send__(:delegator_for, association).__send__(attr)
else
__send__(:delegator_for, association).__send__(attr, *args)
end
end
class_def "#{attr}=" do |val|
__send__(:delegator_for, association).__send__("#{attr}=", val)
end
end
end
protected
def get_association_column_names(association, without_default_rejected_delegate_columns = true)
association_klass = reflect_on_association(association).klass
methods = association_klass.column_names
if without_default_rejected_delegate_columns
methods.reject!{ |x| default_rejected_delegate_columns.include?(x.to_s) }
end
methods
rescue
[]
end
##
# initialize_association :belongs_to, :contact
def initialize_association(type, association, opts = {})
unless [:belongs_to].include?(type.to_s.to_sym)
raise 'Illegal or unimplemented association type.'
end
__send__(type, association, opts) if reflect_on_association(association).nil?
end
private
def class_def(name, method = nil, &blk)
class_eval { method.nil? ? define_method(name, &blk) : define_method(name, method) }
end
end
def delegator_for(association)
if __send__(association).nil?
__send__("#{association}=", self.class.reflect_on_association(association).klass.new)
end
__send__(association)
end
protected :delegator_for
end
ActiveRecord::Base.include(DelegateBelongsTo)

View File

@@ -0,0 +1,13 @@
# frozen_string_literal: true
module Spree
module Core
class Environment
class Calculators
include EnvironmentExtension
attr_accessor :shipping_methods, :tax_rates
end
end
end
end

View File

@@ -0,0 +1,27 @@
# frozen_string_literal: true
module Spree
module Core
module EnvironmentExtension
extend ActiveSupport::Concern
def add_class(name)
instance_variable_set "@#{name}", Set.new
create_method( "#{name}=".to_sym ) { |val|
instance_variable_set( "@" + name, val)
}
create_method(name.to_sym) do
instance_variable_get( "@" + name )
end
end
private
def create_method(name, &block)
self.class.__send__(:define_method, name, &block)
end
end
end
end

View File

@@ -0,0 +1,7 @@
# frozen_string_literal: true
module Spree
module Core
class GatewayError < RuntimeError; end
end
end

View File

@@ -0,0 +1,24 @@
# frozen_string_literal: true
# Allows us to intercept any outbound mail message and make last minute changes
# (such as specifying a "from" address or sending to a test email account)
#
# See http://railscasts.com/episodes/206-action-mailer-in-rails-3 for more details.
module Spree
module Core
class MailInterceptor
def self.delivering_email(message)
return unless MailSettings.override?
if Config[:intercept_email].present?
message.subject = "#{message.to} #{message.subject}"
message.to = Config[:intercept_email]
end
return if Config[:mail_bcc].blank?
message.bcc ||= Config[:mail_bcc]
end
end
end
end

View File

@@ -0,0 +1,63 @@
# frozen_string_literal: true
module Spree
module Core
class MailSettings
MAIL_AUTH = ['None', 'plain', 'login', 'cram_md5'].freeze
SECURE_CONNECTION_TYPES = ['None', 'SSL', 'TLS'].freeze
# Override the Rails application mail settings based on preferences
# This makes it possible to configure the mail settings through an admin
# interface instead of requiring changes to the Rails envrionment file
def self.init
new.override! if override?
end
def self.override?
Config.override_actionmailer_config
end
def override!
if Config.enable_mail_delivery
ActionMailer::Base.default_url_options[:host] ||= Config.site_url
ActionMailer::Base.smtp_settings = mail_server_settings
ActionMailer::Base.perform_deliveries = true
else
ActionMailer::Base.perform_deliveries = false
end
end
private
def mail_server_settings
settings = if need_authentication?
basic_settings.merge(user_credentials)
else
basic_settings
end
settings.merge(enable_starttls_auto: secure_connection?)
end
def user_credentials
{ user_name: Config.smtp_username,
password: Config.smtp_password }
end
def basic_settings
{ address: Config.mail_host,
domain: Config.mail_domain,
port: Config.mail_port,
authentication: Config.mail_auth_type }
end
def need_authentication?
Config.mail_auth_type != 'None'
end
def secure_connection?
Config.secure_connection_type == 'TLS'
end
end
end
end

View File

@@ -0,0 +1,75 @@
# frozen_string_literal: true
require 'stringex'
module Spree
module Core
module Permalinks
extend ActiveSupport::Concern
included do
class_attribute :permalink_options
end
module ClassMethods
def make_permalink(options = {})
options[:field] ||= :permalink
self.permalink_options = options
return unless connected? &&
table_exists? &&
column_names.include?(permalink_options[:field].to_s)
before_validation(on: :create) { save_permalink }
end
def find_by_param(value, *args)
__send__("find_by_#{permalink_field}", value, *args)
end
def find_by_param!(value, *args)
__send__("find_by_#{permalink_field}!", value, *args)
end
def permalink_field
permalink_options[:field]
end
def permalink_prefix
permalink_options[:prefix] || ""
end
def permalink_order
order = permalink_options[:order]
"#{order} ASC," if order
end
end
def generate_permalink
"#{self.class.permalink_prefix}#{Array.new(9) { rand(9) }.join}"
end
def save_permalink(permalink_value = to_param)
with_lock do
permalink_value ||= generate_permalink
field = self.class.permalink_field
# Do other links exist with this permalink?
other = self.class.
where("#{self.class.table_name}.#{field} LIKE ?", "#{permalink_value}%")
if other.any?
# Find the existing permalink with the highest number, and increment that number.
# (If none of the existing permalinks have a number, this will evaluate to 1.)
number = other.map { |o| o.__send__(field)[/-(\d+)$/, 1].to_i }.max + 1
permalink_value += "-#{number}"
end
write_attribute(field, permalink_value)
end
end
end
end
end
ActiveRecord::Base.include(Spree::Core::Permalinks)
ActiveRecord::Relation.include(Spree::Core::Permalinks)

View File

@@ -0,0 +1,35 @@
# frozen_string_literal: true
module Spree
module Core
# This module exists to reduce duplication in S3 settings between
# the Image and Taxon models in Spree
module S3Support
extend ActiveSupport::Concern
included do
def self.supports_s3(field)
# Load user defined paperclip settings
config = Spree::Config
return unless config[:use_s3]
s3_creds = { access_key_id: config[:s3_access_key],
secret_access_key: config[:s3_secret],
bucket: config[:s3_bucket] }
attachment_definitions[field][:storage] = :s3
attachment_definitions[field][:s3_credentials] = s3_creds
attachment_definitions[field][:s3_headers] = ActiveSupport::JSON.
decode(config[:s3_headers])
attachment_definitions[field][:bucket] = config[:s3_bucket]
if config[:s3_protocol].present?
attachment_definitions[field][:s3_protocol] = config[:s3_protocol].downcase
end
return if config[:s3_host_alias].blank?
attachment_definitions[field][:s3_host_alias] = config[:s3_host_alias]
end
end
end
end
end

View File

@@ -0,0 +1,28 @@
# frozen_string_literal: true
module Spree
module Core
module TokenResource
module ClassMethods
def token_resource
has_one :tokenized_permission, as: :permissable
delegate :token, to: :tokenized_permission, allow_nil: true
after_create :create_token
end
end
def create_token
permission = build_tokenized_permission
permission.token = token = ::SecureRandom.hex(8)
permission.save!
token
end
def self.included(receiver)
receiver.extend ClassMethods
end
end
end
end
ActiveRecord::Base.class_eval { include Spree::Core::TokenResource }

38
lib/spree/i18n.rb Normal file
View File

@@ -0,0 +1,38 @@
# frozen_string_literal: true
require 'i18n'
require 'active_support/core_ext/array/extract_options'
require 'spree/i18n/base'
module Spree
extend ActionView::Helpers::TranslationHelper
class << self
# Add spree namespace and delegate to Rails TranslationHelper for some nice
# extra functionality. e.g return reasonable strings for missing translations
def translate(*args)
@virtual_path = virtual_path
options = args.extract_options!
options[:scope] = [*options[:scope]].unshift(:spree)
args << options
super(*args)
end
alias_method :t, :translate
def context
Spree::ViewContext.context
end
def virtual_path
return unless context
path = context.instance_variable_get("@virtual_path")
return unless path
path.gsub(/spree/, '')
end
end
end

19
lib/spree/i18n/base.rb Normal file
View File

@@ -0,0 +1,19 @@
# frozen_string_literal: true
module Spree
module ViewContext
def self.context=(context)
@context = context
end
def self.context
@context
end
def view_context
super.tap do |context|
Spree::ViewContext.context = context
end
end
end
end

View File

@@ -0,0 +1,3 @@
# frozen_string_literal: true
Spree::BaseController.include(Spree::ViewContext)

42
lib/spree/money.rb Normal file
View File

@@ -0,0 +1,42 @@
# frozen_string_literal: false
require 'money'
module Spree
class Money
attr_reader :money
delegate :cents, to: :money
def initialize(amount, options = {})
@money = ::Money.parse([amount, (options[:currency] || Spree::Config[:currency])].join)
@options = {}
@options[:with_currency] = Spree::Config[:display_currency]
@options[:symbol_position] = Spree::Config[:currency_symbol_position].to_sym
@options[:no_cents] = Spree::Config[:hide_cents]
@options[:decimal_mark] = Spree::Config[:currency_decimal_mark]
@options[:thousands_separator] = Spree::Config[:currency_thousands_separator]
@options.merge!(options)
# Must be a symbol because the Money gem doesn't do the conversion
@options[:symbol_position] = @options[:symbol_position].to_sym
end
def to_s
@money.format(@options)
end
def to_html(options = { html: true })
output = @money.format(@options.merge(options))
if options[:html]
# 1) prevent blank, breaking spaces
# 2) prevent escaping of HTML character entities
output = output.gsub(" ", "&nbsp;").html_safe
end
output
end
def ==(other)
@money == other.money
end
end
end

View File

@@ -0,0 +1,63 @@
# frozen_string_literal: true
module Spree
class ProductDuplicator
attr_accessor :product
def initialize(product)
@product = product
end
def duplicate
new_product = duplicate_product
# don't dup the actual variants, just the characterising types
new_product.option_types = product.option_types if product.has_variants?
# allow site to do some customization
new_product.__send__(:duplicate_extra, product) if new_product.respond_to?(:duplicate_extra)
new_product.save!
new_product
end
protected
def duplicate_product
product.dup.tap do |new_product|
new_product.name = "COPY OF #{product.name}"
new_product.taxons = product.taxons
new_product.created_at = nil
new_product.deleted_at = nil
new_product.updated_at = nil
new_product.product_properties = reset_properties
new_product.master = duplicate_master
end
end
def duplicate_master
master = product.master
master.dup.tap do |new_master|
new_master.sku = "COPY OF #{master.sku}"
new_master.deleted_at = nil
new_master.images = master.images.map { |image| duplicate_image image }
new_master.price = master.price
new_master.currency = master.currency
end
end
def duplicate_image(image)
new_image = image.dup
new_image.assign_attributes(attachment: image.attachment.clone)
new_image
end
def reset_properties
product.product_properties.map do |prop|
prop.dup.tap do |new_prop|
new_prop.created_at = nil
new_prop.updated_at = nil
end
end
end
end
end

57
lib/spree/responder.rb Normal file
View File

@@ -0,0 +1,57 @@
# frozen_string_literal: true
module Spree
class Responder < ::ActionController::Responder #:nodoc:
attr_accessor :on_success, :on_failure
def initialize(controller, resources, options = {})
super
class_name = controller.class.name.to_sym
action_name = options.delete(:action_name)
result = Spree::BaseController.spree_responders[class_name].
try(:[], action_name).
try(:[], self.format.to_sym)
return unless result
self.on_success = handler(controller, result, :success)
self.on_failure = handler(controller, result, :failure)
end
def to_html
if !(on_success || on_failure)
super
return
end
has_errors? ? controller.instance_exec(&on_failure) : controller.instance_exec(&on_success)
end
def to_format
if !(on_success || on_failure)
super
return
end
has_errors? ? controller.instance_exec(&on_failure) : controller.instance_exec(&on_success)
end
private
def handler(controller, result, status)
return result if result.respond_to? :call
case result
when Hash
if result[status].is_a? Symbol
controller.method(result[status])
else
result[status]
end
when Symbol
controller.method(result)
end
end
end
end

View File

@@ -9,6 +9,90 @@ describe BaseController, type: :controller do
end
end
describe "#current_order" do
let(:user) { create(:user) }
it "doesn't change anything without a user" do
expect {
get :index
}.to_not change { Spree::Order.count }
end
it "creates a new order" do
allow(controller).to receive(:spree_current_user).and_return(user)
expect {
get :index
}.to change { Spree::Order.count }.by(1)
expect(user.orders.count).to eq 1
end
it "uses the last incomplete order" do
last_cart = create(:order, user: user, created_by: user, state: "cart", completed_at: nil)
allow(controller).to receive(:spree_current_user).and_return(user)
expect {
get :index
}.to_not change { Spree::Order.count }
expect(session[:order_id]).to eq last_cart.id
end
it "ignores the last incomplete order" do
# Spree used to merge the last order with the current one.
# And we used to override that logic to delete old incomplete orders.
# Now we are checking here that none of that is happening.
last_cart = create(:order, user: user, created_by: user, state: "cart", completed_at: nil)
last_cart.line_items << create(:line_item)
current_cart = create(
:order,
user: user,
created_by: user,
state: "cart",
completed_at: nil,
created_at: 1.week.ago
)
session[:order_id] = current_cart.id
allow(controller).to receive(:spree_current_user).and_return(user)
expect {
get :index
}.to_not change { Spree::Order.count }
expect(current_cart.line_items.count).to eq 0
end
it "doesn't recover old orders after checkout, a new empty one is created" do
last_cart = create(:order, user: user, created_by: user, state: "cart", completed_at: nil)
last_cart.line_items << create(:line_item)
just_completed_order = create(
:order,
user: user,
created_by: user,
state: "complete",
completed_at: Time.zone.now,
created_at: 1.week.ago
)
expect(just_completed_order.completed_at).to be_present
session[:order_id] = just_completed_order.id
allow(controller).to receive(:spree_current_user).and_return(user)
expect {
get :index
}.to change { Spree::Order.count }.by(1)
expect(session[:order_id]).to_not eq just_completed_order.id
expect(session[:order_id]).to_not eq last_cart.id
expect(controller.current_order.line_items.count).to eq 0
end
end
it "redirects to home with message if order cycle is expired" do
expect(controller).to receive(:current_order_cycle).and_return(oc).twice
expect(controller).to receive(:current_order).and_return(order).twice

View File

@@ -1,4 +1,6 @@
describe 'Checkout service', ->
BugsnagMock =
notify: (arg) ->
Checkout = null
orderData = null
$httpBackend = null
@@ -48,6 +50,8 @@ describe 'Checkout service', ->
ship_address: {test: "bar"}
user_id: 901
window.Bugsnag = BugsnagMock
module 'Darkswarm'
module ($provide)->
$provide.value "RailsFlashLoader", FlashLoaderMock
@@ -128,6 +132,7 @@ describe 'Checkout service', ->
expect(Checkout.errors).toEqual {error: "frogs"}
it "throws exception and sends generic flash message when there are errors but no flash message", ->
spyOn(BugsnagMock, "notify")
$httpBackend.expectPUT("/checkout.json").respond 400, {errors: {error: "broken response"}}
try
Checkout.submit()
@@ -136,9 +141,11 @@ describe 'Checkout service', ->
expect(error.data.errors.error).toBe("broken response")
expect(Checkout.errors).toEqual {}
expect(BugsnagMock.notify).toHaveBeenCalled()
it "throws an exception and sends a flash message to the flash service when reponse doesnt contain errors nor a flash message", ->
spyOn(FlashLoaderMock, "loadFlash") # Stubbing out writes to window.location
spyOn(BugsnagMock, "notify")
$httpBackend.expectPUT("/checkout.json").respond 400, "broken response"
try
Checkout.submit()
@@ -147,9 +154,11 @@ describe 'Checkout service', ->
expect(error.data).toBe("broken response")
expect(FlashLoaderMock.loadFlash).toHaveBeenCalledWith({ error: t("checkout.failed") })
expect(BugsnagMock.notify).toHaveBeenCalled()
it "throws an exception and sends a flash message to the flash service when an exception is thrown while handling the error", ->
spyOn(FlashLoaderMock, "loadFlash") # Stubbing out writes to window.location
spyOn(BugsnagMock, "notify")
navigationSpy.and.callFake(-> throw "unexpected error")
$httpBackend.expectPUT("/checkout.json").respond 400, {path: 'path'}
try
@@ -159,6 +168,7 @@ describe 'Checkout service', ->
expect(error).toBe("unexpected error")
expect(FlashLoaderMock.loadFlash).toHaveBeenCalledWith({ error: t("checkout.failed") })
expect(BugsnagMock.notify).toHaveBeenCalled()
describe "when using the Stripe Connect gateway", ->
beforeEach inject ($injector, StripeElements) ->

View File

@@ -1,5 +1,7 @@
require "spec_helper"
require 'open_food_network/orders_and_fulfillments_report'
require 'open_food_network/orders_and_fulfillments_report/customer_totals_report'
require 'open_food_network/order_grouper'
RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::CustomerTotalsReport do
let!(:distributor) { create(:distributor_enterprise) }
@@ -79,6 +81,27 @@ RSpec.describe OpenFoodNetwork::OrdersAndFulfillmentsReport::CustomerTotalsRepor
end
end
context "displaying payment fees" do
context "with both failed and completed payments present" do
let!(:order) {
create(:order_ready_to_ship, user: customer.user,
customer: customer, distributor: distributor)
}
let(:completed_payment) { order.payments.completed.first }
let!(:failed_payment) { create(:payment, order: order, state: "failed") }
before do
completed_payment.adjustment.update amount: 123.00
failed_payment.adjustment.update amount: 456.00, eligible: false, state: "finalized"
end
it "shows the correct payment fee amount for the order" do
payment_fee_field = report_table.last[12]
expect(payment_fee_field).to eq completed_payment.adjustment.amount
end
end
end
context 'when a variant override applies' do
let!(:order) do
create(:completed_order_with_totals, line_items_count: 1, user: customer.user,

View File

@@ -1,5 +1,6 @@
require 'spec_helper'
require 'open_food_network/orders_and_fulfillments_report'
require 'open_food_network/order_grouper'
describe OpenFoodNetwork::OrdersAndFulfillmentsReport do
include AuthenticationHelper

View File

@@ -1,15 +0,0 @@
require 'open_food_network/reports/report'
module OpenFoodNetwork::Reports
class TestReport < Report
header 'One', 'Two', 'Three', 'Four'
end
describe Report do
let(:report) { TestReport.new }
it "returns the header" do
expect(report.header).to eq(%w(One Two Three Four))
end
end
end

View File

@@ -1,19 +0,0 @@
require 'spec_helper'
require 'open_food_network/reports/row'
module OpenFoodNetwork::Reports
describe Row do
let(:row) { Row.new }
# rubocop:disable Style/Proc
let(:proc) { Proc.new {} }
# rubocop:enable Style/Proc
it "can define a number of columns and return them as an array" do
row.column(&proc)
row.column(&proc)
row.column(&proc)
expect(row.to_a).to eq([proc, proc, proc])
end
end
end

View File

@@ -1,21 +0,0 @@
require 'spec_helper'
require 'open_food_network/reports/rule'
module OpenFoodNetwork::Reports
describe Rule do
let(:rule) { Rule.new }
# rubocop:disable Style/Proc
let(:proc) { Proc.new {} }
# rubocop:enable Style/Proc
it "can define a group proc and return it in a hash" do
rule.group(&proc)
expect(rule.to_h).to eq(group_by: proc, sort_by: nil)
end
it "can define a sort proc and return it in a hash" do
rule.sort(&proc)
expect(rule.to_h).to eq(group_by: nil, sort_by: proc)
end
end
end

View File

@@ -0,0 +1,73 @@
# frozen_string_literal: true
require 'spec_helper'
# Its pretty difficult to test this module in isolation b/c it needs to work in conjunction
# with an actual class that extends ActiveRecord::Base and has a corresponding table in the DB.
# So we'll just test it using Order and ShippingMethod. These classes are including the module.
describe Spree::Core::CalculatedAdjustments do
let(:calculator) { build(:calculator) }
let(:tax_rate) { Spree::TaxRate.new(calculator: calculator) }
before do
allow(calculator).to receive(:compute) { 10 }
allow(calculator).to receive(:[]) { nil }
end
it "should add has_one :calculator relationship" do
assert Spree::ShippingMethod.
reflect_on_all_associations(:has_one).map(&:name).include?(:calculator)
end
context "#create_adjustment and its resulting adjustment" do
let(:order) { Spree::Order.create }
let(:target) { order }
it "should be associated with the target" do
expect(target.adjustments).to receive(:create)
tax_rate.create_adjustment("foo", target, order)
end
it "should have the correct originator and an amount derived from the calculator and supplied calculable" do
adjustment = tax_rate.create_adjustment("foo", target, order)
expect(adjustment).not_to be_nil
expect(adjustment.amount).to eq 10
expect(adjustment.source).to eq order
expect(adjustment.originator).to eq tax_rate
end
it "should be mandatory if true is supplied for that parameter" do
adjustment = tax_rate.create_adjustment("foo", target, order, true)
expect(adjustment).to be_mandatory
end
context "when the calculator returns 0" do
before { allow(calculator).to receive_messages(compute: 0) }
context "when adjustment is mandatory" do
before { tax_rate.create_adjustment("foo", target, order, true) }
it "should create an adjustment" do
expect(Spree::Adjustment.count).to eq 1
end
end
context "when adjustment is not mandatory" do
before { tax_rate.create_adjustment("foo", target, order, false) }
it "should not create an adjustment" do
expect(Spree::Adjustment.count).to eq 0
end
end
end
end
context "#update_adjustment" do
it "should update the adjustment using its calculator (and the specified source)" do
adjustment = double(:adjustment).as_null_object
calculable = double :calculable
expect(adjustment).to receive(:update_column).with(:amount, 10)
tax_rate.update_adjustment(adjustment, calculable)
end
end
end

View File

@@ -0,0 +1,19 @@
# frozen_string_literal: true
require 'spec_helper'
describe Spree::Core::Environment do
# Our version doesn't add any features we could test.
# So we just check that our file is loaded correctly.
let(:our_file) { Rails.root.join("lib/spree/core/environment.rb").to_s }
it "is defined in our code" do
file = subject.method(:initialize).source_location.first
expect(file).to eq our_file
end
it "used by Spree" do
file = Spree::Core::Engine.config.spree.method(:initialize).source_location.first
expect(file).to eq our_file
end
end

View File

@@ -0,0 +1,82 @@
# frozen_string_literal: true
require 'spec_helper'
# Here we use the OrderMailer as a way to test the mail interceptor.
describe Spree::OrderMailer do
let(:order) do
Spree::Order.new(distributor: create(:enterprise),
bill_address: create(:address))
end
let(:message) { Spree::OrderMailer.confirm_email_for_shop(order) }
before(:all) do
ActionMailer::Base.perform_deliveries = true
ActionMailer::Base.deliveries.clear
end
context "#deliver" do
before do
ActionMailer::Base.delivery_method = :test
end
after { ActionMailer::Base.deliveries.clear }
it "should use the from address specified in the preference" do
Spree::Config[:mails_from] = "no-reply@foobar.com"
message.deliver
@email = ActionMailer::Base.deliveries.first
expect(@email.from).to eq ["no-reply@foobar.com"]
end
it "should use the provided from address" do
Spree::Config[:mails_from] = "preference@foobar.com"
message.from = "override@foobar.com"
message.to = "test@test.com"
message.deliver
email = ActionMailer::Base.deliveries.first
expect(email.from).to eq ["override@foobar.com"]
expect(email.to).to eq ["test@test.com"]
end
it "should add the bcc email when provided" do
Spree::Config[:mail_bcc] = "bcc-foo@foobar.com"
message.deliver
@email = ActionMailer::Base.deliveries.first
expect(@email.bcc).to eq ["bcc-foo@foobar.com"]
end
context "when intercept_email is provided" do
it "should strip the bcc recipients" do
expect(message.bcc).to be_blank
end
it "should strip the cc recipients" do
expect(message.cc).to be_blank
end
it "should replace the receipient with the specified address" do
Spree::Config[:intercept_email] = "intercept@foobar.com"
message.deliver
@email = ActionMailer::Base.deliveries.first
expect(@email.to).to eq ["intercept@foobar.com"]
end
it "should modify the subject to include the original email" do
Spree::Config[:intercept_email] = "intercept@foobar.com"
message.deliver
@email = ActionMailer::Base.deliveries.first
expect(@email.subject).to include order.distributor.contact.email
end
end
context "when intercept_mode is not provided" do
it "should not modify the recipient" do
Spree::Config[:intercept_email] = ""
message.deliver
@email = ActionMailer::Base.deliveries.first
expect(@email.to).to eq [order.distributor.contact.email]
end
end
end
end

View File

@@ -0,0 +1,90 @@
# frozen_string_literal: true
require 'spec_helper'
module Spree
module Core
describe MailSettings do
let!(:subject) { MailSettings.new }
context "override option is true" do
before { Config.override_actionmailer_config = true }
context "init" do
it "calls override!" do
expect(MailSettings).to receive(:new).and_return(subject)
expect(subject).to receive(:override!)
MailSettings.init
end
end
context "enable delivery" do
before { Config.enable_mail_delivery = true }
context "overrides appplication defaults" do
context "authentication method is none" do
before do
Config.mail_host = "smtp.example.com"
Config.mail_domain = "example.com"
Config.mail_port = 123
Config.mail_auth_type = MailSettings::SECURE_CONNECTION_TYPES[0]
Config.smtp_username = "schof"
Config.smtp_password = "hellospree!"
Config.secure_connection_type = "TLS"
subject.override!
end
it { expect(ActionMailer::Base.smtp_settings[:address]).to eq "smtp.example.com" }
it { expect(ActionMailer::Base.smtp_settings[:domain]).to eq "example.com" }
it { expect(ActionMailer::Base.smtp_settings[:port]).to eq 123 }
it { expect(ActionMailer::Base.smtp_settings[:authentication]).to eq "None" }
it { expect(ActionMailer::Base.smtp_settings[:enable_starttls_auto]).to be_truthy }
it "doesnt touch user name config" do
expect(ActionMailer::Base.smtp_settings[:user_name]).to be_nil
end
it "doesnt touch password config" do
expect(ActionMailer::Base.smtp_settings[:password]).to be_nil
end
end
end
context "when mail_auth_type is other than none" do
before do
Config.mail_auth_type = "login"
Config.smtp_username = "schof"
Config.smtp_password = "hellospree!"
subject.override!
end
context "overrides user credentials" do
it { expect(ActionMailer::Base.smtp_settings[:user_name]).to eq "schof" }
it { expect(ActionMailer::Base.smtp_settings[:password]).to eq "hellospree!" }
end
end
end
context "do not enable delivery" do
before do
Config.enable_mail_delivery = false
subject.override!
end
it { expect(ActionMailer::Base.perform_deliveries).to be_falsy }
end
end
context "override option is false" do
before { Config.override_actionmailer_config = false }
context "init" do
it "doesnt calls override!" do
expect(subject).not_to receive(:override!)
MailSettings.init
end
end
end
end
end
end

View File

@@ -0,0 +1,35 @@
# frozen_string_literal: true
require 'spec_helper'
# Its pretty difficult to test this module in isolation b/c it needs to work in conjunction
# with an actual class that extends ActiveRecord::Base and has a corresponding table in the DB.
# So we'll just test it using Order instead since it included the module.
describe Spree::Core::TokenResource do
let(:order) { Spree::Order.new }
let(:permission) { double(Spree::TokenizedPermission) }
it 'should add has_one :tokenized_permission relationship' do
assert Spree::Order.
reflect_on_all_associations(:has_one).map(&:name).include?(:tokenized_permission)
end
context '#token' do
it 'should return the token of the associated permission' do
allow(order).to receive_messages tokenized_permission: permission
allow(permission).to receive_messages token: 'foo'
expect(order.token).to eq 'foo'
end
it 'should return nil if there is no associated permission' do
expect(order.token).to be_nil
end
end
context '#create_token' do
it 'should create a randomized 16 character token' do
token = order.create_token
expect(token.size).to eq 16
end
end
end

127
spec/lib/spree/i18n_spec.rb Normal file
View File

@@ -0,0 +1,127 @@
# frozen_string_literal: true
require 'rspec/expectations'
require 'spree/i18n'
require 'spree/testing_support/i18n'
describe "i18n" do
before do
I18n.backend.store_translations(
:en,
{
spree: {
foo: "bar",
bar: {
foo: "bar within bar scope",
invalid: nil,
legacy_translation: "back in the day..."
},
invalid: nil,
legacy_translation: "back in the day..."
}
}
)
end
it "translates within the spree scope" do
expect(Spree.normal_t(:foo)).to eql("bar")
expect(Spree.translate(:foo)).to eql("bar")
end
it "translates within the spree scope using a path" do
allow(Spree).to receive(:virtual_path).and_return('bar')
expect(Spree.normal_t('.legacy_translation')).to eql("back in the day...")
expect(Spree.translate('.legacy_translation')).to eql("back in the day...")
end
it "raise error without any context when using a path" do
expect {
Spree.normal_t('.legacy_translation')
}.to raise_error
expect {
Spree.translate('.legacy_translation')
}.to raise_error
end
it "prepends a string scope" do
expect(Spree.normal_t(:foo, scope: "bar")).to eql("bar within bar scope")
end
it "prepends to an array scope" do
expect(Spree.normal_t(:foo, scope: ["bar"])).to eql("bar within bar scope")
end
it "returns two translations" do
expect(Spree.normal_t([:foo, 'bar.foo'])).to eql(["bar", "bar within bar scope"])
end
it "returns reasonable string for missing translations" do
expect(Spree.t(:missing_entry)).to include("<span")
end
context "missed + unused translations" do
def key_with_locale(key)
"#{key} (#{I18n.locale})"
end
before do
Spree.used_translations = []
end
context "missed translations" do
def assert_missing_translation(key)
key = key_with_locale(key)
message = Spree.missing_translation_messages.detect { |m| m == key }
expect(message).not_to(be_nil, "expected '#{key}' to be missing, but it wasn't.")
end
it "logs missing translations" do
Spree.t(:missing, scope: [:else, :where])
Spree.check_missing_translations
assert_missing_translation("else")
assert_missing_translation("else.where")
assert_missing_translation("else.where.missing")
end
it "does not log present translations" do
Spree.t(:foo)
Spree.check_missing_translations
expect(Spree.missing_translation_messages).to be_empty
end
it "does not break when asked for multiple translations" do
Spree.t [:foo, 'bar.foo']
Spree.check_missing_translations
expect(Spree.missing_translation_messages).to be_empty
end
end
context "unused translations" do
def assert_unused_translation(key)
key = key_with_locale(key)
message = Spree.unused_translation_messages.detect { |m| m == key }
expect(message).not_to(be_nil, "expected '#{key}' to be unused, but it was used.")
end
def assert_used_translation(key)
key = key_with_locale(key)
message = Spree.unused_translation_messages.detect { |m| m == key }
expect(message).to(be_nil, "expected '#{key}' to be used, but it wasn't.")
end
it "logs translations that aren't used" do
Spree.check_unused_translations
assert_unused_translation("bar.legacy_translation")
assert_unused_translation("legacy_translation")
end
it "does not log used translations" do
Spree.t(:foo)
Spree.check_unused_translations
assert_used_translation("foo")
end
end
end
end

View File

@@ -0,0 +1,135 @@
# frozen_string_literal: false
require 'spec_helper'
describe Spree::Money do
before do
configure_spree_preferences do |config|
config.currency = "USD"
config.currency_symbol_position = :before
config.display_currency = false
end
end
it "formats correctly" do
money = Spree::Money.new(10)
expect(money.to_s).to eq("$10.00")
end
it "can get cents" do
money = Spree::Money.new(10)
expect(money.cents).to eq(1000)
end
context "with currency" do
it "passed in option" do
money = Spree::Money.new(10, with_currency: true, html: false)
expect(money.to_s).to eq("$10.00 USD")
end
it "config option" do
Spree::Config[:display_currency] = true
money = Spree::Money.new(10, html: false)
expect(money.to_s).to eq("$10.00 USD")
end
end
context "hide cents" do
it "hides cents suffix" do
Spree::Config[:hide_cents] = true
money = Spree::Money.new(10)
expect(money.to_s).to eq("$10")
end
it "shows cents suffix" do
Spree::Config[:hide_cents] = false
money = Spree::Money.new(10)
expect(money.to_s).to eq("$10.00")
end
end
context "currency parameter" do
context "when currency is specified in Canadian Dollars" do
it "uses the currency param over the global configuration" do
money = Spree::Money.new(10, currency: 'CAD', with_currency: true, html: false)
expect(money.to_s).to eq("$10.00 CAD")
end
end
context "when currency is specified in Japanese Yen" do
it "uses the currency param over the global configuration" do
money = Spree::Money.new(100, currency: 'JPY', html: false)
expect(money.to_s).to eq("¥100")
end
end
end
context "symbol positioning" do
it "passed in option" do
money = Spree::Money.new(10, symbol_position: :after, html: false)
expect(money.to_s).to eq("10.00 $")
end
it "passed in option string" do
money = Spree::Money.new(10, symbol_position: "after", html: false)
expect(money.to_s).to eq("10.00 $")
end
it "config option" do
Spree::Config[:currency_symbol_position] = :after
money = Spree::Money.new(10, html: false)
expect(money.to_s).to eq("10.00 $")
end
end
context "JPY" do
before do
configure_spree_preferences do |config|
config.currency = "JPY"
config.currency_symbol_position = :before
config.display_currency = false
end
end
it "formats correctly" do
money = Spree::Money.new(1000, html: false)
expect(money.to_s).to eq("¥1,000")
end
end
context "EUR" do
before do
configure_spree_preferences do |config|
config.currency = "EUR"
config.currency_symbol_position = :after
config.display_currency = false
end
end
# Regression test for Spree #2634
it "formats as plain by default" do
money = Spree::Money.new(10)
expect(money.to_s).to eq("10.00 €")
end
# Regression test for Spree #2632
it "acknowledges decimal mark option" do
Spree::Config[:currency_decimal_mark] = ","
money = Spree::Money.new(10)
expect(money.to_s).to eq("10,00 €")
end
# Regression test for Spree #2632
it "acknowledges thousands separator option" do
Spree::Config[:currency_thousands_separator] = "."
money = Spree::Money.new(1000)
expect(money.to_s).to eq("1.000.00 €")
end
it "formats as HTML if asked (nicely) to" do
money = Spree::Money.new(10)
# The HTMLified version of the euro sign
expect(money.to_html).to eq("10.00&nbsp;&#x20AC;")
end
end
end

View File

@@ -0,0 +1,86 @@
# frozen_string_literal: true
require 'spec_helper'
module Spree
describe Spree::ProductDuplicator do
let(:product) do
double 'Product',
name: "foo",
taxons: [],
product_properties: [property],
master: variant,
has_variants?: false
end
let(:new_product) do
double 'New Product',
save!: true
end
let(:property) do
double 'Property'
end
let(:new_property) do
double 'New Property'
end
let(:variant) do
double 'Variant',
sku: "12345",
price: 19.99,
currency: "AUD",
images: [image]
end
let(:new_variant) do
double 'New Variant',
sku: "12345"
end
let(:image) do
double 'Image',
attachment: double('Attachment')
end
let(:new_image) do
double 'New Image'
end
before do
expect(product).to receive(:dup).and_return(new_product)
expect(variant).to receive(:dup).and_return(new_variant)
expect(image).to receive(:dup).and_return(new_image)
expect(property).to receive(:dup).and_return(new_property)
end
it "can duplicate a product" do
duplicator = Spree::ProductDuplicator.new(product)
expect(new_product).to receive(:name=).with("COPY OF foo")
expect(new_product).to receive(:taxons=).with([])
expect(new_product).to receive(:product_properties=).with([new_property])
expect(new_product).to receive(:created_at=).with(nil)
expect(new_product).to receive(:updated_at=).with(nil)
expect(new_product).to receive(:deleted_at=).with(nil)
expect(new_product).to receive(:master=).with(new_variant)
expect(new_variant).to receive(:sku=).with("COPY OF 12345")
expect(new_variant).to receive(:deleted_at=).with(nil)
expect(new_variant).to receive(:images=).with([new_image])
expect(new_variant).to receive(:price=).with(variant.price)
expect(new_variant).to receive(:currency=).with(variant.currency)
expect(image.attachment).to receive(:clone).and_return(image.attachment)
expect(new_image).to receive(:assign_attributes).
with(attachment: image.attachment).
and_return(new_image)
expect(new_property).to receive(:created_at=).with(nil)
expect(new_property).to receive(:updated_at=).with(nil)
duplicator.duplicate
end
end
end

View File

@@ -1,149 +0,0 @@
require 'spec_helper'
describe OrderUpdater do
let(:order) { build(:order) }
let(:order_updater) { described_class.new(Spree::OrderUpdater.new(order)) }
it "is failed if no valid payments" do
allow(order).to receive_message_chain(:payments, :valid, :empty?).and_return(true)
order_updater.update_payment_state
expect(order.payment_state).to eq('failed')
end
context "payment total is greater than order total" do
it "is credit_owed" do
order.payment_total = 2
order.total = 1
expect {
order_updater.update_payment_state
}.to change { order.payment_state }.to 'credit_owed'
end
end
context "order total is greater than payment total" do
it "is credit_owed" do
order.payment_total = 1
order.total = 2
expect {
order_updater.update_payment_state
}.to change { order.payment_state }.to 'balance_due'
end
end
context "order total equals payment total" do
it "is paid" do
order.payment_total = 30
order.total = 30
expect {
order_updater.update_payment_state
}.to change { order.payment_state }.to 'paid'
end
end
context "order is canceled" do
before do
order.state = 'canceled'
end
context "and is still unpaid" do
it "is void" do
order.payment_total = 0
order.total = 30
expect {
order_updater.update_payment_state
}.to change { order.payment_state }.to 'void'
end
end
context "and is paid" do
it "is credit_owed" do
order.payment_total = 30
order.total = 30
allow(order).to receive_message_chain(:payments, :valid, :empty?).and_return(false)
allow(order).to receive_message_chain(:payments, :completed, :empty?).and_return(false)
expect {
order_updater.update_payment_state
}.to change { order.payment_state }.to 'credit_owed'
end
end
context "and payment is refunded" do
it "is void" do
order.payment_total = 0
order.total = 30
allow(order).to receive_message_chain(:payments, :valid, :empty?).and_return(false)
allow(order).to receive_message_chain(:payments, :completed, :empty?).and_return(false)
expect {
order_updater.update_payment_state
}.to change { order.payment_state }.to 'void'
end
end
end
context 'when the set payment_state does not match the last payment_state' do
before { order.payment_state = 'previous_to_paid' }
context 'and the order is being updated' do
before { allow(order).to receive(:persisted?) { true } }
it 'creates a new state_change for the order' do
expect { order_updater.update_payment_state }
.to change { order.state_changes.size }.by(1)
end
end
context 'and the order is being created' do
before { allow(order).to receive(:persisted?) { false } }
it 'creates a new state_change for the order' do
expect { order_updater.update_payment_state }
.not_to change { order.state_changes.size }
end
end
end
context 'when the set payment_state matches the last payment_state' do
before { order.payment_state = 'paid' }
it 'does not create any state_change' do
expect { order_updater.update_payment_state }
.not_to change { order.state_changes.size }
end
end
context '#before_save_hook' do
let(:distributor) { build(:distributor_enterprise) }
let(:shipment) { create(:shipment_with, :shipping_method, shipping_method: shipping_method) }
before do
order.distributor = distributor
order.shipments = [shipment]
end
context 'when shipping method is pickup' do
let(:shipping_method) { create(:shipping_method_with, :pickup) }
let(:address) { build(:address, firstname: 'joe') }
before { distributor.address = address }
it "populates the shipping address from distributor" do
order_updater.before_save_hook
expect(order.ship_address.address1).to eq(distributor.address.address1)
end
end
context 'when shipping_method is delivery' do
let(:shipping_method) { create(:shipping_method_with, :delivery) }
let(:address) { build(:address, firstname: 'will') }
before { order.ship_address = address }
it "does not populate the shipping address from distributor" do
order_updater.before_save_hook
expect(order.ship_address.firstname).to eq("will")
end
end
end
end