mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-22 20:16:50 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49de11567b | ||
|
|
3af0365c6b | ||
|
|
be92b0049b | ||
|
|
a1c94d0d9f | ||
|
|
f6bb8a9a04 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -31,7 +31,6 @@ public/system
|
||||
public/stylesheets
|
||||
public/images
|
||||
public/spree
|
||||
public/assets
|
||||
config/abr.yml
|
||||
config/initializers/feature_toggle.rb
|
||||
NERD_tree*
|
||||
|
||||
@@ -33,6 +33,7 @@ Layout/LineLength:
|
||||
- app/controllers/admin/inventory_items_controller.rb
|
||||
- app/controllers/admin/manager_invitations_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
|
||||
@@ -88,6 +89,7 @@ Layout/LineLength:
|
||||
- app/models/spree/tax_rate_decorator.rb
|
||||
- app/models/spree/taxon_decorator.rb
|
||||
- app/models/spree/user.rb
|
||||
- app/models/spree/variant_decorator.rb
|
||||
- app/models/subscription.rb
|
||||
- app/models/variant_override.rb
|
||||
- app/models/variant_override_set.rb
|
||||
@@ -96,6 +98,7 @@ Layout/LineLength:
|
||||
- app/services/embedded_page_service.rb
|
||||
- app/services/order_cycle_form.rb
|
||||
- app/services/order_factory.rb
|
||||
- app/services/subscriptions_count.rb
|
||||
- app/services/variants_stock_levels.rb
|
||||
- engines/web/app/helpers/web/cookies_policy_helper.rb
|
||||
- lib/discourse/single_sign_on.rb
|
||||
@@ -155,6 +158,7 @@ Layout/LineLength:
|
||||
- spec/controllers/spree/admin/orders/customer_details_controller_spec.rb
|
||||
- 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
|
||||
@@ -179,6 +183,7 @@ Layout/LineLength:
|
||||
- spec/features/admin/image_settings_spec.rb
|
||||
- spec/features/admin/multilingual_spec.rb
|
||||
- spec/features/admin/order_cycles_spec.rb
|
||||
- spec/features/admin/orders_spec.rb
|
||||
- spec/features/admin/overview_spec.rb
|
||||
- spec/features/admin/payment_method_spec.rb
|
||||
- spec/features/admin/product_import_spec.rb
|
||||
@@ -234,7 +239,10 @@ 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/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
|
||||
- spec/lib/open_food_network/subscription_summarizer_spec.rb
|
||||
- spec/lib/open_food_network/tag_rule_applicator_spec.rb
|
||||
- spec/lib/open_food_network/users_and_enterprises_report_spec.rb
|
||||
- spec/lib/open_food_network/xero_invoices_report_spec.rb
|
||||
@@ -309,6 +317,10 @@ Layout/LineLength:
|
||||
- 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
|
||||
- spec/services/subscription_variants_service_spec.rb
|
||||
- spec/spec_helper.rb
|
||||
- spec/support/cancan_helper.rb
|
||||
- spec/support/delayed_job_helper.rb
|
||||
@@ -374,6 +386,7 @@ Metrics/AbcSize:
|
||||
- app/helpers/spree/admin/base_helper.rb
|
||||
- app/helpers/spree/admin/zones_helper.rb
|
||||
- app/helpers/spree/orders_helper.rb
|
||||
- app/mailers/producer_mailer.rb
|
||||
- app/models/calculator/flat_percent_per_item.rb
|
||||
- app/models/column_preference.rb
|
||||
- app/models/enterprise.rb
|
||||
@@ -398,7 +411,7 @@ Metrics/AbcSize:
|
||||
- app/services/cart_service.rb
|
||||
- app/services/create_order_cycle.rb
|
||||
- app/services/order_syncer.rb
|
||||
- engines/order_management/app/services/order_management/subscriptions/validator.rb
|
||||
- app/services/subscription_validator.rb
|
||||
- lib/active_merchant/billing/gateways/stripe_decorator.rb
|
||||
- lib/active_merchant/billing/gateways/stripe_payment_intents.rb
|
||||
- lib/discourse/single_sign_on.rb
|
||||
@@ -464,6 +477,7 @@ Metrics/BlockLength:
|
||||
- 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
|
||||
- spec/lib/open_food_network/group_buy_report_spec.rb
|
||||
- spec/models/tag_rule/discount_order_spec.rb
|
||||
@@ -569,6 +583,7 @@ Metrics/MethodLength:
|
||||
- app/helpers/spree/admin/navigation_helper.rb
|
||||
- app/helpers/spree/admin/base_helper.rb
|
||||
- app/jobs/subscription_placement_job.rb
|
||||
- app/mailers/producer_mailer.rb
|
||||
- app/models/column_preference.rb
|
||||
- app/models/enterprise.rb
|
||||
- app/models/enterprise_relationship.rb
|
||||
@@ -671,12 +686,6 @@ Metrics/ModuleLength:
|
||||
- app/helpers/injection_helper.rb
|
||||
- app/helpers/spree/admin/navigation_helper.rb
|
||||
- app/helpers/spree/admin/base_helper.rb
|
||||
- engines/order_management/spec/services/order_management/subscriptions/estimator_spec.rb
|
||||
- engines/order_management/spec/services/order_management/subscriptions/form_spec.rb
|
||||
- engines/order_management/spec/services/order_management/subscriptions/proxy_order_syncer_spec.rb
|
||||
- engines/order_management/spec/services/order_management/subscriptions/summarizer_spec.rb
|
||||
- engines/order_management/spec/services/order_management/subscriptions/validator_spec.rb
|
||||
- engines/order_management/spec/services/order_management/subscriptions/variants_list_spec.rb
|
||||
- lib/open_food_network/column_preference_defaults.rb
|
||||
- spec/controllers/admin/enterprises_controller_spec.rb
|
||||
- spec/controllers/admin/order_cycles_controller_spec.rb
|
||||
@@ -692,7 +701,9 @@ 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/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
|
||||
- spec/lib/open_food_network/tag_rule_applicator_spec.rb
|
||||
- spec/lib/open_food_network/users_and_enterprises_report_spec.rb
|
||||
- spec/models/spree/ability_spec.rb
|
||||
|
||||
@@ -71,6 +71,7 @@ Lint/DuplicateHashKey:
|
||||
Lint/DuplicateMethods:
|
||||
Exclude:
|
||||
- 'lib/discourse/single_sign_on.rb'
|
||||
- 'lib/open_food_network/subscription_summary.rb'
|
||||
|
||||
# Offense count: 10
|
||||
Lint/IneffectiveAccessModifier:
|
||||
@@ -158,7 +159,7 @@ Naming/MethodParameterName:
|
||||
Exclude:
|
||||
- 'app/helpers/spree/admin/base_helper_decorator.rb'
|
||||
- 'app/helpers/spree/base_helper_decorator.rb'
|
||||
- 'engines/order_management/app/services/order_management/subscriptions/validator.rb'
|
||||
- 'app/services/subscription_validator.rb'
|
||||
- 'lib/open_food_network/reports/bulk_coop_report.rb'
|
||||
- 'lib/open_food_network/xero_invoices_report.rb'
|
||||
- 'spec/lib/open_food_network/reports/report_spec.rb'
|
||||
@@ -173,6 +174,7 @@ Naming/MethodParameterName:
|
||||
Naming/PredicateName:
|
||||
Exclude:
|
||||
- 'spec/**/*'
|
||||
- 'app/mailers/producer_mailer.rb'
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/enterprise_relationship.rb'
|
||||
- 'app/models/order_cycle.rb'
|
||||
@@ -629,6 +631,7 @@ Style/FrozenStringLiteralComment:
|
||||
- 'app/jobs/subscription_placement_job.rb'
|
||||
- 'app/jobs/welcome_enterprise_job.rb'
|
||||
- 'app/mailers/enterprise_mailer.rb'
|
||||
- 'app/mailers/producer_mailer.rb'
|
||||
- 'app/mailers/spree/base_mailer_decorator.rb'
|
||||
- 'app/mailers/spree/order_mailer_decorator.rb'
|
||||
- 'app/mailers/spree/user_mailer.rb'
|
||||
@@ -846,6 +849,11 @@ Style/FrozenStringLiteralComment:
|
||||
- 'app/services/reset_order_service.rb'
|
||||
- 'app/services/restart_checkout.rb'
|
||||
- 'app/services/search_orders.rb'
|
||||
- 'app/services/subscription_estimator.rb'
|
||||
- 'app/services/subscription_form.rb'
|
||||
- 'app/services/subscription_validator.rb'
|
||||
- 'app/services/subscription_variants_service.rb'
|
||||
- 'app/services/subscriptions_count.rb'
|
||||
- 'app/services/tax_rate_finder.rb'
|
||||
- 'app/services/upload_sanitizer.rb'
|
||||
- 'app/services/variant_deleter.rb'
|
||||
@@ -853,6 +861,7 @@ Style/FrozenStringLiteralComment:
|
||||
- 'app/validators/date_time_string_validator.rb'
|
||||
- 'app/validators/distributors_validator.rb'
|
||||
- 'app/validators/integer_array_validator.rb'
|
||||
- 'app/views/spree/admin/taxons/search.rabl'
|
||||
- 'config.ru'
|
||||
- 'engines/order_management/app/controllers/order_management/application_controller.rb'
|
||||
- 'engines/order_management/app/services/order_management/reports/enterprise_fee_summary/authorizer.rb'
|
||||
@@ -883,7 +892,6 @@ Style/FrozenStringLiteralComment:
|
||||
- 'engines/order_management/lib/order_management/engine.rb'
|
||||
- 'engines/order_management/lib/order_management/version.rb'
|
||||
- 'engines/order_management/order_management.gemspec'
|
||||
- 'engines/order_management/spec/performance/order_management/subscriptions/proxy_order_syncer_spec.rb'
|
||||
- 'engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/authorizer_spec.rb'
|
||||
- 'engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/parameters_spec.rb'
|
||||
- 'engines/order_management/spec/services/order_management/reports/enterprise_fee_summary/permissions_spec.rb'
|
||||
@@ -941,6 +949,7 @@ Style/FrozenStringLiteralComment:
|
||||
- 'lib/open_food_network/products_and_inventory_report.rb'
|
||||
- 'lib/open_food_network/products_and_inventory_report_base.rb'
|
||||
- 'lib/open_food_network/property_merge.rb'
|
||||
- 'lib/open_food_network/proxy_order_syncer.rb'
|
||||
- 'lib/open_food_network/rack_request_blocker.rb'
|
||||
- 'lib/open_food_network/referer_parser.rb'
|
||||
- 'lib/open_food_network/reports/bulk_coop_allocation_report.rb'
|
||||
@@ -957,6 +966,8 @@ Style/FrozenStringLiteralComment:
|
||||
- 'lib/open_food_network/scope_variants_for_search.rb'
|
||||
- 'lib/open_food_network/spree_api_key_loader.rb'
|
||||
- 'lib/open_food_network/subscription_payment_updater.rb'
|
||||
- 'lib/open_food_network/subscription_summarizer.rb'
|
||||
- 'lib/open_food_network/subscription_summary.rb'
|
||||
- 'lib/open_food_network/tag_rule_applicator.rb'
|
||||
- 'lib/open_food_network/user_balance_calculator.rb'
|
||||
- 'lib/open_food_network/users_and_enterprises_report.rb'
|
||||
@@ -1198,6 +1209,7 @@ Style/FrozenStringLiteralComment:
|
||||
- 'spec/lib/open_food_network/permissions_spec.rb'
|
||||
- 'spec/lib/open_food_network/products_and_inventory_report_spec.rb'
|
||||
- 'spec/lib/open_food_network/property_merge_spec.rb'
|
||||
- 'spec/lib/open_food_network/proxy_order_syncer_spec.rb'
|
||||
- 'spec/lib/open_food_network/referer_parser_spec.rb'
|
||||
- 'spec/lib/open_food_network/reports/report_spec.rb'
|
||||
- 'spec/lib/open_food_network/reports/row_spec.rb'
|
||||
@@ -1206,6 +1218,8 @@ Style/FrozenStringLiteralComment:
|
||||
- 'spec/lib/open_food_network/scope_variant_to_hub_spec.rb'
|
||||
- 'spec/lib/open_food_network/scope_variants_to_search_spec.rb'
|
||||
- 'spec/lib/open_food_network/subscription_payment_updater_spec.rb'
|
||||
- 'spec/lib/open_food_network/subscription_summarizer_spec.rb'
|
||||
- 'spec/lib/open_food_network/subscription_summary_spec.rb'
|
||||
- 'spec/lib/open_food_network/tag_rule_applicator_spec.rb'
|
||||
- 'spec/lib/open_food_network/user_balance_calculator_spec.rb'
|
||||
- 'spec/lib/open_food_network/users_and_enterprises_report_spec.rb'
|
||||
@@ -1290,6 +1304,7 @@ Style/FrozenStringLiteralComment:
|
||||
- 'spec/models/variant_override_spec.rb'
|
||||
- 'spec/performance/injection_helper_spec.rb'
|
||||
- 'spec/performance/orders_controller_spec.rb'
|
||||
- 'spec/performance/proxy_order_syncer_spec.rb'
|
||||
- 'spec/performance/shop_controller_spec.rb'
|
||||
- 'spec/requests/checkout/failed_checkout_spec.rb'
|
||||
- 'spec/requests/checkout/paypal_spec.rb'
|
||||
@@ -1340,6 +1355,11 @@ Style/FrozenStringLiteralComment:
|
||||
- 'spec/services/reset_order_service_spec.rb'
|
||||
- 'spec/services/restart_checkout_spec.rb'
|
||||
- 'spec/services/search_orders_spec.rb'
|
||||
- 'spec/services/subscription_estimator_spec.rb'
|
||||
- 'spec/services/subscription_form_spec.rb'
|
||||
- 'spec/services/subscription_validator_spec.rb'
|
||||
- 'spec/services/subscription_variants_service_spec.rb'
|
||||
- 'spec/services/subscriptions_count_spec.rb'
|
||||
- 'spec/services/tax_rate_finder_spec.rb'
|
||||
- 'spec/services/upload_sanitizer_spec.rb'
|
||||
- 'spec/services/variants_stock_levels_spec.rb'
|
||||
@@ -1537,6 +1557,7 @@ Style/Send:
|
||||
- 'spec/lib/open_food_network/products_and_inventory_report_spec.rb'
|
||||
- 'spec/lib/open_food_network/sales_tax_report_spec.rb'
|
||||
- 'spec/lib/open_food_network/subscription_payment_updater_spec.rb'
|
||||
- 'spec/lib/open_food_network/subscription_summarizer_spec.rb'
|
||||
- 'spec/lib/open_food_network/tag_rule_applicator_spec.rb'
|
||||
- 'spec/lib/open_food_network/xero_invoices_report_spec.rb'
|
||||
- 'spec/lib/stripe/webhook_handler_spec.rb'
|
||||
|
||||
13
DOCKER.md
13
DOCKER.md
@@ -35,22 +35,13 @@ Download the Docker images and build the containers:
|
||||
$ docker-compose build
|
||||
```
|
||||
|
||||
Setup the database and seed it with sample data:
|
||||
```sh
|
||||
$ docker-compose run web bundle exec rake db:reset
|
||||
$ docker-compose run web bundle exec rake db:test:prepare
|
||||
$ docker-compose run web bundle exec rake ofn:sample_data
|
||||
```
|
||||
|
||||
Finally, run the app with all the required containers:
|
||||
Run the app with all the required containers:
|
||||
|
||||
```sh
|
||||
$ docker-compose up
|
||||
```
|
||||
|
||||
The default admin user is 'ofn@example.com' with 'ofn123' password.
|
||||
This command will setup the database and seed it with sample data. The default admin user is 'ofn@example.com' with 'ofn123' password.
|
||||
Check the app in the browser at `http://localhost:3000`.
|
||||
|
||||
You will then get the trace of the containers in the terminal. You can stop the containers using Ctrl-C in the terminal.
|
||||
|
||||
You can find some useful tips and commands [here](https://github.com/openfoodfoundation/openfoodnetwork/wiki/Docker:-useful-tips-and-commands).
|
||||
|
||||
@@ -12,7 +12,7 @@ ENV BUNDLE_PATH /bundles
|
||||
WORKDIR /usr/src/app
|
||||
COPY .ruby-version .
|
||||
|
||||
# Install Rbenv & Ruby
|
||||
# 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 && \
|
||||
@@ -21,15 +21,12 @@ RUN git clone https://github.com/rbenv/rbenv.git ${RBENV_ROOT} && \
|
||||
rbenv global $(cat .ruby-version) && \
|
||||
gem install bundler --version=1.17.2
|
||||
|
||||
# Install Postgres
|
||||
# Postgres
|
||||
RUN sh -c "echo 'deb https://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main' > /etc/apt/sources.list.d/pgdg.list" && \
|
||||
wget --quiet -O - https://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | apt-key add - && \
|
||||
apt-get update && \
|
||||
apt-get install -yqq --no-install-recommends postgresql-client-9.5 libpq-dev
|
||||
|
||||
# Install node
|
||||
RUN apt-get install -y nodejs
|
||||
|
||||
# Install Chrome
|
||||
RUN wget --quiet -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add - && \
|
||||
sh -c "echo 'deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main' >> /etc/apt/sources.list.d/google-chrome.list" && \
|
||||
@@ -41,6 +38,4 @@ RUN wget https://chromedriver.storage.googleapis.com/2.41/chromedriver_linux64.z
|
||||
unzip chromedriver_linux64.zip -d /usr/bin && \
|
||||
chmod u+x /usr/bin/chromedriver
|
||||
|
||||
# Copy code and install app dependencies
|
||||
COPY . /usr/src/app/
|
||||
RUN bundle install
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
This is a general guide to setting up an Open Food Network development environment on your local machine.
|
||||
|
||||
The fastest way to make it work locally is to use Docker, see the [Docker setup guide](DOCKER.md).
|
||||
|
||||
The following guides are located in the wiki and provide more OS-specific step-by-step instructions:
|
||||
|
||||
- [Ubuntu Setup Guide][ubuntu]
|
||||
@@ -13,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.3.7
|
||||
* Ruby 2.1.9
|
||||
* PostgreSQL database
|
||||
* PhantomJS (for testing)
|
||||
* See Gemfile for a list of gems required
|
||||
@@ -60,10 +58,10 @@ Now, your dreams of spinning up a development server can be realised:
|
||||
|
||||
bundle exec rails server
|
||||
|
||||
To login as the default user, use:
|
||||
To login as Spree default user, use:
|
||||
|
||||
email: ofn@example.com
|
||||
password: ofn123
|
||||
email: spree@example.com
|
||||
password: spree123
|
||||
|
||||
### Testing
|
||||
|
||||
@@ -120,7 +118,7 @@ $ createdb open_food_network_test --owner=ofn
|
||||
If these commands succeed, you should be able to [continue the setup process](#get-it-running).
|
||||
|
||||
[developer-wiki]: https://github.com/openfoodfoundation/openfoodnetwork/wiki
|
||||
[sierra]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup%3A-macOS-%28Sierra%2C-HighSierra%2C-Mojave-and-Catalina%29
|
||||
[sierra]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup%3A-macOS-%28Sierra%2C-HighSierra-and-Mojave%29
|
||||
[el-capitan]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup:-OS-X-(El-Capitan)
|
||||
[ubuntu]: https://github.com/openfoodfoundation/openfoodnetwork/wiki/Development-Environment-Setup:-Ubuntu
|
||||
[wiki]: https://github.com/openfoodfoundation/openfoodnetwork/wiki
|
||||
|
||||
14
Gemfile
14
Gemfile
@@ -9,6 +9,8 @@ gem 'rails-i18n', '~> 3.0.0'
|
||||
gem 'rails_safe_tasks', '~> 1.0'
|
||||
|
||||
gem "activerecord-import"
|
||||
# Patched version. See http://rubysec.com/advisories/CVE-2015-5312/.
|
||||
gem 'nokogiri', '>= 1.6.7.1'
|
||||
|
||||
gem "catalog", path: "./engines/catalog"
|
||||
gem "order_management", path: "./engines/order_management"
|
||||
@@ -43,6 +45,10 @@ gem 'daemons'
|
||||
gem 'delayed_job_active_record'
|
||||
gem 'delayed_job_web'
|
||||
|
||||
# Fix bug in simple_form preventing collection_check_boxes usage within form_for block
|
||||
# When merged, revert to upstream gem
|
||||
gem 'simple_form', github: 'RohanM/simple_form'
|
||||
|
||||
# Spree's default pagination gem (locked to the current version used by Spree)
|
||||
# We use it's methods in OFN code as well, so this is a direct dependency
|
||||
gem 'kaminari', '~> 0.14.1'
|
||||
@@ -53,6 +59,7 @@ gem 'aws-sdk'
|
||||
gem 'bugsnag'
|
||||
gem 'db2fog'
|
||||
gem 'haml'
|
||||
gem 'rabl'
|
||||
gem 'redcarpet'
|
||||
gem 'sass', "~> 3.3"
|
||||
gem 'sass-rails', '~> 3.2.3'
|
||||
@@ -67,6 +74,7 @@ gem 'angularjs-file-upload-rails', '~> 2.4.1'
|
||||
gem 'blockenspiel'
|
||||
gem 'custom_error_message', github: 'jeremydurham/custom-err-msg'
|
||||
gem 'dalli'
|
||||
gem 'deface', '1.0.2'
|
||||
gem 'diffy'
|
||||
gem 'figaro'
|
||||
gem 'geocoder'
|
||||
@@ -94,7 +102,7 @@ gem 'test-unit', '~> 3.3'
|
||||
gem 'coffee-rails', '~> 3.2.1'
|
||||
gem 'compass-rails'
|
||||
|
||||
gem 'mini_racer', '0.2.10'
|
||||
gem 'mini_racer', '0.2.9'
|
||||
|
||||
gem 'uglifier', '>= 1.0.3'
|
||||
|
||||
@@ -104,6 +112,7 @@ gem 'momentjs-rails'
|
||||
gem 'turbo-sprockets-rails3'
|
||||
|
||||
gem "foundation-rails"
|
||||
gem 'foundation_rails_helper', github: 'willrjmarshall/foundation_rails_helper', branch: "rails3"
|
||||
|
||||
gem 'jquery-migrate-rails'
|
||||
gem 'jquery-rails', '3.1.5'
|
||||
@@ -114,14 +123,13 @@ gem 'ofn-qz', github: 'openfoodfoundation/ofn-qz', ref: '60da2ae4c44cbb4c8d602f5
|
||||
|
||||
group :production, :staging do
|
||||
gem 'ddtrace'
|
||||
gem 'unicorn-worker-killer'
|
||||
end
|
||||
|
||||
group :test, :development do
|
||||
# Pretty printed test output
|
||||
gem 'atomic'
|
||||
gem 'awesome_print'
|
||||
gem 'capybara', '>= 2.18.0' # 3.0 requires rack 1.6 that only works with Rails 4.2
|
||||
gem 'capybara', '>= 2.18.0' # 3.0 requires nokogiri 1.8
|
||||
gem 'database_cleaner', '0.7.1', require: false
|
||||
gem "factory_bot_rails", require: false
|
||||
gem 'fuubar', '~> 2.5.0'
|
||||
|
||||
82
Gemfile.lock
82
Gemfile.lock
@@ -1,3 +1,11 @@
|
||||
GIT
|
||||
remote: https://github.com/RohanM/simple_form.git
|
||||
revision: 45f08a213b40f3d4bda5f5398db841137587160a
|
||||
specs:
|
||||
simple_form (2.0.2)
|
||||
actionpack (~> 3.0)
|
||||
activemodel (~> 3.0)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/jeremydurham/custom-err-msg.git
|
||||
revision: 3a8ec9dddc7a5b0aab7c69a6060596de300c68f4
|
||||
@@ -23,7 +31,7 @@ GIT
|
||||
|
||||
GIT
|
||||
remote: https://github.com/openfoodfoundation/spree.git
|
||||
revision: e10ca1f689b1658040b081939b7523f6fb68895a
|
||||
revision: 8a8585a43cd04d1a50dc65227f337a91b18d66d5
|
||||
branch: 2-0-4-stable
|
||||
specs:
|
||||
spree_core (2.0.4)
|
||||
@@ -32,13 +40,14 @@ GIT
|
||||
awesome_nested_set (= 2.1.5)
|
||||
aws-sdk (~> 1.11.1)
|
||||
cancan (~> 1.6.10)
|
||||
deface (>= 0.9.1)
|
||||
ffaker (~> 1.16)
|
||||
highline (= 1.6.18)
|
||||
httparty (~> 0.11)
|
||||
json (>= 1.7.7)
|
||||
kaminari (~> 0.14.1)
|
||||
money (= 5.1.1)
|
||||
paperclip (~> 3.4.1)
|
||||
paperclip (~> 3.0)
|
||||
paranoia (~> 1.3)
|
||||
rails (~> 3.2.14)
|
||||
ransack (= 0.7.2)
|
||||
@@ -56,6 +65,16 @@ GIT
|
||||
rails-i18n
|
||||
spree_core (>= 1.1)
|
||||
|
||||
GIT
|
||||
remote: https://github.com/willrjmarshall/foundation_rails_helper.git
|
||||
revision: 4d5d53fdc4b1fb71e66524d298c5c635de82cfbb
|
||||
branch: rails3
|
||||
specs:
|
||||
foundation_rails_helper (0.4)
|
||||
actionpack (>= 3.0)
|
||||
activemodel (>= 3.0)
|
||||
railties (>= 3.0)
|
||||
|
||||
PATH
|
||||
remote: engines/catalog
|
||||
specs:
|
||||
@@ -154,7 +173,7 @@ GEM
|
||||
xpath (>= 2.0, < 4.0)
|
||||
childprocess (3.0.0)
|
||||
chronic (0.10.2)
|
||||
chunky_png (1.3.11)
|
||||
chunky_png (1.3.10)
|
||||
climate_control (0.2.0)
|
||||
cocaine (0.5.8)
|
||||
climate_control (>= 0.0.3, < 1.0)
|
||||
@@ -166,6 +185,7 @@ GEM
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.10.0)
|
||||
colorize (0.8.1)
|
||||
combine_pdf (1.0.16)
|
||||
ruby-rc4 (>= 0.1.5)
|
||||
compass (1.0.3)
|
||||
@@ -180,7 +200,7 @@ GEM
|
||||
sass (>= 3.3.0, < 3.5)
|
||||
compass-import-once (1.0.5)
|
||||
sass (>= 3.2, < 3.5)
|
||||
compass-rails (4.0.0)
|
||||
compass-rails (3.1.0)
|
||||
compass (~> 1.0.0)
|
||||
sass-rails (< 5.1)
|
||||
sprockets (< 4.0)
|
||||
@@ -196,9 +216,14 @@ GEM
|
||||
activerecord (>= 3.2.0, < 5.0)
|
||||
fog (~> 1.0)
|
||||
rails (>= 3.2.0, < 5.0)
|
||||
ddtrace (0.35.1)
|
||||
ddtrace (0.33.1)
|
||||
msgpack
|
||||
debugger-linecache (1.2.0)
|
||||
deface (1.0.2)
|
||||
colorize (>= 0.5.8)
|
||||
nokogiri (~> 1.6.0)
|
||||
polyglot
|
||||
rails (>= 3.1)
|
||||
delayed_job (4.1.8)
|
||||
activesupport (>= 3.0, < 6.1)
|
||||
delayed_job_active_record (4.1.4)
|
||||
@@ -231,8 +256,8 @@ GEM
|
||||
railties (>= 3.0.0)
|
||||
faraday (1.0.0)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffaker (1.32.1)
|
||||
ffi (1.12.2)
|
||||
ffaker (1.22.1)
|
||||
ffi (1.11.3)
|
||||
figaro (1.1.1)
|
||||
thor (~> 0.14)
|
||||
fission (0.5.0)
|
||||
@@ -396,8 +421,6 @@ GEM
|
||||
rspec-core (~> 3.0)
|
||||
ruby-progressbar (~> 1.4)
|
||||
geocoder (1.1.8)
|
||||
get_process_mem (0.2.5)
|
||||
ffi (~> 1.0)
|
||||
gmaps4rails (1.5.6)
|
||||
haml (4.0.7)
|
||||
tilt
|
||||
@@ -442,9 +465,9 @@ GEM
|
||||
method_source (0.9.2)
|
||||
mime-types (1.25.1)
|
||||
mini_mime (1.0.1)
|
||||
mini_portile2 (2.4.0)
|
||||
mini_racer (0.2.10)
|
||||
libv8 (> 7.3)
|
||||
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)
|
||||
@@ -454,15 +477,15 @@ GEM
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.1.1)
|
||||
newrelic_rpm (3.18.1.330)
|
||||
nokogiri (1.10.9)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
nokogiri (1.6.8.1)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
oauth2 (1.4.4)
|
||||
faraday (>= 0.8, < 2.0)
|
||||
jwt (>= 1.0, < 3.0)
|
||||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
rack (>= 1.2, < 3)
|
||||
oj (3.10.6)
|
||||
oj (3.10.5)
|
||||
orm_adapter (0.5.0)
|
||||
paper_trail (5.2.3)
|
||||
activerecord (>= 3.0, < 6.0)
|
||||
@@ -476,7 +499,7 @@ GEM
|
||||
parallel (1.19.1)
|
||||
paranoia (1.3.4)
|
||||
activerecord (~> 3.1)
|
||||
parser (2.7.1.0)
|
||||
parser (2.7.0.5)
|
||||
ast (~> 2.4.0)
|
||||
paypal-sdk-core (0.2.10)
|
||||
multi_json (~> 1.0)
|
||||
@@ -495,6 +518,8 @@ GEM
|
||||
byebug (>= 9.0, < 9.1)
|
||||
pry (~> 0.10)
|
||||
public_suffix (4.0.3)
|
||||
rabl (0.8.4)
|
||||
activesupport (>= 2.3.14)
|
||||
rack (1.4.7)
|
||||
rack-cache (1.11.0)
|
||||
rack (>= 0.4)
|
||||
@@ -534,8 +559,8 @@ GEM
|
||||
activerecord (~> 3.0)
|
||||
polyamorous (~> 0.5.0)
|
||||
rb-fsevent (0.10.3)
|
||||
rb-inotify (0.10.1)
|
||||
ffi (~> 1.0)
|
||||
rb-inotify (0.9.10)
|
||||
ffi (>= 0.5.0, < 2)
|
||||
rbvmomi (1.13.0)
|
||||
builder (~> 3.0)
|
||||
json (>= 1.8)
|
||||
@@ -579,15 +604,15 @@ GEM
|
||||
rspec-retry (0.6.2)
|
||||
rspec-core (> 3.3)
|
||||
rspec-support (3.9.2)
|
||||
rubocop (0.81.0)
|
||||
rubocop (0.80.1)
|
||||
jaro_winkler (~> 1.5.1)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 2.7.0.1)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
rexml
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 2.0)
|
||||
rubocop-rails (2.5.2)
|
||||
unicode-display_width (>= 1.4.0, < 1.7)
|
||||
rubocop-rails (2.5.0)
|
||||
activesupport
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 0.72.0)
|
||||
@@ -646,16 +671,13 @@ GEM
|
||||
tzinfo (0.3.56)
|
||||
uglifier (4.2.0)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
unicode-display_width (1.7.0)
|
||||
unicorn (5.5.5)
|
||||
unicode-display_width (1.6.1)
|
||||
unicorn (5.5.4)
|
||||
kgio (~> 2.6)
|
||||
raindrops (~> 0.7)
|
||||
unicorn-rails (2.2.1)
|
||||
rack
|
||||
unicorn
|
||||
unicorn-worker-killer (0.4.4)
|
||||
get_process_mem (~> 0)
|
||||
unicorn (>= 4, < 6)
|
||||
uuidtools (2.1.5)
|
||||
warden (1.2.7)
|
||||
rack (>= 1.0)
|
||||
@@ -706,6 +728,7 @@ DEPENDENCIES
|
||||
db2fog
|
||||
ddtrace
|
||||
debugger-linecache
|
||||
deface (= 1.0.2)
|
||||
delayed_job_active_record
|
||||
delayed_job_web
|
||||
devise (~> 2.2.5)
|
||||
@@ -717,6 +740,7 @@ DEPENDENCIES
|
||||
foreigner
|
||||
foundation-icons-sass-rails
|
||||
foundation-rails
|
||||
foundation_rails_helper!
|
||||
fuubar (~> 2.5.0)
|
||||
geocoder
|
||||
gmaps4rails
|
||||
@@ -732,9 +756,10 @@ DEPENDENCIES
|
||||
kaminari (~> 0.14.1)
|
||||
knapsack
|
||||
letter_opener (>= 1.4.1)
|
||||
mini_racer (= 0.2.10)
|
||||
mini_racer (= 0.2.9)
|
||||
momentjs-rails
|
||||
newrelic_rpm (~> 3.0)
|
||||
nokogiri (>= 1.6.7.1)
|
||||
oauth2 (~> 1.4.4)
|
||||
ofn-qz!
|
||||
oj
|
||||
@@ -743,6 +768,7 @@ DEPENDENCIES
|
||||
paperclip (~> 3.4.1)
|
||||
pg (~> 0.21.0)
|
||||
pry-byebug (>= 3.4.3)
|
||||
rabl
|
||||
rack-mini-profiler (< 3.0.0)
|
||||
rack-rewrite
|
||||
rack-ssl
|
||||
@@ -761,6 +787,7 @@ DEPENDENCIES
|
||||
select2-rails (~> 3.4.7)
|
||||
selenium-webdriver
|
||||
shoulda-matchers
|
||||
simple_form!
|
||||
simplecov
|
||||
spinjs-rails
|
||||
spree_core!
|
||||
@@ -776,7 +803,6 @@ DEPENDENCIES
|
||||
uglifier (>= 1.0.3)
|
||||
unicorn
|
||||
unicorn-rails
|
||||
unicorn-worker-killer
|
||||
web!
|
||||
webdrivers
|
||||
webmock
|
||||
|
||||
@@ -29,7 +29,7 @@ angular.module("admin.enterprises")
|
||||
# from a directive "nav-check" in the page - if we pass it here it will be called in the test suite,
|
||||
# and on all new uses of this contoller, and we might not want that.
|
||||
enterpriseNavCallback = ->
|
||||
if $scope.enterprise_form?.$dirty
|
||||
if $scope.enterprise_form != undefined && $scope.enterprise_form.$dirty
|
||||
t('admin.unsaved_confirm_leave')
|
||||
|
||||
# Register the NavigationCheck callback
|
||||
|
||||
@@ -2,24 +2,19 @@ angular.module("admin.indexUtils").factory "PagedFetcher", (dataFetcher) ->
|
||||
new class PagedFetcher
|
||||
# Given a URL like http://example.com/foo?page=::page::&per_page=20
|
||||
# And the response includes an attribute pages with the number of pages to fetch
|
||||
# Fetch each page async, and call the pageCallback callback with the resulting data
|
||||
# Developer note: this class should not be re-used!
|
||||
page: 1
|
||||
last_page: 1
|
||||
# Fetch each page async, and call the processData callback with the resulting data
|
||||
fetch: (url, processData, onLastPageComplete) ->
|
||||
dataFetcher(@urlForPage(url, 1)).then (data) =>
|
||||
processData data
|
||||
|
||||
fetch: (url, pageCallback) ->
|
||||
@fetchPages(url, @page, pageCallback)
|
||||
if data.pages > 1
|
||||
for page in [2..data.pages]
|
||||
lastPromise = dataFetcher(@urlForPage(url, page)).then (data) ->
|
||||
processData data
|
||||
onLastPageComplete && lastPromise.then onLastPageComplete
|
||||
return
|
||||
else
|
||||
onLastPageComplete && onLastPageComplete()
|
||||
|
||||
urlForPage: (url, page) ->
|
||||
url.replace("::page::", page)
|
||||
|
||||
fetchPages: (url, page, pageCallback) ->
|
||||
dataFetcher(@urlForPage(url, page)).then (data) =>
|
||||
@page++
|
||||
@last_page = data.pages
|
||||
|
||||
pageCallback(data) if pageCallback
|
||||
|
||||
if @page <= @last_page
|
||||
@fetchPages(url, @page, pageCallback)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout, $http, $q, StatusMessage, Columns, SortOptions, Dereferencer, Orders, LineItems, Enterprises, OrderCycles, VariantUnitManager, RequestMonitor) ->
|
||||
$scope.initialized = false
|
||||
$scope.RequestMonitor = RequestMonitor
|
||||
$scope.line_items = LineItems.all
|
||||
$scope.filteredLineItems = []
|
||||
$scope.confirmDelete = true
|
||||
$scope.startDate = moment().startOf('day').subtract(7, 'days').format('YYYY-MM-DD')
|
||||
$scope.endDate = moment().startOf('day').format('YYYY-MM-DD')
|
||||
@@ -15,77 +15,50 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
$scope.confirmRefresh = ->
|
||||
LineItems.allSaved() || confirm(t("unsaved_changes_warning"))
|
||||
|
||||
$scope.resetFilters = ->
|
||||
$scope.distributorFilter = ''
|
||||
$scope.supplierFilter = ''
|
||||
$scope.orderCycleFilter = ''
|
||||
$scope.quickSearch = ''
|
||||
|
||||
$scope.resetSelectFilters = ->
|
||||
$scope.resetFilters()
|
||||
$scope.refreshData()
|
||||
$scope.distributorFilter = 0
|
||||
$scope.supplierFilter = 0
|
||||
$scope.orderCycleFilter = 0
|
||||
$scope.quickSearch = ""
|
||||
|
||||
$scope.refreshData = ->
|
||||
unless !$scope.orderCycleFilter? || $scope.orderCycleFilter == ''
|
||||
$scope.setOrderCycleDateRange()
|
||||
unless !$scope.orderCycleFilter? || $scope.orderCycleFilter == 0
|
||||
$scope.startDate = moment(OrderCycles.byID[$scope.orderCycleFilter].orders_open_at).format('YYYY-MM-DD')
|
||||
$scope.endDate = moment(OrderCycles.byID[$scope.orderCycleFilter].orders_close_at).startOf('day').format('YYYY-MM-DD')
|
||||
|
||||
$scope.formattedStartDate = moment($scope.startDate).format()
|
||||
$scope.formattedEndDate = moment($scope.endDate).add(1,'day').format()
|
||||
formatted_start_date = moment($scope.startDate).format()
|
||||
formatted_end_date = moment($scope.endDate).add(1,'day').format()
|
||||
|
||||
return unless moment($scope.formattedStartDate).isValid() and moment($scope.formattedEndDate).isValid()
|
||||
|
||||
$scope.loadOrders()
|
||||
$scope.loadLineItems()
|
||||
|
||||
unless $scope.initialized
|
||||
$scope.loadAssociatedData()
|
||||
|
||||
$scope.dereferenceLoadedData()
|
||||
|
||||
$scope.setOrderCycleDateRange = ->
|
||||
start_date = OrderCycles.byID[$scope.orderCycleFilter].orders_open_at
|
||||
end_date = OrderCycles.byID[$scope.orderCycleFilter].orders_close_at
|
||||
format = "YYYY-MM-DD HH:mm:ss Z"
|
||||
$scope.startDate = moment(start_date, format).format('YYYY-MM-DD')
|
||||
$scope.endDate = moment(end_date, format).startOf('day').format('YYYY-MM-DD')
|
||||
|
||||
$scope.loadOrders = ->
|
||||
RequestMonitor.load $scope.orders = Orders.index(
|
||||
"q[state_not_eq]": "canceled",
|
||||
"q[completed_at_not_null]": "true",
|
||||
"q[distributor_id_eq]": $scope.distributorFilter,
|
||||
"q[order_cycle_id_eq]": $scope.orderCycleFilter,
|
||||
"q[completed_at_gteq]": $scope.formattedStartDate,
|
||||
"q[completed_at_lt]": $scope.formattedEndDate
|
||||
"q[completed_at_gteq]": formatted_start_date,
|
||||
"q[completed_at_lt]": formatted_end_date
|
||||
)
|
||||
|
||||
$scope.loadLineItems = ->
|
||||
RequestMonitor.load LineItems.index(
|
||||
"q[order_state_not_eq]": "canceled",
|
||||
"q[order_completed_at_not_null]": "true",
|
||||
"q[order_distributor_id_eq]": $scope.distributorFilter,
|
||||
"q[variant_product_supplier_id_eq]": $scope.supplierFilter,
|
||||
"q[order_order_cycle_id_eq]": $scope.orderCycleFilter,
|
||||
"q[order_completed_at_gteq]": $scope.formattedStartDate,
|
||||
"q[order_completed_at_lt]": $scope.formattedEndDate
|
||||
RequestMonitor.load $scope.lineItems = LineItems.index(
|
||||
"q[order][state_not_eq]": "canceled",
|
||||
"q[order][completed_at_not_null]": "true",
|
||||
"q[order][completed_at_gteq]": formatted_start_date,
|
||||
"q[order][completed_at_lt]": formatted_end_date
|
||||
)
|
||||
|
||||
$scope.loadAssociatedData = ->
|
||||
RequestMonitor.load $scope.distributors = Enterprises.index(action: "visible", ams_prefix: "basic", "q[sells_in][]": ["own", "any"])
|
||||
RequestMonitor.load $scope.orderCycles = OrderCycles.index(ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{moment().subtract(90,'days').format()}")
|
||||
RequestMonitor.load $scope.suppliers = Enterprises.index(action: "visible", ams_prefix: "basic", "q[is_primary_producer_eq]": "true")
|
||||
unless $scope.initialized
|
||||
RequestMonitor.load $scope.distributors = Enterprises.index(action: "visible", ams_prefix: "basic", "q[sells_in][]": ["own", "any"])
|
||||
RequestMonitor.load $scope.orderCycles = OrderCycles.index(ams_prefix: "basic", as: "distributor", "q[orders_close_at_gt]": "#{moment().subtract(90,'days').format()}")
|
||||
RequestMonitor.load $scope.suppliers = Enterprises.index(action: "visible", ams_prefix: "basic", "q[is_primary_producer_eq]": "true")
|
||||
|
||||
$scope.dereferenceLoadedData = ->
|
||||
RequestMonitor.load $q.all([$scope.orders.$promise, $scope.distributors.$promise, $scope.orderCycles.$promise, $scope.suppliers.$promise, $scope.line_items.$promise]).then ->
|
||||
RequestMonitor.load $q.all([$scope.orders.$promise, $scope.distributors.$promise, $scope.orderCycles.$promise, $scope.suppliers.$promise, $scope.lineItems.$promise]).then ->
|
||||
Dereferencer.dereferenceAttr $scope.orders, "distributor", Enterprises.byID
|
||||
Dereferencer.dereferenceAttr $scope.orders, "order_cycle", OrderCycles.byID
|
||||
Dereferencer.dereferenceAttr $scope.line_items, "supplier", Enterprises.byID
|
||||
Dereferencer.dereferenceAttr $scope.line_items, "order", Orders.byID
|
||||
Dereferencer.dereferenceAttr $scope.lineItems, "supplier", Enterprises.byID
|
||||
Dereferencer.dereferenceAttr $scope.lineItems, "order", Orders.byID
|
||||
$scope.bulk_order_form.$setPristine()
|
||||
StatusMessage.clear()
|
||||
|
||||
unless $scope.initialized
|
||||
$scope.initialized = true
|
||||
$timeout ->
|
||||
$scope.resetSelectFilters()
|
||||
|
||||
$scope.$watch 'bulk_order_form.$dirty', (newVal, oldVal) ->
|
||||
if newVal == true
|
||||
@@ -104,12 +77,13 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
|
||||
$scope.deleteLineItem = (lineItem) ->
|
||||
if ($scope.confirmDelete && confirm(t "are_you_sure")) || !$scope.confirmDelete
|
||||
LineItems.delete lineItem
|
||||
LineItems.delete lineItem, =>
|
||||
$scope.lineItems.splice $scope.lineItems.indexOf(lineItem), 1
|
||||
|
||||
$scope.deleteLineItems = (lineItemsToDelete) ->
|
||||
$scope.deleteLineItems = (lineItems) ->
|
||||
existingState = $scope.confirmDelete
|
||||
$scope.confirmDelete = false
|
||||
$scope.deleteLineItem lineItem for lineItem in lineItemsToDelete when lineItem.checked
|
||||
$scope.deleteLineItem lineItem for lineItem in lineItems when lineItem.checked
|
||||
$scope.confirmDelete = existingState
|
||||
|
||||
$scope.allBoxesChecked = ->
|
||||
@@ -180,5 +154,4 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
lineItem.final_weight_volume = LineItems.pristineByID[lineItem.id].final_weight_volume * lineItem.quantity / LineItems.pristineByID[lineItem.id].quantity
|
||||
$scope.weightAdjustedPrice(lineItem)
|
||||
|
||||
$scope.resetFilters()
|
||||
$scope.refreshData()
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
angular.module('admin.orderCycles')
|
||||
.controller 'AdminEditOrderCycleCtrl', ($scope, $controller, $filter, $location, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, Schedules, RequestMonitor, NavigationCheck, ocInstance) ->
|
||||
.controller 'AdminEditOrderCycleCtrl', ($scope, $controller, $filter, $location, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, Schedules, RequestMonitor, ocInstance) ->
|
||||
$controller('AdminOrderCycleBasicCtrl', {$scope: $scope, ocInstance: ocInstance})
|
||||
|
||||
order_cycle_id = $location.absUrl().match(/\/admin\/order_cycles\/(\d+)/)[1]
|
||||
@@ -18,12 +18,5 @@ angular.module('admin.orderCycles')
|
||||
|
||||
$scope.submit = ($event, destination) ->
|
||||
$event.preventDefault()
|
||||
NavigationCheck.clear()
|
||||
StatusMessage.display 'progress', t('js.saving')
|
||||
OrderCycle.update(destination, $scope.order_cycle_form)
|
||||
|
||||
warnAboutUnsavedChanges = ->
|
||||
if $scope.order_cycle_form?.$dirty
|
||||
t('admin.unsaved_confirm_leave')
|
||||
|
||||
NavigationCheck.register(warnAboutUnsavedChanges)
|
||||
@@ -67,7 +67,7 @@ angular.module("admin.orders").controller "ordersCtrl", ($scope, $timeout, Reque
|
||||
return unless sort && sort.predicate != ""
|
||||
|
||||
$scope.sorting = sort.getSortingExpr()
|
||||
$scope.fetchResults()
|
||||
$scope.fetchProducts()
|
||||
, true
|
||||
|
||||
$scope.capturePayment = (order) ->
|
||||
|
||||
@@ -14,10 +14,9 @@ angular.module("admin.payments").factory 'AdminStripeElements', ($rootScope, Sta
|
||||
@stripe.createToken(@card, cardData).then (response) =>
|
||||
if(response.error)
|
||||
StatusMessage.display 'error', response.error.message
|
||||
console.error(JSON.stringify(response.error))
|
||||
else
|
||||
secrets.token = response.token.id
|
||||
secrets.cc_type = @mapTokenApiCardBrand(response.token.card.brand)
|
||||
secrets.cc_type = @mapCC(response.token.card.brand)
|
||||
secrets.card = response.token.card
|
||||
submit()
|
||||
|
||||
@@ -30,16 +29,15 @@ angular.module("admin.payments").factory 'AdminStripeElements', ($rootScope, Sta
|
||||
@stripe.createPaymentMethod({ type: 'card', card: @card }, @card, cardData).then (response) =>
|
||||
if(response.error)
|
||||
StatusMessage.display 'error', response.error.message
|
||||
console.error(JSON.stringify(response.error))
|
||||
else
|
||||
secrets.token = response.paymentMethod.id
|
||||
secrets.cc_type = @mapPaymentMethodsApiCardBrand(response.paymentMethod.card.brand)
|
||||
secrets.cc_type = response.paymentMethod.card.brand
|
||||
secrets.card = response.paymentMethod.card
|
||||
submit()
|
||||
|
||||
# Maps the brand returned by Stripe's tokenAPI to that required by activemerchant
|
||||
mapTokenApiCardBrand: (cardBrand) ->
|
||||
switch cardBrand
|
||||
# Maps the brand returned by Stripe to that required by activemerchant
|
||||
mapCC: (ccType) ->
|
||||
switch ccType
|
||||
when 'MasterCard' then return 'master'
|
||||
when 'Visa' then return 'visa'
|
||||
when 'American Express' then return 'american_express'
|
||||
@@ -47,14 +45,6 @@ angular.module("admin.payments").factory 'AdminStripeElements', ($rootScope, Sta
|
||||
when 'JCB' then return 'jcb'
|
||||
when 'Diners Club' then return 'diners_club'
|
||||
|
||||
# Maps the brand returned by Stripe's paymentMethodsAPI to that required by activemerchant
|
||||
mapPaymentMethodsApiCardBrand: (cardBrand) ->
|
||||
switch cardBrand
|
||||
when 'mastercard' then return 'master'
|
||||
when 'amex' then return 'american_express'
|
||||
when 'diners' then return 'diners_club'
|
||||
else return cardBrand # a few brands are equal, for example, visa
|
||||
|
||||
# It doesn't matter if any of these are nil, all are optional.
|
||||
makeCardData: (secrets) ->
|
||||
{'name': secrets.name,
|
||||
|
||||
@@ -2,6 +2,7 @@ angular.module("admin.resources").factory 'LineItemResource', ($resource) ->
|
||||
$resource('/admin/bulk_line_items/:id.json', {}, {
|
||||
'index':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
'update':
|
||||
method: 'PUT'
|
||||
transformRequest: (data, headersGetter) =>
|
||||
|
||||
@@ -1,27 +1,20 @@
|
||||
angular.module("admin.resources").factory 'LineItems', ($q, LineItemResource) ->
|
||||
new class LineItems
|
||||
all: []
|
||||
byID: {}
|
||||
pristineByID: {}
|
||||
pagination: {}
|
||||
|
||||
index: (params={}, callback=null) ->
|
||||
request = LineItemResource.index params, (data) =>
|
||||
LineItemResource.index params, (data) =>
|
||||
@load(data)
|
||||
(callback || angular.noop)(data)
|
||||
@all.$promise = request.$promise
|
||||
@all
|
||||
|
||||
resetData: ->
|
||||
@all.length = 0
|
||||
@byID = {}
|
||||
@pristineByID = {}
|
||||
|
||||
load: (data) ->
|
||||
angular.extend(@pagination, data.pagination)
|
||||
load: (lineItems) ->
|
||||
@resetData()
|
||||
for lineItem in data.line_items
|
||||
@all.push lineItem
|
||||
for lineItem in lineItems
|
||||
@byID[lineItem.id] = lineItem
|
||||
@pristineByID[lineItem.id] = angular.copy(lineItem)
|
||||
|
||||
@@ -32,9 +25,8 @@ angular.module("admin.resources").factory 'LineItems', ($q, LineItemResource) ->
|
||||
|
||||
save: (lineItem) ->
|
||||
deferred = $q.defer()
|
||||
lineItemResource = new LineItemResource(lineItem)
|
||||
lineItem.errors = {}
|
||||
lineItemResource.$update({id: lineItem.id})
|
||||
lineItem.$update({id: lineItem.id})
|
||||
.then( (data) =>
|
||||
@pristineByID[lineItem.id] = angular.copy(lineItem)
|
||||
deferred.resolve(data)
|
||||
@@ -62,10 +54,8 @@ angular.module("admin.resources").factory 'LineItems', ($q, LineItemResource) ->
|
||||
|
||||
delete: (lineItem, callback=null) ->
|
||||
deferred = $q.defer()
|
||||
lineItemResource = new LineItemResource(lineItem)
|
||||
lineItemResource.$delete({id: lineItem.id})
|
||||
lineItem.$delete({id: lineItem.id})
|
||||
.then( (data) =>
|
||||
@all.splice(@all.indexOf(lineItem),1)
|
||||
delete @byID[lineItem.id]
|
||||
delete @pristineByID[lineItem.id]
|
||||
(callback || angular.noop)(data)
|
||||
|
||||
@@ -43,11 +43,12 @@ angular.module("admin.variantOverrides").controller "AdminVariantOverridesCtrl",
|
||||
|
||||
$scope.fetchProducts = ->
|
||||
url = "/api/products/overridable?page=::page::;per_page=100"
|
||||
PagedFetcher.fetch url, $scope.addProducts
|
||||
PagedFetcher.fetch url, (data) => $scope.addProducts data.products
|
||||
|
||||
$scope.addProducts = (data) ->
|
||||
$scope.products = $scope.products.concat data.products
|
||||
VariantOverrides.ensureDataFor hubs, data.products
|
||||
|
||||
$scope.addProducts = (products) ->
|
||||
$scope.products = $scope.products.concat products
|
||||
VariantOverrides.ensureDataFor hubs, products
|
||||
|
||||
$scope.displayDirty = ->
|
||||
if DirtyVariantOverrides.count() > 0
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
#= require angular-animate
|
||||
#= require angular-resource
|
||||
#= require lodash.underscore.js
|
||||
# bluebird.js is a dependency of angular-google-maps.js 2.0.0
|
||||
#= require bluebird.js
|
||||
#= require angular-scroll.min.js
|
||||
#= require angular-google-maps.min.js
|
||||
#= require ../shared/mm-foundation-tpls-0.9.0-20180826174721.min.js
|
||||
|
||||
@@ -9,13 +9,8 @@ Darkswarm.controller "EnterprisesCtrl", ($scope, $rootScope, $timeout, $location
|
||||
$scope.show_closed = false
|
||||
$scope.filtersActive = false
|
||||
$scope.distanceMatchesShown = false
|
||||
$scope.closed_shops_loading = false
|
||||
$scope.closed_shops_loaded = false
|
||||
|
||||
$scope.$watch "query", (query)->
|
||||
$scope.resetSearch(query)
|
||||
|
||||
$scope.resetSearch = (query) ->
|
||||
Enterprises.flagMatching query
|
||||
Search.search query
|
||||
$rootScope.$broadcast 'enterprisesChanged'
|
||||
@@ -24,7 +19,6 @@ Darkswarm.controller "EnterprisesCtrl", ($scope, $rootScope, $timeout, $location
|
||||
$timeout ->
|
||||
Enterprises.calculateDistance query, $scope.firstNameMatch()
|
||||
$rootScope.$broadcast 'enterprisesChanged'
|
||||
$scope.closed_shops_loading = false
|
||||
|
||||
$timeout ->
|
||||
if $location.search()['show_closed']?
|
||||
@@ -79,12 +73,6 @@ Darkswarm.controller "EnterprisesCtrl", ($scope, $rootScope, $timeout, $location
|
||||
undefined
|
||||
|
||||
$scope.showClosedShops = ->
|
||||
unless $scope.closed_shops_loaded
|
||||
$scope.closed_shops_loading = true
|
||||
$scope.closed_shops_loaded = true
|
||||
Enterprises.loadClosedEnterprises().then ->
|
||||
$scope.resetSearch($scope.query)
|
||||
|
||||
$scope.show_closed = true
|
||||
$location.search('show_closed', '1')
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ Darkswarm.controller "HubNodeCtrl", ($scope, HashNavigation, CurrentHub, $http,
|
||||
$scope.shopfront_loading = true
|
||||
$scope.toggle_tab(event)
|
||||
|
||||
$http.get("/api/shops/" + $scope.hub.id)
|
||||
$http.get("/api/enterprises/" + $scope.hub.id + "/shopfront")
|
||||
.success (data) ->
|
||||
$scope.shopfront_loading = false
|
||||
$scope.hub = data
|
||||
|
||||
@@ -24,7 +24,7 @@ Darkswarm.controller "ProducerNodeCtrl", ($scope, HashNavigation, $anchorScroll,
|
||||
$scope.shopfront_loading = true
|
||||
$scope.toggle_tab(event)
|
||||
|
||||
$http.get("/api/shops/" + $scope.producer.id)
|
||||
$http.get("/api/enterprises/" + $scope.producer.id + "/shopfront")
|
||||
.success (data) ->
|
||||
$scope.shopfront_loading = false
|
||||
$scope.producer = data
|
||||
|
||||
@@ -7,7 +7,7 @@ window.Darkswarm = angular.module("Darkswarm", [
|
||||
'templates',
|
||||
'ngSanitize',
|
||||
'ngAnimate',
|
||||
'uiGmapgoogle-maps',
|
||||
'google-maps',
|
||||
'duScroll',
|
||||
'angularFileUpload',
|
||||
'angularSlideables'
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
Darkswarm.directive "darkerBackground", ->
|
||||
restrict: "A"
|
||||
link: (scope, elm, attr)->
|
||||
toggleClass = (value) ->
|
||||
elm.closest('.page-view').toggleClass("with-darker-background", value)
|
||||
|
||||
toggleClass(true)
|
||||
|
||||
# if an OrderCycle is selected, disable darker background
|
||||
scope.$watch 'order_cycle.order_cycle_id', (newvalue, oldvalue) ->
|
||||
toggleClass(false) if newvalue
|
||||
@@ -1,6 +1,6 @@
|
||||
Darkswarm.directive 'mapOsmTiles', ($timeout) ->
|
||||
restrict: 'E'
|
||||
require: '^uiGmapGoogleMap'
|
||||
require: '^googleMap'
|
||||
scope: {}
|
||||
link: (scope, elem, attrs, ctrl) ->
|
||||
$timeout =>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
Darkswarm.directive 'mapSearch', ($timeout, Search) ->
|
||||
# Install a basic search field in a map
|
||||
restrict: 'E'
|
||||
require: ['^uiGmapGoogleMap', 'ngModel']
|
||||
require: ['^googleMap', 'ngModel']
|
||||
replace: true
|
||||
template: '<input id="pac-input" ng-model="query" placeholder="' + t('location_placeholder') + '"></input>'
|
||||
scope: {}
|
||||
|
||||
@@ -5,9 +5,5 @@ Darkswarm.directive "shopVariant", ->
|
||||
scope:
|
||||
variant: '='
|
||||
controller: ($scope, Cart) ->
|
||||
$scope.$watchGroup [
|
||||
'variant.line_item.quantity',
|
||||
'variant.line_item.max_quantity'
|
||||
], (new_value, old_value) ->
|
||||
return if old_value[0] == null && new_value[0] == null
|
||||
$scope.$watchGroup ['variant.line_item.quantity', 'variant.line_item.max_quantity'], ->
|
||||
Cart.adjust($scope.variant.line_item)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, $modal, $rootScope, $resource, localStorageService, RailsFlashLoader) ->
|
||||
Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, $modal, $rootScope, $resource, localStorageService) ->
|
||||
# Handles syncing of current cart/order state to server
|
||||
new class Cart
|
||||
dirty: false
|
||||
@@ -50,7 +50,7 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, $modal, $roo
|
||||
@popQueue() if @update_enqueued
|
||||
|
||||
.error (response, status)=>
|
||||
RailsFlashLoader.loadFlash({error: t('js.cart.add_to_cart_failed')})
|
||||
@scheduleRetry(status)
|
||||
@update_running = false
|
||||
|
||||
compareAndNotifyStockLevels: (stockLevels) =>
|
||||
@@ -87,6 +87,13 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http, $modal, $roo
|
||||
max_quantity: li.max_quantity
|
||||
{variants: variants}
|
||||
|
||||
scheduleRetry: (status) =>
|
||||
console.log "Error updating cart: #{status}. Retrying in 3 seconds..."
|
||||
$timeout =>
|
||||
console.log "Retrying cart update"
|
||||
@orderChanged()
|
||||
, 3000
|
||||
|
||||
saved: =>
|
||||
@dirty = false
|
||||
$(window).unbind "beforeunload"
|
||||
|
||||
@@ -14,28 +14,15 @@ Darkswarm.factory 'Checkout', ($injector, CurrentOrder, ShippingMethods, StripeE
|
||||
|
||||
submit: =>
|
||||
Loading.message = t 'submitting_order'
|
||||
$http.put('/checkout.json', {order: @preprocess()})
|
||||
.then (response) =>
|
||||
Navigation.go response.data.path
|
||||
.catch (response) =>
|
||||
try
|
||||
@handle_checkout_error_response(response)
|
||||
catch error
|
||||
@loadFlash(error: t("checkout.failed")) # inform the user about the unexpected error
|
||||
throw error # generate a BugsnagJS alert
|
||||
|
||||
handle_checkout_error_response: (response) =>
|
||||
if response.data.path
|
||||
Navigation.go response.data.path
|
||||
else
|
||||
throw response unless response.data.flash
|
||||
|
||||
@errors = response.data.errors
|
||||
@loadFlash(response.data.flash)
|
||||
|
||||
loadFlash: (flash) =>
|
||||
Loading.clear()
|
||||
RailsFlashLoader.loadFlash(flash)
|
||||
$http.put('/checkout.json', {order: @preprocess()}).success (data, status)=>
|
||||
Navigation.go data.path
|
||||
.error (response, status)=>
|
||||
if response.path
|
||||
Navigation.go response.path
|
||||
else
|
||||
Loading.clear()
|
||||
@errors = response.errors
|
||||
RailsFlashLoader.loadFlash(response.flash)
|
||||
|
||||
# Rails wants our Spree::Address data to be provided with _attributes
|
||||
preprocess: ->
|
||||
|
||||
@@ -5,7 +5,7 @@ Darkswarm.factory "EnterpriseModal", ($modal, $rootScope, $http)->
|
||||
scope = $rootScope.$new(true) # Spawn an isolate to contain the enterprise
|
||||
scope.embedded_layout = window.location.search.indexOf("embedded_shopfront=true") != -1
|
||||
|
||||
$http.get("/api/shops/" + enterprise.id).success (data) ->
|
||||
$http.get("/api/enterprises/" + enterprise.id + "/shopfront").success (data) ->
|
||||
scope.enterprise = data
|
||||
$modal.open(templateUrl: "enterprise_modal.html", scope: scope)
|
||||
.error (data) ->
|
||||
|
||||
@@ -1,30 +1,27 @@
|
||||
Darkswarm.factory 'Enterprises', (enterprises, ShopsResource, CurrentHub, Taxons, Dereferencer, Matcher, Geo, $rootScope) ->
|
||||
Darkswarm.factory 'Enterprises', (enterprises, CurrentHub, Taxons, Dereferencer, Matcher, Geo, $rootScope) ->
|
||||
new class Enterprises
|
||||
enterprises: []
|
||||
enterprises_by_id: {}
|
||||
|
||||
constructor: ->
|
||||
# Populate Enterprises.enterprises from json in page.
|
||||
@initEnterprises(enterprises)
|
||||
@enterprises = enterprises
|
||||
|
||||
initEnterprises: (enterprises) ->
|
||||
# Map enterprises to id/object pairs for lookup.
|
||||
for enterprise in enterprises
|
||||
@enterprises.push enterprise
|
||||
@enterprises_by_id[enterprise.id] = enterprise
|
||||
|
||||
# Replace enterprise and taxons ids with actual objects.
|
||||
@dereferenceEnterprises(enterprises)
|
||||
@dereferenceEnterprises()
|
||||
|
||||
@producers = @enterprises.filter (enterprise)->
|
||||
enterprise.category in ["producer_hub", "producer_shop", "producer"]
|
||||
@hubs = @enterprises.filter (enterprise)->
|
||||
enterprise.category in ["hub", "hub_profile", "producer_hub", "producer_shop"]
|
||||
|
||||
dereferenceEnterprises: (enteprises) ->
|
||||
dereferenceEnterprises: ->
|
||||
if CurrentHub.hub?.id
|
||||
CurrentHub.hub = @enterprises_by_id[CurrentHub.hub.id]
|
||||
for enterprise in enterprises
|
||||
for enterprise in @enterprises
|
||||
@dereferenceEnterprise enterprise
|
||||
|
||||
dereferenceEnterprise: (enterprise) ->
|
||||
@@ -45,12 +42,6 @@ Darkswarm.factory 'Enterprises', (enterprises, ShopsResource, CurrentHub, Taxons
|
||||
for enterprise in new_enterprises
|
||||
@enterprises_by_id[enterprise.id] = enterprise
|
||||
|
||||
loadClosedEnterprises: ->
|
||||
request = ShopsResource.closed_shops {}, (data) =>
|
||||
@initEnterprises(data)
|
||||
|
||||
request.$promise
|
||||
|
||||
flagMatching: (query) ->
|
||||
for enterprise in @enterprises
|
||||
enterprise.matches_name_query = if query? && query.length > 0
|
||||
@@ -59,7 +50,7 @@ Darkswarm.factory 'Enterprises', (enterprises, ShopsResource, CurrentHub, Taxons
|
||||
false
|
||||
|
||||
calculateDistance: (query, firstMatching) ->
|
||||
if query?.length > 0 and Geo.OK
|
||||
if query?.length > 0
|
||||
if firstMatching?
|
||||
@setDistanceFrom firstMatching
|
||||
else
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Darkswarm.service "Geo", ->
|
||||
new class Geo
|
||||
OK: google?.maps?.GeocoderStatus?.OK
|
||||
OK: google.maps.GeocoderStatus.OK
|
||||
|
||||
# Usage:
|
||||
# Geo.geocode address, (results, status) ->
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
Darkswarm.factory 'OrderCycle', ($resource, orderCycleData) ->
|
||||
class OrderCycle
|
||||
@order_cycle = orderCycleData # Object or {}
|
||||
@order_cycle = orderCycleData # Object or {} due to RABL
|
||||
@push_order_cycle: (callback) ->
|
||||
new $resource("/shop/order_cycle").save {order_cycle_id: @order_cycle.order_cycle_id}, (order_data)->
|
||||
OrderCycle.order_cycle.orders_close_at = order_data.orders_close_at
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
Darkswarm.factory 'ShopsResource', ($resource) ->
|
||||
$resource('/api/shops/:id.json', {}, {
|
||||
'closed_shops':
|
||||
method: 'GET'
|
||||
isArray: true
|
||||
url: '/api/shops/closed_shops.json'
|
||||
})
|
||||
@@ -15,11 +15,9 @@ Darkswarm.factory 'StripeElements', ($rootScope, Loading, RailsFlashLoader) ->
|
||||
if(response.error)
|
||||
Loading.clear()
|
||||
RailsFlashLoader.loadFlash({error: t("error") + ": #{response.error.message}"})
|
||||
@triggerAngularDigest()
|
||||
console.error(JSON.stringify(response.error))
|
||||
else
|
||||
secrets.token = response.token.id
|
||||
secrets.cc_type = @mapTokenApiCardBrand(response.token.card.brand)
|
||||
secrets.cc_type = @mapCC(response.token.card.brand)
|
||||
secrets.card = response.token.card
|
||||
submit()
|
||||
|
||||
@@ -34,21 +32,15 @@ Darkswarm.factory 'StripeElements', ($rootScope, Loading, RailsFlashLoader) ->
|
||||
if(response.error)
|
||||
Loading.clear()
|
||||
RailsFlashLoader.loadFlash({error: t("error") + ": #{response.error.message}"})
|
||||
@triggerAngularDigest()
|
||||
console.error(JSON.stringify(response.error))
|
||||
else
|
||||
secrets.token = response.paymentMethod.id
|
||||
secrets.cc_type = @mapPaymentMethodsApiCardBrand(response.paymentMethod.card.brand)
|
||||
secrets.cc_type = response.paymentMethod.card.brand
|
||||
secrets.card = response.paymentMethod.card
|
||||
submit()
|
||||
|
||||
triggerAngularDigest: ->
|
||||
# $evalAsync is improved way of triggering a digest without calling $apply
|
||||
$rootScope.$evalAsync()
|
||||
|
||||
# Maps the brand returned by Stripe's tokenAPI to that required by activemerchant
|
||||
mapTokenApiCardBrand: (cardBrand) ->
|
||||
switch cardBrand
|
||||
# Maps the brand returned by Stripe to that required by activemerchant
|
||||
mapCC: (ccType) ->
|
||||
switch ccType
|
||||
when 'MasterCard' then return 'master'
|
||||
when 'Visa' then return 'visa'
|
||||
when 'American Express' then return 'american_express'
|
||||
@@ -56,14 +48,6 @@ Darkswarm.factory 'StripeElements', ($rootScope, Loading, RailsFlashLoader) ->
|
||||
when 'JCB' then return 'jcb'
|
||||
when 'Diners Club' then return 'diners_club'
|
||||
|
||||
# Maps the brand returned by Stripe's paymentMethodsAPI to that required by activemerchant
|
||||
mapPaymentMethodsApiCardBrand: (cardBrand) ->
|
||||
switch cardBrand
|
||||
when 'mastercard' then return 'master'
|
||||
when 'amex' then return 'american_express'
|
||||
when 'diners' then return 'diners_club'
|
||||
else return cardBrand # a few brands are equal, for example, visa
|
||||
|
||||
# It doesn't matter if any of these are nil, all are optional.
|
||||
makeCardData: (secrets) ->
|
||||
{'name': secrets.name,
|
||||
|
||||
@@ -8,4 +8,4 @@
|
||||
%hr
|
||||
%div.menu_item.text-center
|
||||
%input.fullwidth.orange{ type: "button", ng: { value: "saved() ? 'Saved': 'Saving'", show: "saved() || saving", disabled: "saved()" } }
|
||||
%input.fullwidth.red{ type: "button", :value => t('admin.column_save_as_default').html_safe, ng: { show: "!saved() && !saving", click: "saveColumnPreferences(action)"} }
|
||||
%input.fullwidth.red{ type: "button", value: 'Save As Default', ng: { show: "!saved() && !saving", click: "saveColumnPreferences(action)"} }
|
||||
|
||||
@@ -6,8 +6,6 @@
|
||||
min: 0,
|
||||
placeholder: "0",
|
||||
"ofn-disable-scroll" => true,
|
||||
"ng-debounce" => "500",
|
||||
onwheel: "this.blur()",
|
||||
"ng-model" => "variant.line_item.quantity",
|
||||
"ofn-on-hand" => "{{variant.on_demand && 9999 || variant.on_hand }}",
|
||||
"ng-disabled" => "!variant.on_demand && variant.on_hand == 0",
|
||||
|
||||
@@ -9,8 +9,6 @@
|
||||
"ng-model" => "variant.line_item.quantity",
|
||||
placeholder: "{{::'shop_variant_quantity_min' | t}}",
|
||||
"ofn-disable-scroll" => true,
|
||||
"ng-debounce" => "500",
|
||||
onwheel: "this.blur()",
|
||||
"ofn-on-hand" => "{{variant.on_demand && 9999 || variant.on_hand }}",
|
||||
name: "variants[{{::variant.id}}]", id: "variants_{{::variant.id}}"}
|
||||
%span.bulk-input
|
||||
@@ -21,8 +19,6 @@
|
||||
"ng-model" => "variant.line_item.max_quantity",
|
||||
placeholder: "{{::'shop_variant_quantity_max' | t}}",
|
||||
"ofn-disable-scroll" => true,
|
||||
"ng-debounce" => "500",
|
||||
onwheel: "this.blur()",
|
||||
min: "{{variant.line_item.quantity}}",
|
||||
name: "variant_attributes[{{::variant.id}}][max_quantity]",
|
||||
id: "variants_{{::variant.id}}_max"}
|
||||
|
||||
@@ -9,9 +9,6 @@
|
||||
|
||||
input#search {
|
||||
@include medium-input(rgba(0, 0, 0, 0.3), #777, $clr-brick);
|
||||
|
||||
// avoid zoom on iphone, see issue #4535
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
// ordering
|
||||
|
||||
@@ -49,7 +49,7 @@ ordercycle {
|
||||
border-radius: 0.25em 0 0 0.25em;
|
||||
float: left;
|
||||
font-size: 1em;
|
||||
line-height: 1.3em;
|
||||
line-height: 1.5em;
|
||||
padding: 0.5em 0.75em;
|
||||
height: 2.35em;
|
||||
|
||||
@@ -60,15 +60,6 @@ ordercycle {
|
||||
}
|
||||
|
||||
select {
|
||||
background-image: url('/assets/white-caret.svg');
|
||||
}
|
||||
|
||||
p {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
select,
|
||||
p {
|
||||
width: inherit;
|
||||
display: inline-block;
|
||||
color: $white;
|
||||
@@ -76,9 +67,10 @@ ordercycle {
|
||||
border: 0;
|
||||
margin-bottom: 0;
|
||||
font-size: 1em;
|
||||
line-height: 1.3em;
|
||||
line-height: 1.5em;
|
||||
padding: 0.5em 1.25em 0.5em 0.75em;
|
||||
height: 2.35em;
|
||||
background-image: url('/assets/white-caret.svg');
|
||||
background-size: 30px auto;
|
||||
border-radius: 0 0.25em 0.25em 0;
|
||||
min-width: 13em;
|
||||
@@ -88,10 +80,6 @@ ordercycle {
|
||||
}
|
||||
}
|
||||
|
||||
option {
|
||||
color: $grey-700;
|
||||
}
|
||||
|
||||
@media all and (max-width: 1024px) {
|
||||
float: none;
|
||||
margin-right: 1em;
|
||||
|
||||
@@ -38,15 +38,14 @@ $med-drk-grey: #444;
|
||||
$dark-grey: #333;
|
||||
$light-grey: #ddd;
|
||||
$light-grey-transparency: rgba(0, 0, 0, .1);
|
||||
$very-light-grey-transparency: rgba(0, 0, 0, .05);
|
||||
$black: #000;
|
||||
$white: #fff;
|
||||
|
||||
$grey-050: #f7f7f7;
|
||||
|
||||
$grey-400: #bbb;
|
||||
$grey-500: #999;
|
||||
$grey-600: #777;
|
||||
$grey-650: #666;
|
||||
$grey-700: #555;
|
||||
$grey-800: #333;
|
||||
|
||||
@@ -55,7 +54,6 @@ $teal-400: #4cb5c5;
|
||||
$teal-500: #0096ad;
|
||||
|
||||
$orange-400: #ff9466;
|
||||
$orange-450: #f4704c;
|
||||
$orange-500: #f27052;
|
||||
$orange-600: #d7583a;
|
||||
|
||||
|
||||
@@ -109,4 +109,9 @@ checkout {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.error {
|
||||
color: #c82020;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,10 +14,5 @@
|
||||
|
||||
.more-controls {
|
||||
text-align: center;
|
||||
|
||||
.spinner {
|
||||
height: 2.25em;
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,16 +114,7 @@
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.select-oc-message {
|
||||
margin-top: 1rem;
|
||||
|
||||
.highlighted {
|
||||
color: $red-700;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.open-shop-message {
|
||||
.shopfront-message {
|
||||
a {
|
||||
color: #0096ad;
|
||||
|
||||
@@ -134,44 +125,21 @@
|
||||
}
|
||||
}
|
||||
|
||||
.closed-shop-header {
|
||||
background-color: $grey-650;
|
||||
color: $white;
|
||||
|
||||
h4 {
|
||||
color: $white;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 1rem 0 0.4rem;
|
||||
}
|
||||
|
||||
.message {
|
||||
display: inline-block;
|
||||
}
|
||||
.shopfront_closed_message, .shopfront_hidden_message {
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.warning-sign {
|
||||
margin: 0 10px 0 5px;
|
||||
display: inline-block;
|
||||
.shopfront_closed_message {
|
||||
border: 2px solid #eb4c46;
|
||||
}
|
||||
|
||||
strong {
|
||||
color: $grey-650;
|
||||
display: block;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
width: 23px;
|
||||
}
|
||||
.shopfront_closed_message {
|
||||
margin: 2em 0em;
|
||||
}
|
||||
|
||||
.rectangle {
|
||||
background-color: $white;
|
||||
border-radius: 4px;
|
||||
color: $grey-650;
|
||||
height: 23px;
|
||||
position: absolute;
|
||||
top: 27px;
|
||||
transform: rotate(-315deg);
|
||||
width: 23px;
|
||||
}
|
||||
.shopfront_hidden_message {
|
||||
border: 2px solid #db4;
|
||||
margin: 2em 0em;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,9 +76,9 @@
|
||||
// content revealed in accordion
|
||||
|
||||
.page-view {
|
||||
margin-bottom: 5em;
|
||||
background: none;
|
||||
border: none;
|
||||
padding-bottom: 5em;
|
||||
|
||||
.content {
|
||||
padding: 1.25em 0;
|
||||
@@ -121,13 +121,5 @@
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
&.with-darker-background {
|
||||
background-color: $very-light-grey-transparency;
|
||||
|
||||
a {
|
||||
color: $teal-500;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,14 +115,3 @@
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
.links {
|
||||
.button {
|
||||
padding: 1.125rem 0 1.1875rem;
|
||||
width: 210px;
|
||||
|
||||
@media all and (max-width: 480px) {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,13 +64,13 @@
|
||||
|
||||
.button.primary, button.primary {
|
||||
font-family: $body-font;
|
||||
background: $orange-450;
|
||||
background: $clr-brick;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.button.primary:hover, .button.primary:active, .button.primary:focus, button.primary:hover, button.primary:active, button.primary:focus {
|
||||
background: $orange-400;
|
||||
text-shadow: 0 1px 0 $orange-450;
|
||||
background: $clr-brick-bright;
|
||||
text-shadow: 0 1px 0 $clr-brick;
|
||||
}
|
||||
|
||||
button.success, .button.success {
|
||||
|
||||
@@ -138,10 +138,6 @@ a {
|
||||
&.ms {
|
||||
background-color: #000 !important;
|
||||
}
|
||||
|
||||
&.ig {
|
||||
background-color: #fb3958 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar .soc-btn {
|
||||
|
||||
@@ -4,17 +4,18 @@ module Admin
|
||||
#
|
||||
def index
|
||||
order_params = params[:q].andand.delete :order
|
||||
orders = order_permissions.editable_orders.ransack(order_params).result
|
||||
|
||||
@line_items = order_permissions.
|
||||
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')
|
||||
|
||||
@line_items = @line_items.page(page).per(params[:per_page]) if using_pagination?
|
||||
|
||||
render json: { line_items: serialized_line_items, pagination: pagination_data }
|
||||
render_as_json line_items
|
||||
end
|
||||
|
||||
# PUT /admin/bulk_line_items/:id.json
|
||||
@@ -64,12 +65,6 @@ module Admin
|
||||
Api::Admin::LineItemSerializer
|
||||
end
|
||||
|
||||
def serialized_line_items
|
||||
ActiveModel::ArraySerializer.new(
|
||||
@line_items, each_serializer: serializer(nil)
|
||||
)
|
||||
end
|
||||
|
||||
def authorize_update!
|
||||
authorize! :update, order
|
||||
authorize! :read, order
|
||||
@@ -78,28 +73,5 @@ module Admin
|
||||
def order
|
||||
@line_item.order
|
||||
end
|
||||
|
||||
def order_permissions
|
||||
::Permissions::Order.new(spree_current_user)
|
||||
end
|
||||
|
||||
def using_pagination?
|
||||
params[:per_page]
|
||||
end
|
||||
|
||||
def pagination_data
|
||||
return unless using_pagination?
|
||||
|
||||
{
|
||||
results: @line_items.total_count,
|
||||
pages: @line_items.num_pages,
|
||||
page: page.to_i,
|
||||
per_page: params[:per_page].to_i
|
||||
}
|
||||
end
|
||||
|
||||
def page
|
||||
params[:page] || 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,9 +17,8 @@ module Admin
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.json do
|
||||
render_as_json @collection,
|
||||
tag_rule_mapping: tag_rule_mapping,
|
||||
customer_tags: customer_tags_by_id
|
||||
tag_rule_mapping = TagRule.mapping_for(Enterprise.where(id: params[:enterprise_id]))
|
||||
render_as_json @collection, tag_rule_mapping: tag_rule_mapping
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -65,13 +64,8 @@ module Admin
|
||||
def collection
|
||||
return Customer.where("1=0") unless json_request? && params[:enterprise_id].present?
|
||||
|
||||
Customer.of(managed_enterprise_id).
|
||||
includes(:bill_address, :ship_address, user: :credit_cards)
|
||||
end
|
||||
|
||||
def managed_enterprise_id
|
||||
@managed_enterprise_id ||= Enterprise.managed_by(spree_current_user).
|
||||
select('enterprises.id').find_by_id(params[:enterprise_id])
|
||||
enterprise = Enterprise.managed_by(spree_current_user).find_by_id(params[:enterprise_id])
|
||||
Customer.of(enterprise)
|
||||
end
|
||||
|
||||
def load_managed_shops
|
||||
@@ -86,28 +80,5 @@ module Admin
|
||||
def ams_prefix_whitelist
|
||||
[:subscription]
|
||||
end
|
||||
|
||||
def tag_rule_mapping
|
||||
TagRule.mapping_for(Enterprise.where(id: managed_enterprise_id))
|
||||
end
|
||||
|
||||
# Fetches tags for all customers of the enterprise and returns a hash indexed by customer_id
|
||||
def customer_tags_by_id
|
||||
customer_tags = ::ActsAsTaggableOn::Tag.
|
||||
joins(:taggings).
|
||||
includes(:taggings).
|
||||
where(taggings:
|
||||
{ taggable_type: 'Customer',
|
||||
taggable_id: Customer.of(managed_enterprise_id),
|
||||
context: 'tags' })
|
||||
|
||||
customer_tags.each_with_object({}) do |tag, indexed_hash|
|
||||
tag.taggings.each do |tagging|
|
||||
customer_id = tagging.taggable_id
|
||||
indexed_hash[customer_id] ||= []
|
||||
indexed_hash[customer_id] << tag.name
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,13 +1,9 @@
|
||||
module Admin
|
||||
class EnterpriseRelationshipsController < ResourceController
|
||||
def index
|
||||
@my_enterprises = Enterprise.
|
||||
includes(:shipping_methods, :payment_methods).
|
||||
managed_by(spree_current_user).by_name
|
||||
@all_enterprises = Enterprise.includes(:shipping_methods, :payment_methods).by_name
|
||||
@enterprise_relationships = EnterpriseRelationship.
|
||||
includes(:parent, :child).
|
||||
by_name.involving_enterprises @my_enterprises
|
||||
@my_enterprises = Enterprise.managed_by(spree_current_user).by_name
|
||||
@all_enterprises = Enterprise.by_name
|
||||
@enterprise_relationships = EnterpriseRelationship.by_name.involving_enterprises @my_enterprises
|
||||
end
|
||||
|
||||
def create
|
||||
|
||||
@@ -16,7 +16,7 @@ module Admin
|
||||
render_as_json @collection,
|
||||
ams_prefix: params[:ams_prefix],
|
||||
current_user: spree_current_user,
|
||||
subscriptions_count: OrderManagement::Subscriptions::Count.new(@collection)
|
||||
subscriptions_count: SubscriptionsCount.new(@collection)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -74,7 +74,7 @@ module Admin
|
||||
render_as_json @order_cycles,
|
||||
ams_prefix: 'index',
|
||||
current_user: spree_current_user,
|
||||
subscriptions_count: OrderManagement::Subscriptions::Count.new(@collection)
|
||||
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
|
||||
|
||||
@@ -9,19 +9,25 @@ module Admin
|
||||
|
||||
def cancel
|
||||
if @proxy_order.cancel
|
||||
render_as_json @proxy_order
|
||||
respond_with(@proxy_order) do |format|
|
||||
format.json { render_as_json @proxy_order }
|
||||
end
|
||||
else
|
||||
render json: { errors: [t('admin.proxy_orders.cancel.could_not_cancel_the_order')] },
|
||||
status: :unprocessable_entity
|
||||
respond_with(@proxy_order) do |format|
|
||||
format.json { render json: { errors: [t('admin.proxy_orders.cancel.could_not_cancel_the_order')] }, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def resume
|
||||
if @proxy_order.resume
|
||||
render_as_json @proxy_order
|
||||
respond_with(@proxy_order) do |format|
|
||||
format.json { render_as_json @proxy_order }
|
||||
end
|
||||
else
|
||||
render json: { errors: [t('admin.proxy_orders.resume.could_not_resume_the_order')] },
|
||||
status: :unprocessable_entity
|
||||
respond_with(@proxy_order) do |format|
|
||||
format.json { render json: { errors: [t('admin.proxy_orders.resume.could_not_resume_the_order')] }, status: :unprocessable_entity }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
require 'open_food_network/permissions'
|
||||
require 'order_management/subscriptions/proxy_order_syncer'
|
||||
require 'open_food_network/proxy_order_syncer'
|
||||
|
||||
module Admin
|
||||
class SchedulesController < ResourceController
|
||||
@@ -81,7 +81,7 @@ module Admin
|
||||
return unless removed_ids.any? || new_ids.any?
|
||||
|
||||
subscriptions = Subscription.where(schedule_id: @schedule)
|
||||
syncer = OrderManagement::Subscriptions::ProxyOrderSyncer.new(subscriptions)
|
||||
syncer = OpenFoodNetwork::ProxyOrderSyncer.new(subscriptions)
|
||||
syncer.sync!
|
||||
end
|
||||
end
|
||||
|
||||
@@ -56,7 +56,7 @@ module Admin
|
||||
end
|
||||
|
||||
def variant_if_eligible(variant_id)
|
||||
OrderManagement::Subscriptions::VariantsList.eligible_variants(@shop).find_by_id(variant_id)
|
||||
SubscriptionVariantsService.eligible_variants(@shop).find_by_id(variant_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
require 'open_food_network/permissions'
|
||||
require 'open_food_network/proxy_order_syncer'
|
||||
|
||||
module Admin
|
||||
class SubscriptionsController < ResourceController
|
||||
@@ -64,7 +65,7 @@ module Admin
|
||||
private
|
||||
|
||||
def save_form_and_render(render_issues = true)
|
||||
form = OrderManagement::Subscriptions::Form.new(@subscription, params[:subscription])
|
||||
form = SubscriptionForm.new(@subscription, params[:subscription])
|
||||
unless form.save
|
||||
render json: { errors: form.json_errors }, status: :unprocessable_entity
|
||||
return
|
||||
|
||||
@@ -73,10 +73,8 @@ module Admin
|
||||
end
|
||||
|
||||
def collection
|
||||
@variant_overrides = VariantOverride.
|
||||
includes(variant: :product).
|
||||
for_hubs(params[:hub_id] || @hubs).
|
||||
select { |vo| vo.variant.present? }
|
||||
@variant_overrides = VariantOverride.includes(:variant).for_hubs(params[:hub_id] || @hubs)
|
||||
@variant_overrides.select { |vo| vo.variant.present? }
|
||||
end
|
||||
|
||||
def collection_actions
|
||||
|
||||
@@ -5,6 +5,7 @@ module Api
|
||||
before_filter :override_sells, only: [:create, :update]
|
||||
before_filter :override_visible, only: [:create, :update]
|
||||
respond_to :json
|
||||
skip_authorization_check only: [:shopfront]
|
||||
|
||||
def create
|
||||
authorize! :create, Enterprise
|
||||
@@ -41,6 +42,12 @@ module Api
|
||||
end
|
||||
end
|
||||
|
||||
def shopfront
|
||||
enterprise = Enterprise.find_by_id(params[:id])
|
||||
|
||||
render text: Api::EnterpriseShopfrontSerializer.new(enterprise).to_json, status: :ok
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def override_owner
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
module Api
|
||||
class OrderCyclesController < Api::BaseController
|
||||
include EnterprisesHelper
|
||||
include ApiActionCaching
|
||||
respond_to :json
|
||||
|
||||
skip_authorization_check
|
||||
skip_before_filter :authenticate_user, :ensure_api_key, only: [:taxons, :properties]
|
||||
|
||||
caches_action :taxons, :properties,
|
||||
expires_in: CacheService::FILTERS_EXPIRY,
|
||||
cache_path: proc { |controller| controller.request.url }
|
||||
|
||||
def products
|
||||
return render_no_products unless order_cycle.open?
|
||||
|
||||
products = ProductsRenderer.new(
|
||||
distributor,
|
||||
order_cycle,
|
||||
@@ -22,7 +15,7 @@ module Api
|
||||
|
||||
render json: products
|
||||
rescue ProductsRenderer::NoProducts
|
||||
render_no_products
|
||||
render status: :not_found, json: ''
|
||||
end
|
||||
|
||||
def taxons
|
||||
@@ -42,10 +35,6 @@ module Api
|
||||
|
||||
private
|
||||
|
||||
def render_no_products
|
||||
render status: :not_found, json: ''
|
||||
end
|
||||
|
||||
def product_properties
|
||||
Spree::Property.
|
||||
joins(:products).
|
||||
@@ -81,11 +70,11 @@ module Api
|
||||
end
|
||||
|
||||
def distributor
|
||||
@distributor ||= Enterprise.find_by_id(params[:distributor])
|
||||
Enterprise.find_by_id(params[:distributor])
|
||||
end
|
||||
|
||||
def order_cycle
|
||||
@order_cycle ||= OrderCycle.find_by_id(params[:id])
|
||||
OrderCycle.find_by_id(params[:id])
|
||||
end
|
||||
|
||||
def customer
|
||||
|
||||
@@ -69,12 +69,12 @@ module Api
|
||||
end
|
||||
|
||||
def overridable
|
||||
producer_ids = OpenFoodNetwork::Permissions.new(current_api_user).
|
||||
variant_override_producers.by_name.select('enterprises.id')
|
||||
producers = OpenFoodNetwork::Permissions.new(current_api_user).
|
||||
variant_override_producers.by_name
|
||||
|
||||
@products = paged_products_for_producers producer_ids
|
||||
@products = paged_products_for_producers producers
|
||||
|
||||
render_paged_products @products, ::Api::Admin::ProductSimpleSerializer
|
||||
render_paged_products @products
|
||||
end
|
||||
|
||||
# POST /api/products/:product_id/clone
|
||||
@@ -118,20 +118,19 @@ module Api
|
||||
]
|
||||
end
|
||||
|
||||
def paged_products_for_producers(producer_ids)
|
||||
def paged_products_for_producers(producers)
|
||||
Spree::Product.scoped.
|
||||
merge(product_scope).
|
||||
includes(variants: [:product, :default_price, :stock_items]).
|
||||
where(supplier_id: producer_ids).
|
||||
where(supplier_id: producers).
|
||||
by_producer.by_name.
|
||||
ransack(params[:q]).result.
|
||||
page(params[:page]).per(params[:per_page])
|
||||
end
|
||||
|
||||
def render_paged_products(products, product_serializer = ::Api::Admin::ProductSerializer)
|
||||
def render_paged_products(products)
|
||||
serializer = ActiveModel::ArraySerializer.new(
|
||||
products,
|
||||
each_serializer: product_serializer
|
||||
each_serializer: ::Api::Admin::ProductSerializer
|
||||
)
|
||||
|
||||
render text: {
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Api
|
||||
class ShopsController < BaseController
|
||||
respond_to :json
|
||||
skip_authorization_check only: [:show, :closed_shops]
|
||||
|
||||
def show
|
||||
enterprise = Enterprise.find_by_id(params[:id])
|
||||
|
||||
render text: Api::EnterpriseShopfrontSerializer.new(enterprise).to_json, status: :ok
|
||||
end
|
||||
|
||||
def closed_shops
|
||||
@active_distributor_ids = []
|
||||
@earliest_closing_times = []
|
||||
|
||||
serialized_closed_shops = ActiveModel::ArraySerializer.new(
|
||||
ShopsListService.new.closed_shops,
|
||||
each_serializer: Api::EnterpriseSerializer,
|
||||
data: OpenFoodNetwork::EnterpriseInjectionData.new
|
||||
)
|
||||
|
||||
render json: serialized_closed_shops
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -14,6 +14,10 @@ class BaseController < ApplicationController
|
||||
|
||||
helper 'spree/base'
|
||||
|
||||
# Spree::Core::ControllerHelpers declares helper_method get_taxonomies, so we need to
|
||||
# include Spree::ProductsHelper so that method is available on the controller
|
||||
include Spree::ProductsHelper
|
||||
|
||||
before_filter :set_locale
|
||||
before_filter :check_order_cycle_expiry
|
||||
|
||||
@@ -25,19 +29,17 @@ class BaseController < ApplicationController
|
||||
return
|
||||
end
|
||||
|
||||
@order_cycles = Shop::OrderCyclesList.new(@distributor, current_customer).call
|
||||
@order_cycles = OrderCycle.with_distributor(@distributor).active
|
||||
.order(@distributor.preferred_shopfront_order_cycle_order)
|
||||
|
||||
set_order_cycle
|
||||
end
|
||||
applicator = OpenFoodNetwork::TagRuleApplicator.new(@distributor,
|
||||
"FilterOrderCycles",
|
||||
current_customer.andand.tag_list)
|
||||
applicator.filter!(@order_cycles)
|
||||
|
||||
# Default to the only order cycle if there's only one
|
||||
#
|
||||
# Here we need to use @order_cycles.size not @order_cycles.count
|
||||
# because OrderCyclesList returns a modified ActiveRecord::Relation
|
||||
# and these modifications are not seen if it is reloaded with count
|
||||
def set_order_cycle
|
||||
return if @order_cycles.size != 1
|
||||
|
||||
current_order(true).set_order_cycle! @order_cycles.first
|
||||
# And default to the only order cycle if there's only the one
|
||||
if @order_cycles.count == 1
|
||||
current_order(true).set_order_cycle! @order_cycles.first
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,24 +4,24 @@ class CartController < BaseController
|
||||
before_filter :check_authorization
|
||||
|
||||
def populate
|
||||
order = current_order(true)
|
||||
|
||||
# Without intervention, the Spree::Adjustment#update_adjustable callback is called many times
|
||||
# during cart population, for both taxation and enterprise fees. This operation triggers a
|
||||
# costly Spree::Order#update!, which only needs to be run once. We avoid this by disabling
|
||||
# callbacks on Spree::Adjustment and then manually invoke Spree::Order#update! on success.
|
||||
Spree::Adjustment.without_callbacks do
|
||||
cart_service = CartService.new(order)
|
||||
cart_service = CartService.new(current_order(true))
|
||||
|
||||
if cart_service.populate(params.slice(:products, :variants, :quantity), true)
|
||||
order.update_distribution_charge!
|
||||
order.cap_quantity_at_stock!
|
||||
order.update!
|
||||
fire_event('spree.cart.add')
|
||||
fire_event('spree.order.contents_changed')
|
||||
|
||||
current_order.cap_quantity_at_stock!
|
||||
current_order.update!
|
||||
|
||||
variant_ids = variant_ids_in(cart_service.variants_h)
|
||||
|
||||
render json: { error: false,
|
||||
stock_levels: VariantsStockLevels.new.call(order, variant_ids) },
|
||||
stock_levels: VariantsStockLevels.new.call(current_order, variant_ids) },
|
||||
status: :ok
|
||||
else
|
||||
render json: { error: true }, status: :precondition_failed
|
||||
|
||||
@@ -53,8 +53,9 @@ class CheckoutController < Spree::StoreController
|
||||
rescue Spree::Core::GatewayError => e
|
||||
rescue_from_spree_gateway_error(e)
|
||||
rescue StandardError => e
|
||||
Bugsnag.notify(e)
|
||||
flash[:error] = I18n.t("checkout.failed")
|
||||
update_failed(e)
|
||||
update_failed
|
||||
end
|
||||
|
||||
# Clears the cached order. Required for #current_order to return a new order
|
||||
@@ -133,6 +134,13 @@ class CheckoutController < Spree::StoreController
|
||||
@order.ship_address = finder.ship_address
|
||||
end
|
||||
|
||||
def before_delivery
|
||||
return if params[:order].present?
|
||||
|
||||
packages = @order.shipments.map(&:to_package)
|
||||
@differentiator = Spree::Stock::Differentiator.new(@order, packages)
|
||||
end
|
||||
|
||||
def before_payment
|
||||
current_order.payments.destroy_all if request.put?
|
||||
end
|
||||
@@ -146,12 +154,10 @@ class CheckoutController < Spree::StoreController
|
||||
end
|
||||
|
||||
def valid_payment_intent_provided?
|
||||
return false unless params["payment_intent"]&.starts_with?("pi_")
|
||||
|
||||
last_payment = OrderPaymentFinder.new(@order).last_payment
|
||||
@order.state == "payment" &&
|
||||
last_payment&.state == "pending" &&
|
||||
last_payment&.response_code == params["payment_intent"]
|
||||
params["payment_intent"]&.starts_with?("pi_") &&
|
||||
@order.state == "payment" &&
|
||||
@order.payments.last.state == "pending" &&
|
||||
@order.payments.last.response_code == params["payment_intent"]
|
||||
end
|
||||
|
||||
def handle_redirect_from_stripe
|
||||
@@ -159,7 +165,7 @@ class CheckoutController < Spree::StoreController
|
||||
checkout_succeeded
|
||||
redirect_to(order_path(@order)) && return
|
||||
else
|
||||
flash[:error] = order_error
|
||||
flash[:error] = order_workflow_error
|
||||
checkout_failed
|
||||
end
|
||||
end
|
||||
@@ -174,6 +180,7 @@ class CheckoutController < Spree::StoreController
|
||||
|
||||
next if advance_order_state(@order)
|
||||
|
||||
flash[:error] = order_workflow_error
|
||||
return update_failed
|
||||
end
|
||||
|
||||
@@ -198,7 +205,7 @@ class CheckoutController < Spree::StoreController
|
||||
false
|
||||
end
|
||||
|
||||
def order_error
|
||||
def order_workflow_error
|
||||
if @order.errors.present?
|
||||
@order.errors.full_messages.to_sentence
|
||||
else
|
||||
@@ -211,7 +218,7 @@ class CheckoutController < Spree::StoreController
|
||||
checkout_succeeded
|
||||
update_succeeded_response
|
||||
else
|
||||
update_failed(RuntimeError.new("Order not complete after the checkout workflow"))
|
||||
update_failed
|
||||
end
|
||||
end
|
||||
|
||||
@@ -237,10 +244,7 @@ class CheckoutController < Spree::StoreController
|
||||
end
|
||||
end
|
||||
|
||||
def update_failed(error = RuntimeError.new(order_error))
|
||||
Bugsnag.notify(error)
|
||||
|
||||
flash[:error] = order_error if flash.empty?
|
||||
def update_failed
|
||||
checkout_failed
|
||||
update_failed_response
|
||||
end
|
||||
|
||||
@@ -96,8 +96,8 @@ class EnterprisesController < BaseController
|
||||
end
|
||||
|
||||
def reset_order_cycle(order, distributor)
|
||||
order_cycles = Shop::OrderCyclesList.new(distributor, current_customer).call
|
||||
order.order_cycle = order_cycles.first if order_cycles.size == 1
|
||||
order_cycle_options = OrderCycle.active.with_distributor(distributor)
|
||||
order.order_cycle = order_cycle_options.first if order_cycle_options.count == 1
|
||||
end
|
||||
|
||||
def shop_order_cycles
|
||||
|
||||
@@ -5,23 +5,12 @@ class HomeController < BaseController
|
||||
|
||||
def index
|
||||
if ContentConfig.home_show_stats
|
||||
@num_distributors = cached_count('distributors', Enterprise.is_distributor.activated.visible)
|
||||
@num_producers = cached_count('producers', Enterprise.is_primary_producer.activated.visible)
|
||||
@num_orders = cached_count('orders', Spree::Order.complete)
|
||||
@num_users = cached_count(
|
||||
'users', Spree::Order.complete.select('DISTINCT spree_orders.user_id')
|
||||
)
|
||||
@num_distributors = Enterprise.is_distributor.activated.visible.count
|
||||
@num_producers = Enterprise.is_primary_producer.activated.visible.count
|
||||
@num_users = Spree::Order.complete.count('DISTINCT user_id')
|
||||
@num_orders = Spree::Order.complete.count
|
||||
end
|
||||
end
|
||||
|
||||
def sell; end
|
||||
|
||||
private
|
||||
|
||||
# Cache the value of the query count
|
||||
def cached_count(statistic, query)
|
||||
CacheService.home_stats(statistic) do
|
||||
query.count
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,6 +4,13 @@ class ShopsController < BaseController
|
||||
before_filter :enable_embedded_shopfront
|
||||
|
||||
def index
|
||||
@enterprises = ShopsListService.new.open_shops
|
||||
@enterprises = Enterprise
|
||||
.activated
|
||||
.visible
|
||||
.is_distributor
|
||||
.includes(address: [:state, :country])
|
||||
.includes(:properties)
|
||||
.includes(supplied_products: :properties)
|
||||
.all
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,6 +4,10 @@ module Spree
|
||||
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
|
||||
|
||||
|
||||
@@ -29,8 +29,6 @@ module Spree
|
||||
return
|
||||
end
|
||||
|
||||
authorize_stripe_sca_payment
|
||||
|
||||
if @order.completed?
|
||||
@payment.process!
|
||||
flash[:success] = flash_message_for(@payment, :successfully_created)
|
||||
@@ -95,7 +93,7 @@ module Spree
|
||||
available(:back_end).
|
||||
select{ |pm| pm.has_distributor? @order.distributor }
|
||||
|
||||
@payment_method = if @payment&.payment_method
|
||||
@payment_method = if @payment && @payment.payment_method
|
||||
@payment.payment_method
|
||||
else
|
||||
@payment_methods.first
|
||||
@@ -126,13 +124,6 @@ module Spree
|
||||
def load_payment
|
||||
@payment = Payment.find(params[:id])
|
||||
end
|
||||
|
||||
def authorize_stripe_sca_payment
|
||||
return unless @payment.payment_method.class == Spree::Gateway::StripeSCA
|
||||
|
||||
@payment.authorize!
|
||||
raise Spree::Core::GatewayError, I18n.t('authorization_failure') unless @payment.pending?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
module Spree
|
||||
module Admin
|
||||
module Reports
|
||||
class EnterpriseFeeSummariesController < BaseController
|
||||
before_filter :load_report_parameters
|
||||
before_filter :load_permissions
|
||||
|
||||
def new; end
|
||||
|
||||
def create
|
||||
return respond_to_invalid_parameters unless @report_parameters.valid?
|
||||
|
||||
@report_parameters.authorize!(@permissions)
|
||||
|
||||
@report = report_klass::ReportService.new(@permissions, @report_parameters)
|
||||
renderer.render(self)
|
||||
rescue ::Reports::Authorizer::ParameterNotAllowedError => e
|
||||
flash[:error] = e.message
|
||||
render_report_form
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def respond_to_invalid_parameters
|
||||
flash[:error] = I18n.t("invalid_filter_parameters", scope: i18n_scope)
|
||||
render_report_form
|
||||
end
|
||||
|
||||
def i18n_scope
|
||||
"order_management.reports.enterprise_fee_summary"
|
||||
end
|
||||
|
||||
def render_report_form
|
||||
render action: :new
|
||||
end
|
||||
|
||||
def report_klass
|
||||
OrderManagement::Reports::EnterpriseFeeSummary
|
||||
end
|
||||
|
||||
def load_report_parameters
|
||||
@report_parameters = report_klass::Parameters.new(params[:report] || {})
|
||||
end
|
||||
|
||||
def load_permissions
|
||||
@permissions = report_klass::Permissions.new(spree_current_user)
|
||||
end
|
||||
|
||||
def report_renderer_klass
|
||||
case params[:report_format]
|
||||
when "csv"
|
||||
report_klass::Renderers::CsvRenderer
|
||||
when nil, "", "html"
|
||||
report_klass::Renderers::HtmlRenderer
|
||||
else
|
||||
raise Reports::UnsupportedReportFormatException
|
||||
end
|
||||
end
|
||||
|
||||
def renderer
|
||||
@renderer ||= report_renderer_klass.new(@report)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -298,20 +298,11 @@ module Spree
|
||||
end
|
||||
|
||||
def url_for_report(report)
|
||||
if report_in_order_management_engine?(report)
|
||||
main_app.public_send("new_order_management_reports_#{report}_url".to_sym)
|
||||
else
|
||||
public_send("#{report}_admin_reports_url".to_sym)
|
||||
end
|
||||
public_send("#{report}_admin_reports_url".to_sym)
|
||||
rescue NoMethodError
|
||||
url_for([:new, :admin, :reports, report.to_s.singularize])
|
||||
end
|
||||
|
||||
# List of reports that have been moved to the Order Management engine
|
||||
def report_in_order_management_engine?(report)
|
||||
report == :enterprise_fee_summary
|
||||
end
|
||||
|
||||
def timestamp
|
||||
Time.zone.now.strftime("%Y%m%d")
|
||||
end
|
||||
|
||||
@@ -3,6 +3,14 @@ module Spree
|
||||
class TaxonsController < Spree::Admin::BaseController
|
||||
respond_to :html, :json, :js
|
||||
|
||||
def search
|
||||
@taxons = if params[:ids]
|
||||
Spree::Taxon.where(id: params[:ids].split(','))
|
||||
else
|
||||
Spree::Taxon.limit(20).search(name_cont: params[:q]).result
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
@taxonomy = Taxonomy.find(params[:taxonomy_id])
|
||||
@taxon = @taxonomy.taxons.build(params[:taxon])
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
module ApplicationHelper
|
||||
include FoundationRailsHelper::FlashHelper
|
||||
|
||||
def feature?(feature)
|
||||
OpenFoodNetwork::FeatureToggle.enabled? feature
|
||||
end
|
||||
|
||||
@@ -47,7 +47,7 @@ module InjectionHelper
|
||||
enterprises_and_relatives = current_distributor.
|
||||
relatives_including_self.
|
||||
activated.
|
||||
includes(:properties, address: [:state, :country], supplied_products: :properties).
|
||||
includes(address: [:state, :country]).
|
||||
all
|
||||
|
||||
inject_json_ams "enterprises",
|
||||
|
||||
@@ -47,6 +47,17 @@ module OrderCyclesHelper
|
||||
end
|
||||
end
|
||||
|
||||
def order_cycle_options
|
||||
@order_cycles.
|
||||
with_distributor(current_distributor).
|
||||
map { |oc| [order_cycle_close_to_s(oc.orders_close_at), oc.id] }
|
||||
end
|
||||
|
||||
def order_cycle_close_to_s(orders_close_at)
|
||||
"%s (%s)" % [orders_close_at.strftime("#{orders_close_at.day.ordinalize} %b"),
|
||||
distance_of_time_in_words_to_now(orders_close_at)]
|
||||
end
|
||||
|
||||
def active_order_cycle_for_distributor?(_distributor)
|
||||
OrderCycle.active.with_distributor(@distributor).present?
|
||||
end
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module OrderHelper
|
||||
def last_payment_method(order)
|
||||
OrderPaymentFinder.new(order).last_payment&.payment_method
|
||||
end
|
||||
end
|
||||
@@ -13,7 +13,7 @@ module ShopHelper
|
||||
end
|
||||
|
||||
def require_customer?
|
||||
@require_customer ||= current_distributor.require_login? && !user_is_related_to_distributor?
|
||||
current_distributor.require_login? && !user_is_related_to_distributor?
|
||||
end
|
||||
|
||||
def user_is_related_to_distributor?
|
||||
@@ -48,6 +48,6 @@ module ShopHelper
|
||||
end
|
||||
|
||||
def no_open_order_cycles?
|
||||
@no_open_order_cycles ||= @order_cycles&.empty?
|
||||
@order_cycles && @order_cycles.empty?
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Spree
|
||||
module ProductsHelper
|
||||
def product_has_variant_unit_option_type?(product)
|
||||
product.option_types.any? { |option_type| variant_unit_option_type? option_type }
|
||||
end
|
||||
|
||||
def variant_unit_option_type?(option_type)
|
||||
Spree::Product.all_variant_unit_option_types.include? option_type
|
||||
end
|
||||
end
|
||||
end
|
||||
23
app/helpers/spree/products_helper_decorator.rb
Normal file
23
app/helpers/spree/products_helper_decorator.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
module Spree
|
||||
ProductsHelper.class_eval do
|
||||
# Return the price of the variant, overriding sprees price diff capability.
|
||||
# This will allways return the variant price as if the show_variant_full_price is set.
|
||||
def variant_price_diff(variant)
|
||||
"(#{Spree::Money.new(variant.price)})"
|
||||
end
|
||||
|
||||
def product_has_variant_unit_option_type?(product)
|
||||
product.option_types.any? { |option_type| variant_unit_option_type? option_type }
|
||||
end
|
||||
|
||||
def variant_unit_option_type?(option_type)
|
||||
Spree::Product.all_variant_unit_option_types.include? option_type
|
||||
end
|
||||
|
||||
def product_variant_unit_options
|
||||
[[I18n.t(:weight), 'weight'],
|
||||
[I18n.t(:volume), 'volume'],
|
||||
[I18n.t(:items), 'items']]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,9 +1,17 @@
|
||||
require 'order_management/subscriptions/summarizer'
|
||||
require 'open_food_network/subscription_payment_updater'
|
||||
require 'open_food_network/subscription_summarizer'
|
||||
|
||||
# Confirms orders of unconfirmed proxy orders in recently closed Order Cycles
|
||||
class SubscriptionConfirmJob
|
||||
def perform
|
||||
confirm_proxy_orders!
|
||||
ids = proxy_orders.pluck(:id)
|
||||
proxy_orders.update_all(confirmed_at: Time.zone.now)
|
||||
ProxyOrder.where(id: ids).each do |proxy_order|
|
||||
Rails.logger.info "Confirming Order for Proxy Order #{proxy_order.id}"
|
||||
@order = proxy_order.order
|
||||
process!
|
||||
end
|
||||
|
||||
send_confirmation_summary_emails
|
||||
end
|
||||
|
||||
private
|
||||
@@ -12,26 +20,10 @@ class SubscriptionConfirmJob
|
||||
delegate :record_and_log_error, :send_confirmation_summary_emails, to: :summarizer
|
||||
|
||||
def summarizer
|
||||
@summarizer ||= OrderManagement::Subscriptions::Summarizer.new
|
||||
@summarizer ||= OpenFoodNetwork::SubscriptionSummarizer.new
|
||||
end
|
||||
|
||||
def confirm_proxy_orders!
|
||||
# Fetch all unconfirmed proxy orders
|
||||
unconfirmed_proxy_orders_ids = unconfirmed_proxy_orders.pluck(:id)
|
||||
|
||||
# Mark these proxy orders as confirmed
|
||||
unconfirmed_proxy_orders.update_all(confirmed_at: Time.zone.now)
|
||||
|
||||
# Confirm these proxy orders
|
||||
ProxyOrder.where(id: unconfirmed_proxy_orders_ids).each do |proxy_order|
|
||||
Rails.logger.info "Confirming Order for Proxy Order #{proxy_order.id}"
|
||||
confirm_order!(proxy_order.order)
|
||||
end
|
||||
|
||||
send_confirmation_summary_emails
|
||||
end
|
||||
|
||||
def unconfirmed_proxy_orders
|
||||
def proxy_orders
|
||||
ProxyOrder.not_canceled.where('confirmed_at IS NULL AND placed_at IS NOT NULL')
|
||||
.joins(:order_cycle).merge(recently_closed_order_cycles)
|
||||
.joins(:order).merge(Spree::Order.complete.not_state('canceled'))
|
||||
@@ -41,55 +33,30 @@ class SubscriptionConfirmJob
|
||||
OrderCycle.closed.where('order_cycles.orders_close_at BETWEEN (?) AND (?) OR order_cycles.updated_at BETWEEN (?) AND (?)', 1.hour.ago, Time.zone.now, 1.hour.ago, Time.zone.now)
|
||||
end
|
||||
|
||||
# It sets up payments, processes payments and sends confirmation emails
|
||||
def confirm_order!(order)
|
||||
record_order(order)
|
||||
def process!
|
||||
record_order(@order)
|
||||
update_payment! if @order.payment_required?
|
||||
return send_failed_payment_email if @order.errors.present?
|
||||
|
||||
if process_payment!(order)
|
||||
send_confirmation_email(order)
|
||||
else
|
||||
send_failed_payment_email(order)
|
||||
end
|
||||
@order.process_payments! if @order.payment_required?
|
||||
return send_failed_payment_email if @order.errors.present?
|
||||
|
||||
send_confirm_email
|
||||
end
|
||||
|
||||
def process_payment!(order)
|
||||
return false if order.errors.present?
|
||||
return true unless order.payment_required?
|
||||
|
||||
setup_payment!(order)
|
||||
return false if order.errors.any?
|
||||
|
||||
authorize_payment!(order)
|
||||
return false if order.errors.any?
|
||||
|
||||
order.process_payments!
|
||||
return false if order.errors.any?
|
||||
|
||||
true
|
||||
def update_payment!
|
||||
OpenFoodNetwork::SubscriptionPaymentUpdater.new(@order).update!
|
||||
end
|
||||
|
||||
def setup_payment!(order)
|
||||
OrderManagement::Subscriptions::PaymentSetup.new(order).call!
|
||||
return if order.errors.any?
|
||||
|
||||
OrderManagement::Subscriptions::StripePaymentSetup.new(order).call!
|
||||
def send_confirm_email
|
||||
@order.update!
|
||||
record_success(@order)
|
||||
SubscriptionMailer.confirmation_email(@order).deliver
|
||||
end
|
||||
|
||||
def authorize_payment!(order)
|
||||
return if order.subscription.payment_method.class != Spree::Gateway::StripeSCA
|
||||
|
||||
OrderManagement::Subscriptions::StripeScaPaymentAuthorize.new(order).call!
|
||||
end
|
||||
|
||||
def send_confirmation_email(order)
|
||||
order.update!
|
||||
record_success(order)
|
||||
SubscriptionMailer.confirmation_email(order).deliver
|
||||
end
|
||||
|
||||
def send_failed_payment_email(order)
|
||||
order.update!
|
||||
record_and_log_error(:failed_payment, order)
|
||||
SubscriptionMailer.failed_payment_email(order).deliver
|
||||
def send_failed_payment_email
|
||||
@order.update!
|
||||
record_and_log_error(:failed_payment, @order)
|
||||
SubscriptionMailer.failed_payment_email(@order).deliver
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
require 'order_management/subscriptions/summarizer'
|
||||
require 'open_food_network/subscription_summarizer'
|
||||
|
||||
class SubscriptionPlacementJob
|
||||
def perform
|
||||
@@ -17,7 +17,7 @@ class SubscriptionPlacementJob
|
||||
delegate :record_and_log_error, :send_placement_summary_emails, to: :summarizer
|
||||
|
||||
def summarizer
|
||||
@summarizer ||= OrderManagement::Subscriptions::Summarizer.new
|
||||
@summarizer ||= OpenFoodNetwork::SubscriptionSummarizer.new
|
||||
end
|
||||
|
||||
def proxy_orders
|
||||
|
||||
@@ -1,58 +1,41 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class ProducerMailer < Spree::BaseMailer
|
||||
include I18nHelper
|
||||
|
||||
def order_cycle_report(producer, order_cycle)
|
||||
@producer = producer
|
||||
@coordinator = order_cycle.coordinator
|
||||
@order_cycle = order_cycle
|
||||
line_items = line_items_from(@order_cycle, @producer)
|
||||
@grouped_line_items = line_items.group_by(&:product_and_full_name)
|
||||
@receival_instructions = @order_cycle.receival_instructions_for @producer
|
||||
@total = total_from_line_items(line_items)
|
||||
@tax_total = tax_total_from_line_items(line_items)
|
||||
|
||||
with_unscoped_products_and_variants do
|
||||
load_data
|
||||
I18n.with_locale valid_locale(@producer.owner) do
|
||||
order_cycle_subject = I18n.t('producer_mailer.order_cycle.subject', producer: producer.name)
|
||||
subject = "[#{Spree::Config.site_name}] #{order_cycle_subject}"
|
||||
|
||||
I18n.with_locale(owner_locale) do
|
||||
return unless orders?(order_cycle, producer)
|
||||
return unless has_orders?(order_cycle, producer)
|
||||
|
||||
mail(
|
||||
to: @producer.contact.email,
|
||||
from: from_address,
|
||||
subject: subject,
|
||||
reply_to: @coordinator.contact.email,
|
||||
cc: @coordinator.contact.email
|
||||
)
|
||||
end
|
||||
mail(
|
||||
to: @producer.contact.email,
|
||||
from: from_address,
|
||||
subject: subject,
|
||||
reply_to: @coordinator.contact.email,
|
||||
cc: @coordinator.contact.email
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def owner_locale
|
||||
valid_locale(@producer.owner)
|
||||
end
|
||||
|
||||
def load_data
|
||||
@coordinator = @order_cycle.coordinator
|
||||
|
||||
line_items = line_items_from(@order_cycle, @producer)
|
||||
|
||||
@grouped_line_items = line_items.group_by(&:product_and_full_name)
|
||||
@receival_instructions = @order_cycle.receival_instructions_for(@producer)
|
||||
@total = total_from_line_items(line_items)
|
||||
@tax_total = tax_total_from_line_items(line_items)
|
||||
end
|
||||
|
||||
def subject
|
||||
order_cycle_subject = I18n.t('producer_mailer.order_cycle.subject', producer: @producer.name)
|
||||
"[#{Spree::Config.site_name}] #{order_cycle_subject}"
|
||||
end
|
||||
|
||||
def orders?(order_cycle, producer)
|
||||
def has_orders?(order_cycle, producer)
|
||||
line_items_from(order_cycle, producer).any?
|
||||
end
|
||||
|
||||
def line_items_from(order_cycle, producer)
|
||||
@line_items ||= Spree::LineItem.
|
||||
includes(:option_values, variant: [:product, { option_values: :option_type }]).
|
||||
Spree::LineItem.
|
||||
includes(variant: { option_values: :option_type }).
|
||||
from_order_cycle(order_cycle).
|
||||
sorted_by_name_and_unit_value.
|
||||
merge(Spree::Product.in_supplier(producer)).
|
||||
@@ -66,22 +49,4 @@ class ProducerMailer < Spree::BaseMailer
|
||||
def tax_total_from_line_items(line_items)
|
||||
Spree::Money.new line_items.sum(&:included_tax)
|
||||
end
|
||||
|
||||
# This hack makes ActiveRecord skip the default_scope (deleted_at IS NULL)
|
||||
# when eager loading associations. Further details:
|
||||
# https://github.com/rails/rails/issues/11036
|
||||
def with_unscoped_products_and_variants
|
||||
variant_default_scopes = Spree::Variant.default_scopes
|
||||
product_default_scopes = Spree::Product.default_scopes
|
||||
|
||||
Spree::Variant.default_scopes = []
|
||||
Spree::Product.default_scopes = []
|
||||
|
||||
return_value = yield
|
||||
|
||||
Spree::Variant.default_scopes = variant_default_scopes
|
||||
Spree::Product.default_scopes = product_default_scopes
|
||||
|
||||
return_value
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,7 +2,6 @@ Spree::OrderMailer.class_eval do
|
||||
helper HtmlHelper
|
||||
helper CheckoutHelper
|
||||
helper SpreeCurrencyHelper
|
||||
helper OrderHelper
|
||||
include I18nHelper
|
||||
|
||||
def cancel_email(order_or_order_id, resend = false)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
class SubscriptionMailer < Spree::BaseMailer
|
||||
helper CheckoutHelper
|
||||
helper ShopMailHelper
|
||||
helper OrderHelper
|
||||
include I18nHelper
|
||||
|
||||
def confirmation_email(order)
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# API controllers inherit from ActionController::Metal to keep them slim and fast.
|
||||
# This concern adds the minimum requirements needed to use Action Caching in the API.
|
||||
|
||||
module ApiActionCaching
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
include ActionController::Caching
|
||||
include ActionController::Caching::Actions
|
||||
include AbstractController::Layouts
|
||||
|
||||
# These configs are not assigned to the controller automatically with ActionController::Metal
|
||||
self.cache_store = Rails.configuration.cache_store
|
||||
self.perform_caching = true
|
||||
|
||||
# ActionController::Caching asks for a controller's layout, but they're not used in the API
|
||||
layout false
|
||||
end
|
||||
end
|
||||
@@ -40,18 +40,9 @@ module VariantStock
|
||||
|
||||
# Checks whether this variant is produced on demand.
|
||||
def on_demand
|
||||
# A variant that has not been saved yet or has been soft-deleted doesn't have a stock item
|
||||
# A variant that has not been saved yet, doesn't have a stock item
|
||||
# This provides a default value for variant.on_demand using Spree::StockLocation.backorderable_default
|
||||
return Spree::StockLocation.first.backorderable_default if new_record? || deleted?
|
||||
|
||||
# This can be removed unless we have seen this error in Bugsnag recently
|
||||
if stock_item.nil?
|
||||
Bugsnag.notify(
|
||||
RuntimeError.new("Variant #stock_item called, but the stock_item does not exist!"),
|
||||
object: as_json
|
||||
)
|
||||
return Spree::StockLocation.first.backorderable_default
|
||||
end
|
||||
return Spree::StockLocation.first.backorderable_default if stock_items.empty?
|
||||
|
||||
stock_item.backorderable?
|
||||
end
|
||||
|
||||
@@ -57,8 +57,8 @@ class ContentConfiguration < Spree::Preferences::FileConfiguration
|
||||
# Other
|
||||
preference :footer_facebook_url, :string, default: "https://www.facebook.com/OpenFoodNet"
|
||||
preference :footer_twitter_url, :string, default: "https://twitter.com/OpenFoodNet"
|
||||
preference :footer_instagram_url, :string, default: "https://www.instagram.com/openfoodnetworkuk/"
|
||||
preference :footer_linkedin_url, :string, default: "https://www.linkedin.com/company/openfoodnetwork/"
|
||||
preference :footer_instagram_url, :string, default: ""
|
||||
preference :footer_linkedin_url, :string, default: "http://www.linkedin.com/groups/Open-Food-Foundation-4743336"
|
||||
preference :footer_googleplus_url, :string, default: ""
|
||||
preference :footer_pinterest_url, :string, default: ""
|
||||
preference :footer_email, :string, default: "hello@openfoodnetwork.org"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class DistributorShippingMethod < ActiveRecord::Base
|
||||
self.table_name = "distributors_shipping_methods"
|
||||
belongs_to :shipping_method, class_name: Spree::ShippingMethod, touch: true
|
||||
belongs_to :shipping_method, class_name: Spree::ShippingMethod
|
||||
belongs_to :distributor, class_name: Enterprise, touch: true
|
||||
end
|
||||
|
||||
@@ -16,9 +16,8 @@ class OrderCycle < ActiveRecord::Base
|
||||
has_many :suppliers, source: :sender, through: :cached_incoming_exchanges, uniq: true
|
||||
has_many :distributors, source: :receiver, through: :cached_outgoing_exchanges, uniq: true
|
||||
|
||||
has_many :schedules, through: :order_cycle_schedules
|
||||
has_many :order_cycle_schedules
|
||||
has_paper_trail meta: { custom_data: proc { |order_cycle| order_cycle.schedule_ids.to_s } }
|
||||
has_and_belongs_to_many :schedules, join_table: 'order_cycle_schedules'
|
||||
has_paper_trail meta: { custom_data: :schedule_ids }
|
||||
|
||||
attr_accessor :incoming_exchanges, :outgoing_exchanges
|
||||
|
||||
@@ -241,8 +240,7 @@ class OrderCycle < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def exchanges_supplying(order)
|
||||
variant_ids_relation = Spree::LineItem.in_orders(order).select(:variant_id)
|
||||
exchanges.supplying_to(order.distributor).with_any_variant(variant_ids_relation)
|
||||
exchanges.supplying_to(order.distributor).with_any_variant(order.variants.map(&:id))
|
||||
end
|
||||
|
||||
def coordinated_by?(user)
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class OrderCycleSchedule < ActiveRecord::Base
|
||||
belongs_to :schedule
|
||||
belongs_to :order_cycle
|
||||
end
|
||||
@@ -4,6 +4,18 @@ class ProducerProperty < ActiveRecord::Base
|
||||
|
||||
default_scope { order("#{table_name}.position") }
|
||||
|
||||
scope :ever_sold_by, ->(shop) {
|
||||
joins(producer: { supplied_products: { variants: { exchanges: :order_cycle } } }).
|
||||
merge(Exchange.outgoing).
|
||||
merge(Exchange.to_enterprise(shop)).
|
||||
select('DISTINCT producer_properties.*')
|
||||
}
|
||||
|
||||
scope :currently_sold_by, ->(shop) {
|
||||
ever_sold_by(shop).
|
||||
merge(OrderCycle.active)
|
||||
}
|
||||
|
||||
def property_name
|
||||
property.name if property
|
||||
end
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
class Schedule < ActiveRecord::Base
|
||||
has_paper_trail meta: { custom_data: proc { |schedule| schedule.order_cycle_ids.to_s } }
|
||||
has_and_belongs_to_many :order_cycles, join_table: 'order_cycle_schedules'
|
||||
has_paper_trail meta: { custom_data: :order_cycle_ids }
|
||||
|
||||
has_many :order_cycles, through: :order_cycle_schedules
|
||||
has_many :order_cycle_schedules, dependent: :destroy
|
||||
has_many :coordinators, uniq: true, through: :order_cycles
|
||||
|
||||
attr_accessible :name, :order_cycle_ids
|
||||
|
||||
@@ -14,6 +14,7 @@ Spree::AppConfiguration.class_eval do
|
||||
preference :privacy_policy_url, :string, default: nil
|
||||
preference :cookies_consent_banner_toggle, :boolean, default: false
|
||||
preference :cookies_policy_matomo_section, :boolean, default: false
|
||||
preference :cookies_policy_ga_section, :boolean, default: false
|
||||
|
||||
# Tax Preferences
|
||||
preference :products_require_tax_category, :boolean, default: false
|
||||
|
||||
@@ -17,9 +17,9 @@ module Spree
|
||||
order_amount = line_items_for(object).map { |x| x.price * x.quantity }.sum
|
||||
|
||||
if order_amount < min
|
||||
cost = preferred_normal_amount.to_f
|
||||
cost = preferred_normal_amount.to_i
|
||||
elsif order_amount >= min
|
||||
cost = preferred_discount_amount.to_f
|
||||
cost = preferred_discount_amount.to_i
|
||||
end
|
||||
|
||||
cost
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
Spree::Classification.class_eval do
|
||||
belongs_to :product, class_name: "Spree::Product", touch: true
|
||||
belongs_to :taxon, class_name: "Spree::Taxon", touch: true
|
||||
|
||||
before_destroy :dont_destroy_if_primary_taxon
|
||||
|
||||
|
||||
6
app/models/spree/money_decorator.rb
Normal file
6
app/models/spree/money_decorator.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
Spree::Money.class_eval do
|
||||
# return the currency symbol (on it's own) for the current default currency
|
||||
def self.currency_symbol
|
||||
Money.new(0, Spree::Config[:currency]).symbol
|
||||
end
|
||||
end
|
||||
@@ -210,7 +210,7 @@ Spree::Order.class_eval do
|
||||
end
|
||||
|
||||
def cap_quantity_at_stock!
|
||||
line_items.includes(variant: :stock_items).all.each(&:cap_quantity_at_stock!)
|
||||
line_items.each(&:cap_quantity_at_stock!)
|
||||
end
|
||||
|
||||
def set_distributor!(distributor)
|
||||
@@ -237,10 +237,7 @@ Spree::Order.class_eval do
|
||||
with_lock do
|
||||
EnterpriseFee.clear_all_adjustments_on_order self
|
||||
|
||||
loaded_line_items =
|
||||
line_items.includes(variant: :product, order: [:distributor, :order_cycle]).all
|
||||
|
||||
loaded_line_items.each do |line_item|
|
||||
line_items.each do |line_item|
|
||||
if provided_by_order_cycle? line_item
|
||||
OpenFoodNetwork::EnterpriseFeeCalculator.new.create_line_item_adjustments_for line_item
|
||||
end
|
||||
@@ -266,11 +263,7 @@ Spree::Order.class_eval do
|
||||
end
|
||||
|
||||
def line_item_variants
|
||||
if line_items.loaded?
|
||||
line_items.map(&:variant)
|
||||
else
|
||||
line_items.includes(:variant).map(&:variant)
|
||||
end
|
||||
line_items.map(&:variant)
|
||||
end
|
||||
|
||||
# Show already bought line items of this order cycle
|
||||
|
||||
@@ -12,7 +12,7 @@ Spree::Product.class_eval do
|
||||
has_many :option_types, through: :product_option_types, dependent: :destroy
|
||||
|
||||
belongs_to :supplier, class_name: 'Enterprise', touch: true
|
||||
belongs_to :primary_taxon, class_name: 'Spree::Taxon', touch: true
|
||||
belongs_to :primary_taxon, class_name: 'Spree::Taxon'
|
||||
|
||||
delegate_belongs_to :master, :unit_value, :unit_description
|
||||
delegate :images_attributes=, :display_as=, to: :master
|
||||
|
||||
@@ -2,16 +2,11 @@ module Spree
|
||||
class Property < ActiveRecord::Base
|
||||
has_many :product_properties, dependent: :destroy
|
||||
has_many :products, through: :product_properties
|
||||
has_many :producer_properties
|
||||
|
||||
attr_accessible :name, :presentation
|
||||
|
||||
validates :name, :presentation, presence: true
|
||||
|
||||
scope :sorted, -> { order(:name) }
|
||||
|
||||
def property
|
||||
self
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
27
app/models/spree/property_decorator.rb
Normal file
27
app/models/spree/property_decorator.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
module Spree
|
||||
Property.class_eval do
|
||||
has_many :producer_properties
|
||||
|
||||
scope :applied_by, ->(enterprise) {
|
||||
select('DISTINCT spree_properties.*').
|
||||
joins(:product_properties).
|
||||
where('spree_product_properties.product_id IN (?)', enterprise.supplied_product_ids)
|
||||
}
|
||||
|
||||
scope :ever_sold_by, ->(shop) {
|
||||
joins(products: { variants: { exchanges: :order_cycle } }).
|
||||
merge(Exchange.outgoing).
|
||||
merge(Exchange.to_enterprise(shop)).
|
||||
select('DISTINCT spree_properties.*')
|
||||
}
|
||||
|
||||
scope :currently_sold_by, ->(shop) {
|
||||
ever_sold_by(shop).
|
||||
merge(OrderCycle.active)
|
||||
}
|
||||
|
||||
def property
|
||||
self
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,40 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Spree
|
||||
module Stock
|
||||
class Quantifier
|
||||
attr_reader :stock_items
|
||||
|
||||
def initialize(variant)
|
||||
@variant = variant
|
||||
@stock_items = fetch_stock_items
|
||||
end
|
||||
|
||||
def total_on_hand
|
||||
# Associated stock_items no longer exist if the variant has been soft-deleted. A variant
|
||||
# may still be in an active cart after it's deleted, so this will mark it as out of stock.
|
||||
return 0 if @variant.deleted?
|
||||
|
||||
stock_items.sum(&:count_on_hand)
|
||||
end
|
||||
|
||||
def backorderable?
|
||||
stock_items.any?(&:backorderable)
|
||||
end
|
||||
|
||||
def can_supply?(required)
|
||||
total_on_hand >= required || backorderable?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fetch_stock_items
|
||||
# Don't re-fetch associated stock items from the DB if we've already eager-loaded them
|
||||
return @variant.stock_items.to_a if @variant.stock_items.loaded?
|
||||
|
||||
Spree::StockItem.joins(:stock_location).
|
||||
where(:variant_id => @variant, Spree::StockLocation.table_name => { active: true })
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user