Compare commits

..

2 Commits

Author SHA1 Message Date
Maikel Linke
f0ee4aab01 Restore old pagination API for products
It's still used by the inventory page. This is an easy fix that I can
deploy without risk. A rewrite of the inventory pagination should
follow.
2019-09-09 14:51:44 +10:00
Maikel Linke
452593b6f1 Ignore block length cop for feature and scenario
They are typically long and that's okay, same with `describe` and `it`.
2019-09-09 14:51:44 +10:00
688 changed files with 11085 additions and 32761 deletions

66
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,66 @@
<!-- Provide a general summary of the issue in the Title above.
If your issue is not a bug, please use the Feature template instead:
https://github.com/openfoodfoundation/openfoodnetwork/wiki/Feature-template
-->
## Description
<!-- Provide a more detailed introduction to the issue itself, and why you consider it to be a bug -->
## Expected Behavior
<!-- Tell us what should happen -->
## Actual Behavior
<!-- Tell us what happens instead -->
## Steps to Reproduce
<!-- Provide an unambiguous set of steps to reproduce this bug -->
<!-- Include code to reproduce if relevant -->
1.
2.
3.
4.
## Animated Gif/Screenshot
<!-- Provide a screenshot or brief animated gif reproducing the bug. Linux users can use
[Peek](https://github.com/phw/peek#ubuntu) while Mac users can use [Recordit](http://recordit.co/) -->
## Context
<!-- How has this bug affected you? What were you trying to accomplish? -->
## Severity
<!-- Assign a label and explain the impact.
bug-s1: a critical feature is broken: checkout, payments, signup, login
bug-s2: a non-critical feature is broken, no workaround
bug-s3: a feature is broken but there is a workaround
bug-s4: it's annoying, but you can use it
bug-s5: we can live with it, only a few users impacted
https://github.com/openfoodfoundation/openfoodnetwork/wiki/Bug-severity
-->
## Your Environment
<!-- Include relevant details about the environment you experienced the bug in -->
* Version used:
* Browser name and version:
* Operating System and version (desktop or mobile):
## Possible Fix
<!-- Not obligatory, but suggest a fix or reason for the bug -->

View File

@@ -9,7 +9,6 @@ assignees: ''
## Description
<!-- Provide a more detailed introduction to the issue itself, and why you consider it to be a bug -->
<!-- How has this bug affected you? What were you trying to accomplish? -->
## Expected Behavior
@@ -23,8 +22,6 @@ assignees: ''
## Steps to Reproduce
<!-- Provide an unambiguous set of steps to reproduce this bug -->
<!-- Include code to reproduce if relevant -->
<!-- Include links -->
<!-- Include user ID -->
1.
2.
@@ -32,11 +29,13 @@ assignees: ''
4.
## Animated Gif/Screenshot
<!-- Provide a screenshot or brief video reproducing the bug. -->
<!-- Please try to have the dev tools opened on the network tab (press F12 to open the devtools of your browser -->
<!-- Provide a screenshot or brief animated gif reproducing the bug. Linux users can use
[Peek](https://github.com/phw/peek#ubuntu) while Mac users can use [Recordit](http://recordit.co/) -->
## Context
<!-- How has this bug affected you? What were you trying to accomplish? -->
## Workaround
<!-- Include a workaround for this bug (if relevant) -->
## Severity
<!-- Assign a label and explain the impact.
@@ -56,6 +55,7 @@ https://github.com/openfoodfoundation/openfoodnetwork/wiki/Bug-severity
* Version used:
* Browser name and version:
* Operating System and version (desktop or mobile):
* OFN Platform instance where you discovered the bug, and which version of the software they are using.
## Possible Fix
<!-- Not obligatory, but suggest a fix or reason for the bug -->

View File

@@ -1,19 +0,0 @@
---
name: Release task
about: Track the process of a new release
title: ''
labels: ''
assignees: ''
---
Steps:
- [ ] Include translations
- [ ] Draft: https://github.com/openfoodfoundation/openfoodnetwork/releases/new <!-- replace the URL -->
- [ ] Test: https://semaphoreci.com/openfoodfoundation/openfoodnetwork-2/branches/master <!-- replace the URL -->
- [ ] Publish and notify #global-community
- [ ] Deploy and notify #instance-managers
- [ ] Nudge next release manager
The full process is described at https://github.com/openfoodfoundation/openfoodnetwork/wiki/Releasing.

View File

@@ -14,12 +14,5 @@ assignees: ''
**- I want to be able to do:** (specify the desired behavior)
(Link to others issues or resources to provide context > only if really necessary). -->
## Acceptance Criteria & Tests
<!-- Document the outcomes that need to be achieved before this component can be considered complete.
-->
<!-- Provide an unambiguous set of steps a tester should do to validate the PR that will solve this issue -->
1.
2.
3.
4.
## Acceptance Criteria
<!-- Document the outcomes that need to be achieved before this component can be considered complete. -->

View File

@@ -4,7 +4,6 @@
#
# The configuration is split into three files. Look into those files for more details.
#
require: rubocop-rails
inherit_from:
# The automatically generated todo list to ignore all current violations.

View File

@@ -14,43 +14,53 @@
# rubocop > rubo.log
# # inspect log file to see which cops are failing
# # copy cop configurations and add Exclude parameter
# grep ExampleCop rubo.log | cut -d ":" -f 1 | sort -u | while read f; do echo " - $f"; done >> .rubocop.yml
# grep ExampleCop rubo.log | cut -d ":" -f 1 | sort -u >> .rubocop.yml
# # use vim to add `- ` before each line
#
# This process probably doesn't need repeating. Otherwise there is plenty
# of room for improvements and automation.
Layout/LineLength:
Metrics/LineLength:
Max: 100
Exclude:
- Gemfile
- app/controllers/admin/bulk_line_items_controller.rb
- app/controllers/admin/contents_controller.rb
- app/controllers/admin/customers_controller.rb
- app/controllers/admin/enterprises_controller.rb
- app/controllers/admin/enterprise_fees_controller.rb
- app/controllers/admin/enterprise_groups_controller.rb
- app/controllers/admin/enterprise_relationships_controller.rb
- app/controllers/admin/enterprise_roles_controller.rb
- app/controllers/admin/enterprises_controller.rb
- app/controllers/admin/inventory_items_controller.rb
- app/controllers/admin/manager_invitations_controller.rb
- app/controllers/admin/order_cycles_controller.rb
- app/controllers/admin/product_import_controller.rb
- app/controllers/admin/proxy_orders_controller.rb
- app/controllers/admin/schedules_controller.rb
- app/controllers/admin/subscriptions_controller.rb
- app/controllers/admin/variant_overrides_controller.rb
- app/controllers/api/enterprise_attachment_controller.rb
- app/controllers/api/order_cycles_controller.rb
- app/controllers/api/product_images_controller.rb
- app/controllers/application_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/spree/admin/adjustments_controller_decorator.rb
- app/controllers/spree/admin/base_controller_decorator.rb
- app/controllers/spree/admin/orders_controller_decorator.rb
- app/controllers/spree/admin/payments_controller_decorator.rb
- app/controllers/spree/admin/payment_methods_controller_decorator.rb
- app/controllers/spree/admin/reports_controller_decorator.rb
- app/controllers/spree/api/products_controller_decorator.rb
- app/controllers/spree/credit_cards_controller.rb
- app/controllers/spree/orders_controller_decorator.rb
- app/controllers/spree/paypal_controller_decorator.rb
- app/controllers/stripe/callbacks_controller.rb
- app/helpers/admin/injection_helper.rb
- app/helpers/angular_form_builder.rb
- app/helpers/angular_form_helper.rb
- app/helpers/checkout_helper.rb
- app/helpers/enterprises_helper.rb
- app/helpers/footer_links_helper.rb
- app/helpers/injection_helper.rb
- app/helpers/markdown_helper.rb
- app/helpers/order_cycles_helper.rb
@@ -79,6 +89,7 @@ Layout/LineLength:
- app/models/proxy_order.rb
- app/models/schedule.rb
- app/models/spree/ability_decorator.rb
- app/models/spree/adjustment_decorator.rb
- app/models/spree/app_configuration_decorator.rb
- app/models/spree/calculator/default_tax_decorator.rb
- app/models/spree/classification_decorator.rb
@@ -89,14 +100,28 @@ Layout/LineLength:
- app/models/spree/payment_decorator.rb
- app/models/spree/payment_method_decorator.rb
- app/models/spree/product_decorator.rb
- app/models/spree/shipment_decorator.rb
- app/models/spree/shipping_method_decorator.rb
- app/models/spree/tax_rate_decorator.rb
- app/models/spree/taxon_decorator.rb
- app/models/spree/user.rb
- app/models/spree/user_decorator.rb
- app/models/spree/variant_decorator.rb
- app/models/subscription.rb
- app/models/variant_override.rb
- app/models/variant_override_set.rb
- app/overrides/add_enterprise_fees_to_admin_configurations_menu.rb
- app/serializers/api/admin/basic_enterprise_serializer.rb
- app/serializers/api/admin/enterprise_fee_serializer.rb
- app/serializers/api/admin/enterprise_serializer.rb
- app/serializers/api/admin/exchange_serializer.rb
- app/serializers/api/admin/for_order_cycle/enterprise_serializer.rb
- app/serializers/api/admin/index_enterprise_serializer.rb
- app/serializers/api/admin/index_order_cycle_serializer.rb
- app/serializers/api/admin/line_item_serializer.rb
- app/serializers/api/admin/order_cycle_serializer.rb
- app/serializers/api/admin/subscription_serializer.rb
- app/serializers/api/admin/tag_rule_serializer.rb
- app/serializers/api/admin/variant_override_serializer.rb
- app/services/cart_service.rb
- app/services/default_stock_location.rb
- app/services/embedded_page_service.rb
@@ -104,6 +129,11 @@ Layout/LineLength:
- app/services/order_factory.rb
- app/services/subscriptions_count.rb
- app/services/variants_stock_levels.rb
- app/views/json/_groups.rabl
- app/views/json/_producer.rabl
- app/views/json/partials/_enterprise.rabl
- app/views/spree/api/products/bulk_show.v1.rabl
- app/views/spree/api/variants/bulk_show.v1.rabl
- engines/web/app/helpers/web/cookies_policy_helper.rb
- lib/discourse/single_sign_on.rb
- lib/open_food_network/available_payment_method_filter.rb
@@ -114,17 +144,26 @@ Layout/LineLength:
- lib/open_food_network/enterprise_issue_validator.rb
- lib/open_food_network/group_buy_report.rb
- lib/open_food_network/lettuce_share_report.rb
- lib/open_food_network/order_and_distributor_report.rb
- lib/open_food_network/order_cycle_form_applicator.rb
- lib/open_food_network/order_cycle_management_report.rb
- lib/open_food_network/order_grouper.rb
- lib/open_food_network/orders_and_fulfillments_report.rb
- lib/open_food_network/payments_report.rb
- lib/open_food_network/permalink_generator.rb
- lib/open_food_network/products_cache.rb
- lib/open_food_network/products_renderer.rb
- lib/open_food_network/reports/bulk_coop_allocation_report.rb
- lib/open_food_network/reports/line_items.rb
- lib/open_food_network/sales_tax_report.rb
- lib/open_food_network/users_and_enterprises_report.rb
- lib/open_food_network/variant_and_line_item_naming.rb
- lib/open_food_network/xero_invoices_report.rb
- lib/spree/core/controller_helpers/respond_with_decorator.rb
- lib/spree/localized_number.rb
- lib/spree/product_filters.rb
- lib/stripe/profile_storer.rb
- lib/tasks/cache.rake
- lib/tasks/data.rake
- lib/tasks/enterprises.rake
- spec/controllers/admin/bulk_line_items_controller_spec.rb
@@ -141,16 +180,11 @@ Layout/LineLength:
- spec/controllers/admin/subscription_line_items_controller_spec.rb
- spec/controllers/admin/subscriptions_controller_spec.rb
- spec/controllers/admin/variant_overrides_controller_spec.rb
- spec/controllers/api/base_controller_spec.rb
- spec/controllers/api/exchange_products_controller_spec.rb
- spec/controllers/api/logos_controller_spec.rb
- spec/controllers/api/order_cycles_controller_spec.rb
- spec/controllers/api/orders_controller_spec.rb
- spec/controllers/api/product_images_controller_spec.rb
- spec/controllers/api/products_controller_spec.rb
- spec/controllers/api/promo_images_controller_spec.rb
- spec/controllers/api/shipments_controller_spec.rb
- spec/controllers/api/variants_controller_spec.rb
- spec/controllers/cart_controller_spec.rb
- spec/controllers/checkout_controller_spec.rb
- spec/controllers/enterprises_controller_spec.rb
@@ -163,9 +197,12 @@ Layout/LineLength:
- spec/controllers/spree/admin/orders_controller_spec.rb
- spec/controllers/spree/admin/payment_methods_controller_spec.rb
- spec/controllers/spree/admin/payments_controller_spec.rb
- spec/controllers/spree/admin/products_controller_spec.rb
- spec/controllers/spree/admin/reports_controller_spec.rb
- spec/controllers/spree/admin/variants_controller_spec.rb
- spec/controllers/spree/api/line_items_controller_spec.rb
- spec/controllers/spree/api/products_controller_spec.rb
- spec/controllers/spree/api/shipments_controller_spec.rb
- spec/controllers/spree/api/variants_controller_spec.rb
- spec/controllers/spree/credit_cards_controller_spec.rb
- spec/controllers/spree/orders_controller_spec.rb
- spec/controllers/spree/user_sessions_controller_spec.rb
@@ -173,6 +210,7 @@ Layout/LineLength:
- spec/controllers/stripe/callbacks_controller_spec.rb
- spec/controllers/stripe/webhooks_controller_spec.rb
- spec/controllers/user_confirmations_controller_spec.rb
- spec/controllers/user_registrations_controller_spec.rb
- spec/features/admin/adjustments_spec.rb
- spec/features/admin/bulk_order_management_spec.rb
- spec/features/admin/bulk_product_update_spec.rb
@@ -197,7 +235,6 @@ Layout/LineLength:
- spec/features/admin/shipping_methods_spec.rb
- spec/features/admin/subscriptions_spec.rb
- spec/features/admin/tag_rules_spec.rb
- spec/features/admin/users_spec.rb
- spec/features/admin/variant_overrides_spec.rb
- spec/features/consumer/account/cards_spec.rb
- spec/features/consumer/account/settings_spec.rb
@@ -225,13 +262,17 @@ Layout/LineLength:
- spec/helpers/order_cycles_helper_spec.rb
- spec/helpers/spree/admin/base_helper_spec.rb
- spec/jobs/confirm_order_job_spec.rb
- spec/jobs/products_cache_integrity_checker_job_spec.rb
- spec/jobs/refresh_products_cache_job_spec.rb
- spec/jobs/subscription_confirm_job_spec.rb
- spec/jobs/subscription_placement_job_spec.rb
- spec/lib/open_food_network/address_finder_spec.rb
- spec/lib/open_food_network/bulk_coop_report_spec.rb
- spec/lib/open_food_network/cached_products_renderer_spec.rb
- spec/lib/open_food_network/customers_report_spec.rb
- spec/lib/open_food_network/enterprise_fee_applicator_spec.rb
- spec/lib/open_food_network/enterprise_fee_calculator_spec.rb
- spec/lib/open_food_network/enterprise_injection_data_spec.rb
- spec/lib/open_food_network/group_buy_report_spec.rb
- spec/lib/open_food_network/lettuce_share_report_spec.rb
- spec/lib/open_food_network/option_value_namer_spec.rb
@@ -243,6 +284,8 @@ Layout/LineLength:
- spec/lib/open_food_network/packing_report_spec.rb
- spec/lib/open_food_network/permissions_spec.rb
- spec/lib/open_food_network/products_and_inventory_report_spec.rb
- spec/lib/open_food_network/products_cache_spec.rb
- spec/lib/open_food_network/products_renderer_spec.rb
- spec/lib/open_food_network/proxy_order_syncer_spec.rb
- spec/lib/open_food_network/scope_variant_to_hub_spec.rb
- spec/lib/open_food_network/subscription_payment_updater_spec.rb
@@ -255,7 +298,6 @@ Layout/LineLength:
- spec/mailers/order_mailer_spec.rb
- spec/mailers/producer_mailer_spec.rb
- spec/mailers/subscription_mailer_spec.rb
- spec/models/calculator/weight_spec.rb
- spec/models/column_preference_spec.rb
- spec/models/concerns/order_shipment_spec.rb
- spec/models/concerns/product_stock_spec.rb
@@ -277,11 +319,11 @@ Layout/LineLength:
- spec/models/spree/calculator/price_sack_spec.rb
- spec/models/spree/classification_spec.rb
- spec/models/spree/gateway/stripe_connect_spec.rb
- spec/models/spree/image_spec.rb
- spec/models/spree/line_item_spec.rb
- spec/models/spree/order_spec.rb
- spec/models/spree/payment_method_spec.rb
- spec/models/spree/payment_spec.rb
- spec/models/spree/product_set_spec.rb
- spec/models/spree/product_spec.rb
- spec/models/spree/property_spec.rb
- spec/models/spree/shipping_method_spec.rb
@@ -300,27 +342,22 @@ Layout/LineLength:
- spec/performance/shop_controller_spec.rb
- spec/requests/checkout/failed_checkout_spec.rb
- spec/requests/embedded_shopfronts_headers_spec.rb
- spec/serializers/api/admin/customer_serializer_spec.rb
- spec/serializers/api/admin/exchange_serializer_spec.rb
- spec/serializers/api/admin/for_order_cycle/enterprise_serializer_spec.rb
- spec/serializers/api/admin/for_order_cycle/supplied_product_serializer_spec.rb
- spec/serializers/api/admin/order_cycle_serializer_spec.rb
- spec/serializers/api/admin/subscription_customer_serializer_spec.rb
- spec/serializers/api/admin/variant_override_serializer_spec.rb
- spec/serializers/api/current_order_serializer_spec.rb
- spec/requests/shop_spec.rb
- spec/serializers/admin/customer_serializer_spec.rb
- spec/serializers/admin/exchange_serializer_spec.rb
- spec/serializers/admin/for_order_cycle/enterprise_serializer_spec.rb
- spec/serializers/admin/for_order_cycle/supplied_product_serializer_spec.rb
- spec/serializers/admin/subscription_customer_serializer_spec.rb
- spec/serializers/admin/variant_override_serializer_spec.rb
- spec/serializers/api/enterprise_shopfront_serializer_spec.rb
- spec/serializers/api/order_serializer_spec.rb
- spec/serializers/current_order_serializer_spec.rb
- spec/serializers/order_serializer_spec.rb
- spec/services/cart_service_spec.rb
- spec/services/embedded_page_service_spec.rb
- spec/services/exchange_products_renderer_spec.rb
- spec/services/order_cycle_distributed_products_spec.rb
- spec/services/order_cycle_distributed_variants_spec.rb
- spec/services/order_cycle_form_spec.rb
- spec/services/order_factory_spec.rb
- spec/services/order_syncer_spec.rb
- spec/services/permissions/order_spec.rb
- spec/services/product_tag_rules_filterer_spec.rb
- spec/services/products_renderer_spec.rb
- spec/services/subscription_estimator_spec.rb
- spec/services/subscription_form_spec.rb
- spec/services/subscription_validator_spec.rb
@@ -341,8 +378,8 @@ Metrics/AbcSize:
Exclude:
- app/controllers/admin/bulk_line_items_controller.rb
- app/controllers/admin/customers_controller.rb
- app/controllers/admin/enterprise_fees_controller.rb
- app/controllers/admin/enterprises_controller.rb
- app/controllers/admin/enterprise_fees_controller.rb
- app/controllers/admin/order_cycles_controller.rb
- app/controllers/admin/product_import_controller.rb
- app/controllers/admin/schedules_controller.rb
@@ -350,37 +387,28 @@ Metrics/AbcSize:
- app/controllers/admin/subscription_line_items_controller.rb
- app/controllers/admin/subscriptions_controller.rb
- app/controllers/api/enterprises_controller.rb
- app/controllers/api/order_cycles_controller.rb
- app/controllers/api/product_images_controller.rb
- app/controllers/api/products_controller.rb
- app/controllers/api/shipments_controller.rb
- app/controllers/api/taxons_controller.rb
- app/controllers/api/variants_controller.rb
- app/controllers/base_controller.rb
- app/controllers/cart_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/discourse_sso_controller.rb
- app/controllers/enterprises_controller.rb
- app/controllers/spree/admin/adjustments_controller_decorator.rb
- app/controllers/spree/admin/image_settings_controller.rb
- app/controllers/spree/admin/orders/customer_details_controller_decorator.rb
- app/controllers/spree/admin/orders_controller_decorator.rb
- app/controllers/spree/admin/overview_controller.rb
- app/controllers/spree/admin/payment_methods_controller.rb
- app/controllers/spree/admin/overview_controller_decorator.rb
- app/controllers/spree/admin/payments_controller_decorator.rb
- app/controllers/spree/admin/reports_controller.rb
- app/controllers/spree/admin/resource_controller.rb
- app/controllers/spree/admin/products_controller.rb
- app/controllers/spree/admin/payment_methods_controller_decorator.rb
- app/controllers/spree/admin/products_controller_decorator.rb
- app/controllers/spree/admin/reports_controller_decorator.rb
- app/controllers/spree/admin/search_controller_decorator.rb
- app/controllers/spree/admin/taxons_controller.rb
- app/controllers/spree/admin/users_controller.rb
- app/controllers/spree/admin/variants_controller.rb
- app/controllers/spree/checkout_controller.rb
- app/controllers/spree/admin/variants_controller_decorator.rb
- app/controllers/spree/api/products_controller_decorator.rb
- app/controllers/spree/api/shipments_controller_decorator.rb
- app/controllers/spree/credit_cards_controller.rb
- app/controllers/spree/orders_controller.rb
- app/controllers/spree/user_passwords_controller.rb
- app/controllers/spree/user_registrations_controller.rb
- app/controllers/spree/user_sessions_controller.rb
- app/controllers/spree/users_controller.rb
- app/controllers/spree/orders_controller_decorator.rb
- app/controllers/spree/user_sessions_controller_decorator.rb
- app/controllers/stripe/callbacks_controller.rb
- app/controllers/user_confirmations_controller.rb
- app/controllers/user_passwords_controller.rb
@@ -388,7 +416,6 @@ Metrics/AbcSize:
- app/helpers/checkout_helper.rb
- app/helpers/i18n_helper.rb
- app/helpers/order_cycles_helper.rb
- app/helpers/spree/admin/navigation_helper_decorator.rb
- app/helpers/spree/orders_helper.rb
- app/jobs/subscription_placement_job.rb
- app/mailers/producer_mailer.rb
@@ -410,7 +437,6 @@ Metrics/AbcSize:
- app/models/spree/product_decorator.rb
- app/models/spree/taxon_decorator.rb
- app/serializers/api/admin/enterprise_serializer.rb
- app/serializers/api/admin/order_cycle_serializer.rb
- app/serializers/api/product_serializer.rb
- app/serializers/api/variant_serializer.rb
- app/services/cart_service.rb
@@ -428,30 +454,29 @@ Metrics/AbcSize:
- lib/open_food_network/order_cycle_form_applicator.rb
- lib/open_food_network/order_cycle_management_report.rb
- lib/open_food_network/order_cycle_permissions.rb
- lib/open_food_network/orders_and_fulfillments_report.rb
- lib/open_food_network/packing_report.rb
- lib/open_food_network/payments_report.rb
- lib/open_food_network/permissions.rb
- lib/open_food_network/products_and_inventory_report.rb
- lib/open_food_network/rack_request_blocker.rb
- lib/open_food_network/reports/line_items.rb
- lib/open_food_network/sales_tax_report.rb
- lib/open_food_network/users_and_enterprises_report.rb
- lib/open_food_network/variant_and_line_item_naming.rb
- lib/open_food_network/xero_invoices_report.rb
- lib/spree/api/controller_setup.rb
- lib/spree/core/controller_helpers/respond_with_decorator.rb
- lib/spree/localized_number.rb
- lib/stripe/account_connector.rb
- lib/tasks/enterprises.rake
- lib/tasks/sample_data/product_factory.rb
- spec/controllers/spree/api/shipments_controller_spec.rb
- spec/features/admin/product_import_spec.rb
- spec/features/admin/reports_spec.rb
- spec/features/admin/subscriptions_spec.rb
- spec/features/consumer/shopping/checkout_paypal_spec.rb
- spec/features/consumer/shopping/checkout_spec.rb
- spec/features/consumer/shopping/variant_overrides_spec.rb
- spec/models/enterprise_spec.rb
- spec/models/product_importer_spec.rb
- spec/services/restart_checkout_spec.rb
- spec/support/performance_helper.rb
Metrics/BlockLength:
@@ -471,14 +496,8 @@ Metrics/BlockLength:
]
Exclude:
- lib/tasks/data.rake
- lib/tasks/dev.rake
- spec/controllers/spree/admin/invoices_controller_spec.rb
- spec/factories.rb
- spec/factories/enterprise_factory.rb
- spec/factories/order_cycle_factory.rb
- spec/factories/order_factory.rb
- spec/factories/product_factory.rb
- spec/factories/shipping_method_factory.rb
- spec/factories/subscription_factory.rb
- spec/factories/variant_factory.rb
- spec/features/admin/orders_spec.rb
- spec/features/consumer/shopping/embedded_shopfronts_spec.rb
@@ -492,12 +511,11 @@ Metrics/BlockLength:
Metrics/CyclomaticComplexity:
Max: 6
Exclude:
- app/controllers/admin/enterprise_fees_controller.rb
- app/controllers/admin/enterprises_controller.rb
- app/controllers/admin/enterprise_fees_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/spree/admin/payments_controller_decorator.rb
- app/controllers/spree/admin/taxons_controller.rb
- app/controllers/spree/orders_controller.rb
- app/controllers/spree/orders_controller_decorator.rb
- app/helpers/checkout_helper.rb
- app/helpers/i18n_helper.rb
- app/helpers/order_cycles_helper.rb
@@ -514,6 +532,7 @@ Metrics/CyclomaticComplexity:
- lib/discourse/single_sign_on.rb
- lib/open_food_network/bulk_coop_report.rb
- lib/open_food_network/enterprise_issue_validator.rb
- lib/open_food_network/orders_and_fulfillments_report.rb
- lib/spree/core/controller_helpers/order_decorator.rb
- lib/spree/core/controller_helpers/respond_with_decorator.rb
- lib/spree/localized_number.rb
@@ -523,11 +542,9 @@ Metrics/PerceivedComplexity:
Max: 7
Exclude:
- app/controllers/admin/enterprises_controller.rb
- app/controllers/api/variants_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/spree/admin/payments_controller_decorator.rb
- app/controllers/spree/admin/taxons_controller.rb
- app/controllers/spree/orders_controller.rb
- app/controllers/spree/orders_controller_decorator.rb
- app/helpers/checkout_helper.rb
- app/helpers/i18n_helper.rb
- app/helpers/order_cycles_helper.rb
@@ -540,6 +557,7 @@ Metrics/PerceivedComplexity:
- lib/discourse/single_sign_on.rb
- lib/open_food_network/bulk_coop_report.rb
- lib/open_food_network/enterprise_issue_validator.rb
- lib/open_food_network/orders_and_fulfillments_report.rb
- lib/spree/core/controller_helpers/order_decorator.rb
- lib/spree/core/controller_helpers/respond_with_decorator.rb
- lib/spree/localized_number.rb
@@ -549,35 +567,25 @@ Metrics/MethodLength:
Max: 10
Exclude:
- app/controllers/admin/customers_controller.rb
- app/controllers/admin/enterprise_fees_controller.rb
- app/controllers/admin/enterprises_controller.rb
- app/controllers/admin/enterprise_fees_controller.rb
- app/controllers/admin/manager_invitations_controller.rb
- app/controllers/admin/order_cycles_controller.rb
- app/controllers/admin/stripe_accounts_controller.rb
- app/controllers/admin/subscriptions_controller.rb
- app/controllers/api/products_controller.rb
- app/controllers/api/shipments_controller.rb
- app/controllers/api/taxons_controller.rb
- app/controllers/api/variants_controller.rb
- app/controllers/base_controller.rb
- app/controllers/cart_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/shop_controller.rb
- app/controllers/spree/admin/image_settings_controller.rb
- app/controllers/spree/admin/orders/customer_details_controller_decorator.rb
- app/controllers/spree/admin/payment_methods_controller.rb
- app/controllers/spree/admin/payments_controller_decorator.rb
- app/controllers/spree/admin/reports_controller.rb
- app/controllers/spree/admin/resource_controller.rb
- app/controllers/spree/admin/products_controller.rb
- app/controllers/spree/admin/payment_methods_controller_decorator.rb
- app/controllers/spree/admin/products_controller_decorator.rb
- app/controllers/spree/admin/reports_controller_decorator.rb
- app/controllers/spree/admin/search_controller_decorator.rb
- app/controllers/spree/admin/tax_categories_controller.rb
- app/controllers/spree/admin/taxons_controller.rb
- app/controllers/spree/admin/users_controller.rb
- app/controllers/spree/credit_cards_controller.rb
- app/controllers/spree/orders_controller.rb
- app/controllers/spree/user_registrations_controller.rb
- app/controllers/spree/user_sessions_controller.rb
- app/controllers/spree/orders_controller_decorator.rb
- app/controllers/spree/user_sessions_controller_decorator.rb
- app/controllers/stripe/callbacks_controller.rb
- app/controllers/user_confirmations_controller.rb
- app/controllers/user_passwords_controller.rb
@@ -619,10 +627,12 @@ Metrics/MethodLength:
- lib/open_food_network/order_cycle_management_report.rb
- lib/open_food_network/order_cycle_permissions.rb
- lib/open_food_network/order_grouper.rb
- lib/open_food_network/orders_and_fulfillments_report.rb
- lib/open_food_network/packing_report.rb
- lib/open_food_network/payments_report.rb
- lib/open_food_network/permissions.rb
- lib/open_food_network/products_and_inventory_report.rb
- lib/open_food_network/products_renderer.rb
- lib/open_food_network/rack_request_blocker.rb
- lib/open_food_network/reports/bulk_coop_allocation_report.rb
- lib/open_food_network/reports/bulk_coop_supplier_report.rb
@@ -630,12 +640,11 @@ Metrics/MethodLength:
- lib/open_food_network/sales_tax_report.rb
- lib/open_food_network/users_and_enterprises_report.rb
- lib/open_food_network/xero_invoices_report.rb
- lib/spree/api/controller_setup.rb
- lib/spree/core/controller_helpers/respond_with_decorator.rb
- lib/spree/localized_number.rb
- lib/stripe/profile_storer.rb
- lib/tasks/sample_data/product_factory.rb
- spec/features/consumer/shopping/checkout_paypal_spec.rb
- spec/features/consumer/shopping/checkout_spec.rb
- spec/features/consumer/shopping/variant_overrides_spec.rb
- spec/models/product_importer_spec.rb
- spec/support/request/authentication_workflow.rb
@@ -646,22 +655,13 @@ Metrics/ClassLength:
- app/controllers/admin/enterprises_controller.rb
- app/controllers/admin/order_cycles_controller.rb
- app/controllers/admin/subscriptions_controller.rb
- app/controllers/api/products_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/spree/admin/base_controller.rb
- app/controllers/spree/admin/payment_methods_controller.rb
- app/controllers/spree/admin/reports_controller.rb
- app/controllers/spree/admin/resource_controller.rb
- app/controllers/spree/admin/products_controller.rb
- app/controllers/spree/admin/users_controller.rb
- app/controllers/spree/orders_controller.rb
- app/models/enterprise.rb
- app/models/order_cycle.rb
- app/models/product_import/entry_processor.rb
- app/models/product_import/entry_validator.rb
- app/models/product_import/product_importer.rb
- app/models/spree/ability_decorator.rb
- app/models/spree/user.rb
- app/serializers/api/cached_enterprise_serializer.rb
- app/serializers/api/enterprise_shopfront_serializer.rb
- app/services/cart_service.rb
@@ -671,24 +671,24 @@ Metrics/ClassLength:
- lib/open_food_network/order_cycle_form_applicator.rb
- lib/open_food_network/order_cycle_management_report.rb
- lib/open_food_network/order_cycle_permissions.rb
- lib/open_food_network/orders_and_fulfillments_report.rb
- lib/open_food_network/packing_report.rb
- lib/open_food_network/payments_report.rb
- lib/open_food_network/permissions.rb
- lib/open_food_network/users_and_enterprises_report.rb
- lib/open_food_network/products_cache.rb
- lib/open_food_network/xero_invoices_report.rb
Metrics/ModuleLength:
Max: 100
Exclude:
- app/helpers/admin/injection_helper.rb
- app/helpers/injection_helper.rb
- lib/open_food_network/column_preference_defaults.rb
- spec/controllers/admin/enterprises_controller_spec.rb
- spec/controllers/admin/order_cycles_controller_spec.rb
- spec/controllers/api/order_cycles_controller_spec.rb
- spec/controllers/api/orders_controller_spec.rb
- spec/controllers/spree/admin/payment_methods_controller_spec.rb
- spec/controllers/spree/api/products_controller_spec.rb
- spec/lib/open_food_network/address_finder_spec.rb
- spec/lib/open_food_network/cached_products_renderer_spec.rb
- spec/lib/open_food_network/customers_report_spec.rb
- spec/lib/open_food_network/enterprise_fee_calculator_spec.rb
- spec/lib/open_food_network/option_value_namer_spec.rb
@@ -697,6 +697,7 @@ Metrics/ModuleLength:
- spec/lib/open_food_network/order_grouper_spec.rb
- spec/lib/open_food_network/permissions_spec.rb
- spec/lib/open_food_network/products_and_inventory_report_spec.rb
- spec/lib/open_food_network/products_cache_spec.rb
- spec/lib/open_food_network/proxy_order_syncer_spec.rb
- spec/lib/open_food_network/scope_variant_to_hub_spec.rb
- spec/lib/open_food_network/subscription_payment_updater_spec.rb
@@ -708,7 +709,6 @@ Metrics/ModuleLength:
- spec/models/spree/payment_spec.rb
- spec/models/spree/product_spec.rb
- spec/models/spree/variant_spec.rb
- spec/services/permissions/order_spec.rb
- spec/support/request/web_helper.rb
Metrics/ParameterLists:
@@ -716,5 +716,6 @@ Metrics/ParameterLists:
Exclude:
- app/helpers/angular_form_builder.rb
- app/models/product_import/entry_processor.rb
- app/models/product_import/entry_validator.rb
- lib/open_food_network/xero_invoices_report.rb
- spec/features/admin/reports_spec.rb

View File

@@ -5,9 +5,9 @@
# rubocop locally, the default configuration file `.rubocop.yml` loads
# our "todo lists" to ignore all current violations.
AllCops:
TargetRubyVersion: 2.1
TargetRailsVersion: 3.2
Exclude:
- 'bin/**/*'
- 'db/**/*'
- 'config/**/*'
- 'script/**/*'
@@ -40,7 +40,7 @@ Layout/MultilineMethodCallIndentation:
Enabled: true
EnforcedStyle: indented
Layout/LineLength:
Metrics/LineLength:
Max: 100
## TEMPORARY/CONTESTED SETTINGS

File diff suppressed because it is too large Load Diff

View File

@@ -1 +1 @@
2.3.7
2.1.5

View File

@@ -19,10 +19,6 @@ If you want to run the whole test suite, we recommend using a free CI service to
bundle exec rspec spec
## Which issue to pick first?
We have curated all issues interesting for new members of the community within the [Welcome New Developers project board][welcome-dev]. Have a look and pick the one you would prefer working on!
## Internationalisation (i18n)
The locale `en` is maintained in the source code, but other locales are managed at [Transifex][ofn-transifex]. Read more about [internationalisation][i18n] in the developer wiki.
@@ -66,4 +62,3 @@ From here, your pull request will progress through the [Review, Test, Merge & De
[slack-dev]: https://openfoodnetwork.slack.com/messages/C2GQ45KNU
[ofn-transifex]: https://www.transifex.com/open-food-foundation/open-food-network/
[i18n]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/i18n
[welcome-dev]: https://github.com/openfoodfoundation/openfoodnetwork/projects/27

View File

@@ -6,19 +6,16 @@ RUN apt-get update && apt-get install -y curl git build-essential software-prope
# Setup ENV variables
ENV PATH /usr/local/src/rbenv/shims:/usr/local/src/rbenv/bin:$PATH
ENV RBENV_ROOT /usr/local/src/rbenv
ENV RUBY_VERSION 2.1.5
ENV CONFIGURE_OPTS --disable-install-doc
ENV BUNDLE_PATH /bundles
WORKDIR /usr/src/app
COPY .ruby-version .
# Rbenv & Ruby part
RUN git clone https://github.com/rbenv/rbenv.git ${RBENV_ROOT} && \
git clone https://github.com/rbenv/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build && \
${RBENV_ROOT}/plugins/ruby-build/install.sh && \
echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh && \
rbenv install $(cat .ruby-version) && \
rbenv global $(cat .ruby-version) && \
rbenv install $RUBY_VERSION && \
rbenv global $RUBY_VERSION && \
gem install bundler --version=1.17.2
# Postgres
@@ -27,4 +24,8 @@ RUN sh -c "echo 'deb https://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main'
apt-get update && \
apt-get install -yqq --no-install-recommends postgresql-client-9.5 libpq-dev
ENV BUNDLE_PATH /bundles
COPY . /usr/src/app/
WORKDIR /usr/src/app

View File

@@ -11,7 +11,7 @@ The following guides are located in the wiki and provide more OS-specific step-b
### Dependencies
* Rails 3.2.x
* Ruby 2.1.9
* Ruby 2.1.5
* PostgreSQL database
* PhantomJS (for testing)
* See Gemfile for a list of gems required

35
Gemfile
View File

@@ -1,9 +1,9 @@
source 'https://rubygems.org'
ruby "2.3.7"
ruby "2.1.5"
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
gem 'i18n', '~> 0.6.11'
gem 'i18n-js', '~> 3.5.1'
gem 'i18n-js', '~> 3.3.0'
gem 'rails', '~> 3.2.22'
gem 'rails-i18n', '~> 3.0.0'
gem 'rails_safe_tasks', '~> 1.0'
@@ -15,12 +15,12 @@ gem 'nokogiri', '>= 1.6.7.1'
gem "order_management", path: "./engines/order_management"
gem 'web', path: './engines/web'
gem 'activerecord-postgresql-adapter'
gem 'pg', '~> 0.21.0'
gem 'pg'
# OFN-maintained and patched version of Spree v2.0.4. See
# https://github.com/openfoodfoundation/openfoodnetwork/wiki/Spree-2.0-upgrade
# for details.
gem 'spree_api', github: 'openfoodfoundation/spree', branch: '2-0-4-stable'
gem 'spree_backend', github: 'openfoodfoundation/spree', branch: '2-0-4-stable'
gem 'spree_core', github: 'openfoodfoundation/spree', branch: '2-0-4-stable'
@@ -39,7 +39,7 @@ gem 'activemerchant', '~> 1.78'
gem 'devise', '~> 2.2.5'
gem 'devise-encryptable', '0.2.0'
gem 'jwt', '~> 2.2'
gem 'oauth2', '~> 1.4.2' # Used for Stripe Connect
gem 'oauth2', '~> 1.4.1' # Used for Stripe Connect
gem 'daemons'
gem 'delayed_job_active_record'
@@ -84,7 +84,8 @@ gem 'paper_trail', '~> 5.2.3'
gem 'paperclip', '~> 3.4.1'
gem 'rack-rewrite'
gem 'rack-ssl', require: 'rack/ssl'
gem 'roadie-rails', '~> 1.3.0'
gem 'roadie-rails', '~> 1.1.1'
gem 'skylight', '< 2.0'
gem 'spinjs-rails'
gem 'combine_pdf'
@@ -93,20 +94,18 @@ gem 'wkhtmltopdf-binary'
gem 'foreigner'
gem 'immigrant'
gem 'roo', '~> 2.8.2'
gem 'roo', '~> 2.7.0'
gem 'roo-xls', '~> 1.1.0'
gem 'whenever', require: false
gem 'test-unit', '~> 3.3'
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'coffee-rails', '~> 3.2.1'
gem 'compass-rails'
gem 'mini_racer', '0.2.9'
gem 'therubyracer', '=0.12.0'
gem 'uglifier', '>= 1.0.3'
@@ -132,10 +131,10 @@ group :test, :development do
# Pretty printed test output
gem 'atomic'
gem 'awesome_print'
gem 'capybara', '>= 2.18.0' # 3.0 requires nokogiri 1.8
gem 'capybara', '>= 2.15.4'
gem 'database_cleaner', '0.7.1', require: false
gem "factory_bot_rails", require: false
gem 'fuubar', '~> 2.5.0'
gem 'fuubar', '~> 2.4.1'
gem 'json_spec', '~> 1.1.4'
gem 'knapsack'
gem 'letter_opener', '>= 1.4.1'
@@ -145,7 +144,7 @@ group :test, :development do
gem 'shoulda-matchers'
gem 'timecop'
gem 'unicorn-rails'
gem 'webdrivers'
gem 'webdrivers', '3.8.1'
end
group :test do
@@ -158,10 +157,14 @@ end
group :development do
gem 'byebug', '~> 9.0.0' # 9.1 requires ruby 2.2
gem 'debugger-linecache'
gem 'guard'
gem 'guard-livereload'
gem 'guard-rails'
gem 'guard-rspec', '~> 4.7.3'
gem 'listen', '3.0.8' # 3.1.0 requires ruby 2.2
gem "newrelic_rpm", "~> 3.0"
gem 'pry-byebug', '>= 3.4.3'
gem 'rubocop'
gem 'rubocop-rails'
gem 'rubocop', '>= 0.49.1'
gem 'spring', '1.7.2'
gem 'spring-commands-rspec'
@@ -170,5 +173,5 @@ group :development do
# greater than 1.0.9, so we just required the latest available version here.
gem 'eventmachine', '>= 1.2.3'
gem 'rack-mini-profiler', '< 2.0.0'
gem 'rack-mini-profiler', '< 1.0.0'
end

View File

@@ -129,10 +129,8 @@ GEM
activesupport (= 3.2.22.5)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activerecord-import (1.0.4)
activerecord-import (1.0.2)
activerecord (>= 3.2)
activerecord-postgresql-adapter (0.0.1)
pg
activeresource (3.2.22.5)
activemodel (= 3.2.22.5)
activesupport (= 3.2.22.5)
@@ -166,7 +164,7 @@ GEM
bcrypt-ruby (3.1.5)
bcrypt (>= 3.1.3)
blockenspiel (0.5.0)
bugsnag (6.12.2)
bugsnag (6.12.0)
concurrent-ruby (~> 1.0)
builder (3.0.4)
byebug (9.0.6)
@@ -178,7 +176,8 @@ GEM
rack (>= 1.0.0)
rack-test (>= 0.5.4)
xpath (>= 2.0, < 4.0)
childprocess (3.0.0)
childprocess (0.9.0)
ffi (~> 1.0, >= 1.0.11)
chronic (0.10.2)
chunky_png (1.3.10)
climate_control (0.2.0)
@@ -212,9 +211,10 @@ GEM
sass-rails (< 5.1)
sprockets (< 4.0)
concurrent-ruby (1.1.5)
connection_pool (2.2.2)
crack (0.4.3)
safe_yaml (~> 1.0.0)
css_parser (1.7.0)
css_parser (1.6.0)
addressable
daemons (1.3.1)
dalli (2.7.10)
@@ -223,7 +223,7 @@ GEM
activerecord (>= 3.2.0, < 5.0)
fog (~> 1.0)
rails (>= 3.2.0, < 5.0)
ddtrace (0.31.1)
ddtrace (0.26.0)
msgpack
debugger-linecache (1.2.0)
deface (1.0.2)
@@ -252,19 +252,22 @@ GEM
diffy (3.3.0)
docile (1.3.2)
dry-inflector (0.1.2)
em-websocket (0.5.1)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
erubis (2.7.0)
eventmachine (1.2.7)
excon (0.71.1)
excon (0.62.0)
execjs (2.7.0)
factory_bot (4.10.0)
activesupport (>= 3.0.0)
factory_bot_rails (4.10.0)
factory_bot (~> 4.10.0)
railties (>= 3.0.0)
faraday (0.17.1)
faraday (0.15.4)
multipart-post (>= 1.2, < 3)
ffaker (1.22.1)
ffi (1.11.3)
ffi (1.10.0)
figaro (1.1.1)
thor (~> 0.14)
fission (0.5.0)
@@ -424,25 +427,48 @@ GEM
foundation-rails (5.5.2.1)
railties (>= 3.1.0)
sass (>= 3.3.0, < 3.5)
fuubar (2.5.0)
fuubar (2.4.1)
rspec-core (~> 3.0)
ruby-progressbar (~> 1.4)
geocoder (1.1.8)
gmaps4rails (1.5.6)
guard (2.15.0)
formatador (>= 0.2.4)
listen (>= 2.7, < 4.0)
lumberjack (>= 1.0.12, < 2.0)
nenv (~> 0.1)
notiffany (~> 0.0)
pry (>= 0.9.12)
shellany (~> 0.0)
thor (>= 0.18.1)
guard-compat (1.2.1)
guard-livereload (2.5.2)
em-websocket (~> 0.5)
guard (~> 2.8)
guard-compat (~> 1.0)
multi_json (~> 1.8)
guard-rails (0.7.2)
guard (~> 2.11)
guard-compat (~> 1.0)
guard-rspec (4.7.3)
guard (~> 2.1)
guard-compat (~> 1.1)
rspec (>= 2.99.0, < 4.0)
haml (4.0.7)
tilt
hashdiff (1.0.0)
highline (1.6.18)
hike (1.2.3)
http_parser.rb (0.6.0)
httparty (0.16.2)
multi_xml (>= 0.5.2)
i18n (0.6.11)
i18n-js (3.5.1)
i18n-js (3.3.0)
i18n (>= 0.6.6)
immigrant (0.3.6)
activerecord (>= 3.0)
ipaddress (0.8.3)
jaro_winkler (1.5.4)
jaro_winkler (1.5.1)
journey (1.0.4)
jquery-migrate-rails (1.2.1)
jquery-rails (3.0.4)
@@ -465,7 +491,11 @@ GEM
addressable (~> 2.3)
letter_opener (1.7.0)
launchy (~> 2.2)
libv8 (7.3.492.27.1)
libv8 (3.16.14.19)
listen (3.0.8)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
lumberjack (1.0.13)
mail (2.5.5)
mime-types (~> 1.16)
treetop (~> 1.4.8)
@@ -473,26 +503,30 @@ GEM
mime-types (1.25.1)
mini_mime (1.0.1)
mini_portile2 (2.1.0)
mini_racer (0.2.9)
libv8 (>= 6.9.411)
momentjs-rails (2.20.1)
railties (>= 3.1)
money (5.1.1)
i18n (~> 0.6.0)
msgpack (1.3.1)
multi_json (1.14.1)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.1.1)
nenv (0.3.0)
net-http-persistent (3.1.0)
connection_pool (~> 2.2)
newrelic_rpm (3.18.1.330)
nokogiri (1.6.8.1)
mini_portile2 (~> 2.1.0)
oauth2 (1.4.2)
faraday (>= 0.8, < 2.0)
notiffany (0.1.1)
nenv (~> 0.1)
shellany (~> 0.0)
oauth2 (1.4.1)
faraday (>= 0.8, < 0.16.0)
jwt (>= 1.0, < 3.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
oj (3.10.1)
oj (3.7.12)
orm_adapter (0.5.0)
paper_trail (5.2.3)
activerecord (>= 3.0, < 6.0)
@@ -503,10 +537,10 @@ GEM
activesupport (>= 3.0.0)
cocaine (~> 0.5.0)
mime-types
parallel (1.19.1)
parallel (1.11.2)
paranoia (1.3.4)
activerecord (~> 3.1)
parser (2.7.0.2)
parser (2.5.1.0)
ast (~> 2.4.0)
paypal-sdk-core (0.2.10)
multi_json (~> 1.0)
@@ -517,20 +551,20 @@ GEM
polyamorous (0.5.0)
activerecord (~> 3.0)
polyglot (0.3.5)
power_assert (1.1.5)
powerpack (0.1.1)
pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
pry-byebug (3.4.3)
byebug (>= 9.0, < 9.1)
pry (~> 0.10)
public_suffix (4.0.3)
public_suffix (3.1.1)
rabl (0.8.4)
activesupport (>= 2.3.14)
rack (1.4.7)
rack-cache (1.9.0)
rack (>= 0.4)
rack-mini-profiler (1.1.4)
rack-mini-profiler (0.10.7)
rack (>= 1.2.0)
rack-protection (1.5.5)
rack
@@ -560,7 +594,7 @@ GEM
thor (>= 0.14.6, < 2.0)
rainbow (3.0.0)
raindrops (0.19.0)
rake (13.0.0)
rake (12.3.3)
ransack (0.7.2)
actionpack (~> 3.0)
activerecord (~> 3.0)
@@ -576,58 +610,57 @@ GEM
rdoc (3.12.2)
json (~> 1.4)
redcarpet (3.5.0)
ref (2.0.0)
request_store (1.4.1)
rack (>= 1.4)
roadie (3.4.0)
css_parser (~> 1.4)
nokogiri (~> 1.5)
roadie-rails (1.3.0)
railties (>= 3.0, < 5.3)
roadie-rails (1.1.1)
railties (>= 3.0, < 5.1)
roadie (~> 3.1)
roo (2.8.2)
roo (2.7.1)
nokogiri (~> 1)
rubyzip (>= 1.2.1, < 2.0.0)
rubyzip (~> 1.1, < 2.0.0)
roo-xls (1.1.0)
nokogiri
roo (>= 2.0.0beta1, < 3)
spreadsheet (> 0.9.0)
rspec (3.9.0)
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
rspec-mocks (~> 3.9.0)
rspec-core (3.9.0)
rspec-support (~> 3.9.0)
rspec-expectations (3.9.0)
rspec (3.8.0)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-core (3.8.0)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-mocks (3.9.0)
rspec-support (~> 3.8.0)
rspec-mocks (3.8.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-rails (3.9.0)
rspec-support (~> 3.8.0)
rspec-rails (3.8.2)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
rspec-mocks (~> 3.9.0)
rspec-support (~> 3.9.0)
rspec-retry (0.6.2)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-support (~> 3.8.0)
rspec-retry (0.6.1)
rspec-core (> 3.3)
rspec-support (3.9.0)
rubocop (0.79.0)
rspec-support (3.8.0)
rubocop (0.57.2)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.7.0.1)
parser (>= 2.5)
powerpack (~> 0.1)
rainbow (>= 2.2.2, < 4.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.7)
rubocop-rails (2.4.1)
rack (>= 1.1)
rubocop (>= 0.72.0)
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-ole (1.2.12.1)
ruby-progressbar (1.10.1)
ruby-rc4 (0.1.5)
rubyzip (1.3.0)
rubyzip (1.2.2)
safe_yaml (1.0.5)
sass (3.3.14)
sass-rails (3.2.6)
@@ -637,12 +670,13 @@ GEM
select2-rails (3.4.9)
sass-rails
thor (~> 0.14)
selenium-webdriver (3.142.7)
childprocess (>= 0.5, < 4.0)
rubyzip (>= 1.2.2)
selenium-webdriver (3.141.0)
childprocess (~> 0.5)
rubyzip (~> 1.2, >= 1.2.2)
shellany (0.0.1)
shoulda-matchers (2.8.0)
activesupport (>= 3.0.0)
simplecov (0.17.1)
simplecov (0.17.0)
docile (~> 1.1)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
@@ -651,6 +685,8 @@ GEM
rack (~> 1.4)
rack-protection (~> 1.4)
tilt (>= 1.3, < 3)
skylight (1.7.2)
activesupport (>= 3.0.0)
spinjs-rails (1.4)
rails (>= 3.1)
spreadsheet (1.1.7)
@@ -665,9 +701,12 @@ GEM
tilt (~> 1.1, != 1.3.0)
state_machine (1.2.0)
stringex (1.5.1)
stripe (5.11.0)
test-unit (3.3.5)
power_assert
stripe (4.24.0)
faraday (~> 0.13)
net-http-persistent (~> 3.0)
therubyracer (0.12.0)
libv8 (~> 3.16.14.0)
ref
thor (0.20.3)
tilt (1.4.1)
timecop (0.9.1)
@@ -679,11 +718,11 @@ GEM
turbo-sprockets-rails3 (0.3.14)
railties (> 3.2.8, < 4.0.0)
sprockets (>= 2.2.0)
tzinfo (0.3.56)
uglifier (4.2.0)
tzinfo (0.3.55)
uglifier (4.1.20)
execjs (>= 0.3.0, < 3)
unicode-display_width (1.6.0)
unicorn (5.5.2)
unicode-display_width (1.3.2)
unicorn (5.5.1)
kgio (~> 2.6)
raindrops (~> 0.7)
unicorn-rails (2.2.1)
@@ -696,18 +735,18 @@ GEM
railties (>= 3.0)
warden (1.2.7)
rack (>= 1.0)
webdrivers (4.2.0)
webdrivers (3.8.1)
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (>= 3.0, < 4.0)
webmock (3.8.0)
rubyzip (~> 1.0)
selenium-webdriver (~> 3.0)
webmock (3.7.1)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
whenever (0.11.0)
chronic (>= 0.6.3)
wicked_pdf (1.1.0)
wkhtmltopdf-binary (0.12.5)
wkhtmltopdf-binary (0.12.4)
xml-simple (1.1.5)
xpath (2.1.0)
nokogiri (~> 1.3)
@@ -719,7 +758,6 @@ DEPENDENCIES
active_model_serializers (= 0.8.4)
activemerchant (~> 1.78)
activerecord-import
activerecord-postgresql-adapter
acts-as-taggable-on (~> 3.4)
andand
angular-rails-templates (~> 0.3.0)
@@ -731,7 +769,7 @@ DEPENDENCIES
blockenspiel
bugsnag
byebug (~> 9.0.0)
capybara (>= 2.18.0)
capybara (>= 2.15.4)
coffee-rails (~> 3.2.1)
combine_pdf
compass-rails
@@ -755,12 +793,16 @@ DEPENDENCIES
foundation-icons-sass-rails
foundation-rails
foundation_rails_helper!
fuubar (~> 2.5.0)
fuubar (~> 2.4.1)
geocoder
gmaps4rails
guard
guard-livereload
guard-rails
guard-rspec (~> 4.7.3)
haml
i18n (~> 0.6.11)
i18n-js (~> 3.5.1)
i18n-js (~> 3.3.0)
immigrant
jquery-migrate-rails
jquery-rails (= 3.0.4)
@@ -769,40 +811,41 @@ DEPENDENCIES
kaminari (~> 0.14.1)
knapsack
letter_opener (>= 1.4.1)
mini_racer (= 0.2.9)
listen (= 3.0.8)
momentjs-rails
newrelic_rpm (~> 3.0)
nokogiri (>= 1.6.7.1)
oauth2 (~> 1.4.2)
oauth2 (~> 1.4.1)
ofn-qz!
oj
order_management!
paper_trail (~> 5.2.3)
paperclip (~> 3.4.1)
pg (~> 0.21.0)
pg
pry-byebug (>= 3.4.3)
rabl
rack-mini-profiler (< 2.0.0)
rack-mini-profiler (< 1.0.0)
rack-rewrite
rack-ssl
rails (~> 3.2.22)
rails-i18n (~> 3.0.0)
rails_safe_tasks (~> 1.0)
redcarpet
roadie-rails (~> 1.3.0)
roo (~> 2.8.2)
roadie-rails (~> 1.1.1)
roo (~> 2.7.0)
roo-xls (~> 1.1.0)
rspec-rails (>= 3.5.2)
rspec-retry
rubocop
rubocop-rails
rubocop (>= 0.49.1)
sass (~> 3.3)
sass-rails (~> 3.2.3)
selenium-webdriver
shoulda-matchers
simple_form!
simplecov
skylight (< 2.0)
spinjs-rails
spree_api!
spree_backend!
spree_core!
spree_i18n!
@@ -810,7 +853,7 @@ DEPENDENCIES
spring (= 1.7.2)
spring-commands-rspec
stripe
test-unit (~> 3.3)
therubyracer (= 0.12.0)
timecop
truncate_html
turbo-sprockets-rails3
@@ -818,14 +861,14 @@ DEPENDENCIES
unicorn
unicorn-rails
web!
webdrivers
webdrivers (= 3.8.1)
webmock
whenever
wicked_pdf
wkhtmltopdf-binary
RUBY VERSION
ruby 2.3.7p456
ruby 2.1.5p273
BUNDLED WITH
1.17.2

11
Guardfile Normal file
View File

@@ -0,0 +1,11 @@
# A sample Guardfile
# More info at https://github.com/guard/guard#readme
guard 'livereload' do
watch(%r{app/views/.+\.(erb|haml|slim)$})
watch(%r{app/helpers/.+\.rb})
watch(%r{public/.+\.(css|js|html)})
# Rails Assets Pipeline
watch(%r{(app|vendor)(/assets/\w+/(.+\.(css|js|html|png|jpg))).*}) { |m| "/assets/#{m[3]}" }
end

View File

@@ -1,22 +1,23 @@
[![Build Status](https://semaphoreci.com/api/v1/openfoodfoundation/openfoodnetwork-2/branches/master/badge.svg)](https://semaphoreci.com/openfoodfoundation/openfoodnetwork-2)
[![Code Climate](https://codeclimate.com/github/openfoodfoundation/openfoodnetwork.png)](https://codeclimate.com/github/openfoodfoundation/openfoodnetwork)
[![View performance data on Skylight](https://badges.skylight.io/status/EiXQ6sSKij8y.svg)](https://oss.skylight.io/app/applications/EiXQ6sSKij8y)
# Open Food Network
The Open Food Network is an online marketplace for local food. It enables a network of independent online food stores that connects farmers and food hubs (including co-ops, online farmers markets, independent food businesses, etc) with individuals and local businesses. It gives farmers and food hubs an easier and fairer way to distribute their food.
The Open Food Network is an online marketplace for local food. It enables a network of independent online food stores that connect farmers and food hubs (including coops, online farmers' markets, independent food businesses etc); with individuals and local businesses. It gives farmers and food hubs an easier and fairer way to distribute their food.
Supported by the Open Food Foundation and a network of global affiliates, we are proudly open source and not-for-profit - we're trying to seriously disrupt the concentration of power in global agri-food systems, and we need as many smart people working together on this as possible.
We're part of global movement - get involved!
* Join the conversation [on Slack][slack-invite]. Make sure you introduce yourself in the #general channel.
* Join the conversation [on Slack][slack-invite]. Make sure you introduce yourself in the #general channel
* Head to [https://openfoodnetwork.org](https://openfoodnetwork.org) for more information about the global OFN project.
* Check out the [User Guide](https://guide.openfoodnetwork.org/) for a list of features and tutorials.
* Join our [discussion forum](https://community.openfoodnetwork.org).
## Contributing
If you are interested in contributing to the OFN in any capacity, please introduce yourself [on Slack][slack-invite], and have a look through our [Contributor Guide][contributor-guide].
If you are interested in contributing to the OFN in any capacity, please introducing yourself [on Slack][slack-invite], and have a look through our [Contributor Guide][contributor-guide]
Our [GETTING_STARTED](GETTING_STARTED.md) and [CONTRIBUTING](CONTRIBUTING.md) guides are the best place to start for developers looking to set up a development environment and make contributions to the codebase.
@@ -35,7 +36,7 @@ We use [BrowserStack](https://www.browserstack.com/) as a manual testing tool. B
Copyright (c) 2012 - 2019 Open Food Foundation, released under the AGPL licence.
[survey]: https://docs.google.com/a/eaterprises.com.au/forms/d/1zxR5vSiU9CigJ9cEaC8-eJLgYid8CR8er7PPH9Mc-30/edit#
[slack-invite]: https://join.slack.com/t/openfoodnetwork/shared_invite/enQtNzY3NDEwNzM2MDM0LWFmNGRhNDUwYzNmNWNkYmFkMzgxNDg1OTg1ODNjNWY4Y2FhNDIwNmE4ZWI0OThiMGNmZjFkODczNGZiYTJmNWI
[slack-invite]: https://openfoodnetwork.org/slack-invite
[contributor-guide]: https://ofn-user-guide.gitbook.io/ofn-contributor-guide/who-are-we
[ofn-install]: https://github.com/openfoodfoundation/ofn-install
[super-admin-guide]: https://ofn-user-guide.gitbook.io/ofn-super-admin-guide

View File

@@ -1,4 +1,4 @@
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $filter, $http, $window, BulkProducts, DisplayProperties, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, Columns, tax_categories, RequestMonitor) ->
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $filter, $http, $window, BulkProducts, DisplayProperties, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, SpreeApiAuth, Columns, tax_categories, RequestMonitor) ->
$scope.StatusMessage = StatusMessage
$scope.columns = Columns.columns
@@ -39,7 +39,12 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.DisplayProperties = DisplayProperties
$scope.initialise = ->
$scope.fetchProducts()
SpreeApiAuth.authorise()
.then ->
$scope.spree_api_key_ok = true
$scope.fetchProducts()
.catch (message) ->
$scope.api_error_msg = message
$scope.$watchCollection '[query, producerFilter, categoryFilter, importDateFilter, per_page]', ->
$scope.page = 1 # Reset page when changing filters for new search
@@ -103,15 +108,9 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.categoryFilter = "0"
$scope.importDateFilter = "0"
confirm_unsaved_changes = () ->
(DirtyProducts.count() > 0 and confirm(t("unsaved_changes_confirmation"))) or (DirtyProducts.count() == 0)
editProductUrl = (product, variant) ->
"/admin/products/" + product.permalink_live + ((if variant then "/variants/" + variant.id else "")) + "/edit"
$scope.editWarn = (product, variant) ->
if confirm_unsaved_changes()
window.open(editProductUrl(product, variant), "_blank")
if (DirtyProducts.count() > 0 and confirm(t("unsaved_changes_confirmation"))) or (DirtyProducts.count() == 0)
window.location = "/admin/products/" + product.permalink_live + ((if variant then "/variants/" + variant.id else "")) + "/edit"
$scope.toggleShowAllVariants = ->
@@ -142,7 +141,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
if confirm("Are you sure?")
$http(
method: "DELETE"
url: "/api/products/" + product.id
url: "/api/products/" + product.id + "/soft_delete"
).success (data) ->
$scope.products.splice $scope.products.indexOf(product), 1
DirtyProducts.deleteProduct product.id
@@ -157,7 +156,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
if confirm(t("are_you_sure"))
$http(
method: "DELETE"
url: "/api/products/" + product.permalink_live + "/variants/" + variant.id
url: "/api/products/" + product.permalink_live + "/variants/" + variant.id + "/soft_delete"
).success (data) ->
$scope.removeVariant(product, variant)
else

View File

@@ -0,0 +1,16 @@
angular.module("admin.indexUtils").factory "SpreeApiAuth", ($q, $http, SpreeApiKey) ->
new class SpreeApiAuth
authorise: ->
deferred = $q.defer()
$http.get("/api/users/authorise_api?token=" + SpreeApiKey)
.success (response) ->
if response?.success == "Use of API Authorised"
$http.defaults.headers.common["X-Spree-Token"] = SpreeApiKey
deferred.resolve()
.error (response) ->
error = response?.error || t('js.unauthorized')
deferred.reject(error)
deferred.promise

View File

@@ -1,12 +1,92 @@
angular.module('admin.orderCycles')
.controller 'AdminCreateOrderCycleCtrl', ($scope, $controller, $filter, $window, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, ocInstance, StatusMessage) ->
$controller('AdminOrderCycleBasicCtrl', {$scope: $scope, ocInstance: ocInstance})
$scope.order_cycle = OrderCycle.new({ coordinator_id: ocInstance.coordinator_id})
.controller 'AdminCreateOrderCycleCtrl', ($scope, $filter, $window, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, ocInstance, StatusMessage) ->
$scope.enterprises = Enterprise.index(coordinator_id: ocInstance.coordinator_id)
$scope.supplier_enterprises = Enterprise.producer_enterprises
$scope.distributor_enterprises = Enterprise.hub_enterprises
$scope.supplied_products = Enterprise.supplied_products
$scope.enterprise_fees = EnterpriseFee.index(coordinator_id: ocInstance.coordinator_id)
$scope.schedules = Schedules.index({enterprise_id: ocInstance.coordinator_id})
$scope.OrderCycle = OrderCycle
$scope.order_cycle = OrderCycle.new({ coordinator_id: ocInstance.coordinator_id})
$scope.StatusMessage = StatusMessage
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue
$scope.$watch 'order_cycle_form.$valid', (isValid) ->
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
$scope.suppliedVariants = (enterprise_id) ->
Enterprise.suppliedVariants(enterprise_id)
$scope.exchangeSelectedVariants = (exchange) ->
OrderCycle.exchangeSelectedVariants(exchange)
$scope.setExchangeVariants = (exchange, variants, selected) ->
OrderCycle.setExchangeVariants(exchange, variants, selected)
$scope.enterpriseTotalVariants = (enterprise) ->
Enterprise.totalVariants(enterprise)
$scope.productSuppliedToOrderCycle = (product) ->
OrderCycle.productSuppliedToOrderCycle(product)
$scope.variantSuppliedToOrderCycle = (variant) ->
OrderCycle.variantSuppliedToOrderCycle(variant)
$scope.incomingExchangeVariantsFor = (enterprise_id) ->
$filter('filterExchangeVariants')(OrderCycle.incomingExchangesVariants(), $scope.order_cycle.visible_variants_for_outgoing_exchanges[enterprise_id])
$scope.exchangeDirection = (exchange) ->
OrderCycle.exchangeDirection(exchange)
$scope.enterprisesWithFees = ->
$scope.enterprises[id] for id in OrderCycle.participatingEnterpriseIds() when $scope.enterpriseFeesForEnterprise(id).length > 0
$scope.enterpriseFeesForEnterprise = (enterprise_id) ->
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
$scope.addSupplier = ($event) ->
$event.preventDefault()
OrderCycle.addSupplier($scope.new_supplier_id)
$scope.addDistributor = ($event) ->
$event.preventDefault()
OrderCycle.addDistributor($scope.new_distributor_id)
$scope.removeExchange = ($event, exchange) ->
$event.preventDefault()
OrderCycle.removeExchange(exchange)
$scope.order_cycle_form.$dirty = true
$scope.addCoordinatorFee = ($event) ->
$event.preventDefault()
OrderCycle.addCoordinatorFee()
$scope.removeCoordinatorFee = ($event, index) ->
$event.preventDefault()
OrderCycle.removeCoordinatorFee(index)
$scope.addExchangeFee = ($event, exchange) ->
$event.preventDefault()
OrderCycle.addExchangeFee(exchange)
$scope.removeExchangeFee = ($event, exchange, index) ->
$event.preventDefault()
OrderCycle.removeExchangeFee(exchange, index)
$scope.removeDistributionOfVariant = (variant_id) ->
OrderCycle.removeDistributionOfVariant(variant_id)
$scope.submit = ($event, destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
OrderCycle.create(destination)
$scope.cancel = (destination) ->
$window.location = destination

View File

@@ -1,17 +1,91 @@
angular.module('admin.orderCycles')
.controller 'AdminEditOrderCycleCtrl', ($scope, $controller, $filter, $location, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, Schedules, RequestMonitor, ocInstance) ->
$controller('AdminOrderCycleBasicCtrl', {$scope: $scope, ocInstance: ocInstance})
.controller 'AdminEditOrderCycleCtrl', ($scope, $filter, $location, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, Schedules, RequestMonitor, ocInstance) ->
order_cycle_id = $location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1]
$scope.order_cycle = OrderCycle.load(order_cycle_id)
$scope.enterprises = Enterprise.index(order_cycle_id: order_cycle_id)
$scope.supplier_enterprises = Enterprise.producer_enterprises
$scope.distributor_enterprises = Enterprise.hub_enterprises
$scope.supplied_products = Enterprise.supplied_products
$scope.enterprise_fees = EnterpriseFee.index(order_cycle_id: order_cycle_id)
$scope.schedules = Schedules.index({enterprise_id: ocInstance.coordinator_id})
$scope.OrderCycle = OrderCycle
$scope.order_cycle = OrderCycle.load(order_cycle_id)
$scope.StatusMessage = StatusMessage
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue
$scope.$watch 'order_cycle_form.$valid', (isValid) ->
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
$scope.suppliedVariants = (enterprise_id) ->
Enterprise.suppliedVariants(enterprise_id)
$scope.exchangeSelectedVariants = (exchange) ->
OrderCycle.exchangeSelectedVariants(exchange)
$scope.setExchangeVariants = (exchange, variants, selected) ->
OrderCycle.setExchangeVariants(exchange, variants, selected)
$scope.enterpriseTotalVariants = (enterprise) ->
Enterprise.totalVariants(enterprise)
$scope.productSuppliedToOrderCycle = (product) ->
OrderCycle.productSuppliedToOrderCycle(product)
$scope.variantSuppliedToOrderCycle = (variant) ->
OrderCycle.variantSuppliedToOrderCycle(variant)
$scope.incomingExchangeVariantsFor = (enterprise_id) ->
$filter('filterExchangeVariants')(OrderCycle.incomingExchangesVariants(), $scope.order_cycle.visible_variants_for_outgoing_exchanges[enterprise_id])
$scope.exchangeDirection = (exchange) ->
OrderCycle.exchangeDirection(exchange)
$scope.enterprisesWithFees = ->
$scope.enterprises[id] for id in OrderCycle.participatingEnterpriseIds() when $scope.enterpriseFeesForEnterprise(id).length > 0
$scope.enterpriseFeesForEnterprise = (enterprise_id) ->
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
$scope.addSupplier = ($event) ->
$event.preventDefault()
OrderCycle.addSupplier($scope.new_supplier_id)
$scope.addDistributor = ($event) ->
$event.preventDefault()
OrderCycle.addDistributor($scope.new_distributor_id)
$scope.removeExchange = ($event, exchange) ->
$event.preventDefault()
OrderCycle.removeExchange(exchange)
$scope.order_cycle_form.$dirty = true
$scope.addCoordinatorFee = ($event) ->
$event.preventDefault()
OrderCycle.addCoordinatorFee()
$scope.removeCoordinatorFee = ($event, index) ->
$event.preventDefault()
OrderCycle.removeCoordinatorFee(index)
$scope.order_cycle_form.$dirty = true
$scope.addExchangeFee = ($event, exchange) ->
$event.preventDefault()
OrderCycle.addExchangeFee(exchange)
$scope.removeExchangeFee = ($event, exchange, index) ->
$event.preventDefault()
OrderCycle.removeExchangeFee(exchange, index)
$scope.order_cycle_form.$dirty = true
$scope.removeDistributionOfVariant = (variant_id) ->
OrderCycle.removeDistributionOfVariant(variant_id)
$scope.submit = (destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
@@ -20,3 +94,6 @@ angular.module('admin.orderCycles')
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
OrderCycle.update(destination, $scope.order_cycle_form)
$scope.cancel = (destination) ->
$window.location = destination

View File

@@ -1,31 +0,0 @@
angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($scope, $controller, $location, Enterprise, OrderCycle, ExchangeProduct, ocInstance) ->
$controller('AdminOrderCycleExchangesCtrl', {$scope: $scope, ocInstance: ocInstance, $location: $location})
$scope.view = 'incoming'
$scope.exchangeTotalVariants = (exchange) ->
return unless $scope.enterprises? && $scope.enterprises[exchange.enterprise_id]?
enterprise = $scope.enterprises[exchange.enterprise_id]
return enterprise.numVariants if enterprise.numVariants?
enterprise.numVariants = 0
params = { exchange_id: exchange.id, enterprise_id: exchange.enterprise_id, order_cycle_id: $scope.order_cycle.id, incoming: true}
ExchangeProduct.countVariants params, (variants_count) ->
enterprise.numVariants = variants_count
$scope.setSelectAllVariantsCheckboxValue(exchange, enterprise.numVariants)
return enterprise.numVariants
$scope.addSupplier = ($event) ->
$event.preventDefault()
OrderCycle.addSupplier $scope.new_supplier_id
# To select all variants we first need to load them all from the server
#
# This is only needed in Incoming exchanges as here we use supplied_products,
# in Outgoing Exchanges the variants are loaded as part of the Exchange payload
$scope.selectAllVariants = (exchange, selected) ->
$scope.loadAllExchangeProducts(exchange).then ->
$scope.setExchangeVariants(exchange, $scope.suppliedVariants(exchange.enterprise_id), selected)
$scope.$apply()

View File

@@ -1,40 +0,0 @@
angular.module('admin.orderCycles')
.controller 'AdminOrderCycleBasicCtrl', ($scope, $filter, $window, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, ocInstance, StatusMessage) ->
$scope.StatusMessage = StatusMessage
$scope.OrderCycle = OrderCycle
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue
$scope.$watch 'order_cycle_form.$valid', (isValid) ->
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
$scope.enterpriseFeesForEnterprise = (enterprise_id) ->
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
$scope.cancel = (destination) ->
$window.location = destination
# Used in panels/exchange_products_supplied.html
$scope.suppliedVariants = (enterprise_id) ->
Enterprise.suppliedVariants(enterprise_id)
# Used in panels/exchange_products_supplied.html and panels/exchange_products_distributed.html
$scope.setExchangeVariants = (exchange, variants, selected) ->
OrderCycle.setExchangeVariants(exchange, variants, selected)
# The following methods are specific to the general settings pages:
# - simple create, simple edit and general settings pages
$scope.schedules = Schedules.index({enterprise_id: ocInstance.coordinator_id})
$scope.addCoordinatorFee = ($event) ->
$event.preventDefault()
OrderCycle.addCoordinatorFee()
$scope.removeCoordinatorFee = ($event, index) ->
$event.preventDefault()
OrderCycle.removeCoordinatorFee(index)

View File

@@ -1,76 +0,0 @@
angular.module('admin.orderCycles')
.controller 'AdminOrderCycleExchangesCtrl', ($scope, $controller, $filter, $window, $location, $timeout, OrderCycle, ExchangeProduct, Enterprise, EnterpriseFee, Schedules, RequestMonitor, ocInstance, StatusMessage) ->
$controller('AdminEditOrderCycleCtrl', {$scope: $scope, ocInstance: ocInstance, $location: $location})
$scope.supplier_enterprises = Enterprise.producer_enterprises
$scope.distributor_enterprises = Enterprise.hub_enterprises
$scope.productsLoading = ->
RequestMonitor.loading
$scope.setSelectAllVariantsCheckboxValue = (exchange, totalNumberOfVariants) ->
exchange.select_all_variants = $scope.exchangeSelectedVariants(exchange) >= totalNumberOfVariants
$scope.exchangeSelectedVariants = (exchange) ->
OrderCycle.exchangeSelectedVariants(exchange)
$scope.exchangeDirection = (exchange) ->
OrderCycle.exchangeDirection(exchange)
$scope.enterprisesWithFees = ->
$scope.enterprises[id] for id in OrderCycle.participatingEnterpriseIds() when $scope.enterpriseFeesForEnterprise(id).length > 0
$scope.removeExchange = ($event, exchange) ->
$event.preventDefault()
OrderCycle.removeExchange(exchange)
$scope.order_cycle_form.$dirty = true
$scope.addExchangeFee = ($event, exchange) ->
$event.preventDefault()
OrderCycle.addExchangeFee(exchange)
$scope.removeExchangeFee = ($event, exchange, index) ->
$event.preventDefault()
OrderCycle.removeExchangeFee(exchange, index)
$scope.order_cycle_form.$dirty = true
$scope.setPickupTimeFieldDirty = (index) ->
$timeout ->
pickup_time_field_name = "order_cycle_outgoing_exchange_" + index + "_pickup_time"
$scope.order_cycle_form[pickup_time_field_name].$setDirty()
$scope.removeDistributionOfVariant = (variant_id) ->
OrderCycle.removeDistributionOfVariant(variant_id)
$scope.loadExchangeProducts = (exchange, page = 1) ->
enterprise = $scope.enterprises[exchange.enterprise_id]
enterprise.supplied_products ?= []
return if enterprise.last_page_loaded? && enterprise.last_page_loaded >= page
enterprise.last_page_loaded = page
incoming = true if $scope.view == 'incoming'
params = { exchange_id: exchange.id, enterprise_id: exchange.enterprise_id, order_cycle_id: $scope.order_cycle.id, incoming: incoming, page: page}
ExchangeProduct.index params, (products, num_of_pages, num_of_products) ->
enterprise.num_of_pages = num_of_pages
enterprise.num_of_products = num_of_products
enterprise.supplied_products.push products...
$scope.loadMoreExchangeProducts = (exchange) ->
$scope.loadExchangeProducts(exchange, $scope.enterprises[exchange.enterprise_id].last_page_loaded + 1)
$scope.loadAllExchangeProducts = (exchange) ->
enterprise = $scope.enterprises[exchange.enterprise_id]
if enterprise.last_page_loaded < enterprise.num_of_pages
for page_to_load in [(enterprise.last_page_loaded + 1)..enterprise.num_of_pages]
RequestMonitor.load $scope.loadExchangeProducts(exchange, page_to_load).$promise
RequestMonitor.loadQueue
# initialize exchange products panel if not yet done
$scope.exchangeProdutsPanelInitialized = []
$scope.initializeExchangeProductsPanel = (exchange) ->
return if $scope.exchangeProdutsPanelInitialized[exchange.enterprise_id]
RequestMonitor.load $scope.loadExchangeProducts(exchange).$promise
$scope.exchangeProdutsPanelInitialized[exchange.enterprise_id] = true

View File

@@ -1,24 +0,0 @@
angular.module('admin.orderCycles').controller 'AdminOrderCycleOutgoingCtrl', ($scope, $controller, $filter, $location, OrderCycle, ocInstance, StatusMessage) ->
$controller('AdminOrderCycleExchangesCtrl', {$scope: $scope, ocInstance: ocInstance, $location: $location})
$scope.view = 'outgoing'
$scope.variantSuppliedToOrderCycle = (variant) ->
OrderCycle.variantSuppliedToOrderCycle(variant)
$scope.incomingExchangeVariantsFor = (enterprise_id) ->
$filter('filterExchangeVariants')(OrderCycle.incomingExchangesVariants(), $scope.order_cycle.visible_variants_for_outgoing_exchanges[enterprise_id])
$scope.exchangeTotalVariants = (exchange) ->
totalNumberOfVariants = $scope.incomingExchangeVariantsFor(exchange.enterprise_id).length
$scope.setSelectAllVariantsCheckboxValue(exchange, totalNumberOfVariants)
totalNumberOfVariants
$scope.addDistributor = ($event) ->
$event.preventDefault()
OrderCycle.addDistributor $scope.new_distributor_id
$scope.submit = ($event, destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
OrderCycle.update(destination, $scope.order_cycle_form) if OrderCycle.confirmNoDistributors()

View File

@@ -1,38 +1,58 @@
angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, $controller, $window, OrderCycle, Enterprise, EnterpriseFee, ExchangeProduct, StatusMessage, Schedules, RequestMonitor, ocInstance) ->
$controller('AdminOrderCycleBasicCtrl', {$scope: $scope, ocInstance: ocInstance})
angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, Schedules, RequestMonitor, ocInstance) ->
$scope.StatusMessage = StatusMessage
$scope.OrderCycle = OrderCycle
$scope.schedules = Schedules.index({enterprise_id: ocInstance.coordinator_id})
$scope.order_cycle = OrderCycle.new {coordinator_id: ocInstance.coordinator_id}, =>
# TODO: make this a get method, which only fetches one enterprise
$scope.enterprises = Enterprise.index {coordinator_id: ocInstance.coordinator_id}, (enterprises) =>
$scope.init(enterprises)
$scope.enterprise_fees = EnterpriseFee.index(coordinator_id: ocInstance.coordinator_id)
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue
$scope.$watch 'order_cycle_form.$valid', (isValid) ->
StatusMessage.setValidation(isValid)
$scope.init = (enterprises) ->
enterprise = enterprises[Object.keys(enterprises)[0]]
OrderCycle.order_cycle.coordinator_id = enterprise.id
OrderCycle.addDistributor enterprise.id, $scope.setOutgoingExchange
OrderCycle.addSupplier enterprise.id, $scope.loadExchangeProducts
$scope.setOutgoingExchange = ->
OrderCycle.addSupplier enterprise.id
OrderCycle.addDistributor enterprise.id
$scope.outgoing_exchange = OrderCycle.order_cycle.outgoing_exchanges[0]
$scope.loadExchangeProducts = ->
$scope.incoming_exchange = OrderCycle.order_cycle.incoming_exchanges[0]
params = { enterprise_id: $scope.incoming_exchange.enterprise_id, incoming: true }
ExchangeProduct.index params, $scope.storeProductsAndSelectAllVariants
$scope.storeProductsAndSelectAllVariants = (products) ->
$scope.enterprises[$scope.incoming_exchange.enterprise_id].supplied_products = products
# All variants start as checked
OrderCycle.setExchangeVariants($scope.incoming_exchange,
Enterprise.suppliedVariants($scope.incoming_exchange.enterprise_id), true)
OrderCycle.setExchangeVariants(OrderCycle.order_cycle.incoming_exchanges[0],
Enterprise.suppliedVariants(enterprise.id), true)
OrderCycle.order_cycle.coordinator_id = enterprise.id
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
$scope.removeDistributionOfVariant = angular.noop
$scope.setExchangeVariants = (exchange, variants, selected) ->
OrderCycle.setExchangeVariants(exchange, variants, selected)
$scope.suppliedVariants = (enterprise_id) ->
Enterprise.suppliedVariants(enterprise_id)
$scope.addCoordinatorFee = ($event) ->
$event.preventDefault()
OrderCycle.addCoordinatorFee()
$scope.removeCoordinatorFee = ($event, index) ->
$event.preventDefault()
OrderCycle.removeCoordinatorFee(index)
$scope.enterpriseFeesForEnterprise = (enterprise_id) ->
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
$scope.submit = ($event, destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
OrderCycle.mirrorIncomingToOutgoingProducts()
OrderCycle.create(destination) if OrderCycle.confirmNoDistributors()
OrderCycle.create(destination)
$scope.cancel = (destination) ->
$window.location = destination

View File

@@ -1,27 +1,51 @@
angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $controller, $location, $window, OrderCycle, Enterprise, EnterpriseFee, ExchangeProduct, Schedules, RequestMonitor, StatusMessage, ocInstance) ->
$controller('AdminOrderCycleBasicCtrl', {$scope: $scope, ocInstance: ocInstance})
angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $location, $window, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, StatusMessage, ocInstance) ->
$scope.orderCycleId = ->
$location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1]
$scope.StatusMessage = StatusMessage
$scope.enterprises = Enterprise.index(order_cycle_id: $scope.orderCycleId())
$scope.enterprise_fees = EnterpriseFee.index(order_cycle_id: $scope.orderCycleId())
$scope.schedules = Schedules.index({enterprise_id: ocInstance.coordinator_id})
$scope.OrderCycle = OrderCycle
$scope.order_cycle = OrderCycle.load $scope.orderCycleId(), (order_cycle) =>
$scope.init()
$scope.$watch 'order_cycle_form.$dirty', (newValue) ->
StatusMessage.display 'notice', t("admin.unsaved_changes") if newValue
$scope.$watch 'order_cycle_form.$valid', (isValid) ->
StatusMessage.setValidation(isValid)
$scope.loaded = ->
Enterprise.loaded && EnterpriseFee.loaded && OrderCycle.loaded && !RequestMonitor.loading
$scope.init = ->
$scope.outgoing_exchange = OrderCycle.order_cycle.outgoing_exchanges[0]
$scope.loadExchangeProducts()
$scope.loadExchangeProducts = ->
exchange = OrderCycle.order_cycle.incoming_exchanges[0]
ExchangeProduct.index { exchange_id: exchange.id }, (products) ->
$scope.enterprises[exchange.enterprise_id].supplied_products = products
$scope.enterpriseFeesForEnterprise = (enterprise_id) ->
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
$scope.removeDistributionOfVariant = angular.noop
$scope.setExchangeVariants = (exchange, variants, selected) ->
OrderCycle.setExchangeVariants(exchange, variants, selected)
$scope.suppliedVariants = (enterprise_id) ->
Enterprise.suppliedVariants(enterprise_id)
$scope.addCoordinatorFee = ($event) ->
$event.preventDefault()
OrderCycle.addCoordinatorFee()
$scope.removeCoordinatorFee = ($event, index) ->
$event.preventDefault()
OrderCycle.removeCoordinatorFee(index)
$scope.submit = ($event, destination) ->
$event.preventDefault()
StatusMessage.display 'progress', t('js.saving')
OrderCycle.mirrorIncomingToOutgoingProducts()
OrderCycle.update(destination, $scope.order_cycle_form) if OrderCycle.confirmNoDistributors()
OrderCycle.update(destination, $scope.order_cycle_form)
$scope.cancel = (destination) ->
$window.location = destination

View File

@@ -12,6 +12,7 @@ angular.module('admin.orderCycles').factory('Enterprise', ($resource) ->
enterprises: {}
producer_enterprises: []
hub_enterprises: []
supplied_products: []
loaded: false
index: (params={}, callback=null) ->
@@ -21,6 +22,9 @@ angular.module('admin.orderCycles').factory('Enterprise', ($resource) ->
@producer_enterprises.push(enterprise) if enterprise.is_primary_producer
@hub_enterprises.push(enterprise) if enterprise.sells == 'any'
for product in enterprise.supplied_products
@supplied_products.push(product)
@loaded = true
(callback || angular.noop)(@enterprises)
@@ -35,4 +39,13 @@ angular.module('admin.orderCycles').factory('Enterprise', ($resource) ->
variant.id for variant in product.variants
else
[product.master_id]
totalVariants: (enterprise) ->
numVariants = 0
if enterprise
counts = for product in enterprise.supplied_products
numVariants += if product.variants.length == 0 then 1 else product.variants.length
numVariants
})

View File

@@ -1,16 +0,0 @@
angular.module('admin.orderCycles').factory('ExchangeProduct', ($resource) ->
ExchangeProductResource = $resource('/api/exchanges/:exchange_id/products.json', {}, {
'index': { method: 'GET' }
'variant_count': { method: 'GET', params: { action_name: "variant_count" }}
})
{
ExchangeProductResource: ExchangeProductResource
index: (params={}, callback=null) ->
ExchangeProductResource.index params, (data) =>
(callback || angular.noop)(data.products, data.pagination.pages, data.pagination.results)
countVariants: (params={}, callback=null) ->
ExchangeProductResource.variant_count params, (data) =>
(callback || angular.noop)(data.count)
})

View File

@@ -1,4 +1,4 @@
angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, $timeout, StatusMessage, Panels) ->
angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, StatusMessage, Panels) ->
OrderCycleResource = $resource '/admin/order_cycles/:action_name/:order_cycle_id.json', {}, {
'index': { method: 'GET', isArray: true}
'new' : { method: 'GET', params: { action_name: "new" } }
@@ -44,15 +44,11 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, $
@removeDistributionOfVariant(variant.id) if exchange.incoming
addSupplier: (new_supplier_id, callback) ->
this.order_cycle.incoming_exchanges.push({enterprise_id: new_supplier_id, incoming: true, active: true, variants: {}, enterprise_fees: []})
$timeout ->
(callback || angular.noop)()
addSupplier: (new_supplier_id) ->
this.order_cycle.incoming_exchanges.push({enterprise_id: new_supplier_id, incoming: true, active: true, variants: {}, enterprise_fees: []})
addDistributor: (new_distributor_id, callback) ->
this.order_cycle.outgoing_exchanges.push({ enterprise_id: new_distributor_id, incoming: false, active: true, variants: {}, enterprise_fees: [] })
$timeout ->
(callback || angular.noop)()
addDistributor: (new_distributor_id) ->
this.order_cycle.outgoing_exchanges.push({enterprise_id: new_distributor_id, incoming: false, active: true, variants: {}, enterprise_fees: []})
removeExchange: (exchange) ->
if exchange.incoming
@@ -75,6 +71,18 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, $
removeExchangeFee: (exchange, index) ->
exchange.enterprise_fees.splice(index, 1)
productSuppliedToOrderCycle: (product) ->
product_variant_ids = (variant.id for variant in product.variants)
variant_ids = [product.master_id].concat(product_variant_ids)
incomingExchangesVariants = this.incomingExchangesVariants()
# TODO: This is an O(n^2) implementation of set intersection and thus is slooow.
# Use a better algorithm if needed.
# Also, incomingExchangesVariants is called every time, when it only needs to be
# called once per change to incoming variants. Some sort of caching?
ids = (variant_id for variant_id in variant_ids when incomingExchangesVariants.indexOf(variant_id) != -1)
ids.length > 0
variantSuppliedToOrderCycle: (variant) ->
this.incomingExchangesVariants().indexOf(variant.id) != -1
@@ -135,18 +143,15 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, $
delete(service.order_cycle.exchanges)
service.loaded = true
$timeout ->
(callback || angular.noop)(service.order_cycle)
(callback || angular.noop)(service.order_cycle)
this.order_cycle
create: (destination) ->
return unless @confirmNoDistributors()
oc = new OrderCycleResource({order_cycle: this.dataForSubmit()})
oc.$create (data) ->
if destination? && destination.length != 0
$window.location = destination
else if data.edit_path?
$window.location = data.edit_path
$window.location = destination
, (response) ->
if response.data.errors?
StatusMessage.display('failure', response.data.errors[0])
@@ -154,6 +159,7 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, $
StatusMessage.display('failure', t('js.order_cycles.create_failure'))
update: (destination, form) ->
return unless @confirmNoDistributors()
oc = new OrderCycleResource({order_cycle: this.dataForSubmit()})
oc.$update {order_cycle_id: this.order_cycle.id, reloading: (if destination? then 1 else 0)}, (data) =>
form.$setPristine() if form
@@ -167,6 +173,7 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, $
else
StatusMessage.display('failure', t('js.order_cycles.update_failure'))
confirmNoDistributors: ->
if @order_cycle.outgoing_exchanges.length == 0
confirm t('js.order_cycles.no_distributors')

View File

@@ -1,4 +1,4 @@
angular.module("admin.orders").controller "ordersCtrl", ($scope, $timeout, RequestMonitor, Orders, SortOptions, $window, $filter) ->
angular.module("admin.orders").controller "ordersCtrl", ($scope, RequestMonitor, Orders, SortOptions, $window, $filter) ->
$scope.RequestMonitor = RequestMonitor
$scope.pagination = Orders.pagination
$scope.orders = Orders.all
@@ -13,7 +13,6 @@ angular.module("admin.orders").controller "ordersCtrl", ($scope, $timeout, Reque
$scope.selected = false
$scope.select_all = false
$scope.poll = 0
$scope.rowStatus = {}
$scope.initialise = ->
$scope.per_page = 15
@@ -70,23 +69,6 @@ angular.module("admin.orders").controller "ordersCtrl", ($scope, $timeout, Reque
$scope.fetchResults()
, true
$scope.capturePayment = (order) ->
$scope.rowAction('capture', order)
$scope.shipOrder = (order) ->
$scope.rowAction('ship', order)
$scope.rowAction = (action, order) ->
$scope.rowStatus[order.id] = "loading"
Orders[action](order).$promise.then (data) ->
$scope.rowStatus[order.id] = "success"
$timeout(->
$scope.rowStatus[order.id] = null
, 1500)
, (error) ->
$scope.rowStatus[order.id] = "error"
$scope.changePage = (newPage) ->
$scope.page = newPage
$scope.fetchResults(newPage)

View File

@@ -5,14 +5,4 @@ angular.module("admin.resources").factory 'OrderResource', ($resource) ->
method: 'GET'
'update':
method: 'PUT'
'capture':
url: '/api/orders/:id/capture.json'
method: 'PUT'
params:
id: '@id'
'ship':
url: '/api/orders/:id/ship.json'
method: 'PUT'
params:
id: '@id'
})

View File

@@ -44,19 +44,5 @@ angular.module("admin.resources").factory 'Orders', ($q, OrderResource, RequestM
changed.push attr unless attr is "$$hashKey"
changed
capture: (order) ->
@processAction('capture', order)
ship: (order) ->
@processAction('ship', order)
processAction: (action, order) ->
OrderResource[action] {id: order.number}, (data) =>
if data.id
angular.merge(order, data)
data
, (response) =>
response.data
resetAttribute: (order, attribute) ->
order[attribute] = @pristineByID[order.id][attribute]

View File

@@ -20,4 +20,4 @@ angular.module("admin.subscriptions").controller "ProductsPanelController", ($sc
keys = Object.keys(response.data.errors)
StatusMessage.display 'failure', response.data.errors[keys[0]][0]
else
StatusMessage.display 'failure', t('js.admin.subscriptions.error_saving')
StatusMessage.display 'success', t('js.changes_saved')

View File

@@ -1,4 +1,4 @@
angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl", ($scope, $http, $timeout, Indexer, Columns, Views, PagedFetcher, StatusMessage, RequestMonitor, hubs, producers, hubPermissions, InventoryItems, VariantOverrides, DirtyVariantOverrides) ->
angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl", ($scope, $http, $timeout, Indexer, Columns, Views, SpreeApiAuth, PagedFetcher, StatusMessage, RequestMonitor, hubs, producers, hubPermissions, InventoryItems, VariantOverrides, DirtyVariantOverrides) ->
$scope.hubs = Indexer.index hubs
$scope.hub_id = if hubs.length == 1 then hubs[0].id else null
$scope.products = []
@@ -39,7 +39,13 @@ angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl",
$scope.producerFilter != 0 || $scope.query != ''
$scope.initialise = ->
$scope.fetchProducts()
SpreeApiAuth.authorise()
.then ->
$scope.spree_api_key_ok = true
$scope.fetchProducts()
.catch (message) ->
$scope.api_error_msg = message
$scope.fetchProducts = ->
url = "/api/products/overridable?page=::page::;per_page=100"

View File

@@ -1,4 +1,4 @@
Darkswarm.controller "OrderCycleCtrl", ($scope, $rootScope, $timeout, OrderCycle) ->
Darkswarm.controller "OrderCycleCtrl", ($scope, $timeout, OrderCycle) ->
$scope.order_cycle = OrderCycle.order_cycle
$scope.OrderCycle = OrderCycle
@@ -6,12 +6,11 @@ Darkswarm.controller "OrderCycleCtrl", ($scope, $rootScope, $timeout, OrderCycle
# This is a hack. We should probably write our own "popover" directive
# That takes an expression instead of a trigger, and binds to that
$timeout =>
$rootScope.$broadcast 'orderCycleSelected'
if !$scope.OrderCycle.selected()
$("#order_cycle_id").trigger("openTrigger")
Darkswarm.controller "OrderCycleChangeCtrl", ($scope, $rootScope, $timeout, OrderCycle, Products, Variants, Cart, ChangeableOrdersAlert) ->
Darkswarm.controller "OrderCycleChangeCtrl", ($scope, $timeout, OrderCycle, Products, Variants, Cart, ChangeableOrdersAlert) ->
# Track previous order cycle id for use with revertOrderCycle()
$scope.previous_order_cycle_id = OrderCycle.order_cycle.order_cycle_id
$scope.$watch 'order_cycle.order_cycle_id', (newValue, oldValue)->
@@ -33,4 +32,3 @@ Darkswarm.controller "OrderCycleChangeCtrl", ($scope, $rootScope, $timeout, Orde
Products.update()
Cart.reloadFinalisedLineItems()
ChangeableOrdersAlert.reload()
$rootScope.$broadcast 'orderCycleSelected'

View File

@@ -1,65 +1,41 @@
Darkswarm.controller "ProductsCtrl", ($scope, $filter, $rootScope, Products, OrderCycle, OrderCycleResource, FilterSelectorsService, Cart, Dereferencer, Taxons, Properties, currentHub, $timeout) ->
Darkswarm.controller "ProductsCtrl", ($scope, $filter, $rootScope, Products, OrderCycle, FilterSelectorsService, Cart, Taxons, Properties) ->
$scope.Products = Products
$scope.Cart = Cart
$scope.query = ""
$scope.taxonSelectors = FilterSelectorsService.createSelectors()
$scope.propertySelectors = FilterSelectorsService.createSelectors()
$scope.filtersActive = true
$scope.page = 1
$scope.per_page = 10
$scope.limit = 10
$scope.order_cycle = OrderCycle.order_cycle
$scope.supplied_taxons = null
$scope.supplied_properties = null
# $scope.infiniteDisabled = true
$rootScope.$on "orderCycleSelected", ->
$scope.update_filters()
$scope.clearAll()
# All of this logic basically just replicates the functionality filtering an ng-repeat
# except that it allows us to filter a separate list before rendering, meaning that
# we can get much better performance when applying filters by resetting the limit on the
# number of products being rendered each time a filter is changed.
$scope.update_filters = ->
order_cycle_id = OrderCycle.order_cycle.order_cycle_id
$scope.$watch "Products.loading", (newValue, oldValue) ->
$scope.updateFilteredProducts()
$scope.$broadcast("loadFilterSelectors") if !newValue
return unless order_cycle_id
$scope.incrementLimit = ->
if $scope.limit < Products.products.length
$scope.limit += 10
$scope.updateVisibleProducts()
params = {
id: order_cycle_id,
distributor: currentHub.id
}
OrderCycleResource.taxons params, (data)=>
$scope.supplied_taxons = {}
data.map( (taxon) ->
$scope.supplied_taxons[taxon.id] = Taxons.taxons_by_id[taxon.id]
)
OrderCycleResource.properties params, (data)=>
$scope.supplied_properties = {}
data.map( (property) ->
$scope.supplied_properties[property.id] = Properties.properties_by_id[property.id]
)
$scope.$watch 'query', -> $scope.updateFilteredProducts()
$scope.$watchCollection 'activeTaxons', -> $scope.updateFilteredProducts()
$scope.$watchCollection 'activeProperties', -> $scope.updateFilteredProducts()
$scope.loadMore = ->
if ($scope.page * $scope.per_page) <= Products.products.length
$scope.loadMoreProducts()
$scope.updateFilteredProducts = ->
$scope.limit = 10
f1 = $filter('products')(Products.products, $scope.query)
f2 = $filter('taxons')(f1, $scope.activeTaxons)
$scope.filteredProducts = $filter('properties')(f2, $scope.activeProperties)
$scope.updateVisibleProducts()
$scope.$watch 'query', (newValue, oldValue) -> $scope.loadProducts() if newValue != oldValue
$scope.$watchCollection 'activeTaxons', (newValue, oldValue) -> $scope.loadProducts() if newValue != oldValue
$scope.$watchCollection 'activeProperties', (newValue, oldValue) -> $scope.loadProducts() if newValue != oldValue
$scope.loadProducts = ->
$scope.page = 1
Products.update($scope.queryParams())
$scope.loadMoreProducts = ->
Products.update($scope.queryParams($scope.page + 1), true)
$scope.page += 1
$scope.queryParams = (page = null) ->
{
id: $scope.order_cycle.order_cycle_id,
page: page || $scope.page,
per_page: $scope.per_page,
'q[name_or_meta_keywords_or_supplier_name_cont]': $scope.query,
'q[properties_id_or_supplier_properties_id_in_any][]': $scope.activeProperties,
'q[primary_taxon_id_in_any][]': $scope.activeTaxons
}
$scope.updateVisibleProducts = ->
$scope.visibleProducts = $filter('limitTo')($scope.filteredProducts, $scope.limit)
$scope.searchKeypress = (e)->
code = e.keyCode || e.which
@@ -80,11 +56,3 @@ Darkswarm.controller "ProductsCtrl", ($scope, $filter, $rootScope, Products, Ord
$scope.query = ""
$scope.taxonSelectors.clearAll()
$scope.propertySelectors.clearAll()
$scope.refreshStaleData = ->
# If the products template has already been loaded but the controller is being initialized
# again after the template has switched, refresh loaded data to avoid conflicts
if $scope.Products.products.length > 0
$scope.Products.products = []
$scope.update_filters()
$scope.loadProducts()

View File

@@ -5,15 +5,13 @@ Darkswarm.directive "tabsetCtrl", (Tabsets, $location) ->
selected: "@"
navigate: "="
prefix: "@?"
alwaysopen: "="
controller: ($scope, $element) ->
if $scope.navigate
path = $location.path()?.match(/^\/\w+$/)?[0]
$scope.selected = path[1..] if path
this.toggle = (name) ->
state = if $scope.alwaysopen then 'open' else null
Tabsets.toggle($scope.id, name, state)
Tabsets.toggle($scope.id, name)
this.select = (selection) ->
$scope.$broadcast("selection:changed", selection)

View File

@@ -1,21 +0,0 @@
Darkswarm.factory 'OrderCycleResource', ($resource) ->
$resource('/api/order_cycles/:id', {}, {
'products':
method: 'GET'
isArray: true
url: '/api/order_cycles/:id/products'
params:
id: '@id'
'taxons':
method: 'GET'
isArray: true
url: '/api/order_cycles/:id/taxons'
params:
id: '@id'
'properties':
method: 'GET'
isArray: true
url: '/api/order_cycles/:id/properties'
params:
id: '@id'
})

View File

@@ -1,34 +1,26 @@
Darkswarm.factory 'Products', (OrderCycleResource, OrderCycle, Shopfront, currentHub, Dereferencer, Taxons, Properties, Cart, Variants) ->
Darkswarm.factory 'Products', ($resource, Shopfront, Dereferencer, Taxons, Properties, Cart, Variants) ->
new class Products
constructor: ->
@update()
products: []
fetched_products: []
# TODO: don't need to scope this into object
# Already on object as far as controller scope is concerned
products: null
loading: true
update: (params = {}, load_more = false) =>
update: =>
@loading = true
order_cycle_id = OrderCycle.order_cycle.order_cycle_id
@products = []
$resource("/shop/products").query (products)=>
@products = products
if order_cycle_id == undefined
@loading = false
return
params['id'] = order_cycle_id
params['distributor'] = currentHub.id
OrderCycleResource.products params, (data)=>
@products = [] unless load_more
@fetched_products = data
@extend()
@dereference()
@registerVariants()
@products = @products.concat(@fetched_products)
@loading = false
extend: ->
for product in @fetched_products
for product in @products
if product.variants?.length > 0
prices = (v.price for v in product.variants)
product.price = Math.min.apply(null, prices)
@@ -38,7 +30,7 @@ Darkswarm.factory 'Products', (OrderCycleResource, OrderCycle, Shopfront, curren
product.largeImage = product.images[0]?.large_url if product.images
dereference: ->
for product in @fetched_products
for product in @products
product.supplier = Shopfront.producers_by_id[product.supplier.id]
Dereferencer.dereference product.taxons, Taxons.taxons_by_id
@@ -48,7 +40,7 @@ Darkswarm.factory 'Products', (OrderCycleResource, OrderCycle, Shopfront, curren
# May return different objects! If the variant has already been registered
# by another service, we fetch those
registerVariants: ->
for product in @fetched_products
for product in @products
if product.variants
product.variant_names = ""
product.variants = for variant in product.variants

View File

@@ -1,7 +1,5 @@
.row.exchange-distributed-products{'ng-init' => 'initializeExchangeProductsPanel(exchange)'}
.sixteen.columns.alpha.omega{ 'ng-show' => 'enterprises[exchange.enterprise_id].supplied_products.length != 0' }
%div{ 'ng-include' => "'admin/panels/exchange_products_panel_header.html'" }
.row.exchange-distributed-products
.sixteen.columns.alpha.omega
.exchange-select-all-variants
%label
%input{ type: 'checkbox', name: 'order_cycle_outgoing_exchange_{{ $parent.$index }}_select_all_variants',
@@ -9,10 +7,11 @@
'ng-model' => 'exchange.select_all_variants',
'ng-change' => 'setExchangeVariants(exchange, incomingExchangeVariantsFor(exchange.enterprise_id), exchange.select_all_variants)',
'id' => 'order_cycle_outgoing_exchange_{{ $parent.$index }}_select_all_variants' }
{{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }}
{{ 'admin.select_all' | t }}
.exchange-products{ 'ng-hide' => 'productsLoading()' }
.exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products | filter:visibleProducts:exchange:order_cycle.visible_variants_for_outgoing_exchanges' }
.exchange-products
-# Scope product list based on permissions the current user has to view variants in this exchange
.exchange-product{'ng-repeat' => 'product in supplied_products | filter:productSuppliedToOrderCycle | visibleProducts:exchange:order_cycle.visible_variants_for_outgoing_exchanges | orderBy:"name"' }
.exchange-product-details
%label
%img{'ng-src' => '{{ product.image_url }}'}
@@ -27,5 +26,3 @@
'id' => 'order_cycle_outgoing_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}',
'ng-disabled' => '!order_cycle.editable_variants_for_outgoing_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_outgoing_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' }
{{ variant.label }}
%div{ 'ng-include' => "'admin/panels/exchange_products_panel_footer.html'" }

View File

@@ -1,11 +0,0 @@
.pagination{ 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages && !productsLoading()'}
.button{ 'ng-click' => 'loadMoreExchangeProducts(exchange)' }
{{ 'js.admin.panels.exchange_products.load_more_products' | t }}
.button{ 'ng-click' => 'loadAllExchangeProducts(exchange)' }
{{ 'js.admin.panels.exchange_products.load_all_products' | t }}
.sixteen.columns.alpha#loading{ 'ng-show' => 'productsLoading()' }
%br
%img.spinner{ src: "/assets/spinning-circles.svg" }
%h1
{{ 'js.admin.panels.exchange_products.loading_products' | t }}

View File

@@ -1,5 +0,0 @@
.exchange-load-all-variants
%div
{{ 'js.admin.panels.exchange_products.products_loaded' | t:{ num_of_products_loaded: enterprises[exchange.enterprise_id].supplied_products.length, total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }}
%a{ 'ng-click' => 'loadAllExchangeProducts(exchange)', 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages' }
{{ 'js.admin.panels.exchange_products.load_all_products' | t }}

View File

@@ -1,12 +0,0 @@
.row.exchange-supplied-products
.sixteen.columns.alpha.omega
.exchange-select-all-variants
%label
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants',
value: 1,
'ng-model' => 'exchange.select_all_variants',
'ng-change' => 'setExchangeVariants(exchange, suppliedVariants(exchange.enterprise_id), exchange.select_all_variants)',
'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' }
{{ 'admin.select_all' | t }}
%div{ 'ng-include' => "'admin/panels/exchange_products_supplied_list.html'" }

View File

@@ -1,16 +0,0 @@
.row.exchange-supplied-products{'ng-init' => 'initializeExchangeProductsPanel(exchange)'}
.sixteen.columns.alpha.omega{ 'ng-show' => 'enterprises[exchange.enterprise_id].supplied_products.length != 0' }
%div{ 'ng-include' => "'admin/panels/exchange_products_panel_header.html'" }
.exchange-select-all-variants
%label
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants',
value: 1,
'ng-model' => 'exchange.select_all_variants',
'ng-change' => 'selectAllVariants(exchange, exchange.select_all_variants)',
'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' }
{{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }}
%div{ 'ng-include' => "'admin/panels/exchange_products_supplied_list.html'" }
%div{ 'ng-include' => "'admin/panels/exchange_products_panel_footer.html'" }

View File

@@ -1,16 +0,0 @@
.exchange-products{ 'ng-hide' => 'productsLoading()' }
.exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products'}
.exchange-product-details
%label
%img{'ng-src' => '{{ product.image_url }}'}
{{ product.name }}
.exchange-product-variant{'ng-repeat' => 'variant in product.variants'}
%label
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}',
value: 1,
'ng-model' => 'exchange.variants[variant.id]',
'ofn-sync-distributions' => '{{ variant.id }}',
'id' => 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}',
'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' }
{{ variant.label }}

View File

@@ -0,0 +1,49 @@
.row.exchange-supplied-products
.sixteen.columns.alpha.omega
.exchange-select-all-variants
%label
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants',
value: 1,
'ng-model' => 'exchange.select_all_variants',
'ng-change' => 'setExchangeVariants(exchange, suppliedVariants(exchange.enterprise_id), exchange.select_all_variants)',
'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' }
{{ 'admin.select_all' | t }}
.exchange-products
-# No need to scope product list based on permissions, because if an incoming exchange is visible,
-# then all of the variants within it should be visible. May change in the future?
.exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products'}
.exchange-product-details
%label
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $parent.$index }}_variants_{{ product.master_id }}',
value: 1,
'ng-hide' => 'product.variants.length > 0',
'ng-model' => 'exchange.variants[product.master_id]',
'ofn-sync-distributions' => '{{ product.master_id }}',
'id' => 'order_cycle_incoming_exchange_{{ $parent.$index }}_variants_{{ product.master_id }}',
'ng-disabled' => 'product.variants.length > 0 || !order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(product.master_id) < 0' }
%img{'ng-src' => '{{ product.image_url }}'}
{{ product.name }}
-# When the master variant is in the order cycle but the product has variants, we want to
-# be able to remove the master variant, since it serves no purpose. Display a checkbox to do so.
.exchange-product-variant{'ng-show' => 'exchange.variants[product.master_id] && product.variants.length > 0'}
%label
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $parent.$index }}_variants_{{ product.master_id }}',
value: 1,
'ng-model' => 'exchange.variants[product.master_id]',
'ofn-sync-distributions' => '{{ product.master_id }}',
'id' => 'order_cycle_incoming_exchange_{{ $parent.$index }}_variants_{{ product.master_id }}',
'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(product.master_id) < 0' }
{{ 'admin.obsolete_master' | t }}
.exchange-product-variant{'ng-repeat' => 'variant in product.variants'}
%label
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}',
value: 1,
'ng-model' => 'exchange.variants[variant.id]',
'ofn-sync-distributions' => '{{ variant.id }}',
'id' => 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}',
'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' }
{{ variant.label }}

View File

@@ -1,9 +1,9 @@
#save-bar.animate-show{ ng: { show: 'dirty || persist || StatusMessage.active()' } }
.container
.seven.columns.alpha
.eight.columns.alpha
%h5#status-message{ ng: { show: "StatusMessage.invalidMessage == ''", style: 'StatusMessage.statusMessage.style' } }
{{ StatusMessage.statusMessage.text || "&nbsp;" }}
%h5#status-message{ ng: { show: "StatusMessage.invalidMessage !== ''" }, style: 'color: #da5354' }
{{ StatusMessage.invalidMessage || "&nbsp;" }}
.nine.columns.omega.text-right{ ng: { transclude: true } }
.eight.columns.omega.text-right{ ng: { transclude: true } }

View File

@@ -17,7 +17,7 @@
.small-4.medium-2.large-2.columns.variant-price
.table-cell.price
%i.ofn-i_009-close
{{ variant.price_with_fees | localizeCurrency }}
{{ ::variant.price_with_fees | localizeCurrency }}
-# Now in a template in app/assets/javascripts/templates !
%price-breakdown{"price-breakdown" => "_", variant: "variant",

View File

@@ -1,32 +0,0 @@
@import '../variables';
.row-loading {
opacity: .5;
}
.row-loading-icons {
margin-left: 3em;
position: absolute;
.spinner {
border: 0;
width: 2.3em;
}
i {
font-size: 2.3em;
opacity: .75;
&::before {
vertical-align: top;
}
&.success {
color: $spree-green;
}
&.error {
color: $warning-red;
}
}
}

View File

@@ -1,4 +0,0 @@
#powerTip {
max-width: 240px;
white-space: normal;
}

View File

@@ -19,9 +19,6 @@ ul.wizard-progress {
line-height: 30px;
padding: 0 25px 0 40px;
position: relative;
a {
color: #494949;
}
&:first-child {
padding-left: 25px;
border-top-left-radius: 3px;
@@ -65,9 +62,6 @@ ul.wizard-progress {
&.current {
background-color: $color_selected;
color: #fff;
a {
color: #fff;
}
&:after {
background-color: $color_selected;
}

View File

@@ -104,13 +104,9 @@ form.order_cycle {
width: 20px;
}
.exchange-load-all-variants {
margin: 0px 5px 20px 5px;
}
.exchange-select-all-variants {
clear: both;
margin: 15px 5px 25px 5px;
margin: 5px;
}
.exchange-products {
@@ -213,7 +209,6 @@ table#listing_enterprise_groups {
#loading {
text-align: center;
img.spinner {
border: 0px;
width: 100px;
height: 100px;
}
@@ -260,9 +255,6 @@ text-angular {
background-color: #4583bf;
}
}
a {
color: $spree-green
}
}
span.required {

View File

@@ -19,10 +19,6 @@ ordercycle {
margin: 0;
font-weight: 700;
}
@media all and (max-width: 768px) {
z-index: 10;
}
}
}

View File

@@ -114,7 +114,12 @@
margin-bottom: 0px;
}
.shopfront-message {
.alert-box.shopfront-message {
border: 2px solid $clr-turquoise;
border-radius: 5px;
background-color: $clr-turquoise-light;
color: $clr-turquoise;
a {
color: #0096ad;

View File

@@ -4,25 +4,20 @@
// Tabs styling
.tabset-ctrl#shop-tabs {
background: url("/assets/gray_jean.png") top left repeat;
.tab-buttons {
background: url("/assets/gray_jean.png") top left repeat;
@include box-shadow(inset 0 2px 3px 0 rgba(0, 0, 0, 0.15));
@include box-shadow(inset 0 2px 3px 0 rgba(0, 0, 0, 0.15));
color: $dark-grey;
.row:first-child {
display: flex;
justify-content: space-between;
}
}
display: block;
color: $dark-grey;
.tab {
text-align: center;
border-top: 4px solid transparent;
display: inline-block;
width: 100%;
@media all and (max-width: 640px) {
text-align: left;
}
>a {
outline: none;
@@ -40,7 +35,7 @@
line-height: 1;
font-size: 0.875em;
text-shadow: 0 -1px 1px #ffffff;
padding: 1em 2em;
padding: 1em;
border: none;
&:hover, &:focus, &:active {
@@ -55,13 +50,51 @@
padding: 0.35em 0 0.65em 0;
text-shadow: none;
}
&:after {
padding-left: 8px;
content: "";
visibility: hidden;
@include icon-font;
@media all and (max-width: 640px) {
content: "";
}
}
}
&:hover {
a:after {
visibility: visible;
}
}
&.selected {
border-bottom: 4px solid $clr-brick;
border-top: 4px solid $clr-brick;
@media all and (max-width: 640px) {
border-top: 4px solid transparent;
background-color: $clr-brick;
}
a {
color: $clr-brick;
@media all and (max-width: 640px) {
color: white;
}
}
a:after {
content: "";
visibility: visible;
@include icon-font;
@media all and (max-width: 640px) {
content: "";
}
}
}
}
@@ -69,45 +102,43 @@
// content revealed in accordion
.tab-view {
margin-bottom: 5em;
margin-bottom: 0;
padding: 0;
background: none;
border: none;
.content {
padding: 1.25em 0;
background-color: $white;
img {
margin: 0px 0px 0px 40px;
}
img {
margin: 0px 0px 0px 40px;
p {
max-width: 100%;
@media all and (max-width: 768px) {
height: auto !important;
}
}
h5 {
margin-bottom: 1em;
}
ul {
list-style-type: none;
padding-left: none;
}
p {
max-width: 100%;
.header {
text-align: center;
text-transform: uppercase;
color: $dark-grey;
border-bottom: 1px solid $disabled-dark;
margin-top: 0.75rem;
margin-bottom: 0.75rem;
padding-bottom: 0.25rem;
font-size: 0.875rem;
}
@media all and (max-width: 768px) {
height: auto !important;
}
}
ul {
list-style-type: none;
padding-left: none;
}
.header {
text-align: center;
text-transform: uppercase;
color: $dark-grey;
border-bottom: 1px solid $disabled-dark;
margin-top: 0.75rem;
margin-bottom: 0.75rem;
padding-bottom: 0.25rem;
font-size: 0.875rem;
}
.panel {
padding-bottom: 1.25em;
border-color: $clr-brick-bright;
background-color: rgba(255, 255, 255, 0);
}
}
}

View File

@@ -4,18 +4,9 @@ module Admin
#
def index
order_params = params[:q].andand.delete :order
order_permissions = ::Permissions::Order.new(spree_current_user)
orders = order_permissions.
editable_orders.ransack(order_params).result
line_items = order_permissions.
editable_line_items.where(order_id: orders).
includes(variant: { option_values: :option_type }).
ransack(params[:q]).result.
reorder('spree_line_items.order_id ASC, spree_line_items.id ASC')
render_as_json line_items
orders = OpenFoodNetwork::Permissions.new(spree_current_user).editable_orders.ransack(order_params).result
line_items = OpenFoodNetwork::Permissions.new(spree_current_user).editable_line_items.where(order_id: orders).ransack(params[:q])
render_as_json line_items.result.reorder('order_id ASC, id ASC')
end
# PUT /admin/bulk_line_items/:id.json

View File

@@ -0,0 +1,27 @@
require 'open_food_network/products_cache_integrity_checker'
module Admin
class CacheSettingsController < Spree::Admin::BaseController
def edit
@results = Exchange.cachable.map do |exchange|
checker = OpenFoodNetwork::ProductsCacheIntegrityChecker
.new(exchange.receiver, exchange.order_cycle)
{
distributor: exchange.receiver,
order_cycle: exchange.order_cycle,
status: checker.ok?,
diff: checker.diff
}
end
end
def update
Spree::Config.set(params[:preferences])
respond_to do |format|
format.html { redirect_to main_app.edit_admin_cache_settings_path }
end
end
end
end

View File

@@ -63,7 +63,6 @@ module Admin
def collection
return Customer.where("1=0") unless json_request? && params[:enterprise_id].present?
enterprise = Enterprise.managed_by(spree_current_user).find_by_id(params[:enterprise_id])
Customer.of(enterprise)
end

View File

@@ -28,12 +28,15 @@ module Admin
def bulk_update
@enterprise_fee_set = EnterpriseFeeSet.new(params[:enterprise_fee_set])
if @enterprise_fee_set.save
redirect_path = main_app.admin_enterprise_fees_path
if params.key? :enterprise_id
redirect_path = main_app.admin_enterprise_fees_path(enterprise_id: params[:enterprise_id])
end
redirect_to redirect_path, notice: I18n.t(:enterprise_fees_update_notice)
else
redirect_to redirect_path,
flash: { error: @enterprise_fee_set.errors.full_messages.to_sentence }
render :index
end
end
@@ -70,13 +73,5 @@ module Admin
def current_enterprise
Enterprise.find params[:enterprise_id] if params.key? :enterprise_id
end
def redirect_path
if params.key? :enterprise_id
return main_app.admin_enterprise_fees_path(enterprise_id: params[:enterprise_id])
end
main_app.admin_enterprise_fees_path
end
end
end

View File

@@ -66,7 +66,7 @@ module Admin
if @enterprise.update_attributes(attributes)
flash[:success] = I18n.t(:enterprise_register_success_notice, enterprise: @enterprise.name)
redirect_to admin_dashboard_path
redirect_to admin_path
else
flash[:error] = I18n.t(:enterprise_register_error, enterprise: @enterprise.name)
render :welcome, layout: "spree/layouts/bare_admin"
@@ -148,8 +148,7 @@ module Admin
unless enterprises.empty?
enterprises.includes(
supplied_products:
[:supplier, master: [:images], variants: { option_values: :option_type }]
supplied_products: [:supplier, :variants, master: [:images]]
)
end
when :index

View File

@@ -2,7 +2,6 @@ module Admin
class OrderCyclesController < ResourceController
include OrderCyclesHelper
prepend_before_filter :set_order_cycle_id, only: [:incoming, :outgoing]
before_filter :load_data_for_index, only: :index
before_filter :require_coordinator, only: :new
before_filter :remove_protected_attrs, only: [:update]
@@ -13,10 +12,7 @@ module Admin
respond_to do |format|
format.html
format.json do
render_as_json @collection,
ams_prefix: params[:ams_prefix],
current_user: spree_current_user,
subscriptions_count: SubscriptionsCount.new(@collection)
render_as_json @collection, ams_prefix: params[:ams_prefix], current_user: spree_current_user, subscriptions_count: SubscriptionsCount.new(@collection)
end
end
end
@@ -44,17 +40,12 @@ module Admin
if @order_cycle_form.save
flash[:notice] = I18n.t(:order_cycles_create_notice)
render json: { success: true,
edit_path: main_app.admin_order_cycle_incoming_path(@order_cycle) }
render json: { success: true }
else
render json: { errors: @order_cycle.errors.full_messages }, status: :unprocessable_entity
end
end
def set_order_cycle_id
params[:id] = params[:order_cycle_id]
end
def update
@order_cycle_form = OrderCycleForm.new(@order_cycle, params, spree_current_user)
@@ -71,10 +62,7 @@ module Admin
def bulk_update
if order_cycle_set.andand.save
render_as_json @order_cycles,
ams_prefix: 'index',
current_user: spree_current_user,
subscriptions_count: SubscriptionsCount.new(@collection)
render_as_json @order_cycles, ams_prefix: 'index', current_user: spree_current_user, subscriptions_count: SubscriptionsCount.new(@collection)
else
order_cycle = order_cycle_set.collection.find{ |oc| oc.errors.present? }
render json: { errors: order_cycle.errors.full_messages }, status: :unprocessable_entity
@@ -84,16 +72,14 @@ module Admin
def clone
@order_cycle = OrderCycle.find params[:id]
@order_cycle.clone!
redirect_to main_app.admin_order_cycles_path,
notice: I18n.t(:order_cycles_clone_notice, name: @order_cycle.name)
redirect_to main_app.admin_order_cycles_path, notice: I18n.t(:order_cycles_clone_notice, name: @order_cycle.name)
end
# Send notifications to all producers who are part of the order cycle
def notify_producers
Delayed::Job.enqueue OrderCycleNotificationJob.new(params[:id].to_i)
redirect_to main_app.admin_order_cycles_path,
notice: I18n.t(:order_cycles_email_to_producers_notice)
redirect_to main_app.admin_order_cycles_path, notice: I18n.t(:order_cycles_email_to_producers_notice)
end
protected
@@ -101,9 +87,20 @@ module Admin
def collection
return Enterprise.where("1=0") unless json_request?
return order_cycles_from_set if params[:order_cycle_set]
ocs = if params[:as] == "distributor"
OrderCycle.preload(:schedules).ransack(params[:q]).result.
involving_managed_distributors_of(spree_current_user).order('updated_at DESC')
elsif params[:as] == "producer"
OrderCycle.preload(:schedules).ransack(params[:q]).result.
involving_managed_producers_of(spree_current_user).order('updated_at DESC')
else
OrderCycle.preload(:schedules).ransack(params[:q]).result.accessible_by(spree_current_user)
end
ocs = order_cycles
ocs.undated | ocs.soonest_closing | ocs.soonest_opening | ocs.closed
ocs.undated |
ocs.soonest_closing |
ocs.soonest_opening |
ocs.closed
end
def collection_actions
@@ -112,60 +109,21 @@ module Admin
private
def order_cycles
if params[:as] == "distributor"
order_cycles_as_distributor
elsif params[:as] == "producer"
order_cycles_as_producer
else
order_cycles_as_both
end
end
def order_cycles_as_distributor
OrderCycle.
preload(:schedules).
ransack(params[:q]).
result.
involving_managed_distributors_of(spree_current_user).
order('updated_at DESC')
end
def order_cycles_as_producer
OrderCycle.
preload(:schedules).
ransack(params[:q]).
result.
involving_managed_producers_of(spree_current_user).
order('updated_at DESC')
end
def order_cycles_as_both
OrderCycle.
preload(:schedules).
ransack(params[:q]).
result.
accessible_by(spree_current_user)
end
def load_data_for_index
if json_request?
# Split ransack params into all those that currently exist and new ones
# to limit returned ocs to recent or undated
# Split ransack params into all those that currently exist and new ones to limit returned ocs to recent or undated
orders_close_at_gt = params[:q].andand.delete(:orders_close_at_gt) || 31.days.ago
params[:q] = {
g: [params.delete(:q) || {}, { m: 'or',
orders_close_at_gt: orders_close_at_gt,
orders_close_at_null: true }]
g: [params.delete(:q) || {}, { m: 'or', orders_close_at_gt: orders_close_at_gt, orders_close_at_null: true }]
}
@collection = collection
end
end
def require_coordinator
@order_cycle.coordinator =
permitted_coordinating_enterprises_for(@order_cycle).find_by_id(params[:coordinator_id])
return if params[:coordinator_id] && @order_cycle.coordinator
if params[:coordinator_id] && @order_cycle.coordinator = permitted_coordinating_enterprises_for(@order_cycle).find_by_id(params[:coordinator_id])
return
end
available_coordinators = permitted_coordinating_enterprises_for(@order_cycle)
case available_coordinators.count
@@ -175,9 +133,7 @@ module Admin
when 1
@order_cycle.coordinator = available_coordinators.first
else
if params[:coordinator_id]
flash[:error] = I18n.t(:order_cycles_no_permission_to_create_error)
end
flash[:error] = I18n.t(:order_cycles_no_permission_to_create_error) if params[:coordinator_id]
render :set_coordinator
end
end
@@ -201,9 +157,7 @@ module Admin
params[:order_cycle].delete :coordinator_id
unless Enterprise.managed_by(spree_current_user).include?(@order_cycle.coordinator)
params[:order_cycle].delete_if do |k, _v|
[:name, :orders_open_at, :orders_close_at].include? k.to_sym
end
params[:order_cycle].delete_if{ |k, _v| [:name, :orders_open_at, :orders_close_at].include? k.to_sym }
end
end
@@ -227,9 +181,7 @@ module Admin
def require_order_cycle_set_params
return if params[:order_cycle_set]
render json: { errors: t('admin.order_cycles.bulk_update.no_data') },
status: :unprocessable_entity
render json: { errors: t('admin.order_cycles.bulk_update.no_data') }, status: :unprocessable_entity
end
def ams_prefix_whitelist

View File

@@ -23,13 +23,11 @@ module Admin
def validate_data
return unless process_data('validate')
render json: @importer.import_results, response: 200
end
def save_data
return unless process_data('save')
render json: @importer.save_results, response: 200
end

View File

@@ -31,7 +31,6 @@ module Admin
def collection
return Schedule.where("1=0") unless json_request?
if params[:enterprise_id]
filter_schedules_by_enterprise_id(permissions.visible_schedules, params[:enterprise_id])
else
@@ -50,7 +49,6 @@ module Admin
def check_editable_order_cycle_ids
return unless params[:schedule][:order_cycle_ids]
requested = params[:schedule][:order_cycle_ids]
@existing_order_cycle_ids = @schedule.persisted? ? @schedule.order_cycle_ids : []
permitted = OrderCycle.where(id: params[:schedule][:order_cycle_ids] | @existing_order_cycle_ids).merge(OrderCycle.managed_by(spree_current_user)).pluck(:id)
@@ -63,23 +61,19 @@ module Admin
def check_dependent_subscriptions
return if Subscription.where(schedule_id: @schedule).empty?
render json: { errors: [t('admin.schedules.destroy.associated_subscriptions_error')] }, status: :conflict
end
def permissions
return @permissions unless @permission.nil?
@permissions = OpenFoodNetwork::Permissions.new(spree_current_user)
end
def sync_subscriptions
return unless params[:schedule][:order_cycle_ids]
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)
syncer = OpenFoodNetwork::ProxyOrderSyncer.new(subscriptions)
syncer.sync!

View File

@@ -22,15 +22,13 @@ module Admin
redirect_to main_app.edit_admin_enterprise_path(stripe_account.enterprise)
rescue ActiveRecord::RecordNotFound
flash[:error] = "Failed to disconnect Stripe."
redirect_to spree.admin_dashboard_path
redirect_to spree.admin_path
end
def status
return render json: { status: :stripe_disabled } unless Spree::Config.stripe_connect_enabled
stripe_account = StripeAccount.find_by_enterprise_id(params[:enterprise_id])
return render json: { status: :account_missing } unless stripe_account
authorize! :status, stripe_account
begin

View File

@@ -8,7 +8,6 @@ module Admin
def edit
return @stripe_account = { status: :empty_api_key_error_html } if Stripe.api_key.blank?
attrs = %i[id business_name charges_enabled]
@obfuscated_secret_key = obfuscated_secret_key
@stripe_account = Stripe::Account.retrieve.to_hash.slice(*attrs).merge(status: :ok)

View File

@@ -36,20 +36,17 @@ module Admin
def ensure_shop
return if @shop
render json: { errors: ['Unauthorised'] }, status: :unauthorized
end
def ensure_variant
return if @variant
error = "#{@shop.name} is not permitted to sell the selected product"
render json: { errors: [error] }, status: :unprocessable_entity
end
def price_estimate
return unless @order_cycle
fee_calculator = OpenFoodNetwork::EnterpriseFeeCalculator.new(@shop, @order_cycle)
OpenFoodNetwork::ScopeVariantToHub.new(@shop).scope(@variant)
@variant.price + fee_calculator.indexed_fees_for(@variant)

View File

@@ -80,7 +80,6 @@ module Admin
def permissions
return @permissions unless @permissions.nil?
@permissions = OpenFoodNetwork::Permissions.new(spree_current_user)
end
@@ -127,17 +126,14 @@ module Admin
def check_for_open_orders
return if params[:open_orders] == 'cancel'
@open_orders_to_keep = @subscription.proxy_orders.placed_and_open.pluck(:id)
return if @open_orders_to_keep.empty? || params[:open_orders] == 'keep'
render json: { errors: { open_orders: t('admin.subscriptions.confirm_cancel_open_orders_msg') } }, status: :conflict
end
def check_for_canceled_orders
return if params[:canceled_orders] == 'notified'
return if @subscription.proxy_orders.active.canceled.empty?
render json: { errors: { canceled_orders: t('admin.subscriptions.resume_canceled_orders_msg') } }, status: :conflict
end

View File

@@ -1,44 +1,16 @@
# Base controller for OFN's API
require_dependency 'spree/api/controller_setup'
# Includes the minimum machinery required by ActiveModelSerializers
module Api
class BaseController < ActionController::Metal
include Spree::Api::ControllerSetup
include Spree::Core::ControllerHelpers::SSL
include ::ActionController::Head
respond_to :json
attr_accessor :current_api_user
before_filter :set_content_type
before_filter :authenticate_user
after_filter :set_jsonp_format
rescue_from Exception, with: :error_during_processing
rescue_from CanCan::AccessDenied, with: :unauthorized
rescue_from ActiveRecord::RecordNotFound, with: :not_found
helper Spree::Api::ApiHelpers
ssl_allowed
# Include these because we inherit from ActionController::Metal
# rather than ActionController::Base and these are required for AMS
class BaseController < Spree::Api::BaseController
# Need to include these because Spree::Api::BaseContoller inherits
# from ActionController::Metal rather than ActionController::Base
# and they are required by ActiveModelSerializers
include ActionController::Serialization
include ActionController::UrlFor
include Rails.application.routes.url_helpers
use_renderers :json
check_authorization
def set_jsonp_format
return unless params[:callback] && request.get?
self.response_body = "#{params[:callback]}(#{response_body})"
headers["Content-Type"] = 'application/javascript'
end
def respond_with_conflict(json_hash)
render json: json_hash, status: :conflict
end
@@ -47,63 +19,16 @@ module Api
# Use logged in user (spree_current_user) for API authentication (current_api_user)
def authenticate_user
return if @current_api_user = try_spree_current_user
if api_key.blank?
# An anonymous user
@current_api_user = Spree.user_class.new
return
end
return if @current_api_user = Spree.user_class.find_by_spree_api_key(api_key.to_s)
invalid_api_key
@current_api_user = try_spree_current_user
super
end
def set_content_type
content_type = case params[:format]
when "json"
"application/json"
when "xml"
"text/xml"
end
headers["Content-Type"] = content_type
end
def error_during_processing(exception)
render(text: { exception: exception.message }.to_json,
status: :unprocessable_entity) && return
end
def current_ability
Spree::Ability.new(current_api_user)
end
def api_key
request.headers["X-Spree-Token"] || params[:token]
end
helper_method :api_key
def invalid_resource!(resource)
@resource = resource
render(json: { error: I18n.t(:invalid_resource, scope: "spree.api"),
errors: @resource.errors },
status: :unprocessable_entity)
end
def invalid_api_key
render(json: { error: I18n.t(:invalid_api_key, key: api_key, scope: "spree.api") },
status: :unauthorized) && return
end
def unauthorized
render(json: { error: I18n.t(:unauthorized, scope: "spree.api") },
status: :unauthorized) && return
end
def not_found
render(json: { error: I18n.t(:resource_not_found, scope: "spree.api") },
status: :not_found) && return
# Allows API access without authentication, but only for OFN controllers which inherit
# from Api::BaseController. @current_api_user will now initialize an empty Spree::User
# unless one is present. We now also apply devise's `check_authorization`. See here for
# details: https://github.com/CanCanCommunity/cancancan/wiki/Ensure-Authorization
def requires_authentication?
false
end
end
end

View File

@@ -27,7 +27,6 @@ module Api
def load_enterprise
@enterprise = Enterprise.find_by_permalink(params[:enterprise_id].to_s)
raise UnknownEnterpriseAuthorizationActionError if enterprise_authorize_action.blank?
authorize!(enterprise_authorize_action, @enterprise)
end

View File

@@ -1,92 +0,0 @@
# This controller lists products that can be added to an exchange
module Api
class ExchangeProductsController < Api::BaseController
DEFAULT_PAGE = 1
DEFAULT_PER_PAGE = 100
skip_authorization_check only: [:index]
# If exchange_id is present in the URL:
# Lists Products that can be added to that Exchange
#
# If exchange_id is not present in the URL:
# Lists Products of the Enterprise given that can be added to the given Order Cycle
# In this case parameters are: enterprise_id, order_cycle_id and incoming
# (order_cycle_id is not necessary for incoming exchanges)
def index
if params[:exchange_id].present?
load_data_from_exchange
else
load_data_from_other_params
end
render_variant_count && return if params[:action_name] == "variant_count"
render_paginated_products paginated_products
end
private
def render_variant_count
render text: {
count: Spree::Variant.
not_master.
where(product_id: products).
count
}.to_json
end
def products
ExchangeProductsRenderer.
new(@order_cycle, spree_current_user).
exchange_products(@incoming, @enterprise)
end
def paginated_products
products.
page(params[:page] || DEFAULT_PAGE).
per(params[:per_page] || DEFAULT_PER_PAGE)
end
def load_data_from_exchange
exchange = Exchange.find_by_id(params[:exchange_id])
@order_cycle = exchange.order_cycle
@incoming = exchange.incoming
@enterprise = exchange.sender
end
def load_data_from_other_params
@enterprise = Enterprise.find_by_id(params[:enterprise_id])
if params[:order_cycle_id]
@order_cycle = OrderCycle.find_by_id(params[:order_cycle_id])
elsif !params[:incoming]
raise "order_cycle_id is required to list products for new outgoing exchange"
end
@incoming = params[:incoming]
end
def render_paginated_products(paginated_products)
serializer = ActiveModel::ArraySerializer.new(
paginated_products,
each_serializer: Api::Admin::ForOrderCycle::SuppliedProductSerializer,
order_cycle: @order_cycle
)
render text: {
products: serializer,
pagination: pagination_data(paginated_products)
}.to_json
end
def pagination_data(paginated_products)
{
results: paginated_products.total_count,
pages: paginated_products.num_pages,
page: (params[:page] || DEFAULT_PAGE).to_i,
per_page: (params[:per_page] || DEFAULT_PER_PAGE).to_i
}
end
end
end

View File

@@ -1,88 +0,0 @@
module Api
class OrderCyclesController < BaseController
include EnterprisesHelper
respond_to :json
skip_authorization_check
def products
products = ProductsRenderer.new(
distributor,
order_cycle,
customer,
search_params
).products_json
render json: products
rescue ProductsRenderer::NoProducts
render status: :not_found, json: ''
end
def taxons
taxons = Spree::Taxon.
joins(:products).
where(spree_products: { id: distributed_products }).
select('DISTINCT spree_taxons.*')
render json: ActiveModel::ArraySerializer.new(taxons, each_serializer: Api::TaxonSerializer)
end
def properties
render json: ActiveModel::ArraySerializer.new(
product_properties | producer_properties, each_serializer: Api::PropertySerializer
)
end
private
def product_properties
Spree::Property.
joins(:products).
where(spree_products: { id: distributed_products }).
select('DISTINCT spree_properties.*')
end
def producer_properties
producers = Enterprise.
joins(:supplied_products).
where(spree_products: { id: distributed_products })
Spree::Property.
joins(:producer_properties).
where(producer_properties: { producer_id: producers }).
select('DISTINCT spree_properties.*')
end
def search_params
permitted_search_params = params.slice :q, :page, :per_page
if permitted_search_params.key? :q
permitted_search_params[:q].slice!(*permitted_ransack_params)
end
permitted_search_params
end
def permitted_ransack_params
[:name_or_meta_keywords_or_supplier_name_cont,
:properties_id_or_supplier_properties_id_in_any,
:primary_taxon_id_in_any]
end
def distributor
Enterprise.find_by_id(params[:distributor])
end
def order_cycle
OrderCycle.find_by_id(params[:id])
end
def customer
@current_api_user.andand.customer_of(distributor) || nil
end
def distributed_products
OrderCycleDistributedProducts.new(distributor, order_cycle, customer).products_relation
end
end
end

View File

@@ -1,10 +1,5 @@
module Api
class OrdersController < BaseController
def show
authorize! :read, order
render json: order, serializer: Api::OrderDetailedSerializer, current_order: order
end
def index
authorize! :admin, Spree::Order
@@ -16,50 +11,13 @@ module Api
}
end
def ship
authorize! :admin, order
if order.ship
render json: order.reload, serializer: Api::Admin::OrderSerializer, status: :ok
else
render json: { error: I18n.t('api.orders.failed_to_update') }, status: :unprocessable_entity
end
end
def capture
authorize! :admin, order
pending_payment = order.pending_payments.first
return payment_capture_failed unless order.payment_required? && pending_payment
if pending_payment.capture!
render json: order.reload, serializer: Api::Admin::OrderSerializer, status: :ok
else
payment_capture_failed
end
rescue Spree::Core::GatewayError => e
error_during_processing(e)
end
private
def payment_capture_failed
render json: { error: t(:payment_processing_failed) }, status: :unprocessable_entity
end
def serialized_orders(orders)
ActiveModel::ArraySerializer.new(
orders,
each_serializer: Api::Admin::OrderSerializer
)
end
def order
@order ||= Spree::Order.
where(number: params[:id]).
includes(line_items: { variant: [:product, :stock_items, :default_price] }).
first!
end
end
end

View File

@@ -19,7 +19,7 @@ module Api
@product = Spree::Product.new(params[:product])
begin
if @product.save
render json: @product, serializer: Api::Admin::ProductSerializer, status: :created
render json: @product, serializer: Api::Admin::ProductSerializer, status: 201
else
invalid_resource!(@product)
end
@@ -33,7 +33,7 @@ module Api
authorize! :update, Spree::Product
@product = find_product(params[:id])
if @product.update_attributes(params[:product])
render json: @product, serializer: Api::Admin::ProductSerializer, status: :ok
render json: @product, serializer: Api::Admin::ProductSerializer, status: 200
else
invalid_resource!(@product)
end
@@ -42,11 +42,12 @@ module Api
def destroy
authorize! :delete, Spree::Product
@product = find_product(params[:id])
authorize! :delete, @product
@product.destroy
render json: @product, serializer: Api::Admin::ProductSerializer, status: :no_content
@product.update_attribute(:deleted_at, Time.zone.now)
@product.variants_including_master.update_all(deleted_at: Time.zone.now)
render json: @product, serializer: Api::Admin::ProductSerializer, status: 204
end
# TODO: This should be named 'managed'. Is the action above used? Maybe we should remove it.
def bulk_products
product_query = OpenFoodNetwork::Permissions.new(current_api_user).
editable_products.merge(product_scope)
@@ -71,6 +72,14 @@ module Api
render_paged_products @products
end
def soft_delete
authorize! :delete, Spree::Product
@product = find_product(params[:product_id])
authorize! :delete, @product
@product.destroy
render json: @product, serializer: Api::Admin::ProductSerializer, status: 204
end
# POST /api/products/:product_id/clone
#
def clone
@@ -80,18 +89,15 @@ module Api
@product = original_product.duplicate
render json: @product, serializer: Api::Admin::ProductSerializer, status: :created
render json: @product, serializer: Api::Admin::ProductSerializer, status: 201
end
private
def find_product(id)
product_scope.find_by_permalink!(id.to_s)
rescue ActiveRecord::RecordNotFound
product_scope.find(id)
end
# Copied and modified from SpreeApi::BaseController to allow
# enterprise users to access inactive products
def product_scope
# This line modified
if current_api_user.has_spree_role?("admin") || current_api_user.enterprises.present?
scope = Spree::Product
if params[:show_deleted]
@@ -101,15 +107,7 @@ module Api
scope = Spree::Product.active
end
scope.includes(product_query_includes)
end
def product_query_includes
[
master: [:images],
variants: [:default_price, :stock_locations, :stock_items, :variant_overrides,
{ option_values: :option_type }]
]
scope.includes(:master)
end
def paged_products_for_producers(producers)

View File

@@ -1,105 +0,0 @@
require 'open_food_network/scope_variant_to_hub'
module Api
class ShipmentsController < Api::BaseController
respond_to :json
before_filter :find_order
before_filter :find_and_update_shipment, only: [:ship, :ready, :add, :remove]
def create
variant = scoped_variant(params[:variant_id])
quantity = params[:quantity].to_i
@shipment = get_or_create_shipment(params[:stock_location_id])
@order.contents.add(variant, quantity, nil, @shipment)
@shipment.refresh_rates
@shipment.save!
render json: @shipment.reload, serializer: Api::ShipmentSerializer, status: :ok
end
def update
authorize! :read, Spree::Shipment
@shipment = @order.shipments.find_by_number!(params[:id])
params[:shipment] ||= []
unlock = params[:shipment].delete(:unlock)
if unlock == 'yes'
@shipment.adjustment.open
end
@shipment.update_attributes(params[:shipment])
if unlock == 'yes'
@shipment.adjustment.close
end
render json: @shipment.reload, serializer: Api::ShipmentSerializer, status: :ok
end
def ready
authorize! :read, Spree::Shipment
unless @shipment.ready?
if @shipment.can_ready?
@shipment.ready!
else
render(json: { error: I18n.t(:cannot_ready, scope: "spree.api.shipment") },
status: :unprocessable_entity) && return
end
end
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
end
def ship
authorize! :read, Spree::Shipment
unless @shipment.shipped?
@shipment.ship!
end
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
end
def add
variant = scoped_variant(params[:variant_id])
quantity = params[:quantity].to_i
@order.contents.add(variant, quantity, nil, @shipment)
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
end
def remove
variant = scoped_variant(params[:variant_id])
quantity = params[:quantity].to_i
@order.contents.remove(variant, quantity, @shipment)
@shipment.reload if @shipment.persisted?
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
end
private
def find_order
@order = Spree::Order.find_by_number!(params[:order_id])
authorize! :read, @order
end
def find_and_update_shipment
@shipment = @order.shipments.find_by_number!(params[:id])
@shipment.update_attributes(params[:shipment])
@shipment.reload
end
def scoped_variant(variant_id)
variant = Spree::Variant.find(variant_id)
OpenFoodNetwork::ScopeVariantToHub.new(@order.distributor).scope(variant)
variant
end
def get_or_create_shipment(stock_location_id)
@order.shipment || @order.shipments.create(stock_location_id: stock_location_id)
end
end
end

View File

@@ -10,7 +10,7 @@ module Api
def job_queue_alive?
Spree::Config.last_job_queue_heartbeat_at.present? &&
Time.parse(Spree::Config.last_job_queue_heartbeat_at).in_time_zone > 6.minutes.ago
Time.parse(Spree::Config.last_job_queue_heartbeat_at) > 6.minutes.ago
end
end
end

View File

@@ -1,12 +0,0 @@
module Api
class TaxonomiesController < Api::BaseController
respond_to :json
skip_authorization_check only: :jstree
def jstree
@taxonomy = Spree::Taxonomy.find(params[:id])
render json: @taxonomy.root, serializer: Api::TaxonJstreeSerializer
end
end
end

View File

@@ -1,72 +0,0 @@
module Api
class TaxonsController < Api::BaseController
respond_to :json
skip_authorization_check only: [:index, :show, :jstree]
def index
if taxonomy
@taxons = taxonomy.root.children
else
if params[:ids]
@taxons = Spree::Taxon.where(id: params[:ids].split(","))
else
@taxons = Spree::Taxon.ransack(params[:q]).result
end
end
render json: @taxons, each_serializer: Api::TaxonSerializer
end
def jstree
@taxon = taxon
render json: @taxon.children, each_serializer: Api::TaxonJstreeSerializer
end
def create
authorize! :create, Spree::Taxon
@taxon = Spree::Taxon.new(params[:taxon])
@taxon.taxonomy_id = params[:taxonomy_id]
taxonomy = Spree::Taxonomy.find_by_id(params[:taxonomy_id])
if taxonomy.nil?
@taxon.errors[:taxonomy_id] = I18n.t(:invalid_taxonomy_id, scope: 'spree.api')
invalid_resource!(@taxon) && return
end
@taxon.parent_id = taxonomy.root.id unless params[:taxon][:parent_id]
if @taxon.save
render json: @taxon, serializer: Api::TaxonSerializer, status: :created
else
invalid_resource!(@taxon)
end
end
def update
authorize! :update, Spree::Taxon
if taxon.update_attributes(params[:taxon])
render json: taxon, serializer: Api::TaxonSerializer, status: :ok
else
invalid_resource!(taxon)
end
end
def destroy
authorize! :delete, Spree::Taxon
taxon.destroy
render json: taxon, serializer: Api::TaxonSerializer, status: :no_content
end
private
def taxonomy
return if params[:taxonomy_id].blank?
@taxonomy ||= Spree::Taxonomy.find(params[:taxonomy_id])
end
def taxon
@taxon ||= taxonomy.taxons.find(params[:id])
end
end
end

View File

@@ -6,12 +6,12 @@ module Api
before_filter :product
def index
@variants = scope.includes(option_values: :option_type).ransack(params[:q]).result
@variants = scope.includes(:option_values).ransack(params[:q]).result
render json: @variants, each_serializer: Api::VariantSerializer
end
def show
@variant = scope.includes(option_values: :option_type).find(params[:id])
@variant = scope.includes(:option_values).find(params[:id])
render json: @variant, serializer: Api::VariantSerializer
end
@@ -19,7 +19,7 @@ module Api
authorize! :create, Spree::Variant
@variant = scope.new(params[:variant])
if @variant.save
render json: @variant, serializer: Api::VariantSerializer, status: :created
render json: @variant, serializer: Api::VariantSerializer, status: 201
else
invalid_resource!(@variant)
end
@@ -29,19 +29,25 @@ module Api
authorize! :update, Spree::Variant
@variant = scope.find(params[:id])
if @variant.update_attributes(params[:variant])
render json: @variant, serializer: Api::VariantSerializer, status: :ok
render json: @variant, serializer: Api::VariantSerializer, status: 200
else
invalid_resource!(@product)
end
end
def destroy
authorize! :delete, Spree::Variant
@variant = scope.find(params[:id])
def soft_delete
@variant = scope.find(params[:variant_id])
authorize! :delete, @variant
VariantDeleter.new.delete(@variant)
render json: @variant, serializer: Api::VariantSerializer, status: :no_content
render json: @variant, serializer: Api::VariantSerializer, status: 204
end
def destroy
authorize! :delete, Spree::Variant
@variant = scope.find(params[:id])
@variant.destroy
render json: @variant, serializer: Api::VariantSerializer, status: 204
end
private
@@ -52,11 +58,11 @@ module Api
def scope
if @product
variants = if current_api_user.has_spree_role?("admin") || params[:show_deleted]
@product.variants_including_master.with_deleted
else
@product.variants_including_master
end
unless current_api_user.has_spree_role?("admin") || params[:show_deleted]
variants = @product.variants_including_master
else
variants = @product.variants_including_master.with_deleted
end
else
variants = Spree::Variant.scoped
if current_api_user.has_spree_role?("admin")

View File

@@ -47,7 +47,6 @@ class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource_or_scope)
return session[:shopfront_redirect] if session[:shopfront_redirect]
stored_location_for(resource_or_scope) || signed_in_root_path(resource_or_scope)
end

View File

@@ -3,10 +3,6 @@ require 'open_food_network/address_finder'
class CheckoutController < Spree::CheckoutController
layout 'darkswarm'
# We need pessimistic locking to avoid race conditions.
# Otherwise we fail on duplicate indexes or end up with negative stock.
prepend_around_filter CurrentOrderLocker, only: :update
prepend_before_filter :check_hub_ready_for_checkout
prepend_before_filter :check_order_cycle_expiry
prepend_before_filter :require_order_cycle
@@ -156,7 +152,7 @@ class CheckoutController < Spree::CheckoutController
end
def update_failed
current_order.updater.shipping_address_from_distributor
clear_ship_address
RestartCheckout.new(@order).call
respond_to do |format|
@@ -169,6 +165,15 @@ class CheckoutController < Spree::CheckoutController
end
end
# When we have a pickup Shipping Method,
# we clone the distributor address into ship_address before_save
# We don't want this data in the form, so we clear it out
def clear_ship_address
unless current_order.shipping_method.andand.require_ship_address
current_order.ship_address = Spree::Address.default
end
end
def load_order
@order = current_order
redirect_to(main_app.shop_path) && return unless @order && @order.checkout_allowed?

View File

@@ -16,7 +16,6 @@ class EnterprisesController < BaseController
def shop
return redirect_to main_app.cart_path unless enough_stock?
set_noindex_meta_tag
@enterprise = current_distributor

View File

@@ -23,7 +23,6 @@ class LineItemsController < BaseController
# List all items the user already ordered in the current order cycle
def bought_items
return [] unless current_order_cycle && spree_current_user && current_distributor
current_order_cycle.items_bought_by_user(spree_current_user, current_distributor)
end

View File

@@ -1,3 +1,5 @@
require 'open_food_network/cached_products_renderer'
class ShopController < BaseController
layout "darkswarm"
before_filter :require_distributor_chosen, :set_order_cycles, except: :changeable_orders_alert
@@ -7,6 +9,19 @@ class ShopController < BaseController
redirect_to main_app.enterprise_shop_path(current_distributor)
end
def products
renderer = OpenFoodNetwork::CachedProductsRenderer.new(current_distributor,
current_order_cycle)
# If we add any more filtering logic, we should probably
# move it all to a lib class like 'CachedProductsFilterer'
products_json = filter(renderer.products_json)
render json: products_json
rescue OpenFoodNetwork::CachedProductsRenderer::NoProducts
render status: :not_found, json: ''
end
def order_cycle
if request.post?
if oc = OrderCycle.with_distributor(@distributor).active.find_by_id(params[:order_cycle_id])
@@ -24,4 +39,27 @@ class ShopController < BaseController
def changeable_orders_alert
render layout: false
end
private
def filtered_json(products_json)
if applicator.rules.any?
filter(products_json)
else
products_json
end
end
def filter(products_json)
products_hash = JSON.parse(products_json)
applicator.filter!(products_hash)
JSON.unparse(products_hash)
end
def applicator
return @applicator unless @applicator.nil?
@applicator = OpenFoodNetwork::TagRuleApplicator.new(current_distributor,
"FilterProducts",
current_customer.andand.tag_list)
end
end

View File

@@ -1,23 +1,12 @@
module Spree
module Admin
class AdjustmentsController < ResourceController
belongs_to 'spree/order', find_by: :number
destroy.after :reload_order
AdjustmentsController.class_eval do
prepend_before_filter :set_included_tax, only: [:create, :update]
before_filter :set_default_tax_rate, only: :edit
before_filter :enable_updates, only: :update
private
def reload_order
@order.reload
end
def collection
parent.adjustments.eligible
end
# Choose a default tax rate to show on the edit form. The adjustment stores its included
# tax in dollars, but doesn't store the source of the tax (ie. TaxRate that generated it).
# We guess which tax rate here, choosing:
@@ -26,34 +15,28 @@ module Spree
# When we have to go with 2, we show an error message to ask the admin to check that the
# correct tax is being applied.
def set_default_tax_rate
return if @adjustment.included_tax <= 0
if @adjustment.included_tax > 0
trs = TaxRate.match(@order)
tr_yielding_matching_tax = trs.select { |tr| tr.compute_tax(@adjustment.amount) == @adjustment.included_tax }.first.andand.id
tr_valid_for_order = TaxRate.match(@order).first.andand.id
tax_rates = TaxRate.match(@order)
tax_rate_with_matching_tax = find_tax_rate_with_matching_tax(tax_rates)
tax_rate_valid_for_order = tax_rates.first.andand.id
@tax_rate_id = tr_yielding_matching_tax || tr_valid_for_order
@tax_rate_id = tax_rate_with_matching_tax || tax_rate_valid_for_order
return unless tax_rate_with_matching_tax.nil?
@adjustment.errors.add :tax_rate_id, I18n.t(:adjustments_tax_rate_error)
end
def find_tax_rate_with_matching_tax(tax_rates)
tax_rates_yielding_matching_tax = tax_rates.select do |tr|
tr.compute_tax(@adjustment.amount) == @adjustment.included_tax
if tr_yielding_matching_tax.nil?
@adjustment.errors.add :tax_rate_id, I18n.t(:adjustments_tax_rate_error)
end
end
tax_rates_yielding_matching_tax.first.andand.id
end
def set_included_tax
included_tax = 0
if params[:tax_rate_id].present?
tax_rate = TaxRate.find params[:tax_rate_id]
amount = params[:adjustment][:amount].to_f
included_tax = tax_rate.compute_tax amount
params[:adjustment][:included_tax] = tax_rate.compute_tax amount
else
params[:adjustment][:included_tax] = 0
end
params[:adjustment][:included_tax] = included_tax
end
# Spree 2.0 keeps shipping fee adjustments open unless they are manually

View File

@@ -1,142 +0,0 @@
module Spree
module Admin
class BaseController < Spree::BaseController
ssl_required
helper 'spree/admin/navigation'
layout '/spree/layouts/admin'
include I18nHelper
before_filter :authorize_admin
before_filter :set_locale
before_filter :warn_invalid_order_cycles, if: :html_request?
# Warn the user when they have an active order cycle with hubs that are not ready
# for checkout (ie. does not have valid shipping and payment methods).
def warn_invalid_order_cycles
distributors = active_distributors_not_ready_for_checkout
return if distributors.empty? || flash[:notice].present?
flash[:notice] = active_distributors_not_ready_for_checkout_message(distributors)
end
# This is in Spree::Core::ControllerHelpers::Auth
# But you can't easily reopen modules in Ruby
def unauthorized
if try_spree_current_user
flash[:error] = t(:authorization_failure)
redirect_to '/unauthorized'
else
store_location
redirect_to root_path(anchor: "login?after_login=#{request.env['PATH_INFO']}")
end
end
protected
def model_class
const_name = controller_name.classify
return "Spree::#{const_name}".constantize if Spree.const_defined?(const_name)
nil
end
def action
params[:action].to_sym
end
def authorize_admin
if respond_to?(:model_class, true) && model_class
record = model_class
else
# This allows specificity for each non-resource controller
# (to be consistent with "authorize_resource :class => false", see https://github.com/ryanb/cancan/blob/60cf6a67ef59c0c9b63bc27ea0101125c4193ea6/lib/cancan/controller_resource.rb#L146)
record = self.class.to_s.
sub("Controller", "").
underscore.split('/').last.singularize.to_sym
end
authorize! :admin, record
authorize! resource_authorize_action, record
end
def resource_authorize_action
action
end
def flash_message_for(object, event_sym)
resource_desc = object.class.model_name.human
resource_desc += " \"#{object.name}\"" if object.respond_to?(:name) && object.name.present?
Spree.t(event_sym, resource: resource_desc)
end
def render_js_for_destroy
render partial: '/spree/admin/shared/destroy'
end
# Index request for JSON needs to pass a CSRF token in order to prevent JSON Hijacking
def check_json_authenticity
return unless request.format.js? || request.format.json?
return unless protect_against_forgery?
auth_token = params[request_forgery_protection_token]
return if auth_token && form_authenticity_token == CGI.unescape(auth_token)
raise(ActionController::InvalidAuthenticityToken)
end
def config_locale
Spree::Backend::Config[:locale]
end
private
def active_distributors_not_ready_for_checkout
ocs = OrderCycle.managed_by(spree_current_user).active
distributors = ocs.includes(:distributors).map(&:distributors).flatten.uniq
Enterprise.where('enterprises.id IN (?)', distributors).not_ready_for_checkout
end
def active_distributors_not_ready_for_checkout_message(distributors)
distributor_names = distributors.map(&:name).join ', '
if distributors.count > 1
I18n.t(:active_distributors_not_ready_for_checkout_message_plural,
distributor_names: distributor_names)
else
I18n.t(:active_distributors_not_ready_for_checkout_message_singular,
distributor_names: distributor_names)
end
end
def html_request?
request.format.html?
end
def json_request?
request.format.json?
end
def render_as_json(data, options = {})
ams_prefix = options.delete :ams_prefix
if [Array, ActiveRecord::Relation].include? data.class
render options.merge(json: data, each_serializer: serializer(ams_prefix))
else
render options.merge(json: data, serializer: serializer(ams_prefix))
end
end
def serializer(ams_prefix)
unless ams_prefix.nil? || ams_prefix_whitelist.include?(ams_prefix.to_sym)
raise "Suffix '#{ams_prefix}' not found in ams_prefix_whitelist for #{self.class.name}."
end
prefix = ams_prefix.andand.classify || ""
name = controller_name.classify
"::Api::Admin::#{prefix}#{name}Serializer".constantize
end
end
end
end

View File

@@ -0,0 +1,104 @@
require 'spree/core/controller_helpers/respond_with_decorator'
Spree::Admin::BaseController.class_eval do
include I18nHelper
layout 'spree/layouts/admin'
before_filter :set_locale
before_filter :warn_invalid_order_cycles, if: :html_request?
# Warn the user when they have an active order cycle with hubs that are not ready
# for checkout (ie. does not have valid shipping and payment methods).
def warn_invalid_order_cycles
distributors = active_distributors_not_ready_for_checkout
if distributors.any? && flash[:notice].nil?
flash[:notice] = active_distributors_not_ready_for_checkout_message(distributors)
end
end
# Override Spree method
# It's a shame Spree doesn't just let CanCan handle this in it's own way
def authorize_admin
if respond_to?(:model_class, true) && model_class
record = model_class
else
# this line changed to allow specificity for each non-resource controller (to be consistent with "authorize_resource :class => false", see https://github.com/ryanb/cancan/blob/60cf6a67ef59c0c9b63bc27ea0101125c4193ea6/lib/cancan/controller_resource.rb#L146)
record = self.class.to_s.sub("Controller", "").underscore.split('/').last.singularize.to_sym
end
authorize! :admin, record
authorize! resource_authorize_action, record
end
def resource_authorize_action
action
end
# This is in Spree::Core::ControllerHelpers::Auth
# But you can't easily reopen modules in Ruby
def unauthorized
if try_spree_current_user
flash[:error] = t(:authorization_failure)
redirect_to '/unauthorized'
else
store_location
redirect_to root_path(anchor: "login?after_login=#{request.env['PATH_INFO']}")
end
end
protected
def model_class
const_name = controller_name.classify
if Spree.const_defined?(const_name)
return "Spree::#{const_name}".constantize
end
nil
end
private
def active_distributors_not_ready_for_checkout
ocs = OrderCycle.managed_by(spree_current_user).active
distributors = ocs.includes(:distributors).map(&:distributors).flatten.uniq
Enterprise.where('enterprises.id IN (?)', distributors).not_ready_for_checkout
end
def active_distributors_not_ready_for_checkout_message(distributors)
distributor_names = distributors.map(&:name).join ', '
if distributors.count > 1
I18n.t(:active_distributors_not_ready_for_checkout_message_plural, distributor_names: distributor_names)
else
I18n.t(:active_distributors_not_ready_for_checkout_message_singular, distributor_names: distributor_names)
end
end
def html_request?
request.format.html?
end
def json_request?
request.format.json?
end
def render_as_json(data, options = {})
ams_prefix = options.delete :ams_prefix
if [Array, ActiveRecord::Relation].include? data.class
render options.merge(json: data, each_serializer: serializer(ams_prefix))
else
render options.merge(json: data, serializer: serializer(ams_prefix))
end
end
def serializer(ams_prefix)
if ams_prefix.nil? || ams_prefix_whitelist.include?(ams_prefix.to_sym)
prefix = ams_prefix.andand.classify || ""
name = controller_name.classify
"Api::Admin::#{prefix}#{name}Serializer".constantize
else
raise "Suffix '#{ams_prefix}' not found in ams_prefix_whitelist for #{self.class.name}."
end
end
end

View File

@@ -1,9 +0,0 @@
module Spree
module Admin
class CountriesController < ResourceController
def collection
super.order(:name)
end
end
end
end

View File

@@ -1,24 +0,0 @@
module Spree
module Admin
class GeneralSettingsController < Spree::Admin::BaseController
def edit
@preferences_general = [:site_name, :default_seo_title, :default_meta_keywords,
:default_meta_description, :site_url, :bugherd_api_key]
@preferences_security = [:allow_ssl_in_production,
:allow_ssl_in_staging, :allow_ssl_in_development_and_test]
@preferences_currency = [:display_currency, :hide_cents]
end
def update
params.each do |name, value|
next unless Spree::Config.has_preference? name
Spree::Config[name] = value
end
flash[:success] = Spree.t(:successfully_updated, resource: Spree.t(:general_settings))
redirect_to edit_admin_general_settings_path
end
end
end
end

View File

@@ -0,0 +1,14 @@
module Spree
module Admin
GeneralSettingsController.class_eval do
end
module GeneralSettingsEditPreferences
def edit
super
@preferences_general << :bugherd_api_key
end
end
GeneralSettingsController.prepend(GeneralSettingsEditPreferences)
end
end

View File

@@ -1,79 +0,0 @@
module Spree
module Admin
class ImageSettingsController < Spree::Admin::BaseController
def edit
@styles = ActiveSupport::JSON.decode(Spree::Config[:attachment_styles])
@headers = ActiveSupport::JSON.decode(Spree::Config[:s3_headers])
end
def update
update_styles(params)
update_headers(params) if Spree::Config[:use_s3]
Spree::Config.set(params[:preferences])
update_paperclip_settings
respond_to do |format|
format.html {
flash[:success] = Spree.t(:image_settings_updated)
redirect_to spree.edit_admin_image_settings_path
}
end
end
private
def update_styles(params)
if params[:new_attachment_styles].present?
params[:new_attachment_styles].each do |_index, style|
params[:attachment_styles][style[:name]] = style[:value] unless style[:value].empty?
end
end
styles = params[:attachment_styles]
Spree::Config[:attachment_styles] = ActiveSupport::JSON.encode(styles) unless styles.nil?
end
def update_headers(params)
if params[:new_s3_headers].present?
params[:new_s3_headers].each do |_index, header|
params[:s3_headers][header[:name]] = header[:value] unless header[:value].empty?
end
end
headers = params[:s3_headers]
Spree::Config[:s3_headers] = ActiveSupport::JSON.encode(headers) unless headers.nil?
end
def update_paperclip_settings
if Spree::Config[:use_s3]
s3_creds = { access_key_id: Spree::Config[:s3_access_key],
secret_access_key: Spree::Config[:s3_secret],
bucket: Spree::Config[:s3_bucket] }
Spree::Image.attachment_definitions[:attachment][:storage] = :s3
Spree::Image.attachment_definitions[:attachment][:s3_credentials] = s3_creds
Spree::Image.attachment_definitions[:attachment][:s3_headers] =
ActiveSupport::JSON.decode(Spree::Config[:s3_headers])
Spree::Image.attachment_definitions[:attachment][:bucket] = Spree::Config[:s3_bucket]
else
Spree::Image.attachment_definitions[:attachment].delete :storage
end
Spree::Image.attachment_definitions[:attachment][:styles] =
ActiveSupport::JSON.decode(Spree::Config[:attachment_styles]).symbolize_keys!
Spree::Image.attachment_definitions[:attachment][:path] = Spree::Config[:attachment_path]
Spree::Image.attachment_definitions[:attachment][:default_url] =
Spree::Config[:attachment_default_url]
Spree::Image.attachment_definitions[:attachment][:default_style] =
Spree::Config[:attachment_default_style]
# Spree stores attachent definitions in JSON. This converts the style name and format to
# strings. However, when paperclip encounters these, it doesn't recognise the format.
# Here we solve that problem by converting format and style name to symbols.
Spree::Image.reformat_styles
end
end
end
end

View File

@@ -0,0 +1,11 @@
Spree::Admin::ImageSettingsController.class_eval do
# Spree stores attachent definitions in JSON. This converts the style name and format to
# strings. However, when paperclip encounters these, it doesn't recognise the format.
# Here we solve that problem by converting format and style name to symbols.
def update_paperclip_settings_with_format_styles
update_paperclip_settings_without_format_styles
Spree::Image.reformat_styles
end
alias_method_chain :update_paperclip_settings, :format_styles
end

View File

@@ -1,39 +0,0 @@
module Spree
module Admin
class ImagesController < ResourceController
# This will make resource controller redirect correctly after deleting product images.
# This can be removed after upgrading to Spree 2.1.
# See here https://github.com/spree/spree/commit/334a011d2b8e16355e4ae77ae07cd93f7cbc8fd1
belongs_to 'spree/product', find_by: :permalink
before_filter :load_data
create.before :set_viewable
update.before :set_viewable
destroy.before :destroy_before
private
def location_after_save
admin_product_images_url(@product)
end
def load_data
@product = Product.find_by_permalink(params[:product_id])
@variants = @product.variants.collect do |variant|
[variant.options_text, variant.id]
end
@variants.insert(0, [Spree.t(:all), @product.master.id])
end
def set_viewable
@image.viewable_type = 'Spree::Variant'
@image.viewable_id = params[:image][:viewable_id]
end
def destroy_before
@viewable = @image.viewable
end
end
end
end

View File

@@ -0,0 +1,6 @@
Spree::Admin::ImagesController.class_eval do
# This will make resource controller redirect correctly after deleting product images.
# This can be removed after upgrading to Spree 2.1.
# See here https://github.com/spree/spree/commit/334a011d2b8e16355e4ae77ae07cd93f7cbc8fd1
belongs_to 'spree/product', find_by: :permalink
end

View File

@@ -1,40 +0,0 @@
module Spree
module Admin
class MailMethodsController < Spree::Admin::BaseController
after_filter :initialize_mail_settings
def update
if params[:smtp_password].blank?
params.delete(:smtp_password)
end
params.each do |name, value|
next unless Spree::Config.has_preference? name
Spree::Config[name] = value
end
flash[:success] = Spree.t(:successfully_updated, resource: Spree.t(:mail_methods))
render :edit
end
def testmail
if TestMailer.test_email(try_spree_current_user).deliver
flash[:success] = Spree.t('admin.mail_methods.testmail.delivery_success')
else
flash[:error] = Spree.t('admin.mail_methods.testmail.delivery_error')
end
rescue StandardError => e
flash[:error] = Spree.t('admin.mail_methods.testmail.error') % { e: e }
ensure
redirect_to edit_admin_mail_method_url
end
private
def initialize_mail_settings
Spree::Core::MailSettings.init
end
end
end
end

View File

@@ -43,7 +43,6 @@ Spree::Admin::Orders::CustomerDetailsController.class_eval do
params[:order][:guest_checkout] = registered_user.nil?
return unless registered_user
@order.user_id = registered_user.id
end
end

View File

@@ -3,6 +3,7 @@ require 'open_food_network/spree_api_key_loader'
Spree::Admin::OrdersController.class_eval do
include OpenFoodNetwork::SpreeApiKeyLoader
helper CheckoutHelper
before_filter :load_spree_api_key, only: :bulk_management
before_filter :load_order, only: %i[show edit update fire resend invoice print print_ticket]
before_filter :load_distribution_choices, only: [:new, :edit, :update]
@@ -26,10 +27,6 @@ Spree::Admin::OrdersController.class_eval do
# within the page then fetches the data it needs from Api::OrdersController
end
def bulk_management
load_spree_api_key
end
def edit
@order.shipments.map &:refresh_rates

View File

@@ -1,79 +0,0 @@
# this clas was inspired (heavily) from the mephisto admin architecture
module Spree
module Admin
class OverviewController < Spree::Admin::BaseController
def index
@enterprises = Enterprise
.managed_by(spree_current_user)
.order('is_primary_producer ASC, name')
@product_count = Spree::Product.active.managed_by(spree_current_user).count
@order_cycle_count = OrderCycle.active.managed_by(spree_current_user).count
if first_access
redirect_to enterprises_path
else
render dashboard_view
end
end
private
# Checks whether the user is accessing the admin for the first time
#
# @return [Boolean]
def first_access
outside_referral && incomplete_enterprise_registration?
end
# Checks whether the request comes from another admin page or not
#
# @return [Boolean]
def outside_referral
!URI(request.referer.to_s).path.match(%r{/admin})
end
# Checks that all of the enterprises owned by the current user have a 'sells'
# property specified, which indicates that the registration process has been
# completed
#
# @return [Boolean]
def incomplete_enterprise_registration?
@incomplete_enterprise_registration ||= spree_current_user
.owned_enterprises
.where(sells: 'unspecified')
.exists?
end
# Returns the appropriate enterprise path for the current user
#
# @return [String]
def enterprises_path
if managed_enterprises.size == 1
@enterprise = @enterprises.first
main_app.welcome_admin_enterprise_path(@enterprise)
else
main_app.admin_enterprises_path
end
end
# Returns the appropriate dashboard view for the current user
#
# @return [String]
def dashboard_view
if managed_enterprises.size == 1
@enterprise = @enterprises.first
:single_enterprise_dashboard
else
:multi_enterprise_dashboard
end
end
# Returns the list of enterprises the current user is manager of
#
# @return [ActiveRecord::Relation<Enterprise>]
def managed_enterprises
spree_current_user.enterprises
end
end
end
end

View File

@@ -0,0 +1,74 @@
Spree::Admin::OverviewController.class_eval do
def index
@enterprises = Enterprise
.managed_by(spree_current_user)
.order('is_primary_producer ASC, name')
@product_count = Spree::Product.active.managed_by(spree_current_user).count
@order_cycle_count = OrderCycle.active.managed_by(spree_current_user).count
if first_access
redirect_to enterprises_path
else
render dashboard_view
end
end
private
# Checks whether the user is accessing the admin for the first time
#
# @return [Boolean]
def first_access
outside_referral && incomplete_enterprise_registration?
end
# Checks whether the request comes from another admin page or not
#
# @return [Boolean]
def outside_referral
!URI(request.referer.to_s).path.match(%r{/admin})
end
# Checks that all of the enterprises owned by the current user have a 'sells'
# property specified, which indicates that the registration process has been
# completed
#
# @return [Boolean]
def incomplete_enterprise_registration?
@incomplete_enterprise_registration ||= spree_current_user
.owned_enterprises
.where(sells: 'unspecified')
.exists?
end
# Returns the appropriate enterprise path for the current user
#
# @return [String]
def enterprises_path
if managed_enterprises.size == 1
@enterprise = @enterprises.first
main_app.welcome_admin_enterprise_path(@enterprise)
else
main_app.admin_enterprises_path
end
end
# Returns the appropriate dashboard view for the current user
#
# @return [String]
def dashboard_view
if managed_enterprises.size == 1
@enterprise = @enterprises.first
:single_enterprise_dashboard
else
:multi_enterprise_dashboard
end
end
# Returns the list of enterprises the current user is manager of
#
# @return [ActiveRecord::Relation<Enterprise>]
def managed_enterprises
spree_current_user.enterprises
end
end

View File

@@ -1,68 +1,16 @@
module Spree
module Admin
class PaymentMethodsController < ResourceController
skip_before_filter :load_resource, only: [:create, :show_provider_preferences]
before_filter :load_data
before_filter :validate_payment_method_provider, only: [:create]
PaymentMethodsController.class_eval do
before_filter :restrict_stripe_account_change, only: [:update]
before_filter :force_environment, only: [:create, :update]
skip_before_filter :load_resource, only: [:show_provider_preferences]
before_filter :load_hubs, only: [:new, :edit, :update]
create.before :load_hubs
respond_to :html
def create
force_environment
@payment_method = params[:payment_method].
delete(:type).
constantize.
new(params[:payment_method])
@object = @payment_method
invoke_callbacks(:create, :before)
if @payment_method.save
invoke_callbacks(:create, :after)
flash[:success] = Spree.t(:successfully_created, resource: Spree.t(:payment_method))
redirect_to edit_admin_payment_method_path(@payment_method)
else
invoke_callbacks(:create, :fails)
respond_with(@payment_method)
end
end
def update
restrict_stripe_account_change
force_environment
invoke_callbacks(:update, :before)
payment_method_type = params[:payment_method].delete(:type)
if @payment_method['type'].to_s != payment_method_type
@payment_method.update_column(:type, payment_method_type)
@payment_method = PaymentMethod.find(params[:id])
end
payment_method_params = params[ActiveModel::Naming.param_key(@payment_method)] || {}
attributes = params[:payment_method].merge(payment_method_params)
attributes.each do |k, _v|
if k.include?("password") && attributes[k].blank?
attributes.delete(k)
end
end
if @payment_method.update_attributes(attributes)
invoke_callbacks(:update, :after)
flash[:success] = Spree.t(:successfully_updated, resource: Spree.t(:payment_method))
redirect_to edit_admin_payment_method_path(@payment_method)
else
invoke_callbacks(:update, :fails)
respond_with(@payment_method)
end
end
# Only show payment methods that user has access to and sort by distributor name
# ! Redundant code copied from Spree::Admin::ResourceController with modifications marked
def collection
return parent.public_send(controller_name) if parent_data.present?
collection = if model_class.respond_to?(:accessible_by) &&
!current_ability.has_block?(params[:action], model_class)
@@ -114,14 +62,6 @@ module Spree
@calculators = PaymentMethod.calculators.sort_by(&:name)
end
def validate_payment_method_provider
valid_payment_methods = Rails.application.config.spree.payment_methods.map(&:to_s)
return if valid_payment_methods.include?(params[:payment_method][:type])
flash[:error] = Spree.t(:invalid_payment_provider)
redirect_to new_admin_payment_method_path
end
def load_hubs
# rubocop:disable Style/TernaryParentheses
@hubs = Enterprise.managed_by(spree_current_user).is_distributor.sort_by! do |d|
@@ -133,8 +73,7 @@ module Spree
# Show Stripe as an option if enabled, or if the
# current payment_method is already a Stripe method
def show_stripe?
Spree::Config.stripe_connect_enabled ||
@payment_method.try(:type) == "Spree::Gateway::StripeConnect"
Spree::Config.stripe_connect_enabled || @payment_method.try(:type) == "Spree::Gateway::StripeConnect"
end
def restrict_stripe_account_change

View File

@@ -43,8 +43,8 @@ Spree::Admin::PaymentsController.class_eval do
else
flash[:error] = t(:cannot_perform_operation)
end
rescue Spree::Core::GatewayError => e
flash[:error] = e.message
rescue Spree::Core::GatewayError => ge
flash[:error] = ge.message
ensure
redirect_to request.referer
end

Some files were not shown because too many files have changed in this diff Show More