mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-14 18:56:49 +00:00
Compare commits
42 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e6a1021d6e | ||
|
|
e82aa0c89a | ||
|
|
8be05e94bd | ||
|
|
7317347fd6 | ||
|
|
c5c542069f | ||
|
|
dc9e3aa1a0 | ||
|
|
a48b57f7a7 | ||
|
|
f501d48caa | ||
|
|
2429b186ce | ||
|
|
7df2759475 | ||
|
|
681cb34c48 | ||
|
|
94b903179e | ||
|
|
59070712d9 | ||
|
|
76aebf329e | ||
|
|
b2b5606f2e | ||
|
|
f890c4a31d | ||
|
|
b087f8da19 | ||
|
|
e3c1159c17 | ||
|
|
14054f0e70 | ||
|
|
d525ddfe14 | ||
|
|
df0b997258 | ||
|
|
ffbb0d26a4 | ||
|
|
3da14233bf | ||
|
|
940c067b60 | ||
|
|
6e8fe080cb | ||
|
|
8867ec977c | ||
|
|
4931edc67c | ||
|
|
51ed9a6b78 | ||
|
|
e96428e7e2 | ||
|
|
b629a4f912 | ||
|
|
967380c542 | ||
|
|
ff0aa377a1 | ||
|
|
da683e3ecf | ||
|
|
aa46a4b5da | ||
|
|
61dad61ef7 | ||
|
|
cd940bd140 | ||
|
|
5d48da72c7 | ||
|
|
9d07295480 | ||
|
|
f435039061 | ||
|
|
97ae4def98 | ||
|
|
91501f05f2 | ||
|
|
93601ca556 |
3
.github/ISSUE_TEMPLATE/release.md
vendored
3
.github/ISSUE_TEMPLATE/release.md
vendored
@@ -9,10 +9,11 @@ assignees: ''
|
||||
|
||||
Steps:
|
||||
|
||||
- [ ] Include translations
|
||||
- [ ] Include translations: `tx pull --force`
|
||||
- [ ] [Draft new release]
|
||||
- [ ] Notify #instance-managers of user-facing changes.
|
||||
- [ ] Test: https://semaphoreci.com/openfoodfoundation/openfoodnetwork-2/branches/master <!-- replace the URL -->
|
||||
- [ ] Update translations if necessary
|
||||
- [ ] Publish and notify #global-community
|
||||
- [ ] Deploy and notify #instance-managers
|
||||
- [ ] Nudge next release manager
|
||||
|
||||
@@ -330,6 +330,13 @@ Layout/LineLength:
|
||||
- spec/requests/api/orders_spec.rb
|
||||
- spec/swagger_helper.rb
|
||||
- spec/views/spree/admin/payment_methods/index.html.haml_spec.rb
|
||||
- app/models/spree/image.rb
|
||||
- app/models/spree/payment_method.rb
|
||||
- spec/factories/line_item_factory.rb
|
||||
- spec/factories/shipment_factory.rb
|
||||
- spec/factories/stock_location_factory.rb
|
||||
- spec/factories/user_factory.rb
|
||||
- spec/lib/spree/core/calculated_adjustments_spec.rb
|
||||
|
||||
Metrics/AbcSize:
|
||||
Max: 15
|
||||
@@ -459,6 +466,13 @@ Metrics/AbcSize:
|
||||
- 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
|
||||
- app/models/spree/zone.rb
|
||||
- lib/spree/core/calculated_adjustments.rb
|
||||
- lib/spree/core/delegate_belongs_to.rb
|
||||
- lib/spree/core/permalinks.rb
|
||||
- lib/spree/core/s3_support.rb
|
||||
- lib/spree/money.rb
|
||||
- spec/support/i18n_translations_checker.rb
|
||||
|
||||
Metrics/BlockLength:
|
||||
Max: 25
|
||||
@@ -501,6 +515,9 @@ Metrics/BlockLength:
|
||||
- app/models/spree/payment/processing.rb
|
||||
- spec/requests/api/orders_spec.rb
|
||||
- spec/swagger_helper.rb
|
||||
- spec/factories/address_factory.rb
|
||||
- spec/factories/payment_method_factory.rb
|
||||
- spec/factories/shipment_factory.rb
|
||||
|
||||
Metrics/CyclomaticComplexity:
|
||||
Max: 6
|
||||
@@ -535,6 +552,9 @@ Metrics/CyclomaticComplexity:
|
||||
- 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
|
||||
- app/models/spree/payment_method.rb
|
||||
- app/models/spree/zone.rb
|
||||
- lib/spree/core/calculated_adjustments.rb
|
||||
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 7
|
||||
@@ -563,6 +583,8 @@ Metrics/PerceivedComplexity:
|
||||
- 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
|
||||
- app/models/spree/zone.rb
|
||||
- lib/spree/core/calculated_adjustments.rb
|
||||
|
||||
Metrics/MethodLength:
|
||||
Max: 10
|
||||
@@ -675,6 +697,15 @@ Metrics/MethodLength:
|
||||
- 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
|
||||
- app/models/spree/credit_card.rb
|
||||
- app/models/spree/payment_method.rb
|
||||
- app/models/spree/zone.rb
|
||||
- lib/spree/core/calculated_adjustments.rb
|
||||
- lib/spree/core/delegate_belongs_to.rb
|
||||
- lib/spree/core/permalinks.rb
|
||||
- lib/spree/core/s3_support.rb
|
||||
- lib/spree/responder.rb
|
||||
- spec/support/i18n_translations_checker.rb
|
||||
|
||||
Metrics/ClassLength:
|
||||
Max: 100
|
||||
@@ -719,6 +750,8 @@ Metrics/ClassLength:
|
||||
- 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
|
||||
- app/models/spree/credit_card.rb
|
||||
- app/models/spree/zone.rb
|
||||
|
||||
Metrics/ModuleLength:
|
||||
Max: 100
|
||||
@@ -764,6 +797,8 @@ Metrics/ModuleLength:
|
||||
- spec/support/request/web_helper.rb
|
||||
- app/models/spree/order/checkout.rb
|
||||
- app/models/spree/payment/processing.rb
|
||||
- spec/lib/open_food_network/packing_report_spec.rb
|
||||
- spec/models/spree/credit_card_spec.rb
|
||||
|
||||
Metrics/ParameterLists:
|
||||
Max: 5
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config --exclude-limit 1400`
|
||||
# on 2020-08-13 16:05:53 +1000 using RuboCop version 0.81.0.
|
||||
# on 2020-09-10 16:12:05 +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
|
||||
@@ -28,13 +28,14 @@ Layout/EmptyLines:
|
||||
Exclude:
|
||||
- 'spec/models/spree/payment_spec.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Offense count: 4
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: empty_lines, no_empty_lines
|
||||
Layout/EmptyLinesAroundBlockBody:
|
||||
Exclude:
|
||||
- 'spec/models/spree/payment_spec.rb'
|
||||
- 'spec/models/spree/zone_spec.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
@@ -61,7 +62,7 @@ Layout/FirstHashElementIndentation:
|
||||
- 'spec/models/spree/payment_spec.rb'
|
||||
- 'spec/swagger_helper.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# Offense count: 8
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowMultipleStyles, EnforcedHashRocketStyle, EnforcedColonStyle, EnforcedLastArgumentHashStyle.
|
||||
# SupportedHashRocketStyles: key, separator, table
|
||||
@@ -69,6 +70,7 @@ Layout/FirstHashElementIndentation:
|
||||
# SupportedLastArgumentHashStyles: always_inspect, always_ignore, ignore_implicit, ignore_explicit
|
||||
Layout/HashAlignment:
|
||||
Exclude:
|
||||
- 'spec/lib/open_food_network/packing_report_spec.rb'
|
||||
- 'spec/models/spree/payment_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
@@ -79,13 +81,6 @@ 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: 409
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
@@ -123,13 +118,22 @@ Layout/SpaceInsideHashLiteralBraces:
|
||||
- 'spec/services/checkout/form_data_adapter_spec.rb'
|
||||
- 'spec/services/user_locale_setter_spec.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: final_newline, final_blank_line
|
||||
Layout/TrailingEmptyLines:
|
||||
Exclude:
|
||||
- 'spec/factories.rb'
|
||||
- 'spec/factories/address_factory.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/lib/open_food_network/orders_and_fulfillments_report/customer_totals_report_spec.rb'
|
||||
- 'spec/requests/api/orders_spec.rb'
|
||||
|
||||
# Offense count: 2
|
||||
@@ -145,6 +149,13 @@ Lint/IneffectiveAccessModifier:
|
||||
- 'app/services/mail_configuration.rb'
|
||||
- 'lib/open_food_network/feature_toggle.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: IgnoreEmptyBlocks, AllowUnusedKeywordArguments.
|
||||
Lint/UnusedBlockArgument:
|
||||
Exclude:
|
||||
- 'spec/factories/stock_location_factory.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods, IgnoreNotImplementedMethods.
|
||||
@@ -160,48 +171,6 @@ Lint/UselessAccessModifier:
|
||||
- 'app/services/mail_configuration.rb'
|
||||
- 'lib/open_food_network/feature_toggle.rb'
|
||||
|
||||
# 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: 102
|
||||
|
||||
# Offense count: 2
|
||||
# Configuration parameters: CountComments.
|
||||
Metrics/ClassLength:
|
||||
Max: 231
|
||||
|
||||
# Offense count: 3
|
||||
# Configuration parameters: IgnoredMethods.
|
||||
Metrics/CyclomaticComplexity:
|
||||
Max: 23
|
||||
|
||||
# Offense count: 19
|
||||
# Configuration parameters: CountComments, ExcludedMethods.
|
||||
Metrics/MethodLength:
|
||||
Max: 140
|
||||
|
||||
# Offense count: 2
|
||||
# Configuration parameters: CountComments.
|
||||
Metrics/ModuleLength:
|
||||
Max: 208
|
||||
|
||||
# Offense count: 2
|
||||
# Configuration parameters: IgnoredMethods.
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 24
|
||||
|
||||
# Offense count: 9
|
||||
Naming/AccessorMethodName:
|
||||
Exclude:
|
||||
@@ -227,7 +196,7 @@ Naming/MemoizedInstanceVariableName:
|
||||
- 'app/mailers/producer_mailer.rb'
|
||||
- 'lib/open_food_network/address_finder.rb'
|
||||
|
||||
# Offense count: 19
|
||||
# Offense count: 20
|
||||
# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros.
|
||||
# NamePrefix: is_, has_, have_
|
||||
# ForbiddenPrefixes: is_, has_, have_
|
||||
@@ -241,9 +210,10 @@ Naming/PredicateName:
|
||||
- 'app/models/order_cycle.rb'
|
||||
- 'app/models/spree/ability_decorator.rb'
|
||||
- 'app/models/spree/adjustment_decorator.rb'
|
||||
- 'app/models/spree/credit_card.rb'
|
||||
- 'app/models/spree/line_item_decorator.rb'
|
||||
- 'app/models/spree/order_decorator.rb'
|
||||
- 'app/models/spree/payment_method_decorator.rb'
|
||||
- 'app/models/spree/payment_method.rb'
|
||||
- 'app/models/spree/preferences/file_configuration.rb'
|
||||
- 'app/models/spree/shipping_method_decorator.rb'
|
||||
- 'lib/open_food_network/customers_report.rb'
|
||||
@@ -252,6 +222,13 @@ Naming/PredicateName:
|
||||
- 'lib/open_food_network/packing_report.rb'
|
||||
- 'lib/tasks/data.rake'
|
||||
|
||||
# Offense count: 2
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: snake_case, normalcase, non_integer
|
||||
Naming/VariableNumber:
|
||||
Exclude:
|
||||
- 'spec/factories/stock_location_factory.rb'
|
||||
|
||||
# Offense count: 7
|
||||
# Cop supports --auto-correct.
|
||||
Rails/ActiveRecordAliases:
|
||||
@@ -261,12 +238,13 @@ Rails/ActiveRecordAliases:
|
||||
- 'spec/features/consumer/shopping/orders_spec.rb'
|
||||
- 'spec/requests/api/orders_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Offense count: 3
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: strict, flexible
|
||||
Rails/Date:
|
||||
Exclude:
|
||||
- 'app/models/order_cycle.rb'
|
||||
- 'app/models/spree/credit_card.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
@@ -281,7 +259,7 @@ Rails/Delegate:
|
||||
# Whitelist: find_by_sql
|
||||
Rails/DynamicFindBy:
|
||||
Exclude:
|
||||
- 'app/controllers/spree/admin/orders/customer_details_controller.rb'
|
||||
- 'spec/factories/state_factory.rb'
|
||||
|
||||
# Offense count: 16
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
@@ -323,7 +301,7 @@ Rails/FindEach:
|
||||
- 'app/models/spree/order_decorator.rb'
|
||||
- 'app/models/spree/shipment.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# Offense count: 6
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/models/**/*.rb
|
||||
Rails/HasAndBelongsToMany:
|
||||
@@ -332,8 +310,9 @@ Rails/HasAndBelongsToMany:
|
||||
- 'app/models/enterprise_group.rb'
|
||||
- 'app/models/spree/concerns/payment_method_distributors.rb'
|
||||
- 'app/models/spree/line_item_decorator.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
|
||||
# Offense count: 26
|
||||
# Offense count: 27
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/models/**/*.rb
|
||||
Rails/HasManyOrHasOneDependent:
|
||||
@@ -342,8 +321,9 @@ Rails/HasManyOrHasOneDependent:
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/order_cycle.rb'
|
||||
- 'app/models/spree/adjustment_decorator.rb'
|
||||
- 'app/models/spree/credit_card.rb'
|
||||
- 'app/models/spree/order_decorator.rb'
|
||||
- 'app/models/spree/payment_method_decorator.rb'
|
||||
- 'app/models/spree/payment_method.rb'
|
||||
- 'app/models/spree/property.rb'
|
||||
- 'app/models/spree/shipment.rb'
|
||||
- 'app/models/spree/shipping_method_decorator.rb'
|
||||
@@ -392,7 +372,7 @@ Rails/LexicallyScopedActionFilter:
|
||||
- 'app/controllers/spree/users_controller.rb'
|
||||
- 'app/controllers/user_passwords_controller.rb'
|
||||
|
||||
# Offense count: 12
|
||||
# Offense count: 13
|
||||
Rails/OutputSafety:
|
||||
Exclude:
|
||||
- 'app/controllers/spree/admin/reports_controller.rb'
|
||||
@@ -403,6 +383,7 @@ Rails/OutputSafety:
|
||||
- 'app/helpers/spree/admin/zones_helper.rb'
|
||||
- 'app/helpers/spree/reports_helper.rb'
|
||||
- 'app/serializers/api/product_serializer.rb'
|
||||
- 'lib/spree/money.rb'
|
||||
- 'lib/spree/money_decorator.rb'
|
||||
- 'spec/features/admin/order_print_ticket_spec.rb'
|
||||
|
||||
@@ -422,7 +403,7 @@ Rails/ReflectionClassName:
|
||||
- 'app/models/enterprise_role.rb'
|
||||
- 'app/models/subscription.rb'
|
||||
|
||||
# Offense count: 233
|
||||
# Offense count: 241
|
||||
# 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:
|
||||
@@ -439,17 +420,19 @@ Rails/SkipsModelValidations:
|
||||
- 'app/models/product_import/inventory_reset_strategy.rb'
|
||||
- 'app/models/proxy_order.rb'
|
||||
- 'app/models/spree/address_decorator.rb'
|
||||
- 'app/models/spree/credit_card_decorator.rb'
|
||||
- 'app/models/spree/credit_card.rb'
|
||||
- 'app/models/spree/order_decorator.rb'
|
||||
- 'app/models/spree/payment.rb'
|
||||
- 'app/models/spree/shipment.rb'
|
||||
- 'app/models/spree/shipping_method_decorator.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
- 'app/models/subscription.rb'
|
||||
- 'app/models/variant_override.rb'
|
||||
- 'app/services/order_factory.rb'
|
||||
- 'engines/order_management/spec/performance/order_management/subscriptions/proxy_order_syncer_spec.rb'
|
||||
- 'engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/report_service_spec.rb'
|
||||
- 'engines/order_management/spec/services/order_management/subscriptions/stripe_payment_setup_spec.rb'
|
||||
- 'lib/spree/core/calculated_adjustments.rb'
|
||||
- 'lib/tasks/data/anonymize_data.rake'
|
||||
- 'lib/tasks/sample_data/product_factory.rb'
|
||||
- 'lib/tasks/users.rake'
|
||||
@@ -494,6 +477,7 @@ Rails/SkipsModelValidations:
|
||||
- 'spec/models/enterprise_relationship_spec.rb'
|
||||
- 'spec/models/exchange_spec.rb'
|
||||
- 'spec/models/spree/adjustment_spec.rb'
|
||||
- 'spec/models/spree/asset_spec.rb'
|
||||
- 'spec/models/spree/line_item_spec.rb'
|
||||
- 'spec/models/spree/order_spec.rb'
|
||||
- 'spec/models/spree/variant_spec.rb'
|
||||
@@ -510,7 +494,7 @@ Rails/SkipsModelValidations:
|
||||
- 'spec/support/request/shop_workflow.rb'
|
||||
- 'spec/views/spree/shared/_order_details.html.haml_spec.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Offense count: 4
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/models/**/*.rb
|
||||
Rails/UniqueValidationWithoutIndex:
|
||||
@@ -518,6 +502,7 @@ Rails/UniqueValidationWithoutIndex:
|
||||
- 'app/models/customer.rb'
|
||||
- 'app/models/exchange.rb'
|
||||
- 'app/models/spree/stock_item.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Configuration parameters: Environments.
|
||||
@@ -527,23 +512,29 @@ Rails/UnknownEnv:
|
||||
- 'app/models/spree/app_configuration_decorator.rb'
|
||||
- 'lib/spree/core/controller_helpers/ssl.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: percent_q, bare_percent
|
||||
Style/BarePercentLiterals:
|
||||
Exclude:
|
||||
- 'spec/support/request/web_helper.rb'
|
||||
|
||||
# Offense count: 2
|
||||
Style/CaseEquality:
|
||||
Exclude:
|
||||
- 'app/helpers/angular_form_helper.rb'
|
||||
- 'spec/models/spree/payment_spec.rb'
|
||||
|
||||
# Offense count: 71
|
||||
# Offense count: 64
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AutoCorrect, EnforcedStyle.
|
||||
# SupportedStyles: nested, compact
|
||||
Style/ClassAndModuleChildren:
|
||||
Exclude:
|
||||
- 'app/models/calculator/flat_percent_per_item.rb'
|
||||
- 'app/models/spree/concerns/payment_method_distributors.rb'
|
||||
- 'app/models/spree/gateway/migs.rb'
|
||||
- 'app/models/spree/gateway/pin.rb'
|
||||
- 'app/models/spree/preferences/file_configuration.rb'
|
||||
- 'app/models/spree/product_set.rb'
|
||||
- 'app/models/tag_rule/discount_order.rb'
|
||||
- 'app/models/tag_rule/filter_order_cycles.rb'
|
||||
@@ -601,11 +592,13 @@ Style/ClassAndModuleChildren:
|
||||
- 'app/serializers/api/variant_serializer.rb'
|
||||
- 'lib/open_food_network/locking.rb'
|
||||
- 'spec/controllers/spree/admin/base_controller_spec.rb'
|
||||
- 'spec/models/spree/payment_method_spec.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Offense count: 3
|
||||
Style/ClassVars:
|
||||
Exclude:
|
||||
- 'lib/open_food_network/rack_request_blocker.rb'
|
||||
- 'lib/spree/core/delegate_belongs_to.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
@@ -615,7 +608,7 @@ Style/FormatStringToken:
|
||||
- 'lib/open_food_network/sales_tax_report.rb'
|
||||
- 'spec/features/admin/bulk_order_management_spec.rb'
|
||||
|
||||
# Offense count: 847
|
||||
# Offense count: 829
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: always, always_true, never
|
||||
@@ -710,10 +703,6 @@ Style/FrozenStringLiteralComment:
|
||||
- 'app/controllers/spree/admin/zones_controller.rb'
|
||||
- 'app/controllers/spree/credit_cards_controller.rb'
|
||||
- 'app/controllers/spree/orders_controller.rb'
|
||||
- 'app/controllers/spree/store_controller.rb'
|
||||
- 'app/controllers/spree/user_passwords_controller.rb'
|
||||
- 'app/controllers/spree/user_registrations_controller.rb'
|
||||
- 'app/controllers/spree/user_sessions_controller.rb'
|
||||
- 'app/controllers/spree/users_controller.rb'
|
||||
- 'app/controllers/stripe/callbacks_controller.rb'
|
||||
- 'app/controllers/stripe/webhooks_controller.rb'
|
||||
@@ -781,11 +770,9 @@ Style/FrozenStringLiteralComment:
|
||||
- 'app/models/coordinator_fee.rb'
|
||||
- 'app/models/customer.rb'
|
||||
- 'app/models/distributor_shipping_method.rb'
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/enterprise_fee.rb'
|
||||
- 'app/models/enterprise_fee_set.rb'
|
||||
- 'app/models/enterprise_group.rb'
|
||||
- 'app/models/enterprise_relationship.rb'
|
||||
- 'app/models/enterprise_relationship_permission.rb'
|
||||
- 'app/models/enterprise_role.rb'
|
||||
- 'app/models/enterprise_set.rb'
|
||||
@@ -796,7 +783,6 @@ Style/FrozenStringLiteralComment:
|
||||
- 'app/models/model_set.rb'
|
||||
- 'app/models/order_cycle.rb'
|
||||
- 'app/models/order_cycle_set.rb'
|
||||
- 'app/models/order_updater.rb'
|
||||
- 'app/models/preference_sections/footer_and_external_links_section.rb'
|
||||
- 'app/models/preference_sections/group_signup_page_section.rb'
|
||||
- 'app/models/preference_sections/header_section.rb'
|
||||
@@ -824,16 +810,12 @@ Style/FrozenStringLiteralComment:
|
||||
- 'app/models/spree/calculator_decorator.rb'
|
||||
- 'app/models/spree/classification_decorator.rb'
|
||||
- 'app/models/spree/concerns/payment_method_distributors.rb'
|
||||
- 'app/models/spree/credit_card_decorator.rb'
|
||||
- 'app/models/spree/gateway/migs.rb'
|
||||
- 'app/models/spree/gateway/pin.rb'
|
||||
- 'app/models/spree/gateway/stripe_connect.rb'
|
||||
- 'app/models/spree/gateway_decorator.rb'
|
||||
- 'app/models/spree/image_decorator.rb'
|
||||
- 'app/models/spree/line_item_decorator.rb'
|
||||
- 'app/models/spree/option_type_decorator.rb'
|
||||
- 'app/models/spree/order_decorator.rb'
|
||||
- 'app/models/spree/payment_method_decorator.rb'
|
||||
- 'app/models/spree/preferences/file_configuration.rb'
|
||||
- 'app/models/spree/price_decorator.rb'
|
||||
- 'app/models/spree/product_decorator.rb'
|
||||
@@ -842,7 +824,6 @@ Style/FrozenStringLiteralComment:
|
||||
- 'app/models/spree/product_set.rb'
|
||||
- 'app/models/spree/property.rb'
|
||||
- 'app/models/spree/shipping_method_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'
|
||||
@@ -1125,7 +1106,6 @@ 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_spec.rb'
|
||||
@@ -1169,6 +1149,8 @@ Style/FrozenStringLiteralComment:
|
||||
- 'spec/factories/product_factory.rb'
|
||||
- 'spec/factories/shipment_factory.rb'
|
||||
- 'spec/factories/shipping_method_factory.rb'
|
||||
- 'spec/factories/state_factory.rb'
|
||||
- 'spec/factories/stock_movement_factory.rb'
|
||||
- 'spec/factories/subscription_factory.rb'
|
||||
- 'spec/factories/tag_rule_factory.rb'
|
||||
- 'spec/factories/user_factory.rb'
|
||||
@@ -1323,7 +1305,6 @@ Style/FrozenStringLiteralComment:
|
||||
- 'spec/models/exchange_spec.rb'
|
||||
- 'spec/models/model_set_spec.rb'
|
||||
- 'spec/models/order_cycle_spec.rb'
|
||||
- 'spec/models/order_updater_spec.rb'
|
||||
- 'spec/models/product_import/entry_processor_spec.rb'
|
||||
- 'spec/models/product_import/inventory_reset_strategy_spec.rb'
|
||||
- 'spec/models/product_import/reset_absent_spec.rb'
|
||||
@@ -1461,6 +1442,7 @@ Style/FrozenStringLiteralComment:
|
||||
- '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'
|
||||
- 'spec/views/spree/admin/shared/_order_links.html.haml_spec.rb'
|
||||
|
||||
# Offense count: 48
|
||||
# Configuration parameters: MinBodyLength.
|
||||
@@ -1491,18 +1473,21 @@ Style/GuardClause:
|
||||
- 'spec/support/request/distribution_helper.rb'
|
||||
- 'spec/support/request/shop_workflow.rb'
|
||||
|
||||
# Offense count: 54
|
||||
# Offense count: 66
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
|
||||
# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
|
||||
Style/HashSyntax:
|
||||
Exclude:
|
||||
- 'spec/factories/stock_location_factory.rb'
|
||||
- 'spec/models/spree/credit_card_spec.rb'
|
||||
- 'spec/models/spree/payment_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Offense count: 2
|
||||
Style/MissingRespondToMissing:
|
||||
Exclude:
|
||||
- 'app/helpers/application_helper.rb'
|
||||
- 'app/models/spree/gateway.rb'
|
||||
|
||||
# Offense count: 2
|
||||
Style/MixinUsage:
|
||||
@@ -1510,7 +1495,7 @@ Style/MixinUsage:
|
||||
- 'lib/open_food_network/orders_and_fulfillments_report.rb'
|
||||
- 'spec/lib/open_food_network/packing_report_spec.rb'
|
||||
|
||||
# Offense count: 39
|
||||
# Offense count: 37
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AutoCorrect, EnforcedStyle, IgnoredMethods.
|
||||
# SupportedStyles: predicate, comparison
|
||||
@@ -1521,7 +1506,6 @@ Style/NumericPredicate:
|
||||
- 'app/controllers/spree/orders_controller.rb'
|
||||
- 'app/helpers/checkout_helper.rb'
|
||||
- 'app/helpers/shared_helper.rb'
|
||||
- 'app/models/order_updater.rb'
|
||||
- 'app/models/product_import/product_importer.rb'
|
||||
- 'app/models/product_import/spreadsheet_entry.rb'
|
||||
- 'app/models/spree/adjustment_decorator.rb'
|
||||
@@ -1548,6 +1532,18 @@ Style/RaiseArgs:
|
||||
Exclude:
|
||||
- 'spec/controllers/checkout_controller_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/RandomWithOffset:
|
||||
Exclude:
|
||||
- 'spec/factories.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
Style/RedundantPercentQ:
|
||||
Exclude:
|
||||
- 'spec/support/request/web_helper.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, AllowInnerSlashes.
|
||||
@@ -1556,6 +1552,14 @@ Style/RegexpLiteral:
|
||||
Exclude:
|
||||
- 'lib/spree/core/controller_helpers/auth.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: implicit, explicit
|
||||
Style/RescueStandardError:
|
||||
Exclude:
|
||||
- 'lib/spree/core/delegate_belongs_to.rb'
|
||||
|
||||
# Offense count: 231
|
||||
Style/Send:
|
||||
Exclude:
|
||||
|
||||
@@ -204,7 +204,7 @@ GEM
|
||||
activerecord (>= 3.2.0, < 5.0)
|
||||
fog (~> 1.0)
|
||||
rails (>= 3.2.0, < 5.0)
|
||||
ddtrace (0.39.0)
|
||||
ddtrace (0.40.0)
|
||||
msgpack
|
||||
debugger-linecache (1.2.0)
|
||||
delayed_job (4.1.8)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, $modal, $rootScope, $resource, localStorageService, RailsFlashLoader) ->
|
||||
Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, $modal, $rootScope, $resource, localStorageService, Messages) ->
|
||||
# Handles syncing of current cart/order state to server
|
||||
new class Cart
|
||||
dirty: false
|
||||
@@ -50,7 +50,7 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, $modal, $roo
|
||||
@popQueue() if @update_enqueued
|
||||
|
||||
.error (response, status)=>
|
||||
RailsFlashLoader.loadFlash({error: t('js.cart.add_to_cart_failed')})
|
||||
Messages.flash({error: t('js.cart.add_to_cart_failed')})
|
||||
@update_running = false
|
||||
|
||||
compareAndNotifyStockLevels: (stockLevels) =>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Darkswarm.factory 'Checkout', ($injector, CurrentOrder, ShippingMethods, StripeElements, PaymentMethods, $http, Navigation, CurrentHub, RailsFlashLoader, Loading)->
|
||||
Darkswarm.factory 'Checkout', ($injector, CurrentOrder, ShippingMethods, StripeElements, PaymentMethods, $http, Navigation, CurrentHub, Messages)->
|
||||
new class Checkout
|
||||
errors: {}
|
||||
secrets: {}
|
||||
@@ -13,7 +13,7 @@ Darkswarm.factory 'Checkout', ($injector, CurrentOrder, ShippingMethods, StripeE
|
||||
@submit()
|
||||
|
||||
submit: =>
|
||||
Loading.message = t 'submitting_order'
|
||||
Messages.loading(t 'submitting_order')
|
||||
$http.put('/checkout.json', {order: @preprocess()})
|
||||
.then (response) =>
|
||||
Navigation.go response.data.path
|
||||
@@ -39,8 +39,7 @@ Darkswarm.factory 'Checkout', ($injector, CurrentOrder, ShippingMethods, StripeE
|
||||
@loadFlash(response.data.flash)
|
||||
|
||||
loadFlash: (flash) =>
|
||||
Loading.clear()
|
||||
RailsFlashLoader.loadFlash(flash)
|
||||
Messages.flash(flash)
|
||||
|
||||
# Rails wants our Spree::Address data to be provided with _attributes
|
||||
preprocess: ->
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Darkswarm.factory 'CreditCard', ($injector, $rootScope, CreditCards, StripeElements, Navigation, $http, RailsFlashLoader, Loading)->
|
||||
Darkswarm.factory 'CreditCard', ($injector, $rootScope, CreditCards, StripeElements, Navigation, $http, Messages)->
|
||||
new class CreditCard
|
||||
visible: false
|
||||
errors: {}
|
||||
@@ -12,16 +12,15 @@ Darkswarm.factory 'CreditCard', ($injector, $rootScope, CreditCards, StripeEleme
|
||||
params = @process_params()
|
||||
$http.put('/credit_cards/new_from_token', params )
|
||||
.success (data, status) =>
|
||||
Loading.clear()
|
||||
Messages.clear()
|
||||
@reset()
|
||||
CreditCards.add(data)
|
||||
.error (response, status) =>
|
||||
if response.path
|
||||
Navigation.go response.path
|
||||
else
|
||||
Loading.clear()
|
||||
@errors = response.errors
|
||||
RailsFlashLoader.loadFlash(response.flash)
|
||||
Messages.flash(response.flash)
|
||||
|
||||
setFullName: ->
|
||||
@secrets.name = "#{@secrets.first_name} #{@secrets.last_name}"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Darkswarm.factory 'CreditCards', ($http, $filter, savedCreditCards, RailsFlashLoader)->
|
||||
Darkswarm.factory 'CreditCards', ($http, $filter, savedCreditCards, Messages)->
|
||||
new class CreditCard
|
||||
saved: $filter('orderBy')(savedCreditCards,'-is_default')
|
||||
|
||||
@@ -10,6 +10,6 @@ Darkswarm.factory 'CreditCards', ($http, $filter, savedCreditCards, RailsFlashLo
|
||||
for othercard in @saved when othercard != card
|
||||
othercard.is_default = false
|
||||
$http.put("/credit_cards/#{card.id}", is_default: true).then (data) ->
|
||||
RailsFlashLoader.loadFlash({success: t('js.default_card_updated')})
|
||||
Messages.success(t('js.default_card_updated'))
|
||||
, (response) ->
|
||||
RailsFlashLoader.loadFlash({error: response.data.flash.error})
|
||||
Messages.flash(response.data.flash)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("Darkswarm").factory 'Customer', ($resource, RailsFlashLoader) ->
|
||||
angular.module("Darkswarm").factory 'Customer', ($resource, Messages) ->
|
||||
Customer = $resource('/api/customers/:id/:action.json', {}, {
|
||||
'index':
|
||||
method: 'GET'
|
||||
@@ -13,8 +13,8 @@ angular.module("Darkswarm").factory 'Customer', ($resource, RailsFlashLoader) ->
|
||||
|
||||
Customer.prototype.update = ->
|
||||
@$update().then (response) =>
|
||||
RailsFlashLoader.loadFlash({success: t('js.changes_saved')})
|
||||
Messages.success(t('js.changes_saved'))
|
||||
, (response) =>
|
||||
RailsFlashLoader.loadFlash({error: response.data.error})
|
||||
Messages.error(response.data.error)
|
||||
|
||||
Customer
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Darkswarm.factory "Loading", ->
|
||||
new class Loading
|
||||
message: null
|
||||
message: null
|
||||
clear: =>
|
||||
@message = null
|
||||
|
||||
17
app/assets/javascripts/darkswarm/services/messages.js.coffee
Normal file
17
app/assets/javascripts/darkswarm/services/messages.js.coffee
Normal file
@@ -0,0 +1,17 @@
|
||||
Darkswarm.factory "Messages", (Loading, RailsFlashLoader)->
|
||||
new class Messages
|
||||
loading: (message) ->
|
||||
Loading.message = message
|
||||
|
||||
success: (message) ->
|
||||
@flash(success: message)
|
||||
|
||||
error: (message) ->
|
||||
@flash(error: message)
|
||||
|
||||
flash: (flash) ->
|
||||
@clear()
|
||||
RailsFlashLoader.loadFlash(flash)
|
||||
|
||||
clear: ->
|
||||
Loading.clear()
|
||||
@@ -1,4 +1,4 @@
|
||||
Darkswarm.factory 'StripeElements', ($rootScope, Loading, RailsFlashLoader) ->
|
||||
Darkswarm.factory 'StripeElements', ($rootScope, Messages) ->
|
||||
new class StripeElements
|
||||
# These are both set from the StripeElements directive
|
||||
stripe: null
|
||||
@@ -8,39 +8,49 @@ Darkswarm.factory 'StripeElements', ($rootScope, Loading, RailsFlashLoader) ->
|
||||
requestToken: (secrets, submit, loading_message = t("processing_payment")) ->
|
||||
return unless @stripe? && @card?
|
||||
|
||||
Loading.message = loading_message
|
||||
Messages.loading loading_message
|
||||
cardData = @makeCardData(secrets)
|
||||
|
||||
@stripe.createToken(@card, cardData).then (response) =>
|
||||
if(response.error)
|
||||
Loading.clear()
|
||||
RailsFlashLoader.loadFlash({error: t("error") + ": #{response.error.message}"})
|
||||
@triggerAngularDigest()
|
||||
console.error(JSON.stringify(response.error))
|
||||
@reportError(response.error, t("error") + ": #{response.error.message}")
|
||||
else
|
||||
secrets.token = response.token.id
|
||||
secrets.cc_type = @mapTokenApiCardBrand(response.token.card.brand)
|
||||
secrets.card = response.token.card
|
||||
submit()
|
||||
.catch (response) =>
|
||||
# Stripe handles errors in the response above. This code may never be
|
||||
# reached. But if we get here, we want to know.
|
||||
@reportError(response, t("js.stripe_elements.unknown_error_from_stripe"))
|
||||
throw response
|
||||
|
||||
# Create Payment Method to be used with the Stripe Payment Intents API
|
||||
createPaymentMethod: (secrets, submit, loading_message = t("processing_payment")) ->
|
||||
return unless @stripe? && @card?
|
||||
|
||||
Loading.message = loading_message
|
||||
Messages.loading loading_message
|
||||
cardData = @makeCardData(secrets)
|
||||
|
||||
@stripe.createPaymentMethod({ type: 'card', card: @card }, @card, cardData).then (response) =>
|
||||
if(response.error)
|
||||
Loading.clear()
|
||||
RailsFlashLoader.loadFlash({error: t("error") + ": #{response.error.message}"})
|
||||
@triggerAngularDigest()
|
||||
console.error(JSON.stringify(response.error))
|
||||
@reportError(response.error, t("error") + ": #{response.error.message}")
|
||||
else
|
||||
secrets.token = response.paymentMethod.id
|
||||
secrets.cc_type = @mapPaymentMethodsApiCardBrand(response.paymentMethod.card.brand)
|
||||
secrets.card = response.paymentMethod.card
|
||||
submit()
|
||||
.catch (response) =>
|
||||
# Stripe handles errors in the response above. This code may never be
|
||||
# reached. But if we get here, we want to know.
|
||||
@reportError(response, t("js.stripe_elements.unknown_error_from_stripe"))
|
||||
throw response
|
||||
|
||||
reportError: (error, messageForUser) ->
|
||||
Messages.error(messageForUser)
|
||||
@triggerAngularDigest()
|
||||
console.error(error)
|
||||
Bugsnag.notify(new Error(JSON.stringify(error)))
|
||||
|
||||
triggerAngularDigest: ->
|
||||
# $evalAsync is improved way of triggering a digest without calling $apply
|
||||
|
||||
177
app/models/spree/adjustment.rb
Normal file
177
app/models/spree/adjustment.rb
Normal file
@@ -0,0 +1,177 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spree/localized_number'
|
||||
require 'concerns/adjustment_scopes'
|
||||
|
||||
# Adjustments represent a change to the +item_total+ of an Order. Each adjustment
|
||||
# has an +amount+ that can be either positive or negative.
|
||||
#
|
||||
# Adjustments can be open/closed/finalized
|
||||
#
|
||||
# Once an adjustment is finalized, it cannot be changed, but an adjustment can
|
||||
# toggle between open/closed as needed
|
||||
#
|
||||
# Boolean attributes:
|
||||
#
|
||||
# +mandatory+
|
||||
#
|
||||
# If this flag is set to true then it means the the charge is required and will not
|
||||
# be removed from the order, even if the amount is zero. In other words a record
|
||||
# will be created even if the amount is zero. This is useful for representing things
|
||||
# such as shipping and tax charges where you may want to make it explicitly clear
|
||||
# that no charge was made for such things.
|
||||
#
|
||||
# +eligible?+
|
||||
#
|
||||
# This boolean attributes stores whether this adjustment is currently eligible
|
||||
# for its order. Only eligible adjustments count towards the order's adjustment
|
||||
# total. This allows an adjustment to be preserved if it becomes ineligible so
|
||||
# it might be reinstated.
|
||||
module Spree
|
||||
class Adjustment < ActiveRecord::Base
|
||||
extend Spree::LocalizedNumber
|
||||
|
||||
# Deletion of metadata is handled in the database.
|
||||
# So we don't need the option `dependent: :destroy` as long as
|
||||
# AdjustmentMetadata has no destroy logic itself.
|
||||
has_one :metadata, class_name: 'AdjustmentMetadata'
|
||||
|
||||
belongs_to :adjustable, polymorphic: true
|
||||
belongs_to :source, polymorphic: true
|
||||
belongs_to :originator, polymorphic: true
|
||||
belongs_to :tax_rate, -> { where spree_adjustments: { originator_type: 'Spree::TaxRate' } },
|
||||
foreign_key: 'originator_id'
|
||||
|
||||
validates :label, presence: true
|
||||
validates :amount, numericality: true
|
||||
|
||||
after_save :update_adjustable
|
||||
after_destroy :update_adjustable
|
||||
|
||||
state_machine :state, initial: :open do
|
||||
event :close do
|
||||
transition from: :open, to: :closed
|
||||
end
|
||||
|
||||
event :open do
|
||||
transition from: :closed, to: :open
|
||||
end
|
||||
|
||||
event :finalize do
|
||||
transition from: [:open, :closed], to: :finalized
|
||||
end
|
||||
end
|
||||
|
||||
scope :tax, -> { where(originator_type: 'Spree::TaxRate', adjustable_type: 'Spree::Order') }
|
||||
scope :price, -> { where(adjustable_type: 'Spree::LineItem') }
|
||||
scope :optional, -> { where(mandatory: false) }
|
||||
scope :charge, -> { where('amount >= 0') }
|
||||
scope :credit, -> { where('amount < 0') }
|
||||
scope :return_authorization, -> { where(source_type: "Spree::ReturnAuthorization") }
|
||||
|
||||
scope :enterprise_fee, -> { where(originator_type: 'EnterpriseFee') }
|
||||
scope :admin, -> { where(source_type: nil, originator_type: nil) }
|
||||
scope :included_tax, -> {
|
||||
where(originator_type: 'Spree::TaxRate', adjustable_type: 'Spree::LineItem')
|
||||
}
|
||||
|
||||
scope :with_tax, -> { where('spree_adjustments.included_tax <> 0') }
|
||||
scope :without_tax, -> { where('spree_adjustments.included_tax = 0') }
|
||||
scope :payment_fee, -> { where(AdjustmentScopes::PAYMENT_FEE_SCOPE) }
|
||||
scope :shipping, -> { where(AdjustmentScopes::SHIPPING_SCOPE) }
|
||||
scope :eligible, -> { where(AdjustmentScopes::ELIGIBLE_SCOPE) }
|
||||
|
||||
localize_number :amount
|
||||
|
||||
# Update the boolean _eligible_ attribute which determines which adjustments
|
||||
# count towards the order's adjustment_total.
|
||||
def set_eligibility
|
||||
result = mandatory || (amount != 0 && eligible_for_originator?)
|
||||
update_column(:eligible, result)
|
||||
end
|
||||
|
||||
# Allow originator of the adjustment to perform an additional eligibility of the adjustment
|
||||
# Should return _true_ if originator is absent or doesn't implement _eligible?_
|
||||
def eligible_for_originator?
|
||||
return true if originator.nil?
|
||||
|
||||
!originator.respond_to?(:eligible?) || originator.eligible?(source)
|
||||
end
|
||||
|
||||
# Update both the eligibility and amount of the adjustment. Adjustments
|
||||
# delegate updating of amount to their Originator when present, but only if
|
||||
# +locked+ is false. Adjustments that are +locked+ will never change their amount.
|
||||
#
|
||||
# Adjustments delegate updating of amount to their Originator when present,
|
||||
# but only if when they're in "open" state, closed or finalized adjustments
|
||||
# are not recalculated.
|
||||
#
|
||||
# It receives +calculable+ as the updated source here so calculations can be
|
||||
# performed on the current values of that source. If we used +source+ it
|
||||
# could load the old record from db for the association. e.g. when updating
|
||||
# more than on line items at once via accepted_nested_attributes the order
|
||||
# object on the association would be in a old state and therefore the
|
||||
# adjustment calculations would not performed on proper values
|
||||
def update!(calculable = nil)
|
||||
return if immutable?
|
||||
|
||||
# Fix for Spree issue #3381
|
||||
# If we attempt to call 'source' before the reload, then source is currently
|
||||
# the order object. After calling a reload, the source is the Shipment.
|
||||
reload
|
||||
originator.update_adjustment(self, calculable || source) if originator.present?
|
||||
set_eligibility
|
||||
end
|
||||
|
||||
def currency
|
||||
adjustable ? adjustable.currency : Spree::Config[:currency]
|
||||
end
|
||||
|
||||
def display_amount
|
||||
Spree::Money.new(amount, currency: currency)
|
||||
end
|
||||
|
||||
def immutable?
|
||||
state != "open"
|
||||
end
|
||||
|
||||
def set_included_tax!(rate)
|
||||
tax = amount - (amount / (1 + rate))
|
||||
set_absolute_included_tax! tax
|
||||
end
|
||||
|
||||
def set_absolute_included_tax!(tax)
|
||||
# This rubocop issue can now fixed by renaming Adjustment#update! to something else,
|
||||
# then AR's update! can be used instead of update_attributes!
|
||||
# rubocop:disable Rails/ActiveRecordAliases
|
||||
update_attributes! included_tax: tax.round(2)
|
||||
# rubocop:enable Rails/ActiveRecordAliases
|
||||
end
|
||||
|
||||
def display_included_tax
|
||||
Spree::Money.new(included_tax, currency: currency)
|
||||
end
|
||||
|
||||
def has_tax?
|
||||
included_tax.positive?
|
||||
end
|
||||
|
||||
def self.without_callbacks
|
||||
skip_callback :save, :after, :update_adjustable
|
||||
skip_callback :destroy, :after, :update_adjustable
|
||||
|
||||
result = yield
|
||||
ensure
|
||||
set_callback :save, :after, :update_adjustable
|
||||
set_callback :destroy, :after, :update_adjustable
|
||||
|
||||
result
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def update_adjustable
|
||||
adjustable.update! if adjustable.is_a? Order
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,62 +0,0 @@
|
||||
require 'spree/localized_number'
|
||||
require 'concerns/adjustment_scopes'
|
||||
|
||||
module Spree
|
||||
Adjustment.class_eval do
|
||||
extend Spree::LocalizedNumber
|
||||
|
||||
# Deletion of metadata is handled in the database.
|
||||
# So we don't need the option `dependent: :destroy` as long as
|
||||
# AdjustmentMetadata has no destroy logic itself.
|
||||
has_one :metadata, class_name: 'AdjustmentMetadata'
|
||||
belongs_to :tax_rate, -> { where spree_adjustments: { originator_type: 'Spree::TaxRate' } },
|
||||
foreign_key: 'originator_id'
|
||||
|
||||
scope :enterprise_fee, -> { where(originator_type: 'EnterpriseFee') }
|
||||
scope :admin, -> { where(source_type: nil, originator_type: nil) }
|
||||
scope :included_tax, -> {
|
||||
where(originator_type: 'Spree::TaxRate', adjustable_type: 'Spree::LineItem')
|
||||
}
|
||||
|
||||
scope :with_tax, -> { where('spree_adjustments.included_tax <> 0') }
|
||||
scope :without_tax, -> { where('spree_adjustments.included_tax = 0') }
|
||||
scope :payment_fee, -> { where(AdjustmentScopes::PAYMENT_FEE_SCOPE) }
|
||||
scope :shipping, -> { where(AdjustmentScopes::SHIPPING_SCOPE) }
|
||||
scope :eligible, -> { where(AdjustmentScopes::ELIGIBLE_SCOPE) }
|
||||
|
||||
localize_number :amount
|
||||
|
||||
def set_included_tax!(rate)
|
||||
tax = amount - (amount / (1 + rate))
|
||||
set_absolute_included_tax! tax
|
||||
end
|
||||
|
||||
def set_absolute_included_tax!(tax)
|
||||
# This rubocop issue can only be fixed when Adjustment#update! is brought from Spree to OFN
|
||||
# and renamed to something else, then AR's update! can be used instead of update_attributes!
|
||||
# rubocop:disable Rails/ActiveRecordAliases
|
||||
update_attributes! included_tax: tax.round(2)
|
||||
# rubocop:enable Rails/ActiveRecordAliases
|
||||
end
|
||||
|
||||
def display_included_tax
|
||||
Spree::Money.new(included_tax, currency: currency)
|
||||
end
|
||||
|
||||
def has_tax?
|
||||
included_tax > 0
|
||||
end
|
||||
|
||||
def self.without_callbacks
|
||||
skip_callback :save, :after, :update_adjustable
|
||||
skip_callback :destroy, :after, :update_adjustable
|
||||
|
||||
result = yield
|
||||
ensure
|
||||
set_callback :save, :after, :update_adjustable
|
||||
set_callback :destroy, :after, :update_adjustable
|
||||
|
||||
result
|
||||
end
|
||||
end
|
||||
end
|
||||
56
app/models/spree/calculator.rb
Normal file
56
app/models/spree/calculator.rb
Normal file
@@ -0,0 +1,56 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Spree
|
||||
class Calculator < ActiveRecord::Base
|
||||
belongs_to :calculable, polymorphic: true
|
||||
|
||||
# This method must be overriden in concrete calculator.
|
||||
#
|
||||
# It should return amount computed based on #calculable and/or optional parameter
|
||||
def compute(_something = nil)
|
||||
raise NotImplementedError, 'please use concrete calculator'
|
||||
end
|
||||
|
||||
# overwrite to provide description for your calculators
|
||||
def self.description
|
||||
'Base Calculator'
|
||||
end
|
||||
|
||||
###################################################################
|
||||
|
||||
def self.register(*klasses); end
|
||||
|
||||
# Returns all calculators applicable for kind of work
|
||||
def self.calculators
|
||||
Rails.application.config.spree.calculators
|
||||
end
|
||||
|
||||
def to_s
|
||||
self.class.name.titleize.gsub("Calculator\/", "")
|
||||
end
|
||||
|
||||
def description
|
||||
self.class.description
|
||||
end
|
||||
|
||||
def available?(_object)
|
||||
true
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Given an object which might be an Order or a LineItem (amongst
|
||||
# others), return a collection of line items.
|
||||
def line_items_for(object)
|
||||
if object.is_a?(Spree::LineItem)
|
||||
[object]
|
||||
elsif object.respond_to? :line_items
|
||||
object.line_items
|
||||
elsif object.respond_to?(:order) && object.order.present?
|
||||
object.order.line_items
|
||||
else
|
||||
[object]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,19 +0,0 @@
|
||||
module Spree
|
||||
Calculator.class_eval do
|
||||
private
|
||||
|
||||
# Given an object which might be an Order or a LineItem (amongst
|
||||
# others), return a collection of line items.
|
||||
def line_items_for(object)
|
||||
if object.is_a?(Spree::LineItem)
|
||||
[object]
|
||||
elsif object.respond_to? :line_items
|
||||
object.line_items
|
||||
elsif object.respond_to?(:order) && object.order.present?
|
||||
object.order.line_items
|
||||
else
|
||||
[object]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,12 +3,14 @@ require 'active_support/concern'
|
||||
# This concern is used to duplicate the associations distributors and distributor_ids
|
||||
# across payment method and gateway
|
||||
# this fixes the inheritance problem https://github.com/openfoodfoundation/openfoodnetwork/issues/2781
|
||||
module Spree::PaymentMethodDistributors
|
||||
extend ActiveSupport::Concern
|
||||
module Spree
|
||||
module PaymentMethodDistributors
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
def self.included(base)
|
||||
base.class_eval do
|
||||
has_and_belongs_to_many :distributors, join_table: 'distributors_payment_methods', class_name: 'Enterprise', foreign_key: 'payment_method_id', association_foreign_key: 'distributor_id'
|
||||
def self.included(base)
|
||||
base.class_eval do
|
||||
has_and_belongs_to_many :distributors, join_table: 'distributors_payment_methods', class_name: 'Enterprise', foreign_key: 'payment_method_id', association_foreign_key: 'distributor_id'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -179,11 +179,11 @@ module Spree
|
||||
# For more information, please see Spree::Payment#set_unique_identifier
|
||||
order_id: gateway_order_id }
|
||||
|
||||
options.merge!({ shipping: order.ship_total * 100,
|
||||
tax: order.tax_total * 100,
|
||||
subtotal: order.item_total * 100,
|
||||
discount: order.promo_total * 100,
|
||||
currency: currency })
|
||||
options.merge!(shipping: order.ship_total * 100,
|
||||
tax: order.tax_total * 100,
|
||||
subtotal: order.item_total * 100,
|
||||
discount: 0,
|
||||
currency: currency)
|
||||
|
||||
options.merge!({ billing_address: order.bill_address.try(:active_merchant_hash),
|
||||
shipping_address: order.ship_address.try(:active_merchant_hash) })
|
||||
|
||||
@@ -1,45 +1,47 @@
|
||||
module Spree::Preferences
|
||||
class FileConfiguration < Configuration
|
||||
def self.preference(name, type, *args)
|
||||
if type == :file
|
||||
super "#{name}_file_name", :string, *args
|
||||
super "#{name}_content_type", :string, *args
|
||||
super "#{name}_file_size", :integer, *args
|
||||
super "#{name}_updated_at", :string, *args
|
||||
module Spree
|
||||
module Preferences
|
||||
class FileConfiguration < Configuration
|
||||
def self.preference(name, type, *args)
|
||||
if type == :file
|
||||
super "#{name}_file_name", :string, *args
|
||||
super "#{name}_content_type", :string, *args
|
||||
super "#{name}_file_size", :integer, *args
|
||||
super "#{name}_updated_at", :string, *args
|
||||
|
||||
else
|
||||
super name, type, *args
|
||||
else
|
||||
super name, type, *args
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_preference(key)
|
||||
if !has_preference?(key) && has_attachment?(key)
|
||||
public_send key
|
||||
else
|
||||
super key
|
||||
def get_preference(key)
|
||||
if !has_preference?(key) && has_attachment?(key)
|
||||
public_send key
|
||||
else
|
||||
super key
|
||||
end
|
||||
end
|
||||
end
|
||||
alias :[] :get_preference
|
||||
alias :[] :get_preference
|
||||
|
||||
def preference_type(name)
|
||||
if has_attachment? name
|
||||
:file
|
||||
else
|
||||
super name
|
||||
def preference_type(name)
|
||||
if has_attachment? name
|
||||
:file
|
||||
else
|
||||
super name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Spree's Configuration responds to preference methods via method_missing, but doesn't
|
||||
# override respond_to?, which consequently reports those methods as unavailable. Paperclip
|
||||
# errors if respond_to? isn't correct, so we override it here.
|
||||
def respond_to?(method, include_all = false)
|
||||
name = method.to_s.delete('=')
|
||||
super(self.class.preference_getter_method(name), include_all) || super(method, include_all)
|
||||
end
|
||||
# Spree's Configuration responds to preference methods via method_missing, but doesn't
|
||||
# override respond_to?, which consequently reports those methods as unavailable. Paperclip
|
||||
# errors if respond_to? isn't correct, so we override it here.
|
||||
def respond_to?(method, include_all = false)
|
||||
name = method.to_s.delete('=')
|
||||
super(self.class.preference_getter_method(name), include_all) || super(method, include_all)
|
||||
end
|
||||
|
||||
def has_attachment?(name)
|
||||
self.class.respond_to?(:attachment_definitions) &&
|
||||
self.class.attachment_definitions.key?(name.to_sym)
|
||||
def has_attachment?(name)
|
||||
self.class.respond_to?(:attachment_definitions) &&
|
||||
self.class.attachment_definitions.key?(name.to_sym)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
20
app/models/spree/tax_category.rb
Normal file
20
app/models/spree/tax_category.rb
Normal file
@@ -0,0 +1,20 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Spree
|
||||
class TaxCategory < ActiveRecord::Base
|
||||
acts_as_paranoid
|
||||
validates :name, presence: true, uniqueness: { scope: :deleted_at }
|
||||
|
||||
has_many :tax_rates, dependent: :destroy
|
||||
|
||||
before_save :set_default_category
|
||||
|
||||
def set_default_category
|
||||
# set existing default tax category to false if this one has been marked as default
|
||||
|
||||
return unless is_default && tax_category = self.class.find_by(is_default: true)
|
||||
|
||||
tax_category.update_column(:is_default, false) unless tax_category == self
|
||||
end
|
||||
end
|
||||
end
|
||||
132
app/models/spree/tax_rate.rb
Normal file
132
app/models/spree/tax_rate.rb
Normal file
@@ -0,0 +1,132 @@
|
||||
# frozen_string_literal: false
|
||||
|
||||
module Spree
|
||||
class DefaultTaxZoneValidator < ActiveModel::Validator
|
||||
def validate(record)
|
||||
return unless record.included_in_price
|
||||
|
||||
return if Zone.default_tax
|
||||
|
||||
record.errors.add(:included_in_price, Spree.t(:included_price_validation))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
module Spree
|
||||
class TaxRate < ActiveRecord::Base
|
||||
acts_as_paranoid
|
||||
include Spree::Core::CalculatedAdjustments
|
||||
belongs_to :zone, class_name: "Spree::Zone"
|
||||
belongs_to :tax_category, class_name: "Spree::TaxCategory"
|
||||
|
||||
validates :amount, presence: true, numericality: true
|
||||
validates :tax_category_id, presence: true
|
||||
validates_with DefaultTaxZoneValidator
|
||||
|
||||
scope :by_zone, ->(zone) { where(zone_id: zone) }
|
||||
|
||||
# Gets the array of TaxRates appropriate for the specified order
|
||||
def self.match(order)
|
||||
return [] if order.distributor && !order.distributor.charges_sales_tax
|
||||
return [] unless order.tax_zone
|
||||
|
||||
all.select do |rate|
|
||||
rate.zone == order.tax_zone || rate.zone.contains?(order.tax_zone) || rate.zone.default_tax
|
||||
end
|
||||
end
|
||||
|
||||
def self.adjust(order)
|
||||
order.adjustments.tax.destroy_all
|
||||
order.line_item_adjustments.where(originator_type: 'Spree::TaxRate').destroy_all
|
||||
|
||||
match(order).each do |rate|
|
||||
rate.adjust(order)
|
||||
end
|
||||
end
|
||||
|
||||
# For VAT, the default rate is the rate that is configured for the default category
|
||||
# It is needed for every price calculation (as all customer facing prices include VAT)
|
||||
# Here we return the actual amount, which may be 0 in case of wrong setup, but is never nil
|
||||
def self.default
|
||||
category = TaxCategory.includes(:tax_rates).find_by(is_default: true)
|
||||
return 0 unless category
|
||||
|
||||
address ||= Address.new(country_id: Spree::Config[:default_country_id])
|
||||
rate = category.tax_rates.detect { |tax_rate| tax_rate.zone.include? address }.try(:amount)
|
||||
|
||||
rate || 0
|
||||
end
|
||||
|
||||
# Creates necessary tax adjustments for the order.
|
||||
def adjust(order)
|
||||
label = create_label
|
||||
if included_in_price
|
||||
if Zone.default_tax.contains? order.tax_zone
|
||||
order.line_items.each { |line_item| create_adjustment(label, line_item, line_item) }
|
||||
else
|
||||
amount = -1 * calculator.compute(order)
|
||||
label = Spree.t(:refund) + label
|
||||
|
||||
order.adjustments.create(
|
||||
amount: amount,
|
||||
source: order,
|
||||
originator: self,
|
||||
state: "closed",
|
||||
label: label
|
||||
)
|
||||
end
|
||||
else
|
||||
create_adjustment(label, order, order)
|
||||
end
|
||||
|
||||
order.adjustments(:reload)
|
||||
order.line_items(:reload)
|
||||
# TaxRate adjustments (order.adjustments.tax)
|
||||
# and price adjustments (tax included on line items) consist of 100% tax
|
||||
(order.adjustments.tax + order.price_adjustments).each do |adjustment|
|
||||
adjustment.set_absolute_included_tax! adjustment.amount
|
||||
end
|
||||
end
|
||||
|
||||
# Manually apply a TaxRate to a particular amount. TaxRates normally compute against
|
||||
# LineItems or Orders, so we mock out a line item here to fit the interface
|
||||
# that our calculator (usually DefaultTax) expects.
|
||||
def compute_tax(amount)
|
||||
line_item = LineItem.new quantity: 1
|
||||
line_item.tax_category = tax_category
|
||||
line_item.define_singleton_method(:price) { amount }
|
||||
|
||||
# Tax on adjustments (represented by the included_tax field) is always inclusive of
|
||||
# tax. However, there's nothing to stop an admin from setting one up with a tax rate
|
||||
# that's marked as not inclusive of tax, and that would result in the DefaultTax
|
||||
# calculator generating a slightly incorrect value. Therefore, we treat the tax
|
||||
# rate as inclusive of tax for the calculations below, regardless of its original
|
||||
# setting.
|
||||
with_tax_included_in_price do
|
||||
calculator.compute line_item
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_label
|
||||
label = ""
|
||||
label << (name.presence || tax_category.name) + " "
|
||||
label << (show_rate_in_label? ? "#{amount * 100}%" : "")
|
||||
end
|
||||
|
||||
def with_tax_included_in_price
|
||||
old_included_in_price = included_in_price
|
||||
|
||||
self.included_in_price = true
|
||||
calculator.calculable.included_in_price = true
|
||||
|
||||
result = yield
|
||||
ensure
|
||||
self.included_in_price = old_included_in_price
|
||||
calculator.calculable.included_in_price = old_included_in_price
|
||||
|
||||
result
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,61 +0,0 @@
|
||||
module Spree
|
||||
TaxRate.class_eval do
|
||||
class << self
|
||||
def match(order)
|
||||
return [] if order.distributor && !order.distributor.charges_sales_tax
|
||||
return [] unless order.tax_zone
|
||||
|
||||
all.select do |rate|
|
||||
rate.zone == order.tax_zone || rate.zone.contains?(order.tax_zone) || rate.zone.default_tax
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def adjust_with_included_tax(order)
|
||||
adjust_without_included_tax(order)
|
||||
|
||||
order.adjustments(:reload)
|
||||
order.line_items(:reload)
|
||||
# TaxRate adjustments (order.adjustments.tax) and price adjustments (tax included on line items) consist of 100% tax
|
||||
(order.adjustments.tax + order.price_adjustments).each do |adjustment|
|
||||
adjustment.set_absolute_included_tax! adjustment.amount
|
||||
end
|
||||
end
|
||||
alias_method_chain :adjust, :included_tax
|
||||
|
||||
# Manually apply a TaxRate to a particular amount. TaxRates normally compute against
|
||||
# LineItems or Orders, so we mock out a line item here to fit the interface
|
||||
# that our calculator (usually DefaultTax) expects.
|
||||
def compute_tax(amount)
|
||||
line_item = LineItem.new quantity: 1
|
||||
line_item.tax_category = tax_category
|
||||
line_item.define_singleton_method(:price) { amount }
|
||||
|
||||
# Tax on adjustments (represented by the included_tax field) is always inclusive of
|
||||
# tax. However, there's nothing to stop an admin from setting one up with a tax rate
|
||||
# that's marked as not inclusive of tax, and that would result in the DefaultTax
|
||||
# calculator generating a slightly incorrect value. Therefore, we treat the tax
|
||||
# rate as inclusive of tax for the calculations below, regardless of its original
|
||||
# setting.
|
||||
with_tax_included_in_price do
|
||||
calculator.compute line_item
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def with_tax_included_in_price
|
||||
old_included_in_price = included_in_price
|
||||
|
||||
self.included_in_price = true
|
||||
calculator.calculable.included_in_price = true
|
||||
|
||||
result = yield
|
||||
ensure
|
||||
self.included_in_price = old_included_in_price
|
||||
calculator.calculable.included_in_price = old_included_in_price
|
||||
|
||||
result
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -990,7 +990,7 @@ ar:
|
||||
resend_email: إعادة إرسال البريد الإلكتروني
|
||||
has_no_payment_methods: "لا تحتوي %{enterprise} حاليًا على طريقة دفع"
|
||||
has_no_shipping_methods: "%{enterprise} لا يوجد لديها حاليا طريقة شحن"
|
||||
email_confirmation: "تأكيد البريد الإلكتروني معلق. لقد أرسلنا رسالة تأكيد بالبريد الإلكتروني إلى %{email}."
|
||||
email_confirmation: "تأكيد البريد الإلكتروني معلق. لقد أرسلنا لك رسالة تأكيد على البريد الإلكتروني إلى %{email}."
|
||||
not_visible: "%{enterprise} غير مرئي وبالتالي لا يمكن العثور عليه على الخريطة أو في عمليات البحث"
|
||||
reports:
|
||||
hidden: خفية
|
||||
@@ -1056,7 +1056,7 @@ ar:
|
||||
unpause_subscription: إلغاء الاشتراك المؤقت
|
||||
cancel_subscription: إلغاء الاشتراك
|
||||
filters:
|
||||
query_placeholder: "البحث عن طريق البريد الإلكتروني ..."
|
||||
query_placeholder: "ابحث عن طريق البريد الإلكتروني ..."
|
||||
setup_explanation:
|
||||
title: "الاشتراكات"
|
||||
just_a_few_more_steps: 'فقط بضع خطوات أخرى قبل أن تبدأ:'
|
||||
@@ -1182,7 +1182,7 @@ ar:
|
||||
footer_secure: "آمن وموثوق به."
|
||||
footer_secure_text: "تستخدم شبكة الغذاء المفتوح تشفير( SSL 2048 بت RSA) في كل مكان للحفاظ على خصوصية معلومات التسوق والدفع. لا تقوم خوادمنا بتخزين تفاصيل بطاقة الائتمان الخاصة بك ، وتتم معالجة المدفوعات بواسطة خدمات متوافقة مع PCI."
|
||||
footer_contact_headline: "أبق على اتصال"
|
||||
footer_contact_email: "ارسل لنا عبر البريد الإلكتروني"
|
||||
footer_contact_email: "راسلنا عبر البريد الإلكتروني"
|
||||
footer_nav_headline: "التنقل"
|
||||
footer_join_headline: "انضم إلينا"
|
||||
footer_join_body: "إنشاء قائمة أو متجر أو دليل المجموعة على شبكة الغذاء المفتوح."
|
||||
@@ -2869,6 +2869,8 @@ ar:
|
||||
adjustments: "التعديلات"
|
||||
payments: "المدفوعات"
|
||||
return_authorizations: "عودة التراخيص"
|
||||
credit_owed: "الائتمان مدين"
|
||||
new_adjustment: "تعديل جديد"
|
||||
payment: "دفعة"
|
||||
payment_method: "طريقة الدفع او السداد"
|
||||
shipment: "الشحنة"
|
||||
@@ -3074,6 +3076,7 @@ ar:
|
||||
other: "منعت أخطاء %{count} حفظ هذا السجل:"
|
||||
there_were_problems_with_the_following_fields: "كانت هناك مشاكل مع الحقول التالية"
|
||||
payments_list:
|
||||
date_time: "التاريخ / الوقت"
|
||||
amount: "القيمة"
|
||||
payment_method: "طريقة الدفع او السداد"
|
||||
payment_state: "حالة الدفعة"
|
||||
@@ -3580,3 +3583,12 @@ ar:
|
||||
shipment:
|
||||
cannot_ready: "لا يمكن تجهيز الشحنة"
|
||||
invalid_taxonomy_id: "معرف التصنيف غير صالح."
|
||||
activerecord:
|
||||
models:
|
||||
spree/payment:
|
||||
zero: المدفوعات
|
||||
one: دفع
|
||||
two: المدفوعات
|
||||
few: المدفوعات
|
||||
many: المدفوعات
|
||||
other: الدفعات
|
||||
|
||||
@@ -2544,7 +2544,7 @@ ca:
|
||||
paid: "pagat"
|
||||
pending: "pendents"
|
||||
processing: "processant"
|
||||
void: "buit"
|
||||
void: "pendent"
|
||||
invalid: "invàlid"
|
||||
resend_user_email_confirmation:
|
||||
resend: "Reenviar"
|
||||
@@ -2849,8 +2849,8 @@ ca:
|
||||
continue: "Continua"
|
||||
fill_in_customer_info: "Ompliu la informació de la consumidora"
|
||||
new_payment: "Nou pagament"
|
||||
capture: "Captura"
|
||||
void: "Buit"
|
||||
capture: "Pagat"
|
||||
void: "Pendent"
|
||||
login: "Inicia sessió"
|
||||
password: "Contrasenya"
|
||||
signature: "Signatura"
|
||||
@@ -3067,7 +3067,7 @@ ca:
|
||||
index:
|
||||
listing_orders: "Llistat comandes"
|
||||
new_order: "Nova comanda"
|
||||
capture: "Captura"
|
||||
capture: "Pagat"
|
||||
ship: "Enviament"
|
||||
edit: "Editar"
|
||||
order_not_updated: "La comanda no s'ha pogut actualitzar"
|
||||
@@ -3201,7 +3201,7 @@ ca:
|
||||
error_saving_payment: Error en desar el pagament
|
||||
submitting_payment: S'està lliurant el pagament...
|
||||
paypal:
|
||||
no_payment_via_admin_backend: Els pagaments amb Paypal no es poden capturar des de l'administració
|
||||
no_payment_via_admin_backend: Els pagaments amb Paypal no es poden marcar com pagats des de l'administració
|
||||
products:
|
||||
image_upload_error: "No s'ha reconegut la imatge del producte. Carregueu una imatge en format PNG o JPG."
|
||||
new:
|
||||
@@ -3363,7 +3363,7 @@ ca:
|
||||
paid: pagat
|
||||
pending: pendents
|
||||
processing: processant
|
||||
void: buit
|
||||
void: pendent
|
||||
invalid: invàlid
|
||||
order_mailer:
|
||||
cancel_email:
|
||||
|
||||
@@ -2771,6 +2771,11 @@ See the %{link} to find out more about %{sitename}'s features and to start using
|
||||
signup_or_login: "Start By Signing Up (or logging in)"
|
||||
have_an_account: "Already have an account?"
|
||||
action_login: "Log in now."
|
||||
stripe_elements:
|
||||
unknown_error_from_stripe: |
|
||||
There was a problem setting up your card in our payments gateway.
|
||||
Please refresh the page and try again, if it fails a second time,
|
||||
please contact us for support.
|
||||
|
||||
# Singular and plural forms of commonly used words.
|
||||
# We use these entries to pluralize unit names in every language.
|
||||
|
||||
@@ -2642,6 +2642,11 @@ en_CA:
|
||||
signup_or_login: "Start By Signing Up (or logging in)"
|
||||
have_an_account: "Already have an account?"
|
||||
action_login: "Log in now."
|
||||
stripe_elements:
|
||||
unknown_error_from_stripe: |
|
||||
There was a problem setting up your card in our payments gateway.
|
||||
Please refresh the page and try again, if it fails a second time,
|
||||
please contact us for support.
|
||||
inflections:
|
||||
each:
|
||||
one: "each"
|
||||
@@ -3301,7 +3306,7 @@ en_CA:
|
||||
sortable_header:
|
||||
name: "Name"
|
||||
number: "Number"
|
||||
state: "Province"
|
||||
state: "State"
|
||||
payment_state: "Payment State"
|
||||
shipment_state: "Shipment State"
|
||||
email: "Email"
|
||||
|
||||
@@ -1244,11 +1244,11 @@ en_FR:
|
||||
menu_4_title: "Groups"
|
||||
menu_4_url: "/groups"
|
||||
menu_5_title: "About"
|
||||
menu_5_url: "https://apropos.openfoodfrance.org/"
|
||||
menu_5_url: "https://apropos.coopcircuits.fr/"
|
||||
menu_6_title: "Connect"
|
||||
menu_6_url: "https://apropos.openfoodfrance.org/blog/"
|
||||
menu_6_url: "https://apropos.coopcircuits.fr/blog/"
|
||||
menu_7_title: "Learn"
|
||||
menu_7_url: "https://apropos.openfoodfrance.org/support/"
|
||||
menu_7_url: "https://apropos.coopcircuits.fr/ressources/"
|
||||
logo: "Logo (640x130)"
|
||||
logo_mobile: "Mobile logo (75x26)"
|
||||
logo_mobile_svg: "Mobile logo (SVG)"
|
||||
@@ -2643,6 +2643,11 @@ en_FR:
|
||||
signup_or_login: "Start By Signing Up (or logging in)"
|
||||
have_an_account: "Already have an account?"
|
||||
action_login: "Log in now."
|
||||
stripe_elements:
|
||||
unknown_error_from_stripe: |
|
||||
There was a problem setting up your card in our payments gateway.
|
||||
Please refresh the page and try again, if it fails a second time,
|
||||
please contact us for support.
|
||||
inflections:
|
||||
each:
|
||||
one: "each"
|
||||
|
||||
@@ -2649,6 +2649,11 @@ en_GB:
|
||||
signup_or_login: "Start By signing up (or logging in)"
|
||||
have_an_account: "Already have an account?"
|
||||
action_login: "Log in now."
|
||||
stripe_elements:
|
||||
unknown_error_from_stripe: |
|
||||
There was a problem setting up your card in our payments gateway.
|
||||
Please refresh the page and try again, if it fails a second time,
|
||||
please contact us for support.
|
||||
inflections:
|
||||
each:
|
||||
one: "each"
|
||||
@@ -2779,6 +2784,8 @@ en_GB:
|
||||
adjustments: "Adjustments"
|
||||
payments: "Payments"
|
||||
return_authorizations: "Return Authorisations"
|
||||
credit_owed: "Credit Owed"
|
||||
new_adjustment: "New Adjustment"
|
||||
payment: "Payment"
|
||||
payment_method: "Payment Method"
|
||||
shipment: "Shipment"
|
||||
@@ -2980,6 +2987,7 @@ en_GB:
|
||||
other: "%{count} errors prohibited this record from being saved:"
|
||||
there_were_problems_with_the_following_fields: "There were problems with the following fields"
|
||||
payments_list:
|
||||
date_time: "Date/time"
|
||||
amount: "Amount"
|
||||
payment_method: "Payment Method"
|
||||
payment_state: "Payment State"
|
||||
@@ -3486,3 +3494,8 @@ en_GB:
|
||||
shipment:
|
||||
cannot_ready: "Cannot ready shipment."
|
||||
invalid_taxonomy_id: "Invalid taxonomy id."
|
||||
activerecord:
|
||||
models:
|
||||
spree/payment:
|
||||
one: Payment
|
||||
other: Payments
|
||||
|
||||
@@ -2773,6 +2773,8 @@ en_US:
|
||||
adjustments: "Adjustments"
|
||||
payments: "Payments"
|
||||
return_authorizations: "Return Authorizations"
|
||||
credit_owed: "Credit Owed"
|
||||
new_adjustment: "New Adjustment"
|
||||
payment: "Payment"
|
||||
payment_method: "Payment Method"
|
||||
shipment: "Shipment"
|
||||
@@ -2974,6 +2976,7 @@ en_US:
|
||||
other: "%{count} errors prohibited this record from being saved:"
|
||||
there_were_problems_with_the_following_fields: "There were problems with the following fields"
|
||||
payments_list:
|
||||
date_time: "Date/time"
|
||||
amount: "Amount"
|
||||
payment_method: "Payment Method"
|
||||
payment_state: "Payment State"
|
||||
@@ -3480,3 +3483,8 @@ en_US:
|
||||
shipment:
|
||||
cannot_ready: "Cannot ready shipment."
|
||||
invalid_taxonomy_id: "Invalid taxonomy id."
|
||||
activerecord:
|
||||
models:
|
||||
spree/payment:
|
||||
one: Payment
|
||||
other: Payments
|
||||
|
||||
@@ -2544,7 +2544,7 @@ es:
|
||||
paid: "pagado"
|
||||
pending: "pendiente"
|
||||
processing: "procesando"
|
||||
void: "vacío"
|
||||
void: "pendiente"
|
||||
invalid: "inválido"
|
||||
resend_user_email_confirmation:
|
||||
resend: "Reenviar"
|
||||
@@ -2849,8 +2849,8 @@ es:
|
||||
continue: "Continuar"
|
||||
fill_in_customer_info: "Por favor complete la información de la consumidora"
|
||||
new_payment: "Nuevo pago"
|
||||
capture: "Captura"
|
||||
void: "Vacío"
|
||||
capture: "Pagado"
|
||||
void: "Pendiente"
|
||||
login: "Iniciar sesión"
|
||||
password: "Contraseña"
|
||||
signature: "Firma"
|
||||
@@ -3067,7 +3067,7 @@ es:
|
||||
index:
|
||||
listing_orders: "Pedidos de listado"
|
||||
new_order: "Nuevo pedido"
|
||||
capture: "Captura"
|
||||
capture: "Pagado"
|
||||
ship: "Envío"
|
||||
edit: "Editar"
|
||||
order_not_updated: "El pedido no se pudo actualizar"
|
||||
@@ -3201,7 +3201,7 @@ es:
|
||||
error_saving_payment: Error al guardar el pago
|
||||
submitting_payment: Enviando pago...
|
||||
paypal:
|
||||
no_payment_via_admin_backend: Los pagos de PayPal no se pueden capturar desde la administración
|
||||
no_payment_via_admin_backend: Los pagos de PayPal no se pueden marcar como pagados desde la administración
|
||||
products:
|
||||
image_upload_error: "La imagen del producto no fue reconocida. Por favor, cargue una imagen en formato PNG o JPG."
|
||||
new:
|
||||
@@ -3363,7 +3363,7 @@ es:
|
||||
paid: pagado
|
||||
pending: pendiente
|
||||
processing: procesando
|
||||
void: vacío
|
||||
void: pendiente
|
||||
invalid: inválido
|
||||
order_mailer:
|
||||
cancel_email:
|
||||
|
||||
@@ -185,7 +185,7 @@ fr:
|
||||
home: "OFF"
|
||||
title: "Open Food France"
|
||||
welcome_to: "Bienvenue sur"
|
||||
site_meta_description: "Tout commence dans le sol. Avec ces paysans, agriculteurs, producteurs, engagés pour une agriculture durable et régénératrice, et désireux de partager leur histoire et leur passion avec fierté. Avec ces distributeurs souhaitant reconnecter les individus à leurs aliments et aux gens qui les produisent, soutenir les prises de conscience, dans une démarche de transparence, d'honnêteté, en assurant une juste rémunération des producteurs. Avec ces acheteurs qui croient que de meilleures décisions d'achats peuvent ..."
|
||||
site_meta_description: "Le service proposé est basé sur le logiciel libre Open Food Network. Les organisateurs de circuits courts qui utilisent la plateforme décident ensemble des évolutions à apporter au logiciel, et gèrent conjointement l’activité de la coopérative CoopCircuits. Ils décident notamment du prix qu’ils paieront pour utiliser cette plateforme."
|
||||
search_by_name: Recherche par nom ou département...
|
||||
producers_join: Les producteurs et autres hubs basés en France sont invités à rejoindre Open Food France.
|
||||
charges_sales_tax: Soumis à la TVA?
|
||||
@@ -1179,21 +1179,21 @@ fr:
|
||||
mobile_menu:
|
||||
cart: "Panier"
|
||||
register_call:
|
||||
selling_on_ofn: "Vous souhaitez proposer vos produits sur Open Food France?"
|
||||
selling_on_ofn: "Vous souhaitez proposer vos produits sur CoopCircuits ?"
|
||||
register: "Démarrez ici"
|
||||
footer:
|
||||
footer_secure: "Fiable et sécurisé."
|
||||
footer_secure_text: "Open Food France utilise un certificat type SSL (2048 bit RSA) pour garantir la confidentialité de votre commandes et données bancaires. Nos serveurs ne conservent pas vos données bancaires et les paiements sont effectués conformément aux normes de sécurité PCI."
|
||||
footer_contact_headline: "Restez en contact"
|
||||
footer_secure_text: "CoopCircuits utilise un certificat type SSL (2048 bit RSA) pour garantir la confidentialité de vos commandes et données bancaires. Nos serveurs ne conservent pas vos données bancaires et les paiements sont effectués conformément aux normes de sécurité PCI."
|
||||
footer_contact_headline: "Général"
|
||||
footer_contact_email: "Nous écrire"
|
||||
footer_nav_headline: "Naviguer"
|
||||
footer_join_headline: "Nous rejoindre"
|
||||
footer_join_body: "Créer un profil, une boutique ou un groupe sur Open Food France."
|
||||
footer_nav_headline: "Naviguer sur la plateforme"
|
||||
footer_join_headline: "S'inscrire"
|
||||
footer_join_body: "Créer un profil, une boutique ou un groupe sur CoopCircuits."
|
||||
footer_join_cta: "Je veux en savoir plus!"
|
||||
footer_legal_call: "Lire nos"
|
||||
footer_legal_tos: "Termes et conditions"
|
||||
footer_legal_tos: "conditions générales d'utilisation"
|
||||
footer_legal_visit: "Nous trouver sur"
|
||||
footer_legal_text_html: "Open Food Network est une plateforme logicielle open source, libre et gratuite. Nos données sont protégées sous licence %{content_license} et notre code sous %{code_license}."
|
||||
footer_legal_text_html: "CoopCircuits utilise pour délivrer son service le logiciel libre Open Food Network, dont le code est protégé sous licence %{code_license}. Les autres productions disponibles sur ce site sont protégées sous licence %{content_license}."
|
||||
footer_data_text_with_privacy_policy_html: "Nous prenons soin de vos données. Voir notre %{privacy_policy} et %{cookies_policy}."
|
||||
footer_data_text_without_privacy_policy_html: "Nous prenons soin de vos données. Voir notre %{cookies_policy}."
|
||||
footer_data_privacy_policy: "politique de confidentialité"
|
||||
@@ -1246,11 +1246,11 @@ fr:
|
||||
menu_4_title: "Groupes"
|
||||
menu_4_url: "/groups"
|
||||
menu_5_title: "A propos"
|
||||
menu_5_url: "https://apropos.openfoodfrance.org/"
|
||||
menu_5_url: "https://openfoodfrance.org/sell"
|
||||
menu_6_title: "Blog"
|
||||
menu_6_url: "https://apropos.openfoodfrance.org/blog/"
|
||||
menu_6_url: "https://apropos.coopcircuits.fr/"
|
||||
menu_7_title: "Support"
|
||||
menu_7_url: "https://apropos.openfoodfrance.org/support/"
|
||||
menu_7_url: "https://apropos.coopcircuits.fr/ressources/"
|
||||
logo: "Logo (640x130)"
|
||||
logo_mobile: "Logo smartphone (75x26)"
|
||||
logo_mobile_svg: "Logo smartphone (SVG)"
|
||||
@@ -1383,24 +1383,24 @@ fr:
|
||||
cookies_accept_button: "Accepter les cookies"
|
||||
home_shop: Faire mes courses
|
||||
brandstory_headline: "Des aliments porteurs de sens."
|
||||
brandstory_intro: "Parfois, le meilleur moyen de réparer le système, c'est d'en inventer un autre..."
|
||||
brandstory_part1: "Tout commence dans le sol. Avec ces paysans, agriculteurs, producteurs, engagés pour une agriculture durable et régénératrice, et désireux de partager leur histoire et leur passion avec fierté. Avec ces distributeurs souhaitant reconnecter les individus à leurs aliments et aux gens qui les produisent, soutenir les prises de conscience, dans une démarche de transparence, d'honnêteté, en assurant une juste rémunération des producteurs. Avec ces acheteurs qui croient que de meilleures décisions d'achats peuvent véritablement changer le monde."
|
||||
brandstory_part2: "Nous avons besoin d'un outil pour rendre tout ça réel. Un moyen de redonner le pouvoir à ceux qui cultivent, vendent et achètent la nourriture. Un moyen de raconter les histoires, de gérer la logistique. Un moyen de transformer chaque jour les transactions en actions porteuses de changement."
|
||||
brandstory_part3: "C'est pour cela que nous construisons cette plateforme, ce \"marché en ligne\", afin de rééquilibrer les échanges et redistribuer le pouvoir. Elle est transparente, pour assurer des relations équitables et favoriser les prises de conscience. Elle est open source, donc possédée par tout le monde. Elle se déploie aux échelles régionales et nationales, et des gens lancent de multiples versions à travers le monde."
|
||||
brandstory_part4: "Elle fonctionne partout. Elle change tout."
|
||||
brandstory_part5_strong: "Cette plateforme s'appelle Open Food Network."
|
||||
brandstory_part6: "Nous aimons notre nourriture. Maintenant nous pouvons aussi aimer notre système alimentaire."
|
||||
brandstory_intro: "Votre plateforme Open Food France change de nom et devient CoopCircuits, une plateforme libre, cogérée et accessible à tous."
|
||||
brandstory_part1: "Le service proposé est basé sur le logiciel libre Open Food Network. Les organisateurs de circuits courts qui utilisent la plateforme décident ensemble des évolutions à apporter au logiciel, et gèrent conjointement l’activité de la coopérative CoopCircuits. Ils décident notamment du prix qu’ils paieront pour utiliser cette plateforme."
|
||||
brandstory_part2: "Afin de permettre à tout type d’initiative de circuit court de fonctionner efficacement, les offres proposées s’adaptent à la diversité des modèles économiques : que vous gériez un groupement d’achat bénévolement, ou pilotiez une entreprise familiale de distribution, CoopCircuits vous accompagne :-)"
|
||||
brandstory_part3: " "
|
||||
brandstory_part4: " "
|
||||
brandstory_part5_strong: " "
|
||||
brandstory_part6: " "
|
||||
learn_body: "Explorer les modèles, les histoires et les ressources disponibles pour vous aider à développer votre propre initiative de commerce/organisation oeuvrant pour un système alimentaire équitable et juste. Trouver des outils pour vous former, des événements et autres opportunités d'apprendre de vos pairs."
|
||||
learn_cta: "Découvrir "
|
||||
connect_body: "Rechercher dans le répertoire des producteurs, hubs et groupes pour trouver des commerçants éthiques à côté de chez vous. Inscrivez votre commerce ou organisation sur OFFrance pour que les acheteurs puissent vous trouver. Rejoignez la communauté pour recevoir du soutien et résoudre ensemble les problèmes."
|
||||
connect_cta: "Explorer"
|
||||
system_headline: "Faire mes courses - comment ça marche?"
|
||||
system_headline: "Commander en ligne - comment ça marche?"
|
||||
system_step1: "1. Recherche"
|
||||
system_step1_text: "Recherchez des produits locaux, de saison, parmi nos multiples boutiques indépendantes. Filtrez par localisation ou catégorie de produits, livraison en point retrait ou à domicile."
|
||||
system_step1_text: "Trouvez le circuit court qui vous convient parmi de multiples points d’achat indépendants aux modèles variés."
|
||||
system_step2: "2. Achat"
|
||||
system_step2_text: "Transformez vos achats en choisissant des produits locaux et abordables, proposés par les divers producteurs et hubs. Découvrez les histoires et les personnes qui se cachent derrière les produits!"
|
||||
system_step2_text: "Commandez en ligne des produits bios/locaux auprès du circuit court sélectionné, et découvrez les producteurs qui se cachent derrière les produits."
|
||||
system_step3: "3. Retrait / Livraison"
|
||||
system_step3_text: "Réceptionnez vos produits à domicile, ou rendez vous chez votre producteur ou hub pour rencontrer les gens qui se cachent derrière les produits. Au delà de la bio-diversité, nous cultivons l'éco-diversité: vivez des expériences d'achat de nourriture uniques et humaines."
|
||||
system_step3_text: "Retirez votre panier au lieu et à l’heure indiqués lors de votre commande, ou à domicile si le circuit sélectionné propose cette option."
|
||||
cta_headline: "Des achats qui rendent le monde un peu meilleur."
|
||||
cta_label: "Je vote avec mes achats"
|
||||
stats_headline: "Nous créons un nouveau système alimentaire."
|
||||
@@ -1600,8 +1600,8 @@ fr:
|
||||
components_filters_nofilters: "Pas de filtre"
|
||||
components_filters_clearfilters: "Vider les filtres"
|
||||
groups_title: Groupes
|
||||
groups_headline: Groupes / réseaux territoriaux
|
||||
groups_text: "Chaque producteur est unique. Chaque entreprise peut offrir quelque chose de différent. Nos groupes sont des collectifs de producteurs, des plateformes et des distributeurs qui partagent une proximité géographique, un marché fermier ou des valeurs. C'est ce qui rend votre expérience d'achat plus simple. Explorez donc ces groupes sélectionnés."
|
||||
groups_headline: Groupes
|
||||
groups_text: "Un groupe sur CoopCircuits est une page permettant de communiquer sur un collectif particulier (de producteurs, réseau de distributeurs d’un même projet et producteurs associés, etc.) Il comprend une présentation du groupe, une carte permettant de visualiser géographiquement les membres, ainsi que des onglets pour un accès rapide aux boutiques et producteurs du groupe."
|
||||
groups_search: "Recherche par nom ou mot-clé"
|
||||
groups_no_groups: "Aucun groupe trouvé"
|
||||
groups_about: "A propos"
|
||||
@@ -1614,23 +1614,23 @@ fr:
|
||||
groups_contact_website: Visiter notre site web
|
||||
groups_contact_facebook: Nous suivre sur Facebook
|
||||
groups_signup_title: S'inscrire en tant que groupe
|
||||
groups_signup_headline: Inscription groupe
|
||||
groups_signup_intro: "Nous sommes une plate-forme très efficace pour le marketing collaboratif, une excellente manière pour vos membres et parties prenantes d'atteindre de nouveaux marchés. Nous sommes à but non lucratif, abordable et simple."
|
||||
groups_signup_headline: 'Groupe : un outil marketing au service de votre réseau'
|
||||
groups_signup_intro: "Rassemblez en un même espace tous les producteurs et boutiques de votre réseau pour renforcer la visibilité de vos membres."
|
||||
groups_signup_email: Nous écrire
|
||||
groups_signup_motivation1: Nous transformons les systèmes alimentaires pour remettre de l'équité dans les échanges.
|
||||
groups_signup_motivation2: C'est pourquoi nous sortons du lit chaque matin. Nous sommes une organisation à but non lucratif, basée sur un code source ouvert. Nous opérons en toute transparence.
|
||||
groups_signup_motivation3: Vous avez de belles idées, et nous voulons vous aider. Nous partageons nos connaissances, réseaux et ressources. Nous savons que l'isolement ne crée pas le changement, alors coopérons.
|
||||
groups_signup_motivation4: Nous venons à votre rencontrer.
|
||||
groups_signup_motivation5: Vous êtes un réseau de circuits de distribution alternatifs, de producteurs, de distributeurs, une administration liée à l'industrie alimentaire ou une autorité locale?
|
||||
groups_signup_motivation6: Quel que soit votre rôle dans la relocalisation des systèmes alimentaires, nous sommes prêts à vous soutenir. Si vous vous demandez à quoi Open Food Network ressemble / pourrait ressembler dans votre coin du monde, contactez-nous.
|
||||
groups_signup_motivation7: Nous contribuons à remettre du sens dans les systèmes alimentaires.
|
||||
groups_signup_motivation8: Vous avez besoin de connecter et d'outiller vos réseaux, nous offrons une plate-forme pour la coopération et l'action. Vous souhaitez de l'engagement. Nous vous aidons à atteindre les acteurs, les parties-prenantes, les secteurs.
|
||||
groups_signup_motivation9: Vous avez besoin de ressources. Nous mettons à votre service notre expérience. Vous avez besoin de coopération. Nous vous connectons à un large réseau d'acteurs et d'organisations soeurs partout dans le monde.
|
||||
groups_signup_pricing: Compte groupe
|
||||
groups_signup_studies: Etudes de cas
|
||||
groups_signup_contact: Vous voulez discuter?
|
||||
groups_signup_contact_text: "Prenez contact et découvrez ce qu'Open Food France peut faire pour vous:"
|
||||
groups_signup_detail: "Plus de précisions."
|
||||
groups_signup_motivation1: A quoi ça sert ?
|
||||
groups_signup_motivation2: Le module “groupe” est un espace dédié comprenant une carte des acteurs de votre réseau, une page de présentation, et une liste des producteurs et des boutiques associées. La carte et les listes comprennent une fonction de recherche. Ce module est accessible via un lien internet (URL) unique et peut être intégré sur votre site web.
|
||||
groups_signup_motivation3: ' '
|
||||
groups_signup_motivation4: ' '
|
||||
groups_signup_motivation5: ' '
|
||||
groups_signup_motivation6: ' '
|
||||
groups_signup_motivation7: ' '
|
||||
groups_signup_motivation8: ' '
|
||||
groups_signup_motivation9: ' '
|
||||
groups_signup_pricing: Pour qui ?
|
||||
groups_signup_studies: Histoires de réseaux
|
||||
groups_signup_contact: Vous souhaitez créer votre module groupe ?
|
||||
groups_signup_contact_text: "Cette fonctionnalité n’est pas encore automatisée. Prenez contact avec nous pour créer votre groupe."
|
||||
groups_signup_detail: "Les avantages CoopCircuits"
|
||||
login_invalid: "Email ou mot de passe erroné"
|
||||
producers_about: A propos
|
||||
producers_buy: Acheter
|
||||
@@ -1644,14 +1644,14 @@ fr:
|
||||
producers_title: Producteurs
|
||||
producers_headline: Trouvez un producteur local
|
||||
producers_signup_title: S'inscrire en tant que producteur
|
||||
producers_signup_headline: Des producteurs, indépendants
|
||||
producers_signup_motivation: Vendez vos produits et racontez vos histoires pour toucher de nouveaux marchés. Gagnez du temps et de l'argent sur la gestion des opérations courantes. Vous pouvez innover sans prendre de risque. Nous nivellons le terrain de jeu pour des échanges plus équitables.
|
||||
producers_signup_send: Rejoindre le réseau
|
||||
producers_signup_enterprise: Comptes entreprises
|
||||
producers_signup_studies: Les histoires de nos producteurs.
|
||||
producers_signup_cta_headline: Rejoindre le réseau!
|
||||
producers_signup_cta_action: Rejoindre le réseau
|
||||
producers_signup_detail: Comment ça marche.
|
||||
producers_signup_headline: 'Producteurs : gérez vos ventes directes'
|
||||
producers_signup_motivation: Vendez vos produits en direct et en ligne via votre boutique producteur. Gagnez du temps sur la gestion de votre commercialisation grâce à CoopCircuits, votre partenaire coopératif et engagé !
|
||||
producers_signup_send: S'inscrire
|
||||
producers_signup_enterprise: CoopCircuits vous simplifie la vie
|
||||
producers_signup_studies: Histoires de producteurs
|
||||
producers_signup_cta_headline: Rejoindre le réseau
|
||||
producers_signup_cta_action: S'inscrire
|
||||
producers_signup_detail: Les avantages CoopCircuits
|
||||
products_item: Produit
|
||||
products_description: Description
|
||||
products_variant: Variante
|
||||
@@ -1661,31 +1661,31 @@ fr:
|
||||
products_price: "Prix"
|
||||
name_or_sku: "NOM OU REF PRODUIT"
|
||||
register_title: S'inscrire
|
||||
sell_title: "S'inscrire"
|
||||
sell_headline: "Aller sur Open Food France!"
|
||||
sell_motivation: "Mettez en avant vos beaux aliments."
|
||||
sell_producers: "Producteurs"
|
||||
sell_hubs: "Hubs"
|
||||
sell_title: "En savoir plus"
|
||||
sell_headline: "Gérez vos ventes en ligne avec CoopCircuits"
|
||||
sell_motivation: "3 options pour interagir avec vos acheteurs"
|
||||
sell_producers: "Boutique producteur"
|
||||
sell_hubs: "Boutique multi-producteurs"
|
||||
sell_groups: "Groupes"
|
||||
sell_producers_detail: "Créer un profil pour votre entreprise sur OFFrance en quelques minutes. A tout moment vous pourrez créer une boutique en ligne pour vendre vos produits en direct aux acheteurs."
|
||||
sell_hubs_detail: "Créer un profil pour votre entreprise de distribution ou organisation sur OFFrance. A tout moment vous pourrez créer une boutique multi-fournisseurs."
|
||||
sell_groups_detail: "Créer un répertoire sur mesure (regroupant différents producteurs et hubs de distribution) pour votre région ou votre organisation."
|
||||
sell_producers_detail: "Vous êtes producteur ? Créez votre profil pour rejoindre le réseau, et ouvrez votre boutique pour vendre en ligne vos produits."
|
||||
sell_hubs_detail: "Vous organisez des distributions de produits en provenance de plusieurs producteurs (drive fermier, groupement d’achat…) ? Créez le profil de votre initiative, et ouvrez votre boutique multi-producteurs."
|
||||
sell_groups_detail: "Vous gérez un collectif et souhaitez communiquer sur l’ensemble des membres qui le composent ? Créez une page groupe."
|
||||
sell_user_guide: "En savoir plus en explorant le guide utilisateur."
|
||||
sell_listing_price: "L'inscription sur OFFrance est gratuite. Ouvrir et gérer une boutique sur OFFrance ou créer un groupe sur OFFrance pour votre organisation ou réseau régional, n'est pas gratuit. Il existe deux formules : soit la formule \"petit débrouillard\" où vous pouvez opter pour un montant libre à nous reverser (mais vous ne pouvez pas disposer de support personnalisé), soit vous nous reversez 1% du volume de vente réalisé sur la plateforme pour bénéfier de notre accompagnement. Ce pourcentage peut être dégressif à partir d'un certain montant. Veuillez nous contacter pour en savoir plus !"
|
||||
sell_embed: "Nous pouvons aussi intégrer votre boutique OFFrance dans votre propre site web ou construire un site web d'alimentation locale sur mesure pour votre région."
|
||||
sell_ask_services: "Nous consulter sur les services des partenaires OFFrance."
|
||||
sell_listing_price: "Créez gratuitement votre profil sur CoopCircuits pour être visible auprès des visiteurs et membres du réseau. L’utilisation de CoopCircuits pour vendre en ligne (boutique) est payante après une période d’essai de 3 mois. Voir le lien “nos offres” en bas de page pour en savoir plus."
|
||||
sell_embed: "Nous pouvons aussi intégrer votre boutique CoopCircuits dans votre propre site web ou construire pour vous un site de vente en ligne s’appuyant sur une boutique CoopCircuits."
|
||||
sell_ask_services: "Nous consulter pour en savoir plus."
|
||||
shops_title: Boutiques
|
||||
shops_headline: Des achats qui transforment.
|
||||
shops_text: Les aliments poussent selon des cycles naturels, les fermiers récoltent en cycles. Alors ici, nous achetons aussi en cycles. Si un cycle de vente est terminé, attendez le suivant ou demandez des infos au hub !
|
||||
shops_headline: Je vote avec mes achats.
|
||||
shops_text: Trouvez des circuits de distribution pour vous approvisionner près de chez vous en bio/local/éthique.
|
||||
shops_signup_title: S'inscrire en tant que hub
|
||||
shops_signup_headline: Des hubs divers et variés
|
||||
shops_signup_motivation: Quel que soit votre modèle, vous pouvez vous appuyer sur Open Food France. Si vous voulez le faire évoluer, nous sommes là pour vous aider. Nous agissons selon des principes de non-lucrativité, d'indépendance, et de transparence. Et nous faisons tout notre possible pour répondre à vos besoins et vous accompagner en toute circonstance.
|
||||
shops_signup_action: Rejoindre le réseau
|
||||
shops_signup_pricing: Comptes entreprises
|
||||
shops_signup_stories: Histoires de hubs.
|
||||
shops_signup_help: Nous sommes là pour vous aider.
|
||||
shops_signup_help_text: Vous avez besoin de pouvoir travailler de manière efficace. Vous avez besoin de nouveaux acheteurs et de partenaires logistiques. Vous souhaitez que votre histoire soit racontée tout au long du circuit, que l'acheteur final sache qui se trouve derrière les produits.
|
||||
shops_signup_detail: Comment ça marche.
|
||||
shops_signup_headline: Des circuits courts offrant une large gamme de produits
|
||||
shops_signup_motivation: 'Que vous soyez vous-même producteur, ou que vous gériez un groupement d’achat, un drive ou autre circuit court, proposez à la vente des produits venant de différents producteurs via votre boutique multi-producteurs. Gagnez du temps sur la gestion de votre commercialisation grâce à CoopCircuits, votre partenaire coopératif et engagé ! '
|
||||
shops_signup_action: S'inscrire
|
||||
shops_signup_pricing: CoopCircuits vous simplifie la vie
|
||||
shops_signup_stories: Histoires de circuits courts
|
||||
shops_signup_help: Rejoindre le réseau
|
||||
shops_signup_help_text: Créez votre profil distributeur, et dès que vous êtes prêt, changez de formule pour ouvrir votre boutique en ligne.
|
||||
shops_signup_detail: Les avantages CoopCircuits
|
||||
orders: Commandes
|
||||
orders_fees: Frais...
|
||||
orders_edit_title: Panier
|
||||
@@ -2673,6 +2673,11 @@ fr:
|
||||
signup_or_login: "Commencez par vous inscrire (ou connexion)"
|
||||
have_an_account: "Déjà inscrit?"
|
||||
action_login: "Se connecter."
|
||||
stripe_elements:
|
||||
unknown_error_from_stripe: |
|
||||
Il a eu un problème lors de la prise en compte de votre carte.
|
||||
Merci de rafraîchir la page. Si cela ne fonctionne pas une seconde fois,
|
||||
merci de nous contacter.
|
||||
inflections:
|
||||
each:
|
||||
one: "chacun"
|
||||
@@ -2748,7 +2753,7 @@ fr:
|
||||
other: "sachets"
|
||||
producers:
|
||||
signup:
|
||||
start_free_profile: "Commencez par créer votre profil entreprise, et changez de formule quand vous êtes prêt !"
|
||||
start_free_profile: "Créez votre profil producteur, et dès que vous êtes prêt, changez de formule pour ouvrir votre boutique en ligne."
|
||||
order_management:
|
||||
reports:
|
||||
enterprise_fee_summaries:
|
||||
|
||||
@@ -721,6 +721,10 @@ pt_BR:
|
||||
enable_subscriptions_tip: "Ativar funcionalidade de inscrições?"
|
||||
enable_subscriptions_false: "Desativado"
|
||||
enable_subscriptions_true: "ativado"
|
||||
customer_names_in_reports: "Nomes dos Clientes nos Relatórios"
|
||||
customer_names_tip: "Permitir que seus fornecedores vejam os nomes dos clientes nos relatórios"
|
||||
customer_names_false: "Desativado"
|
||||
customer_names_true: "Ativado"
|
||||
shopfront_message: "Mensagem da loja virtual"
|
||||
shopfront_message_placeholder: >
|
||||
Uma mensagem opcional para dar as boas-vindas aos clientes e explicar
|
||||
@@ -2771,6 +2775,8 @@ pt_BR:
|
||||
adjustments: "Ajustes"
|
||||
payments: "Pagamentos"
|
||||
return_authorizations: "Autorizações de Retorno"
|
||||
credit_owed: "Crédito Devido"
|
||||
new_adjustment: "Novo Ajuste"
|
||||
payment: "Pagamento"
|
||||
payment_method: "Método de Pagamento"
|
||||
shipment: "Envio"
|
||||
@@ -2972,6 +2978,7 @@ pt_BR:
|
||||
other: "%{count}erros não permitiram que esse registro fosse salvo:"
|
||||
there_were_problems_with_the_following_fields: "Houve problemas com os seguintes campos"
|
||||
payments_list:
|
||||
date_time: "Data/hora"
|
||||
amount: "Montante"
|
||||
payment_method: "Método de Pagamento"
|
||||
payment_state: "Estado de pagamento"
|
||||
@@ -3189,6 +3196,8 @@ pt_BR:
|
||||
stripe:
|
||||
error_saving_payment: Erro ao salvar o pagamento
|
||||
submitting_payment: Enviando pagamento ...
|
||||
paypal:
|
||||
no_payment_via_admin_backend: Pagamentos por Paypal não podem ser completados na Área Administrativa
|
||||
products:
|
||||
image_upload_error: "A imagem do produto não foi reconhecida. Faça o upload de uma imagem no formato PNG ou JPG."
|
||||
new:
|
||||
@@ -3242,6 +3251,8 @@ pt_BR:
|
||||
bulk_coop_allocation: 'Atacado Cooperativa - Alocação'
|
||||
bulk_coop_packing_sheets: 'Atacado Cooperativa - Folhas de Empacotamento'
|
||||
bulk_coop_customer_payments: 'Atacado Cooperativa - Pagamentos de Cliente'
|
||||
customer_names_message:
|
||||
customer_names_tip: "Se os nomes dos clientes estiverem ocultos na lista, você pode entrar em contato com o seu distribuidor e perguntar se ele pode atualizar as preferências de modo que os fornecedores possam ver os nomes dos clientes."
|
||||
users:
|
||||
index:
|
||||
listing_users: "Listando Usuários"
|
||||
@@ -3474,3 +3485,8 @@ pt_BR:
|
||||
shipment:
|
||||
cannot_ready: "Não é possível completar a entrega."
|
||||
invalid_taxonomy_id: "Id invalido de taxonomia"
|
||||
activerecord:
|
||||
models:
|
||||
spree/payment:
|
||||
one: Pagamentos
|
||||
other: Pagamentos
|
||||
|
||||
@@ -11,6 +11,9 @@ env "MAILTO", app_config["SCHEDULE_NOTIFICATIONS"] if app_config["SCHEDULE_NOTIF
|
||||
job_type :run_file, "cd :path; :environment_variable=:environment bundle exec script/rails runner :task :output"
|
||||
job_type :enqueue_job, "cd :path; :environment_variable=:environment bundle exec script/enqueue :task :priority :output"
|
||||
|
||||
every 1.month do
|
||||
rake 'ofn:data:remove_transient_data'
|
||||
end
|
||||
|
||||
every 1.day, at: '2:45am' do
|
||||
rake 'db2fog:clean' if app_config['S3_BACKUPS_BUCKET']
|
||||
|
||||
13
lib/tasks/data/remove_transient_data.rake
Normal file
13
lib/tasks/data/remove_transient_data.rake
Normal file
@@ -0,0 +1,13 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'highline'
|
||||
require 'tasks/data/remove_transient_data'
|
||||
|
||||
namespace :ofn do
|
||||
namespace :data do
|
||||
desc 'Remove transient data'
|
||||
task remove_transient_data: :environment do
|
||||
RemoveTransientData.new.call
|
||||
end
|
||||
end
|
||||
end
|
||||
19
lib/tasks/data/remove_transient_data.rb
Normal file
19
lib/tasks/data/remove_transient_data.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class RemoveTransientData
|
||||
RETENTION_PERIOD = 6.months.ago.to_date
|
||||
|
||||
# This model lets us operate on the sessions DB table using ActiveRecord's
|
||||
# methods within the scope of this service. This relies on the AR's
|
||||
# convention where a Session model maps to a sessions table.
|
||||
class Session < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def call
|
||||
Rails.logger.info("#{self.class.name}: processing")
|
||||
|
||||
Spree::StateChange.where("created_at < ?", RETENTION_PERIOD).delete_all
|
||||
Spree::LogEntry.where("created_at < ?", RETENTION_PERIOD).delete_all
|
||||
Session.where("updated_at < ?", RETENTION_PERIOD).delete_all
|
||||
end
|
||||
end
|
||||
@@ -1,12 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class TruncateData
|
||||
# This model lets us operate on the sessions DB table using ActiveRecord's
|
||||
# methods within the scope of this service. This relies on the AR's
|
||||
# convention where a Session model maps to a sessions table.
|
||||
class Session < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def initialize(months_to_keep = nil)
|
||||
@date = (months_to_keep || 24).to_i.months.ago
|
||||
end
|
||||
@@ -25,8 +19,6 @@ class TruncateData
|
||||
sql_delete_from "order_cycles #{where_ocs_to_delete}"
|
||||
|
||||
Spree::TokenizedPermission.where("created_at < '#{date}'").delete_all
|
||||
|
||||
remove_transient_data
|
||||
end
|
||||
end
|
||||
|
||||
@@ -47,12 +39,6 @@ class TruncateData
|
||||
sql_delete_from "spree_return_authorizations #{where_order_id_in_orders_to_delete}"
|
||||
end
|
||||
|
||||
def remove_transient_data
|
||||
Spree::StateChange.delete_all("created_at < '#{1.month.ago.to_date}'")
|
||||
Spree::LogEntry.delete_all("created_at < '#{1.month.ago.to_date}'")
|
||||
Session.delete_all("created_at < '#{2.weeks.ago.to_date}'")
|
||||
end
|
||||
|
||||
def truncate_subscriptions
|
||||
sql_delete_from "order_cycle_schedules #{where_oc_id_in_ocs_to_delete}"
|
||||
sql_delete_from "proxy_orders #{where_oc_id_in_ocs_to_delete}"
|
||||
|
||||
9
spec/factories/return_authorization_factory.rb
Normal file
9
spec/factories/return_authorization_factory.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
FactoryBot.define do
|
||||
factory :return_authorization, class: Spree::ReturnAuthorization do
|
||||
number '100'
|
||||
amount 100.00
|
||||
association(:order, factory: :shipped_order)
|
||||
reason 'no particular reason'
|
||||
state 'received'
|
||||
end
|
||||
end
|
||||
@@ -1,5 +1,9 @@
|
||||
describe 'CreditCard service', ->
|
||||
CreditCard = null
|
||||
CreditCards = null
|
||||
$http = null
|
||||
Loading = null
|
||||
RailsFlashLoader = null
|
||||
|
||||
beforeEach ->
|
||||
module 'Darkswarm'
|
||||
@@ -8,19 +12,43 @@ describe 'CreditCard service', ->
|
||||
$provide.value "railsFlash", null
|
||||
null
|
||||
|
||||
inject (_CreditCard_)->
|
||||
inject (_CreditCard_, _CreditCards_, _$httpBackend_, _Loading_, _RailsFlashLoader_)->
|
||||
CreditCard = _CreditCard_
|
||||
CreditCards = _CreditCards_
|
||||
$http = _$httpBackend_
|
||||
Loading = _Loading_
|
||||
RailsFlashLoader = _RailsFlashLoader_
|
||||
|
||||
CreditCard.secrets =
|
||||
card:
|
||||
exp_month: "12"
|
||||
exp_year: "2030"
|
||||
last4: "1234"
|
||||
cc_type: 'mastercard'
|
||||
token: "token123"
|
||||
|
||||
describe "submit", ->
|
||||
it "adds a credit card", ->
|
||||
$http.expectPUT("/credit_cards/new_from_token").respond(200, {})
|
||||
spyOn(CreditCards, "add")
|
||||
|
||||
CreditCard.submit()
|
||||
$http.flush()
|
||||
|
||||
expect(CreditCards.add).toHaveBeenCalled()
|
||||
|
||||
it "reports errors", ->
|
||||
$http.expectPUT("/credit_cards/new_from_token").respond(500, {})
|
||||
spyOn(Loading, "clear")
|
||||
spyOn(RailsFlashLoader, "loadFlash")
|
||||
|
||||
CreditCard.submit()
|
||||
$http.flush()
|
||||
|
||||
expect(Loading.clear).toHaveBeenCalled()
|
||||
expect(RailsFlashLoader.loadFlash).toHaveBeenCalled()
|
||||
|
||||
describe "process_params", ->
|
||||
beforeEach ->
|
||||
CreditCard.secrets =
|
||||
card:
|
||||
exp_month: "12"
|
||||
exp_year: "2030"
|
||||
last4: "1234"
|
||||
cc_type: 'mastercard'
|
||||
token: "token123"
|
||||
|
||||
it "uses cc_type, rather than fetching the brand from the card", ->
|
||||
# This is important for processing the card with activemerchant
|
||||
process_params = CreditCard.process_params()
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
describe 'Messages service', ->
|
||||
Messages = null
|
||||
Loading = null
|
||||
RailsFlashLoader = null
|
||||
|
||||
beforeEach ->
|
||||
module 'Darkswarm'
|
||||
|
||||
module ($provide)->
|
||||
$provide.value "railsFlash", null
|
||||
null
|
||||
|
||||
inject (_Messages_, _Loading_, _RailsFlashLoader_)->
|
||||
Messages = _Messages_
|
||||
Loading = _Loading_
|
||||
RailsFlashLoader = _RailsFlashLoader_
|
||||
|
||||
it "shows a loading message", ->
|
||||
Messages.loading("Hang on...")
|
||||
expect(Loading.message).toEqual "Hang on..."
|
||||
|
||||
it "shows a success message", ->
|
||||
spyOn(RailsFlashLoader, "loadFlash")
|
||||
Messages.success("Yay!")
|
||||
expect(RailsFlashLoader.loadFlash).toHaveBeenCalledWith({success: "Yay!"})
|
||||
|
||||
it "shows a error message", ->
|
||||
spyOn(RailsFlashLoader, "loadFlash")
|
||||
Messages.error("Boo!")
|
||||
expect(RailsFlashLoader.loadFlash).toHaveBeenCalledWith({error: "Boo!"})
|
||||
|
||||
it "shows a flash message", ->
|
||||
data = {info: "thinking"}
|
||||
spyOn(RailsFlashLoader, "loadFlash")
|
||||
Messages.flash(data)
|
||||
expect(RailsFlashLoader.loadFlash).toHaveBeenCalledWith(data)
|
||||
|
||||
it "clears a loading message", ->
|
||||
Messages.loading("Hang on...")
|
||||
Messages.success("Done.")
|
||||
expect(Loading.message).toEqual null
|
||||
@@ -46,10 +46,12 @@ describe 'StripeElements Service', ->
|
||||
it "doesn't submit the form, shows an error message instead", inject (Loading, RailsFlashLoader) ->
|
||||
spyOn(Loading, "clear")
|
||||
spyOn(RailsFlashLoader, "loadFlash")
|
||||
spyOn(Bugsnag, "notify")
|
||||
StripeElements.requestToken(secrets, submit).then (data) ->
|
||||
expect(submit).not.toHaveBeenCalled()
|
||||
expect(Loading.clear).toHaveBeenCalled()
|
||||
expect(RailsFlashLoader.loadFlash).toHaveBeenCalledWith({error: "Error: There was a problem"})
|
||||
expect(Bugsnag.notify).toHaveBeenCalled()
|
||||
|
||||
describe 'mapTokenApiCardBrand', ->
|
||||
it "maps the brand returned by Stripe's tokenAPI to that required by activemerchant", ->
|
||||
|
||||
39
spec/lib/tasks/data/remove_transient_data_spec.rb
Normal file
39
spec/lib/tasks/data/remove_transient_data_spec.rb
Normal file
@@ -0,0 +1,39 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require 'tasks/data/remove_transient_data'
|
||||
|
||||
describe RemoveTransientData do
|
||||
describe '#call' do
|
||||
let(:retention_period) { RemoveTransientData::RETENTION_PERIOD }
|
||||
|
||||
before do
|
||||
allow(Spree::StateChange).to receive(:delete_all)
|
||||
allow(Spree::LogEntry).to receive(:delete_all)
|
||||
allow(RemoveTransientData::Session).to receive(:delete_all)
|
||||
allow(Rails.logger).to receive(:info)
|
||||
end
|
||||
|
||||
it 'deletes state changes older than rentention_period' do
|
||||
Spree::StateChange.create(created_at: retention_period - 1.day)
|
||||
|
||||
RemoveTransientData.new.call
|
||||
expect(Spree::StateChange.all).to be_empty
|
||||
end
|
||||
|
||||
it 'deletes log entries older than retention_period' do
|
||||
Spree::LogEntry.create(created_at: retention_period - 1.day)
|
||||
|
||||
expect { RemoveTransientData.new.call }
|
||||
.to change(Spree::LogEntry, :count).by(-1)
|
||||
end
|
||||
|
||||
it 'deletes sessions older than retention_period' do
|
||||
RemoveTransientData::Session.create(session_id: 1, updated_at: retention_period - 1.day)
|
||||
|
||||
RemoveTransientData.new.call
|
||||
|
||||
expect(RemoveTransientData::Session.all).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -7,9 +7,6 @@ describe TruncateData do
|
||||
describe '#call' do
|
||||
before do
|
||||
allow(Spree::ReturnAuthorization).to receive(:delete_all)
|
||||
allow(Spree::StateChange).to receive(:delete_all)
|
||||
allow(Spree::LogEntry).to receive(:delete_all)
|
||||
allow(TruncateData::Session).to receive(:delete_all)
|
||||
allow(Rails.logger).to receive(:info)
|
||||
end
|
||||
|
||||
@@ -24,30 +21,6 @@ describe TruncateData do
|
||||
|
||||
expect(OrderCycle.all).to be_empty
|
||||
end
|
||||
|
||||
it 'deletes state changes older than a month' do
|
||||
TruncateData.new.call
|
||||
|
||||
expect(Spree::StateChange)
|
||||
.to have_received(:delete_all)
|
||||
.with("created_at < '#{1.month.ago.to_date}'")
|
||||
end
|
||||
|
||||
it 'deletes log entries older than a month' do
|
||||
TruncateData.new.call
|
||||
|
||||
expect(Spree::LogEntry)
|
||||
.to have_received(:delete_all)
|
||||
.with("created_at < '#{1.month.ago.to_date}'")
|
||||
end
|
||||
|
||||
it 'deletes sessions older than two weeks' do
|
||||
TruncateData.new.call
|
||||
|
||||
expect(TruncateData::Session)
|
||||
.to have_received(:delete_all)
|
||||
.with("created_at < '#{2.weeks.ago.to_date}'")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when months_to_keep is nil' do
|
||||
@@ -61,30 +34,6 @@ describe TruncateData do
|
||||
|
||||
expect(OrderCycle.all).to be_empty
|
||||
end
|
||||
|
||||
it 'deletes state changes older than a month' do
|
||||
TruncateData.new.call
|
||||
|
||||
expect(Spree::StateChange)
|
||||
.to have_received(:delete_all)
|
||||
.with("created_at < '#{1.month.ago.to_date}'")
|
||||
end
|
||||
|
||||
it 'deletes log entries older than a month' do
|
||||
TruncateData.new.call
|
||||
|
||||
expect(Spree::LogEntry)
|
||||
.to have_received(:delete_all)
|
||||
.with("created_at < '#{1.month.ago.to_date}'")
|
||||
end
|
||||
|
||||
it 'deletes sessions older than two weeks' do
|
||||
TruncateData.new.call
|
||||
|
||||
expect(TruncateData::Session)
|
||||
.to have_received(:delete_all)
|
||||
.with("created_at < '#{2.weeks.ago.to_date}'")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when months_to_keep is specified' do
|
||||
@@ -102,30 +51,6 @@ describe TruncateData do
|
||||
|
||||
expect(OrderCycle.all).to contain_exactly(recent_order_cycle)
|
||||
end
|
||||
|
||||
it 'deletes state changes older than a month' do
|
||||
TruncateData.new.call
|
||||
|
||||
expect(Spree::StateChange)
|
||||
.to have_received(:delete_all)
|
||||
.with("created_at < '#{1.month.ago.to_date}'")
|
||||
end
|
||||
|
||||
it 'deletes log entries older than a month' do
|
||||
TruncateData.new.call
|
||||
|
||||
expect(Spree::LogEntry)
|
||||
.to have_received(:delete_all)
|
||||
.with("created_at < '#{1.month.ago.to_date}'")
|
||||
end
|
||||
|
||||
it 'deletes sessions older than two weeks' do
|
||||
TruncateData.new.call
|
||||
|
||||
expect(TruncateData::Session)
|
||||
.to have_received(:delete_all)
|
||||
.with("created_at < '#{2.weeks.ago.to_date}'")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,6 +2,212 @@ require 'spec_helper'
|
||||
|
||||
module Spree
|
||||
describe Adjustment do
|
||||
let(:order) { build(:order) }
|
||||
let(:adjustment) { Spree::Adjustment.create(label: "Adjustment", amount: 5) }
|
||||
|
||||
describe "scopes" do
|
||||
let!(:arbitrary_adjustment) { create(:adjustment, source: nil, label: "Arbitrary") }
|
||||
let!(:return_authorization_adjustment) { create(:adjustment, source: create(:return_authorization)) }
|
||||
|
||||
it "returns return_authorization adjustments" do
|
||||
expect(Spree::Adjustment.return_authorization.to_a).to eq [return_authorization_adjustment]
|
||||
end
|
||||
end
|
||||
|
||||
context "#update!" do
|
||||
context "when originator present" do
|
||||
let(:originator) { double("originator", update_adjustment: nil) }
|
||||
before do
|
||||
allow(originator).to receive_messages update_amount: true
|
||||
allow(adjustment).to receive_messages originator: originator, label: 'adjustment', amount: 0
|
||||
end
|
||||
|
||||
it "should do nothing when closed" do
|
||||
adjustment.close
|
||||
expect(originator).not_to receive(:update_adjustment)
|
||||
adjustment.update!
|
||||
end
|
||||
|
||||
it "should do nothing when finalized" do
|
||||
adjustment.finalize
|
||||
expect(originator).not_to receive(:update_adjustment)
|
||||
adjustment.update!
|
||||
end
|
||||
|
||||
it "should set the eligibility" do
|
||||
expect(adjustment).to receive(:set_eligibility)
|
||||
adjustment.update!
|
||||
end
|
||||
|
||||
it "should ask the originator to update_adjustment" do
|
||||
expect(originator).to receive(:update_adjustment)
|
||||
adjustment.update!
|
||||
end
|
||||
end
|
||||
|
||||
it "should do nothing when originator is nil" do
|
||||
allow(adjustment).to receive_messages originator: nil
|
||||
expect(adjustment).not_to receive(:amount=)
|
||||
adjustment.update!
|
||||
end
|
||||
end
|
||||
|
||||
context "#eligible? after #set_eligibility" do
|
||||
context "when amount is 0" do
|
||||
before { adjustment.amount = 0 }
|
||||
it "should be eligible if mandatory?" do
|
||||
adjustment.mandatory = true
|
||||
adjustment.set_eligibility
|
||||
expect(adjustment).to be_eligible
|
||||
end
|
||||
|
||||
it "should not be eligible unless mandatory?" do
|
||||
adjustment.mandatory = false
|
||||
adjustment.set_eligibility
|
||||
expect(adjustment).to_not be_eligible
|
||||
end
|
||||
end
|
||||
|
||||
context "when amount is greater than 0" do
|
||||
before { adjustment.amount = 25.00 }
|
||||
|
||||
it "should be eligible if mandatory?" do
|
||||
adjustment.mandatory = true
|
||||
adjustment.set_eligibility
|
||||
expect(adjustment).to be_eligible
|
||||
end
|
||||
|
||||
it "should be eligible if not mandatory and eligible for the originator" do
|
||||
adjustment.mandatory = false
|
||||
allow(adjustment).to receive_messages(eligible_for_originator?: true)
|
||||
adjustment.set_eligibility
|
||||
expect(adjustment).to be_eligible
|
||||
end
|
||||
|
||||
it "should not be eligible if not mandatory not eligible for the originator" do
|
||||
adjustment.mandatory = false
|
||||
allow(adjustment).to receive_messages(eligible_for_originator?: false)
|
||||
adjustment.set_eligibility
|
||||
expect(adjustment).to_not be_eligible
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "#save" do
|
||||
it "should call order#update!" do
|
||||
adjustment = Spree::Adjustment.new(
|
||||
adjustable: order,
|
||||
amount: 10,
|
||||
label: "Foo"
|
||||
)
|
||||
expect(order).to receive(:update!)
|
||||
adjustment.save
|
||||
end
|
||||
end
|
||||
|
||||
context "adjustment state" do
|
||||
let(:adjustment) { create(:adjustment, state: 'open') }
|
||||
|
||||
context "#immutable?" do
|
||||
it "is true when adjustment state isn't open" do
|
||||
adjustment.state = "closed"
|
||||
expect(adjustment).to be_immutable
|
||||
adjustment.state = "finalized"
|
||||
expect(adjustment).to be_immutable
|
||||
end
|
||||
|
||||
it "is false when adjustment state is open" do
|
||||
adjustment.state = "open"
|
||||
expect(adjustment).to_not be_immutable
|
||||
end
|
||||
end
|
||||
|
||||
context "#finalized?" do
|
||||
it "is true when adjustment state is finalized" do
|
||||
adjustment.state = "finalized"
|
||||
expect(adjustment).to be_finalized
|
||||
end
|
||||
|
||||
it "is false when adjustment state isn't finalized" do
|
||||
adjustment.state = "closed"
|
||||
expect(adjustment).to_not be_finalized
|
||||
adjustment.state = "open"
|
||||
expect(adjustment).to_not be_finalized
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "#eligible_for_originator?" do
|
||||
context "with no originator" do
|
||||
specify { expect(adjustment).to be_eligible_for_originator }
|
||||
end
|
||||
|
||||
context "with originator that doesn't have 'eligible?'" do
|
||||
before { adjustment.originator = build(:tax_rate) }
|
||||
specify { expect(adjustment).to be_eligible_for_originator }
|
||||
end
|
||||
|
||||
context "with originator that has 'eligible?'" do
|
||||
let(:originator) { Spree::TaxRate.new }
|
||||
before { adjustment.originator = originator }
|
||||
|
||||
context "and originator is eligible for order" do
|
||||
before { allow(originator).to receive_messages(eligible?: true) }
|
||||
specify { expect(adjustment).to be_eligible_for_originator }
|
||||
end
|
||||
|
||||
context "and originator is not eligible for order" do
|
||||
before { allow(originator).to receive_messages(eligible?: false) }
|
||||
specify { expect(adjustment).to_not be_eligible_for_originator }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "#display_amount" do
|
||||
before { adjustment.amount = 10.55 }
|
||||
|
||||
context "with display_currency set to true" do
|
||||
before { Spree::Config[:display_currency] = true }
|
||||
|
||||
it "shows the currency" do
|
||||
expect(adjustment.display_amount.to_s).to eq "$10.55 #{Spree::Config[:currency]}"
|
||||
end
|
||||
end
|
||||
|
||||
context "with display_currency set to false" do
|
||||
before { Spree::Config[:display_currency] = false }
|
||||
|
||||
it "does not include the currency" do
|
||||
expect(adjustment.display_amount.to_s).to eq "$10.55"
|
||||
end
|
||||
end
|
||||
|
||||
context "with currency set to JPY" do
|
||||
context "when adjustable is set to an order" do
|
||||
before do
|
||||
allow(order).to receive(:currency) { 'JPY' }
|
||||
adjustment.adjustable = order
|
||||
end
|
||||
|
||||
it "displays in JPY" do
|
||||
expect(adjustment.display_amount.to_s).to eq "¥11"
|
||||
end
|
||||
end
|
||||
|
||||
context "when adjustable is nil" do
|
||||
it "displays in the default currency" do
|
||||
expect(adjustment.display_amount.to_s).to eq "$10.55"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context '#currency' do
|
||||
it 'returns the globally configured currency' do
|
||||
expect(adjustment.currency).to eq Spree::Config[:currency]
|
||||
end
|
||||
end
|
||||
|
||||
it "has metadata" do
|
||||
adjustment = create(:adjustment, metadata: create(:adjustment_metadata))
|
||||
expect(adjustment.metadata).to be
|
||||
@@ -39,7 +245,7 @@ module Spree
|
||||
let!(:zone) { create(:zone_with_member) }
|
||||
let!(:order) { create(:order, bill_address: create(:address)) }
|
||||
let!(:line_item) { create(:line_item, order: order) }
|
||||
let(:tax_rate) { create(:tax_rate, included_in_price: true, calculator: Calculator::FlatRate.new(preferred_amount: 0.1)) }
|
||||
let(:tax_rate) { create(:tax_rate, included_in_price: true, calculator: ::Calculator::FlatRate.new(preferred_amount: 0.1)) }
|
||||
let(:adjustment) { line_item.adjustments(:reload).first }
|
||||
|
||||
before do
|
||||
@@ -205,8 +411,10 @@ module Spree
|
||||
end
|
||||
|
||||
context "when enterprise fees inherit their tax_category from the product they are applied to" do
|
||||
let(:product_tax_rate) { create(:tax_rate, included_in_price: true, calculator: ::Calculator::DefaultTax.new, zone: zone, amount: 0.2) }
|
||||
let(:product_tax_category) { create(:tax_category, tax_rates: [product_tax_rate]) }
|
||||
let(:product_tax_rate) {
|
||||
create(:tax_rate, included_in_price: true, calculator: ::Calculator::DefaultTax.new, zone: zone, amount: 0.2)
|
||||
}
|
||||
let(:product_tax_category) { create(:tax_category, tax_rates: [product_tax_rate]) }
|
||||
|
||||
before do
|
||||
variant.product.update_attribute(:tax_category_id, product_tax_category.id)
|
||||
|
||||
30
spec/models/spree/tax_category_spec.rb
Normal file
30
spec/models/spree/tax_category_spec.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Spree::TaxCategory do
|
||||
context 'default tax category' do
|
||||
let(:tax_category) { create(:tax_category) }
|
||||
let(:new_tax_category) { create(:tax_category) }
|
||||
|
||||
before do
|
||||
tax_category.update_column(:is_default, true)
|
||||
end
|
||||
|
||||
it "should undefault the previous default tax category" do
|
||||
new_tax_category.update({ is_default: true })
|
||||
expect(new_tax_category.is_default).to be_truthy
|
||||
|
||||
tax_category.reload
|
||||
expect(tax_category.is_default).to be_falsy
|
||||
end
|
||||
|
||||
it "undefaults the previous default tax category
|
||||
except when updating the existing default tax category" do
|
||||
tax_category.update_column(:description, "Updated description")
|
||||
|
||||
tax_category.reload
|
||||
expect(tax_category.is_default).to be_truthy
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user