mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-02-28 01:53:25 +00:00
Compare commits
1 Commits
v4.4.9
...
v4.4.5-pat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0262dcd11b |
8
.env
8
.env
@@ -52,8 +52,6 @@ SMTP_PASSWORD="f00d"
|
||||
|
||||
# see="https://developers.google.com/maps/documentation/javascript/get-api-key
|
||||
# GOOGLE_MAPS_API_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
# see https://developers.google.com/maps/documentation/javascript/localization#Region
|
||||
# GOOGLE_MAPS_REGION="XX"
|
||||
|
||||
# Stripe details for instance account
|
||||
# Find these under 'Developers' -> 'API keys' in your Stripe account dashboard.
|
||||
@@ -63,9 +61,3 @@ SMTP_PASSWORD="f00d"
|
||||
# STRIPE_INSTANCE_PUBLISHABLE_KEY="pk_test_xxxx" # This can be a test key or a live key
|
||||
# STRIPE_CLIENT_ID="ca_xxxx" # This can be a development ID or a production ID
|
||||
# STRIPE_ENDPOINT_SECRET="whsec_xxxx"
|
||||
|
||||
# New relic settings
|
||||
# see: https://one.eu.newrelic.com/admin-portal/, Administration > API keys to get the license key
|
||||
# NEW_RELIC_AGENT_ENABLED=true
|
||||
# NEW_RELIC_APP_NAME="Open Food Network"
|
||||
# NEW_RELIC_LICENSE_KEY="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||
|
||||
20
.github/ISSUE_TEMPLATE/release.md
vendored
20
.github/ISSUE_TEMPLATE/release.md
vendored
@@ -10,26 +10,16 @@ assignees: ''
|
||||
## 1. Preparation on Thursday
|
||||
|
||||
- [ ] Merge pull requests in the [Ready To Go] column
|
||||
- [ ] Include translations
|
||||
<details><summary>Command line instructions:</summary>
|
||||
<pre>
|
||||
git checkout master
|
||||
git pull upstream master
|
||||
tx pull --force
|
||||
git commit -a -m "Update all locales with the latest Transifex translations"
|
||||
git push upstream master</pre>
|
||||
</details>
|
||||
- [ ] Create a tag: `git push upstream HEAD:refs/tags/vX.Y.Z`
|
||||
- [ ] Include translations: `tx pull --force`
|
||||
- [ ] [Draft new release]. Look at previous [releases] for inspiration.
|
||||
- Select new release tag
|
||||
- _Generate release notes_ and arrange into categories as required.
|
||||
- [ ] Notify [#instance-managers] of user-facing changes.
|
||||
|
||||
## 2. Testing
|
||||
|
||||
- [ ] [Find build] of the release commit and copy it below.
|
||||
- [ ] Move this issue to Test Ready.
|
||||
- [ ] Notify `@testers` in [#testing].
|
||||
- [ ] Test build: [Deploy to Staging] with release tag.
|
||||
- [ ] Test build: <!-- paste build link here, e.g. https://semaphore...builds/1234 -->
|
||||
|
||||
## 3. Finish on Tuesday
|
||||
|
||||
@@ -39,7 +29,7 @@ assignees: ''
|
||||
<pre>
|
||||
cd ofn-install
|
||||
git pull
|
||||
ansible-playbook --limit all-prod --extra-vars "git_version=vX.Y.Z" playbooks/deploy.yml
|
||||
ansible-playbook --limit all-prod --extra-vars "git_version=vx.y.z" playbooks/deploy.yml
|
||||
</pre>
|
||||
</details>
|
||||
- [ ] Notify [#instance-managers]:
|
||||
@@ -54,5 +44,5 @@ The full process is described at https://github.com/openfoodfoundation/openfoodn
|
||||
[releases]: https://github.com/openfoodfoundation/openfoodnetwork/releases
|
||||
[#instance-managers]: https://app.slack.com/client/T02G54U79/CG7NJ966B
|
||||
[#testing]: https://openfoodnetwork.slack.com/app_redirect?channel=C02TZ6X00
|
||||
[Deploy to Staging]: https://github.com/openfoodfoundation/openfoodnetwork/actions/workflows/stage.yml
|
||||
[Find build]: https://semaphoreci.com/openfoodfoundation/openfoodnetwork-2/branches/master
|
||||
[#global-community]: https://app.slack.com/client/T02G54U79/C59ADD8F2
|
||||
|
||||
11
.github/release.yml
vendored
11
.github/release.yml
vendored
@@ -1,11 +0,0 @@
|
||||
changelog:
|
||||
categories:
|
||||
- title: "User-facing changes 👀" # Other categories will need to be manually arrange for now.
|
||||
labels:
|
||||
- '*'
|
||||
exclude:
|
||||
labels:
|
||||
- dependencies
|
||||
- title: Dependencies 📦
|
||||
labels:
|
||||
- dependencies
|
||||
6
.github/workflows/stage.yml
vendored
6
.github/workflows/stage.yml
vendored
@@ -13,10 +13,6 @@ on:
|
||||
- staging.openfoodnetwork.org.uk
|
||||
- staging.openfoodnetwork.org.au
|
||||
- staging.coopcircuits.fr
|
||||
commit_ref:
|
||||
description: "Commit Reference"
|
||||
type: string
|
||||
required: false
|
||||
|
||||
jobs:
|
||||
deploy_pr:
|
||||
@@ -63,4 +59,4 @@ jobs:
|
||||
- name: Deploy to Staging
|
||||
if: success()
|
||||
run: |
|
||||
ssh ofn-deploy@${{ inputs.server }} -o LogLevel=ERROR "$GITHUB_REF_NAME ${{ inputs.commit_ref || github.sha }}"
|
||||
ssh ofn-deploy@${{ inputs.server }} -o LogLevel=ERROR "$GITHUB_REF_NAME $GITHUB_SHA"
|
||||
|
||||
@@ -13,8 +13,7 @@ postcss.config.js
|
||||
|
||||
# SCSS
|
||||
# Enabled: most of admin
|
||||
/app/webpacker/css/admin/globals/mixins.scss
|
||||
/app/webpacker/css/admin/globals/variables.scss
|
||||
/app/webpacker/css/admin/globals/
|
||||
/app/webpacker/css/admin/shared/
|
||||
/app/webpacker/css/admin_v3/globals/variables.scss
|
||||
/app/webpacker/css/darkswarm/
|
||||
|
||||
@@ -53,13 +53,6 @@ Rails/ApplicationRecord:
|
||||
# Migrations should not contain application code:
|
||||
- "db/migrate/*.rb"
|
||||
|
||||
# Allow many-to-many associations without explicit model.
|
||||
# - It avoids the additional code of a model class.
|
||||
# - It simplifies the declaration of the association.
|
||||
# - Rails may know that there are no callbacks associated.
|
||||
Rails/HasAndBelongsToMany:
|
||||
Enabled: false
|
||||
|
||||
Rails/SkipsModelValidations:
|
||||
AllowedMethods:
|
||||
- "touch"
|
||||
|
||||
@@ -1,18 +1,38 @@
|
||||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 1400 --no-auto-gen-timestamp`
|
||||
# using RuboCop version 1.56.0.
|
||||
# using RuboCop version 1.55.0.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the offenses are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
# versions of RuboCop, may require this file to be generated again.
|
||||
|
||||
# Offense count: 1
|
||||
# Offense count: 67
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
|
||||
# URISchemes: http, https
|
||||
Layout/LineLength:
|
||||
Exclude:
|
||||
- 'spec/system/admin/tag_rules_spec.rb'
|
||||
- 'app/controllers/spree/users_controller.rb'
|
||||
- 'app/models/customer.rb'
|
||||
- 'app/models/spree/line_item.rb'
|
||||
- 'spec/controllers/admin/order_cycles_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/orders_controller_spec.rb'
|
||||
- 'spec/lib/reports/customers_report_spec.rb'
|
||||
- 'spec/migrations/migrate_customer_names_spec.rb'
|
||||
- 'spec/models/order_cycle_spec.rb'
|
||||
- 'spec/models/product_importer_spec.rb'
|
||||
- 'spec/models/spree/adjustment_spec.rb'
|
||||
- 'spec/models/spree/line_item_spec.rb'
|
||||
- 'spec/models/spree/variant_spec.rb'
|
||||
- 'spec/services/products_renderer_spec.rb'
|
||||
- 'spec/system/admin/adjustments_spec.rb'
|
||||
- 'spec/system/admin/bulk_order_management_spec.rb'
|
||||
- 'spec/system/admin/customers_spec.rb'
|
||||
- 'spec/system/admin/order_cycles/simple_spec.rb'
|
||||
- 'spec/system/admin/orders_spec.rb'
|
||||
- 'spec/system/admin/product_import_spec.rb'
|
||||
- 'spec/system/consumer/shopping/cart_spec.rb'
|
||||
- 'spec/system/consumer/shopping/products_spec.rb'
|
||||
|
||||
# Offense count: 17
|
||||
# Configuration parameters: AllowedMethods.
|
||||
@@ -53,7 +73,7 @@ Lint/DuplicateRequire:
|
||||
Exclude:
|
||||
- 'spec/lib/open_food_network/scope_variants_to_search_spec.rb'
|
||||
|
||||
# Offense count: 18
|
||||
# Offense count: 19
|
||||
# Configuration parameters: AllowComments, AllowEmptyLambdas.
|
||||
Lint/EmptyBlock:
|
||||
Exclude:
|
||||
@@ -192,17 +212,21 @@ Metrics/BlockNesting:
|
||||
Exclude:
|
||||
- 'app/models/spree/payment/processing.rb'
|
||||
|
||||
# Offense count: 45
|
||||
# Offense count: 48
|
||||
# Configuration parameters: CountComments, Max, CountAsOne.
|
||||
Metrics/ClassLength:
|
||||
Exclude:
|
||||
- 'app/components/products_table_component.rb'
|
||||
- 'app/controllers/admin/enterprises_controller.rb'
|
||||
- 'app/controllers/admin/order_cycles_controller.rb'
|
||||
- 'app/controllers/admin/product_import_controller.rb'
|
||||
- 'app/controllers/admin/resource_controller.rb'
|
||||
- 'app/controllers/admin/schedules_controller.rb'
|
||||
- 'app/controllers/admin/subscriptions_controller.rb'
|
||||
- 'app/controllers/api/v0/products_controller.rb'
|
||||
- 'app/controllers/application_controller.rb'
|
||||
- 'app/controllers/payment_gateways/paypal_controller.rb'
|
||||
- 'app/controllers/split_checkout_controller.rb'
|
||||
- 'app/controllers/spree/admin/orders_controller.rb'
|
||||
- 'app/controllers/spree/admin/payment_methods_controller.rb'
|
||||
- 'app/controllers/spree/admin/payments_controller.rb'
|
||||
@@ -223,16 +247,15 @@ Metrics/ClassLength:
|
||||
- 'app/models/spree/payment.rb'
|
||||
- 'app/models/spree/product.rb'
|
||||
- 'app/models/spree/shipment.rb'
|
||||
- 'app/models/spree/shipping_method.rb'
|
||||
- 'app/models/spree/user.rb'
|
||||
- 'app/models/spree/variant.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
- 'app/reflexes/products_reflex.rb'
|
||||
- 'app/serializers/api/cached_enterprise_serializer.rb'
|
||||
- 'app/serializers/api/enterprise_shopfront_serializer.rb'
|
||||
- 'app/services/cart_service.rb'
|
||||
- 'app/services/order_cycle_form.rb'
|
||||
- 'app/services/order_syncer.rb'
|
||||
- 'app/services/sets/product_set.rb'
|
||||
- 'engines/order_management/app/services/order_management/order/updater.rb'
|
||||
- 'lib/open_food_network/enterprise_fee_calculator.rb'
|
||||
- 'lib/open_food_network/order_cycle_form_applicator.rb'
|
||||
@@ -420,6 +443,39 @@ Naming/VariableNumber:
|
||||
- 'spec/models/spree/tax_rate_spec.rb'
|
||||
- 'spec/requests/api/orders_spec.rb'
|
||||
|
||||
# Offense count: 9
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: ExpectedOrder, Include.
|
||||
# ExpectedOrder: index, show, new, edit, create, update, destroy
|
||||
# Include: app/controllers/**/*.rb
|
||||
Rails/ActionOrder:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/resource_controller.rb'
|
||||
- 'app/controllers/api/v0/orders_controller.rb'
|
||||
- 'app/controllers/spree/admin/images_controller.rb'
|
||||
- 'app/controllers/spree/admin/invoices_controller.rb'
|
||||
- 'app/controllers/spree/admin/products_controller.rb'
|
||||
- 'app/controllers/spree/admin/taxons_controller.rb'
|
||||
- 'app/controllers/spree/admin/variants_controller.rb'
|
||||
- 'app/controllers/user_confirmations_controller.rb'
|
||||
|
||||
# Offense count: 12
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/models/**/*.rb
|
||||
Rails/ActiveRecordCallbacksOrder:
|
||||
Exclude:
|
||||
- 'app/models/customer.rb'
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/enterprise_group.rb'
|
||||
- 'app/models/enterprise_relationship.rb'
|
||||
- 'app/models/spree/order.rb'
|
||||
- 'app/models/spree/payment.rb'
|
||||
- 'app/models/spree/product.rb'
|
||||
- 'app/models/spree/return_authorization.rb'
|
||||
- 'app/models/spree/user.rb'
|
||||
- 'app/models/spree/variant.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: Severity, Include.
|
||||
# Include: app/models/**/*.rb
|
||||
@@ -427,6 +483,86 @@ Rails/ActiveRecordOverride:
|
||||
Exclude:
|
||||
- 'app/models/spree/product.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Rails/ApplicationController:
|
||||
Exclude:
|
||||
- 'engines/dfc_provider/app/controllers/dfc_provider/base_controller.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: NilOrEmpty, NotPresent, UnlessPresent.
|
||||
Rails/Blank:
|
||||
Exclude:
|
||||
- 'app/models/spree/order_contents.rb'
|
||||
- 'app/services/content_sanitizer.rb'
|
||||
- 'engines/order_management/app/services/order_management/stock/package.rb'
|
||||
- 'lib/stripe/authorize_response_patcher.rb'
|
||||
|
||||
# Offense count: 17
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Rails/CompactBlank:
|
||||
Exclude:
|
||||
- 'app/controllers/spree/admin/users_controller.rb'
|
||||
- 'app/models/concerns/address_display.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
- 'app/services/order_cycle_form.rb'
|
||||
- 'lib/reporting/report_headers_builder.rb'
|
||||
- 'lib/reporting/report_ruler.rb'
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/parameters.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Rails/DotSeparatedKeys:
|
||||
Exclude:
|
||||
- 'app/controllers/api/v1/base_controller.rb'
|
||||
|
||||
# Offense count: 27
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Rails/DurationArithmetic:
|
||||
Exclude:
|
||||
- 'app/services/create_order_cycle.rb'
|
||||
- 'spec/jobs/order_cycle_closing_job_spec.rb'
|
||||
- 'spec/jobs/order_cycle_opened_job_spec.rb'
|
||||
- 'spec/services/permissions/order_spec.rb'
|
||||
- 'spec/services/terms_of_service_spec.rb'
|
||||
- 'spec/system/admin/bulk_order_management_spec.rb'
|
||||
- 'spec/system/admin/order_cycles/list_spec.rb'
|
||||
- 'spec/system/admin/orders_spec.rb'
|
||||
- 'spec/system/admin/reports/orders_and_fulfillment_spec.rb'
|
||||
- 'spec/system/admin/reports/packing_report_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Rails/ExpandedDateRange:
|
||||
Exclude:
|
||||
- 'app/models/spree/product.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: slashes, arguments
|
||||
Rails/FilePath:
|
||||
Exclude:
|
||||
- 'app/models/product_import/product_importer.rb'
|
||||
- 'lib/tasks/karma.rake'
|
||||
- 'spec/base_spec_helper.rb'
|
||||
- 'spec/models/content_configuration_spec.rb'
|
||||
- 'spec/support/downloads_helper.rb'
|
||||
|
||||
# Offense count: 8
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/models/**/*.rb
|
||||
Rails/HasAndBelongsToMany:
|
||||
Exclude:
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/enterprise_group.rb'
|
||||
- 'app/models/order_cycle.rb'
|
||||
- 'app/models/spree/role.rb'
|
||||
- 'app/models/spree/shipping_method.rb'
|
||||
- 'app/models/spree/user.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
|
||||
# Offense count: 47
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/models/**/*.rb
|
||||
@@ -467,6 +603,14 @@ Rails/HelperInstanceVariable:
|
||||
- 'app/helpers/spree/admin/orders_helper.rb'
|
||||
- 'app/helpers/spree/orders_helper.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/controllers/**/*.rb
|
||||
Rails/I18nLazyLookup:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/proxy_orders_controller.rb'
|
||||
|
||||
# Offense count: 8
|
||||
# Configuration parameters: Include.
|
||||
# Include: spec/**/*.rb, test/**/*.rb
|
||||
@@ -482,6 +626,12 @@ Rails/I18nLocaleTexts:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/stripe_accounts_controller.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Rails/IgnoredColumnsAssignment:
|
||||
Exclude:
|
||||
- 'app/models/spree/variant.rb'
|
||||
|
||||
# Offense count: 22
|
||||
# Configuration parameters: IgnoreScopes, Include.
|
||||
# Include: app/models/**/*.rb
|
||||
@@ -501,7 +651,7 @@ Rails/InverseOf:
|
||||
- 'app/models/spree/variant.rb'
|
||||
- 'app/models/subscription_line_item.rb'
|
||||
|
||||
# Offense count: 35
|
||||
# Offense count: 38
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/controllers/**/*.rb, app/mailers/**/*.rb
|
||||
Rails/LexicallyScopedActionFilter:
|
||||
@@ -582,24 +732,28 @@ Rails/PluckInWhere:
|
||||
Exclude:
|
||||
- 'app/models/spree/variant.rb'
|
||||
|
||||
# Offense count: 22
|
||||
# Offense count: 30
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Rails/RedundantPresenceValidationOnBelongsTo:
|
||||
Exclude:
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/enterprise_fee.rb'
|
||||
- 'app/models/enterprise_group.rb'
|
||||
- 'app/models/enterprise_relationship.rb'
|
||||
- 'app/models/enterprise_role.rb'
|
||||
- 'app/models/exchange.rb'
|
||||
- 'app/models/inventory_item.rb'
|
||||
- 'app/models/order_cycle.rb'
|
||||
- 'app/models/spree/address.rb'
|
||||
- 'app/models/spree/line_item.rb'
|
||||
- 'app/models/spree/order.rb'
|
||||
- 'app/models/spree/product.rb'
|
||||
- 'app/models/spree/product_property.rb'
|
||||
- 'app/models/spree/return_authorization.rb'
|
||||
- 'app/models/spree/state.rb'
|
||||
- 'app/models/spree/stock_item.rb'
|
||||
- 'app/models/spree/stock_movement.rb'
|
||||
- 'app/models/spree/tax_rate.rb'
|
||||
- 'app/models/spree/variant.rb'
|
||||
- 'app/models/subscription_line_item.rb'
|
||||
- 'app/models/tag_rule.rb'
|
||||
- 'app/models/variant_override.rb'
|
||||
@@ -630,14 +784,30 @@ Rails/ResponseParsedBody:
|
||||
- 'spec/controllers/spree/credit_cards_controller_spec.rb'
|
||||
- 'spec/controllers/user_registrations_controller_spec.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Offense count: 4
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Rails/RootPathnameMethods:
|
||||
Exclude:
|
||||
- 'spec/lib/reports/orders_and_fulfillment/order_cycle_customer_totals_report_spec.rb'
|
||||
- 'spec/models/content_configuration_spec.rb'
|
||||
- 'spec/models/terms_of_service_file_spec.rb'
|
||||
- 'spec/system/admin/configuration/terms_of_service_files_spec.rb'
|
||||
|
||||
# Offense count: 13
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Rails/RootPublicPath:
|
||||
Exclude:
|
||||
- 'app/controllers/concerns/request_timeouts.rb'
|
||||
- 'lib/spree/core/controller_helpers/common.rb'
|
||||
- 'spec/controllers/api/v0/product_images_controller_spec.rb'
|
||||
- 'spec/controllers/api/v0/terms_and_conditions_controller_spec.rb'
|
||||
- 'spec/models/terms_of_service_file_spec.rb'
|
||||
- 'spec/system/admin/bulk_product_update_spec.rb'
|
||||
- 'spec/system/admin/enterprises/terms_and_conditions_spec.rb'
|
||||
- 'spec/system/consumer/shopping/checkout_spec.rb'
|
||||
- 'spec/system/consumer/shopping/embedded_groups_spec.rb'
|
||||
- 'spec/system/consumer/split_checkout_spec.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# Configuration parameters: ForbiddenMethods, AllowedMethods.
|
||||
# ForbiddenMethods: decrement!, decrement_counter, increment!, increment_counter, insert, insert!, insert_all, insert_all!, toggle!, touch, touch_all, update_all, update_attribute, update_column, update_columns, update_counters, upsert, upsert_all
|
||||
@@ -654,6 +824,16 @@ Rails/SquishedSQLHeredocs:
|
||||
- 'app/queries/outstanding_balance.rb'
|
||||
- 'spec/queries/outstanding_balance_spec.rb'
|
||||
|
||||
# Offense count: 24
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Rails/StripHeredoc:
|
||||
Exclude:
|
||||
- 'app/models/content_configuration.rb'
|
||||
- 'app/queries/customers_with_balance.rb'
|
||||
- 'app/queries/outstanding_balance.rb'
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/scope.rb'
|
||||
- 'lib/tasks/data/truncate_data.rake'
|
||||
|
||||
# Offense count: 3
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
@@ -736,6 +916,28 @@ Rails/WhereExists:
|
||||
- 'lib/tasks/sample_data/order_cycle_factory.rb'
|
||||
- 'lib/tasks/sample_data/taxon_factory.rb'
|
||||
|
||||
# Offense count: 24
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Rails/WhereNot:
|
||||
Exclude:
|
||||
- 'app/controllers/spree/admin/products_controller.rb'
|
||||
- 'app/models/concerns/permalink_generator.rb'
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/enterprise_fee.rb'
|
||||
- 'app/models/enterprise_relationship.rb'
|
||||
- 'app/models/product_import/inventory_reset_strategy.rb'
|
||||
- 'app/models/proxy_order.rb'
|
||||
- 'app/models/spree/credit_card.rb'
|
||||
- 'app/models/spree/product.rb'
|
||||
- 'app/models/spree/variant.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
- 'app/models/variant_override.rb'
|
||||
- 'app/services/cap_quantity.rb'
|
||||
- 'engines/catalog/app/services/catalog/product_import/products_reset_strategy.rb'
|
||||
- 'engines/order_management/app/services/order_management/subscriptions/proxy_order_syncer.rb'
|
||||
- 'lib/reporting/reports/users_and_enterprises/base.rb'
|
||||
- 'lib/tasks/data/anonymize_data.rake'
|
||||
|
||||
# Offense count: 1
|
||||
Security/Open:
|
||||
Exclude:
|
||||
@@ -754,6 +956,12 @@ Style/ArrayIntersect:
|
||||
- 'lib/open_food_network/tag_rule_applicator.rb'
|
||||
- 'spec/support/matchers/select2_matchers.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Style/BlockComments:
|
||||
Exclude:
|
||||
- 'spec/system/admin/tag_rules_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: AllowOnConstant, AllowOnSelfClass.
|
||||
@@ -796,6 +1004,20 @@ Style/ClassVars:
|
||||
Exclude:
|
||||
- 'lib/spree/core/delegate_belongs_to.rb'
|
||||
|
||||
# Offense count: 9
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: AllowedVars.
|
||||
Style/FetchEnvVar:
|
||||
Exclude:
|
||||
- 'app/helpers/discourse_helper.rb'
|
||||
- 'app/models/spree/preferences/configuration.rb'
|
||||
- 'app/models/spree/preferences/preferable.rb'
|
||||
- 'app/services/default_country.rb'
|
||||
- 'spec/base_spec_helper.rb'
|
||||
- 'spec/controllers/spree/credit_cards_controller_spec.rb'
|
||||
- 'spec/models/order_balance_spec.rb'
|
||||
- 'spec/support/vcr_setup.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Style/FileRead:
|
||||
@@ -856,6 +1078,14 @@ Style/GuardClause:
|
||||
- 'spec/support/request/shop_workflow.rb'
|
||||
- 'spec/system/support/precompile_assets.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: braces, no_braces
|
||||
Style/HashAsLastArrayItem:
|
||||
Exclude:
|
||||
- 'app/components/products_table_component.rb'
|
||||
|
||||
# Offense count: 12
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: AllowSplatArgument.
|
||||
@@ -878,7 +1108,7 @@ Style/HashLikeCase:
|
||||
Exclude:
|
||||
- 'app/models/enterprise.rb'
|
||||
|
||||
# Offense count: 1784
|
||||
# Offense count: 1781
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: EnforcedStyle, EnforcedShorthandSyntax, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
|
||||
# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
|
||||
@@ -887,6 +1117,8 @@ Style/HashSyntax:
|
||||
Exclude:
|
||||
- 'app/components/confirm_modal_component.rb'
|
||||
- 'app/components/help_modal_component.rb'
|
||||
- 'app/components/products_table_component.rb'
|
||||
- 'app/components/selector_with_filter_component.rb'
|
||||
- 'app/controllers/admin/customers_controller.rb'
|
||||
- 'app/controllers/admin/enterprise_fees_controller.rb'
|
||||
- 'app/controllers/admin/enterprise_groups_controller.rb'
|
||||
@@ -1028,6 +1260,7 @@ Style/HashSyntax:
|
||||
- 'lib/tasks/sample_data/user_factory.rb'
|
||||
- 'lib/tasks/subscriptions/debug.rake'
|
||||
- 'lib/tasks/subscriptions/test.rake'
|
||||
- 'spec/components/product_component_spec.rb'
|
||||
- 'spec/constraints/feature_toggle_constraint_spec.rb'
|
||||
- 'spec/controllers/admin/bulk_line_items_controller_spec.rb'
|
||||
- 'spec/controllers/admin/customers_controller_spec.rb'
|
||||
@@ -1083,6 +1316,7 @@ Style/HashSyntax:
|
||||
- 'spec/helpers/spree/base_helper_spec.rb'
|
||||
- 'spec/jobs/report_job_spec.rb'
|
||||
- 'spec/jobs/subscription_confirm_job_spec.rb'
|
||||
- 'spec/jobs/subscription_placement_job_spec.rb'
|
||||
- 'spec/jobs/webhook_delivery_job_spec.rb'
|
||||
- 'spec/lib/open_food_network/address_finder_spec.rb'
|
||||
- 'spec/lib/open_food_network/enterprise_fee_applicator_spec.rb'
|
||||
@@ -1126,6 +1360,7 @@ Style/HashSyntax:
|
||||
- 'spec/models/concerns/order_shipment_spec.rb'
|
||||
- 'spec/models/concerns/product_stock_spec.rb'
|
||||
- 'spec/models/customer_spec.rb'
|
||||
- 'spec/models/enterprise_caching_spec.rb'
|
||||
- 'spec/models/enterprise_fee_spec.rb'
|
||||
- 'spec/models/enterprise_relationship_spec.rb'
|
||||
- 'spec/models/enterprise_spec.rb'
|
||||
@@ -1139,6 +1374,7 @@ Style/HashSyntax:
|
||||
- 'spec/models/spree/address_spec.rb'
|
||||
- 'spec/models/spree/adjustment_spec.rb'
|
||||
- 'spec/models/spree/calculator_spec.rb'
|
||||
- 'spec/models/spree/classification_spec.rb'
|
||||
- 'spec/models/spree/credit_card_spec.rb'
|
||||
- 'spec/models/spree/gateway/stripe_sca_spec.rb'
|
||||
- 'spec/models/spree/inventory_unit_spec.rb'
|
||||
@@ -1168,6 +1404,7 @@ Style/HashSyntax:
|
||||
- 'spec/queries/customers_with_balance_spec.rb'
|
||||
- 'spec/queries/outstanding_balance_spec.rb'
|
||||
- 'spec/queries/payments_requiring_action_spec.rb'
|
||||
- 'spec/requests/admin/vouchers_controller_spec.rb'
|
||||
- 'spec/requests/api/v1/customers_spec.rb'
|
||||
- 'spec/requests/checkout/failed_checkout_spec.rb'
|
||||
- 'spec/requests/checkout/paypal_spec.rb'
|
||||
@@ -1380,13 +1617,14 @@ Style/RedundantArgument:
|
||||
- 'engines/dfc_provider/app/services/authorization_control.rb'
|
||||
- 'spec/support/query_counter.rb'
|
||||
|
||||
# Offense count: 13
|
||||
# Offense count: 14
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Style/RedundantConstantBase:
|
||||
Exclude:
|
||||
- 'app/controllers/split_checkout_controller.rb'
|
||||
- 'app/controllers/webhook_endpoints_controller.rb'
|
||||
- 'config.ru'
|
||||
- 'spec/base_spec_helper.rb'
|
||||
- 'spec/helpers/checkout_helper_spec.rb'
|
||||
- 'spec/models/spree/order_spec.rb'
|
||||
- 'spec/models/spree/payment_method_spec.rb'
|
||||
@@ -1407,13 +1645,6 @@ Style/RedundantInitialize:
|
||||
Exclude:
|
||||
- 'spec/models/spree/gateway_spec.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
Style/RedundantInterpolation:
|
||||
Exclude:
|
||||
- 'lib/tasks/karma.rake'
|
||||
- 'spec/base_spec_helper.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Style/RedundantRegexpArgument:
|
||||
@@ -1421,17 +1652,6 @@ Style/RedundantRegexpArgument:
|
||||
- 'app/models/spree/shipping_method.rb'
|
||||
- 'lib/spree/i18n.rb'
|
||||
|
||||
# Offense count: 5
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: AllowMultipleReturnValues.
|
||||
Style/RedundantReturn:
|
||||
Exclude:
|
||||
- 'app/models/product_import/entry_validator.rb'
|
||||
- 'app/models/spree/stock/availability_validator.rb'
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/summarizer.rb'
|
||||
- 'lib/stripe/authorize_response_patcher.rb'
|
||||
- 'lib/tasks/data.rake'
|
||||
|
||||
# Offense count: 4
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Style/RedundantStringEscape:
|
||||
@@ -1449,9 +1669,10 @@ Style/ReturnNilInPredicateMethodDefinition:
|
||||
- 'app/serializers/api/admin/customer_serializer.rb'
|
||||
- 'engines/order_management/app/services/order_management/subscriptions/validator.rb'
|
||||
|
||||
# Offense count: 204
|
||||
# Offense count: 205
|
||||
Style/Send:
|
||||
Exclude:
|
||||
- 'app/controllers/split_checkout_controller.rb'
|
||||
- 'spec/controllers/admin/subscriptions_controller_spec.rb'
|
||||
- 'spec/controllers/payment_gateways/paypal_controller_spec.rb'
|
||||
- 'spec/controllers/spree/admin/base_controller_spec.rb'
|
||||
|
||||
7
Gemfile
7
Gemfile
@@ -103,8 +103,8 @@ gem 'redis', '>= 4.0', require: ['redis', 'redis/connection/hiredis']
|
||||
gem 'sidekiq'
|
||||
gem 'sidekiq-scheduler'
|
||||
|
||||
gem "cable_ready", "5.0.1"
|
||||
gem "stimulus_reflex", "3.5.0.rc3"
|
||||
gem "cable_ready", "5.0.0.rc2"
|
||||
gem "stimulus_reflex", "3.5.0.rc2"
|
||||
|
||||
gem 'combine_pdf'
|
||||
gem 'wicked_pdf'
|
||||
@@ -138,8 +138,6 @@ gem 'mini_portile2', '~> 2.8'
|
||||
gem "faraday"
|
||||
gem "private_address_check"
|
||||
|
||||
gem 'newrelic_rpm'
|
||||
|
||||
group :production, :staging do
|
||||
gem 'sd_notify' # For better Systemd process management. Used by Puma.
|
||||
end
|
||||
@@ -159,7 +157,6 @@ group :test, :development do
|
||||
gem 'rspec-retry', require: false
|
||||
gem 'rswag-specs'
|
||||
gem 'shoulda-matchers'
|
||||
gem 'stimulus_reflex_testing'
|
||||
gem 'timecop'
|
||||
end
|
||||
|
||||
|
||||
183
Gemfile.lock
183
Gemfile.lock
@@ -41,49 +41,49 @@ GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
Ascii85 (1.1.0)
|
||||
actioncable (7.0.7.2)
|
||||
actionpack (= 7.0.7.2)
|
||||
activesupport (= 7.0.7.2)
|
||||
actioncable (7.0.6)
|
||||
actionpack (= 7.0.6)
|
||||
activesupport (= 7.0.6)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailbox (7.0.7.2)
|
||||
actionpack (= 7.0.7.2)
|
||||
activejob (= 7.0.7.2)
|
||||
activerecord (= 7.0.7.2)
|
||||
activestorage (= 7.0.7.2)
|
||||
activesupport (= 7.0.7.2)
|
||||
actionmailbox (7.0.6)
|
||||
actionpack (= 7.0.6)
|
||||
activejob (= 7.0.6)
|
||||
activerecord (= 7.0.6)
|
||||
activestorage (= 7.0.6)
|
||||
activesupport (= 7.0.6)
|
||||
mail (>= 2.7.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
actionmailer (7.0.7.2)
|
||||
actionpack (= 7.0.7.2)
|
||||
actionview (= 7.0.7.2)
|
||||
activejob (= 7.0.7.2)
|
||||
activesupport (= 7.0.7.2)
|
||||
actionmailer (7.0.6)
|
||||
actionpack (= 7.0.6)
|
||||
actionview (= 7.0.6)
|
||||
activejob (= 7.0.6)
|
||||
activesupport (= 7.0.6)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (7.0.7.2)
|
||||
actionview (= 7.0.7.2)
|
||||
activesupport (= 7.0.7.2)
|
||||
actionpack (7.0.6)
|
||||
actionview (= 7.0.6)
|
||||
activesupport (= 7.0.6)
|
||||
rack (~> 2.0, >= 2.2.4)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||
actionpack-action_caching (1.2.2)
|
||||
actionpack (>= 4.0.0)
|
||||
actiontext (7.0.7.2)
|
||||
actionpack (= 7.0.7.2)
|
||||
activerecord (= 7.0.7.2)
|
||||
activestorage (= 7.0.7.2)
|
||||
activesupport (= 7.0.7.2)
|
||||
actiontext (7.0.6)
|
||||
actionpack (= 7.0.6)
|
||||
activerecord (= 7.0.6)
|
||||
activestorage (= 7.0.6)
|
||||
activesupport (= 7.0.6)
|
||||
globalid (>= 0.6.0)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (7.0.7.2)
|
||||
activesupport (= 7.0.7.2)
|
||||
actionview (7.0.6)
|
||||
activesupport (= 7.0.6)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
@@ -95,20 +95,20 @@ GEM
|
||||
activemodel (>= 5.2.0)
|
||||
activestorage (>= 5.2.0)
|
||||
activesupport (>= 5.2.0)
|
||||
activejob (7.0.7.2)
|
||||
activesupport (= 7.0.7.2)
|
||||
activejob (7.0.6)
|
||||
activesupport (= 7.0.6)
|
||||
globalid (>= 0.3.6)
|
||||
activemerchant (1.123.0)
|
||||
activesupport (>= 4.2)
|
||||
builder (>= 2.1.2, < 4.0.0)
|
||||
i18n (>= 0.6.9)
|
||||
nokogiri (~> 1.4)
|
||||
activemodel (7.0.7.2)
|
||||
activesupport (= 7.0.7.2)
|
||||
activerecord (7.0.7.2)
|
||||
activemodel (= 7.0.7.2)
|
||||
activesupport (= 7.0.7.2)
|
||||
activerecord-import (1.5.0)
|
||||
activemodel (7.0.6)
|
||||
activesupport (= 7.0.6)
|
||||
activerecord (7.0.6)
|
||||
activemodel (= 7.0.6)
|
||||
activesupport (= 7.0.6)
|
||||
activerecord-import (1.4.1)
|
||||
activerecord (>= 4.2)
|
||||
activerecord-postgresql-adapter (0.0.1)
|
||||
pg
|
||||
@@ -118,14 +118,14 @@ GEM
|
||||
multi_json (~> 1.11, >= 1.11.2)
|
||||
rack (>= 2.0.8, < 3)
|
||||
railties (>= 5.2.4.1)
|
||||
activestorage (7.0.7.2)
|
||||
actionpack (= 7.0.7.2)
|
||||
activejob (= 7.0.7.2)
|
||||
activerecord (= 7.0.7.2)
|
||||
activesupport (= 7.0.7.2)
|
||||
activestorage (7.0.6)
|
||||
actionpack (= 7.0.6)
|
||||
activejob (= 7.0.6)
|
||||
activerecord (= 7.0.6)
|
||||
activesupport (= 7.0.6)
|
||||
marcel (~> 1.0)
|
||||
mini_mime (>= 1.1.0)
|
||||
activesupport (7.0.7.2)
|
||||
activesupport (7.0.6)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
@@ -154,8 +154,8 @@ GEM
|
||||
awesome_nested_set (3.5.0)
|
||||
activerecord (>= 4.0.0, < 7.1)
|
||||
aws-eventstream (1.2.0)
|
||||
aws-partitions (1.809.0)
|
||||
aws-sdk-core (3.181.0)
|
||||
aws-partitions (1.792.0)
|
||||
aws-sdk-core (3.179.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
aws-partitions (~> 1, >= 1.651.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
@@ -163,13 +163,12 @@ GEM
|
||||
aws-sdk-kms (1.71.0)
|
||||
aws-sdk-core (~> 3, >= 3.177.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.133.0)
|
||||
aws-sdk-core (~> 3, >= 3.181.0)
|
||||
aws-sdk-s3 (1.132.0)
|
||||
aws-sdk-core (~> 3, >= 3.179.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.6)
|
||||
aws-sigv4 (1.6.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
base64 (0.1.1)
|
||||
bcrypt (3.1.18)
|
||||
bigdecimal (3.0.2)
|
||||
bindata (2.4.15)
|
||||
@@ -182,7 +181,7 @@ GEM
|
||||
bullet (7.0.7)
|
||||
activesupport (>= 3.0.0)
|
||||
uniform_notifier (~> 1.11)
|
||||
cable_ready (5.0.1)
|
||||
cable_ready (5.0.0.rc2)
|
||||
actionpack (>= 5.2)
|
||||
actionview (>= 5.2)
|
||||
activesupport (>= 5.2)
|
||||
@@ -232,8 +231,8 @@ GEM
|
||||
activerecord (>= 5.a)
|
||||
database_cleaner-core (~> 2.0.0)
|
||||
database_cleaner-core (2.0.1)
|
||||
datafoodconsortium-connector (1.0.0.pre.alpha.8)
|
||||
virtual_assembly-semantizer (~> 1.0, >= 1.0.5)
|
||||
datafoodconsortium-connector (1.0.0.pre.alpha.6)
|
||||
virtual_assembly-semantizer (~> 1.0, >= 1.0.4)
|
||||
date (3.3.3)
|
||||
debug (1.8.0)
|
||||
irb (>= 1.5.0)
|
||||
@@ -353,20 +352,20 @@ GEM
|
||||
jquery-ui-rails (4.2.1)
|
||||
railties (>= 3.2.16)
|
||||
json (2.6.3)
|
||||
json-canonicalization (0.3.2)
|
||||
json-canonicalization (0.3.1)
|
||||
json-jwt (1.16.3)
|
||||
activesupport (>= 4.2)
|
||||
aes_key_wrap
|
||||
bindata
|
||||
faraday (~> 2.0)
|
||||
faraday-follow_redirects
|
||||
json-ld (3.2.5)
|
||||
json-ld (3.2.3)
|
||||
htmlentities (~> 4.3)
|
||||
json-canonicalization (~> 0.3, >= 0.3.2)
|
||||
json-canonicalization (~> 0.3)
|
||||
link_header (~> 0.0, >= 0.0.8)
|
||||
multi_json (~> 1.15)
|
||||
rack (>= 2.2, < 4)
|
||||
rdf (~> 3.2, >= 3.2.10)
|
||||
rack (~> 2.2)
|
||||
rdf (~> 3.2, >= 3.2.9)
|
||||
json-schema (3.0.0)
|
||||
addressable (>= 2.8)
|
||||
json_spec (1.1.5)
|
||||
@@ -375,7 +374,7 @@ GEM
|
||||
jsonapi-serializer (2.2.0)
|
||||
activesupport (>= 4.2)
|
||||
jwt (2.7.1)
|
||||
knapsack_pro (5.4.1)
|
||||
knapsack_pro (5.3.4)
|
||||
rake
|
||||
language_server-protocol (3.17.0.3)
|
||||
launchy (2.5.0)
|
||||
@@ -397,16 +396,16 @@ GEM
|
||||
marcel (1.0.2)
|
||||
matrix (0.4.2)
|
||||
method_source (1.0.0)
|
||||
mime-types (3.5.1)
|
||||
mime-types (3.4.1)
|
||||
mime-types-data (~> 3.2015)
|
||||
mime-types-data (3.2023.0808)
|
||||
mime-types-data (3.2021.0225)
|
||||
mimemagic (0.4.3)
|
||||
nokogiri (~> 1)
|
||||
rake
|
||||
mini_magick (4.11.0)
|
||||
mini_mime (1.1.5)
|
||||
mini_mime (1.1.2)
|
||||
mini_portile2 (2.8.4)
|
||||
minitest (5.19.0)
|
||||
minitest (5.18.1)
|
||||
monetize (1.12.0)
|
||||
money (~> 6.12)
|
||||
money (6.16.0)
|
||||
@@ -414,7 +413,7 @@ GEM
|
||||
msgpack (1.7.1)
|
||||
multi_json (1.15.0)
|
||||
multi_xml (0.6.0)
|
||||
net-imap (0.3.7)
|
||||
net-imap (0.3.6)
|
||||
date
|
||||
net-protocol
|
||||
net-pop (0.1.2)
|
||||
@@ -423,9 +422,8 @@ GEM
|
||||
timeout
|
||||
net-smtp (0.3.3)
|
||||
net-protocol
|
||||
newrelic_rpm (9.4.2)
|
||||
nio4r (2.5.9)
|
||||
nokogiri (1.15.4)
|
||||
nokogiri (1.15.3)
|
||||
mini_portile2 (~> 2.8.2)
|
||||
racc (~> 1.4)
|
||||
oauth2 (1.4.11)
|
||||
@@ -484,14 +482,14 @@ GEM
|
||||
coderay (~> 1.1)
|
||||
method_source (~> 1.0)
|
||||
public_suffix (5.0.3)
|
||||
puma (6.3.1)
|
||||
puma (6.3.0)
|
||||
nio4r (~> 2.0)
|
||||
query_count (1.1.1)
|
||||
activerecord (>= 4.2)
|
||||
railties (>= 4.2)
|
||||
raabro (1.4.0)
|
||||
racc (1.7.1)
|
||||
rack (2.2.8)
|
||||
rack (2.2.7)
|
||||
rack-mini-profiler (2.3.4)
|
||||
rack (>= 1.2.0)
|
||||
rack-oauth2 (1.21.3)
|
||||
@@ -508,25 +506,25 @@ GEM
|
||||
rack-test (2.1.0)
|
||||
rack (>= 1.3)
|
||||
rack-timeout (0.6.3)
|
||||
rails (7.0.7.2)
|
||||
actioncable (= 7.0.7.2)
|
||||
actionmailbox (= 7.0.7.2)
|
||||
actionmailer (= 7.0.7.2)
|
||||
actionpack (= 7.0.7.2)
|
||||
actiontext (= 7.0.7.2)
|
||||
actionview (= 7.0.7.2)
|
||||
activejob (= 7.0.7.2)
|
||||
activemodel (= 7.0.7.2)
|
||||
activerecord (= 7.0.7.2)
|
||||
activestorage (= 7.0.7.2)
|
||||
activesupport (= 7.0.7.2)
|
||||
rails (7.0.6)
|
||||
actioncable (= 7.0.6)
|
||||
actionmailbox (= 7.0.6)
|
||||
actionmailer (= 7.0.6)
|
||||
actionpack (= 7.0.6)
|
||||
actiontext (= 7.0.6)
|
||||
actionview (= 7.0.6)
|
||||
activejob (= 7.0.6)
|
||||
activemodel (= 7.0.6)
|
||||
activerecord (= 7.0.6)
|
||||
activestorage (= 7.0.6)
|
||||
activesupport (= 7.0.6)
|
||||
bundler (>= 1.15.0)
|
||||
railties (= 7.0.7.2)
|
||||
railties (= 7.0.6)
|
||||
rails-controller-testing (1.0.5)
|
||||
actionpack (>= 5.0.1.rc1)
|
||||
actionview (>= 5.0.1.rc1)
|
||||
activesupport (>= 5.0.1.rc1)
|
||||
rails-dom-testing (2.2.0)
|
||||
rails-dom-testing (2.1.1)
|
||||
activesupport (>= 5.0.0)
|
||||
minitest
|
||||
nokogiri (>= 1.6)
|
||||
@@ -538,13 +536,13 @@ GEM
|
||||
rails-html-sanitizer (1.6.0)
|
||||
loofah (~> 2.21)
|
||||
nokogiri (~> 1.14)
|
||||
rails-i18n (7.0.8)
|
||||
rails-i18n (7.0.7)
|
||||
i18n (>= 0.7, < 2)
|
||||
railties (>= 6.0.0, < 8)
|
||||
rails_safe_tasks (1.0.0)
|
||||
railties (7.0.7.2)
|
||||
actionpack (= 7.0.7.2)
|
||||
activesupport (= 7.0.7.2)
|
||||
railties (7.0.6)
|
||||
actionpack (= 7.0.6)
|
||||
activesupport (= 7.0.6)
|
||||
method_source
|
||||
rake (>= 12.2)
|
||||
thor (~> 1.0)
|
||||
@@ -558,7 +556,7 @@ GEM
|
||||
rb-fsevent (0.11.2)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rdf (3.2.11)
|
||||
rdf (3.2.9)
|
||||
link_header (~> 0.0, >= 0.0.8)
|
||||
redcarpet (3.6.0)
|
||||
redis (4.8.1)
|
||||
@@ -618,8 +616,7 @@ GEM
|
||||
rswag-ui (2.10.1)
|
||||
actionpack (>= 3.1, < 7.1)
|
||||
railties (>= 3.1, < 7.1)
|
||||
rubocop (1.56.1)
|
||||
base64 (~> 0.1.1)
|
||||
rubocop (1.55.0)
|
||||
json (~> 2.3)
|
||||
language_server-protocol (>= 3.17.0)
|
||||
parallel (~> 1.10)
|
||||
@@ -695,20 +692,18 @@ GEM
|
||||
state_machines-activerecord (0.9.0)
|
||||
activerecord (>= 6.0)
|
||||
state_machines-activemodel (>= 0.9.0)
|
||||
stimulus_reflex (3.5.0.rc3)
|
||||
stimulus_reflex (3.5.0.rc2)
|
||||
actioncable (>= 5.2, < 8)
|
||||
actionpack (>= 5.2, < 8)
|
||||
actionview (>= 5.2, < 8)
|
||||
activesupport (>= 5.2, < 8)
|
||||
cable_ready (~> 5.0)
|
||||
cable_ready (>= 5.0.0.rc2)
|
||||
nokogiri (~> 1.0)
|
||||
rack (>= 2, < 4)
|
||||
railties (>= 5.2, < 8)
|
||||
redis (>= 4.0, < 6.0)
|
||||
stimulus_reflex_testing (0.3.0)
|
||||
stimulus_reflex (>= 3.3.0)
|
||||
stringex (2.8.6)
|
||||
stripe (9.0.0)
|
||||
stripe (8.6.0)
|
||||
swd (1.3.0)
|
||||
activesupport (>= 3)
|
||||
attr_required (>= 0.0.5)
|
||||
@@ -717,7 +712,7 @@ GEM
|
||||
thor (1.2.2)
|
||||
thread-local (1.1.0)
|
||||
tilt (2.1.0)
|
||||
timecop (0.9.8)
|
||||
timecop (0.9.6)
|
||||
timeout (0.4.0)
|
||||
ttfunk (1.7.0)
|
||||
tzinfo (2.0.6)
|
||||
@@ -742,7 +737,7 @@ GEM
|
||||
rails (>= 5.2, < 8.0)
|
||||
stimulus_reflex (>= 3.5.0.pre2)
|
||||
view_component (>= 2.28.0)
|
||||
virtual_assembly-semantizer (1.0.5)
|
||||
virtual_assembly-semantizer (1.0.4)
|
||||
json-ld (~> 3.2, >= 3.2.3)
|
||||
warden (1.2.9)
|
||||
rack (>= 2.0.9)
|
||||
@@ -764,7 +759,7 @@ GEM
|
||||
railties (>= 5.2)
|
||||
semantic_range (>= 2.3.0)
|
||||
webrick (1.7.0)
|
||||
websocket-driver (0.7.6)
|
||||
websocket-driver (0.7.5)
|
||||
websocket-extensions (>= 0.1.0)
|
||||
websocket-extensions (0.1.5)
|
||||
whenever (1.0.0)
|
||||
@@ -775,7 +770,7 @@ GEM
|
||||
xml-simple (1.1.8)
|
||||
xpath (3.2.0)
|
||||
nokogiri (~> 1.8)
|
||||
zeitwerk (2.6.11)
|
||||
zeitwerk (2.6.8)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
@@ -801,7 +796,7 @@ DEPENDENCIES
|
||||
bootsnap
|
||||
bugsnag
|
||||
bullet
|
||||
cable_ready (= 5.0.1)
|
||||
cable_ready (= 5.0.0.rc2)
|
||||
cancancan (~> 1.15.0)
|
||||
capybara
|
||||
catalog!
|
||||
@@ -852,7 +847,6 @@ DEPENDENCIES
|
||||
mimemagic (> 0.3.5)
|
||||
mini_portile2 (~> 2.8)
|
||||
monetize (~> 1.11)
|
||||
newrelic_rpm
|
||||
oauth2 (~> 1.4.7)
|
||||
omniauth-rails_csrf_protection
|
||||
omniauth_openid_connect
|
||||
@@ -900,8 +894,7 @@ DEPENDENCIES
|
||||
spring
|
||||
spring-commands-rspec
|
||||
state_machines-activerecord
|
||||
stimulus_reflex (= 3.5.0.rc3)
|
||||
stimulus_reflex_testing
|
||||
stimulus_reflex (= 3.5.0.rc2)
|
||||
stringex (~> 2.8.5)
|
||||
stripe
|
||||
timecop
|
||||
|
||||
@@ -135,7 +135,6 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
display_name: null
|
||||
on_hand: null
|
||||
price: null
|
||||
tax_category_id: null
|
||||
DisplayProperties.setShowVariants product.id, true
|
||||
|
||||
|
||||
@@ -347,6 +346,9 @@ filterSubmitProducts = (productsToFilter) ->
|
||||
if product.hasOwnProperty("category_id")
|
||||
filteredProduct.primary_taxon_id = product.category_id
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("tax_category_id")
|
||||
filteredProduct.tax_category_id = product.tax_category_id
|
||||
hasUpdatableProperty = true
|
||||
if product.hasOwnProperty("inherits_properties")
|
||||
filteredProduct.inherits_properties = product.inherits_properties
|
||||
hasUpdatableProperty = true
|
||||
@@ -387,9 +389,6 @@ filterSubmitVariant = (variant) ->
|
||||
if variant.hasOwnProperty("display_name")
|
||||
filteredVariant.display_name = variant.display_name
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("tax_category_id")
|
||||
filteredVariant.tax_category_id = variant.tax_category_id
|
||||
hasUpdatableProperty = true
|
||||
if variant.hasOwnProperty("display_as")
|
||||
filteredVariant.display_as = variant.display_as
|
||||
hasUpdatableProperty = true
|
||||
|
||||
@@ -11,8 +11,14 @@ angular.module("admin.indexUtils").directive "objForUpdate", (switchClass, pendi
|
||||
pendingChanges.remove(scope.object().id, scope.attr)
|
||||
scope.clear()
|
||||
else
|
||||
change =
|
||||
object: scope.object()
|
||||
type: scope.type
|
||||
attr: scope.attr
|
||||
value: if value? then value else ""
|
||||
scope: scope
|
||||
scope.pending()
|
||||
addPendingChange(scope.attr, value ? "")
|
||||
pendingChanges.add(scope.object().id, scope.attr, change)
|
||||
|
||||
scope.reset = (value) ->
|
||||
scope.savedValue = value
|
||||
@@ -28,33 +34,3 @@ angular.module("admin.indexUtils").directive "objForUpdate", (switchClass, pendi
|
||||
|
||||
scope.clear = ->
|
||||
switchClass( element, "", ["update-pending", "update-error", "update-success"], false )
|
||||
|
||||
# When a list of customer is filtered and we removed the "filtered value" from a customer, we
|
||||
# want to make sure the customer is updated. IE. filtering by tag, and removing said tag.
|
||||
# Deleting the "filtered value" from a customer will remove the customer entry, thus
|
||||
# removing "objForUpdate" directive from the active scope. That means $watch won't pick up
|
||||
# the attribute changed.
|
||||
# To ensure the customer is still updated, we check on the $destroy event to see if
|
||||
# the attribute has changed, if so we queue up the change.
|
||||
scope.$on '$destroy', (value) ->
|
||||
# No update
|
||||
return if scope.object()[scope.attr] is scope.savedValue
|
||||
|
||||
# For some reason the code attribute is removed from the object when cleared, so we add
|
||||
# an emptyvalue so it gets updated properly
|
||||
if scope.attr is "code" and scope.object()[scope.attr] is undefined
|
||||
scope.object()["code"] = ""
|
||||
|
||||
# Queuing up change
|
||||
addPendingChange(scope.attr, scope.object()[scope.attr])
|
||||
|
||||
# private
|
||||
|
||||
addPendingChange = (attr, value) ->
|
||||
change =
|
||||
object: scope.object()
|
||||
type: scope.type
|
||||
attr: attr
|
||||
value: value
|
||||
scope: scope
|
||||
pendingChanges.add(scope.object().id, attr, change)
|
||||
|
||||
@@ -9,9 +9,10 @@ angular.module('Darkswarm').controller "RegistrationFormCtrl", ($scope, Registra
|
||||
$scope.create = (form) ->
|
||||
if ($scope.valid(form))
|
||||
$scope.disableButton()
|
||||
EnterpriseRegistrationService.create($scope.enableButton).then(() ->
|
||||
EnterpriseRegistrationService.create().then(() ->
|
||||
$scope.enableButton()
|
||||
)
|
||||
end
|
||||
|
||||
$scope.update = (nextStep, form) ->
|
||||
EnterpriseRegistrationService.update(nextStep) if $scope.valid(form)
|
||||
|
||||
15
app/components/pagination_component.rb
Normal file
15
app/components/pagination_component.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class PaginationComponent < ViewComponentReflex::Component
|
||||
def initialize(pagy:, data:)
|
||||
super
|
||||
@count = pagy.count
|
||||
@page = pagy.page
|
||||
@per_page = pagy.items
|
||||
@pages = pagy.pages
|
||||
@next = pagy.next
|
||||
@prev = pagy.prev
|
||||
@data = data
|
||||
@series = pagy.series
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,16 @@
|
||||
= component_controller do
|
||||
%nav{"aria-label": "pagination"}
|
||||
.pagination
|
||||
.pagination-prev{data: @prev.nil? ? nil : @data, "data-page": @prev, class: "#{'inactive' if @prev.nil?}"}
|
||||
= I18n.t "components.pagination.previous"
|
||||
.pagination-pages
|
||||
- @series.each do |page|
|
||||
- if page == :gap
|
||||
.pagination-gap
|
||||
…
|
||||
- else
|
||||
.pagination-page{data: @data, "data-page": page, class: "#{'active' if page.to_i == @page}"}
|
||||
= page
|
||||
.pagination-next{data: @next.nil? ? nil : @data, "data-page": @next, class: "#{'inactive' if @next.nil?}"}
|
||||
= I18n.t "components.pagination.next"
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
nav {
|
||||
.pagination {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
font-size: 14px;
|
||||
|
||||
.pagination-prev, .pagination-next {
|
||||
cursor: pointer;
|
||||
|
||||
&:after, &:before {
|
||||
font-size: 2em;
|
||||
position: relative;
|
||||
top: 3px;
|
||||
}
|
||||
|
||||
&.inactive {
|
||||
cursor: default;
|
||||
color: $disabled-dark;
|
||||
}
|
||||
}
|
||||
|
||||
.pagination-prev {
|
||||
margin-left: 10px;
|
||||
|
||||
&:before {
|
||||
content: "‹";
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.pagination-next {
|
||||
margin-right: 10px;
|
||||
|
||||
&:after {
|
||||
content: "›";
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.pagination-pages {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
|
||||
.pagination-gap, .pagination-page {
|
||||
padding: 0 0.5rem;
|
||||
margin-left: 10px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.pagination-gap {
|
||||
color: $disabled-dark;
|
||||
}
|
||||
|
||||
.pagination-page {
|
||||
color: $color-4;
|
||||
cursor: pointer;
|
||||
&.active {
|
||||
border-top: 3px solid $spree-blue;
|
||||
color: $spree-blue;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
57
app/components/product_component.rb
Normal file
57
app/components/product_component.rb
Normal file
@@ -0,0 +1,57 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ProductComponent < ViewComponentReflex::Component
|
||||
DATETIME_FORMAT = '%F %T'
|
||||
|
||||
def initialize(product:, columns:)
|
||||
super
|
||||
@product = product
|
||||
@image = @product.image if product.image.present?
|
||||
@columns = columns.map do |c|
|
||||
{
|
||||
id: c[:value],
|
||||
value: column_value(c[:value])
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
# This must be define when using ProductComponent.with_collection()
|
||||
def collection_key
|
||||
@product.id
|
||||
end
|
||||
|
||||
# rubocop:disable Metrics/CyclomaticComplexity
|
||||
def column_value(column)
|
||||
case column
|
||||
when 'name'
|
||||
@product.name
|
||||
when 'price'
|
||||
@product.price
|
||||
when 'unit'
|
||||
"#{@product.variants.first.unit_value} #{@product.variant_unit}"
|
||||
when 'producer'
|
||||
@product.supplier.name
|
||||
when 'category'
|
||||
@product.taxons.map(&:name).join(', ')
|
||||
when 'sku'
|
||||
@product.sku
|
||||
when 'on_hand'
|
||||
@product.on_hand || 0
|
||||
when 'on_demand'
|
||||
@product.on_demand
|
||||
when 'tax_category'
|
||||
@product.tax_category.name
|
||||
when 'inherits_properties'
|
||||
@product.inherits_properties
|
||||
when 'import_date'
|
||||
format_date(@product.import_date)
|
||||
end
|
||||
end
|
||||
# rubocop:enable Metrics/CyclomaticComplexity
|
||||
|
||||
private
|
||||
|
||||
def format_date(date)
|
||||
date&.strftime(DATETIME_FORMAT) || ''
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,6 @@
|
||||
%tr
|
||||
- @columns.each do |column|
|
||||
%td.products_column{class: column[:id]}
|
||||
- if column[:id] == "name" && @image&.attachment.present?
|
||||
= image_tag @image.url(:mini)
|
||||
= column[:value]
|
||||
179
app/components/products_table_component.rb
Normal file
179
app/components/products_table_component.rb
Normal file
@@ -0,0 +1,179 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ProductsTableComponent < ViewComponentReflex::Component
|
||||
include Pagy::Backend
|
||||
|
||||
SORTABLE_COLUMNS = ['name', 'import_date'].freeze
|
||||
SELECTABLE_COLUMNS = [
|
||||
{ label: I18n.t("admin.products_page.columns_selector.price"), value: "price" },
|
||||
{ label: I18n.t("admin.products_page.columns_selector.unit"), value: "unit" },
|
||||
{ label: I18n.t("admin.products_page.columns_selector.producer"), value: "producer" },
|
||||
{ label: I18n.t("admin.products_page.columns_selector.category"), value: "category" },
|
||||
{ label: I18n.t("admin.products_page.columns_selector.sku"), value: "sku" },
|
||||
{ label: I18n.t("admin.products_page.columns_selector.on_hand"), value: "on_hand" },
|
||||
{ label: I18n.t("admin.products_page.columns_selector.on_demand"), value: "on_demand" },
|
||||
{ label: I18n.t("admin.products_page.columns_selector.tax_category"), value: "tax_category" },
|
||||
{
|
||||
label: I18n.t("admin.products_page.columns_selector.inherits_properties"),
|
||||
value: "inherits_properties"
|
||||
},
|
||||
{ label: I18n.t("admin.products_page.columns_selector.import_date"), value: "import_date" }
|
||||
].sort do |a, b|
|
||||
a[:label] <=> b[:label]
|
||||
end.freeze
|
||||
|
||||
PER_PAGE_VALUE = [10, 25, 50, 100].freeze
|
||||
PER_PAGE = PER_PAGE_VALUE.map { |value| { label: value, value: value } }
|
||||
NAME_COLUMN = {
|
||||
label: I18n.t("admin.products_page.columns.name"), value: "name", sortable: true
|
||||
}.freeze
|
||||
|
||||
def initialize(user:)
|
||||
super
|
||||
@user = user
|
||||
@selectable_columns = SELECTABLE_COLUMNS
|
||||
@columns_selected = ['unit', 'price', 'on_hand', 'category', 'import_date']
|
||||
@per_page = PER_PAGE
|
||||
@per_page_selected = [10]
|
||||
@categories = [{ label: "All", value: "all" }] +
|
||||
Spree::Taxon.order(:name)
|
||||
.map { |taxon| { label: taxon.name, value: taxon.id.to_s } }
|
||||
@categories_selected = ["all"]
|
||||
@producers = [{ label: "All", value: "all" }] +
|
||||
OpenFoodNetwork::Permissions.new(@user)
|
||||
.managed_product_enterprises.is_primary_producer.by_name
|
||||
.map { |producer| { label: producer.name, value: producer.id.to_s } }
|
||||
@producers_selected = ["all"]
|
||||
@page = 1
|
||||
@sort = { column: "name", direction: "asc" }
|
||||
@search_term = ""
|
||||
end
|
||||
|
||||
# any change on a "reflex_data_attributes" (defined in the template) will trigger a re render
|
||||
def before_render
|
||||
fetch_products
|
||||
refresh_columns
|
||||
end
|
||||
|
||||
# Element refers to the component the data is set on
|
||||
def search_term
|
||||
# Element is SearchInputComponent
|
||||
@search_term = element.dataset['value']
|
||||
end
|
||||
|
||||
def toggle_column
|
||||
# Element is SelectorComponent
|
||||
column = element.dataset['value']
|
||||
@columns_selected = if @columns_selected.include?(column)
|
||||
@columns_selected - [column]
|
||||
else
|
||||
@columns_selected + [column]
|
||||
end
|
||||
end
|
||||
|
||||
def click_sort
|
||||
# Element is TableHeaderComponent
|
||||
@sort = {
|
||||
column: element.dataset['sort-value'],
|
||||
direction: element.dataset['sort-direction'] == "asc" ? "desc" : "asc"
|
||||
}
|
||||
end
|
||||
|
||||
def toggle_per_page
|
||||
# Element is SelectorComponent
|
||||
selected = element.dataset['value'].to_i
|
||||
@per_page_selected = [selected] if PER_PAGE_VALUE.include?(selected)
|
||||
end
|
||||
|
||||
def toggle_category
|
||||
# Element is SelectorWithFilterComponent
|
||||
category_clicked = element.dataset['value']
|
||||
@categories_selected = toggle_selector_with_filter(category_clicked, @categories_selected)
|
||||
end
|
||||
|
||||
def toggle_producer
|
||||
# Element is SelectorWithFilterComponent
|
||||
producer_clicked = element.dataset['value']
|
||||
@producers_selected = toggle_selector_with_filter(producer_clicked, @producers_selected)
|
||||
end
|
||||
|
||||
def change_page
|
||||
# Element is PaginationComponent
|
||||
page = element.dataset['page'].to_i
|
||||
@page = page if page > 0
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def refresh_columns
|
||||
@columns = @columns_selected.map do |column|
|
||||
{
|
||||
label: I18n.t("admin.products_page.columns.#{column}"),
|
||||
value: column,
|
||||
sortable: SORTABLE_COLUMNS.include?(column)
|
||||
}
|
||||
end.sort! { |a, b| a[:label] <=> b[:label] }
|
||||
@columns.unshift(NAME_COLUMN)
|
||||
end
|
||||
|
||||
def toggle_selector_with_filter(clicked, selected)
|
||||
selected = if selected.include?(clicked)
|
||||
selected - [clicked]
|
||||
else
|
||||
selected + [clicked]
|
||||
end
|
||||
|
||||
if clicked == "all" || selected.empty?
|
||||
selected = ["all"]
|
||||
elsif selected.include?("all") && selected.length > 1
|
||||
selected -= ["all"]
|
||||
end
|
||||
selected
|
||||
end
|
||||
|
||||
def fetch_products
|
||||
product_query = OpenFoodNetwork::Permissions.new(@user).editable_products.merge(product_scope)
|
||||
@products = product_query.ransack(ransack_query).result
|
||||
@pagy, @products = pagy(@products, items: @per_page_selected.first, page: @page)
|
||||
end
|
||||
|
||||
def product_scope
|
||||
scope = if @user.has_spree_role?("admin") || @user.enterprises.present?
|
||||
Spree::Product
|
||||
else
|
||||
Spree::Product.active
|
||||
end
|
||||
|
||||
scope.includes(product_query_includes)
|
||||
end
|
||||
|
||||
def ransack_query
|
||||
query = { s: "#{@sort[:column]} #{@sort[:direction]}" }
|
||||
|
||||
query = if @producers_selected.include?("all")
|
||||
query.merge({ supplier_id_eq: "" })
|
||||
else
|
||||
query.merge({ supplier_id_in: @producers_selected })
|
||||
end
|
||||
|
||||
query = query.merge({ name_cont: @search_term }) if @search_term.present?
|
||||
|
||||
if @categories_selected.include?("all")
|
||||
query.merge({ primary_taxon_id_eq: "" })
|
||||
else
|
||||
query.merge({ primary_taxon_id_in: @categories_selected })
|
||||
end
|
||||
end
|
||||
|
||||
def product_query_includes
|
||||
[
|
||||
:image,
|
||||
variants: [
|
||||
:default_price,
|
||||
:stock_locations,
|
||||
:stock_items,
|
||||
:variant_overrides
|
||||
]
|
||||
]
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,21 @@
|
||||
= component_controller(class: "products-table") do
|
||||
.products-table-form
|
||||
.products-table-form_filter_results
|
||||
= render(SearchInputComponent.new(value: @search_term, data: reflex_data_attributes(:search_term)))
|
||||
.products-table-form_categories_selector
|
||||
= render(SelectorWithFilterComponent.new(title: t("admin.products_page.filters.categories.title"), selected: @categories_selected, items: @categories, data: reflex_data_attributes(:toggle_category), selected_items_i18n_key: "admin.products_page.filters.categories.selected_categories"))
|
||||
.products-table-form_producers_selector
|
||||
= render(SelectorWithFilterComponent.new(title: t("admin.products_page.filters.producers.title"), selected: @producers_selected, items: @producers, data: reflex_data_attributes(:toggle_producer), selected_items_i18n_key: "admin.products_page.filters.producers.selected_producers"))
|
||||
.products-table-form_per-page_selector
|
||||
= render(SelectorComponent.new(title: t('admin.products_page.filters.per_page', count: @per_page_selected[0]), selected: @per_page_selected, items: @per_page, data: reflex_data_attributes(:toggle_per_page)))
|
||||
.products-table-form_columns_selector
|
||||
= render(SelectorComponent.new(title: t("admin.products_page.filters.columns"), selected: @columns_selected, items: @selectable_columns, data: reflex_data_attributes(:toggle_column)))
|
||||
|
||||
.products-table_table
|
||||
%table
|
||||
= render(TableHeaderComponent.new(columns: @columns, sort: @sort, data: reflex_data_attributes(:click_sort)))
|
||||
%tbody
|
||||
= render(ProductComponent.with_collection(@products, columns: @columns))
|
||||
|
||||
.products-table-form_pagination
|
||||
= render(PaginationComponent.new(pagy: @pagy, data: reflex_data_attributes(:change_page)))
|
||||
@@ -0,0 +1,47 @@
|
||||
.products-table {
|
||||
.products-table-form {
|
||||
display: grid;
|
||||
grid-template-columns: repeat( auto-fit, minmax(250px, 1fr) );
|
||||
grid-gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.products-table_table {
|
||||
box-shadow: 0 10px 10px -1px rgb(0 0 0 / 10%);
|
||||
}
|
||||
|
||||
.products-table-form_pagination {
|
||||
position: relative;
|
||||
top: -15px;
|
||||
|
||||
nav, .pagination {
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.products-table.loading {
|
||||
.products-table-form_pagination, .products-table_table {
|
||||
position: relative;
|
||||
|
||||
&:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
}
|
||||
|
||||
.products-table_table {
|
||||
&:before {
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 50px 50px;
|
||||
background-image: url("../images/spinning-circles.svg");
|
||||
}
|
||||
}
|
||||
}
|
||||
9
app/components/search_input_component.rb
Normal file
9
app/components/search_input_component.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class SearchInputComponent < ViewComponentReflex::Component
|
||||
def initialize(value: nil, data: {})
|
||||
super
|
||||
@value = value
|
||||
@data = data
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
= component_controller do
|
||||
%div.search-input
|
||||
%input{type: 'text', placeholder: t("components.search_input.placeholder"), id: 'search_query', data: {action: 'debounced:input->search-input#search'}, value: @value}
|
||||
.search-button{data: @data}
|
||||
%i.fa.fa-search
|
||||
@@ -0,0 +1,23 @@
|
||||
.search-input {
|
||||
border: 1px solid $disabled-light;
|
||||
height: 3em;
|
||||
display: flex;
|
||||
line-height: 3em;
|
||||
align-items: center;
|
||||
|
||||
input {
|
||||
border: none;
|
||||
height: 3em;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.search-button {
|
||||
padding-right: 10px;
|
||||
padding-left: 5px;
|
||||
cursor: pointer;
|
||||
color: $color-4;
|
||||
}
|
||||
|
||||
}
|
||||
17
app/components/selector_component.rb
Normal file
17
app/components/selector_component.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class SelectorComponent < ViewComponentReflex::Component
|
||||
def initialize(title:, selected:, items:, data: {})
|
||||
super
|
||||
@title = title
|
||||
@items = items.map do |item|
|
||||
{
|
||||
label: item[:label],
|
||||
value: item[:value],
|
||||
selected: selected.include?(item[:value])
|
||||
}
|
||||
end
|
||||
@selected = selected
|
||||
@data = data
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
= component_controller do
|
||||
.selector.selector-close
|
||||
.selector-main{ data: { action: "click->selector#toggle" } }
|
||||
.selector-main-title
|
||||
= @title
|
||||
.selector-arrow
|
||||
.selector-wrapper
|
||||
.selector-items
|
||||
- @items.each do |item|
|
||||
.selector-item{ class: ("selected" if item[:selected]), data: @data, "data-value": item[:value] }
|
||||
= item[:label]
|
||||
86
app/components/selector_component/selector_component.scss
Normal file
86
app/components/selector_component/selector_component.scss
Normal file
@@ -0,0 +1,86 @@
|
||||
.selector {
|
||||
position: relative;
|
||||
|
||||
.selector-main {
|
||||
border: 1px solid $disabled-light;
|
||||
height: 3em;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
.selector-main-title {
|
||||
line-height: 3em;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
.selector-arrow {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
height: 3em;
|
||||
width: 1.5em;
|
||||
top: -1px;
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 5px;
|
||||
margin-top: -5px;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-left: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
border-top: 5px solid $disabled-light;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.selector-wrapper {
|
||||
position: absolute;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
z-index: 1;
|
||||
background-color: white;
|
||||
margin-top: -1px;
|
||||
border: 1px solid $disabled-light;
|
||||
|
||||
.selector-items {
|
||||
overflow-y: auto;
|
||||
min-height: 6em;
|
||||
|
||||
.selector-item {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
border-bottom: 1px solid $disabled-light;
|
||||
position: relative;
|
||||
height: 3em;
|
||||
line-height: 3em;
|
||||
|
||||
&:hover {
|
||||
background-color: #eee;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
&:after {
|
||||
content: "✓";
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
&.selector-close {
|
||||
.selector-wrapper {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
11
app/components/selector_with_filter_component.rb
Normal file
11
app/components/selector_with_filter_component.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class SelectorWithFilterComponent < SelectorComponent
|
||||
def initialize(title:, selected:, items:, data: {},
|
||||
selected_items_i18n_key: 'components.selector_with_filter.selected_items')
|
||||
super(title: title, selected: selected, items: items, data: data)
|
||||
@selected_items = items.select { |item| @selected.include?(item[:value]) }
|
||||
@selected_items_i18n_key = selected_items_i18n_key
|
||||
@items = items
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,22 @@
|
||||
= component_controller do
|
||||
.super-selector.selector.selector-close
|
||||
.selector-main{ data: { action: "click->selector-with-filter#toggle" } }
|
||||
.super-selector-label
|
||||
= @title
|
||||
.super-selector-selected-items
|
||||
- case @selected_items.length
|
||||
- when 1, 2
|
||||
- @selected_items.each do |item|
|
||||
.super-selector-selected-item
|
||||
= item[:label]
|
||||
- else
|
||||
.super-selector-selected-item
|
||||
= t(@selected_items_i18n_key, count: @selected_items.length)
|
||||
.selector-arrow
|
||||
.selector-wrapper
|
||||
.super-selector-search
|
||||
%input{type: "text", placeholder: t("components.selector_with_filter.search_placeholder"), data: { action: "debounced:input->selector-with-filter#filter" } }
|
||||
.selector-items
|
||||
- @items.each do |item|
|
||||
.selector-item{ class: ("selected" if item[:selected]), data: @data.merge({ "selector-with-filter-target": "items" }), "data-value": item[:value] }
|
||||
= item[:label]
|
||||
@@ -0,0 +1,51 @@
|
||||
|
||||
.super-selector {
|
||||
position: relative;
|
||||
|
||||
.selector-main {
|
||||
.super-selector-label {
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
margin-left: 10px;
|
||||
position: absolute;
|
||||
top: -1em;
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
|
||||
.super-selector-selected-items {
|
||||
margin-left: 5px;
|
||||
margin-right: 2em;
|
||||
margin-top: 7px;
|
||||
display: flex;
|
||||
|
||||
.super-selector-selected-item {
|
||||
border: 1px solid $pale-blue;
|
||||
background-color: $spree-light-blue;
|
||||
border-radius: 20px;
|
||||
height: 2em;
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
display: inline-block;
|
||||
margin-right: 5px;
|
||||
padding-top: 2px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.selector-wrapper {
|
||||
.super-selector-search {
|
||||
border-bottom: 1px solid $disabled-light;
|
||||
padding: 10px 5px;
|
||||
|
||||
input {
|
||||
border: 1px solid $disabled-light;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
10
app/components/table_header_component.rb
Normal file
10
app/components/table_header_component.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class TableHeaderComponent < ViewComponentReflex::Component
|
||||
def initialize(columns:, sort:, data: {})
|
||||
super
|
||||
@columns = columns
|
||||
@sort = sort
|
||||
@data = data
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
= component_controller do
|
||||
%thead.table-header
|
||||
%tr
|
||||
- @columns.each do |column|
|
||||
%th{class: (column[:sortable] ? "th-sortable " : "" ) + (@sort[:column] == column[:value] ? " th-sorted-#{@sort[:direction]}" : ""), data: (@data if column[:sortable] == true), "data-sort-value": column[:value], "data-sort-direction": @sort[:direction]}
|
||||
= column[:label]
|
||||
@@ -0,0 +1,23 @@
|
||||
thead.table-header {
|
||||
th {
|
||||
&.th-sortable {
|
||||
cursor: pointer;
|
||||
}
|
||||
&.th-sorted-asc, &.th-sorted-desc {
|
||||
&:after {
|
||||
display: inline-block;
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
&.th-sorted-asc {
|
||||
&:after {
|
||||
content: "⇧";
|
||||
}
|
||||
}
|
||||
&.th-sorted-desc {
|
||||
&:after {
|
||||
content: "⇩";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
7
app/controllers/admin/products_controller.rb
Normal file
7
app/controllers/admin/products_controller.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Admin
|
||||
class ProductsController < Spree::Admin::BaseController
|
||||
def index; end
|
||||
end
|
||||
end
|
||||
@@ -13,7 +13,7 @@ module Admin
|
||||
if @proxy_order.cancel
|
||||
render_as_json @proxy_order
|
||||
else
|
||||
render json: { errors: [t('.could_not_cancel_the_order')] },
|
||||
render json: { errors: [t('admin.proxy_orders.cancel.could_not_cancel_the_order')] },
|
||||
status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
@@ -22,7 +22,7 @@ module Admin
|
||||
if @proxy_order.resume
|
||||
render_as_json @proxy_order
|
||||
else
|
||||
render json: { errors: [t('.could_not_resume_the_order')] },
|
||||
render json: { errors: [t('admin.proxy_orders.resume.could_not_resume_the_order')] },
|
||||
status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
@@ -55,15 +55,6 @@ module Admin
|
||||
@report_title = report_title
|
||||
@rendering_options = rendering_options
|
||||
@data = Reporting::FrontendData.new(spree_current_user)
|
||||
|
||||
variant_id_in = params[:variant_id_in]&.compact_blank
|
||||
load_selected_variant if variant_id_in.present?
|
||||
end
|
||||
|
||||
# Orders and Fulfillment Reports include a per product filter, load any selected product
|
||||
def load_selected_variant
|
||||
variant = Spree::Variant.find(params[:variant_id_in][0])
|
||||
@variant_serialized = Api::Admin::VariantSerializer.new(variant)
|
||||
end
|
||||
|
||||
def render_data?
|
||||
|
||||
@@ -24,10 +24,9 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
@object.attributes = permitted_resource_params
|
||||
if @object.save
|
||||
flash[:success] = flash_message_for(@object, :successfully_created)
|
||||
def update
|
||||
if @object.update(permitted_resource_params)
|
||||
flash[:success] = flash_message_for(@object, :successfully_updated)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to location_after_save }
|
||||
format.js { render layout: false }
|
||||
@@ -37,9 +36,10 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
if @object.update(permitted_resource_params)
|
||||
flash[:success] = flash_message_for(@object, :successfully_updated)
|
||||
def create
|
||||
@object.attributes = permitted_resource_params
|
||||
if @object.save
|
||||
flash[:success] = flash_message_for(@object, :successfully_created)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to location_after_save }
|
||||
format.js { render layout: false }
|
||||
|
||||
@@ -8,13 +8,15 @@ module Admin
|
||||
include PaperTrailLogging
|
||||
|
||||
before_action :adapt_params, only: [:update]
|
||||
before_action :editable_order_cycle_ids_for_create, only: [:create]
|
||||
before_action :editable_order_cycle_ids_for_update, only: [:update]
|
||||
before_action :check_dependent_subscriptions, only: [:destroy]
|
||||
|
||||
after_action :sync_subscriptions_for_update, only: :update
|
||||
|
||||
respond_to :json
|
||||
|
||||
OVERRIDE_RESPONSE = { json: {
|
||||
respond_override create: { json: {
|
||||
success: lambda {
|
||||
render_as_json @schedule,
|
||||
editable_schedule_ids: permissions.editable_schedules.pluck(:id)
|
||||
@@ -23,10 +25,17 @@ module Admin
|
||||
render json: { errors: @schedule.errors.full_messages },
|
||||
status: :unprocessable_entity
|
||||
}
|
||||
} }.freeze
|
||||
|
||||
respond_override create: OVERRIDE_RESPONSE
|
||||
respond_override update: OVERRIDE_RESPONSE
|
||||
} }
|
||||
respond_override update: { json: {
|
||||
success: lambda {
|
||||
render_as_json @schedule,
|
||||
editable_schedule_ids: permissions.editable_schedules.pluck(:id)
|
||||
},
|
||||
failure: lambda {
|
||||
render json: { errors: @schedule.errors.full_messages },
|
||||
status: :unprocessable_entity
|
||||
}
|
||||
} }
|
||||
|
||||
def index
|
||||
respond_to do |format|
|
||||
@@ -41,23 +50,22 @@ module Admin
|
||||
end
|
||||
|
||||
def create
|
||||
@schedule_form = ScheduleForm.new(params, spree_current_user, @schedule)
|
||||
return respond_with(@schedule) if params[:order_cycle_ids].blank?
|
||||
|
||||
@schedule.attributes = permitted_resource_params
|
||||
|
||||
if @schedule.save
|
||||
@schedule.order_cycle_ids = params[:order_cycle_ids]
|
||||
@schedule.save!
|
||||
|
||||
if @schedule_form.save
|
||||
flash[:success] = flash_message_for(@schedule, :successfully_created)
|
||||
@existing_order_cycle_ids = []
|
||||
sync_subscriptions_for_create
|
||||
|
||||
flash[:success] = flash_message_for(@schedule, :successfully_created)
|
||||
end
|
||||
|
||||
respond_with(@schedule)
|
||||
end
|
||||
|
||||
def update
|
||||
@existing_order_cycle_ids = @schedule.order_cycle_ids
|
||||
@object = ScheduleForm.new(params, spree_current_user, @schedule)
|
||||
super
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def collection
|
||||
@@ -88,6 +96,37 @@ module Admin
|
||||
params[:schedule][:order_cycle_ids] = params[:order_cycle_ids]
|
||||
end
|
||||
|
||||
def editable_order_cycle_ids_for_create
|
||||
return unless params[:order_cycle_ids]
|
||||
|
||||
@existing_order_cycle_ids = []
|
||||
result = editable_order_cycles(params[:order_cycle_ids])
|
||||
|
||||
params[:order_cycle_ids] = result
|
||||
end
|
||||
|
||||
def editable_order_cycle_ids_for_update
|
||||
return unless params[:schedule][:order_cycle_ids]
|
||||
|
||||
@existing_order_cycle_ids = @schedule.order_cycle_ids
|
||||
result = editable_order_cycles(params[:schedule][:order_cycle_ids])
|
||||
|
||||
params[:schedule][:order_cycle_ids] = result
|
||||
@schedule.order_cycle_ids = result
|
||||
end
|
||||
|
||||
def editable_order_cycles(requested)
|
||||
permitted = OrderCycle
|
||||
.where(id: params[:order_cycle_ids] | @existing_order_cycle_ids)
|
||||
.merge(OrderCycle.managed_by(spree_current_user))
|
||||
.pluck(:id)
|
||||
result = @existing_order_cycle_ids
|
||||
result |= (requested & permitted) # add any requested & permitted ids
|
||||
# remove any existing and permitted ids that were not specifically requested
|
||||
result -= ((result & permitted) - requested)
|
||||
result
|
||||
end
|
||||
|
||||
def check_dependent_subscriptions
|
||||
return if Subscription.where(schedule_id: @schedule).empty?
|
||||
|
||||
@@ -101,14 +140,14 @@ module Admin
|
||||
@permissions = OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
end
|
||||
|
||||
def sync_subscriptions_for_create
|
||||
return unless params[:order_cycle_ids]
|
||||
def sync_subscriptions_for_update
|
||||
return unless params[:schedule][:order_cycle_ids] && @object.errors.blank?
|
||||
|
||||
sync_subscriptions
|
||||
end
|
||||
|
||||
def sync_subscriptions_for_update
|
||||
return unless params[:schedule][:order_cycle_ids] && @schedule.errors.blank?
|
||||
def sync_subscriptions_for_create
|
||||
return unless params[:order_cycle_ids]
|
||||
|
||||
sync_subscriptions
|
||||
end
|
||||
@@ -116,7 +155,6 @@ module Admin
|
||||
def sync_subscriptions
|
||||
removed_ids = @existing_order_cycle_ids - @schedule.order_cycle_ids
|
||||
new_ids = @schedule.order_cycle_ids - @existing_order_cycle_ids
|
||||
|
||||
return unless removed_ids.any? || new_ids.any?
|
||||
|
||||
subscriptions = Subscription.where(schedule_id: @schedule)
|
||||
|
||||
@@ -9,28 +9,19 @@ module Admin
|
||||
end
|
||||
|
||||
def create
|
||||
@voucher = Voucher.new(
|
||||
permitted_resource_params.merge(enterprise: @enterprise)
|
||||
)
|
||||
@voucher = Voucher.create(permitted_resource_params.merge(enterprise: @enterprise))
|
||||
|
||||
if @voucher.save
|
||||
flash[:success] = I18n.t(:successfully_created, resource: "Voucher")
|
||||
flash[:success] = flash_message_for(@voucher, :successfully_created)
|
||||
redirect_to edit_admin_enterprise_path(@enterprise, anchor: :vouchers_panel)
|
||||
else
|
||||
render_error
|
||||
flash[:error] = @voucher.errors.full_messages.to_sentence
|
||||
render :new
|
||||
end
|
||||
rescue ActiveRecord::SubclassNotFound
|
||||
@voucher.errors.add(:type)
|
||||
render_error
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_error
|
||||
flash[:error] = @voucher.errors.full_messages.to_sentence
|
||||
render :new
|
||||
end
|
||||
|
||||
def load_enterprise
|
||||
@enterprise = OpenFoodNetwork::Permissions
|
||||
.new(spree_current_user)
|
||||
@@ -39,7 +30,7 @@ module Admin
|
||||
end
|
||||
|
||||
def permitted_resource_params
|
||||
params.require(:voucher).permit(:code, :amount, :type)
|
||||
params.require(:voucher).permit(:code, :amount)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,6 +5,11 @@ module Api
|
||||
class OrdersController < Api::V0::BaseController
|
||||
include PaginationData
|
||||
|
||||
def show
|
||||
authorize! :read, order
|
||||
render json: order, serializer: Api::OrderDetailedSerializer, current_order: order
|
||||
end
|
||||
|
||||
def index
|
||||
authorize! :admin, Spree::Order
|
||||
|
||||
@@ -21,11 +26,6 @@ module Api
|
||||
}
|
||||
end
|
||||
|
||||
def show
|
||||
authorize! :read, order
|
||||
render json: order, serializer: Api::OrderDetailedSerializer, current_order: order
|
||||
end
|
||||
|
||||
def update
|
||||
authorize! :admin, order
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ module Api
|
||||
skip_authorization_check only: [:show, :bulk_products, :overridable]
|
||||
|
||||
def show
|
||||
@product = product_finder.find_product
|
||||
@product = find_product(params[:id])
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer
|
||||
end
|
||||
|
||||
@@ -30,7 +30,7 @@ module Api
|
||||
|
||||
def update
|
||||
authorize! :update, Spree::Product
|
||||
@product = product_finder.find_product
|
||||
@product = find_product(params[:id])
|
||||
if @product.update(product_params)
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer, status: :ok
|
||||
else
|
||||
@@ -40,20 +40,36 @@ module Api
|
||||
|
||||
def destroy
|
||||
authorize! :delete, Spree::Product
|
||||
@product = product_finder.find_product
|
||||
@product = find_product(params[:id])
|
||||
authorize! :delete, @product
|
||||
@product.destroy
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer, status: :no_content
|
||||
end
|
||||
|
||||
def bulk_products
|
||||
@products = product_finder.bulk_products
|
||||
product_query = OpenFoodNetwork::Permissions.
|
||||
new(current_api_user).
|
||||
editable_products.
|
||||
merge(product_scope)
|
||||
|
||||
if params[:import_date].present?
|
||||
product_query = product_query.
|
||||
imported_on(params[:import_date]).
|
||||
group_by_products_id
|
||||
end
|
||||
|
||||
@products = product_query.
|
||||
ransack(query_params_with_defaults).
|
||||
result
|
||||
|
||||
render_paged_products @products
|
||||
end
|
||||
|
||||
def overridable
|
||||
@products = product_finder.paged_products_for_producers
|
||||
producer_ids = OpenFoodNetwork::Permissions.new(current_api_user).
|
||||
variant_override_producers.by_name.select('enterprises.id')
|
||||
|
||||
@products = paged_products_for_producers producer_ids
|
||||
|
||||
render_paged_products @products, ::Api::Admin::ProductSimpleSerializer
|
||||
end
|
||||
@@ -62,7 +78,7 @@ module Api
|
||||
#
|
||||
def clone
|
||||
authorize! :create, Spree::Product
|
||||
original_product = product_finder.find_product_to_be_cloned
|
||||
original_product = find_product(params[:product_id])
|
||||
authorize! :update, original_product
|
||||
|
||||
@product = original_product.duplicate
|
||||
@@ -72,8 +88,37 @@ module Api
|
||||
|
||||
private
|
||||
|
||||
def product_finder
|
||||
ProductScopeQuery.new(current_api_user, params)
|
||||
def find_product(id)
|
||||
product_scope.find(id)
|
||||
end
|
||||
|
||||
def product_scope
|
||||
if current_api_user.has_spree_role?("admin") || current_api_user.enterprises.present?
|
||||
scope = Spree::Product
|
||||
if params[:show_deleted]
|
||||
scope = scope.with_deleted
|
||||
end
|
||||
else
|
||||
scope = Spree::Product.active
|
||||
end
|
||||
|
||||
scope.includes(product_query_includes)
|
||||
end
|
||||
|
||||
def product_query_includes
|
||||
[
|
||||
image: { attachment_attachment: :blob },
|
||||
variants: [:default_price, :stock_locations, :stock_items, :variant_overrides]
|
||||
]
|
||||
end
|
||||
|
||||
def paged_products_for_producers(producer_ids)
|
||||
Spree::Product.where(nil).
|
||||
merge(product_scope).
|
||||
includes(variants: [:product, :default_price, :stock_items]).
|
||||
where(supplier_id: producer_ids).
|
||||
by_producer.by_name.
|
||||
ransack(params[:q]).result
|
||||
end
|
||||
|
||||
def render_paged_products(products, product_serializer = ::Api::Admin::ProductSerializer)
|
||||
@@ -90,6 +135,10 @@ module Api
|
||||
}
|
||||
end
|
||||
|
||||
def query_params_with_defaults
|
||||
(params[:q] || {}).reverse_merge(s: 'created_at desc')
|
||||
end
|
||||
|
||||
def product_params
|
||||
@product_params ||=
|
||||
params.permit(product: PermittedAttributes::Product.attributes)[:product].to_h
|
||||
|
||||
@@ -69,14 +69,14 @@ module Api
|
||||
end
|
||||
|
||||
def missing_parameter(error)
|
||||
message = I18n.t('api.missing_parameter', param: error.param)
|
||||
message = I18n.t(:missing_parameter, param: error.param, scope: :api)
|
||||
|
||||
render status: :unprocessable_entity,
|
||||
json: json_api_error(message)
|
||||
end
|
||||
|
||||
def unpermitted_parameters(error)
|
||||
message = I18n.t('api.unpermitted_parameters', params: error.params.join(", "))
|
||||
message = I18n.t(:unpermitted_parameters, params: error.params.join(", "), scope: :api)
|
||||
|
||||
render status: :unprocessable_entity,
|
||||
json: json_api_error(message)
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module CheckoutSteps
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
private
|
||||
|
||||
def summary_step?
|
||||
params[:step] == "summary"
|
||||
end
|
||||
|
||||
def payment_step?
|
||||
params[:step] == "payment"
|
||||
end
|
||||
|
||||
def redirect_to_step_based_on_order
|
||||
case @order.state
|
||||
when "cart", "address", "delivery"
|
||||
redirect_to checkout_step_path(:details)
|
||||
when "payment"
|
||||
redirect_to checkout_step_path(:payment)
|
||||
when "confirmation"
|
||||
redirect_to checkout_step_path(:summary)
|
||||
else
|
||||
redirect_to order_path(@order, order_token: @order.token)
|
||||
end
|
||||
end
|
||||
|
||||
def redirect_to_step
|
||||
case params[:step]
|
||||
when "details"
|
||||
return redirect_to checkout_step_path(:payment)
|
||||
when "payment"
|
||||
return redirect_to checkout_step_path(:summary)
|
||||
end
|
||||
redirect_to_step_based_on_order
|
||||
end
|
||||
|
||||
def check_step
|
||||
case @order.state
|
||||
when "cart", "address", "delivery"
|
||||
redirect_to checkout_step_path(:details) unless params[:step] == "details"
|
||||
when "payment"
|
||||
redirect_to checkout_step_path(:payment) if params[:step] == "summary"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -16,7 +16,7 @@ module RequestTimeouts
|
||||
respond_to do |type|
|
||||
type.html {
|
||||
render status: :gateway_timeout,
|
||||
file: Rails.public_path.join('500.html'),
|
||||
file: Rails.root.join("public/500.html"),
|
||||
formats: [:html],
|
||||
layout: nil
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ class ErrorsController < ApplicationController
|
||||
|
||||
event.add_metadata(:request, request.env)
|
||||
end
|
||||
render status: :not_found, formats: :html
|
||||
render status: :not_found
|
||||
end
|
||||
|
||||
def internal_server_error
|
||||
|
||||
@@ -8,7 +8,6 @@ class SplitCheckoutController < ::BaseController
|
||||
include OrderStockCheck
|
||||
include Spree::BaseHelper
|
||||
include CheckoutCallbacks
|
||||
include CheckoutSteps
|
||||
include OrderCompletion
|
||||
include CablecarResponses
|
||||
include WhiteLabel
|
||||
@@ -51,13 +50,60 @@ class SplitCheckoutController < ::BaseController
|
||||
private
|
||||
|
||||
def render_error
|
||||
flash.now[:error] ||= I18n.t('split_checkout.errors.saving_failed')
|
||||
flash.now[:error] ||= I18n.t(
|
||||
'split_checkout.errors.saving_failed',
|
||||
messages: order_error_messages
|
||||
)
|
||||
|
||||
render status: :unprocessable_entity, cable_ready: cable_car.
|
||||
replace("#checkout", partial("split_checkout/checkout")).
|
||||
replace("#flashes", partial("shared/flashes", locals: { flashes: flash }))
|
||||
end
|
||||
|
||||
def order_error_messages
|
||||
# Remove ship_address.* errors if no shipping method is not selected
|
||||
remove_ship_address_errors if no_ship_address_needed?
|
||||
|
||||
# Reorder errors to make sure the most important ones are shown first
|
||||
# and finally, return the error messages to sentence
|
||||
reorder_errors.map(&:full_message).to_sentence
|
||||
end
|
||||
|
||||
def no_ship_address_needed?
|
||||
@order.errors[:shipping_method].present? || params[:ship_address_same_as_billing] == "1"
|
||||
end
|
||||
|
||||
def remove_ship_address_errors
|
||||
@order.errors.delete("ship_address.firstname")
|
||||
@order.errors.delete("ship_address.address1")
|
||||
@order.errors.delete("ship_address.city")
|
||||
@order.errors.delete("ship_address.phone")
|
||||
@order.errors.delete("ship_address.lastname")
|
||||
@order.errors.delete("ship_address.zipcode")
|
||||
end
|
||||
|
||||
def reorder_errors
|
||||
@order.errors.sort_by do |e|
|
||||
case e.attribute
|
||||
when /email/i then 0
|
||||
when /phone/i then 1
|
||||
when /bill_address/i then 2 + bill_address_error_order(e)
|
||||
else 20
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def bill_address_error_order(error)
|
||||
case error.attribute
|
||||
when /firstname/i then 0
|
||||
when /lastname/i then 1
|
||||
when /address1/i then 2
|
||||
when /city/i then 3
|
||||
when /zipcode/i then 4
|
||||
else 5
|
||||
end
|
||||
end
|
||||
|
||||
def check_payments_adjustments
|
||||
@order.payments.each(&:ensure_correct_adjustment)
|
||||
end
|
||||
@@ -68,7 +114,7 @@ class SplitCheckoutController < ::BaseController
|
||||
|
||||
def confirm_order
|
||||
return unless summary_step? && @order.confirmation?
|
||||
return unless validate_current_step
|
||||
return unless validate_summary! && @order.errors.empty?
|
||||
|
||||
@order.customer.touch :terms_and_conditions_accepted_at
|
||||
|
||||
@@ -94,15 +140,48 @@ class SplitCheckoutController < ::BaseController
|
||||
def update_order
|
||||
return if params[:confirm_order] || @order.errors.any?
|
||||
|
||||
# If we have "pick up" shipping method (require_ship_address is set to false), use the
|
||||
# distributor address as shipping address
|
||||
use_shipping_address_from_distributor if shipping_method_ship_address_not_required?
|
||||
|
||||
@order.select_shipping_method(params[:shipping_method_id])
|
||||
@order.update(order_params)
|
||||
@order.update_totals_and_states
|
||||
|
||||
validate_current_step
|
||||
validate_current_step!
|
||||
|
||||
@order.errors.empty?
|
||||
end
|
||||
|
||||
def validate_current_step
|
||||
Checkout::Validation.new(@order, params).call && @order.errors.empty?
|
||||
def use_shipping_address_from_distributor
|
||||
@order.ship_address = @order.address_from_distributor
|
||||
|
||||
# Add the missing data
|
||||
bill_address = params[:order][:bill_address_attributes]
|
||||
@order.ship_address.firstname = bill_address[:firstname]
|
||||
@order.ship_address.lastname = bill_address[:lastname]
|
||||
@order.ship_address.phone = bill_address[:phone]
|
||||
|
||||
# Remove shipping address from parameter so we don't override the address we just set
|
||||
params[:order].delete(:ship_address_attributes)
|
||||
end
|
||||
|
||||
def shipping_method_ship_address_not_required?
|
||||
selected_shipping_method = available_shipping_methods&.select do |sm|
|
||||
sm.id.to_s == params[:shipping_method_id]
|
||||
end
|
||||
|
||||
return false if selected_shipping_method.empty?
|
||||
|
||||
selected_shipping_method.first.require_ship_address == false
|
||||
end
|
||||
|
||||
def summary_step?
|
||||
params[:step] == "summary"
|
||||
end
|
||||
|
||||
def payment_step?
|
||||
params[:step] == "payment"
|
||||
end
|
||||
|
||||
def advance_order_state
|
||||
@@ -111,7 +190,64 @@ class SplitCheckoutController < ::BaseController
|
||||
OrderWorkflow.new(@order).advance_checkout(raw_params.slice(:shipping_method_id))
|
||||
end
|
||||
|
||||
def validate_current_step!
|
||||
step = ([params[:step]] & ["details", "payment", "summary"]).first
|
||||
send("validate_#{step}!")
|
||||
end
|
||||
|
||||
def validate_details!
|
||||
return true if params[:shipping_method_id].present?
|
||||
|
||||
@order.errors.add :shipping_method, I18n.t('split_checkout.errors.select_a_shipping_method')
|
||||
end
|
||||
|
||||
def validate_payment!
|
||||
return true if params.dig(:order, :payments_attributes, 0, :payment_method_id).present?
|
||||
return true if @order.zero_priced_order?
|
||||
|
||||
@order.errors.add :payment_method, I18n.t('split_checkout.errors.select_a_payment_method')
|
||||
end
|
||||
|
||||
def validate_summary!
|
||||
return true if params[:accept_terms]
|
||||
return true unless TermsOfService.required?(@order.distributor)
|
||||
|
||||
@order.errors.add(:terms_and_conditions, t("split_checkout.errors.terms_not_accepted"))
|
||||
end
|
||||
|
||||
def order_params
|
||||
@order_params ||= Checkout::Params.new(@order, params, spree_current_user).call
|
||||
end
|
||||
|
||||
def redirect_to_step_based_on_order
|
||||
case @order.state
|
||||
when "cart", "address", "delivery"
|
||||
redirect_to checkout_step_path(:details)
|
||||
when "payment"
|
||||
redirect_to checkout_step_path(:payment)
|
||||
when "confirmation"
|
||||
redirect_to checkout_step_path(:summary)
|
||||
else
|
||||
redirect_to order_path(@order, order_token: @order.token)
|
||||
end
|
||||
end
|
||||
|
||||
def redirect_to_step
|
||||
case params[:step]
|
||||
when "details"
|
||||
return redirect_to checkout_step_path(:payment)
|
||||
when "payment"
|
||||
return redirect_to checkout_step_path(:summary)
|
||||
end
|
||||
redirect_to_step_based_on_order
|
||||
end
|
||||
|
||||
def check_step
|
||||
case @order.state
|
||||
when "cart", "address", "delivery"
|
||||
redirect_to checkout_step_path(:details) unless params[:step] == "details"
|
||||
when "payment"
|
||||
redirect_to checkout_step_path(:payment) if params[:step] == "summary"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,10 +20,6 @@ module Spree
|
||||
render layout: !request.xhr?
|
||||
end
|
||||
|
||||
def edit
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
end
|
||||
|
||||
def create
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
set_viewable
|
||||
@@ -38,6 +34,10 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
end
|
||||
|
||||
def update
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
set_viewable
|
||||
|
||||
@@ -10,24 +10,57 @@ module Spree
|
||||
authorize! :invoice, @order
|
||||
end
|
||||
|
||||
def show
|
||||
invoice_id = params[:id]
|
||||
invoice_pdf = filepath(invoice_id)
|
||||
def create
|
||||
Spree::Order.where(id: params[:order_ids]).find_each do |order|
|
||||
authorize! :invoice, order
|
||||
end
|
||||
invoice_service = BulkInvoiceService.new
|
||||
invoice_service.start_pdf_job(params[:order_ids])
|
||||
|
||||
send_file(invoice_pdf, type: 'application/pdf', disposition: :inline)
|
||||
render json: invoice_service.id, status: :ok
|
||||
end
|
||||
|
||||
def generate
|
||||
@order = Order.find_by(number: params[:order_id])
|
||||
authorize! :invoice, @order
|
||||
OrderInvoiceGenerator.new(@order).generate_or_update_latest_invoice
|
||||
|
||||
@comparator = OrderInvoiceComparator.new(@order)
|
||||
if @comparator.can_generate_new_invoice?
|
||||
@order.invoices.create!(
|
||||
date: Time.zone.today,
|
||||
number: @order.invoices.count + 1,
|
||||
data: invoice_data
|
||||
)
|
||||
elsif @comparator.can_update_latest_invoice?
|
||||
@order.invoices.last.update!(
|
||||
date: Time.zone.today,
|
||||
data: invoice_data
|
||||
)
|
||||
end
|
||||
redirect_back(fallback_location: spree.admin_dashboard_path)
|
||||
end
|
||||
|
||||
private
|
||||
def show
|
||||
invoice_id = params[:id]
|
||||
invoice_pdf = BulkInvoiceService.new.filepath(invoice_id)
|
||||
|
||||
def filepath(invoice_id)
|
||||
"tmp/invoices/#{invoice_id}.pdf"
|
||||
send_file(invoice_pdf, type: 'application/pdf', disposition: :inline)
|
||||
end
|
||||
|
||||
def poll
|
||||
invoice_id = params[:invoice_id]
|
||||
|
||||
if BulkInvoiceService.new.invoice_created? invoice_id
|
||||
render json: { created: true }, status: :ok
|
||||
else
|
||||
render json: { created: false }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def invoice_data
|
||||
@invoice_data ||= InvoiceDataGenerator.new(@order).generate
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -16,22 +16,8 @@ module Spree
|
||||
before_action :load_spree_api_key, only: [:index, :variant_overrides]
|
||||
before_action :strip_new_properties, only: [:create, :update]
|
||||
|
||||
def index
|
||||
@current_user = spree_current_user
|
||||
@show_latest_import = params[:latest_import] || false
|
||||
end
|
||||
|
||||
def show
|
||||
session[:return_to] ||= request.referer
|
||||
redirect_to( action: :edit )
|
||||
end
|
||||
|
||||
def new
|
||||
@object.shipping_category_id = DefaultShippingCategory.find_or_create.id
|
||||
end
|
||||
|
||||
def edit
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
@object.shipping_category = DefaultShippingCategory.find_or_create
|
||||
end
|
||||
|
||||
def create
|
||||
@@ -49,6 +35,20 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
session[:return_to] ||= request.referer
|
||||
redirect_to( action: :edit )
|
||||
end
|
||||
|
||||
def index
|
||||
@current_user = spree_current_user
|
||||
@show_latest_import = params[:latest_import] || false
|
||||
end
|
||||
|
||||
def edit
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
end
|
||||
|
||||
def update
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
|
||||
@@ -180,7 +180,7 @@ module Spree
|
||||
select('DISTINCT spree_variants.import_date').
|
||||
joins(:product).
|
||||
where('spree_products.supplier_id IN (?)', editable_enterprises.collect(&:id)).
|
||||
where.not(spree_variants: { import_date: nil }).
|
||||
where('spree_variants.import_date IS NOT NULL').
|
||||
where(spree_variants: { deleted_at: nil }).
|
||||
order('spree_variants.import_date DESC')
|
||||
end
|
||||
|
||||
@@ -5,12 +5,6 @@ module Spree
|
||||
class TaxonsController < Spree::Admin::BaseController
|
||||
respond_to :html, :json, :js
|
||||
|
||||
def edit
|
||||
@taxonomy = Taxonomy.find(params[:taxonomy_id])
|
||||
@taxon = @taxonomy.taxons.find(params[:id])
|
||||
@permalink_part = @taxon.permalink.split("/").last
|
||||
end
|
||||
|
||||
def create
|
||||
@taxonomy = Taxonomy.find(params[:taxonomy_id])
|
||||
@taxon = @taxonomy.taxons.build(params[:taxon])
|
||||
@@ -32,6 +26,12 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
@taxonomy = Taxonomy.find(params[:taxonomy_id])
|
||||
@taxon = @taxonomy.taxons.find(params[:id])
|
||||
@permalink_part = @taxon.permalink.split("/").last
|
||||
end
|
||||
|
||||
def update
|
||||
@taxonomy = Taxonomy.find(params[:taxonomy_id])
|
||||
@taxon = @taxonomy.taxons.find(params[:id])
|
||||
|
||||
@@ -28,7 +28,7 @@ module Spree
|
||||
if @user.save
|
||||
|
||||
if roles
|
||||
@user.spree_roles = roles.compact_blank.collect{ |r| Spree::Role.find(r) }
|
||||
@user.spree_roles = roles.reject(&:blank?).collect{ |r| Spree::Role.find(r) }
|
||||
end
|
||||
|
||||
flash.now[:success] = Spree.t(:created_successfully)
|
||||
@@ -45,7 +45,7 @@ module Spree
|
||||
|
||||
if @user.update(user_params)
|
||||
if roles
|
||||
@user.spree_roles = roles.compact_blank.collect{ |r| Spree::Role.find(r) }
|
||||
@user.spree_roles = roles.reject(&:blank?).collect{ |r| Spree::Role.find(r) }
|
||||
end
|
||||
|
||||
flash.now[:success] = update_message
|
||||
|
||||
@@ -7,18 +7,28 @@ module Spree
|
||||
class VariantsController < ::Admin::ResourceController
|
||||
belongs_to 'spree/product'
|
||||
|
||||
before_action :load_data, only: [:new, :edit]
|
||||
|
||||
def index
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
end
|
||||
|
||||
def new
|
||||
def edit
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
@object.shipping_category ||= DefaultShippingCategory.find_or_create
|
||||
end
|
||||
|
||||
def edit
|
||||
def update
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
|
||||
if @object.update(permitted_resource_params)
|
||||
flash[:success] = flash_message_for(@object, :successfully_updated)
|
||||
redirect_to spree.admin_product_variants_url(params[:product_id], @url_filters)
|
||||
else
|
||||
redirect_to spree.edit_admin_product_variant_url(params[:product_id],
|
||||
@object,
|
||||
@url_filters)
|
||||
end
|
||||
end
|
||||
|
||||
def new
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
end
|
||||
|
||||
@@ -43,19 +53,6 @@ module Spree
|
||||
@object.on_hand = on_hand.to_i if on_hand.present?
|
||||
end
|
||||
|
||||
def update
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
|
||||
if @object.update(permitted_resource_params)
|
||||
flash[:success] = flash_message_for(@object, :successfully_updated)
|
||||
redirect_to spree.admin_product_variants_url(params[:product_id], @url_filters)
|
||||
else
|
||||
redirect_to spree.edit_admin_product_variant_url(params[:product_id],
|
||||
@object,
|
||||
@url_filters)
|
||||
end
|
||||
end
|
||||
|
||||
def search
|
||||
scoper = OpenFoodNetwork::ScopeVariantsForSearch.new(variant_search_params)
|
||||
@variants = scoper.search
|
||||
@@ -110,13 +107,6 @@ module Spree
|
||||
:include_out_of_stock
|
||||
).to_h.with_indifferent_access
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_data
|
||||
@tax_categories = TaxCategory.order(:name)
|
||||
@shipping_categories = ShippingCategory.order(:name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -69,10 +69,6 @@ module Spree
|
||||
if @order.contents.update_cart(order_params)
|
||||
@order.recreate_all_fees! # Enterprise fees on line items and on the order itself
|
||||
|
||||
# Re apply the voucher
|
||||
VoucherAdjustmentsService.new(@order).update
|
||||
@order.update_totals_and_states
|
||||
|
||||
if @order.complete?
|
||||
@order.update_payment_fees!
|
||||
@order.create_tax_charge!
|
||||
|
||||
@@ -49,10 +49,8 @@ module Spree
|
||||
render cable_ready: cable_car.inner_html(
|
||||
"#signup-feedback",
|
||||
partial("layouts/alert",
|
||||
locals: {
|
||||
type: "success",
|
||||
message: t('devise.user_registrations.spree_user.signed_up_but_unconfirmed')
|
||||
})
|
||||
locals: { type: "success",
|
||||
message: t('devise.user_registrations.spree_user.signed_up_but_unconfirmed') })
|
||||
)
|
||||
else
|
||||
render status: :unprocessable_entity, cable_ready: cable_car.morph(
|
||||
|
||||
@@ -5,13 +5,6 @@ class UserConfirmationsController < DeviseController
|
||||
include Spree::Core::ControllerHelpers::Auth
|
||||
include CablecarResponses
|
||||
|
||||
# GET /resource/confirmation?confirmation_token=abcdef
|
||||
def show
|
||||
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
|
||||
|
||||
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource) }
|
||||
end
|
||||
|
||||
# GET /resource/confirmation/new
|
||||
def new
|
||||
build_resource({})
|
||||
@@ -40,6 +33,13 @@ class UserConfirmationsController < DeviseController
|
||||
respond_with_navigational(resource){ redirect_to login_path }
|
||||
end
|
||||
|
||||
# GET /resource/confirmation?confirmation_token=abcdef
|
||||
def show
|
||||
self.resource = resource_class.confirm_by_token(params[:confirmation_token])
|
||||
|
||||
respond_with_navigational(resource){ redirect_to after_confirmation_path_for(resource) }
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def set_return_url
|
||||
|
||||
@@ -5,6 +5,9 @@ class VoucherAdjustmentsController < BaseController
|
||||
|
||||
def create
|
||||
if add_voucher
|
||||
VoucherAdjustmentsService.calculate(@order)
|
||||
@order.update_totals_and_states
|
||||
|
||||
update_payment_section
|
||||
elsif @order.errors.present?
|
||||
render_error
|
||||
@@ -18,9 +21,6 @@ class VoucherAdjustmentsController < BaseController
|
||||
@order.voucher_adjustments.where(originator_id: adjustment.originator_id)&.destroy_all
|
||||
end
|
||||
|
||||
# Update order to make sure we display the appropriate payment method
|
||||
@order.update_totals_and_states
|
||||
|
||||
update_payment_section
|
||||
end
|
||||
|
||||
@@ -45,17 +45,12 @@ class VoucherAdjustmentsController < BaseController
|
||||
|
||||
adjustment = voucher.create_adjustment(voucher.code, @order)
|
||||
|
||||
unless adjustment.persisted?
|
||||
unless adjustment.valid?
|
||||
@order.errors.add(:voucher_code, I18n.t('split_checkout.errors.add_voucher_error'))
|
||||
adjustment.errors.each { |error| @order.errors.import(error) }
|
||||
return false
|
||||
end
|
||||
|
||||
clear_payments
|
||||
|
||||
VoucherAdjustmentsService.new(@order).update
|
||||
@order.update_totals_and_states
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
@@ -83,9 +78,4 @@ class VoucherAdjustmentsController < BaseController
|
||||
def voucher_params
|
||||
params.require(:order).permit(:voucher_code)
|
||||
end
|
||||
|
||||
# Clear payments and payment fees, to not affect voucher adjustment calculation
|
||||
def clear_payments
|
||||
@order.payments.incomplete.destroy_all
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ScheduleForm
|
||||
include ActiveModel::Model
|
||||
|
||||
attr_reader :errors, :flash_success
|
||||
|
||||
def initialize(params, user, schedule = nil)
|
||||
@errors = ActiveModel::Errors.new self
|
||||
|
||||
# Not strong
|
||||
@params = params
|
||||
@current_user = user
|
||||
@schedule = schedule
|
||||
end
|
||||
|
||||
def save
|
||||
editable_order_cycle_ids_for_create
|
||||
|
||||
return false if @params[:order_cycle_ids].blank?
|
||||
|
||||
@schedule.attributes = permitted_resource_params
|
||||
|
||||
if @schedule.save
|
||||
@schedule.order_cycle_ids = @params[:order_cycle_ids]
|
||||
@schedule.save!
|
||||
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
def update(_params)
|
||||
editable_order_cycle_ids_for_update
|
||||
|
||||
false unless @schedule.update(permitted_resource_params)
|
||||
end
|
||||
|
||||
def order_cycle_ids
|
||||
@schedule.order_cycle_ids
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def editable_order_cycle_ids_for_create
|
||||
return unless @params[:order_cycle_ids]
|
||||
|
||||
@existing_order_cycle_ids = []
|
||||
result = editable_order_cycles(@params[:order_cycle_ids])
|
||||
@params[:order_cycle_ids] = result
|
||||
end
|
||||
|
||||
def editable_order_cycle_ids_for_update
|
||||
return unless @params[:schedule][:order_cycle_ids]
|
||||
|
||||
@existing_order_cycle_ids = @schedule.order_cycle_ids
|
||||
result = editable_order_cycles(@params[:schedule][:order_cycle_ids])
|
||||
|
||||
@params[:schedule][:order_cycle_ids] = result
|
||||
@schedule.order_cycle_ids = result
|
||||
end
|
||||
|
||||
def editable_order_cycles(requested)
|
||||
permitted = OrderCycle
|
||||
.where(id: @params[:order_cycle_ids] | @existing_order_cycle_ids)
|
||||
.merge(OrderCycle.managed_by(@current_user))
|
||||
.pluck(:id)
|
||||
result = @existing_order_cycle_ids
|
||||
result |= (requested & permitted) # add any requested & permitted ids
|
||||
# remove any existing and permitted ids that were not specifically requested
|
||||
result -= ((result & permitted) - requested)
|
||||
result
|
||||
end
|
||||
|
||||
def permitted_resource_params
|
||||
@params.require(:schedule).permit(:id, :name, order_cycle_ids: [])
|
||||
end
|
||||
end
|
||||
@@ -42,7 +42,7 @@ module Admin
|
||||
{ name: 'shipping_methods', icon_class: "icon-truck", show: show_shipping_methods },
|
||||
{ name: 'payment_methods', icon_class: "icon-money", show: show_payment_methods },
|
||||
{ name: 'enterprise_fees', icon_class: "icon-tasks", show: show_enterprise_fees },
|
||||
{ name: 'vouchers', icon_class: "icon-ticket", show: is_shop },
|
||||
{ name: 'vouchers', icon_class: "icon-ticket", show: true },
|
||||
{ name: 'enterprise_permissions', icon_class: "icon-plug", show: true,
|
||||
href: admin_enterprise_relationships_path },
|
||||
{ name: 'inventory_settings', icon_class: "icon-list-ol", show: is_shop },
|
||||
|
||||
@@ -6,7 +6,7 @@ module DiscourseHelper
|
||||
end
|
||||
|
||||
def discourse_url
|
||||
ENV.fetch('DISCOURSE_URL', nil)
|
||||
ENV['DISCOURSE_URL']
|
||||
end
|
||||
|
||||
def discourse_login_url
|
||||
|
||||
@@ -5,9 +5,13 @@ class BulkInvoiceJob < ApplicationJob
|
||||
delegate :render, to: ActionController::Base
|
||||
|
||||
def perform(order_ids, filepath, options = {})
|
||||
orders = sorted_orders(order_ids)
|
||||
orders.filter!(&:invoiceable?) if OpenFoodNetwork::FeatureToggle.enabled?(:invoices)
|
||||
orders.each(&method(:generate_invoice))
|
||||
pdf = CombinePDF.new
|
||||
|
||||
sorted_orders(order_ids).each do |order|
|
||||
invoice = renderer.render_to_string(order)
|
||||
|
||||
pdf << CombinePDF.parse(invoice)
|
||||
end
|
||||
|
||||
ensure_directory_exists filepath
|
||||
|
||||
@@ -28,17 +32,6 @@ class BulkInvoiceJob < ApplicationJob
|
||||
@renderer ||= InvoiceRenderer.new
|
||||
end
|
||||
|
||||
def generate_invoice(order)
|
||||
renderer_data = if OpenFoodNetwork::FeatureToggle.enabled?(:invoices)
|
||||
OrderInvoiceGenerator.new(order).generate_or_update_latest_invoice
|
||||
order.invoices.first.presenter
|
||||
else
|
||||
order
|
||||
end
|
||||
invoice = renderer.render_to_string(renderer_data)
|
||||
pdf << CombinePDF.parse(invoice)
|
||||
end
|
||||
|
||||
def broadcast(filepath, channel)
|
||||
file_id = filepath.split("/").last.split(".").first
|
||||
|
||||
@@ -54,8 +47,4 @@ class BulkInvoiceJob < ApplicationJob
|
||||
def ensure_directory_exists(filepath)
|
||||
FileUtils.mkdir_p(File.dirname(filepath))
|
||||
end
|
||||
|
||||
def pdf
|
||||
@pdf ||= CombinePDF.new
|
||||
end
|
||||
end
|
||||
|
||||
@@ -48,14 +48,7 @@ module Spree
|
||||
|
||||
def invoice_email(order_or_order_id)
|
||||
@order = find_order(order_or_order_id)
|
||||
renderer_data = if OpenFoodNetwork::FeatureToggle.enabled?(:invoices)
|
||||
OrderInvoiceGenerator.new(@order).generate_or_update_latest_invoice
|
||||
@order.invoices.first.presenter
|
||||
else
|
||||
@order
|
||||
end
|
||||
|
||||
pdf = InvoiceRenderer.new.render_to_string(renderer_data)
|
||||
pdf = InvoiceRenderer.new.render_to_string(@order)
|
||||
|
||||
attach_file("invoice-#{@order.number}.pdf", pdf)
|
||||
I18n.with_locale valid_locale(@order.user) do
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AdjustmentMetadata < ApplicationRecord
|
||||
self.belongs_to_required_by_default = true
|
||||
|
||||
belongs_to :adjustment, class_name: 'Spree::Adjustment'
|
||||
belongs_to :enterprise
|
||||
end
|
||||
|
||||
@@ -45,7 +45,7 @@ module Calculator
|
||||
|
||||
def line_items_total(order)
|
||||
matched_line_items = order.line_items.select do |line_item|
|
||||
line_item.variant.tax_category == rate.tax_category
|
||||
line_item.product.tax_category == rate.tax_category
|
||||
end
|
||||
|
||||
matched_line_items.sum(&:total)
|
||||
@@ -70,7 +70,7 @@ module Calculator
|
||||
def applicable_rate?(applicator, line_item)
|
||||
fee = applicator.enterprise_fee
|
||||
(!fee.inherits_tax_category && fee.tax_category == rate.tax_category) ||
|
||||
(fee.inherits_tax_category && line_item.variant.tax_category == rate.tax_category)
|
||||
(fee.inherits_tax_category && line_item.product.tax_category == rate.tax_category)
|
||||
end
|
||||
|
||||
# Finds relevant fees for whole order,
|
||||
|
||||
@@ -5,6 +5,8 @@ require 'open_food_network/column_preference_defaults'
|
||||
class ColumnPreference < ApplicationRecord
|
||||
extend OpenFoodNetwork::ColumnPreferenceDefaults
|
||||
|
||||
self.belongs_to_required_by_default = true
|
||||
|
||||
# Non-persisted attributes that only have one
|
||||
# setting (ie. the default) for a given column
|
||||
attr_accessor :name
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
module AddressDisplay
|
||||
def full_name_reverse
|
||||
[lastname, firstname].compact_blank.join(" ")
|
||||
[lastname, firstname].reject(&:blank?).join(" ")
|
||||
end
|
||||
|
||||
def full_name_for_sorting
|
||||
[last_name, first_name].compact_blank.join(", ")
|
||||
[last_name, first_name].reject(&:blank?).join(", ")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -34,7 +34,7 @@ module PermalinkGenerator
|
||||
if id.nil?
|
||||
scope_with_deleted
|
||||
else
|
||||
scope_with_deleted.where.not(id:)
|
||||
scope_with_deleted.where('id != ?', id)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -71,7 +71,7 @@ class ContentConfiguration < Spree::Preferences::Configuration
|
||||
preference :footer_pinterest_url, :string, default: ""
|
||||
preference :footer_email, :string, default: "hello@openfoodnetwork.org"
|
||||
preference :community_forum_url, :string, default: "http://community.openfoodnetwork.org"
|
||||
preference :footer_links_md, :text, default: <<~EOS
|
||||
preference :footer_links_md, :text, default: <<-EOS.strip_heredoc
|
||||
[Newsletter sign-up](/)
|
||||
|
||||
[News](/)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class CoordinatorFee < ApplicationRecord
|
||||
self.belongs_to_required_by_default = true
|
||||
|
||||
belongs_to :order_cycle
|
||||
belongs_to :enterprise_fee
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# frozen_string_literal: false
|
||||
|
||||
class CustomTab < ApplicationRecord
|
||||
belongs_to :enterprise
|
||||
belongs_to :enterprise, optional: false
|
||||
|
||||
validates :title, presence: true, length: { maximum: 20 }
|
||||
end
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
class Customer < ApplicationRecord
|
||||
include SetUnusedAddressFields
|
||||
|
||||
self.belongs_to_required_by_default = true
|
||||
|
||||
acts_as_taggable
|
||||
|
||||
searchable_attributes :first_name, :last_name, :email, :code
|
||||
@@ -17,9 +19,6 @@ class Customer < ApplicationRecord
|
||||
belongs_to :enterprise
|
||||
belongs_to :user, class_name: "Spree::User", optional: true
|
||||
has_many :orders, class_name: "Spree::Order"
|
||||
before_validation :downcase_email
|
||||
before_validation :empty_code
|
||||
before_create :associate_user
|
||||
before_destroy :update_orders_and_delete_canceled_subscriptions
|
||||
|
||||
belongs_to :bill_address, class_name: "Spree::Address", optional: true
|
||||
@@ -30,6 +29,9 @@ class Customer < ApplicationRecord
|
||||
alias_attribute :shipping_address, :ship_address
|
||||
accepts_nested_attributes_for :ship_address
|
||||
|
||||
before_validation :downcase_email
|
||||
before_validation :empty_code
|
||||
|
||||
validates :code, uniqueness: { scope: :enterprise_id, allow_nil: true }
|
||||
validates :email, presence: true, 'valid_email_2/email': true,
|
||||
uniqueness: {
|
||||
@@ -39,11 +41,13 @@ class Customer < ApplicationRecord
|
||||
|
||||
scope :of, ->(enterprise) { where(enterprise_id: enterprise) }
|
||||
scope :managed_by, ->(user) {
|
||||
user&.persisted? ? where(user: user).or(of(Enterprise.managed_by(user))) : none
|
||||
}
|
||||
user&.persisted? ? where(user: user).or(of(Enterprise.managed_by(user))) : none
|
||||
}
|
||||
scope :created_manually, -> { where(created_manually: true) }
|
||||
scope :visible, -> { where(id: Spree::Order.complete.select(:customer_id)).or(created_manually) }
|
||||
|
||||
before_create :associate_user
|
||||
|
||||
attr_accessor :gateway_recurring_payment_client_secret, :gateway_shop_id
|
||||
|
||||
def full_name
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
class DistributorPaymentMethod < ApplicationRecord
|
||||
self.table_name = "distributors_payment_methods"
|
||||
self.belongs_to_required_by_default = true
|
||||
|
||||
belongs_to :payment_method, class_name: "Spree::PaymentMethod", touch: true
|
||||
belongs_to :distributor, class_name: "Enterprise", touch: true
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
class DistributorShippingMethod < ApplicationRecord
|
||||
self.table_name = "distributors_shipping_methods"
|
||||
self.belongs_to_required_by_default = true
|
||||
|
||||
belongs_to :shipping_method, class_name: "Spree::ShippingMethod", touch: true
|
||||
belongs_to :distributor, class_name: "Enterprise", touch: true
|
||||
|
||||
@@ -44,7 +44,7 @@ class Enterprise < ApplicationRecord
|
||||
dependent: :destroy
|
||||
has_many :distributed_orders, class_name: 'Spree::Order', foreign_key: 'distributor_id'
|
||||
belongs_to :address, class_name: 'Spree::Address'
|
||||
belongs_to :business_address, optional: true, class_name: 'Spree::Address', dependent: :destroy
|
||||
belongs_to :business_address, class_name: 'Spree::Address', dependent: :destroy
|
||||
has_many :enterprise_fees
|
||||
has_many :enterprise_roles, dependent: :destroy
|
||||
has_many :users, through: :enterprise_roles
|
||||
@@ -91,7 +91,7 @@ class Enterprise < ApplicationRecord
|
||||
end
|
||||
has_one_attached :white_label_logo, service: image_service do |attachment|
|
||||
attachment.variant :default, resize_to_fill: [217, 44]
|
||||
attachment.variant :mobile, resize_to_fill: [128, 26]
|
||||
attachment.variant :mobile, resize_to_fill: [75, 26]
|
||||
end
|
||||
|
||||
validates :logo,
|
||||
@@ -108,7 +108,8 @@ class Enterprise < ApplicationRecord
|
||||
validates :name, presence: true
|
||||
validate :name_is_unique
|
||||
validates :sells, presence: true, inclusion: { in: SELLS }
|
||||
validates :address, associated: true
|
||||
validates :address, presence: true, associated: true
|
||||
validates :owner, presence: true
|
||||
validates :permalink, uniqueness: true, presence: true
|
||||
validate :shopfront_taxons
|
||||
validate :shopfront_producers
|
||||
@@ -124,12 +125,13 @@ class Enterprise < ApplicationRecord
|
||||
before_validation :set_unused_address_fields
|
||||
after_validation :ensure_owner_is_manager, if: lambda { owner_id_changed? && !owner_id.nil? }
|
||||
|
||||
after_touch :touch_distributors
|
||||
after_create :set_default_contact
|
||||
after_create :relate_to_owners_enterprises
|
||||
after_rollback :restore_permalink
|
||||
after_touch :touch_distributors
|
||||
after_create_commit :send_welcome_email
|
||||
|
||||
after_rollback :restore_permalink
|
||||
|
||||
scope :by_name, -> { order('name') }
|
||||
scope :visible, -> { where(visible: "public") }
|
||||
scope :not_hidden, -> { where.not(visible: "hidden") }
|
||||
@@ -149,13 +151,13 @@ class Enterprise < ApplicationRecord
|
||||
select('DISTINCT enterprises.id')
|
||||
|
||||
if ready_enterprises.any?
|
||||
where.not(enterprises: { id: ready_enterprises })
|
||||
where("enterprises.id NOT IN (?)", ready_enterprises)
|
||||
else
|
||||
where(nil)
|
||||
end
|
||||
}
|
||||
scope :is_primary_producer, -> { where("enterprises.is_primary_producer IS TRUE") }
|
||||
scope :is_distributor, -> { where.not(sells: 'none') }
|
||||
scope :is_distributor, -> { where('sells != ?', 'none') }
|
||||
scope :is_hub, -> { where(sells: 'any') }
|
||||
scope :supplying_variant_in, lambda { |variants|
|
||||
joins(supplied_products: :variants).
|
||||
@@ -452,7 +454,7 @@ class Enterprise < ApplicationRecord
|
||||
uri = URI(white_label_logo_link)
|
||||
self.white_label_logo_link = "http://#{white_label_logo_link}" if uri.scheme.nil?
|
||||
rescue URI::InvalidURIError
|
||||
errors.add(:white_label_logo_link, I18n.t(:invalid_url, url: white_label_logo_link))
|
||||
errors.add(:white_label_logo_link, I18n.t(:invalid_url))
|
||||
end
|
||||
|
||||
def image_url_for(image, name)
|
||||
@@ -476,7 +478,7 @@ class Enterprise < ApplicationRecord
|
||||
|
||||
def name_is_unique
|
||||
dups = Enterprise.where(name: name)
|
||||
dups = dups.where.not(id: id) unless new_record?
|
||||
dups = dups.where('id != ?', id) unless new_record?
|
||||
|
||||
errors.add :name, I18n.t(:enterprise_name_error, email: dups.first.owner.email) if dups.any?
|
||||
end
|
||||
@@ -531,7 +533,7 @@ class Enterprise < ApplicationRecord
|
||||
# - it grants permissions to all pre-existing hubs
|
||||
# - all producers grant permission to it
|
||||
|
||||
enterprises = owner.owned_enterprises.where.not(enterprises: { id: self })
|
||||
enterprises = owner.owned_enterprises.where('enterprises.id != ?', self)
|
||||
|
||||
# We grant permissions to all pre-existing hubs
|
||||
hub_permissions = [:add_to_order_cycle]
|
||||
@@ -580,7 +582,7 @@ class Enterprise < ApplicationRecord
|
||||
# We avoid an infinite loop and don't need to touch the whole distributor tree.
|
||||
def touch_distributors
|
||||
Enterprise.distributing_products(supplied_products.select(:id)).
|
||||
where.not(enterprises: { id: id }).
|
||||
where('enterprises.id != ?', id).
|
||||
update_all(updated_at: Time.zone.now)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,7 +6,7 @@ class EnterpriseFee < ApplicationRecord
|
||||
acts_as_paranoid
|
||||
|
||||
belongs_to :enterprise
|
||||
belongs_to :tax_category, optional: true, class_name: 'Spree::TaxCategory'
|
||||
belongs_to :tax_category, class_name: 'Spree::TaxCategory'
|
||||
|
||||
has_many :coordinator_fees, dependent: :destroy
|
||||
has_many :order_cycles, through: :coordinator_fees
|
||||
@@ -37,7 +37,7 @@ class EnterpriseFee < ApplicationRecord
|
||||
}
|
||||
|
||||
scope :per_item, lambda {
|
||||
joins(:calculator).where.not(spree_calculators: { type: PER_ORDER_CALCULATORS })
|
||||
joins(:calculator).where('spree_calculators.type NOT IN (?)', PER_ORDER_CALCULATORS)
|
||||
}
|
||||
scope :per_order, lambda {
|
||||
joins(:calculator).where('spree_calculators.type IN (?)', PER_ORDER_CALCULATORS)
|
||||
|
||||
@@ -8,19 +8,19 @@ class EnterpriseGroup < ApplicationRecord
|
||||
acts_as_list
|
||||
|
||||
has_and_belongs_to_many :enterprises, join_table: 'enterprise_groups_enterprises'
|
||||
belongs_to :owner, class_name: 'Spree::User', inverse_of: :owned_groups, optional: true
|
||||
belongs_to :owner, class_name: 'Spree::User', inverse_of: :owned_groups
|
||||
belongs_to :address, class_name: 'Spree::Address'
|
||||
accepts_nested_attributes_for :address
|
||||
validates :address, associated: true
|
||||
validates :address, presence: true, associated: true
|
||||
before_validation :set_undefined_address_fields
|
||||
before_validation :set_unused_address_fields
|
||||
before_validation :sanitize_permalink
|
||||
after_save :unset_undefined_address_fields
|
||||
after_find :unset_undefined_address_fields
|
||||
after_save :unset_undefined_address_fields
|
||||
|
||||
validates :name, presence: true
|
||||
validates :description, presence: true
|
||||
|
||||
before_validation :sanitize_permalink
|
||||
validates :permalink, uniqueness: true, presence: true
|
||||
|
||||
delegate :phone, :address1, :address2, :city, :zipcode, :state, :country, to: :address
|
||||
@@ -46,14 +46,10 @@ class EnterpriseGroup < ApplicationRecord
|
||||
}
|
||||
|
||||
def set_unused_address_fields
|
||||
return if address.blank?
|
||||
|
||||
address.firstname = address.lastname = address.company = I18n.t(:unused)
|
||||
end
|
||||
|
||||
def set_undefined_address_fields
|
||||
return if address.blank?
|
||||
|
||||
address.phone.present? || address.phone = I18n.t(:undefined)
|
||||
address.address1.present? || address.address1 = I18n.t(:undefined)
|
||||
address.city.present? || address.city = I18n.t(:undefined)
|
||||
|
||||
@@ -5,14 +5,15 @@ class EnterpriseRelationship < ApplicationRecord
|
||||
belongs_to :child, class_name: 'Enterprise', touch: true
|
||||
has_many :permissions, class_name: 'EnterpriseRelationshipPermission', dependent: :destroy
|
||||
|
||||
validates :parent, :child, presence: true
|
||||
validates :child_id, uniqueness: {
|
||||
scope: :parent_id,
|
||||
message: I18n.t('validation_msg_relationship_already_established')
|
||||
}
|
||||
|
||||
after_save :update_permissions_of_child_variant_overrides
|
||||
before_destroy :revoke_all_child_variant_overrides
|
||||
before_destroy :destroy_related_exchanges
|
||||
after_save :update_permissions_of_child_variant_overrides
|
||||
|
||||
scope :with_enterprises, -> {
|
||||
joins("
|
||||
@@ -75,7 +76,7 @@ class EnterpriseRelationship < ApplicationRecord
|
||||
if perms.nil?
|
||||
permissions.destroy_all
|
||||
else
|
||||
permissions.where.not(name: perms).destroy_all
|
||||
permissions.where('name NOT IN (?)', perms).destroy_all
|
||||
perms.map { |name| permissions.find_or_initialize_by name: name }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,6 +4,7 @@ class EnterpriseRole < ApplicationRecord
|
||||
belongs_to :user, class_name: "Spree::User"
|
||||
belongs_to :enterprise
|
||||
|
||||
validates :user, :enterprise, presence: true
|
||||
validates :enterprise_id,
|
||||
uniqueness: { scope: :user_id, message: I18n.t(:enterprise_role_uniqueness_error) }
|
||||
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
# shopfront (outgoing products). But the set of shown products can be smaller
|
||||
# than all incoming products.
|
||||
class Exchange < ApplicationRecord
|
||||
self.belongs_to_required_by_default = false
|
||||
|
||||
acts_as_taggable
|
||||
|
||||
belongs_to :order_cycle
|
||||
@@ -90,6 +88,7 @@ class Exchange < ApplicationRecord
|
||||
exchange = dup
|
||||
exchange.order_cycle = new_order_cycle
|
||||
exchange.enterprise_fee_ids = enterprise_fee_ids
|
||||
exchange.tag_ids = tag_ids
|
||||
exchange.save!
|
||||
clone_all_exchange_variants(exchange.id)
|
||||
exchange
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ExchangeFee < ApplicationRecord
|
||||
self.belongs_to_required_by_default = false
|
||||
|
||||
belongs_to :exchange
|
||||
belongs_to :enterprise_fee
|
||||
end
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ExchangeVariant < ApplicationRecord
|
||||
self.belongs_to_required_by_default = false
|
||||
|
||||
belongs_to :exchange
|
||||
belongs_to :variant, class_name: 'Spree::Variant'
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class InventoryItem < ApplicationRecord
|
||||
self.belongs_to_required_by_default = false
|
||||
|
||||
belongs_to :enterprise
|
||||
belongs_to :variant, class_name: "Spree::Variant"
|
||||
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Invoice < ApplicationRecord
|
||||
self.belongs_to_required_by_default = false
|
||||
|
||||
belongs_to :order, class_name: 'Spree::Order'
|
||||
serialize :data, Hash
|
||||
before_validation :serialize_order
|
||||
after_create :cancel_previous_invoices
|
||||
default_scope { order(created_at: :desc) }
|
||||
|
||||
def self.latest
|
||||
reorder(created_at: :desc).first
|
||||
end
|
||||
|
||||
def presenter
|
||||
@presenter ||= Invoice::DataPresenter.new(self)
|
||||
|
||||
@@ -4,8 +4,7 @@ class Invoice
|
||||
class DataPresenter
|
||||
attr_reader :invoice
|
||||
|
||||
delegate :data, to: :invoice
|
||||
delegate :number, :date, to: :invoice, prefix: true
|
||||
delegate :data, :date, to: :invoice
|
||||
|
||||
FINALIZED_NON_SUCCESSFUL_STATES = %w(canceled returned).freeze
|
||||
|
||||
@@ -79,14 +78,14 @@ class Invoice
|
||||
end.sort_by { |tax| tax[:rate_amount] }
|
||||
end
|
||||
|
||||
def display_date
|
||||
I18n.l(invoice_date.to_date, format: :long)
|
||||
end
|
||||
|
||||
def all_tax_adjustments
|
||||
all_eligible_adjustments.select { |a| a.originator_type == 'Spree::TaxRate' }
|
||||
end
|
||||
|
||||
def invoice_date
|
||||
date
|
||||
end
|
||||
|
||||
def paid?
|
||||
data[:payment_state] == 'paid' || data[:payment_state] == 'credit_owed'
|
||||
end
|
||||
|
||||
@@ -24,10 +24,6 @@ class Invoice
|
||||
render_address([address1, address2, city, zipcode, state&.name])
|
||||
end
|
||||
|
||||
def blank?
|
||||
@data.nil?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_address(address_parts)
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
class Invoice
|
||||
class DataPresenter
|
||||
class Distributor < Invoice::DataPresenter::Base
|
||||
attributes :name, :abn, :acn, :logo_url, :display_invoice_logo, :invoice_text, :email_address,
|
||||
:phone
|
||||
attributes :name, :abn, :acn, :logo_url, :display_invoice_logo, :invoice_text, :email_address
|
||||
attributes_with_presenter :contact, :address, :business_address
|
||||
|
||||
def display_invoice_logo?
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
require 'open_food_network/scope_variant_to_hub'
|
||||
|
||||
class OrderCycle < ApplicationRecord
|
||||
self.belongs_to_required_by_default = false
|
||||
|
||||
searchable_attributes :orders_open_at, :orders_close_at, :coordinator_id
|
||||
searchable_scopes :active, :inactive, :active_or_complete, :upcoming, :closed, :not_closed,
|
||||
:dated, :undated, :soonest_opening, :soonest_closing, :most_recently_closed
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class OrderCycleSchedule < ApplicationRecord
|
||||
self.belongs_to_required_by_default = false
|
||||
|
||||
belongs_to :schedule
|
||||
belongs_to :order_cycle
|
||||
end
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ProducerProperty < ApplicationRecord
|
||||
self.belongs_to_required_by_default = false
|
||||
|
||||
belongs_to :producer, class_name: 'Enterprise', touch: true
|
||||
belongs_to :property, class_name: 'Spree::Property'
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ module ProductImport
|
||||
unit_type: :variant_unit_scale,
|
||||
variant_unit_name: :variant_unit_name,
|
||||
tax_category: :tax_category_id,
|
||||
shipping_category: :shipping_category_id
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ module ProductImport
|
||||
relation = VariantOverride.where(hub_id: enterprise_ids)
|
||||
return relation if excluded_items_ids.blank?
|
||||
|
||||
relation.where.not(id: excluded_items_ids)
|
||||
relation.where('id NOT IN (?)', excluded_items_ids)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -287,7 +287,7 @@ module ProductImport
|
||||
end
|
||||
|
||||
def delete_uploaded_file
|
||||
return unless @file.path == Rails.root.join("tmp/product_import").to_s
|
||||
return unless @file.path == Rails.root.join('tmp', 'product_import').to_s
|
||||
|
||||
File.delete(@file)
|
||||
end
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
# This reduces the need to keep Orders in sync with their parent Subscriptions
|
||||
|
||||
class ProxyOrder < ApplicationRecord
|
||||
self.belongs_to_required_by_default = false
|
||||
|
||||
belongs_to :order, class_name: 'Spree::Order'
|
||||
belongs_to :subscription
|
||||
belongs_to :order_cycle
|
||||
@@ -16,7 +14,7 @@ class ProxyOrder < ApplicationRecord
|
||||
scope :active, -> { joins(:order_cycle).merge(OrderCycle.active) }
|
||||
scope :closed, -> { joins(:order_cycle).merge(OrderCycle.closed) }
|
||||
scope :not_closed, -> { joins(:order_cycle).merge(OrderCycle.not_closed) }
|
||||
scope :canceled, -> { where.not(proxy_orders: { canceled_at: nil }) }
|
||||
scope :canceled, -> { where('proxy_orders.canceled_at IS NOT NULL') }
|
||||
scope :not_canceled, -> { where('proxy_orders.canceled_at IS NULL') }
|
||||
scope :placed_and_open, -> {
|
||||
joins(:order).not_closed
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ReportRenderingOptions < ApplicationRecord
|
||||
self.belongs_to_required_by_default = false
|
||||
|
||||
belongs_to :user, class_name: "Spree::User"
|
||||
serialize :options, Hash
|
||||
end
|
||||
|
||||
@@ -234,6 +234,7 @@ module Spree
|
||||
can [:admin, :index, :read, :create, :edit, :update, :destroy], Spree::Image
|
||||
|
||||
can [:admin, :index, :read, :search], Spree::Taxon
|
||||
can [:admin, :index, :read, :create, :edit], Spree::Classification
|
||||
|
||||
can [:admin, :index, :guide, :import, :save, :save_data,
|
||||
:validate_data, :reset_absent_products], ProductImport::ProductImporter
|
||||
|
||||
@@ -4,8 +4,6 @@ module Spree
|
||||
class Address < ApplicationRecord
|
||||
include AddressDisplay
|
||||
|
||||
self.belongs_to_required_by_default = false
|
||||
|
||||
searchable_attributes :firstname, :lastname, :phone, :full_name
|
||||
searchable_associations :country, :state
|
||||
|
||||
|
||||
@@ -31,8 +31,6 @@ module Spree
|
||||
class Adjustment < ApplicationRecord
|
||||
extend Spree::LocalizedNumber
|
||||
|
||||
self.belongs_to_required_by_default = false
|
||||
|
||||
# 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.
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
module Spree
|
||||
class Asset < ApplicationRecord
|
||||
self.belongs_to_required_by_default = false
|
||||
|
||||
belongs_to :viewable, polymorphic: true, touch: true
|
||||
acts_as_list scope: :viewable
|
||||
end
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
module Spree
|
||||
class Calculator < ApplicationRecord
|
||||
self.belongs_to_required_by_default = false
|
||||
|
||||
belongs_to :calculable, polymorphic: true
|
||||
|
||||
# This method must be overriden in concrete calculator.
|
||||
|
||||
21
app/models/spree/classification.rb
Normal file
21
app/models/spree/classification.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Spree
|
||||
class Classification < ApplicationRecord
|
||||
self.table_name = 'spree_products_taxons'
|
||||
belongs_to :product, class_name: "Spree::Product", touch: true
|
||||
belongs_to :taxon, class_name: "Spree::Taxon", touch: true
|
||||
|
||||
before_destroy :dont_destroy_if_primary_taxon
|
||||
|
||||
private
|
||||
|
||||
def dont_destroy_if_primary_taxon
|
||||
return unless product.primary_taxon == taxon
|
||||
|
||||
errors.add :base, I18n.t(:spree_classification_primary_taxon_error, taxon: taxon.name,
|
||||
product: product.name)
|
||||
throw :abort
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
module Spree
|
||||
class CreditCard < ApplicationRecord
|
||||
self.belongs_to_required_by_default = false
|
||||
|
||||
belongs_to :payment_method
|
||||
belongs_to :user
|
||||
|
||||
@@ -23,7 +21,7 @@ module Spree
|
||||
after_create :ensure_single_default_card
|
||||
after_save :ensure_single_default_card, if: :default_card_needs_updating?
|
||||
|
||||
scope :with_payment_profile, -> { where.not(gateway_customer_profile_id: nil) }
|
||||
scope :with_payment_profile, -> { where('gateway_customer_profile_id IS NOT NULL') }
|
||||
|
||||
# needed for some of the ActiveMerchant gateways (eg. SagePay)
|
||||
alias_attribute :brand, :cc_type
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user