Compare commits

...

455 Commits

Author SHA1 Message Date
Luis Ramos
d162e8c087 Merge pull request #4300 from daningenthron/daningenthron/add-a-new-card
Translation: "Add new credit card"
2019-09-30 13:27:25 +01:00
Luis Ramos
75a56c2be5 Merge pull request #4293 from jasonk357/4031-change-user-email-alert
Improve user email change flash alert message
2019-09-30 13:19:40 +01:00
Luis Ramos
07a5963554 Merge pull request #4311 from mkllnk/rails3-deprecations
Replace deprecated validates_presence_of
2019-09-30 13:19:25 +01:00
luisramos0
a6888cf0be Update all locales with the latest Transifex translations 2019-09-30 13:15:45 +01:00
Luis Ramos
ef35db6db2 Merge pull request #4296 from luisramos0/subs_line_items
Make subscription line items handle soft deleted variants
2019-09-30 13:07:10 +01:00
Pau Pérez Fabregat
49665ae360 Merge pull request #4167 from luisramos0/last_dedeface
Move app_wrapper deface to spree/layouts/admin view
2019-09-27 09:21:28 +02:00
Pau Pérez Fabregat
7e5c194515 Merge pull request #4295 from coopdevs/enable-datadog-analytics
Enable trace & search analytics in Datadog
2019-09-27 09:17:03 +02:00
JASON KNOEPFLER
c46fe7b675 encapsulate new unconfirmed email logic 2019-09-25 19:41:33 -07:00
Luis Ramos
2489a2f5f5 Merge pull request #4294 from openfoodfoundation/transifex
Transifex
2019-09-25 11:22:58 +01:00
Transifex-Openfoodnetwork
a6698230fe Updating translations for config/locales/en_NZ.yml 2019-09-25 20:13:57 +10:00
Luis Ramos
2f3509bf9b Merge pull request #4287 from luisramos0/mini_racer
Replace therubyracer with mini_racer.
2019-09-24 19:48:50 +01:00
Dan Ingenthron
e8f9ace8e6 Correct translation key on add card link 2019-09-24 13:42:31 -05:00
Luis Ramos
04270b6cec Merge pull request #4286 from luisramos0/transpec
Finish transpec
2019-09-24 19:33:26 +01:00
Matt-Yorkley
1155931ea9 Merge pull request #4280 from luisramos0/knapsack
Update knapsack report
2019-09-24 19:26:27 +01:00
Maikel Linke
efd450606e Replace deprecated validates_presence_of
This syntax has been deprecated in Rails 3:
https://guides.rubyonrails.org/3_0_release_notes.html#patches-and-deprecations
2019-09-24 19:16:05 +10:00
Transifex-Openfoodnetwork
a18f6f5b8f Updating translations for config/locales/fr_CA.yml 2019-09-24 01:01:41 +10:00
Transifex-Openfoodnetwork
403653381c Updating translations for config/locales/en_CA.yml 2019-09-24 00:59:20 +10:00
luisramos0
c66e5fe1e9 Make subscription line items handle soft deleted variants
This ensures subscription list page works. The variant can be removed from the subscription by the user in the edit subscription page
2019-09-22 14:59:59 +01:00
JASON KNOEPFLER
4ec8fcd3a6 Assign flash message var from conditional return 2019-09-21 08:10:58 -07:00
Pau Perez
88893a2968 Enable trace & search analytics in Datadog
This will enrich the quality of the reported traces for all web
frameworks in our stack. That means not only memcached as we did in
https://github.com/openfoodfoundation/openfoodnetwork/pull/4266 but
PostgreSQL and Rails too.

After enabling, the Trace Search & Analytics page populates which allows
us to search traces and add APM queries to dashboards.
2019-09-21 14:09:27 +02:00
JASON KNOEPFLER
62599e8dfc Edit user email feature spec 2019-09-20 15:28:25 -07:00
Transifex-Openfoodnetwork
b97c428f72 Updating translations for config/locales/pt_BR.yml 2019-09-21 04:00:00 +10:00
Transifex-Openfoodnetwork
42b074f02e Updating translations for config/locales/pt_BR.yml 2019-09-21 03:56:52 +10:00
JASON KNOEPFLER
07e0951490 Change users#update email change flash alert 2019-09-20 10:35:25 -07:00
luisramos0
9e57807dc2 Replace therubyracer with mini_racer.
This is being replaced to increase the reliability and speed of asset compilation.
2019-09-20 11:22:07 +01:00
luisramos0
052bac196b Fix problem in spec/features/consumer/shopping/shopping_spec introduced with transpec 2019-09-20 10:33:40 +01:00
luisramos0
00e789b95b Force use of expect over should in spec expectations 2019-09-20 10:29:56 +01:00
luisramos0
a004822019 Transpec spec/features/consumer/shopping/shopping_spec 2019-09-20 10:16:08 +01:00
luisramos0
49f7b4c8e2 Transpec spec/features/consumer/shopping/cart_spec.rb 2019-09-20 10:11:02 +01:00
luisramos0
8b503b51ca Fix typo in spec name 2019-09-20 10:03:52 +01:00
luisramos0
4e431ecf18 Transpec spec/features/consumer/shopping/products_spec.rb 2019-09-20 10:02:27 +01:00
luisramos0
81f8b127db Transpec spec/features/consumer/authentication_spec.rb and spec/features/consumer/producers_spec.rb 2019-09-20 09:53:23 +01:00
luisramos0
f9f81086fd Transpec features/consumer/shopping/variant_overrides_spec 2019-09-20 09:02:43 +01:00
Luis Ramos
9807b432f9 Merge pull request #4272 from openfoodfoundation/dependabot/bundler/webmock-3.7.5
Bump webmock from 3.7.4 to 3.7.5
2019-09-20 08:42:12 +01:00
luisramos0
6b0f3cd4f3 Transpec spec/performance/shop_controller_spec 2019-09-19 20:36:33 +01:00
luisramos0
3c412b7b7d Transpec spec/controllers/api/taxonomies_controller_spec, spec/controllers/api/taxons_controller_spec and spec/models/enterprise_spec 2019-09-19 20:34:30 +01:00
luisramos0
c4e6c0af2b Transpec features/consumer/registration_spec 2019-09-19 20:18:24 +01:00
Luis Ramos
746c4f03f6 Merge pull request #4261 from jasonk357/3979-malformed-referer-error
Guard against malformed request referer
2019-09-19 17:29:18 +01:00
Kristina Lim
3535c4d564 Merge pull request #4240 from Matt-Yorkley/backorder_to_the_future_2
Disentangle on_demand and backordered
2019-09-20 00:05:27 +08:00
luisramos0
37abdb7727 Update knapsack report 2019-09-19 16:58:06 +01:00
dependabot-preview[bot]
47056e3cc1 Bump webmock from 3.7.4 to 3.7.5
Bumps [webmock](https://github.com/bblimke/webmock) from 3.7.4 to 3.7.5.
- [Release notes](https://github.com/bblimke/webmock/releases)
- [Changelog](https://github.com/bblimke/webmock/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bblimke/webmock/compare/v3.7.4...v3.7.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-19 13:10:20 +00:00
Kristina Lim
311ee92e84 Update all locales with the latest Transifex translations 2019-09-19 17:08:17 +08:00
Kristina Lim
241e97d938 Merge pull request #4241 from openfoodfoundation/transifex
Transifex
2019-09-19 16:58:57 +08:00
Pau Pérez Fabregat
85b1ba8eae Merge pull request #4263 from coopdevs/index-frequent-spree-orders-query
Index spree_orders on various columns
2019-09-19 10:12:54 +02:00
Pau Pérez Fabregat
baa4783141 Merge pull request #4260 from jasonk357/4184-delivery-report-default-range
Add default date range to Delivery Report
2019-09-19 09:58:06 +02:00
Transifex-Openfoodnetwork
ce40fcaf7b Updating translations for config/locales/fr.yml 2019-09-19 07:44:00 +10:00
Luis Ramos
40438de7fe Merge pull request #4250 from Matt-Yorkley/ruby-2.1.9
Bump Ruby version from 2.1.5 to 2.1.9
2019-09-18 11:39:15 +01:00
Luis Ramos
29dcd96fca Merge pull request #4265 from openfoodfoundation/dependabot/bundler/simplecov-0.17.1
Bump simplecov from 0.17.0 to 0.17.1
2019-09-18 10:25:54 +01:00
Pau Pérez Fabregat
7fd6a7e654 Merge pull request #4270 from openfoodfoundation/dependabot/bundler/webmock-3.7.4
Bump webmock from 3.7.3 to 3.7.4
2019-09-18 10:11:11 +02:00
dependabot-preview[bot]
8f2a80f199 Bump webmock from 3.7.3 to 3.7.4
Bumps [webmock](https://github.com/bblimke/webmock) from 3.7.3 to 3.7.4.
- [Release notes](https://github.com/bblimke/webmock/releases)
- [Changelog](https://github.com/bblimke/webmock/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bblimke/webmock/compare/v3.7.3...v3.7.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-17 19:21:37 +00:00
Pau Perez
ea41405209 Index spree_orders on various columns
The following query

```sql
SELECT spree_orders . *
FROM spree_orders
WHERE spree_orders . user_id = ?
AND spree_orders . completed_at IS ?
AND spree_orders . created_by_id = ?
ORDER BY created_at DESC LIMIT ?
```

performs quite badly even though LIMIT is always 1 because:

* ORDER BY requires sorting by a column which is not indexed therefore
a sequential scan is performed.
* Although `completed_at` is indexed, `user_id` and `created_by_id` are
not causing a sequential scan.

To make it worse this query is executed very often in the following
controllers among others also related to checkout:

* CartController#populate
* EnterprisesController#Shop
* LineItemsController#bought
* ShopController#products
* ShopController#order_cycle

In some cases this query alone accounts for 66.8% of the total time
of the endpoint.

Results

See by yourself. We move from 56.643ms to 0.077ms. Pretty neat.

```
openfoodnetwork=> explain analyze SELECT "spree_orders".* FROM "spree_orders" WHERE "spree_orders"."user_id" = 1 AND "spree_orders"."completed_at" IS NULL AND "spree_orders"."created_by_id" = 1 ORDER BY created_at DESC LIMIT 1;
                                                        QUERY PLAN
--------------------------------------------------------------------------------------------------------------------------
 Limit  (cost=11753.03..11753.04 rows=1 width=195) (actual time=56.580..56.580 rows=0 loops=1)
   ->  Sort  (cost=11753.03..11753.04 rows=1 width=195) (actual time=56.578..56.578 rows=0 loops=1)
         Sort Key: created_at DESC
         Sort Method: quicksort  Memory: 25kB
         ->  Seq Scan on spree_orders  (cost=0.00..11753.02 rows=1 width=195) (actual time=56.571..56.571 rows=0 loops=1)
               Filter: ((completed_at IS NULL) AND (user_id = 1) AND (created_by_id = 1))
               Rows Removed by Filter: 256135
 Planning time: 0.252 ms
 Execution time: 56.643 ms
(9 rows)

openfoodnetwork=> CREATE INDEX ON spree_orders (completed_at, user_id, created_by_id, created_at);
CREATE INDEX
openfoodnetwork=> explain analyze SELECT "spree_orders".* FROM "spree_orders" WHERE "spree_orders"."user_id" = 1 AND "spree_orders"."completed_at" IS NULL AND "spree_orders"."created_by_id" = 1 ORDER BY created_at DESC LIMIT 1;
mit  (cost=8.45..8.46 rows=1 width=195) (actual time=0.030..0.030 rows=0 loops=1)
   ->  Sort  (cost=8.45..8.46 rows=1 width=195) (actual time=0.029..0.029 rows=0 loops=1)
         Sort Key: created_at DESC
         Sort Method: quicksort  Memory: 25kB
         ->  Index Scan using spree_orders_completed_at_user_id_created_by_id_created_at_idx on spree_orders  (cost=0.42..8.44 rows=1 width=195) (actual time=0.021..0.021 rows=0 loops=1)
               Index Cond: ((completed_at IS NULL) AND (user_id = 1) AND (created_by_id = 1))
 Planning time: 0.199 ms
 Execution time: 0.077 ms
```
2019-09-17 17:02:14 +02:00
luisramos0
2683efdd3c Add missing update to db/schema by running db:migrate
This was missed in PR 4242
2019-09-17 15:27:56 +01:00
Luis Ramos
ed1c154b78 Merge pull request #4252 from luisramos0/remove_clear_ship_address
On checkout of pickup orders, set ship_address to shipping_address_from_distributor instead of empty Spree::Address.default
2019-09-17 13:18:20 +01:00
Pau Pérez Fabregat
4aba2730f7 Merge pull request #4230 from openfoodfoundation/dependabot/bundler/ddtrace-0.27.0
Bump ddtrace from 0.26.0 to 0.27.0
2019-09-17 13:11:12 +02:00
Pau Pérez Fabregat
07ae51560e Merge pull request #4259 from openfoodfoundation/dependabot/bundler/webmock-3.7.3
Bump webmock from 3.7.2 to 3.7.3
2019-09-17 09:32:21 +02:00
dependabot-preview[bot]
3c5c842bbf Bump simplecov from 0.17.0 to 0.17.1
Bumps [simplecov](https://github.com/colszowka/simplecov) from 0.17.0 to 0.17.1.
- [Release notes](https://github.com/colszowka/simplecov/releases)
- [Changelog](https://github.com/colszowka/simplecov/blob/master/CHANGELOG.md)
- [Commits](https://github.com/colszowka/simplecov/compare/v0.17.0...v0.17.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-16 21:08:17 +00:00
Luis Ramos
e7e4508555 Merge pull request #4242 from Matt-Yorkley/another_cartastrophe
Soft-delete price objects
2019-09-16 17:18:39 +01:00
Luis Ramos
9a3b5d0700 Merge pull request #4257 from daningenthron/daningenthron/payment-method-translation
Fix typo on 'no payment methods' translation keys
2019-09-16 13:18:46 +01:00
Luis Ramos
46353be9a3 Merge pull request #4237 from coopdevs/unobfuscate-bulk-management-action
Add implicit #bulk_management including filter
2019-09-15 12:15:11 +01:00
JASON KNOEPFLER
91a52ead58 Guard against malformed request referer 2019-09-14 09:13:44 -07:00
JASON KNOEPFLER
0f55049eda OrderCycleManagementReport sets default date range before querying for orders 2019-09-13 17:15:57 -07:00
Luis Ramos
83f1a7a9a9 Merge pull request #4258 from coopdevs/fix-test-example-name
Fix test example name
2019-09-13 23:04:45 +01:00
dependabot-preview[bot]
fac118fce2 Bump webmock from 3.7.2 to 3.7.3
Bumps [webmock](https://github.com/bblimke/webmock) from 3.7.2 to 3.7.3.
- [Release notes](https://github.com/bblimke/webmock/releases)
- [Changelog](https://github.com/bblimke/webmock/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bblimke/webmock/compare/v3.7.2...v3.7.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-13 19:19:34 +00:00
Dan Ingenthron
5270cdaa32 Fixed typo on 'no payment methods' translation keys
Modified to remove edits to translation files. These will be updated via Transifex webhook.
2019-09-13 13:43:13 -05:00
Luis Ramos
ecf336fe51 Merge pull request #4244 from luisramos0/fix_truncate_data
Adapt db truncate task to ofn v2 by removing db tables from v1
2019-09-13 13:09:07 +01:00
Matt-Yorkley
a3efd13d46 Update existing Spree::InventoryItem records: change backordered state to on_hand. 2019-09-13 13:05:15 +01:00
Matt-Yorkley
2ff0169016 Replace hard-deleted prices with empty (0.00) price records 2019-09-13 12:55:24 +01:00
Pau Perez
08d37bbed7 Fix test example name
The name wasn't reflecting the method being tested.
2019-09-13 12:55:34 +02:00
Transifex-Openfoodnetwork
b71443ccd8 Updating translations for config/locales/ca.yml 2019-09-13 20:45:12 +10:00
Transifex-Openfoodnetwork
8fd3d9e03c Updating translations for config/locales/es.yml 2019-09-13 20:42:43 +10:00
Transifex-Openfoodnetwork
787727872f Updating translations for config/locales/ca.yml 2019-09-13 20:42:04 +10:00
Pau Pérez Fabregat
5bf72ae780 Merge pull request #4234 from coopdevs/remove-hidden-integrity-check
Remove integrity check for deleted variants in OCs
2019-09-13 11:27:41 +02:00
Pau Pérez Fabregat
290d00f17d Merge pull request #4232 from coopdevs/remove-guard
Remove Guard and Guard-related gems
2019-09-13 11:25:29 +02:00
Pau Perez
3d7bbbbb19 Remove unused Guardfile 2019-09-13 08:25:54 +02:00
Sigmund Petersen
fd77f48aca Merge pull request #4253 from openfoodfoundation/RachL-patch-1
Update Slack invite link
2019-09-12 09:17:37 +02:00
Rachel Arnould
9a31b99de6 Update missing second link 2019-09-11 15:52:44 +02:00
Transifex-Openfoodnetwork
d98e302047 Updating translations for config/locales/nb.yml 2019-09-11 19:47:09 +10:00
luisramos0
377b4a3755 Do not add ng-controller if main_ng_ctrl_name is not set 2019-09-11 10:36:19 +01:00
luisramos0
0c809b2911 Remove now unused override app_wrapper 2019-09-11 10:35:39 +01:00
luisramos0
33472014f1 Do not add main_ng_app_name if it is not defined 2019-09-11 10:32:30 +01:00
luisramos0
d038c27f1f Fix app_wrapper_attr code by making the content_for tag be only the name of the ng-app and ng-ctrller 2019-09-11 10:32:30 +01:00
luisramos0
3d718d9738 Move admin layout body contents to a separate partial 2019-09-11 10:32:29 +01:00
Luis Ramos
500ef901fd Merge pull request #4164 from luisramos0/little_de_deface
Remove some unused deface overrides and move some others to their views
2019-09-11 10:26:56 +01:00
Matt-Yorkley
a15db65e69 Reload tested variant and price objects 2019-09-11 04:32:19 +01:00
Matt-Yorkley
64a501ee20 Don't index new deleted_at column for spree_prices 2019-09-11 04:29:02 +01:00
Matt-Yorkley
95fcff8bb1 Add migration to remove broken variants from open carts 2019-09-11 04:29:00 +01:00
Luis Ramos
c0bf7e2e75 Merge pull request #4236 from mkllnk/4222-checkout-paypal-error-handling
4233 Add missing Spree route for Paypal
2019-09-10 12:24:21 +01:00
Luis Ramos
1d177a164b Merge pull request #4247 from mkllnk/4243-inventory-pagination
4243 Restore old pagination API for inventory products
2019-09-10 11:35:04 +01:00
Rachel Arnould
d846c31db9 Update Slack invite link
Updated Slack invite link in README
2019-09-10 09:51:59 +02:00
Maikel Linke
efd01f8c9e Move new inventory spec to existing variant overrides spec
I decided to not share the same data setup with the other parts of the
spec because we don't need as much data and it's slow to create.
2019-09-10 10:05:23 +10:00
luisramos0
fb65c64c68 Keep the ship_address clearing logic (this time reusing the OrderUpdate method) thus making the restart_checkout process work for these cases (because order.ship_address is not empty)
OrderUpdater#shipping_address_from_distributor uses order.address_from_distributor to set order.ship_address when order is not delivery: this will clear the ship address as it was done previously without setting an empty address like Spree::Address.default
2019-09-09 22:05:20 +01:00
Transifex-Openfoodnetwork
b8d8ee4edc Updating translations for config/locales/en_GB.yml 2019-09-10 05:14:09 +10:00
Luis Ramos
936784404e Merge pull request #4112 from luisramos0/convert_shipments_rabl
Convert spree/api/shipments views from rabl to ams
2019-09-09 18:34:02 +01:00
Matt-Yorkley
11ea852211 Add migration to reset negative stock levels to zero 2019-09-09 17:49:58 +01:00
Matt-Yorkley
4656c35f71 Don't change on_demand variant's stock when updating shipments 2019-09-09 17:49:58 +01:00
Matt-Yorkley
254315b79e Don't mark on_demand items and shipments as "backordered" 2019-09-09 17:49:56 +01:00
luisramos0
cc7461e692 Remove clear_ship_address from checkout_controller because it is setting an empty address on order.ship_address which is breaking the reset_checkout process in some cases.
This logic is already repeated in the before_save hook in the OrderUpdater where the distributor address is put into the ship_address on order.finalize

In cases the order is not to be finalized we keep the ship_address sent from the client as we may need it to make the order workflow work properly
2019-09-09 17:48:17 +01:00
luisramos0
c4d5eec7fd Covering restart_checkout code with more tests to clarify behaviour with different order.ship_address objects
The edge case here is when ship_address is present but empty, on the checkout_controller we are going to move from using an empty ship_address to using a non-empty one. We keep the original case where this spec was testing with a nil order.ship_address
2019-09-09 17:48:04 +01:00
Luis Ramos
2dc85463ce Merge pull request #4226 from HugsDaniel/4090-missing-translations-order
Add missing translations for orders
2019-09-09 15:16:47 +01:00
Matt-Yorkley
aa3bd93ad0 Bump Ruby version to 2.1.9 2019-09-09 12:22:20 +01:00
Maikel Linke
24c8bb95cb Restore old pagination API for products
It's still used by the inventory page. This is an easy fix that I can
deploy without risk. A rewrite of the inventory pagination should
follow.
2019-09-09 14:53:04 +10:00
Maikel Linke
2e361baeaa Ignore block length cop for feature and scenario
They are typically long and that's okay, same with `describe` and `it`.
2019-09-09 14:53:04 +10:00
luisramos0
a98a0bd264 Adapt db truncate task to ofn v2 by removing db tables from v1 2019-09-08 14:05:49 +01:00
luisramos0
b4de8ef899 Make enterprises/index_spec a bit more resilient 2019-09-08 12:17:36 +01:00
luisramos0
f0586af1c7 Re-organized api/orders resource routes 2019-09-08 12:17:36 +01:00
luisramos0
e9b5551c0f Adpat shipment controller to move out of Spree namespace 2019-09-08 12:17:36 +01:00
luisramos0
7cec24f1d4 Move shipments route, controller and ctrl spec from spree/api to api 2019-09-08 12:17:36 +01:00
luisramos0
26f5ece7c0 Add a few relevant attributes to shipment serializer and fix some details in shipment controller spec 2019-09-08 12:15:33 +01:00
luisramos0
a21a4aba5d Convert spree/api/shipments from rabl to AMS and adapt its spec 2019-09-08 12:15:33 +01:00
Matt-Yorkley
f413ce2a27 Soft-delete price objects 2019-09-06 17:50:19 +01:00
Transifex-Openfoodnetwork
5847b1a51e Updating translations for config/locales/en_ZA.yml 2019-09-07 01:50:35 +10:00
Transifex-Openfoodnetwork
f51ebc63c3 Updating translations for config/locales/en_AU.yml 2019-09-07 01:47:27 +10:00
Pau Pérez Fabregat
908e1dfcaf Merge pull request #4202 from coopdevs/remove-skylight
Remove Skylight
2019-09-06 17:09:14 +02:00
Matt-Yorkley
5bc2c96248 Add specs for existing on_demand behaviour 2019-09-06 15:47:59 +01:00
Pau Perez
ab8c7bad76 Remove Skylight
Since we adopted Skylight to get response times across endpoints and
instances, we failed to get accurate numbers. Our Rails version is not
supported and thus Skylight fails to provide data for the slowest
endpoints, the ones we care about the most. Even with a supported one we
could potentially hit any limits on tracing and have the same problem.

Recently, we started paying for Datadog's APM and the experience,
although it's still early, has been better. It makes it possible to
correlate between services and other metrics which helps spotting the
underlying issues.

Therefore, having two agents running on the server consumes system
resources so we better get rid of Skylight's one.
2019-09-06 16:25:33 +02:00
Pau Perez
55883a0efc Add implicit #bulk_management including filter
OFN it's hard enough. No need to abuse implicitness making things very
hard to follow.

I've spent around 20min trying to find out where this controller action
was implemented until I realized Rails renders the matching view if no
controller action is defined.

Making it git-greppable makes it a bit easier next time.
2019-09-06 16:02:44 +02:00
Pau Pérez Fabregat
2e519957ec Merge pull request #4231 from openfoodfoundation/dependabot/bundler/webmock-3.7.2
Bump webmock from 3.7.1 to 3.7.2
2019-09-06 13:31:55 +02:00
Pau Pérez Fabregat
cd5b3c7393 Merge pull request #4229 from openfoodfoundation/dependabot/bundler/bugsnag-6.12.1
Bump bugsnag from 6.12.0 to 6.12.1
2019-09-06 13:08:47 +02:00
Maikel Linke
eb9f02f3bd Add missing Spree route for Paypal 2019-09-06 19:07:41 +10:00
Maikel Linke
a1f3e8205f Add spec for failing Paypal checkout
https://github.com/openfoodfoundation/openfoodnetwork/issues/4233
2019-09-06 19:05:59 +10:00
Pau Perez
410e23085e Remove integrity check for deleted variants in OCs
We have no way to see the output of this weird RSpec integrity check
thus, it's pointless. It only adds unnecessary load the server.

However, the issue it checks seems to still be happening although
not very often. UK's server has 70 occurrences the last one being from
early 2019 while FR's server returns 10.
2019-09-06 10:30:26 +02:00
Pau Perez
e2b3ee7b3f Remove Guard and Guard-related gems
Guard and the other Guard-related gems should be removed from our
Gemfile. We think is not worth the extra dependencies given the effort
it requires to keep them up-to-date.

This came up in a PR that was upgrading Guard: #4213.
2019-09-06 10:11:17 +02:00
Maikel Linke
242767dc73 Give variables meaningful names in checkout spec 2019-09-06 12:27:15 +10:00
Maikel Linke
8e8c77c5bd Convert specs to RSpec 3.8.0 syntax with Transpec
This conversion is done by Transpec 3.4.0 with the following command:
    transpec spec/features/consumer/shopping/checkout_spec.rb

* 43 conversions
    from: obj.should
      to: expect(obj).to

* 8 conversions
    from: obj.should_not
      to: expect(obj).not_to

* 3 conversions
    from: == expected
      to: eq(expected)

For more details: https://github.com/yujinakayama/transpec#supported-conversions
2019-09-06 11:32:44 +10:00
Luis Ramos
e3ce2a7486 Merge pull request #4104 from luisramos0/convert_taxons_to_ams
Convert spree/api/taxons views from rabl to AMS
2019-09-06 00:04:10 +01:00
dependabot-preview[bot]
8524f49589 Bump webmock from 3.7.1 to 3.7.2
Bumps [webmock](https://github.com/bblimke/webmock) from 3.7.1 to 3.7.2.
- [Release notes](https://github.com/bblimke/webmock/releases)
- [Changelog](https://github.com/bblimke/webmock/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bblimke/webmock/compare/v3.7.1...v3.7.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-05 19:17:24 +00:00
dependabot-preview[bot]
36f9cd9cbf Bump ddtrace from 0.26.0 to 0.27.0
Bumps [ddtrace](https://github.com/DataDog/dd-trace-rb) from 0.26.0 to 0.27.0.
- [Release notes](https://github.com/DataDog/dd-trace-rb/releases)
- [Changelog](https://github.com/DataDog/dd-trace-rb/blob/master/CHANGELOG.md)
- [Commits](https://github.com/DataDog/dd-trace-rb/compare/v0.26.0...v0.27.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-05 19:16:35 +00:00
dependabot-preview[bot]
0fab4a3a8e Bump bugsnag from 6.12.0 to 6.12.1
Bumps [bugsnag](https://github.com/bugsnag/bugsnag-ruby) from 6.12.0 to 6.12.1.
- [Release notes](https://github.com/bugsnag/bugsnag-ruby/releases)
- [Changelog](https://github.com/bugsnag/bugsnag-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bugsnag/bugsnag-ruby/compare/v6.12.0...v6.12.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-05 19:15:41 +00:00
Luis Ramos
722884d8d8 Merge pull request #3895 from luisramos0/fees_based_on_final_weight
Make weight calculator use line_item.final_weight_volume rather than variant.weight
2019-09-05 19:24:56 +01:00
Pau Pérez Fabregat
23740ef908 Merge pull request #4227 from openfoodfoundation/2.4.0-minus-pr-4204
Revert PR #4204
2019-09-05 17:19:15 +02:00
Pau Pérez Fabregat
ba04208999 Merge pull request #4224 from kristinalim/feature/4210-fetch_and_scope_variants_once_in_products_renderer
4210 Fetch and scope variants for shop in ProductsRenderer only once
2019-09-05 17:12:31 +02:00
Kristina Lim
590ce67f38 Fetch and scope variants for shop in ProductsRenderer only once 2019-09-05 22:42:50 +08:00
Matt-Yorkley
e11ea929c3 Merge pull request #4223 from Matt-Yorkley/integrity
Lower integrity checker job interval
2019-09-05 15:36:12 +01:00
Hugo Daniel
f88d54b862 Add missing translations for orders 2019-09-05 15:13:10 +02:00
Matt-Yorkley
fc9f61ecf8 Revert PR #4204
Temporarily reverting these changes for a quick release
2019-09-05 13:23:59 +01:00
Matt-Yorkley
6d283ac839 Lower integrity checker job interval from hourly to daily 2019-09-05 12:54:37 +01:00
Luis Ramos
725807f66d Merge pull request #4155 from coopdevs/fix-styling-in-stripe-tests
Fix Rubocop violations in Stripe connect tests
2019-09-03 15:58:34 +01:00
Pau Pérez Fabregat
149df6569c Merge pull request #4212 from openfoodfoundation/dependabot/bundler/webmock-3.7.1
Bump webmock from 3.6.2 to 3.7.1
2019-09-03 11:16:01 +02:00
Pau Pérez Fabregat
7daa7032aa Merge pull request #4215 from openfoodfoundation/transifex
Transifex
2019-09-03 11:11:51 +02:00
Pau Pérez Fabregat
8b7119beea Merge pull request #4200 from openfoodfoundation/dependabot/bundler/bugsnag-6.12.0
Bump bugsnag from 6.11.1 to 6.12.0
2019-09-03 11:02:51 +02:00
Transifex-Openfoodnetwork
201e87bf12 Updating translations for config/locales/en_US.yml 2019-09-03 12:29:10 +10:00
Transifex-Openfoodnetwork
0fffd6b4e3 Updating translations for config/locales/en_US.yml 2019-09-03 12:26:02 +10:00
Matt-Yorkley
c516d40d4a Update all locales with the latest Transifex translations 2019-09-02 22:24:53 +01:00
Luis Ramos
07d4528276 Merge pull request #4174 from openfoodfoundation/dependabot/bundler/delayed_job_active_record-4.1.4
Bump delayed_job_active_record from 4.1.3 to 4.1.4
2019-09-02 22:24:04 +01:00
Luis Ramos
4ace780431 Merge pull request #4187 from openfoodfoundation/dependabot/bundler/knapsack-1.18.0
Bump knapsack from 1.17.2 to 1.18.0
2019-09-02 22:23:15 +01:00
dependabot-preview[bot]
b69c3fd826 Bump webmock from 3.6.2 to 3.7.1
Bumps [webmock](https://github.com/bblimke/webmock) from 3.6.2 to 3.7.1.
- [Release notes](https://github.com/bblimke/webmock/releases)
- [Changelog](https://github.com/bblimke/webmock/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bblimke/webmock/compare/v3.6.2...v3.7.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-02 19:23:28 +00:00
dependabot-preview[bot]
51df8de64f Bump knapsack from 1.17.2 to 1.18.0
Bumps [knapsack](https://github.com/ArturT/knapsack) from 1.17.2 to 1.18.0.
- [Release notes](https://github.com/ArturT/knapsack/releases)
- [Changelog](https://github.com/ArturT/knapsack/blob/master/CHANGELOG.md)
- [Commits](https://github.com/ArturT/knapsack/compare/v1.17.2...v1.18.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-09-02 16:16:32 +00:00
Matt-Yorkley
d4a5829858 Merge pull request #4081 from Matt-Yorkley/products_pagination
Bulk Edit Products pagination
2019-09-02 17:14:14 +01:00
Matt-Yorkley
ff5fe66994 Fix route after big API refactor merge resolution 2019-09-02 16:29:03 +01:00
Matt-Yorkley
37e50a68e4 Fix timezone date parsing from Angular form fields 2019-09-02 16:29:00 +01:00
Matt-Yorkley
a72c662b97 Update per_page dropdown UX 2019-09-02 14:35:00 +01:00
Matt-Yorkley
ff2db0c5f8 Update spec routes, namespacing, and test content
Resolving new issues after a big merge
2019-09-02 14:35:00 +01:00
Matt-Yorkley
e9c60a33b9 Hide search in dropdown for per_page options 2019-09-02 14:35:00 +01:00
Matt-Yorkley
8e059d3c69 Define a limit on paginated queries with no supplied value for per_page 2019-09-02 14:35:00 +01:00
Matt-Yorkley
806ba94a2e Clarify dependency on kaminari gem 2019-09-02 14:35:00 +01:00
Matt-Yorkley
4bec583bff Refactor import_date_scope 2019-09-02 14:35:00 +01:00
Matt-Yorkley
90256f9c28 Add defaults and pages tests 2019-09-02 14:35:00 +01:00
Matt-Yorkley
eb284c1742 Use constants for defaults 2019-09-02 14:35:00 +01:00
Matt-Yorkley
b614e17f48 Add test coverage for #bulk_products endpoint and test all filtering functions 2019-09-02 14:34:54 +01:00
Pau Perez
1a450733a3 Use ApiHelper to DRY calls to JSON.parse in spec 2019-09-02 15:32:56 +02:00
Pau Perez
ffde7a38df Add spacing to increase readability 2019-09-02 15:32:56 +02:00
Pau Perez
8b4b0621db Fix Rubocop violations in Stripe connect tests 2019-09-02 15:32:56 +02:00
Matt-Yorkley
5259eaae5f Merge pull request #4204 from Matt-Yorkley/cartastrophe
Cartastrophe averted :)
2019-09-02 12:26:08 +01:00
Matt-Yorkley
b0ad0fccfa Add some defaults to avoid returning zero values when not supplied in query 2019-09-02 12:00:32 +01:00
Matt-Yorkley
2a83ad8689 Improve UX and consistency in orders pagination and page changing 2019-09-02 11:59:13 +01:00
Matt-Yorkley
c127110192 Make import_date query modification conditional 2019-09-02 11:59:13 +01:00
Matt-Yorkley
0470725112 Refactor pagination data hash 2019-09-02 11:57:32 +01:00
Matt-Yorkley
0623bab084 Don't respond to a successful update by querying 500 arbitrary products 2019-09-02 11:56:00 +01:00
Matt-Yorkley
4a0df684c7 Adjust specs 2019-09-02 11:56:00 +01:00
Matt-Yorkley
7dccb5ba90 Changing per_page should also reset the query 2019-09-02 11:56:00 +01:00
Matt-Yorkley
5a4be24df0 Add "filter results" button 2019-09-02 11:56:00 +01:00
Matt-Yorkley
5cb5967977 Fix cleared filters submitting "0" as value in queries 2019-09-02 11:56:00 +01:00
Matt-Yorkley
aeb8d30dae Fix server-side import_date filtering 2019-09-02 11:56:00 +01:00
Matt-Yorkley
1822fd97a6 Tidy up filters 2019-09-02 11:54:28 +01:00
Matt-Yorkley
4ff3e9fe10 Update Angular loading conditionals 2019-09-02 11:54:28 +01:00
Matt-Yorkley
a63994440d Add pagination to UI 2019-09-02 11:54:28 +01:00
Matt-Yorkley
f6d0de1454 Improve pagination data in bulk products 2019-09-02 11:54:28 +01:00
Matt-Yorkley
9b0e27a9d1 Add new ProductResource 2019-09-02 11:46:42 +01:00
Matt-Yorkley
415d88f302 Fix indentation in bulk product controller 2019-09-02 11:46:42 +01:00
Pau Pérez Fabregat
f9c98ea9a1 Merge pull request #4199 from openfoodfoundation/transifex
Transifex
2019-09-02 12:33:12 +02:00
Pau Pérez Fabregat
369a5a8a2f Merge pull request #4101 from luisramos0/remove_variants_rabl
Convert spree/api/products and spree/api/variants views from rabl to AMS
2019-09-02 12:14:26 +02:00
Matt-Yorkley
62341c6381 Unit test access to associated objects after soft-delete 2019-08-31 10:06:47 +01:00
Luis Ramos
fa1becb791 Merge pull request #4063 from luisramos0/dead_code
Remove dead code under views/spree/shared
2019-08-30 22:39:01 +01:00
Matt-Yorkley
50a1704994 Make prices soft-deletable 2019-08-30 20:11:32 +01:00
Matt-Yorkley
302538c370 Add failing spec for cart issue 2019-08-30 15:32:45 +01:00
Maikel
0f80b6ce12 Merge pull request #4197 from kristinalim/fix/4195-fix_invalid_date_in_firefox
4195 Specify API date format when converting date to string in JS
2019-08-30 08:36:17 +10:00
dependabot-preview[bot]
69fb8b2afe Bump bugsnag from 6.11.1 to 6.12.0
Bumps [bugsnag](https://github.com/bugsnag/bugsnag-ruby) from 6.11.1 to 6.12.0.
- [Release notes](https://github.com/bugsnag/bugsnag-ruby/releases)
- [Changelog](https://github.com/bugsnag/bugsnag-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bugsnag/bugsnag-ruby/compare/v6.11.1...v6.12.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-29 19:17:20 +00:00
Transifex-Openfoodnetwork
1df8fc903e Updating translations for config/locales/en_ZA.yml 2019-08-30 04:22:54 +10:00
Transifex-Openfoodnetwork
9a2dcb89af Updating translations for config/locales/en_ZA.yml 2019-08-30 04:22:46 +10:00
Transifex-Openfoodnetwork
1661591f6c Updating translations for config/locales/ca.yml 2019-08-29 23:12:46 +10:00
Transifex-Openfoodnetwork
6dde720039 Updating translations for config/locales/es.yml 2019-08-29 23:10:30 +10:00
Transifex-Openfoodnetwork
a54b725d6d Updating translations for config/locales/ca.yml 2019-08-29 23:09:39 +10:00
Luis Ramos
265e76e8ca Merge pull request #4074 from HugsDaniel/defacepocalypse
[Defacepocalypse] De-deface product properties index
2019-08-28 22:18:18 +01:00
luisramos0
192bff4fed Move taxons and taxonomies api routes to api out of spree routes 2019-08-28 22:06:56 +01:00
luisramos0
92a270165e Add missing api taxonomies controller only for the required jstree action 2019-08-28 22:06:56 +01:00
luisramos0
9f5c9916ba Add back required api actions (create, update and destroy) and add AMS serializers for the jstree action 2019-08-28 22:06:56 +01:00
luisramos0
d08de4bdf9 Add extra fields to taxon serializer to be used in the api 2019-08-28 22:06:56 +01:00
luisramos0
45bdb85bf3 Add missing method and skip_authorization_check to taxons controller 2019-08-28 22:06:56 +01:00
luisramos0
ece0652ca3 Adapt spree/admin/shared/_routes.html.erb to new location of the api/taxons routes 2019-08-28 22:06:56 +01:00
luisramos0
7a652fd67b Adapt api/taxons controller to new namespace outside Spree: remove Spree module and add Spree namespace to Taxons and Taxonomy classes 2019-08-28 22:06:56 +01:00
luisramos0
4ca8feeef1 Move api/taxons route and controller out of spree namespace into /api and move the ctrl spec as well 2019-08-28 22:06:56 +01:00
luisramos0
367932a767 Make spree/api/taxons_controller use AMS serializer instead of rabl 2019-08-28 22:06:56 +01:00
luisramos0
e591658f48 Keep only used api/taxons index action, delete all others as not required right now 2019-08-28 22:06:56 +01:00
Kristina Lim
1516069888 Specify API date format when converting date to string in JS 2019-08-29 02:44:14 +08:00
Luis Ramos
cd263b761c Merge pull request #4055 from luisramos0/remove_spree_api
Remove dependency to spree_api - step 1 - controllers and routes
2019-08-28 15:34:08 +01:00
Maikel
c952ad16ad Merge pull request #4163 from luisramos0/swagger
Add swagger.yaml to codebase
2019-08-28 14:46:51 +10:00
Maikel
ca09c58f26 Merge pull request #3985 from jonleighton/string-to-text
Convert several fields from string to text
2019-08-28 11:53:49 +10:00
Maikel Linke
e876a25d59 Fix flaky proxy order spec 2019-08-28 10:48:57 +10:00
Maikel Linke
2a780151be Update all locales with the latest Transifex translations 2019-08-28 09:54:31 +10:00
Maikel
9d2009d2af Merge pull request #4188 from openfoodfoundation/transifex
Transifex
2019-08-28 09:43:02 +10:00
Maikel
f887533dda Merge pull request #4157 from mkllnk/4138-update-products
4138 Avoid infinite loop when updating products
2019-08-28 09:42:28 +10:00
Transifex-Openfoodnetwork
bef3f154d6 Updating translations for config/locales/fr_CA.yml 2019-08-28 09:12:59 +10:00
Transifex-Openfoodnetwork
6fb775d5ed Updating translations for config/locales/en_CA.yml 2019-08-28 09:05:39 +10:00
Transifex-Openfoodnetwork
b5a8563725 Updating translations for config/locales/en_GB.yml 2019-08-27 23:28:34 +10:00
Transifex-Openfoodnetwork
1a9ade6de9 Updating translations for config/locales/en_GB.yml 2019-08-27 23:25:26 +10:00
Maikel Linke
48df853ff5 Skip cascading callbacks when touching distributors 2019-08-27 10:44:19 +10:00
Maikel Linke
2137a2addb Add spec for current bug
https://github.com/openfoodfoundation/openfoodnetwork/issues/4138
2019-08-27 10:44:19 +10:00
Transifex-Openfoodnetwork
e6a7239716 Updating translations for config/locales/en_AU.yml 2019-08-27 10:09:05 +10:00
Transifex-Openfoodnetwork
25bed92f2e Updating translations for config/locales/en_AU.yml 2019-08-27 10:08:32 +10:00
Maikel
909cd407dd Merge pull request #4149 from openfoodfoundation/transifex
Transifex
2019-08-27 09:58:31 +10:00
Luis Ramos
f2d25748b1 Merge pull request #4078 from HugsDaniel/defacepocalypse-variants
[Defacepocalypse] De-deface variants
2019-08-25 22:51:15 +01:00
Luis Ramos
6396e6e970 Merge pull request #4152 from openfoodfoundation/dependabot/bundler/stripe-4.24.0
Bump stripe from 4.19.0 to 4.24.0
2019-08-25 22:49:47 +01:00
Luis Ramos
e52f813dae Merge pull request #4159 from luisramos0/fix_prod_set
Add bugsnag notifications to both product_set and products_controller when stock update fails
2019-08-25 22:49:06 +01:00
Luis Ramos
9ab2eec30c Merge pull request #4185 from kristinalim/fix/4176-fix_saving_of_shipping_method
4176 Fix saving of shipping method when automatically advancing subscription order state
2019-08-25 22:48:39 +01:00
Luis Ramos
f96b37dae3 Merge pull request #4162 from luisramos0/checkout_cache
Checkout is not refreshing products cache
2019-08-25 21:52:55 +01:00
Kristina Lim
5b68b2f707 Fix ship method when advancing subscription order 2019-08-22 21:32:41 +08:00
Kristina Lim
ff634bd870 Test ship method when advancing subscription order 2019-08-22 21:30:21 +08:00
Hugo Daniel
7d21d88dc9 Force hide the select2 close cross 2019-08-22 10:32:07 +02:00
dependabot-preview[bot]
31b62d6296 Bump delayed_job_active_record from 4.1.3 to 4.1.4
Bumps [delayed_job_active_record](https://github.com/collectiveidea/delayed_job_active_record) from 4.1.3 to 4.1.4.
- [Release notes](https://github.com/collectiveidea/delayed_job_active_record/releases)
- [Commits](https://github.com/collectiveidea/delayed_job_active_record/compare/v4.1.3...v4.1.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-20 19:14:59 +00:00
Transifex-Openfoodnetwork
5e68604f11 Updating translations for config/locales/nb.yml 2019-08-20 17:42:09 +10:00
Transifex-Openfoodnetwork
c4edd3a683 Updating translations for config/locales/fr.yml 2019-08-20 17:41:25 +10:00
Transifex-Openfoodnetwork
574781e901 Updating translations for config/locales/nb.yml 2019-08-20 17:39:01 +10:00
Transifex-Openfoodnetwork
8ea4f933da Updating translations for config/locales/fr.yml 2019-08-20 17:38:12 +10:00
Transifex-Openfoodnetwork
1e9820f291 Updating translations for config/locales/fr.yml 2019-08-20 17:35:05 +10:00
Luis Ramos
34ed86cf2d Merge pull request #4132 from Matt-Yorkley/import_launch
Product Import beta
2019-08-19 17:17:16 +01:00
luisramos0
8a4e5b445f Delete unused frontend auth toekn script override and move the backend one to the head partial 2019-08-18 21:53:56 +01:00
luisramos0
2394eda2ac Remove unused sidebar override 2019-08-18 21:47:21 +01:00
luisramos0
f97a3a030a Remove unused nav_bar sessions route and override 2019-08-18 21:44:22 +01:00
luisramos0
ec645f8fa8 Remove unused login override of nav_bar 2019-08-18 21:43:18 +01:00
luisramos0
56a54db602 Remove admin login_nav override and move it to admin layout file 2019-08-18 21:39:19 +01:00
luisramos0
4c3d15b42b Remove users menu entry override and file and add it directly to the tabs view together with all the other entries 2019-08-18 21:36:50 +01:00
luisramos0
5f4429646d Move override to the view that is now in our code base (from spree_auth_devise originally) 2019-08-18 21:33:23 +01:00
luisramos0
f37db456f8 Delete dead overrides of spree frontend code 2019-08-18 21:32:53 +01:00
Kevin Christianson
2dfcedad56 Add swagger.yaml 2019-08-18 18:26:44 +01:00
Kristina Lim
706168f2f0 Refresh variant cache when changing stock movements 2019-08-18 16:22:12 +08:00
Kristina Lim
3ecb5c0c75 Flush background jobs in failing spec 2019-08-18 18:16:28 +10:00
luisramos0
249a3c4e18 Make product set raise error and inform the user something went wrong and keep bugsnag notification so we can get more information about what's going on 2019-08-17 19:19:46 +01:00
luisramos0
2b8ebba233 Fix some rubocop issues in product_set and admin/products_controller 2019-08-17 19:15:32 +01:00
luisramos0
758394464b Add bugsnag notification to products_controller create and update when on_hand or on_demand update fails with exception 2019-08-17 19:15:32 +01:00
luisramos0
d3c624ae10 Add bugsnag notification to product_set create_variant when on_hand or on_demand update fails with exception 2019-08-17 19:15:31 +01:00
luisramos0
163c65849e Make product set a bit more robust by not failing to update on_hand when variant is not valid. This will make the overall set update work 2019-08-17 19:14:25 +01:00
luisramos0
99ff714913 Enable cache on checkout spec to test cache after checkout 2019-08-16 20:17:14 +01:00
luisramos0
c2f302450f Add spec to checkout to validate product is removed from shopfront just after all available quantity is checked out 2019-08-16 19:35:57 +01:00
luisramos0
9186bcd455 Dry out some code in checkout_spec 2019-08-16 19:35:08 +01:00
Transifex-Openfoodnetwork
3d074b530f Updating translations for config/locales/nb.yml 2019-08-15 19:16:43 +10:00
Transifex-Openfoodnetwork
20783db373 Updating translations for config/locales/en_GB.yml 2019-08-15 19:14:53 +10:00
Luis Ramos
d5b37a5171 Merge pull request #4079 from HugsDaniel/defacepocalypse-payments
[Defacepocalypse] De-deface payments
2019-08-14 19:30:33 +01:00
luisramos0
b9ddb39edc Re-add taxons jstree action to make taxonomies config page work again 2019-08-14 16:31:34 +01:00
Luis Ramos
3efe2f878d Merge pull request #4156 from coopdevs/fix-styling-in-paypal-tests
Fix Rubocop violations in PayPal tests
2019-08-14 15:59:14 +01:00
Luis Ramos
064fee79b3 Merge pull request #4151 from Matt-Yorkley/datadog_apm
Enable (optional) APM with Datadog
2019-08-14 15:58:48 +01:00
Luis Ramos
d13f182801 Merge pull request #4154 from Matt-Yorkley/fix_deployments2
Adjust user creation syntax
2019-08-14 15:56:32 +01:00
Luis Ramos
ee34935223 Fix a typo in docker.md 2019-08-14 13:55:58 +01:00
Pau Perez
0b7ce0d6db Fix Rubocop violations in PayPal tests 2019-08-14 13:33:53 +02:00
Matt-Yorkley
9dd02044a5 Fix "can't modify frozen string" error in validation callbacks 2019-08-14 10:24:30 +01:00
Matt-Yorkley
d8a7190f43 Adjust user creation syntax
#skip_confirmation! can't be chained...
2019-08-14 09:22:11 +01:00
Matt-Yorkley
e5e0fcc887 Enable DelayedJob APM 2019-08-14 08:20:47 +01:00
Pau Pérez Fabregat
53496ff9eb Merge branch 'master' into transifex 2019-08-14 09:08:40 +02:00
Pau Pérez Fabregat
6635a89af7 Merge pull request #4153 from Matt-Yorkley/fix_deployments
Fix deployments
2019-08-14 08:59:23 +02:00
Transifex-Openfoodnetwork
c1248857b8 Updating translations for config/locales/en_CA.yml 2019-08-14 09:15:20 +10:00
Matt-Yorkley
8c95399292 Don't prompt if admin user already exists 2019-08-13 21:02:12 +01:00
Matt-Yorkley
14c1abb861 Skip confirmation email on initial admin user creation 2019-08-13 21:00:30 +01:00
dependabot-preview[bot]
e2d61f5e89 Bump stripe from 4.19.0 to 4.24.0
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 4.19.0 to 4.24.0.
- [Release notes](https://github.com/stripe/stripe-ruby/releases)
- [Changelog](https://github.com/stripe/stripe-ruby/blob/master/CHANGELOG.md)
- [Commits](https://github.com/stripe/stripe-ruby/compare/v4.19.0...v4.24.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-13 19:18:17 +00:00
Transifex-Openfoodnetwork
5a1ef04c67 Updating translations for config/locales/en_ZA.yml 2019-08-14 04:57:27 +10:00
Transifex-Openfoodnetwork
e9e73ef0e4 Updating translations for config/locales/en_ZA.yml 2019-08-14 04:43:50 +10:00
Matt-Yorkley
be844253eb Enable (optional) Rails APM with Datadog 2019-08-13 18:57:49 +01:00
Transifex-Openfoodnetwork
001e3688da Updating translations for config/locales/en_GB.yml 2019-08-14 03:28:13 +10:00
luisramos0
b4ffd4dcc2 Update all locales with the latest Transifex translations 2019-08-13 18:25:23 +01:00
Transifex-Openfoodnetwork
e5a9606449 Updating translations for config/locales/en_GB.yml 2019-08-14 03:25:02 +10:00
Pau Pérez Fabregat
9eabbb8dab Merge pull request #4140 from openfoodfoundation/transifex
Transifex
2019-08-13 12:00:48 +02:00
Hugo Daniel
1217811402 Refactor and remove empty lines 2019-08-13 11:03:04 +02:00
Pau Pérez Fabregat
d4f2fcb98a Merge pull request #4126 from Matt-Yorkley/cart_dropdown
Cart dropdown now closes when clicking outside it.
2019-08-13 10:57:56 +02:00
Matt-Yorkley
0b2417849c Merge pull request #4142 from mkllnk/seed-user
Seed user
2019-08-13 08:42:07 +01:00
Matt-Yorkley
3e8369c8f5 Merge pull request #4123 from Matt-Yorkley/navigation-css
Navigation css
2019-08-13 08:41:47 +01:00
Maikel Linke
cbaedcec92 Fix seeding of default user without asking 2019-08-13 09:47:54 +10:00
Hugo Daniel
bf2c1a0c1d Add ng directive for setting on demand 2019-08-09 14:42:39 +02:00
Matt-Yorkley
0284eebf35 Fix cart dropdown positioning 2019-08-09 11:50:33 +01:00
Maikel Linke
e4ba515109 Seed admin user without asking by default 2019-08-09 14:16:01 +10:00
Maikel Linke
af1f6f6c6d Skip confirmation when creating first admin user 2019-08-09 14:16:01 +10:00
Maikel Linke
b0e8ee42c1 Restore spree_auth_devise user seeding 2019-08-09 13:48:50 +10:00
Maikel
86aeb6a3c7 Merge pull request #4135 from coopdevs/remove-bugherd-tests
Remove bugherd specs
2019-08-09 12:53:23 +10:00
Matt-Yorkley
5d83414e9b Disable rubocop for spree tabs helper 2019-08-08 20:09:35 +01:00
Transifex-Openfoodnetwork
9820d7de38 Updating translations for config/locales/ca.yml 2019-08-09 02:36:02 +10:00
Pau Pérez Fabregat
910eca810a Merge pull request #4124 from Matt-Yorkley/order_email
Add SKU to order confirmation email
2019-08-08 18:35:20 +02:00
Transifex-Openfoodnetwork
6feaddf747 Updating translations for config/locales/es.yml 2019-08-09 02:33:35 +10:00
Transifex-Openfoodnetwork
10f6fb91f6 Updating translations for config/locales/ca.yml 2019-08-09 02:32:54 +10:00
Pau Pérez Fabregat
c7bd4b94b8 Merge pull request #4137 from openfoodfoundation/transifex
Transifex
2019-08-08 18:31:47 +02:00
Transifex-Openfoodnetwork
dd223a21f2 Updating translations for config/locales/nb.yml 2019-08-08 20:58:24 +10:00
Transifex-Openfoodnetwork
549366ff15 Updating translations for config/locales/fr.yml 2019-08-08 20:52:28 +10:00
Transifex-Openfoodnetwork
e92f60fb1c Updating translations for config/locales/fr.yml 2019-08-08 20:49:20 +10:00
Pau Pérez Fabregat
92b05c76a3 Merge pull request #4068 from luisramos0/replace_oc_rabl
Convert order_cycle.rabl to Api::OrderCycleSerializer
2019-08-08 12:23:09 +02:00
Hugo Daniel
fa6fa0be64 Add missing translation 2019-08-08 11:11:32 +02:00
Kristina Lim
752efac7cf Merge pull request #4051 from luisramos0/subs_unpause
Sync subscription (create/update orders) when subscription is unpaused
2019-08-08 01:09:09 +08:00
Pau Perez
2b1f1f748b Remove bugherd specs
I don't think these are worth the time it takes to execute them every
time but most importantly I believe we are not using Bugherd anymore.
2019-08-07 16:49:32 +02:00
Pau Pérez Fabregat
798cd9e778 Merge pull request #4114 from kristinalim/fix/4103-add_specs
4103 Add specs for referencing of shipments to deleted variants
2019-08-07 12:52:11 +02:00
Matt-Yorkley
2f5b0a5afb Remove product import FeatureFlag 2019-08-07 09:59:55 +01:00
Maikel
de2d4a5870 Merge pull request #4125 from Matt-Yorkley/variant_overrides
Variant overrides with on_demand
2019-08-07 10:25:32 +10:00
Matt-Yorkley
b3728568a8 Enable product import for non-superadmin users
This class_eval hack for premissions on the #tab method was really hard to find, and is obviously quite ugly, but refactoring it is maybe outside of the scope here...
2019-08-06 18:59:12 +01:00
Matt-Yorkley
6ba98b4b2c Add beta notice to Product Import 2019-08-06 17:02:38 +01:00
Matt-Yorkley
d3d6921a0f Use light grey colour with transparency. 2019-08-06 08:23:38 +01:00
Maikel
68393f1444 Merge pull request #4037 from luisramos0/subs_stock
Subscriptions - When editing subscriptions, check stock levels when changing orders in current OC
2019-08-06 15:16:00 +10:00
Maikel
229e6fa0a3 Merge pull request #4073 from luisramos0/kill_more_rabl
Replace update_prod_image.rabl with ImageSerializer in api/product_image_controller
2019-08-06 15:00:33 +10:00
Matt-Yorkley
8a069787d1 Cart dropdown now closes when clicking outside it. 2019-08-05 21:48:37 +01:00
Matt-Yorkley
29ed38a6cc Add unit tests for overriding #move 2019-08-05 17:01:56 +01:00
Matt-Yorkley
4c7d3a491a Don't decrement variant stock if override is on_demand 2019-08-05 17:01:56 +01:00
Matt-Yorkley
b0f90cf43c Add test for variant override with :on_demand 2019-08-05 17:01:54 +01:00
Pau Pérez Fabregat
02ec0634b3 Merge pull request #4120 from openfoodfoundation/dependabot/bundler/webmock-3.6.2
Bump webmock from 3.6.0 to 3.6.2
2019-08-05 15:13:31 +02:00
Pau Pérez Fabregat
64d21969f0 Merge pull request #4064 from luisramos0/convert_search_Rabl
Replace views/admin/variants/search.rabl with Api::Admin::VariantSerializer
2019-08-05 15:07:10 +02:00
Pau Pérez Fabregat
0995adeb59 Merge pull request #4085 from openfoodfoundation/dependabot/bundler/devise-encryptable-0.2.0
Bump devise-encryptable from 0.1.2 to 0.2.0
2019-08-05 15:01:46 +02:00
Pau Pérez Fabregat
073a3fe2b4 Merge pull request #4119 from openfoodfoundation/transifex
Transifex
2019-08-05 13:18:12 +02:00
Matt-Yorkley
c07df6a5a6 Fix table column alignments 2019-08-04 20:45:00 +01:00
Matt-Yorkley
a7d109833d Add SKU to order confirmation email 2019-08-04 20:43:55 +01:00
Matt-Yorkley
0364a14073 Add navigation bottom border on mobile view 2019-08-04 16:56:43 +01:00
Matt-Yorkley
ddc8d33356 Update border colour on navigation bar 2019-08-04 16:56:03 +01:00
luisramos0
006c6e6b7b Add comment to explain method in weight calculator 2019-08-02 21:02:33 +01:00
luisramos0
41aa4ff479 Improve code readability and fix rubocop complexity issue in weight calculator 2019-08-02 20:54:41 +01:00
luisramos0
0e8f167ab9 Fix spec in weight calculator tests 2019-08-02 20:44:11 +01:00
Kristina Lim
cd81dfaead Move deleted variant to let block in feature spec 2019-08-02 21:52:36 +08:00
Kristina Lim
25073ada84 Move order to a let block in feature spec 2019-08-02 21:52:33 +08:00
Kristina Lim
15b6f9dd5e Add specs testing edit order page still okay when variant deleted
Note that the wrapping example group also loads the edit order page
before this "before" block. This will be fixed in the next commit.
2019-08-02 21:45:39 +08:00
Kristina Lim
0377e02dc1 Add specs testing that shipments see deleted variants 2019-08-02 21:45:38 +08:00
dependabot-preview[bot]
f679708a4e Bump webmock from 3.6.0 to 3.6.2
Bumps [webmock](https://github.com/bblimke/webmock) from 3.6.0 to 3.6.2.
- [Release notes](https://github.com/bblimke/webmock/releases)
- [Changelog](https://github.com/bblimke/webmock/blob/master/CHANGELOG.md)
- [Commits](https://github.com/bblimke/webmock/compare/v3.6.0...v3.6.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-08-01 19:15:26 +00:00
Transifex-Openfoodnetwork
0f748a3333 Updating translations for config/locales/en_GB.yml 2019-08-02 04:32:50 +10:00
Transifex-Openfoodnetwork
bdedaa06d8 Updating translations for config/locales/en_GB.yml 2019-08-02 04:29:40 +10:00
Pau Pérez Fabregat
6a41d9be87 Merge pull request #4092 from coopdevs/remove-admin-products-N+1
Remove N+1 while fetching distributors of OCs
2019-08-01 19:50:49 +02:00
luisramos0
4aa6c673ff Adapt api products and variants controllers to new namespace outside of Spree 2019-08-01 18:34:19 +01:00
luisramos0
aa3c1aa0fe Remove Spree module declaration from these files as they were moved out of the spree namespace 2019-08-01 14:30:11 +01:00
luisramos0
31bac9641f Move api products and variants routes and ctrl out of spree namespace 2019-08-01 14:28:55 +01:00
Hugo Daniel
60bdde6349 Convert variants/new from erb to haml and import new.js.erb 2019-08-01 11:23:44 +02:00
Hugo Daniel
5faf33fabe Import variants/new.html.erb from spree_backend 2019-08-01 10:50:13 +02:00
Hugo Daniel
f3b1a5dd35 Convert variants/edit from erb to haml 2019-08-01 10:45:04 +02:00
Hugo Daniel
07ccbf7f98 Import variants/edit.html.erb from spree_backend 2019-07-31 16:55:47 +02:00
Hugo Daniel
a3af6617a9 Convert payments/show from erb to haml 2019-07-31 16:20:32 +02:00
Hugo Daniel
9f7fb654c8 Import payments/show.html.erb from spree_backend 2019-07-31 16:16:26 +02:00
Hugo Daniel
b4a6686eac Convert payments/_list from erb to haml 2019-07-31 16:15:38 +02:00
Hugo Daniel
ac13ff114c Import payments/_list.html.erb from spree_backend 2019-07-31 16:09:48 +02:00
Hugo Daniel
af9187947f Convert erb to haml 2019-07-31 16:02:48 +02:00
luisramos0
b7f7038934 Remove api/enterprises rabl template, it was only used as a member in the now removed rabl variants/products templates 2019-07-31 14:36:36 +01:00
Hugo Daniel
f0fdbf7cf4 Import payments/index from spree_backend 2019-07-31 14:33:38 +02:00
Hugo Daniel
74ab31c0e6 Import gateway.html.erb and convert to haml 2019-07-31 14:28:15 +02:00
luisramos0
6c054e6078 Add bulk_products and overridable to skip_authorization_check so these endpoints work with AMS 2019-07-31 12:18:27 +01:00
luisramos0
18974c68e1 Remove orphan price check from price model
This is a quick fix. This check is breaking product deletion in some situations and orphan Prices are not really a problem in the DB
2019-07-31 11:24:55 +01:00
luisramos0
78ab852141 Make spree/api/products_controller work with AMS 2019-07-31 11:23:43 +01:00
luisramos0
4497173213 Adapt spree/api/products_controller_spec to AMS serializer 2019-07-31 11:23:18 +01:00
luisramos0
4d74d246e8 Remove spree/api/products_controller index and new actions, not used 2019-07-31 10:32:45 +01:00
luisramos0
cc51537e93 Convert spree/api/products_controller from rabl to ams 2019-07-31 09:50:34 +01:00
luisramos0
07aececdcf Remove unused route api/products managed 2019-07-31 09:50:31 +01:00
luisramos0
c3fbf9cdf9 Remove unused pagination from index and respective specs, fix spec for search by sku by adding sku to the serializer and adapt a few specs to pass with AMS attrivbutes, 2019-07-31 09:40:19 +01:00
luisramos0
180598c603 Convert spree/api/variants_controller to AMS by changing base_controller, using render json instad of respond with, deleting rabl templates and adapting specs
Delete unused pagination spec
2019-07-31 09:40:19 +01:00
luisramos0
69a5527e24 Update/regenarate .rubocop_todo.yml 2019-07-31 09:36:48 +01:00
luisramos0
e4a6b3880f Fix some more simple rubocop issues 2019-07-31 09:36:48 +01:00
luisramos0
96ce4deb45 Transpec spec/support/api_helper.rb 2019-07-31 09:36:48 +01:00
luisramos0
a3c179bd3f Fix some more simple rubocop issues 2019-07-31 09:36:48 +01:00
luisramos0
a57504ba1f Bring api_helper.image from spree_api to support spree/api/products_controller_spec 2019-07-31 09:36:48 +01:00
luisramos0
25451eed6b Bring api spec helpers from spree_api into ofn/api_helper 2019-07-31 09:36:48 +01:00
luisramos0
50765563f8 Bring spree/api_helpers from spree_api 2019-07-31 09:35:46 +01:00
luisramos0
2ae75ce13e Add ControllerSetup from spree_api as it is used in spree/api/base_controller 2019-07-31 09:35:46 +01:00
luisramos0
18aa16650d Remove dependency to Spree::ApiConfiguration, overall requires_authentication? is true, exceptions will be endpoint specific 2019-07-31 09:35:46 +01:00
luisramos0
314ed50e0f Fix a rubocop issue in spree/api/products_controller 2019-07-31 09:34:20 +01:00
luisramos0
7346a49982 Move routes in ofn api namespace to separate routes file 2019-07-31 09:34:20 +01:00
luisramos0
5182286218 Add necessary spree api routes related to api keys for users and bring respective implementations from spree_api 2019-07-31 09:34:20 +01:00
luisramos0
a267848394 Remove unused api routes from views/spree/admin/shared/routes view 2019-07-31 09:32:33 +01:00
luisramos0
104bd31f9b Add necessary spree api routes: taxons, variants and shipments 2019-07-31 09:32:33 +01:00
luisramos0
8bc9985edb Transpec and fix rubocop issues in spree/api/variants_controller_spec 2019-07-31 09:32:33 +01:00
luisramos0
6dfc927730 Make spree/api/variant_controllers_spec pass 2019-07-31 09:32:33 +01:00
luisramos0
3771e26eba Bring tests from spree/api/variants_controller_spec from spree_api 2019-07-31 09:32:33 +01:00
luisramos0
fd21d35aee Transpec and fix rubocop issues in spree/api/shipments_controller_spec 2019-07-31 09:32:33 +01:00
luisramos0
1417b924d2 Bring and adapt tests from spree/api/shipments_controller_spec and mix them with exiting tests in OFN 2019-07-31 09:32:33 +01:00
luisramos0
2912c1b87d Transpec and fix rubocop issues in spree/api/product_controller_spec 2019-07-31 09:32:33 +01:00
luisramos0
e746a0db7d Bring tests from spree/api/products_controller_spec and add them to existing ones on the ofn side
Adapt these tests to have a green build
2019-07-31 09:32:33 +01:00
luisramos0
84a2886003 Improve auth code in spree/api/taxons_controller_spec 2019-07-31 09:32:33 +01:00
luisramos0
c668677b8a Bring spree/api/taxons_controller_spec from spree_api, adapt it, transpec it and fix rubocop issues 2019-07-31 09:32:33 +01:00
luisramos0
2490cbfccb Transpec and fix rubocop issues in spree/api/base_controller_spec 2019-07-31 09:32:33 +01:00
luisramos0
20a46a791c Bring and adapt spree/api/base_controller_spec from spree_api 2019-07-31 09:32:33 +01:00
luisramos0
0e4fe08ac4 Fix logical problem in spree/api/base_controller and in spree/checkout_controller
See this stack overflow post for more info: https://stackoverflow.com/questions/39629976/ruby-return-vs-and-return
2019-07-31 09:32:33 +01:00
luisramos0
cf0f716534 Fix easy rubocop issues in spree/api/taxons_controller 2019-07-31 09:32:33 +01:00
luisramos0
b70cfa5968 Bring spree/api/taxons controller from spree_api as it is needed in OFN admin 2019-07-31 09:32:33 +01:00
luisramos0
f77beb50ff Fix class scope in spree/api/products_controller, should not use Spree namespace here
Also, add missing dependency to spree/admin/products_controller_decorator
2019-07-31 09:32:33 +01:00
luisramos0
a941280982 Fix easy rubocop issues in spree/api/base_controller 2019-07-31 09:32:33 +01:00
luisramos0
9d40ee49e6 Bring spree/api/base_controller from spree_api 2019-07-31 09:32:33 +01:00
luisramos0
6abbdecb97 Fix the easy rubocop issues in the new spree api controllers 2019-07-31 09:32:33 +01:00
luisramos0
660ce92c27 Merge spree api controllers and its decorators 2019-07-31 09:32:33 +01:00
luisramos0
c5bcef6ae4 Delete unused spree/api/line_items_controller_decorator.rb 2019-07-31 09:32:33 +01:00
luisramos0
d26a0b6b73 Bring from spree_api the api controllers that are overriden in OFN so that we can merge the original and the override afterwards 2019-07-31 09:32:33 +01:00
luisramos0
9400516b56 Fix broken (was always green) bulk_product_update_spec updating image spec where the old src url was not stored and the expect command was wrong with != 2019-07-30 20:37:26 +01:00
luisramos0
6ebfb02d0e Update ImageSerializer with missing image size urls: mini/thumb_url, product/image_url that is used in the product image modal 2019-07-30 20:15:21 +01:00
luisramos0
11a77043eb Switch from Spree::Api::BaseController to Api::BaseController so that AMS is activated 2019-07-30 12:20:14 +01:00
luisramos0
58b43c7bc9 Remove update_product_image.v1.rabl and switch controller from respond_with to render json to switch from rabl to AMS 2019-07-30 12:19:42 +01:00
luisramos0
be41271038 Make spelling coherent, as we have serializers with Z we get rid of the few serialisers with S we have 2019-07-29 19:57:12 +01:00
luisramos0
04e13e1136 Change css styling from id to class to make rubocop happy. Keeping id name as it may be needed in spree autocomplete css or js code 2019-07-29 19:46:12 +01:00
luisramos0
8868b7eb12 Fix rubocop issue: use nested class/module definition 2019-07-29 19:05:39 +01:00
Pau Perez
c85d00fcb8 Remove N+1 while fetching distributors of OCs
What used to be done as

```sql
SELECT "order_cycles".* FROM "order_cycles"
WHERE (order_cycles.orders_open_at <= '2019-07-29 17:45:20.137294'
  AND order_cycles.orders_close_at >= '2019-07-29 17:45:20.137333')

SELECT DISTINCT "enterprises".* FROM "enterprises"
INNER JOIN "exchanges" ON "enterprises"."id" = "exchanges"."receiver_id"
WHERE "exchanges"."order_cycle_id" = 1
  AND "exchanges"."incoming" = 'f'
(...)
SELECT DISTINCT "enterprises".* FROM "enterprises"
INNER JOIN "exchanges" ON "enterprises"."id" = "exchanges"."receiver_id"
WHERE "exchanges"."order_cycle_id" = 4
  AND "exchanges"."incoming" = 'f'
```

it became

```sql
SELECT "order_cycles".* FROM "order_cycles"
WHERE (order_cycles.orders_open_at <= '2019-07-29 17:45:20.137294'
  AND order_cycles.orders_close_at >= '2019-07-29 17:45:20.137333')

SELECT "exchanges".* FROM "exchanges"
WHERE "exchanges"."incoming" = 'f'
  AND "exchanges"."order_cycle_id" IN (1, 2, 3, 4)

SELECT "enterprises".* FROM "enterprises"
WHERE "enterprises"."id" IN (3, 4, 5, 6)
```

I haven't got any perf numbers yet but each of the N+1 queries took as
long as the single `enterprises` query on my dev machine.

This should have a noticeable perf impact since the changed method
belongs to the `BaseController` seems to be executed in all HTML
requests as it gets called by

```ruby
before_filter :warn_invalid_order_cycles, if: :html_request?
```
2019-07-29 20:02:47 +02:00
luisramos0
2c6dab9c85 Add spec for Api::OrderCycleSerializer 2019-07-29 18:56:49 +01:00
luisramos0
c45194473b Add spec to cover inject_current_order_cycle 2019-07-29 18:14:00 +01:00
luisramos0
3c0e6eeee2 Make inject_current_order_cycle render {} instad of null if current_order_cycle is null 2019-07-29 18:13:29 +01:00
luisramos0
ca5a5bf301 Convert oc.rabl to oc serializer and use it in both haml file and controller 2019-07-29 18:13:29 +01:00
dependabot-preview[bot]
8c7a7348f4 Bump devise-encryptable from 0.1.2 to 0.2.0
Bumps [devise-encryptable](https://github.com/plataformatec/devise-encryptable) from 0.1.2 to 0.2.0.
- [Release notes](https://github.com/plataformatec/devise-encryptable/releases)
- [Changelog](https://github.com/plataformatec/devise-encryptable/blob/master/Changelog.md)
- [Commits](https://github.com/plataformatec/devise-encryptable/compare/v0.1.2...v0.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2019-07-26 23:12:41 +00:00
Hugo Daniel
3c2b6f4ed1 Remove data-hooks 2019-07-25 14:38:09 +02:00
Hugo Daniel
ec6f6056a8 Remove data-hooks 2019-07-25 14:34:06 +02:00
Hugo Daniel
c464b21d76 Remove data-hooks 2019-07-25 14:27:53 +02:00
Hugo Daniel
c83d249147 Impor missing partials from spree to ofn and convert to haml 2019-07-25 14:23:24 +02:00
Hugo Daniel
aae5ae9f1e De-deface payments/new 2019-07-25 13:27:41 +02:00
Hugo Daniel
888e0e0bb4 Convert erb partials to haml 2019-07-25 13:22:55 +02:00
Hugo Daniel
a0b0fb05a6 Import payments/new from spree_backend to ofn 2019-07-25 13:22:32 +02:00
Hugo Daniel
a11562e4dd Fix incorrect indentation in variants table 2019-07-25 12:05:50 +02:00
Hugo Daniel
2d872c25bf Use Haml javascript tag to make autocomplete work 2019-07-25 11:20:51 +02:00
Hugo Daniel
986837d601 Import variants/_form.html.erb from spree_backend to ofn and de-deface it 2019-07-25 11:07:35 +02:00
Hugo Daniel
353d6fbc5f Import variants/index from spree_backend to ofn and convert to Haml 2019-07-24 16:57:11 +02:00
Hugo Daniel
0a88738faa Replace old ruby syntax with new 2019-07-24 14:37:00 +02:00
Hugo Daniel
4d6af57f79 De-deface product_properties/index 2019-07-24 13:17:45 +02:00
Hugo Daniel
110fd3ecdf Convert erb to haml 2019-07-24 13:12:58 +02:00
Hugo Daniel
1cb065f829 Import product_properties/index.html.erb from spree_backend to ofn 2019-07-24 13:09:04 +02:00
Hugo Daniel
1cfa499b0e De-deface _product_propery_fields 2019-07-24 13:01:50 +02:00
Hugo Daniel
3fc0d4a666 Convert _product_properties_fields from ERB to Haml 2019-07-24 12:40:24 +02:00
Hugo Daniel
de6c96d138 Import product_properties/_product_properties_fields.html.erb from Spree to OFN 2019-07-24 12:38:29 +02:00
luisramos0
ffb8edef0b Fix rubocop css issues 2019-07-23 22:37:10 +01:00
luisramos0
7a8b5e89be Add specs to cover the most important new fields in api/admin/variant_serializer 2019-07-23 22:11:00 +01:00
luisramos0
90690cd238 Move api/admin/variant_serializer_spec to the correct folder under /spec 2019-07-23 22:03:40 +01:00
luisramos0
90c621ac07 Improve translations, css and add button aligment in subscriptions_line_items variant autocomplete 2019-07-23 21:38:29 +01:00
luisramos0
2d5eccbf97 Add :in_stock, :stock_location_id, :stock_location_name to admin variant serializer, these are needed for the variant_autocomplete js code from spree 2019-07-23 21:38:29 +01:00
luisramos0
7e6259da31 Replace admin/variants/search rabl template with existing admin variant serializer with a few added attributes
This commit fixes a bug as the image of the variatn was not being rendered, we need to fetch the image of the product, not the image of the variant.
2019-07-23 21:37:45 +01:00
luisramos0
11974689ef Remove dead code under views/spree/shared 2019-07-23 16:42:00 +01:00
Kristina Lim
e1fce8304d Update weight calculator and add specs 2019-07-23 23:24:00 +08:00
Kristina Lim
0d6ba90ea1 Round off fee from Calculator::Weight to nearest cent 2019-07-24 00:42:42 +10:00
luisramos0
5739a82c19 Remove unused admin variants search rabl template 2019-07-23 12:30:00 +01:00
luisramos0
3d6fd10e59 Add warning about creation of orders when unpausing a subscription 2019-07-17 12:14:36 +01:00
luisramos0
81482683cf Extract method in subs controller 2019-07-17 12:08:51 +01:00
luisramos0
57f1742f24 Save subscription form on subs unpause so that proxy orders and orders are synced 2019-07-17 12:08:48 +01:00
luisramos0
3b467dbae8 Adapt line_item_syncer to the case where item is not added to the completed order because of insufficient stock and the subscription quantity is updated for that item afterwards 2019-07-16 12:08:08 +01:00
luisramos0
306390440a Revert "Swith line_item_syncer.create_new_items from deleting line item in the case of stock issue, to simply set the quantity to zero. This makes things easier later as the line item is already present if the user tries to change quantity of the subscription_line_item"
This reverts commit d153e58933.
2019-07-16 11:00:21 +01:00
luisramos0
267131626e Fix typo and add test case to cover out of stock case 2019-07-16 10:58:25 +01:00
luisramos0
02099ebdae Remove details about stock in line_item_syncer so that we avoid confusing the user with stock numbers, this way the user will know what is the problem and can check stock levels and the order for more details 2019-07-14 21:40:57 +01:00
luisramos0
d153e58933 Swith line_item_syncer.create_new_items from deleting line item in the case of stock issue, to simply set the quantity to zero. This makes things easier later as the line item is already present if the user tries to change quantity of the subscription_line_item 2019-07-14 20:59:42 +01:00
luisramos0
c2a59a374c Fix rubocop issues by simplifying method 2019-07-14 17:21:15 +01:00
luisramos0
2a1011921b Reuse line_item_syncer.add_order_update_issue in line_item_syncer.update_item_quantities to add stock info to the update_quantity order issues 2019-07-14 16:43:46 +01:00
luisramos0
df27ee0d3e Refactor line_item_syncer.add_order_update_issue out of line_item_syncer.create_new_items 2019-07-14 16:06:09 +01:00
luisramos0
c2851015ce Fix deleting created item (destroy doesnt work before save) and add order_update_issue with message so that user can understand what happened 2019-07-14 15:58:00 +01:00
luisramos0
d0c246c345 Fix some rubocop issues 2019-07-14 12:28:32 +01:00
luisramos0
6aed9ba549 Make line_item_syncer delete new line items if stock is insufficient 2019-07-13 22:57:13 +01:00
luisramos0
4f2bc33ec3 Change line_item_syncer to verify stock if order is already complete, this will happen for orders in the current OC when a subscription is changed 2019-07-13 20:56:34 +01:00
luisramos0
0f3404ca27 Rename order_syncer.future_and_undated_orders to explicitly include completed orders from current OC: orders_in_order_cycles_not_closed 2019-07-12 22:20:09 +01:00
Jon Leighton
4398ea12b8 Convert several fields from string to text
See discussion here:
https://github.com/openfoodfoundation/openfoodnetwork/pull/3751#issuecomment-503416955

Fixes #3192.

I have also done a pass over the schema to identify other fields which
would benefit from being a text rather than a string. However, I ignored
all `spree_*` tables because I didn’t want to mess up the ‘default’
Spree schema.
2019-07-09 13:11:30 +10:00
luisramos0
160b535e2f Make weight calculator compute 0 for variants with unit different from weight 2019-06-18 15:21:13 +01:00
luisramos0
e8eeb3d5dc Further improve weight calculator code 2019-06-18 13:28:16 +01:00
luisramos0
4551149532 Improve code of weight calculator 2019-05-31 19:55:39 +01:00
luisramos0
82955b9fe5 Make weight calculator use line_item.final_weight_volume rather than variant.weight for cases where the final weight is set manually in the BOM 2019-05-31 19:55:17 +01:00
290 changed files with 13121 additions and 2994 deletions

View File

@@ -49,7 +49,6 @@ Metrics/LineLength:
- app/controllers/spree/admin/orders_controller_decorator.rb
- app/controllers/spree/admin/payments_controller_decorator.rb
- app/controllers/spree/admin/payment_methods_controller_decorator.rb
- app/controllers/spree/admin/products_controller_decorator.rb
- app/controllers/spree/admin/reports_controller_decorator.rb
- app/controllers/spree/api/products_controller_decorator.rb
- app/controllers/spree/credit_cards_controller.rb
@@ -123,14 +122,11 @@ Metrics/LineLength:
- app/serializers/api/admin/subscription_serializer.rb
- app/serializers/api/admin/tag_rule_serializer.rb
- app/serializers/api/admin/variant_override_serializer.rb
- app/serializers/api/admin/variant_serializer.rb
- app/services/cart_service.rb
- app/services/default_stock_location.rb
- app/services/embedded_page_service.rb
- app/services/line_item_syncer.rb
- app/services/order_cycle_form.rb
- app/services/order_factory.rb
- app/services/order_syncer.rb
- app/services/subscriptions_count.rb
- app/services/variants_stock_levels.rb
- app/views/json/_groups.rabl
@@ -157,7 +153,6 @@ Metrics/LineLength:
- lib/open_food_network/permalink_generator.rb
- lib/open_food_network/products_cache.rb
- lib/open_food_network/products_renderer.rb
- lib/open_food_network/proxy_order_syncer.rb
- lib/open_food_network/reports/bulk_coop_allocation_report.rb
- lib/open_food_network/reports/line_items.rb
- lib/open_food_network/sales_tax_report.rb
@@ -344,11 +339,8 @@ Metrics/LineLength:
- spec/models/tag_rule/filter_shipping_methods_spec.rb
- spec/models/variant_override_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
- spec/requests/checkout/stripe_connect_spec.rb
- spec/requests/embedded_shopfronts_headers_spec.rb
- spec/requests/shop_spec.rb
- spec/serializers/admin/customer_serializer_spec.rb
@@ -443,7 +435,6 @@ Metrics/AbcSize:
- app/models/spree/order_decorator.rb
- app/models/spree/payment_decorator.rb
- app/models/spree/product_decorator.rb
- app/models/spree/product_set.rb
- app/models/spree/taxon_decorator.rb
- app/serializers/api/admin/enterprise_serializer.rb
- app/serializers/api/product_serializer.rb
@@ -490,63 +481,26 @@ Metrics/AbcSize:
Metrics/BlockLength:
Max: 25
ExcludedMethods: ["class_eval", "collection", "context", "describe", "it", "member", "namespace", "resource", "resources"]
ExcludedMethods: [
"class_eval",
"collection",
"context",
"describe",
"feature",
"it",
"member",
"namespace",
"resource",
"resources",
"scenario"
]
Exclude:
- lib/tasks/data.rake
- lib/tasks/dev.rake
- spec/controllers/spree/admin/invoices_controller_spec.rb
- spec/factories/variant_factory.rb
- spec/features/admin/adjustments_spec.rb
- spec/features/admin/bulk_order_management_spec.rb
- spec/features/admin/bulk_product_update_spec.rb
- spec/features/admin/caching_spec.rb
- spec/features/admin/content_spec.rb
- spec/features/admin/customers_spec.rb
- spec/features/admin/enterprise_fees_spec.rb
- spec/features/admin/enterprise_groups_spec.rb
- spec/features/admin/enterprise_relationships_spec.rb
- spec/features/admin/enterprise_roles_spec.rb
- spec/features/admin/enterprises/images_spec.rb
- spec/features/admin/enterprises/index_spec.rb
- spec/features/admin/enterprises_spec.rb
- spec/features/admin/enterprise_user_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
- spec/features/admin/products_spec.rb
- spec/features/admin/reports/enterprise_fee_summaries_spec.rb
- spec/features/admin/reports_spec.rb
- spec/features/admin/schedules_spec.rb
- spec/features/admin/shipping_methods_spec.rb
- spec/features/admin/subscriptions_spec.rb
- spec/features/admin/tag_rules_spec.rb
- spec/features/admin/tax_settings_spec.rb
- spec/features/admin/users_spec.rb
- spec/features/admin/variant_overrides_spec.rb
- spec/features/admin/variants_spec.rb
- spec/features/consumer/account/cards_spec.rb
- spec/features/consumer/account/settings_spec.rb
- spec/features/consumer/account_spec.rb
- spec/features/consumer/authentication_spec.rb
- spec/features/consumer/cookies_spec.rb
- spec/features/consumer/external_services_spec.rb
- spec/features/consumer/groups_spec.rb
- spec/features/consumer/multilingual_spec.rb
- spec/features/consumer/producers_spec.rb
- spec/features/consumer/registration_spec.rb
- spec/features/consumer/shopping/cart_spec.rb
- spec/features/consumer/shopping/checkout_auth_spec.rb
- spec/features/consumer/shopping/checkout_spec.rb
- spec/features/consumer/shopping/embedded_groups_spec.rb
- spec/features/consumer/shopping/embedded_shopfronts_spec.rb
- spec/features/consumer/shopping/orders_spec.rb
- spec/features/consumer/shopping/products_spec.rb
- spec/features/consumer/shopping/shopping_spec.rb
- spec/features/consumer/shopping/variant_overrides_spec.rb
- spec/features/consumer/shops_spec.rb
- spec/lib/open_food_network/group_buy_report_spec.rb
- spec/models/tag_rule/discount_order_spec.rb
- spec/spec_helper.rb
@@ -565,6 +519,7 @@ Metrics/CyclomaticComplexity:
- app/helpers/checkout_helper.rb
- app/helpers/i18n_helper.rb
- app/helpers/order_cycles_helper.rb
- app/helpers/spree/admin/navigation_helper_decorator.rb
- app/models/enterprise.rb
- app/models/enterprise_relationship.rb
- app/models/product_import/entry_processor.rb
@@ -572,7 +527,6 @@ Metrics/CyclomaticComplexity:
- app/models/spree/ability_decorator.rb
- app/models/spree/payment_decorator.rb
- app/models/spree/product_decorator.rb
- app/models/spree/product_set.rb
- app/models/variant_override_set.rb
- app/services/cart_service.rb
- lib/discourse/single_sign_on.rb
@@ -600,7 +554,6 @@ Metrics/PerceivedComplexity:
- app/models/spree/ability_decorator.rb
- app/models/spree/order_decorator.rb
- app/models/spree/product_decorator.rb
- app/models/spree/product_set.rb
- lib/discourse/single_sign_on.rb
- lib/open_food_network/bulk_coop_report.rb
- lib/open_food_network/enterprise_issue_validator.rb
@@ -656,7 +609,6 @@ Metrics/MethodLength:
- app/models/spree/payment_decorator.rb
- app/models/spree/payment_method_decorator.rb
- app/models/spree/product_decorator.rb
- app/models/spree/product_set.rb
- app/serializers/api/admin/order_cycle_serializer.rb
- app/serializers/api/cached_enterprise_serializer.rb
- app/services/order_cycle_form.rb

View File

@@ -186,7 +186,19 @@ Metrics/AbcSize:
Metrics/BlockLength:
Max: 25
ExcludedMethods: ["class_eval", "collection", "context", "describe", "it", "member", "namespace", "resource", "resources"]
ExcludedMethods: [
"class_eval",
"collection",
"context",
"describe",
"feature",
"it",
"member",
"namespace",
"resource",
"resources",
"scenario"
]
Metrics/BlockNesting:
Max: 3

View File

@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config --exclude-limit 1400`
# on 2019-05-28 16:29:07 +0100 using RuboCop version 0.57.2.
# on 2019-07-23 14:09:18 +0100 using RuboCop version 0.57.2.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@@ -32,15 +32,6 @@ Layout/EndAlignment:
Layout/IndentHash:
EnforcedStyle: consistent
# Offense count: 7
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: aligned, indented, indented_relative_to_receiver
Layout/MultilineMethodCallIndentation:
Exclude:
- 'app/models/spree/line_item_decorator.rb'
- 'app/models/spree/product_decorator.rb'
# Offense count: 4
Lint/AmbiguousOperator:
Exclude:
@@ -55,7 +46,7 @@ Lint/DuplicateMethods:
- 'lib/discourse/single_sign_on.rb'
- 'lib/open_food_network/subscription_summary.rb'
# Offense count: 15
# Offense count: 8
Lint/IneffectiveAccessModifier:
Exclude:
- 'app/models/column_preference.rb'
@@ -79,7 +70,13 @@ Lint/UnderscorePrefixedVariableName:
Exclude:
- 'spec/support/cancan_helper.rb'
# Offense count: 6
# Offense count: 1
# Cop supports --auto-correct.
Lint/UnneededCopDisableDirective:
Exclude:
- 'app/models/product_import/entry_validator.rb'
# Offense count: 5
# Configuration parameters: ContextCreatingMethods, MethodCreatingMethods.
Lint/UselessAccessModifier:
Exclude:
@@ -89,28 +86,47 @@ Lint/UselessAccessModifier:
- 'lib/open_food_network/reports/bulk_coop_report.rb'
- 'spec/lib/open_food_network/reports/report_spec.rb'
# Offense count: 91
# Offense count: 8
# Configuration parameters: CheckForMethodsWithNoSideEffects.
Lint/Void:
Exclude:
- 'app/serializers/api/enterprise_serializer.rb'
- 'spec/features/admin/bulk_product_update_spec.rb'
- 'spec/features/admin/enterprise_groups_spec.rb'
- 'spec/features/admin/enterprises/index_spec.rb'
- 'spec/features/admin/enterprises_spec.rb'
- 'spec/features/admin/order_cycles_spec.rb'
- 'spec/features/admin/payment_method_spec.rb'
- 'spec/features/admin/products_spec.rb'
- 'spec/features/admin/variant_overrides_spec.rb'
- 'spec/features/admin/variants_spec.rb'
- 'spec/features/consumer/shopping/checkout_spec.rb'
- 'spec/features/consumer/shopping/shopping_spec.rb'
- 'spec/features/consumer/shopping/variant_overrides_spec.rb'
# Offense count: 109
# Offense count: 15
Metrics/AbcSize:
Max: 36
# Offense count: 13
# Configuration parameters: CountComments, ExcludedMethods.
Metrics/BlockLength:
Max: 774
Max: 115
# Offense count: 2
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 169
# Offense count: 1
Metrics/CyclomaticComplexity:
Max: 8
# Offense count: 8
# Configuration parameters: CountComments.
Metrics/MethodLength:
Max: 31
# Offense count: 2
# Configuration parameters: CountComments.
Metrics/ModuleLength:
Max: 208
# Offense count: 2
Metrics/PerceivedComplexity:
Max: 11
# Offense count: 7
Naming/AccessorMethodName:
@@ -160,7 +176,7 @@ Naming/PredicateName:
- 'lib/open_food_network/packing_report.rb'
- 'lib/tasks/data.rake'
# Offense count: 12
# Offense count: 11
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
# AllowedNames: io, id, to, by, on, in, at
Naming/UncommunicativeMethodParamName:
@@ -288,13 +304,12 @@ Style/CaseEquality:
- 'app/helpers/angular_form_helper.rb'
- 'spec/models/spree/payment_spec.rb'
# Offense count: 79
# Offense count: 78
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, EnforcedStyle.
# SupportedStyles: nested, compact
Style/ClassAndModuleChildren:
Exclude:
- 'app/controllers/spree/store_controller_decorator.rb'
- 'app/helpers/angular_form_helper.rb'
- 'app/models/calculator/flat_percent_per_item.rb'
- 'app/models/spree/concerns/payment_method_distributors.rb'
@@ -379,11 +394,27 @@ Style/CommentedKeyword:
Exclude:
- 'app/controllers/application_controller.rb'
# Offense count: 4
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions.
# SupportedStyles: assign_to_condition, assign_inside_condition
Style/ConditionalAssignment:
Exclude:
- 'app/controllers/spree/api/products_controller.rb'
- 'app/controllers/spree/api/taxons_controller.rb'
- 'app/controllers/spree/api/variants_controller.rb'
# Offense count: 2
Style/DateTime:
Exclude:
- 'lib/open_food_network/users_and_enterprises_report.rb'
# Offense count: 1
# Cop supports --auto-correct.
Style/EachWithObject:
Exclude:
- 'app/controllers/spree/api/base_controller.rb'
# Offense count: 5
# Configuration parameters: EnforcedStyle.
# SupportedStyles: annotated, template, unannotated
@@ -393,7 +424,7 @@ Style/FormatStringToken:
- 'lib/open_food_network/sales_tax_report.rb'
- 'spec/models/enterprise_spec.rb'
# Offense count: 69
# Offense count: 68
# Configuration parameters: MinBodyLength.
Style/GuardClause:
Exclude:
@@ -410,7 +441,9 @@ Style/GuardClause:
- 'app/controllers/spree/admin/products_controller_decorator.rb'
- 'app/controllers/spree/admin/resource_controller_decorator.rb'
- 'app/controllers/spree/admin/variants_controller_decorator.rb'
- 'app/controllers/spree/orders_controller_decorator.rb'
- 'app/controllers/spree/api/base_controller.rb'
- 'app/controllers/spree/checkout_controller.rb'
- 'app/controllers/spree/orders_controller.rb'
- 'app/controllers/spree/paypal_controller_decorator.rb'
- 'app/jobs/products_cache_integrity_checker_job.rb'
- 'app/models/enterprise.rb'
@@ -434,12 +467,23 @@ Style/GuardClause:
- 'spec/support/request/distribution_helper.rb'
- 'spec/support/request/shop_workflow.rb'
# Offense count: 3
# Offense count: 6
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
Style/HashSyntax:
Exclude:
- 'app/controllers/spree/api/base_controller.rb'
- 'app/controllers/spree/checkout_controller.rb'
- 'app/controllers/spree/orders_controller.rb'
# Offense count: 4
Style/IfInsideElse:
Exclude:
- 'app/controllers/admin/column_preferences_controller.rb'
- 'app/controllers/admin/variant_overrides_controller.rb'
- 'app/controllers/spree/admin/products_controller_decorator.rb'
- 'app/controllers/spree/api/taxons_controller.rb'
# Offense count: 1
Style/MissingRespondToMissing:
@@ -492,9 +536,10 @@ Style/RegexpLiteral:
- 'spec/mailers/subscription_mailer_spec.rb'
- 'spec/models/content_configuration_spec.rb'
# Offense count: 243
# Offense count: 244
Style/Send:
Exclude:
- 'app/controllers/spree/checkout_controller.rb'
- 'app/models/spree/shipping_method_decorator.rb'
- 'spec/controllers/admin/subscriptions_controller_spec.rb'
- 'spec/controllers/checkout_controller_spec.rb'
@@ -541,3 +586,9 @@ Style/Send:
Style/StructInheritance:
Exclude:
- 'lib/open_food_network/enterprise_fee_applicator.rb'
# Offense count: 1
# Cop supports --auto-correct.
Style/UnlessElse:
Exclude:
- 'app/controllers/spree/api/variants_controller.rb'

View File

@@ -1 +1 @@
2.1.5
2.1.9

View File

@@ -42,6 +42,6 @@ $ docker-compose up
```
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`.
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.

22
Gemfile
View File

@@ -1,5 +1,5 @@
source 'https://rubygems.org'
ruby "2.1.5"
ruby "2.1.9"
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
gem 'i18n', '~> 0.6.11'
@@ -37,7 +37,7 @@ gem 'stripe'
gem 'activemerchant', '~> 1.78'
gem 'devise', '~> 2.2.5'
gem 'devise-encryptable', '0.1.2'
gem 'devise-encryptable', '0.2.0'
gem 'jwt', '~> 2.2'
gem 'oauth2', '~> 1.4.1' # Used for Stripe Connect
@@ -49,6 +49,10 @@ gem 'delayed_job_web'
# 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'
gem 'andand'
gem 'angularjs-rails', '1.5.5'
gem 'aws-sdk'
@@ -81,7 +85,6 @@ gem 'paperclip', '~> 3.4.1'
gem 'rack-rewrite'
gem 'rack-ssl', require: 'rack/ssl'
gem 'roadie-rails', '~> 1.1.1'
gem 'skylight', '< 2.0'
gem 'spinjs-rails'
gem 'combine_pdf'
@@ -101,7 +104,10 @@ group :assets do
gem 'coffee-rails', '~> 3.2.1'
gem 'compass-rails'
gem 'therubyracer', '=0.12.0'
gem 'mini_racer', '0.1.15'
# Previously we found that libv8 6.7.288.46.1 breakis the compilation of mini_racer.
# Now we see that we need to set the version explicitly. Nothing else depends on libv8.
gem 'libv8', '6.3.292.48.1'
gem 'uglifier', '>= 1.0.3'
@@ -119,6 +125,10 @@ gem 'jquery-rails', '3.0.4'
gem 'ofn-qz', github: 'openfoodfoundation/ofn-qz', ref: '60da2ae4c44cbb4c8d602f59fb5fff8d0f21db3c'
group :production, :staging do
gem 'ddtrace'
end
group :test, :development do
# Pretty printed test output
gem 'atomic'
@@ -149,10 +159,6 @@ end
group :development do
gem 'byebug', '~> 9.0.0' # 9.1 requires ruby 2.2
gem 'debugger-linecache'
gem 'guard'
gem 'guard-livereload'
gem 'guard-rails'
gem 'guard-rspec', '~> 4.7.3'
gem 'listen', '3.0.8' # 3.1.0 requires ruby 2.2
gem "newrelic_rpm", "~> 3.0"
gem 'pry-byebug', '>= 3.4.3'

View File

@@ -141,8 +141,8 @@ GEM
activerecord (>= 3.2, < 5)
acts_as_list (0.2.0)
activerecord (>= 3.0)
addressable (2.6.0)
public_suffix (>= 2.0.2, < 4.0)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
andand (1.3.3)
angular-rails-templates (0.3.0)
railties (>= 3.1)
@@ -164,7 +164,7 @@ GEM
bcrypt-ruby (3.1.5)
bcrypt (>= 3.1.3)
blockenspiel (0.5.0)
bugsnag (6.11.1)
bugsnag (6.12.1)
concurrent-ruby (~> 1.0)
builder (3.0.4)
byebug (9.0.6)
@@ -210,7 +210,7 @@ GEM
compass (~> 1.0.0)
sass-rails (< 5.1)
sprockets (< 4.0)
concurrent-ruby (1.1.4)
concurrent-ruby (1.1.5)
connection_pool (2.2.2)
crack (0.4.3)
safe_yaml (~> 1.0.0)
@@ -223,16 +223,18 @@ GEM
activerecord (>= 3.2.0, < 5.0)
fog (~> 1.0)
rails (>= 3.2.0, < 5.0)
ddtrace (0.27.0)
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.5)
activesupport (>= 3.0, < 5.3)
delayed_job_active_record (4.1.3)
activerecord (>= 3.0, < 5.3)
delayed_job (4.1.8)
activesupport (>= 3.0, < 6.1)
delayed_job_active_record (4.1.4)
activerecord (>= 3.0, < 6.1)
delayed_job (>= 3.0, < 5)
delayed_job_web (1.4.3)
activerecord (> 3.0.0)
@@ -244,15 +246,12 @@ GEM
orm_adapter (~> 0.1)
railties (~> 3.1)
warden (~> 1.2.1)
devise-encryptable (0.1.2)
devise-encryptable (0.2.0)
devise (>= 2.1.0)
diff-lcs (1.3)
diffy (3.3.0)
docile (1.3.2)
dry-inflector (0.1.2)
em-websocket (0.5.1)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
erubis (2.7.0)
eventmachine (1.2.7)
excon (0.62.0)
@@ -430,34 +429,11 @@ GEM
ruby-progressbar (~> 1.4)
geocoder (1.1.8)
gmaps4rails (1.5.6)
guard (2.15.0)
formatador (>= 0.2.4)
listen (>= 2.7, < 4.0)
lumberjack (>= 1.0.12, < 2.0)
nenv (~> 0.1)
notiffany (~> 0.0)
pry (>= 0.9.12)
shellany (~> 0.0)
thor (>= 0.18.1)
guard-compat (1.2.1)
guard-livereload (2.5.2)
em-websocket (~> 0.5)
guard (~> 2.8)
guard-compat (~> 1.0)
multi_json (~> 1.8)
guard-rails (0.7.2)
guard (~> 2.11)
guard-compat (~> 1.0)
guard-rspec (4.7.3)
guard (~> 2.1)
guard-compat (~> 1.1)
rspec (>= 2.99.0, < 4.0)
haml (4.0.7)
tilt
hashdiff (0.4.0)
hashdiff (1.0.0)
highline (1.6.18)
hike (1.2.3)
http_parser.rb (0.6.0)
httparty (0.16.2)
multi_xml (>= 0.5.2)
i18n (0.6.11)
@@ -483,17 +459,16 @@ GEM
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
kgio (2.11.2)
knapsack (1.17.2)
knapsack (1.18.0)
rake
launchy (2.4.3)
addressable (~> 2.3)
letter_opener (1.7.0)
launchy (~> 2.2)
libv8 (3.16.14.19)
libv8 (6.3.292.48.1)
listen (3.0.8)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
lumberjack (1.0.13)
mail (2.5.5)
mime-types (~> 1.16)
treetop (~> 1.4.8)
@@ -501,22 +476,21 @@ GEM
mime-types (1.25.1)
mini_mime (1.0.1)
mini_portile2 (2.1.0)
mini_racer (0.1.15)
libv8 (~> 6.3)
momentjs-rails (2.20.1)
railties (>= 3.1)
money (5.1.1)
i18n (~> 0.6.0)
msgpack (1.3.1)
multi_json (1.13.1)
multi_xml (0.6.0)
multipart-post (2.1.1)
nenv (0.3.0)
net-http-persistent (3.0.1)
net-http-persistent (3.1.0)
connection_pool (~> 2.2)
newrelic_rpm (3.18.1.330)
nokogiri (1.6.8.1)
mini_portile2 (~> 2.1.0)
notiffany (0.1.1)
nenv (~> 0.1)
shellany (~> 0.0)
oauth2 (1.4.1)
faraday (>= 0.8, < 0.16.0)
jwt (>= 1.0, < 3.0)
@@ -555,7 +529,7 @@ GEM
pry-byebug (3.4.3)
byebug (>= 9.0, < 9.1)
pry (~> 0.10)
public_suffix (3.0.3)
public_suffix (3.1.1)
rabl (0.8.4)
activesupport (>= 2.3.14)
rack (1.4.7)
@@ -591,7 +565,7 @@ GEM
thor (>= 0.14.6, < 2.0)
rainbow (3.0.0)
raindrops (0.19.0)
rake (12.3.2)
rake (12.3.3)
ransack (0.7.2)
actionpack (~> 3.0)
activerecord (~> 3.0)
@@ -607,7 +581,6 @@ GEM
rdoc (3.12.2)
json (~> 1.4)
redcarpet (3.5.0)
ref (2.0.0)
request_store (1.4.1)
rack (>= 1.4)
roadie (3.4.0)
@@ -670,10 +643,9 @@ GEM
selenium-webdriver (3.141.0)
childprocess (~> 0.5)
rubyzip (~> 1.2, >= 1.2.2)
shellany (0.0.1)
shoulda-matchers (2.8.0)
activesupport (>= 3.0.0)
simplecov (0.17.0)
simplecov (0.17.1)
docile (~> 1.1)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
@@ -682,8 +654,6 @@ GEM
rack (~> 1.4)
rack-protection (~> 1.4)
tilt (>= 1.3, < 3)
skylight (1.7.2)
activesupport (>= 3.0.0)
spinjs-rails (1.4)
rails (>= 3.1)
spreadsheet (1.1.7)
@@ -698,12 +668,9 @@ GEM
tilt (~> 1.1, != 1.3.0)
state_machine (1.2.0)
stringex (1.5.1)
stripe (4.19.0)
stripe (4.24.0)
faraday (~> 0.13)
net-http-persistent (~> 3.0)
therubyracer (0.12.0)
libv8 (~> 3.16.14.0)
ref
thor (0.20.3)
tilt (1.4.1)
timecop (0.9.1)
@@ -736,7 +703,7 @@ GEM
nokogiri (~> 1.6)
rubyzip (~> 1.0)
selenium-webdriver (~> 3.0)
webmock (3.6.0)
webmock (3.7.5)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
@@ -775,12 +742,13 @@ DEPENDENCIES
dalli
database_cleaner (= 0.7.1)
db2fog
ddtrace
debugger-linecache
deface (= 1.0.2)
delayed_job_active_record
delayed_job_web
devise (~> 2.2.5)
devise-encryptable (= 0.1.2)
devise-encryptable (= 0.2.0)
diffy
eventmachine (>= 1.2.3)
factory_bot_rails
@@ -792,10 +760,6 @@ DEPENDENCIES
fuubar (~> 2.4.1)
geocoder
gmaps4rails
guard
guard-livereload
guard-rails
guard-rspec (~> 4.7.3)
haml
i18n (~> 0.6.11)
i18n-js (~> 3.3.0)
@@ -804,9 +768,12 @@ DEPENDENCIES
jquery-rails (= 3.0.4)
json_spec (~> 1.1.4)
jwt (~> 2.2)
kaminari (~> 0.14.1)
knapsack
letter_opener (>= 1.4.1)
libv8 (= 6.3.292.48.1)
listen (= 3.0.8)
mini_racer (= 0.1.15)
momentjs-rails
newrelic_rpm (~> 3.0)
nokogiri (>= 1.6.7.1)
@@ -838,7 +805,6 @@ DEPENDENCIES
shoulda-matchers
simple_form!
simplecov
skylight (< 2.0)
spinjs-rails
spree_api!
spree_backend!
@@ -848,7 +814,6 @@ DEPENDENCIES
spring (= 1.7.2)
spring-commands-rspec
stripe
therubyracer (= 0.12.0)
timecop
truncate_html
turbo-sprockets-rails3
@@ -863,7 +828,7 @@ DEPENDENCIES
wkhtmltopdf-binary
RUBY VERSION
ruby 2.1.5p273
ruby 2.1.9p490
BUNDLED WITH
1.17.2

View File

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

View File

@@ -1,6 +1,5 @@
[![Build Status](https://semaphoreci.com/api/v1/openfoodfoundation/openfoodnetwork-2/branches/master/badge.svg)](https://semaphoreci.com/openfoodfoundation/openfoodnetwork-2)
[![Code Climate](https://codeclimate.com/github/openfoodfoundation/openfoodnetwork.png)](https://codeclimate.com/github/openfoodfoundation/openfoodnetwork)
[![View performance data on Skylight](https://badges.skylight.io/status/EiXQ6sSKij8y.svg)](https://oss.skylight.io/app/applications/EiXQ6sSKij8y)
# Open Food Network
@@ -36,7 +35,7 @@ We use [BrowserStack](https://www.browserstack.com/) as a manual testing tool. B
Copyright (c) 2012 - 2019 Open Food Foundation, released under the AGPL licence.
[survey]: https://docs.google.com/a/eaterprises.com.au/forms/d/1zxR5vSiU9CigJ9cEaC8-eJLgYid8CR8er7PPH9Mc-30/edit#
[slack-invite]: https://openfoodnetwork.org/slack-invite
[slack-invite]: https://join.slack.com/t/openfoodnetwork/shared_invite/enQtMzU2Mjk5MDc2MjA5LTM4ZTAzZjIwNzIxMmU5ODFiNWY1MTU2ZWUyNzQwNjdjNTY0N2VhY2UwOGU4ZmVjNzYyZDU2NjY3NzZkZmQwYjk
[contributor-guide]: https://ofn-user-guide.gitbook.io/ofn-contributor-guide/who-are-we
[ofn-install]: https://github.com/openfoodfoundation/ofn-install
[super-admin-guide]: https://ofn-user-guide.gitbook.io/ofn-super-admin-guide

View File

@@ -1,267 +1,287 @@
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $http, $window, BulkProducts, DisplayProperties, dataFetcher, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, SpreeApiAuth, Columns, tax_categories) ->
$scope.loading = true
$scope.loadingAllPages = true
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $filter, $http, $window, BulkProducts, DisplayProperties, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, SpreeApiAuth, Columns, tax_categories, RequestMonitor) ->
$scope.StatusMessage = StatusMessage
$scope.StatusMessage = StatusMessage
$scope.columns = Columns.columns
$scope.columns = Columns.columns
$scope.variant_unit_options = VariantUnitManager.variantUnitOptions()
$scope.variant_unit_options = VariantUnitManager.variantUnitOptions()
$scope.RequestMonitor = RequestMonitor
$scope.pagination = BulkProducts.pagination
$scope.per_page_options = [
{id: 15, name: t('js.admin.orders.index.per_page', results: 15)},
{id: 50, name: t('js.admin.orders.index.per_page', results: 50)},
{id: 100, name: t('js.admin.orders.index.per_page', results: 100)}
]
$scope.filterableColumns = [
{ name: t("label_producers"), db_column: "producer_name" },
{ name: t("name"), db_column: "name" }
]
$scope.filterableColumns = [
{ name: t("label_producers"), db_column: "producer_name" },
{ name: t("name"), db_column: "name" }
]
$scope.filterTypes = [
{ name: t("equals"), predicate: "eq" },
{ name: t("contains"), predicate: "cont" }
]
$scope.filterTypes = [
{ name: t("equals"), predicate: "eq" },
{ name: t("contains"), predicate: "cont" }
]
$scope.optionTabs =
filters: { title: t("filter_products"), visible: false }
$scope.optionTabs =
filters: { title: t("filter_products"), visible: false }
$scope.producers = producers
$scope.taxons = Taxons.all
$scope.tax_categories = tax_categories
$scope.producerFilter = ""
$scope.categoryFilter = ""
$scope.importDateFilter = ""
$scope.page = 1
$scope.per_page = 15
$scope.products = BulkProducts.products
$scope.query = ""
$scope.DisplayProperties = DisplayProperties
$scope.initialise = ->
SpreeApiAuth.authorise()
.then ->
$scope.spree_api_key_ok = true
$scope.fetchProducts()
.catch (message) ->
$scope.api_error_msg = message
$scope.$watchCollection '[query, producerFilter, categoryFilter, importDateFilter, per_page]', ->
$scope.page = 1 # Reset page when changing filters for new search
$scope.changePage = (newPage) ->
$scope.page = newPage
$scope.fetchProducts()
$scope.fetchProducts = ->
removeClearedValues()
params = {
'q[name_cont]': $scope.query,
'q[supplier_id_eq]': $scope.producerFilter,
'q[primary_taxon_id_eq]': $scope.categoryFilter,
import_date: $scope.importDateFilter,
page: $scope.page,
per_page: $scope.per_page
}
RequestMonitor.load(BulkProducts.fetch(params).$promise).then ->
$scope.resetProducts()
removeClearedValues = ->
delete $scope.producerFilter if $scope.producerFilter == "0"
delete $scope.categoryFilter if $scope.categoryFilter == "0"
delete $scope.importDateFilter if $scope.importDateFilter == "0"
$timeout ->
if $scope.showLatestImport
$scope.importDateFilter = $scope.importDates[1].id
$scope.resetProducts = ->
DirtyProducts.clear()
StatusMessage.clear()
$scope.updateOnHand = (product) ->
on_demand_variants = []
if product.variants
on_demand_variants = (variant for id, variant of product.variants when variant.on_demand)
unless product.on_demand || on_demand_variants.length > 0
product.on_hand = $scope.onHand(product)
$scope.producers = producers
$scope.taxons = Taxons.all
$scope.tax_categories = tax_categories
$scope.filterProducers = [{id: "0", name: ""}].concat $scope.producers
$scope.filterTaxons = [{id: "0", name: ""}].concat $scope.taxons
$scope.onHand = (product) ->
onHand = 0
if product.hasOwnProperty("variants") and product.variants instanceof Object
for id, variant of product.variants
onHand = onHand + parseInt(if variant.on_hand > 0 then variant.on_hand else 0)
else
onHand = "error"
onHand
$scope.shiftTab = (tab) ->
$scope.visibleTab.visible = false unless $scope.visibleTab == tab || $scope.visibleTab == undefined
tab.visible = !tab.visible
$scope.visibleTab = tab
$scope.resetSelectFilters = ->
$scope.query = ""
$scope.producerFilter = "0"
$scope.categoryFilter = "0"
$scope.importDateFilter = "0"
$scope.products = BulkProducts.products
$scope.filteredProducts = []
$scope.currentFilters = []
$scope.limit = 15
$scope.query = ""
$scope.DisplayProperties = DisplayProperties
$scope.initialise = ->
SpreeApiAuth.authorise()
.then ->
$scope.spree_api_key_ok = true
$scope.fetchProducts()
.catch (message) ->
$scope.api_error_msg = message
$scope.$watchCollection '[query, producerFilter, categoryFilter, importDateFilter]', ->
$scope.limit = 15 # Reset limit whenever searching
$scope.fetchProducts = ->
$scope.loading = true
$scope.loadingAllPages = true
BulkProducts.fetch($scope.currentFilters, ->
$scope.loadingAllPages = false
).then ->
$scope.resetProducts()
$scope.loading = false
$timeout ->
if $scope.showLatestImport
$scope.importDateFilter = $scope.importDates[1].id
$scope.resetProducts = ->
DirtyProducts.clear()
StatusMessage.clear()
$scope.updateOnHand = (product) ->
on_demand_variants = []
if product.variants
on_demand_variants = (variant for id, variant of product.variants when variant.on_demand)
unless product.on_demand || on_demand_variants.length > 0
product.on_hand = $scope.onHand(product)
$scope.editWarn = (product, variant) ->
if (DirtyProducts.count() > 0 and confirm(t("unsaved_changes_confirmation"))) or (DirtyProducts.count() == 0)
window.location = "/admin/products/" + product.permalink_live + ((if variant then "/variants/" + variant.id else "")) + "/edit"
$scope.onHand = (product) ->
onHand = 0
if product.hasOwnProperty("variants") and product.variants instanceof Object
for id, variant of product.variants
onHand = onHand + parseInt(if variant.on_hand > 0 then variant.on_hand else 0)
else
onHand = "error"
onHand
$scope.toggleShowAllVariants = ->
showVariants = !DisplayProperties.showVariants 0
$scope.products.forEach (product) ->
DisplayProperties.setShowVariants product.id, showVariants
DisplayProperties.setShowVariants 0, showVariants
$scope.shiftTab = (tab) ->
$scope.visibleTab.visible = false unless $scope.visibleTab == tab || $scope.visibleTab == undefined
tab.visible = !tab.visible
$scope.visibleTab = tab
$scope.resetSelectFilters = ->
$scope.query = ""
$scope.producerFilter = "0"
$scope.categoryFilter = "0"
$scope.importDateFilter = "0"
$scope.editWarn = (product, variant) ->
if (DirtyProducts.count() > 0 and confirm(t("unsaved_changes_confirmation"))) or (DirtyProducts.count() == 0)
window.location = "/admin/products/" + product.permalink_live + ((if variant then "/variants/" + variant.id else "")) + "/edit"
$scope.addVariant = (product) ->
product.variants.push
id: $scope.nextVariantId()
unit_value: null
unit_description: null
on_demand: false
display_as: null
display_name: null
on_hand: null
price: null
DisplayProperties.setShowVariants product.id, true
$scope.toggleShowAllVariants = ->
showVariants = !DisplayProperties.showVariants 0
$scope.filteredProducts.forEach (product) ->
DisplayProperties.setShowVariants product.id, showVariants
DisplayProperties.setShowVariants 0, showVariants
$scope.nextVariantId = ->
$scope.variantIdCounter = 0 unless $scope.variantIdCounter?
$scope.variantIdCounter -= 1
$scope.variantIdCounter
$scope.addVariant = (product) ->
product.variants.push
id: $scope.nextVariantId()
unit_value: null
unit_description: null
on_demand: false
display_as: null
display_name: null
on_hand: null
price: null
DisplayProperties.setShowVariants product.id, true
$scope.nextVariantId = ->
$scope.variantIdCounter = 0 unless $scope.variantIdCounter?
$scope.variantIdCounter -= 1
$scope.variantIdCounter
$scope.deleteProduct = (product) ->
if confirm("Are you sure?")
$http(
method: "DELETE"
url: "/api/products/" + product.id + "/soft_delete"
).success (data) ->
$scope.products.splice $scope.products.indexOf(product), 1
DirtyProducts.deleteProduct product.id
$scope.displayDirtyProducts()
$scope.deleteVariant = (product, variant) ->
if product.variants.length > 1
if !$scope.variantSaved(variant)
$scope.removeVariant(product, variant)
else
if confirm(t("are_you_sure"))
$http(
method: "DELETE"
url: "/api/products/" + product.permalink_live + "/variants/" + variant.id + "/soft_delete"
).success (data) ->
$scope.removeVariant(product, variant)
else
alert(t("delete_product_variant"))
$scope.removeVariant = (product, variant) ->
product.variants.splice product.variants.indexOf(variant), 1
DirtyProducts.deleteVariant product.id, variant.id
$scope.displayDirtyProducts()
$scope.cloneProduct = (product) ->
BulkProducts.cloneProduct product
$scope.hasVariants = (product) ->
product.variants.length > 0
$scope.hasUnit = (product) ->
product.variant_unit_with_scale?
$scope.variantSaved = (variant) ->
variant.hasOwnProperty('id') && variant.id > 0
$scope.hasOnDemandVariants = (product) ->
(variant for id, variant of product.variants when variant.on_demand).length > 0
$scope.submitProducts = ->
# Pack pack $scope.products, so they will match the list returned from the server,
# then pack $scope.dirtyProducts, ensuring that the correct product info is sent to the server.
$scope.packProduct product for id, product of $scope.products
$scope.packProduct product for id, product of DirtyProducts.all()
productsToSubmit = filterSubmitProducts(DirtyProducts.all())
if productsToSubmit.length > 0
$scope.updateProducts productsToSubmit # Don't submit an empty list
else
StatusMessage.display 'alert', t("products_change")
$scope.updateProducts = (productsToSubmit) ->
$scope.displayUpdating()
$scope.deleteProduct = (product) ->
if confirm("Are you sure?")
$http(
method: "POST"
url: "/admin/products/bulk_update"
data:
products: productsToSubmit
filters: $scope.currentFilters
).success((data) ->
DirtyProducts.clear()
BulkProducts.updateVariantLists(data.products || [])
$timeout -> $scope.displaySuccess()
).error (data, status) ->
if status == 400 && data.errors? && data.errors.length > 0
errors = error + "\n" for error in data.errors
alert t("products_update_error") + "\n" + errors
$scope.displayFailure t("products_update_error")
else
$scope.displayFailure t("products_update_error_data") + status
method: "DELETE"
url: "/api/products/" + product.id + "/soft_delete"
).success (data) ->
$scope.products.splice $scope.products.indexOf(product), 1
DirtyProducts.deleteProduct product.id
$scope.displayDirtyProducts()
$scope.cancel = (destination) ->
$window.location = destination
$scope.packProduct = (product) ->
if product.variant_unit_with_scale
match = product.variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/)
if match
product.variant_unit = match[1]
product.variant_unit_scale = parseFloat(match[2])
else
product.variant_unit = product.variant_unit_with_scale
product.variant_unit_scale = null
$scope.deleteVariant = (product, variant) ->
if product.variants.length > 1
if !$scope.variantSaved(variant)
$scope.removeVariant(product, variant)
else
product.variant_unit = product.variant_unit_scale = null
if confirm(t("are_you_sure"))
$http(
method: "DELETE"
url: "/api/products/" + product.permalink_live + "/variants/" + variant.id + "/soft_delete"
).success (data) ->
$scope.removeVariant(product, variant)
else
alert(t("delete_product_variant"))
$scope.packVariant product, product.master if product.master
if product.variants
for id, variant of product.variants
$scope.packVariant product, variant
$scope.removeVariant = (product, variant) ->
product.variants.splice product.variants.indexOf(variant), 1
DirtyProducts.deleteVariant product.id, variant.id
$scope.displayDirtyProducts()
$scope.packVariant = (product, variant) ->
if variant.hasOwnProperty("unit_value_with_description")
match = variant.unit_value_with_description.match(/^([\d\.]+(?= |$)|)( |)(.*)$/)
if match
product = BulkProducts.find product.id
variant.unit_value = parseFloat(match[1])
variant.unit_value = null if isNaN(variant.unit_value)
variant.unit_value *= product.variant_unit_scale if variant.unit_value && product.variant_unit_scale
variant.unit_description = match[3]
$scope.cloneProduct = (product) ->
BulkProducts.cloneProduct product
$scope.incrementLimit = ->
if $scope.limit < $scope.products.length
$scope.limit = $scope.limit + 5
$scope.hasVariants = (product) ->
product.variants.length > 0
$scope.displayUpdating = ->
StatusMessage.display 'progress', t("saving")
$scope.hasUnit = (product) ->
product.variant_unit_with_scale?
$scope.displaySuccess = ->
StatusMessage.display 'success',t("products_changes_saved")
$scope.bulk_product_form.$setPristine()
$scope.variantSaved = (variant) ->
variant.hasOwnProperty('id') && variant.id > 0
$scope.displayFailure = (failMessage) ->
StatusMessage.display 'failure', t("products_update_error_msg") + "#{failMessage}"
$scope.hasOnDemandVariants = (product) ->
(variant for id, variant of product.variants when variant.on_demand).length > 0
$scope.displayDirtyProducts = ->
count = DirtyProducts.count()
switch count
when 0 then StatusMessage.clear()
when 1 then StatusMessage.display 'notice', t("one_product_unsaved")
else StatusMessage.display 'notice', t("products_unsaved", n: count)
$scope.submitProducts = ->
# Pack pack $scope.products, so they will match the list returned from the server,
# then pack $scope.dirtyProducts, ensuring that the correct product info is sent to the server.
$scope.packProduct product for id, product of $scope.products
$scope.packProduct product for id, product of DirtyProducts.all()
productsToSubmit = filterSubmitProducts(DirtyProducts.all())
if productsToSubmit.length > 0
$scope.updateProducts productsToSubmit # Don't submit an empty list
else
StatusMessage.display 'alert', t("products_change")
$scope.updateProducts = (productsToSubmit) ->
$scope.displayUpdating()
$http(
method: "POST"
url: "/admin/products/bulk_update"
data:
products: productsToSubmit
filters:
'q[name_cont]': $scope.query
'q[supplier_id_eq]': $scope.producerFilter
'q[primary_taxon_id_eq]': $scope.categoryFilter
import_date: $scope.importDateFilter
page: $scope.page
per_page: $scope.per_page
).success((data) ->
DirtyProducts.clear()
BulkProducts.updateVariantLists(data.products || [])
$timeout -> $scope.displaySuccess()
).error (data, status) ->
if status == 400 && data.errors? && data.errors.length > 0
errors = error + "\n" for error in data.errors
alert t("products_update_error") + "\n" + errors
$scope.displayFailure t("products_update_error")
else
$scope.displayFailure t("products_update_error_data") + status
$scope.cancel = (destination) ->
$window.location = destination
$scope.packProduct = (product) ->
if product.variant_unit_with_scale
match = product.variant_unit_with_scale.match(/^([^_]+)_([\d\.]+)$/)
if match
product.variant_unit = match[1]
product.variant_unit_scale = parseFloat(match[2])
else
product.variant_unit = product.variant_unit_with_scale
product.variant_unit_scale = null
else
product.variant_unit = product.variant_unit_scale = null
$scope.packVariant product, product.master if product.master
if product.variants
for id, variant of product.variants
$scope.packVariant product, variant
$scope.packVariant = (product, variant) ->
if variant.hasOwnProperty("unit_value_with_description")
match = variant.unit_value_with_description.match(/^([\d\.]+(?= |$)|)( |)(.*)$/)
if match
product = BulkProducts.find product.id
variant.unit_value = parseFloat(match[1])
variant.unit_value = null if isNaN(variant.unit_value)
variant.unit_value *= product.variant_unit_scale if variant.unit_value && product.variant_unit_scale
variant.unit_description = match[3]
$scope.incrementLimit = ->
if $scope.limit < $scope.products.length
$scope.limit = $scope.limit + 5
$scope.displayUpdating = ->
StatusMessage.display 'progress', t("saving")
$scope.displaySuccess = ->
StatusMessage.display 'success',t("products_changes_saved")
$scope.bulk_product_form.$setPristine()
$scope.displayFailure = (failMessage) ->
StatusMessage.display 'failure', t("products_update_error_msg") + "#{failMessage}"
$scope.displayDirtyProducts = ->
count = DirtyProducts.count()
switch count
when 0 then StatusMessage.clear()
when 1 then StatusMessage.display 'notice', t("one_product_unsaved")
else StatusMessage.display 'notice', t("products_unsaved", n: count)
filterSubmitProducts = (productsToFilter) ->

View File

@@ -23,7 +23,7 @@ angular.module("admin.orders").controller "ordersCtrl", ($scope, RequestMonitor,
$scope.fetchResults = (page=1) ->
$scope.resetSelected()
Orders.index({
params = {
'q[completed_at_lt]': $scope['q']['completed_at_lt'],
'q[completed_at_gt]': $scope['q']['completed_at_gt'],
'q[state_eq]': $scope['q']['state_eq'],
@@ -39,7 +39,8 @@ angular.module("admin.orders").controller "ordersCtrl", ($scope, RequestMonitor,
'q[s]': $scope.sorting || 'completed_at desc',
per_page: $scope.per_page,
page: page
})
}
RequestMonitor.load(Orders.index(params).$promise)
$scope.resetSelected = ->
$scope.selected_orders.length = 0

View File

@@ -0,0 +1,19 @@
angular.module("admin.products").directive "setOnDemand", ->
link: (scope, element, attr) ->
onHand = element.context.querySelector("#variant_on_hand")
onDemand = element.context.querySelector("#variant_on_demand")
disableOnHandIfOnDemand = ->
if onDemand.checked
onHand.disabled = 'disabled'
onHand.dataStock = onHand.value
onHand.value = t('admin.products.variants.infinity')
disableOnHandIfOnDemand()
onDemand.addEventListener 'change', (event) ->
disableOnHandIfOnDemand()
if !onDemand.checked
onHand.removeAttribute('disabled')
onHand.value = onHand.dataStock

View File

@@ -0,0 +1,6 @@
angular.module("admin.resources").factory 'ProductResource', ($resource) ->
$resource('/admin/product/:id/:action.json', {}, {
'index':
url: '/api/products/bulk_products.json'
method: 'GET'
})

View File

@@ -1,15 +1,13 @@
angular.module("ofn.admin").factory "BulkProducts", (PagedFetcher, dataFetcher, $http) ->
angular.module("ofn.admin").factory "BulkProducts", (ProductResource, dataFetcher, $http) ->
new class BulkProducts
products: []
pagination: {}
fetch: (filters, onComplete) ->
queryString = filters.reduce (qs,f) ->
return qs + "q[#{f.property.db_column}_#{f.predicate.predicate}]=#{f.value};"
, ""
url = "/api/products/bulk_products?page=::page::;per_page=20;#{queryString}"
processData = (data) => @addProducts data.products
PagedFetcher.fetch url, processData, onComplete
fetch: (params) ->
ProductResource.index params, (data) =>
@products.length = 0
@addProducts data.products
angular.extend(@pagination, data.pagination)
cloneProduct: (product) ->
$http.post("/api/products/" + product.id + "/clone").success (data) =>

View File

@@ -27,8 +27,6 @@ angular.module("admin.utils").directive "variantAutocomplete", ($timeout) ->
window.variants = data # this is how spree auto complete JS code picks up variants
results: data
formatResult: (variant) ->
if variant["images"][0] != undefined && variant["images"][0].image != undefined
variant.image = variant.images[0].image.mini_url
variantTemplate variant: variant
formatSelection: (variant) ->
element.parent().children(".options_placeholder").html variant.options_text

View File

@@ -1,8 +0,0 @@
Darkswarm.directive "cart", ->
# Toggles visibility of the "cart" popover
restrict: 'A'
link: (scope, elem, attr)->
scope.open = false
elem.bind 'click', ->
scope.$apply ->
scope.open = !scope.open

View File

@@ -0,0 +1,19 @@
Darkswarm.directive "cartToggle", ($document) ->
# Toggles visibility of the "cart" popover
restrict: 'A'
link: (scope, elem, attr)->
scope.open = false
$document.bind 'click', (event) ->
cart_button = elem[0]
element_and_parents = [event.target, event.target.parentElement, event.target.parentElement.parentElement]
cart_button_clicked = (element_and_parents.indexOf(cart_button) != -1)
if cart_button_clicked
scope.$apply ->
scope.open = !scope.open
else
scope.$apply ->
scope.open = false
return

View File

@@ -1,10 +1,15 @@
@API_DATETIME_FORMAT = "YYYY-MM-DD HH:mm:SS Z"
Darkswarm.filter "date_in_words", ->
(date) ->
moment(date).fromNow()
(date, dateFormat) ->
dateFormat ?= @API_DATETIME_FORMAT
moment(date, dateFormat).fromNow()
Darkswarm.filter "sensible_timeframe", (date_in_wordsFilter)->
(date) ->
if moment().add(2, 'days') < moment(date)
(date, dateFormat) ->
dateFormat ?= @API_DATETIME_FORMAT
if moment().add(2, 'days') < moment(date, dateFormat)
t 'orders_open'
else
t('closing') + date_in_wordsFilter(date)

View File

@@ -0,0 +1,11 @@
.add-line-item {
fieldset {
.vertical-align-top {
vertical-align: top;
}
.actions {
padding-top: 18px;
}
}
}

View File

@@ -3,7 +3,7 @@
.select2-container {
.select2-choice {
.select2-search-choice-close {
display: none;
display: none !important;
}
.select2-arrow {
width: 22px;

View File

@@ -35,5 +35,6 @@ $med-grey: #666;
$med-drk-grey: #444;
$dark-grey: #333;
$light-grey: #ddd;
$light-grey-transparency: rgba(0, 0, 0, .1);
$black: #000;
$white: #fff;

View File

@@ -42,7 +42,7 @@ nav.top-bar {
}
.top-bar-section {
border-bottom: 1px solid $ofn-grey;
border-bottom: 1px solid $light-grey-transparency;
a.icon {
&:hover {
@@ -170,9 +170,10 @@ nav.top-bar {
.tab-bar {
background-color: white;
border-bottom: 1px solid $light-grey-transparency;
height: 2.8em;
position: fixed;
width: 100%;
height: 2.8em;
z-index: 1;
.cart-span {

View File

@@ -1,6 +1,7 @@
@import "mixins";
@import "branding";
@import "compass/css3/user-interface";
@import 'variables';
.cart {
@include user-select(none);
@@ -15,8 +16,8 @@
.joyride-tip-guide {
display: block;
right: 10px;
top: 55px;
right: 0;
top: $topbar-height;
width: 480px;
@media screen and (min-width: 641px) {

View File

@@ -1,4 +1,5 @@
require 'open_food_network/permissions'
require 'open_food_network/proxy_order_syncer'
module Admin
class SubscriptionsController < ResourceController
@@ -32,21 +33,11 @@ module Admin
end
def create
form = SubscriptionForm.new(@subscription, params[:subscription])
if form.save
render_as_json @subscription
else
render json: { errors: form.json_errors }, status: :unprocessable_entity
end
save_form_and_render(false)
end
def update
form = SubscriptionForm.new(@subscription, params[:subscription])
if form.save
render_as_json @subscription, order_update_issues: form.order_update_issues
else
render json: { errors: form.json_errors }, status: :unprocessable_entity
end
save_form_and_render
end
def cancel
@@ -67,12 +58,26 @@ module Admin
end
def unpause
@subscription.update_attributes(paused_at: nil)
render_as_json @subscription
params[:subscription][:paused_at] = nil
save_form_and_render
end
private
def save_form_and_render(render_issues = true)
form = SubscriptionForm.new(@subscription, params[:subscription])
unless form.save
render json: { errors: form.json_errors }, status: :unprocessable_entity
return
end
if render_issues
render_as_json @subscription, order_update_issues: form.order_update_issues
else
render_as_json @subscription
end
end
def permissions
return @permissions unless @permissions.nil?
@permissions = OpenFoodNetwork::Permissions.new(spree_current_user)

View File

@@ -9,8 +9,8 @@ module Admin
def map_by_tag
respond_to do |format|
format.json do
serialiser = ActiveModel::ArraySerializer.new(collection)
render json: serialiser.to_json
serializer = ActiveModel::ArraySerializer.new(collection)
render json: serializer.to_json
end
end
end

View File

@@ -1,5 +1,5 @@
module Api
class ProductImagesController < Spree::Api::BaseController
class ProductImagesController < BaseController
respond_to :json
def update_product_image
@@ -8,11 +8,11 @@ module Api
if @product.images.first.nil?
@image = Spree::Image.create(attachment: params[:file], viewable_id: @product.master.id, viewable_type: 'Spree::Variant')
respond_with(@image, status: 201)
render json: @image, serializer: ImageSerializer, status: :created
else
@image = @product.images.first
@image.update_attributes(attachment: params[:file])
respond_with(@image, status: 200)
render json: @image, serializer: ImageSerializer, status: :ok
end
end
end

View File

@@ -0,0 +1,146 @@
require 'open_food_network/permissions'
module Api
class ProductsController < Api::BaseController
respond_to :json
DEFAULT_PAGE = 1
DEFAULT_PER_PAGE = 15
skip_authorization_check only: [:show, :bulk_products, :overridable]
def show
@product = find_product(params[:id])
render json: @product, serializer: Api::Admin::ProductSerializer
end
def create
authorize! :create, Spree::Product
params[:product][:available_on] ||= Time.zone.now
@product = Spree::Product.new(params[:product])
begin
if @product.save
render json: @product, serializer: Api::Admin::ProductSerializer, status: 201
else
invalid_resource!(@product)
end
rescue ActiveRecord::RecordNotUnique
@product.permalink = nil
retry
end
end
def update
authorize! :update, Spree::Product
@product = find_product(params[:id])
if @product.update_attributes(params[:product])
render json: @product, serializer: Api::Admin::ProductSerializer, status: 200
else
invalid_resource!(@product)
end
end
def destroy
authorize! :delete, Spree::Product
@product = find_product(params[:id])
@product.update_attribute(:deleted_at, Time.zone.now)
@product.variants_including_master.update_all(deleted_at: Time.zone.now)
render json: @product, serializer: Api::Admin::ProductSerializer, status: 204
end
# TODO: This should be named 'managed'. Is the action above used? Maybe we should remove it.
def bulk_products
product_query = OpenFoodNetwork::Permissions.new(current_api_user).
editable_products.merge(product_scope)
if params[:import_date].present?
product_query = product_query.imported_on(params[:import_date]).group_by_products_id
end
@products = product_query.order('created_at DESC').
ransack(params[:q]).result.
page(params[:page] || DEFAULT_PAGE).per(params[:per_page] || DEFAULT_PER_PAGE)
render_paged_products @products
end
def overridable
producers = OpenFoodNetwork::Permissions.new(current_api_user).
variant_override_producers.by_name
@products = paged_products_for_producers producers
render_paged_products @products
end
def soft_delete
authorize! :delete, Spree::Product
@product = find_product(params[:product_id])
authorize! :delete, @product
@product.destroy
render json: @product, serializer: Api::Admin::ProductSerializer, status: 204
end
# POST /api/products/:product_id/clone
#
def clone
authorize! :create, Spree::Product
original_product = find_product(params[:product_id])
authorize! :update, original_product
@product = original_product.duplicate
render json: @product, serializer: Api::Admin::ProductSerializer, status: 201
end
private
# Copied and modified from SpreeApi::BaseController to allow
# enterprise users to access inactive products
def product_scope
# This line modified
if current_api_user.has_spree_role?("admin") || current_api_user.enterprises.present?
scope = Spree::Product
if params[:show_deleted]
scope = scope.with_deleted
end
else
scope = Spree::Product.active
end
scope.includes(:master)
end
def paged_products_for_producers(producers)
Spree::Product.scoped.
merge(product_scope).
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)
serializer = ActiveModel::ArraySerializer.new(
products,
each_serializer: ::Api::Admin::ProductSerializer
)
render text: {
products: serializer,
# This line is used by the PagedFetcher JS service (inventory).
pages: products.num_pages,
# This hash is used by the BulkProducts JS service.
pagination: pagination_data(products)
}.to_json
end
def pagination_data(results)
{
results: results.total_count,
pages: results.num_pages,
page: (params[:page] || DEFAULT_PAGE).to_i,
per_page: (params[:per_page] || DEFAULT_PER_PAGE).to_i
}
end
end
end

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,79 @@
module Api
class VariantsController < Api::BaseController
respond_to :json
skip_authorization_check only: [:index, :show]
before_filter :product
def index
@variants = scope.includes(:option_values).ransack(params[:q]).result
render json: @variants, each_serializer: Api::VariantSerializer
end
def show
@variant = scope.includes(:option_values).find(params[:id])
render json: @variant, serializer: Api::VariantSerializer
end
def create
authorize! :create, Spree::Variant
@variant = scope.new(params[:variant])
if @variant.save
render json: @variant, serializer: Api::VariantSerializer, status: 201
else
invalid_resource!(@variant)
end
end
def update
authorize! :update, Spree::Variant
@variant = scope.find(params[:id])
if @variant.update_attributes(params[:variant])
render json: @variant, serializer: Api::VariantSerializer, status: 200
else
invalid_resource!(@product)
end
end
def soft_delete
@variant = scope.find(params[:variant_id])
authorize! :delete, @variant
VariantDeleter.new.delete(@variant)
render json: @variant, serializer: Api::VariantSerializer, status: 204
end
def destroy
authorize! :delete, Spree::Variant
@variant = scope.find(params[:id])
@variant.destroy
render json: @variant, serializer: Api::VariantSerializer, status: 204
end
private
def product
@product ||= Spree::Product.find_by_permalink(params[:product_id]) if params[:product_id]
end
def scope
if @product
unless current_api_user.has_spree_role?("admin") || params[:show_deleted]
variants = @product.variants_including_master
else
variants = @product.variants_including_master.with_deleted
end
else
variants = Spree::Variant.scoped
if current_api_user.has_spree_role?("admin")
unless params[:show_deleted]
variants = Spree::Variant.active
end
else
variants = variants.active
end
end
variants
end
end
end

View File

@@ -152,7 +152,7 @@ class CheckoutController < Spree::CheckoutController
end
def update_failed
clear_ship_address
current_order.updater.shipping_address_from_distributor
RestartCheckout.new(@order).call
respond_to do |format|
@@ -165,15 +165,6 @@ class CheckoutController < Spree::CheckoutController
end
end
# When we have a pickup Shipping Method,
# we clone the distributor address into ship_address before_save
# We don't want this data in the form, so we clear it out
def clear_ship_address
unless current_order.shipping_method.andand.require_ship_address
current_order.ship_address = Spree::Address.default
end
end
def load_order
@order = current_order
redirect_to(main_app.shop_path) && return unless @order && @order.checkout_allowed?

View File

@@ -27,12 +27,12 @@ class ShopController < BaseController
if oc = OrderCycle.with_distributor(@distributor).active.find_by_id(params[:order_cycle_id])
current_order(true).set_order_cycle! oc
@current_order_cycle = oc
render partial: "json/order_cycle"
render json: @current_order_cycle, serializer: Api::OrderCycleSerializer
else
render status: :not_found, json: ""
end
else
render partial: "json/order_cycle"
render json: current_order_cycle, serializer: Api::OrderCycleSerializer
end
end

View File

@@ -61,7 +61,7 @@ Spree::Admin::BaseController.class_eval do
def active_distributors_not_ready_for_checkout
ocs = OrderCycle.managed_by(spree_current_user).active
distributors = ocs.map(&:distributors).flatten.uniq
distributors = ocs.includes(:distributors).map(&:distributors).flatten.uniq
Enterprise.where('enterprises.id IN (?)', distributors).not_ready_for_checkout
end

View File

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

View File

@@ -1,5 +1,6 @@
require 'open_food_network/spree_api_key_loader'
require 'open_food_network/referer_parser'
require 'open_food_network/permissions'
Spree::Admin::ProductsController.class_eval do
include OpenFoodNetwork::SpreeApiKeyLoader
@@ -48,19 +49,13 @@ Spree::Admin::ProductsController.class_eval do
end
def bulk_update
collection_hash = Hash[params[:products].each_with_index.map { |p, i| [i, p] }]
product_set = Spree::ProductSet.new(collection_attributes: collection_hash)
params[:filters] ||= {}
bulk_index_query = params[:filters].reduce("") do |string, filter|
"#{string}q[#{filter[:property][:db_column]}_#{filter[:predicate][:predicate]}]=#{filter[:value]};"
end
product_set = product_set_from_params(params)
# Ensure we're authorised to update all products
product_set.collection.each { |p| authorize! :update, p }
if product_set.save
redirect_to "/api/products/bulk_products?page=1;per_page=500;#{bulk_index_query}"
redirect_to main_app.bulk_products_api_products_path( bulk_index_query(params) )
else
if product_set.errors.present?
render json: { errors: product_set.errors }, status: :bad_request
@@ -73,7 +68,8 @@ Spree::Admin::ProductsController.class_eval do
protected
def collection
# This method is copied directly from the spree product controller, except where we narrow the search below with the managed_by search to support
# This method is copied directly from the spree product controller
# except where we narrow the search below with the managed_by search to support
# enterprise users.
# TODO: There has to be a better way!!!
return @collection if @collection.present?
@@ -108,14 +104,32 @@ Spree::Admin::ProductsController.class_eval do
private
def product_set_from_params(params)
collection_hash = Hash[params[:products].each_with_index.map { |p, i| [i, p] }]
Spree::ProductSet.new(collection_attributes: collection_hash)
end
def bulk_index_query(params)
params[:filters].to_h.merge(page: params[:page], per_page: params[:per_page])
end
def load_form_data
@producers = OpenFoodNetwork::Permissions.new(spree_current_user).managed_product_enterprises.is_primary_producer.by_name
@producers = OpenFoodNetwork::Permissions.new(spree_current_user).
managed_product_enterprises.is_primary_producer.by_name
@taxons = Spree::Taxon.order(:name)
@import_dates = product_import_dates.uniq.to_json
end
def product_import_dates
import_dates = Spree::Variant.
options = [{ id: '0', name: '' }]
product_import_dates_query.collect(&:import_date).
map { |i| options.push(id: i.to_date, name: i.to_date.to_formatted_s(:long)) }
options
end
def product_import_dates_query
Spree::Variant.
select('DISTINCT spree_variants.import_date').
joins(:product).
where('spree_products.supplier_id IN (?)', editable_enterprises.collect(&:id)).
@@ -123,18 +137,14 @@ Spree::Admin::ProductsController.class_eval do
where(spree_variants: { is_master: false }).
where(spree_variants: { deleted_at: nil }).
order('spree_variants.import_date DESC')
options = [{ id: '0', name: '' }]
import_dates.collect(&:import_date).map { |i| options.push(id: i.to_date, name: i.to_date.to_formatted_s(:long)) }
options
end
def strip_new_properties
unless spree_current_user.admin? || params[:product][:product_properties_attributes].nil?
names = Spree::Property.pluck(:name)
params[:product][:product_properties_attributes].each do |key, property|
params[:product][:product_properties_attributes].delete key unless names.include? property[:property_name]
return if spree_current_user.admin? || params[:product][:product_properties_attributes].nil?
names = Spree::Property.pluck(:name)
params[:product][:product_properties_attributes].each do |key, property|
unless names.include? property[:property_name]
params[:product][:product_properties_attributes].delete key
end
end
end
@@ -149,12 +159,32 @@ Spree::Admin::ProductsController.class_eval do
end
def set_stock_levels(product, on_hand, on_demand)
variant = product.master
if product.variants.any?
variant = product.variants.first
variant = product_variant(product)
begin
variant.on_demand = on_demand if on_demand.present?
variant.on_hand = on_hand.to_i if on_hand.present?
rescue StandardError => error
notify_bugsnag(error, product, variant)
raise error
end
end
def notify_bugsnag(error, product, variant)
Bugsnag.notify(error) do |report|
report.add_tab(:product, product.attributes)
report.add_tab(:product_error, product.errors.first) unless product.valid?
report.add_tab(:variant, variant.attributes)
report.add_tab(:variant_error, variant.errors.first) unless variant.valid?
end
end
def product_variant(product)
if product.variants.any?
product.variants.first
else
product.master
end
variant.on_demand = on_demand if on_demand.present?
variant.on_hand = on_hand.to_i if on_hand.present?
end
def set_product_master_variant_price_to_zero

View File

@@ -46,7 +46,12 @@ module Spree
@user.spree_roles = roles.reject(&:blank?).collect{ |r| Spree::Role.find(r) }
end
flash.now[:success] = Spree.t(:account_updated)
message = if new_email_unconfirmed?
Spree.t(:email_updated)
else
Spree.t(:account_updated)
end
flash.now[:success] = message
end
render :edit
end
@@ -126,6 +131,10 @@ module Spree
def load_roles
@roles = Spree::Role.scoped
end
def new_email_unconfirmed?
params[:user][:email] != @user.email
end
end
end
end

View File

@@ -18,6 +18,7 @@ Spree::Admin::VariantsController.class_eval do
def search
scoper = OpenFoodNetwork::ScopeVariantsForSearch.new(params)
@variants = scoper.search
render json: @variants, each_serializer: Api::Admin::VariantSerializer
end
def destroy

View File

@@ -0,0 +1,130 @@
require_dependency 'spree/api/controller_setup'
module Spree
module Api
class BaseController < ActionController::Metal
include Spree::Api::ControllerSetup
include Spree::Core::ControllerHelpers::SSL
include ::ActionController::Head
self.responder = Spree::Api::Responders::AppResponder
respond_to :json
attr_accessor :current_api_user
before_filter :set_content_type
before_filter :check_for_user_or_api_key, :if => :requires_authentication?
before_filter :authenticate_user
after_filter :set_jsonp_format
rescue_from Exception, :with => :error_during_processing
rescue_from CanCan::AccessDenied, :with => :unauthorized
rescue_from ActiveRecord::RecordNotFound, :with => :not_found
helper Spree::Api::ApiHelpers
ssl_allowed
def set_jsonp_format
if params[:callback] && request.get?
self.response_body = "#{params[:callback]}(#{response_body})"
headers["Content-Type"] = 'application/javascript'
end
end
def map_nested_attributes_keys(klass, attributes)
nested_keys = klass.nested_attributes_options.keys
attributes.inject({}) do |h, (k, v)|
key = nested_keys.include?(k.to_sym) ? "#{k}_attributes" : k
h[key] = v
h
end.with_indifferent_access
end
private
def set_content_type
content_type = case params[:format]
when "json"
"application/json"
when "xml"
"text/xml"
end
headers["Content-Type"] = content_type
end
def check_for_user_or_api_key
# User is already authenticated with Spree, make request this way instead.
return true if @current_api_user = try_spree_current_user ||
!requires_authentication?
return if api_key.present?
render("spree/api/errors/must_specify_api_key", status: :unauthorized) && return
end
def authenticate_user
return if @current_api_user
if requires_authentication? || api_key.present?
unless @current_api_user = Spree.user_class.find_by_spree_api_key(api_key.to_s)
render("spree/api/errors/invalid_api_key", status: :unauthorized) && return
end
else
# An anonymous user
@current_api_user = Spree.user_class.new
end
end
def unauthorized
render("spree/api/errors/unauthorized", status: :unauthorized) && return
end
def error_during_processing(exception)
render(text: { exception: exception.message }.to_json,
status: :unprocessable_entity) && return
end
def requires_authentication?
true
end
def not_found
render("spree/api/errors/not_found", status: :not_found) && return
end
def current_ability
Spree::Ability.new(current_api_user)
end
def invalid_resource!(resource)
@resource = resource
render "spree/api/errors/invalid_resource", status: :unprocessable_entity
end
def api_key
request.headers["X-Spree-Token"] || params[:token]
end
helper_method :api_key
def find_product(id)
product_scope.find_by_permalink!(id.to_s)
rescue ActiveRecord::RecordNotFound
product_scope.find(id)
end
def product_scope
if current_api_user.has_spree_role?("admin")
scope = Product
if params[:show_deleted]
scope = scope.with_deleted
end
else
scope = Product.active
end
scope.includes(:master)
end
end
end
end

View File

@@ -1,13 +0,0 @@
Spree::Api::LineItemsController.class_eval do
around_filter :apply_enterprise_fees_with_lock, only: :update
private
def apply_enterprise_fees_with_lock
authorize! :read, order
order.with_lock do
yield
order.update_distribution_charge!
end
end
end

View File

@@ -1,86 +0,0 @@
require 'open_food_network/permissions'
Spree::Api::ProductsController.class_eval do
def managed
authorize! :admin, Spree::Product
authorize! :read, Spree::Product
@products = product_scope.ransack(params[:q]).result.managed_by(current_api_user).page(params[:page]).per(params[:per_page])
respond_with(@products, default_template: :index)
end
# TODO: This should be named 'managed'. Is the action above used? Maybe we should remove it.
def bulk_products
@products = OpenFoodNetwork::Permissions.new(current_api_user).editable_products.
merge(product_scope).
order('created_at DESC').
ransack(params[:q]).result.
page(params[:page]).per(params[:per_page])
render_paged_products @products
end
def overridable
producers = OpenFoodNetwork::Permissions.new(current_api_user).
variant_override_producers.by_name
@products = paged_products_for_producers producers
render_paged_products @products
end
def soft_delete
authorize! :delete, Spree::Product
@product = find_product(params[:product_id])
authorize! :delete, @product
@product.destroy
respond_with(@product, status: 204)
end
# POST /api/products/:product_id/clone
#
def clone
authorize! :create, Spree::Product
original_product = find_product(params[:product_id])
authorize! :update, original_product
@product = original_product.duplicate
respond_with(@product, status: 201, default_template: :show)
end
private
# Copied and modified from Spree::Api::BaseController to allow
# enterprise users to access inactive products
def product_scope
if current_api_user.has_spree_role?("admin") || current_api_user.enterprises.present? # This line modified
scope = Spree::Product
if params[:show_deleted]
scope = scope.with_deleted
end
else
scope = Spree::Product.active
end
scope.includes(:master)
end
def paged_products_for_producers(producers)
Spree::Product.scoped.
merge(product_scope).
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)
serializer = ActiveModel::ArraySerializer.new(
products,
each_serializer: Api::Admin::ProductSerializer
)
render text: { products: serializer, pages: products.num_pages }.to_json
end
end

View File

@@ -1,47 +0,0 @@
require 'open_food_network/scope_variant_to_hub'
Spree::Api::ShipmentsController.class_eval do
def create
variant = scoped_variant(params[:variant_id])
quantity = params[:quantity].to_i
@shipment = get_or_create_shipment(params[:stock_location_id])
@order.contents.add(variant, quantity, nil, @shipment)
@shipment.refresh_rates
@shipment.save!
respond_with(@shipment.reload, default_template: :show)
end
def add
variant = scoped_variant(params[:variant_id])
quantity = params[:quantity].to_i
@order.contents.add(variant, quantity, nil, @shipment)
respond_with(@shipment, default_template: :show)
end
def remove
variant = scoped_variant(params[:variant_id])
quantity = params[:quantity].to_i
@order.contents.remove(variant, quantity, @shipment)
@shipment.reload if @shipment.persisted?
respond_with(@shipment, default_template: :show)
end
private
def scoped_variant(variant_id)
variant = Spree::Variant.find(variant_id)
OpenFoodNetwork::ScopeVariantToHub.new(@order.distributor).scope(variant)
variant
end
def get_or_create_shipment(stock_location_id)
@order.shipment || @order.shipments.create(stock_location_id: stock_location_id)
end
end

View File

@@ -1,9 +0,0 @@
Spree::Api::VariantsController.class_eval do
def soft_delete
@variant = scope.find(params[:variant_id])
authorize! :delete, @variant
VariantDeleter.new.delete(@variant)
respond_with @variant, status: 204
end
end

View File

@@ -29,7 +29,7 @@ module Spree
def load_order
@order = current_order
redirect_to main_app.cart_path && return unless @order
redirect_to(main_app.cart_path) && return unless @order
if params[:state]
redirect_to checkout_state_path(@order.state) if @order.can_go_to_state?(params[:state])

View File

@@ -38,10 +38,6 @@ module Spree
end
end
def nav_bar
render partial: 'spree/shared/nav_bar'
end
private
def accurate_title

View File

@@ -61,6 +61,12 @@ module InjectionHelper
inject_json_ams "currentOrder", current_order, Api::CurrentOrderSerializer, current_distributor: current_distributor, current_order_cycle: current_order_cycle
end
def inject_current_order_cycle
serializer = Api::OrderCycleSerializer.new(current_order_cycle)
json = serializer.object.present? ? serializer.to_json : "{}"
render partial: "json/injection_ams", locals: { name: "orderCycleData", json: json }
end
def inject_available_shipping_methods
inject_json_ams "shippingMethods", available_shipping_methods,
Api::ShippingMethodSerializer, current_order: current_order

View File

@@ -18,6 +18,7 @@ module Spree
klass = Spree::Order if klass == :bulk_order_management
klass = EnterpriseGroup if klass == :group
klass = VariantOverride if klass == :Inventory
klass = ProductImport::ProductImporter if klass == :import
klass = Spree::Admin::ReportsController if klass == :report
klass
end

View File

@@ -0,0 +1,120 @@
module Spree
module Api
module ApiHelpers
def required_fields_for(model)
required_fields = model._validators.select do |_field, validations|
validations.any? { |v| v.is_a?(ActiveModel::Validations::PresenceValidator) }
end.map(&:first) # get fields that are invalid
# Permalinks presence is validated, but are really automatically generated
# Therefore we shouldn't tell API clients that they MUST send one through
required_fields.map!(&:to_s).delete("permalink")
required_fields
end
def product_attributes
[:id, :name, :description, :price, :available_on, :permalink, :meta_description,
:meta_keywords, :shipping_category_id, :taxon_ids]
end
def product_property_attributes
[:id, :product_id, :property_id, :value, :property_name]
end
def variant_attributes
[:id, :name, :sku, :price, :weight, :height, :width, :depth,
:is_master, :cost_price, :permalink]
end
def image_attributes
[:id, :position, :attachment_content_type, :attachment_file_name,
:type, :attachment_updated_at, :attachment_width, :attachment_height, :alt]
end
def option_value_attributes
[:id, :name, :presentation, :option_type_name, :option_type_id]
end
def order_attributes
[:id, :number, :item_total, :total, :state, :adjustment_total, :user_id,
:created_at, :updated_at, :completed_at, :payment_total,
:shipment_state, :payment_state, :email, :special_instructions, :token]
end
def line_item_attributes
[:id, :quantity, :price, :variant_id]
end
def option_type_attributes
[:id, :name, :presentation, :position]
end
def payment_attributes
[:id, :source_type, :source_id, :amount, :payment_method_id,
:response_code, :state, :avs_response, :created_at, :updated_at]
end
def payment_method_attributes
[:id, :name, :description]
end
def shipment_attributes
[:id, :tracking, :number, :cost, :shipped_at, :state]
end
def taxonomy_attributes
[:id, :name]
end
def taxon_attributes
[:id, :name, :pretty_name, :permalink, :position, :parent_id, :taxonomy_id]
end
def inventory_unit_attributes
[:id, :lock_version, :state, :variant_id, :shipment_id, :return_authorization_id]
end
def return_authorization_attributes
[:id, :number, :state, :amount, :order_id, :reason, :created_at, :updated_at]
end
def country_attributes
[:id, :iso_name, :iso, :iso3, :name, :numcode]
end
def state_attributes
[:id, :name, :abbr, :country_id]
end
def adjustment_attributes
[:id, :source_type, :source_id, :adjustable_type, :adjustable_id, :originator_type,
:originator_id, :amount, :label, :mandatory, :locked, :eligible, :created_at, :updated_at]
end
def creditcard_attributes
[:id, :month, :year, :cc_type, :last_digits, :first_name, :last_name,
:gateway_customer_profile_id, :gateway_payment_profile_id]
end
def user_attributes
[:id, :email, :created_at, :updated_at]
end
def property_attributes
[:id, :name, :presentation]
end
def stock_location_attributes
[:id, :name, :address1, :address2, :city,
:state_id, :state_name, :country_id, :zipcode, :phone, :active]
end
def stock_movement_attributes
[:id, :quantity, :stock_item_id]
end
def stock_item_attributes
[:id, :count_on_hand, :backorderable, :lock_version, :stock_location_id, :variant_id]
end
end
end
end

View File

@@ -59,7 +59,7 @@ class SubscriptionPlacementJob
end
def move_to_completion(order)
until order.completed? do order.next! end
AdvanceOrderService.new(order).call!
end
def unavailable_stock_lines_for(order)

View File

@@ -13,8 +13,43 @@ module Calculator
def compute(object)
line_items = line_items_for object
total_weight = line_items.sum { |li| ((li.variant.andand.weight || 0) * li.quantity) }
total_weight * preferred_per_kg
(total_weight(line_items) * preferred_per_kg).round(2)
end
private
def total_weight(line_items)
line_items.sum do |line_item|
line_item_weight(line_item)
end
end
def line_item_weight(line_item)
if line_item.final_weight_volume.present?
weight_per_final_weight_volume(line_item)
else
weight_per_variant(line_item) * line_item.quantity
end
end
def weight_per_variant(line_item)
line_item.variant.andand.weight || 0
end
def weight_per_final_weight_volume(line_item)
if line_item.variant.product.andand.variant_unit == 'weight'
# Divided by 1000 because grams is the base weight unit and the calculator price is per_kg
line_item.final_weight_volume / 1000.0
else
weight_per_variant(line_item) * quantity_implied_in_final_weight_volume(line_item)
end
end
# Example: 2 (line_item.quantity) wine glasses of 125mL (line_item.variant.unit_value)
# Customer ends up getting 350mL (line_item.final_weight_volume) of wine
# that represent 2.8 (quantity_implied_in_final_weight_volume) glasses of wine
def quantity_implied_in_final_weight_volume(line_item)
(1.0 * line_item.final_weight_volume / line_item.variant.unit_value).round(3)
end
end
end

View File

@@ -100,13 +100,13 @@ module VariantStock
# Here we depend only on variant.total_on_hand and variant.on_demand.
# This way, variant_overrides only need to override variant.total_on_hand and variant.on_demand.
def fill_status(quantity)
if on_hand >= quantity
on_hand = quantity
backordered = 0
else
on_hand = [0, total_on_hand].max
backordered = on_demand ? (quantity - on_hand) : 0
end
on_hand = if total_on_hand >= quantity || on_demand
quantity
else
[0, total_on_hand].max
end
backordered = 0
[on_hand, backordered]
end
@@ -117,6 +117,9 @@ module VariantStock
def move(quantity, originator = nil)
raise_error_if_no_stock_item_available
# Don't change variant stock if variant is on_demand
return if on_demand
# Creates a stock movement: it updates stock_item.count_on_hand and fills backorders
#
# This is the original Spree::StockLocation#move,

View File

@@ -90,7 +90,6 @@ class Enterprise < ActiveRecord::Base
validates :permalink, uniqueness: true, presence: true
validate :shopfront_taxons
validate :enforce_ownership_limit, if: lambda { owner_id_changed? && !owner_id.nil? }
validates :description, length: { maximum: 255 }
before_validation :initialize_permalink, if: lambda { permalink.nil? }
before_validation :ensure_owner_is_manager, if: lambda { owner_id_changed? && !owner_id.nil? }
@@ -464,9 +463,11 @@ class Enterprise < ActiveRecord::Base
self.permalink = Enterprise.find_available_permalink(name)
end
# Touch distributors without them touching their distributors.
# We avoid an infinite loop and don't need to touch the whole distributor tree.
def touch_distributors
Enterprise.distributing_products(supplied_products.select(:id)).
where('enterprises.id != ?', id).
find_each(&:touch)
update_all(updated_at: Time.zone.now)
end
end

View File

@@ -1,20 +0,0 @@
# Tells whether a particular feature is enabled or not
class FeatureFlags
# Constructor
#
# @param user [User]
def initialize(user)
@user = user
end
# Checks whether product import is enabled for the specified user
#
# @return [Boolean]
def product_import_enabled?
user.superadmin?
end
private
attr_reader :user
end

View File

@@ -1,9 +1,22 @@
module Spree
Price.class_eval do
acts_as_paranoid without_default_scope: true
after_save :refresh_products_cache
# Allow prices to access associated soft-deleted variants.
def variant
Spree::Variant.unscoped { super }
end
private
def check_price
if currency.nil?
self.currency = Spree::Config[:currency]
end
end
def refresh_products_cache
variant.andand.refresh_products_cache
end

View File

@@ -56,6 +56,12 @@ Spree::Product.class_eval do
ON (o_order_cycles.id = o_exchanges.order_cycle_id)")
}
scope :imported_on, lambda { |import_date|
import_date = Time.zone.parse import_date if import_date.is_a? String
import_date = import_date.to_date
joins(:variants).merge(Spree::Variant.where(import_date: import_date.beginning_of_day..import_date.end_of_day))
}
scope :with_order_cycles_inner, -> {
joins(variants_including_master: { exchanges: :order_cycle })
}

View File

@@ -17,9 +17,7 @@ class Spree::ProductSet < ModelSet
# variant.update_attributes( { price: xx.x } )
#
def update_attributes(attributes)
if attributes[:taxon_ids].present?
attributes[:taxon_ids] = attributes[:taxon_ids].split(',')
end
split_taxon_ids!(attributes)
found_model = @collection.find do |model|
model.id.to_s == attributes[:id].to_s && model.persisted?
@@ -28,12 +26,20 @@ class Spree::ProductSet < ModelSet
if found_model.nil?
@klass.new(attributes).save unless @reject_if.andand.call(attributes)
else
update_product_only_attributes(found_model, attributes) &&
update_product_variants(found_model, attributes) &&
update_product_master(found_model, attributes)
update_product(found_model, attributes)
end
end
def split_taxon_ids!(attributes)
attributes[:taxon_ids] = attributes[:taxon_ids].split(',') if attributes[:taxon_ids].present?
end
def update_product(found_model, attributes)
update_product_only_attributes(found_model, attributes) &&
update_product_variants(found_model, attributes) &&
update_product_master(found_model, attributes)
end
def update_product_only_attributes(product, attributes)
variant_related_attrs = [:id, :variants_attributes, :master_attributes]
product_related_attrs = attributes.except(*variant_related_attrs)
@@ -90,8 +96,23 @@ class Spree::ProductSet < ModelSet
variant = product.variants.create(variant_attributes)
variant.on_demand = on_demand if on_demand.present?
variant.on_hand = on_hand.to_i if on_hand.present?
begin
variant.on_demand = on_demand if on_demand.present?
variant.on_hand = on_hand.to_i if on_hand.present?
rescue StandardError => error
notify_bugsnag(error, product, variant, variant_attributes)
raise error
end
end
def notify_bugsnag(error, product, variant, variant_attributes)
Bugsnag.notify(error) do |report|
report.add_tab(:product, product.attributes)
report.add_tab(:product_error, product.errors.first) unless product.valid?
report.add_tab(:variant_attributes, variant_attributes)
report.add_tab(:variant, variant.attributes)
report.add_tab(:variant_error, variant.errors.first) unless variant.valid?
end
end
def collection_attributes=(attributes)

View File

@@ -0,0 +1,10 @@
Spree::StockMovement.class_eval do
after_save :refresh_products_cache
private
def refresh_products_cache
return if stock_item.variant.blank?
OpenFoodNetwork::ProductsCache.variant_changed stock_item.variant
end
end

View File

@@ -136,6 +136,16 @@ module Spree
has_spree_role?('admin')
end
def generate_spree_api_key!
self.spree_api_key = SecureRandom.hex(24)
save!
end
def clear_spree_api_key!
self.spree_api_key = nil
save!
end
protected
def password_required?

View File

@@ -91,6 +91,11 @@ Spree::Variant.class_eval do
can_supply?(quantity)
end
# Allow variant to access associated soft-deleted prices.
def default_price
Spree::Price.unscoped { super }
end
def price_with_fees(distributor, order_cycle)
price + fees_for(distributor, order_cycle)
end

View File

@@ -10,6 +10,11 @@ class SubscriptionLineItem < ActiveRecord::Base
(price_estimate || 0) * (quantity || 0)
end
# Ensure SubscriptionLineItem always has access to soft-deleted Variant attribute
def variant
Spree::Variant.unscoped { super }
end
# Used to calculators to estimate fees
alias_method :amount, :total_estimate

View File

@@ -1,6 +0,0 @@
Deface::Override.new(virtual_path: "spree/layouts/admin",
name: "user_admin_tabs",
insert_bottom: "[data-hook='admin_tabs'], #admin_tabs[data-hook]",
partial: "spree/admin/users_tab",
disabled: false,
original: '031652cf5a054796022506622082ab6d2693699f')

View File

@@ -1,5 +0,0 @@
Deface::Override.new(virtual_path: "spree/layouts/admin",
name: "auth_admin_login_navigation_bar",
insert_top: "[data-hook='admin_login_navigation_bar'], #admin_login_navigation_bar[data-hook]",
partial: "spree/layouts/admin/login_nav",
original: '841227d0aedf7909d62237d8778df99100087715')

View File

@@ -1,6 +0,0 @@
Deface::Override.new(virtual_path: "spree/shared/_nav_bar",
name: "auth_shared_login_bar",
insert_before: "li#search-bar",
partial: "spree/shared/login_bar",
disabled: false,
original: 'eb3fa668cd98b6a1c75c36420ef1b238a1fc55ac')

View File

@@ -1,3 +0,0 @@
Deface::Override.new(virtual_path: "spree/shared/_nav_bar",
remove: "#search-bar",
name: "search_removal")

View File

@@ -1,3 +0,0 @@
Deface::Override.new(virtual_path: "spree/shared/_sidebar",
remove: "#sidebar",
name: "sidebar_removal")

View File

@@ -1,5 +0,0 @@
Deface::Override.new(virtual_path: "spree/layouts/admin",
insert_bottom: "[data-hook='admin_inside_head']",
partial: "layouts/auth_token_script",
name: "set_auth_token_in_backend",
original: '6bc2c5de1c8f7542d033548557437c9fe4b3ba02')

View File

@@ -1,5 +0,0 @@
Deface::Override.new(virtual_path: "spree/layouts/spree_application",
insert_bottom: "[data-hook='inside_head']",
partial: "layouts/auth_token_script",
name: "set_auth_token_in_frontend",
original: '5659ac7dbf6ac6469907b005b85285b894677815')

View File

@@ -1,2 +0,0 @@
/replace 'code[erb-loud]:contains("form_for @payment")'
= form_for @payment, :url => admin_order_payments_path(@order), :html => {"ng-app" => "admin.payments", "ng-controller" => "PaymentCtrl"} do |f|

View File

@@ -1,3 +0,0 @@
/ insert_before "fieldset.no-border-top"
%save-bar{ persist: "true" }

View File

@@ -1,2 +0,0 @@
/replace 'code[erb-loud]:contains("button @order.cart?")'
= button_tag t(:update), type: 'button', "ng-click" => "submitPayment()"

View File

@@ -1,6 +0,0 @@
/ replace_contents "td.property_name"
- if spree_current_user.admin?
= f.text_field :property_name, :class => 'autocomplete'
- else
= f.select :property_name, @properties, { :include_blank => true }, { class: 'select2 fullwidth' }

View File

@@ -1,26 +0,0 @@
/ insert_after 'table.index.sortable'
=f.check_box :inherits_properties
=f.label :inherits_properties, t(".inherits_properties_checkbox_hint", supplier: @product.supplier.name)
%br
%br
#inherited_properties
%table.index
%thead
%tr{"data-hook" => "producer_properties_header"}
%th= t('admin.products.properties.inherited_property')
%th= t('admin.description')
%th.actions
%tbody#producer_properties{"data-hook" => ""}
- @product.supplier.producer_properties.each do |producer_property|
%tr
%td= producer_property.property.presentation
%td= producer_property.value
%td.actions
:coffee
$(document).ready ->
$("#inherited_properties").toggle $("input#product_inherits_properties").is(':checked')
$("input#product_inherits_properties").change ->
$("#inherited_properties").toggle $(this).is(':checked')

View File

@@ -1,5 +0,0 @@
/ replace "tr[data-hook='product_properties_header']"
%tr{"data-hook" => "product_properties_header"}
%th= t('admin.products.properties.property_name')
%th= t('admin.description')
%th.actions

View File

@@ -1,2 +0,0 @@
add_to_attributes '[data-hook="admin_variant_form_fields"]'
attributes 'ng-app' => 'admin.products'

View File

@@ -1,25 +0,0 @@
/ insert_top "[data-hook='admin_variant_form_fields']"
.field
= f.label :display_name, t(:display_name)
= f.text_field :display_name, class: "fullwidth"
.field
= f.label :display_as, t(:display_as)
= f.text_field :display_as, class: "fullwidth"
- if product_has_variant_unit_option_type?(@product)
- if @product.variant_unit != 'items'
.field{"data-hook" => "unit_value", 'ng-controller' => 'variantUnitsCtrl'}
= f.label :unit_value, "#{t('admin.'+@product.variant_unit)} ({{unitName(#{@product.variant_unit_scale}, '#{@product.variant_unit}')}})"
= hidden_field_tag 'product_variant_unit_scale', @product.variant_unit_scale
= text_field_tag :unit_value_human, nil, {class: "fullwidth", 'ng-model' => 'unit_value_human', 'ng-change' => 'updateValue()'}
= f.text_field :unit_value, {hidden: true, 'ng-value' => 'unit_value'}
.field{"data-hook" => "unit_description"}
= f.label :unit_description, t(:spree_admin_unit_description)
= f.text_field :unit_description, class: "fullwidth", placeholder: t('admin.products.unit_name_placeholder')
:javascript
angular.element(document.getElementById("new_variant")).ready(function() {
angular.bootstrap(document.getElementById("new_variant"), ['admin.products']);
});

View File

@@ -1,11 +0,0 @@
/ insert_bottom "[data-hook='admin_variant_form_fields']"
- if Spree::Config[:track_inventory_levels]
.field.checkbox
%label
= f.check_box :on_demand
= t(:on_demand)
.field
= f.label :on_hand, t(:on_hand)
.fullwidth
= f.text_field :on_hand

View File

@@ -1,10 +0,0 @@
/ replace "[data-hook='presentation']"
- unless variant_unit_option_type?(option_type)
.field{"data-hook" => "presentation"}
= label :new_variant, option_type.presentation
- if @variant.new_record?
= select(:new_variant, option_type.presentation, option_type.option_values.collect {|ov| [ ov.presentation, ov.id ] }, {}, {:class => 'select2 fullwidth'})
- else
- if opt = @variant.option_values.detect {|o| o.option_type == option_type }.try(:presentation)
= text_field(:new_variant, option_type.presentation, :value => opt, :disabled => 'disabled', :class => 'fullwidth')

View File

@@ -1,33 +0,0 @@
/ insert_bottom "[data-hook='admin_variant_form_fields']"
:javascript
$(document).ready(function() {
var on_demand = $('input#variant_on_demand');
var on_hand = $('input#variant_on_hand');
disableOnHandIfOnDemand = function() {
on_demand_checked = on_demand.attr('checked')
if ( on_demand_checked == undefined )
on_demand_checked = false;
on_hand.attr('disabled', on_demand_checked);
if(on_demand_checked) {
on_hand.attr('data-stock', on_hand.val());
on_hand.val(t('admin.products.variants.infinity'));
}
}
disableOnHandIfOnDemand();
on_demand.change(function(){
disableOnHandIfOnDemand();
if(!this.checked) {
if(on_hand.attr('data-stock') !== undefined) {
on_hand.val(on_hand.attr('data-stock'));
} else {
on_hand.val("0");
}
}
});
});

View File

@@ -1,3 +0,0 @@
/ insert_bottom "[data-hook='on_demand']"
%div{'ofn-with-tip' => t('admin.products.variants.to_order_tip')}
%a= t('admin.whats_this')

View File

@@ -1,14 +0,0 @@
/ replace "[data-hook='admin_variant_form_additional_fields']"
.right.six.columns.omega.label-block{"data-hook" => "admin_variant_form_additional_fields"}
- if @product.variant_unit != 'weight'
.field{"data-hook" => 'weight'}
= f.label 'weight', t('weight')+' (kg)'
- value = number_with_precision(@variant.weight, :precision => 2)
= f.text_field 'weight', :value => value, :class => 'fullwidth'
- [:height, :width, :depth].each do |field|
.field{"data-hook" => field}
= f.label field, t(field)
- value = number_with_precision(@variant.send(field), :precision => 2)
= f.text_field field, :value => value, :class => 'fullwidth'

View File

@@ -1,3 +0,0 @@
/ replace "code[erb-loud]:contains('variant.options_text')"
= variant.full_name

View File

@@ -1,5 +0,0 @@
<!-- surround_contents 'body' -->
<div <%= yield(:app_wrapper_attrs).strip.html_safe %>>
<%= render_original %>
</div>

View File

@@ -1,19 +0,0 @@
/ replace "footer"
-#= render partial: "shared/footer"
%footer
%hr/
-#.row
-#.seven.columns.offset-by-three
-#%center
-#%h1 What is open food network?
-#%p
-#%i
-#Open food network is an online space in which people can connect with, trade and sell food directly with
-#Australian farmers. We aim to reconnect people with their food.
-#%hr/
-#.row
-#.five.columns.secondary.offset-by-seven.secondary
-#All rights reserved. &copy; 2013 Open Food Foundation

View File

@@ -1,8 +0,0 @@
/ replace "#logo"
%figure#logo.columns.eight
- if current_distributor
%h1= link_to current_distributor.name, main_app.enterprise_shop_path(current_distributor)
.change-location= link_to 'Change Location', root_path
- else
%h1= link_to "OPEN FOOD NETWORK", root_path

View File

@@ -1,2 +0,0 @@
/ set_attributes '#top-nav-bar'
/ attributes({:class => "columns eight"})

View File

@@ -1,5 +0,0 @@
/ insert_before "#password-credentials"
- if @unconfirmed_email
%p.alert-box
= t('spree.users.show.unconfirmed_email', unconfirmed_email: @unconfirmed_email)

View File

@@ -1,15 +1,49 @@
class Api::Admin::VariantSerializer < ActiveModel::Serializer
attributes :id, :options_text, :unit_value, :unit_description, :unit_to_display, :on_demand, :display_as, :display_name, :name_to_display, :sku
attributes :on_hand, :price, :import_date
attributes :id, :name, :producer_name, :image, :sku, :import_date
attributes :options_text, :unit_value, :unit_description, :unit_to_display
attributes :display_as, :display_name, :name_to_display
attributes :price, :on_demand, :on_hand, :in_stock, :stock_location_id, :stock_location_name
has_many :variant_overrides
def name
if object.full_name.present?
"#{object.name} - #{object.full_name}"
else
object.name
end
end
def on_hand
return 0 if object.on_hand.nil?
object.on_hand
end
def price
# Decimals are passed to json as strings, we need to run parseFloat.toFixed(2) on the client side.
# Decimals are passed to json as strings, we need to run parseFloat.toFixed(2) on the client.
object.price.nil? ? 0.to_f : object.price
end
def producer_name
object.product.supplier.name
end
def image
return if object.product.images.empty?
object.product.images.first.mini_url
end
def in_stock
object.in_stock?
end
def stock_location_id
return if object.stock_items.empty?
object.stock_items.first.stock_location.id
end
def stock_location_name
return if object.stock_items.empty?
object.stock_items.first.stock_location.name
end
end

View File

@@ -1,10 +1,18 @@
class Api::ImageSerializer < ActiveModel::Serializer
attributes :id, :alt, :small_url, :large_url
attributes :id, :alt, :thumb_url, :small_url, :image_url, :large_url
def thumb_url
object.attachment.url(:mini, false)
end
def small_url
object.attachment.url(:small, false)
end
def image_url
object.attachment.url(:product, false)
end
def large_url
object.attachment.url(:large, false)
end

View File

@@ -0,0 +1,13 @@
module Api
class OrderCycleSerializer < ActiveModel::Serializer
attributes :order_cycle_id, :orders_close_at
def order_cycle_id
object.id
end
def orders_close_at
object.orders_close_at.to_s
end
end
end

View File

@@ -0,0 +1,13 @@
module Api
class ShipmentSerializer < ActiveModel::Serializer
attributes :id, :tracking, :number, :order_id, :cost, :shipped_at, :stock_location_name, :state
def order_id
object.order.number
end
def stock_location_name
object.stock_location.name
end
end
end

View File

@@ -0,0 +1,5 @@
module Api
class TaxonJstreeAttributeSerializer < ActiveModel::Serializer
attributes :id, :name
end
end

View File

@@ -0,0 +1,18 @@
module Api
class TaxonJstreeSerializer < ActiveModel::Serializer
attributes :data, :state
has_one :attr, serializer: TaxonJstreeAttributeSerializer
def data
object.name
end
def attr
object
end
def state
"closed"
end
end
end

View File

@@ -2,7 +2,7 @@ class Api::TaxonSerializer < ActiveModel::Serializer
cached
delegate :cache_key, to: :object
attributes :id, :name, :permalink, :icon
attributes :id, :name, :permalink, :icon, :pretty_name, :position, :parent_id, :taxonomy_id
def icon
object.icon(:original)

View File

@@ -1,6 +1,8 @@
class Api::VariantSerializer < ActiveModel::Serializer
attributes :id, :is_master, :on_hand, :name_to_display, :unit_to_display, :unit_value
attributes :options_text, :on_demand, :price, :fees, :price_with_fees, :product_name
attributes :id, :is_master, :product_name, :sku
attributes :options_text, :unit_value, :unit_description, :unit_to_display
attributes :display_as, :display_name, :name_to_display
attributes :price, :on_demand, :on_hand, :fees, :price_with_fees
attributes :tag_list
delegate :price, to: :object

View File

@@ -73,7 +73,9 @@ class EmbeddedPageService
def current_referer
return if @request.referer.blank?
URI(@request.referer).host.downcase
uri = URI(@request.referer)
return if uri.host.blank?
uri.host.downcase
end
def current_referer_without_www

View File

@@ -22,20 +22,36 @@ class LineItemSyncer
def update_item_quantities(order)
changed_subscription_line_items.each do |sli|
line_item = order.line_items.find_by_variant_id(sli.variant_id)
next if update_quantity(line_item, sli)
product_name = "#{line_item.product.name} - #{line_item.full_name}"
order_update_issues.add(order, product_name)
if line_item.blank?
order_update_issues.add(order, sli.variant.product_and_full_name)
next
end
unless update_quantity(line_item, sli)
add_order_update_issue(order, line_item)
end
end
end
def create_new_items(order)
new_subscription_line_items.each do |sli|
order.line_items.create(variant_id: sli.variant_id, quantity: sli.quantity, skip_stock_check: true)
new_line_item = order.line_items.create(variant_id: sli.variant_id,
quantity: sli.quantity,
skip_stock_check: skip_stock_check?(order))
next if skip_stock_check?(order) || new_line_item.sufficient_stock?
order.line_items.delete(new_line_item)
add_order_update_issue(order, new_line_item)
end
end
def destroy_obsolete_items(order)
order.line_items.where(variant_id: subscription_line_items.select(&:marked_for_destruction?).map(&:variant_id)).destroy_all
order.line_items.
where(variant_id: subscription_line_items.
select(&:marked_for_destruction?).
map(&:variant_id)).
destroy_all
end
def changed_subscription_line_items
@@ -48,8 +64,27 @@ class LineItemSyncer
def update_quantity(line_item, sli)
if line_item.quantity == sli.quantity_was
return line_item.update_attributes(quantity: sli.quantity, skip_stock_check: true)
return line_item.update_attributes(quantity: sli.quantity,
skip_stock_check: skip_stock_check?(line_item.order))
end
line_item.quantity == sli.quantity
end
def skip_stock_check?(order)
!order.complete?
end
def add_order_update_issue(order, line_item)
issue_description = "#{line_item.product.name} - #{line_item.variant.full_name}"
issue_description << " - #{stock_issue_description(line_item)}" if line_item.insufficient_stock?
order_update_issues.add(order, issue_description)
end
def stock_issue_description(line_item)
if line_item.variant.in_stock?
I18n.t("admin.subscriptions.stock.insufficient_stock")
else
I18n.t("admin.subscriptions.stock.out_of_stock")
end
end
end

View File

@@ -1,6 +1,5 @@
# Responsible for ensuring that any updates to a Subscription are propagated to any
# orders belonging to that Subscription which have been instantiated
class OrderSyncer
attr_reader :order_update_issues
@@ -11,8 +10,9 @@ class OrderSyncer
end
def sync!
future_and_undated_orders.all? do |order|
order.assign_attributes(customer_id: customer_id, email: customer.andand.email, distributor_id: shop_id)
orders_in_order_cycles_not_closed.all? do |order|
order.assign_attributes(customer_id: customer_id, email: customer.andand.email,
distributor_id: shop_id)
update_associations_for(order)
line_item_syncer.sync!(order)
order.save
@@ -25,7 +25,8 @@ class OrderSyncer
delegate :orders, :bill_address, :ship_address, :subscription_line_items, to: :subscription
delegate :shop_id, :customer, :customer_id, to: :subscription
delegate :shipping_method, :shipping_method_id, :payment_method, :payment_method_id, to: :subscription
delegate :shipping_method, :shipping_method_id,
:payment_method, :payment_method_id, to: :subscription
delegate :shipping_method_id_changed?, :shipping_method_id_was, to: :subscription
delegate :payment_method_id_changed?, :payment_method_id_was, to: :subscription
@@ -36,9 +37,10 @@ class OrderSyncer
update_payment_for(order) if payment_method_id_changed?
end
def future_and_undated_orders
return @future_and_undated_orders unless @future_and_undated_orders.nil?
@future_and_undated_orders = orders.joins(:order_cycle).merge(OrderCycle.not_closed).readonly(false)
def orders_in_order_cycles_not_closed
return @orders_in_order_cycles_not_closed unless @orders_in_order_cycles_not_closed.nil?
@orders_in_order_cycles_not_closed = orders.joins(:order_cycle).
merge(OrderCycle.not_closed).readonly(false)
end
def update_bill_address_for(order)
@@ -49,7 +51,8 @@ class OrderSyncer
end
def update_payment_for(order)
payment = order.payments.with_state('checkout').where(payment_method_id: payment_method_id_was).last
payment = order.payments.
with_state('checkout').where(payment_method_id: payment_method_id_was).last
if payment
payment.andand.void_transaction!
order.payments.create(payment_method_id: payment_method_id, amount: order.reload.total)

View File

@@ -9,8 +9,8 @@ class SubscriptionValidator
attr_reader :subscription
validates_presence_of :shop, :customer, :schedule, :shipping_method, :payment_method
validates_presence_of :bill_address, :ship_address, :begins_at
validates :shop, :customer, :schedule, :shipping_method, :payment_method, presence: true
validates :bill_address, :ship_address, :begins_at, presence: true
validate :shipping_method_allowed?
validate :payment_method_allowed?
validate :payment_method_type_allowed?

View File

@@ -2,8 +2,8 @@
%h1.page-title
=t :customers
- content_for :app_wrapper_attrs do
= "ng-app='admin.customers'"
- content_for :main_ng_app_name do
= "admin.customers"
- content_for :page_actions do
%li

View File

@@ -4,8 +4,8 @@
= t('.editing')
= @enterprise.name
- content_for :app_wrapper_attrs do
= "ng-app='admin.enterprises'"
- content_for :main_ng_app_name do
= "admin.enterprises"
- content_for :page_actions do
%li= select :enterprise, :id, options_for_select(editable_enterprises.collect {|e| [e.name, e.id, {:'data-url' => "#{main_app.edit_admin_enterprise_path(e.permalink)}", :'ng-selected' => "selected==#{e.id}"}]}, @enterprise.id ), {}, {:'enterprise-switcher' => '', 'data-initial' => "#{@enterprise.id}", :'ng-init' => "selected='#{@enterprise.id}'", :'ng-model' => 'selected', :id => 'enterprise_switcher', :class => 'select2'}

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