Compare commits

..

407 Commits

Author SHA1 Message Date
Pau Perez
8ccc8dfaf6 Update all locales with the latest Transifex translations 2020-03-12 13:33:42 +01:00
Luis Ramos
55b32c828c Merge pull request #4978 from Matt-Yorkley/dev-env-reload
Fix reloading issue in dev environment
2020-03-12 12:22:00 +00:00
Pau Pérez Fabregat
25dfd8ad40 Merge pull request #4939 from openfoodfoundation/transifex
Transifex
2020-03-12 13:19:59 +01:00
Pau Pérez Fabregat
2a5311493f Merge pull request #4969 from luisramos0/oc_apli
Fix spec in rails 4 branch by making code in OrderCycleFormApplicator a bit more resilient
2020-03-12 12:51:23 +01:00
Pau Pérez Fabregat
57ac28cfbd Merge pull request #4970 from openfoodfoundation/dependabot/bundler/ddtrace-0.33.1
Bump ddtrace from 0.33.0 to 0.33.1
2020-03-12 12:50:01 +01:00
Pau Pérez Fabregat
fb02043e6e Merge pull request #4926 from luisramos0/prod_api
Fix products api spec in rails 4
2020-03-12 12:46:45 +01:00
Transifex-Openfoodnetwork
30d7cc89fa Updating translations for config/locales/pt_BR.yml 2020-03-12 09:25:51 +11:00
Transifex-Openfoodnetwork
d14b5eb46b Updating translations for config/locales/pt_BR.yml 2020-03-12 09:22:44 +11:00
Matt-Yorkley
933b5f1606 Fix reloading issue in dev environment
I constantly get `NameError: uninitialized constant Spree::AuthenticationHelpers` when touching local files and then reloading a page, and have to restart my rails server every time (in development). I read the other day that this is the best way to fix the issue, and it seems to work...
2020-03-11 15:31:25 +01:00
Transifex-Openfoodnetwork
4c7b8209b9 Updating translations for config/locales/nb.yml 2020-03-11 19:49:14 +11:00
Pau Pérez Fabregat
802ac647e3 Merge pull request #4879 from coopdevs/inner-join-visible-orders
Inner join visible orders
2020-03-10 22:54:03 +01:00
dependabot-preview[bot]
c83bded763 Bump ddtrace from 0.33.0 to 0.33.1
Bumps [ddtrace](https://github.com/DataDog/dd-trace-rb) from 0.33.0 to 0.33.1.
- [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.33.0...v0.33.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-10 19:19:31 +00:00
Luis Ramos
03246d425d Make this method handle the case where the variants hash passed is nil
This fixes a spec in the rails 4 branch
2020-03-10 18:41:26 +00:00
Luis Ramos
7585e3d1d6 The variants_to_a method was dead but actually we can use it to make the code simpler 2020-03-10 18:40:46 +00:00
Pau Pérez Fabregat
50cdda7c63 Merge pull request #4802 from luisramos0/too_many
Last batch to fix error "subquery with too many columns" in rails 4 branch
2020-03-10 09:20:44 +01:00
Pau Pérez Fabregat
d0af046e59 Merge pull request #4908 from luisramos0/package_spec
Make package spec work in rails 4
2020-03-10 09:17:53 +01:00
Pau Pérez Fabregat
5811f3ead1 Merge pull request #4905 from luisramos0/untouch
Remove some live but elderly debug code
2020-03-10 09:17:13 +01:00
Pau Pérez Fabregat
d7d3c9ea53 Merge pull request #4938 from openfoodfoundation/dependabot/bundler/ddtrace-0.33.0
Bump ddtrace from 0.32.0 to 0.33.0
2020-03-10 08:48:31 +01:00
Pau Pérez Fabregat
a02cc1de34 Merge pull request #4857 from luisramos0/schedules_ctrl
Remove dead spec in SchedulesController
2020-03-10 08:38:46 +01:00
Luis Ramos
2184c7c06b Merge pull request #4856 from Matt-Yorkley/dead-code
Delete some dead code in Product Import (fixes 1 broken spec)
2020-03-07 15:26:39 +00:00
Transifex-Openfoodnetwork
928bf0d9c7 Updating translations for config/locales/fr.yml 2020-03-08 01:24:08 +11:00
Transifex-Openfoodnetwork
0d02b2afcf Updating translations for config/locales/en_FR.yml 2020-03-08 01:21:12 +11:00
Transifex-Openfoodnetwork
1e76f3f744 Updating translations for config/locales/fr.yml 2020-03-08 01:20:57 +11:00
dependabot-preview[bot]
7c3a0a292f Bump ddtrace from 0.32.0 to 0.33.0
Bumps [ddtrace](https://github.com/DataDog/dd-trace-rb) from 0.32.0 to 0.33.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.32.0...v0.33.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-06 19:31:47 +00:00
Luis Ramos
c5ca0976a5 Merge pull request #4873 from jeduardo824/ampersand-not-showing-correctly
fix ampersand problem using ng-bind-html
2020-03-06 17:40:54 +00:00
Pau Pérez Fabregat
be7b3d5a12 Merge pull request #4809 from jeduardo824/redirect-to-shops-when-shop-does-not-exist
redirect to shops list when an enterprise is not found
2020-03-06 18:39:00 +01:00
Luis Ramos
6304a085c0 Update all locales with the latest Transifex translations 2020-03-06 08:30:04 +00:00
Luis Ramos
7c708de937 Merge pull request #4928 from openfoodfoundation/transifex
Transifex
2020-03-06 08:28:09 +00:00
Transifex-Openfoodnetwork
5d51e5d393 Updating translations for config/locales/pt_BR.yml 2020-03-06 07:41:46 +11:00
Transifex-Openfoodnetwork
464717dec5 Updating translations for config/locales/pt_BR.yml 2020-03-06 07:38:36 +11:00
Pau Pérez Fabregat
7a06018c3e Merge pull request #4874 from openfoodfoundation/transifex
Transifex
2020-03-05 19:29:21 +01:00
Pau Pérez Fabregat
b8c76ff633 Merge pull request #4906 from luisramos0/ent_caching
Fix enterprise_caching_spec in rails 4
2020-03-05 19:28:54 +01:00
Pau Pérez Fabregat
1ecc0bfe07 Merge pull request #4927 from luisramos0/variants_delete
Fix spree/admin/variants_controller_spec.rb in rails 4
2020-03-05 19:24:35 +01:00
Pau Pérez Fabregat
600d2d23c8 Merge pull request #4912 from luisramos0/cart_serv_fix
Make cart_service spec green in rails 4 branch
2020-03-05 19:11:58 +01:00
Pau Pérez Fabregat
bf3211fd01 Merge pull request #4918 from luisramos0/bulk_lis
Fix spec/controllers/admin/bulk_line_items_controller_spec in rails 4
2020-03-05 19:07:37 +01:00
Pau Pérez Fabregat
5fd0d9406d Merge pull request #4923 from openfoodfoundation/dependabot/bundler/oj-3.10.5
Bump oj from 3.10.3 to 3.10.5
2020-03-05 19:06:20 +01:00
Pau Pérez Fabregat
c78a6bea91 Merge pull request #4921 from luisramos0/li_ctrl
Fix line_items_controller_spec in the rails 4 branch
2020-03-05 19:05:46 +01:00
Pau Pérez Fabregat
be9f33312b Merge pull request #4904 from luisramos0/tax_rates_match
Move TaxRate#match to OFN to avoid having to adapt to the spree 2.1 version
2020-03-05 18:55:55 +01:00
Luis Ramos
f23575302b In rails 4 variant.destroy is removing the variants from the exchanges as needed and variant.exchange_variants becomes immediatly empty but variant.exchanges is not automatically updated anymore and needs a refresh to become empty 2020-03-05 17:07:08 +00:00
Pau Perez
0042ab2f28 Rewrite INNER JOIN in ActiveRecord's DSL 2020-03-05 17:45:06 +01:00
Pau Perez
53a63775fe Replace LEFT JOIN with INNER JOIN
I see no reason why a LEFT might be needed and its the root cause of the
awful performance.
2020-03-05 17:45:06 +01:00
Pau Perez
461b1b26f3 Add controller tests to cover totals by supplier 2020-03-05 17:45:06 +01:00
Luis Ramos
f13d7d6845 Fix products api spec in rails 4 2020-03-05 15:20:45 +00:00
dependabot-preview[bot]
e4d09b5404 Bump oj from 3.10.3 to 3.10.5
Bumps [oj](https://github.com/ohler55/oj) from 3.10.3 to 3.10.5.
- [Release notes](https://github.com/ohler55/oj/releases)
- [Changelog](https://github.com/ohler55/oj/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/ohler55/oj/compare/v3.10.3...v3.10.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-04 19:16:40 +00:00
Luis Ramos
415415273c In rails 4 we need to update the stub after we update the order.user otherwise the stub will return the previous value 2020-03-04 15:50:52 +00:00
Luis Ramos
d969190ca5 Bypass problem with quick_login_as_admin in rails 4 and just user simple factory 2020-03-04 14:29:11 +00:00
Luis Ramos
a180576c0a Make cart_service spec green in rails 4 branch 2020-03-03 17:29:38 +00:00
Luis Ramos
7fdaa0f0c7 Make package spec work in rails 4 by persisting the test enterprises so that the copnnection between shipping methods and enterprises works 2020-03-03 14:46:12 +00:00
Luis Ramos
ba750547a2 The touch process in 'belongs_to :supplier, class_name: 'Enterprise', touch: true' must have changed in rails 4 and now we need to reload the enterprise to get the new updated_at value 2020-03-03 12:26:18 +00:00
Luis Ramos
af8369ae1b Remove 5 years old debug code
This reverts ab9bc7b1dc, it can be added if the issue happens again
2020-03-03 10:56:57 +00:00
Luis Ramos
829a73c58d Merge pull request #4886 from openfoodfoundation/dependabot/bundler/oj-3.10.3
Bump oj from 3.10.2 to 3.10.3
2020-03-03 09:57:46 +00:00
Luis Ramos
a2691df64e Merge pull request #4887 from openfoodfoundation/dependabot/bundler/rubocop-0.80.1
Bump rubocop from 0.80.0 to 0.80.1
2020-03-03 09:56:37 +00:00
Luis Ramos
6c8b175344 Merge match and its alias method 2020-03-03 09:29:02 +00:00
Pau Pérez Fabregat
ad10053271 Merge pull request #4903 from luisramos0/address_finder
[Spree 2.1] Adapt address finder spec to work with spree 2.1 code
2020-03-03 10:27:13 +01:00
Luis Ramos
a508c55700 Bring TaxRate.match to OFN
The version of this method in spree 2.1 will break our build

This way we simply bypass this fix in spree: https://github.com/spree/spree/pull/3669

We can get back to this in the future if we ever experience the mentioned bug
2020-03-03 09:27:04 +00:00
Transifex-Openfoodnetwork
2712be3fa4 Updating translations for config/locales/fr.yml 2020-03-03 14:14:38 +11:00
Transifex-Openfoodnetwork
484326561f Updating translations for config/locales/en_GB.yml 2020-03-03 14:11:28 +11:00
Transifex-Openfoodnetwork
7ea96f88e8 Updating translations for config/locales/en_CA.yml 2020-03-03 14:08:26 +11:00
Transifex-Openfoodnetwork
de752b05a7 Updating translations for config/locales/fr_CA.yml 2020-03-03 14:08:17 +11:00
Maikel
0b18344572 Merge pull request #4790 from mkllnk/4779-payment-method-display
4779 payment method display
2020-03-03 10:10:51 +11:00
Luis Ramos
690474c01a Adapt address finder spec to work with spree 2.1 code
Order ship address is required to get have an order with shipping rates
2020-03-02 21:55:21 +00:00
dependabot-preview[bot]
e4c5893c1e Bump rubocop from 0.80.0 to 0.80.1
Bumps [rubocop](https://github.com/rubocop-hq/rubocop) from 0.80.0 to 0.80.1.
- [Release notes](https://github.com/rubocop-hq/rubocop/releases)
- [Changelog](https://github.com/rubocop-hq/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop-hq/rubocop/compare/v0.80.0...v0.80.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-02 19:36:43 +00:00
dependabot-preview[bot]
67aeae4a6d Bump oj from 3.10.2 to 3.10.3
Bumps [oj](https://github.com/ohler55/oj) from 3.10.2 to 3.10.3.
- [Release notes](https://github.com/ohler55/oj/releases)
- [Changelog](https://github.com/ohler55/oj/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/ohler55/oj/compare/v3.10.2...v3.10.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-03-02 19:34:09 +00:00
Luis Ramos
c37218fdc5 Merge pull request #4719 from luisramos0/stripe_card_to_pm
Make StripeSCA payment method work with existing credit cards (the ones saved through the Stripe Charges API)
2020-03-02 17:22:07 +00:00
Luis Ramos
dad21a52b2 Merge pull request #4672 from luisramos0/stripe_sca_method
Add new Stripe payment method compatible with the new Stripe Payment Intents API
2020-03-02 17:19:05 +00:00
Pau Pérez Fabregat
97a65d760f Merge pull request #4527 from luisramos0/subs_logs
Improve Subscriptions logging
2020-03-02 15:48:45 +01:00
Transifex-Openfoodnetwork
63e92197f5 Updating translations for config/locales/pt_BR.yml 2020-03-02 09:40:20 +11:00
Transifex-Openfoodnetwork
fd534bf629 Updating translations for config/locales/pt_BR.yml 2020-03-02 09:37:10 +11:00
Eduardo
64d83bfc4d fix ampersand problem using ng-bind-html 2020-03-01 17:54:36 -03:00
Pau Pérez Fabregat
83065a798e Merge pull request #4814 from luisramos0/rubop_rules
Add new cops (disabled) to rubocop config
2020-02-28 11:15:34 +01:00
Matt-Yorkley
b661b3ee40 Merge pull request #4823 from luisramos0/require_specs
Add some require statements to specs
2020-02-28 10:46:29 +01:00
Luis Ramos
b528903aa8 Remove spec covering html format in SchedulesController#index, this is not used anywhere 2020-02-27 19:05:36 +00:00
Matt-Yorkley
38215c2a88 Delete some dead code
This feature for assigning defaults via the UI was previously removed
2020-02-27 19:28:25 +01:00
Matt-Yorkley
d280bf0d4d Update all locales with the latest Transifex translations 2020-02-27 11:42:02 +01:00
Eduardo
4c3916a93d redirect to shops list when an enterprise is not found 2020-02-26 19:25:38 -03:00
Luis Ramos
677f31ffa8 Make payment source_views/gateway work with nil credit card
This will happen if user deletes a saved credit card used previously. In this case, the admin payment details page will render empty details and the payment amount
2020-02-26 11:55:17 +00:00
Luis Ramos
5848a46149 Add missing template to render stripeSCA payment and add spec to verify it's presence 2020-02-26 11:38:42 +00:00
Luis Ramos
03c91dfac1 Merge pull request #4780 from luisramos0/bulk_prod_errors
Fix javascript logic that parses server errors in the bulk product edit page
2020-02-25 18:49:54 +00:00
Luis Ramos
60e12063cd Merge pull request #4758 from luisramos0/fix_incomplete_stripe
Make the payment methods filter handle misconfigured stripe payment methods
2020-02-25 18:47:09 +00:00
Pau Pérez Fabregat
e5b57af315 Merge pull request #4815 from openfoodfoundation/transifex
Transifex
2020-02-25 13:37:30 +01:00
Pau Pérez Fabregat
a396a7f0af Merge pull request #4818 from luisramos0/delete_dead_code
Delete dead code after PRs 4512 and 4508
2020-02-25 13:32:23 +01:00
Transifex-Openfoodnetwork
d084789c56 Updating translations for config/locales/nb.yml 2020-02-25 19:57:08 +11:00
Transifex-Openfoodnetwork
dafac32e70 Updating translations for config/locales/nb.yml 2020-02-25 19:53:59 +11:00
Transifex-Openfoodnetwork
6ca39f3aa5 Updating translations for config/locales/fr_CA.yml 2020-02-25 09:10:13 +11:00
Transifex-Openfoodnetwork
234a9ef1b4 Updating translations for config/locales/en_CA.yml 2020-02-25 08:41:07 +11:00
Luis Ramos
24a1327805 Merge pull request #4785 from openfoodfoundation/dependabot/bundler/stripe-5.15.0
Bump stripe from 5.11.0 to 5.15.0
2020-02-24 20:12:39 +00:00
Luis Ramos
33d77d57f4 Merge pull request #4776 from luisramos0/remove_assets_group
Remove the assets group from the gemfile (taken from spree upgrade branch)
2020-02-24 20:12:01 +00:00
Transifex-Openfoodnetwork
0571b657aa Updating translations for config/locales/en_FR.yml 2020-02-25 04:39:02 +11:00
Transifex-Openfoodnetwork
e4958baddc Updating translations for config/locales/en_FR.yml 2020-02-25 04:35:52 +11:00
Transifex-Openfoodnetwork
c985747297 Updating translations for config/locales/fr.yml 2020-02-25 04:31:33 +11:00
Luis Ramos
03fac6f285 Avoid subquery with too many columns error by specifying the selected column 2020-02-23 20:05:13 +00:00
Transifex-Openfoodnetwork
f5ffdfc258 Updating translations for config/locales/en_NZ.yml 2020-02-23 22:32:56 +11:00
Luis Ramos
2108a282c8 Add some require statements to specs 2020-02-22 11:49:52 +00:00
Luis Ramos
a3a61967a8 Merge pull request #4621 from luisramos0/spree_backend_js
OFN without spree_backend 🎉
2020-02-22 10:24:50 +00:00
luisramos0
404e7c1f37 Make credit card cloner clone the payment method even if the customer is not given
This makes the payments without saving card work again in the frontoffice as well as the payments taken by the seller in the backoffice
2020-02-21 14:11:13 +00:00
Luis Ramos
1bdeda4a21 Delete dead code after PRs 4512 and 4508 2020-02-21 12:25:07 +00:00
Luis Ramos
47916f823f Add spec to credit card cloner. No customer given. 2020-02-21 10:56:32 +00:00
Luis Ramos
ab4add1954 Fix CreditCardCloner basic spec 2020-02-21 10:56:32 +00:00
Luis Ramos
10fff31dca Fix stripe_sca spec 2020-02-21 10:56:32 +00:00
Luis Ramos
7fb85092ce Remove duplicate customers stubs 2020-02-21 10:56:32 +00:00
Luis Ramos
7584e96759 Make customer stub always return the same customer id
I cant make stripe customers stub return different customer_ids based on the stripe_account header
2020-02-21 10:56:32 +00:00
Luis Ramos
f8ab64d71e Move specs around in stripe_sca_spec so we can re-use the cloning stubs when storing a new card and when re-using a new card 2020-02-21 10:56:32 +00:00
Luis Ramos
ccb4c77d1f Adapt credit card cloner to not clone card if it's a card to be used only once
Adapt stripe_sca specs to new cloner logic
2020-02-21 10:56:32 +00:00
luisramos0
5ef1510fc7 Adapt CreditCard cloner to clone not 'cards of the platform account to payment_methods of the connected accounts' but instead 'cards or payment_methods of the platform account to payment_methods of the connected accounts'
This process mimicks the existing process of generating a token on the connected account from a card on the platform account. In the Payment Intents API we need to create a payment method in the connected account, a token is not enough
2020-02-21 10:56:32 +00:00
luisramos0
1afd712ff4 Make StripeSCA store cards (and delete them) on the Stripe platform account and not the Stripe Connected account (the sellers accounts)
This is important so that cards can be re-used across sellers in OFN
2020-02-21 10:56:32 +00:00
luisramos0
699110258b Add spec for credit_card_cloner 2020-02-21 10:56:32 +00:00
luisramos0
3fb1df9bb3 Rename CardCloner to CreditCardCloner because it's dependent on Spree:CreditCard attributes 2020-02-21 10:56:32 +00:00
luisramos0
14c03ead31 Extract CardCloner to separate class 2020-02-21 10:56:32 +00:00
luisramos0
4480c2f0f0 Add logic to stripe_sca gateway to handle cards stored in the platform account with the stripe Charges API: card_* 2020-02-21 10:56:32 +00:00
luisramos0
b3ac5d8f41 Improve code readability a little 2020-02-21 10:52:56 +00:00
luisramos0
6fb74c88cd Fix a typo 2020-02-21 10:52:56 +00:00
luisramos0
38fd028a9f Fix some rubocop issues from previous commit 2020-02-21 10:52:56 +00:00
luisramos0
4e84310d63 Add StripeSCA where StripeConnect is treated as an exception in the setting up of process of a payment method and subscriptions
Here we are copy pasting and adding stripe SCA because we are planning to delete the StripeConnect that will be replaced by the stripe sca implementation
2020-02-21 10:52:56 +00:00
luisramos0
66440f9e4c Add missing translations for new payment method stripe sca 2020-02-21 10:52:56 +00:00
luisramos0
b8457ebece Make profile storer a bit easier to read 2020-02-21 10:52:56 +00:00
Luis Ramos
668fd1c7c0 Add spec for profile storer to cover happy path for both response attribute cases: existin stripe integration and new stripe sca 2020-02-21 10:52:55 +00:00
Luis Ramos
aff934c814 Remove unnecessary test setup code 2020-02-21 10:52:55 +00:00
Luis Ramos
6bb04f6cc6 Adapt stripe_sca_spec to actual stripe SCA API 2020-02-21 10:52:55 +00:00
luisramos0
0e815439b3 Duplicate stripe_connect_spec and adapt to new stripe_sca
stripe_connect_spec will be deleted at some point when all users are migrated to the sca api
2020-02-21 10:52:55 +00:00
luisramos0
c7b01c37af Fix a problem in credit cards controller spec and test case where stripe_account_id must be included in the stripe api call 2020-02-21 10:52:55 +00:00
luisramos0
ac8f3c811f Fix rubocop issues in some stripe integration related files 2020-02-21 10:52:55 +00:00
luisramos0
1b820ea85c Fix rubocop issues in credit_cards_controller 2020-02-21 10:52:55 +00:00
luisramos0
ec7b91bb68 Make ProfileStorer a bit easier to read 2020-02-21 10:52:29 +00:00
luisramos0
c773cde191 Add admin payment template for stripe sca and respective js code to make it work 2020-02-21 10:52:29 +00:00
luisramos0
db1065a69e Make saving a card on checkout work with the payment intents api by making profile storer work with the slightly different api responses from stripe 2020-02-21 10:52:29 +00:00
luisramos0
9fa4bad0b4 Add stripe SCA checkotu payment template and move stripe object definition to it and the other stripe template
We need to set the stripe object with the stripe account id to work with the payment intents api but we cannot set it to work with the stripe charges api

This makes the two payment methods incompatible: a given enterprise cannot use both the old stripe integration and this new one at the same time.
2020-02-21 10:52:29 +00:00
luisramos0
a52c4b542c Make destroy stored cards work for stripe SCA by setting stripe account id before making the call to the stripe api
This account id cannot be sent when dealing with the old StripeConnect gateway
2020-02-21 10:52:29 +00:00
luisramos0
283abf9a88 Remove dead code from Stripe connect gateway
Update Source is dead since a74c502fd9
2020-02-21 10:52:29 +00:00
luisramos0
f691d1aafd Add new payment method StripeSCA that will use the Stripe Payment Intents API instead of the Stripe Charges API that the current StripeConnect gatreway uses 2020-02-21 10:52:29 +00:00
luisramos0
5724c3bb0a Add code from ActiveMerchant v1.98.0 that supports the Stripe Payment Intents API
This commit can be reverted once we upgrade to v1.98.0
2020-02-21 10:52:29 +00:00
Transifex-Openfoodnetwork
49ba83da6d Updating translations for config/locales/en_GB.yml 2020-02-21 05:32:39 +11:00
Transifex-Openfoodnetwork
19d1497c4b Updating translations for config/locales/en_GB.yml 2020-02-21 05:29:31 +11:00
Luis Ramos
06200c9d3c Add new cops (disabled) to rubocop config 2020-02-20 18:04:43 +00:00
Luis Ramos
2412658e51 Update db/schema timestamp according to last change 2020-02-20 11:41:49 +00:00
Luis Ramos
0c4f22f847 Fix images/new.js path and add simple spec to verify the page loads correctly
Testing the file upload would be a bit more complicated
2020-02-20 11:18:22 +00:00
Luis Ramos
1803ea3c38 Add traling breakline to case where errors come in a array 2020-02-20 10:06:10 +00:00
Pau Pérez Fabregat
93fda02e43 Merge pull request #4803 from openfoodfoundation/dependabot/bundler/rubocop-0.80.0
Bump rubocop from 0.79.0 to 0.80.0
2020-02-20 09:34:10 +01:00
Pau Pérez Fabregat
77958f9afe Merge pull request #4796 from openfoodfoundation/dependabot/bundler/i18n-js-3.6.0
Bump i18n-js from 3.5.1 to 3.6.0
2020-02-20 09:32:02 +01:00
Maikel Linke
82e402f31a Update translations from Transifex 2020-02-20 16:20:06 +11:00
Maikel Linke
03fa3e2269 Find last payment deterministically 2020-02-20 15:59:57 +11:00
Maikel Linke
11fbe7d5c9 Show last payment method in order confirmations 2020-02-20 15:59:57 +11:00
Maikel Linke
799c1f08de Optimise finding last payment
Suggested by Rubocop.
2020-02-20 15:59:56 +11:00
Maikel Linke
6b66458bfd Replace andand with new Ruby syntax 2020-02-20 15:59:56 +11:00
Maikel Linke
3e0a5bac6a Move helper to service for re-use 2020-02-20 15:59:56 +11:00
Maikel Linke
2c2023df03 Show last payment method in order confirmation
If we had multiple failed payments and then a successful payment, the
order confirmation was displaying the payment method of the first failed
payment. That was confusing and is now changed to the last payment
method.
2020-02-20 15:59:56 +11:00
Maikel Linke
7306d379a5 Display payment method literally
Don't allow for HTML and potentially bad scripts. But this also prevents
accidental display errors. If someone wrote, "We only take <cash>", it
would mess with the site.
2020-02-20 15:59:56 +11:00
Maikel Linke
e15c61d862 Add spec for order confirmation view 2020-02-20 15:59:56 +11:00
Maikel
35aeb98d45 Merge pull request #4792 from openfoodfoundation/transifex
Transifex
2020-02-20 10:43:45 +11:00
Luis Ramos
d99cba3b6e Merge pull request #4709 from mkllnk/4172-js-pluralize
Pluralize common variant unit names
2020-02-19 22:28:54 +00:00
dependabot-preview[bot]
4c6fd96bcc Bump rubocop from 0.79.0 to 0.80.0
Bumps [rubocop](https://github.com/rubocop-hq/rubocop) from 0.79.0 to 0.80.0.
- [Release notes](https://github.com/rubocop-hq/rubocop/releases)
- [Changelog](https://github.com/rubocop-hq/rubocop/blob/master/CHANGELOG.md)
- [Commits](https://github.com/rubocop-hq/rubocop/compare/v0.79.0...v0.80.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-18 19:18:53 +00:00
Luis Ramos
1eba17f048 Make select column explicit to avoid too many columns sql error 2020-02-18 18:32:52 +00:00
dependabot-preview[bot]
ff088c6203 Bump stripe from 5.11.0 to 5.15.0
Bumps [stripe](https://github.com/stripe/stripe-ruby) from 5.11.0 to 5.15.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/v5.11.0...v5.15.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-18 12:01:10 +00:00
Luis Ramos
a1cb6928db Merge pull request #4793 from openfoodfoundation/dependabot/bundler/webmock-3.8.2
Bump webmock from 3.8.1 to 3.8.2
2020-02-18 11:59:14 +00:00
Luis Ramos
40a5b60dcb Merge pull request #4794 from openfoodfoundation/dependabot/bundler/oauth2-1.4.4
Bump oauth2 from 1.4.3 to 1.4.4
2020-02-18 11:58:58 +00:00
Luis Ramos
2711736004 Use Array#join and make code simpler 2020-02-18 10:49:41 +00:00
Luis Ramos
18c165e893 Merge pull request #4784 from CSCI-462-01-2020/Issue4731
Add Order Cycle Button Tooltips
2020-02-17 19:32:39 +00:00
Luis Ramos
0aaa04295b Improve and unit test errorsParser 2020-02-17 11:21:21 +00:00
Luis Ramos
7639e9a38d Extrac ErrorsParser to separate class and make it handle the rails error structure with keys 2020-02-17 11:21:21 +00:00
Transifex-Openfoodnetwork
d783bd771f Updating translations for config/locales/ar.yml 2020-02-15 09:33:06 +11:00
Transifex-Openfoodnetwork
9dd9d14107 Updating translations for config/locales/ar.yml 2020-02-15 09:29:56 +11:00
Transifex-Openfoodnetwork
e942266dd7 Updating translations for config/locales/pt_BR.yml 2020-02-15 07:05:18 +11:00
dependabot-preview[bot]
c8f78904d6 Bump i18n-js from 3.5.1 to 3.6.0
Bumps [i18n-js](https://github.com/fnando/i18n-js) from 3.5.1 to 3.6.0.
- [Release notes](https://github.com/fnando/i18n-js/releases)
- [Changelog](https://github.com/fnando/i18n-js/blob/master/CHANGELOG.md)
- [Commits](https://github.com/fnando/i18n-js/compare/v3.5.1...v3.6.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-14 19:24:49 +00:00
Transifex-Openfoodnetwork
a982fd1e2b Updating translations for config/locales/tr.yml 2020-02-14 22:27:33 +11:00
Transifex-Openfoodnetwork
7e8b2f6be5 Updating translations for config/locales/tr.yml 2020-02-14 22:24:23 +11:00
Transifex-Openfoodnetwork
921c7bbc3a Updating translations for config/locales/tr.yml 2020-02-14 22:21:12 +11:00
Transifex-Openfoodnetwork
eaff6b0c68 Updating translations for config/locales/nb.yml 2020-02-14 19:26:01 +11:00
Transifex-Openfoodnetwork
e1ab424481 Updating translations for config/locales/nb.yml 2020-02-14 19:22:51 +11:00
Transifex-Openfoodnetwork
e59c9720fc Updating translations for config/locales/en_GB.yml 2020-02-14 06:53:13 +11:00
dependabot-preview[bot]
b25f0007f0 Bump oauth2 from 1.4.3 to 1.4.4
Bumps [oauth2](https://github.com/oauth-xx/oauth2) from 1.4.3 to 1.4.4.
- [Release notes](https://github.com/oauth-xx/oauth2/releases)
- [Changelog](https://github.com/oauth-xx/oauth2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/oauth-xx/oauth2/compare/v1.4.3...v1.4.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-13 19:19:44 +00:00
dependabot-preview[bot]
65c5cdd52f Bump webmock from 3.8.1 to 3.8.2
Bumps [webmock](https://github.com/bblimke/webmock) from 3.8.1 to 3.8.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.8.1...v3.8.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-13 19:16:18 +00:00
Transifex-Openfoodnetwork
a2873ea553 Updating translations for config/locales/fr.yml 2020-02-14 05:05:51 +11:00
Transifex-Openfoodnetwork
3a593ff255 Updating translations for config/locales/fr.yml 2020-02-14 05:02:42 +11:00
Transifex-Openfoodnetwork
92e1193ffb Updating translations for config/locales/en_FR.yml 2020-02-14 05:01:02 +11:00
Transifex-Openfoodnetwork
016968dcb9 Updating translations for config/locales/fr.yml 2020-02-14 04:59:33 +11:00
Luis Ramos
9d8608f210 Merge pull request #4630 from Matt-Yorkley/product_counts
Show counts including all variants in order cycle exchanges
2020-02-13 11:33:58 +00:00
Luis Ramos
323ca906bc Merge pull request #4759 from pacodelaluna/order-admin-products
Order admin products
2020-02-13 11:33:05 +00:00
Luis Ramos
c43b34e0fa Merge pull request #4760 from luisramos0/checkout_ctrl
Merge Spree::CheckoutController with CheckoutController and clean it up
2020-02-13 11:31:15 +00:00
Luis Ramos
bc7f0e0962 Update all locales with the latest Transifex translations 2020-02-13 11:19:07 +00:00
Luis Ramos
cf4f7c562a Merge pull request #4778 from openfoodfoundation/transifex
Transifex
2020-02-13 11:08:01 +00:00
François Turbelin
4c7bd4d6a8 Fix mess with order 2020-02-13 06:38:13 +01:00
François Turbelin
523b266308 Put back created_at desc as default order 2020-02-13 06:38:13 +01:00
François Turbelin
212413c8b3 Avoid mutable q params 2020-02-13 06:38:13 +01:00
François Turbelin
b248dc598e Cosmetics 2020-02-13 06:38:13 +01:00
François Turbelin
e7b74b99ba Refactor SortingOptions JS 2020-02-13 06:38:13 +01:00
François Turbelin
89d2750fc4 Set default value at backend side 2020-02-13 06:38:13 +01:00
François Turbelin
7100111f93 Fix specs and cosmetics 2020-02-13 06:38:13 +01:00
François Turbelin
3dcb66014e Factorize column sorter partial 2020-02-13 06:38:13 +01:00
François Turbelin
06971b7198 Add sortable name column for Admin Products 2020-02-13 06:38:13 +01:00
François Turbelin
56f9adc5b7 Filter Admin products by name asc 2020-02-13 06:38:13 +01:00
Luis Ramos
38374a9835 Merge pull request #4761 from openfoodfoundation/dependabot/bundler/unicorn-5.5.3
Bump unicorn from 5.5.2 to 5.5.3
2020-02-12 20:56:19 +00:00
Luis Ramos
8d6a8ee214 Merge pull request #4763 from mkllnk/rails4-form-rendering
Future proof form rendering in admin orders
2020-02-12 20:56:00 +00:00
blainebillings
fec653186a Add Order Cycle Button Tooltips 2020-02-11 10:10:39 -05:00
Transifex-Openfoodnetwork
ebe7456b66 Updating translations for config/locales/tr.yml 2020-02-11 21:48:53 +11:00
Transifex-Openfoodnetwork
8187669a25 Updating translations for config/locales/tr.yml 2020-02-11 21:45:44 +11:00
Transifex-Openfoodnetwork
a6aa0df53b Updating translations for config/locales/fr_BE.yml 2020-02-10 03:32:33 +11:00
Transifex-Openfoodnetwork
116695b1d9 Updating translations for config/locales/en_NZ.yml 2020-02-08 18:53:00 +11:00
Transifex-Openfoodnetwork
387ac40dc9 Updating translations for config/locales/en_NZ.yml 2020-02-08 18:49:51 +11:00
luisramos0
66320b5055 Remove the assets group from the gemfile, it will disappear in rails 4 2020-02-07 12:29:02 +00:00
luisramos0
858d2cc6c2 Add doc to Spree::CheckoutController to make it more obvious why this controller exists 2020-02-07 11:50:23 +00:00
luisramos0
43280da187 Dup params to avoid nasty effects of a mutated params object in the controller 2020-02-07 10:26:04 +00:00
luisramos0
3b399b899c Extract methods in subscription_placement_job to fix rubocop complexity issues 2020-02-07 10:06:59 +00:00
luisramos0
01d69c89aa Add some log messages to help debug problems in subscription placement and subscription confirmation processes 2020-02-07 10:06:58 +00:00
luisramos0
a2801e40a2 Improve readability of proxy_order_syncer and add some log messages 2020-02-07 10:06:58 +00:00
luisramos0
abd4f0b923 Add custom_data column to paper_trail versions table so we can track a specific list of ids in a model
Activate paper_trail in order_cycles and schedules and track each others ids

An alternative way of doing this would be to use a gem for paper_trail associations but this way we avoid adding a new dependency to the app
2020-02-07 10:06:58 +00:00
Luis Ramos
e1eface5f8 Merge pull request #4542 from luisramos0/logger
Add timestamp to log entries
2020-02-07 10:02:55 +00:00
Luis Ramos
5cd14253d0 Merge pull request #4770 from openfoodfoundation/dependabot/bundler/webmock-3.8.1
Bump webmock from 3.8.0 to 3.8.1
2020-02-07 09:31:19 +00:00
Maikel
be691df7ac Merge pull request #4769 from openfoodfoundation/transifex
Transifex
2020-02-07 18:09:31 +11:00
Maikel Linke
7783b28ca2 Update concurrency spec after refactor
In order to make the spec fail if the controller was not thread safe, it
uses breakpoints. One of those breakpoints was set for a method that has
now been removed.

I changed the method that is used for the breakpoint and changed `allow`
to `expect` so that this spec will fail if we remove that method as
well. Future version of Rspec will check if a mocked method actually
exists but our version just mocks it anyway. This is one way how specs
can become invalid after refactoring.
2020-02-07 17:46:42 +11:00
Maikel
6d51856821 Merge pull request #4734 from openfoodfoundation/dependabot/bundler/oauth2-1.4.3
Bump oauth2 from 1.4.2 to 1.4.3
2020-02-07 16:48:42 +11:00
dependabot-preview[bot]
890704b75c Bump webmock from 3.8.0 to 3.8.1
Bumps [webmock](https://github.com/bblimke/webmock) from 3.8.0 to 3.8.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.8.0...v3.8.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-06 19:17:54 +00:00
Transifex-Openfoodnetwork
922484b2e7 Updating translations for config/locales/en_GB.yml 2020-02-07 05:02:38 +11:00
Luis Ramos
3e7288648b Merge pull request #4762 from openfoodfoundation/dependabot/bundler/roo-2.8.3
Bump roo from 2.8.2 to 2.8.3
2020-02-06 14:44:21 +00:00
luisramos0
f0f537ff8f Fix path of spree-select2.js pointing to the file in ofn rather the file in spree_backend 2020-02-06 11:21:47 +00:00
Transifex-Openfoodnetwork
b7f920c4b6 Updating translations for config/locales/ca.yml 2020-02-06 21:12:27 +11:00
Pau Pérez Fabregat
be19d50639 Merge pull request #4768 from openfoodfoundation/transifex
Transifex
2020-02-06 11:11:23 +01:00
Transifex-Openfoodnetwork
0ceb8ab6c4 Updating translations for config/locales/ca.yml 2020-02-06 21:09:16 +11:00
Pau Pérez Fabregat
e387c7db83 Merge pull request #4548 from luisramos0/improve_truncate_data
Improve truncate data process
2020-02-06 11:01:36 +01:00
Pau Pérez Fabregat
d5df48f3c0 Merge pull request #4737 from openfoodfoundation/transifex
Transifex
2020-02-06 11:00:46 +01:00
Pau Pérez Fabregat
c9abdac2e0 Merge pull request #4722 from mkllnk/code-climate-rubocop
Bump Code Climate's Rubocop version to their latest
2020-02-06 10:32:46 +01:00
Transifex-Openfoodnetwork
ff08d9f210 Updating translations for config/locales/nb.yml 2020-02-06 09:39:52 +11:00
luisramos0
e5c9468d09 Fix rubocop issues in navigation_helper 2020-02-05 22:16:20 +00:00
luisramos0
8aed173127 Uncomment events in order edit page and remove unused spree autocomplete js code 2020-02-05 20:04:15 +00:00
luisramos0
61ecca7257 Move template loading to directive of customer search override 2020-02-05 20:04:15 +00:00
luisramos0
7eba657b2f Add missing templates from spree_backend 2020-02-05 20:04:15 +00:00
luisramos0
784de340d1 Disable adaptive menu when running tests, this is what spree_backend was doing before 2020-02-05 20:04:15 +00:00
luisramos0
9191628f29 Bring custom form_builder initializer from spree_backend 2020-02-05 20:04:15 +00:00
luisramos0
88410b1efd Add missing general config routes from spree_backend 2020-02-05 20:04:12 +00:00
luisramos0
afea032361 Add return_authorizations route from spree_backend 2020-02-05 16:02:43 +00:00
luisramos0
3decb4056c Remove repeated include spree_paypal_express and add require css select2 2020-02-05 16:02:43 +00:00
luisramos0
8e9b08feca Remove jquery-alerts from head html 2020-02-05 16:02:43 +00:00
luisramos0
694995ea5d Prefix root_path with main_app so that ofn's route is used. The spree root path is no longer defined, we dont need it 2020-02-05 16:02:43 +00:00
luisramos0
22de7252d0 Fix route in login nav and bring reports and properties resource route from spree_backend 2020-02-05 16:02:43 +00:00
luisramos0
2acf8e5125 Remove config_locale from base controller, in OFN we dont have separate locales for frontoffice and backoffice 2020-02-05 16:02:43 +00:00
luisramos0
e1f61e645d Remove dependency to spree_backend and add dependencies still required: jquery-ui-rails and select2-rails 2020-02-05 16:02:43 +00:00
luisramos0
687d827ceb Add required css require for select2 2020-02-05 16:02:43 +00:00
luisramos0
2885e38113 Re-activate/re-add click events that were registered in spree_backend code before 2020-02-05 16:02:43 +00:00
luisramos0
9f3ca58b55 Add empty admin/spree_backend.js
This file is required by spree_paypal_express that we still need after leaving spree_backend
2020-02-05 16:02:43 +00:00
luisramos0
ffe3228848 Remove spree_backend dependencies from all.js and all.css and fix some dependencies path problems 2020-02-05 16:02:43 +00:00
luisramos0
834231eb8f Add js code needed for the zones admin page 2020-02-05 16:02:43 +00:00
luisramos0
68f5aabd3f Add js code needed where calculators are used: ship methods and payment methods config pages 2020-02-05 16:02:43 +00:00
luisramos0
7e7ea92833 Add js code needed in the states admin page 2020-02-05 16:02:43 +00:00
luisramos0
ebf22ceb19 Add js and css code for image settings from spree_backend 2020-02-05 16:02:43 +00:00
Luis Ramos
9313a57d19 Merge pull request #4511 from luisramos0/backend_ctrl_search
Bring spree_backend search controller to OFN
2020-02-05 15:54:30 +00:00
Luis Ramos
c38c7c35bc Add spec for user default address setter 2020-02-05 14:49:17 +00:00
luisramos0
2663f74767 Add specs for new services 2020-02-05 14:49:17 +00:00
luisramos0
b41de52012 Moved checkout services into a specific folder under app/services 2020-02-05 14:49:17 +00:00
luisramos0
214eb43122 Add frozen string literal magic comment 2020-02-05 14:49:17 +00:00
luisramos0
01fc4e0513 Add Spree::CheckoutController only to redirect to CheckoutController
I have not managed to make the spree checkout route, that paypal express uses, go to CheckoutController directly. According to the rails docs "to: '/checkout#edit'" should do it, but it doesnt work here.
2020-02-05 14:49:17 +00:00
luisramos0
6ce50a5fa5 Extract paypal redirect logic to service class 2020-02-05 14:49:17 +00:00
luisramos0
4fbd2cfa52 Extract UserDefaultAddress logic into separate class to take more 30 lines out of CheckoutController 2020-02-05 14:49:17 +00:00
luisramos0
383b28e170 Add order and current_user to checkout_form_data_adapter where they are required
Also re-add order.state condition to update_result: in some tests, the order state is complete but no completion data (completed?) is present
2020-02-05 14:49:17 +00:00
luisramos0
bf55a15f81 Extract checkout params adaptation logic into a service class 2020-02-05 14:49:17 +00:00
luisramos0
eb7e6dc5b8 Remove spree checkout controller spec, it is no longer necessary 2020-02-05 14:49:17 +00:00
luisramos0
139ecfe604 Remove rubocop exceptions resolved so far in checkout controller 2020-02-05 14:49:17 +00:00
luisramos0
43a6798db2 Move methods around in checkout controller into a more logical organisation: first the filters code and then support code for the update action 2020-02-05 14:49:17 +00:00
luisramos0
06d6579486 Refactor construct_saved_card_attributes to fix rubocop issues 2020-02-05 14:49:17 +00:00
luisramos0
76df526002 Remove dead code from construct_saved_card_attributes 2020-02-05 14:49:17 +00:00
luisramos0
06569ea24c Refactor load_order to fix rubocop issues 2020-02-05 14:49:17 +00:00
luisramos0
25431f851b Refactor object_params to fix rubocop issues 2020-02-05 14:49:17 +00:00
luisramos0
bab2420bb3 Break up default address methods to fix rubocop issues 2020-02-05 14:49:17 +00:00
luisramos0
0b2acb3a76 Extracted two methods from checkout_workflow to fix rubocop issues 2020-02-05 14:49:17 +00:00
luisramos0
27db9e604f Extract respond_to_update_succeeded from update_succeeded 2020-02-05 14:49:17 +00:00
luisramos0
c4e58ebb9e Extract update_succeeded from checkout#update 2020-02-05 14:49:17 +00:00
luisramos0
9a0ee254af Extract checkout_workflow from checkout#update 2020-02-05 14:49:17 +00:00
luisramos0
5ce3e1e0d2 Fix some rubocop issues in checkout controller 2020-02-05 14:49:17 +00:00
luisramos0
4b345d928c Remove old code to detect Phantom Fees, no bugsnag events detected at all 2020-02-05 14:49:17 +00:00
luisramos0
52b1e6c71a Move all logic required in Spree::CheckoutController to CheckoutController 2020-02-05 14:49:17 +00:00
Matt-Yorkley
140e0b9cb1 Refactor #exchangeLoadedVariants 2020-02-05 15:11:34 +01:00
Matt-Yorkley
b3f05d1a98 Use "Variants" instead of "Products" in order cycle exchanges UI 2020-02-05 15:11:34 +01:00
Matt-Yorkley
9644b145cc Remove num_of_products 2020-02-05 15:11:34 +01:00
Matt-Yorkley
6f644936b0 Show counts including all variants in order cycle exchanges 2020-02-05 15:10:26 +01:00
Matt-Yorkley
b86759d7a7 Fix form rendering in admin orders
ActionView::Template::Error: Nil location provided. Can't build URI.
  0) Account and Billing Settings updating as an admin user loads the page
     Failure/Error: = form_tag false, {name: "orders_form", "ng-submit" => "fetchResults()"} do
2020-02-05 16:37:23 +11:00
luisramos0
b0f2e01c70 Delete extra inventory_units that are for some unknown reason connected to shipments of orders to delete but not to orders to delete 2020-02-05 16:30:14 +11:00
Maikel
747be81aec Link to new release template 2020-02-05 15:21:26 +11:00
Maikel
fd124daf50 Add task to notify instance managers of upcoming changes 2020-02-05 14:58:57 +11:00
Transifex-Openfoodnetwork
ef33d27e6c Updating translations for config/locales/en_FR.yml 2020-02-05 06:55:27 +11:00
Transifex-Openfoodnetwork
3a01e00d7b Updating translations for config/locales/fr.yml 2020-02-05 06:51:14 +11:00
Luis Ramos
81103f3f71 Merge pull request #4742 from CSCI-462-01-2020/Issue4109
Edit new_resource partial
2020-02-04 19:44:16 +00:00
dependabot-preview[bot]
9d1e3f0318 Bump roo from 2.8.2 to 2.8.3
Bumps [roo](https://github.com/roo-rb/roo) from 2.8.2 to 2.8.3.
- [Release notes](https://github.com/roo-rb/roo/releases)
- [Changelog](https://github.com/roo-rb/roo/blob/master/CHANGELOG.md)
- [Commits](https://github.com/roo-rb/roo/compare/v2.8.2...v2.8.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-04 19:23:42 +00:00
dependabot-preview[bot]
67adf3c801 Bump unicorn from 5.5.2 to 5.5.3
Bumps [unicorn](https://yhbt.net/unicorn/) from 5.5.2 to 5.5.3.

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-02-04 19:22:39 +00:00
Luis Ramos
a8b48a561f Merge pull request #4733 from lin-d-hop/master
Fixing incorrect payment and balance calculation
2020-02-04 18:11:48 +00:00
Luis Ramos
c7038f6ac9 Merge pull request #4620 from luisramos0/spree_backend_css
Bring basic CSS rules from spree backend
2020-02-04 18:06:15 +00:00
Luis Ramos
ea75714561 Merge pull request #4635 from luisramos0/main_app_routes
Replace use of spree.root_path and root_url with main_app.root_path and main_app.root_url
2020-02-04 16:02:48 +00:00
luisramos0
b7d19dd34c Remove unused route from Spree.routes 2020-02-04 14:55:34 +00:00
luisramos0
44d1b3f00c Remove unused search/users controller action 2020-02-04 14:55:34 +00:00
luisramos0
f8376c0aeb Remove unused route search_customer_addresses 2020-02-04 14:55:34 +00:00
luisramos0
88464d58c2 Fix some rubocop issues and extract ransack hash to reduce repetition 2020-02-04 14:55:34 +00:00
luisramos0
962779bba1 Merge search controller with decorator 2020-02-04 14:54:51 +00:00
luisramos0
1ae73dd6ae Add search_controller from spree_backend so that we can now merge it with the OFN's decorator 2020-02-04 14:54:51 +00:00
luisramos0
f48ab57782 Add explicit css import statements where they are needed 2020-02-04 14:52:44 +00:00
luisramos0
8b6ebfb351 Add imports for new css files from spree_backend 2020-02-04 14:52:44 +00:00
luisramos0
9c0788c3e0 Bring shared css rules from spree_backend 2020-02-04 14:52:17 +00:00
luisramos0
f61258d0b4 Bring components css from spree_backend
pagination and navigation rules were merged
2020-02-04 14:52:17 +00:00
luisramos0
289f62f115 Bring and require date picker css from spree_backend 2020-02-04 14:52:17 +00:00
luisramos0
c3a98d5a4f Bring css dependencies from spree_backend
These dependencies are in spree_core so we dont need to bring them to ofn right now
2020-02-04 14:52:17 +00:00
Luis Ramos
d8374e9caa Merge pull request #4614 from luisramos0/base_admin_js
Bring some basic js functions and dependencies from spree_backend
2020-02-04 14:48:38 +00:00
luisramos0
0648f23e94 Move css dependencies to specific css files and add some required dependencies from spree_backend 2020-02-04 14:47:51 +00:00
luisramos0
e37cb2d63f Remove underscope from select2 css file name 2020-02-04 14:47:51 +00:00
luisramos0
ee64238bdd Add jquery.adaptivemenu require but commeent out the activation for now because it is already called in spree_backend
This can be reverted when spree_backend is removed
2020-02-04 14:47:51 +00:00
luisramos0
d3130e111f Remove on click events
These events can only be added to OFN when spree_backend is removed otherwise the evetns will be registered twice
2020-02-04 14:47:51 +00:00
luisramos0
93f4eee887 Make newly imported js files compatible with the karma build 2020-02-04 14:47:51 +00:00
luisramos0
408ada9097 Remove unnecessary build exception 2020-02-04 14:47:51 +00:00
luisramos0
e14ebd9503 Add required variables from spree_backend 2020-02-04 14:47:51 +00:00
luisramos0
289b99c30e Bring and require equalize from spree_backend 2020-02-04 14:47:26 +00:00
luisramos0
f85c36a17e Bring and require select2 from spree_backend 2020-02-04 14:47:26 +00:00
luisramos0
4715df3258 Bring and require jquery.horizontalNav.js from spree_backend 2020-02-04 14:47:26 +00:00
luisramos0
b20be101cc Bring and require spin from spree_backend and respective progress indicator js and css 2020-02-04 14:47:26 +00:00
luisramos0
d424987587 Bring and require jquery.vAlign.js from spree_backend 2020-02-04 14:47:26 +00:00
luisramos0
a0575430dd Require spree.js from spree_core for some basic functions like Spree.url 2020-02-04 14:46:57 +00:00
luisramos0
c1e6344b18 Merge spree js function and override 2020-02-04 14:46:57 +00:00
luisramos0
ed0198382f Bring spree_backend admin.js.erb, rename it to base.js.erb and remove requires that are not used in ofn 2020-02-04 14:46:57 +00:00
blainebillings
577fb88843 Move Create and Cancel References to Actions Namespace 2020-02-04 09:39:01 -05:00
Pau Pérez Fabregat
2b879221b2 Merge pull request #4756 from kristinalim/fix/4489-flaky_spec_for_editing_oc
4489 Flaky spec when editing outgoing exchanges in OC
2020-02-04 15:38:37 +01:00
blainebillings
22db2e99f0 Merge branch 'Issue4109' of https://github.com/CSCI-462-01-2020/openfoodnetwork into Issue4109 2020-02-04 09:38:19 -05:00
blainebillings
ef4aa488c3 Moves Create and Cancel References to Actions Namespace 2020-02-04 09:34:28 -05:00
Pau Pérez Fabregat
57775f49bc Merge pull request #4739 from openfoodfoundation/dependabot/bundler/rack-mini-profiler-1.1.6
Bump rack-mini-profiler from 1.1.4 to 1.1.6
2020-02-04 15:29:20 +01:00
Pau Pérez Fabregat
e8a12d9897 Merge pull request #4738 from openfoodfoundation/dependabot/bundler/oj-3.10.2
Bump oj from 3.10.1 to 3.10.2
2020-02-04 15:28:40 +01:00
Pau Pérez Fabregat
f3b8d5b868 Merge pull request #4741 from openfoodfoundation/dependabot/bundler/bugsnag-6.13.0
Bump bugsnag from 6.12.2 to 6.13.0
2020-02-04 15:28:00 +01:00
Pau Pérez Fabregat
246235b921 Merge pull request #4667 from Matt-Yorkley/rails-4-prep
Rails 4 prep
2020-02-04 15:20:28 +01:00
Luis Ramos
0ded41afee Merge pull request #4513 from luisramos0/backend_ctrl_orders
Bring spree_backend orders controller to OFN
2020-02-04 11:51:54 +00:00
luisramos0
d32e106bf0 Add partials needed in the orders edit page 2020-02-04 11:51:13 +00:00
luisramos0
bbb3748d3c Simplify orders events logic 2020-02-04 11:51:13 +00:00
luisramos0
08dd992344 Merge orders_helper with decorator 2020-02-04 11:51:13 +00:00
luisramos0
914244a1ee Bring orders helper from spree_backend 2020-02-04 11:51:13 +00:00
luisramos0
e5f089610c Bring admin orders routes from spree_backend 2020-02-04 11:51:13 +00:00
luisramos0
6e26841817 Fix load_order before filter and remove unused open and close adjustments actions 2020-02-04 11:50:44 +00:00
luisramos0
ab60c4a9dd Remove unnecessary index action override because this is no longer a decorator
Remove useless todo comment
2020-02-04 11:50:44 +00:00
luisramos0
7009cd89e0 Fix rubocop issues in customer details controller and update rubocop manual todo accordingly 2020-02-04 11:50:44 +00:00
luisramos0
b93af37ea9 Merge customer details decorator with controller 2020-02-04 11:50:03 +00:00
luisramos0
76b6a85509 Merge spree/admin/orders_controller and its decorator and fix a few rubocop issues 2020-02-04 11:50:03 +00:00
luisramos0
a1d4b4ee98 Add orders_controller from spree_backend so that we can now merge it with the OFN's decorator 2020-02-04 11:50:03 +00:00
luisramos0
51bca7ce2f Add customer_details_controller from spree_backend so that we can now merge it with the OFN's decorator 2020-02-04 11:50:03 +00:00
Luis Ramos
70147f908a Merge pull request #4611 from luisramos0/taxonomies_js
Bring js code to make taxonomies admin work without spree_backend
2020-02-04 11:47:27 +00:00
Luis Ramos
c4bf4f001f Merge pull request #4509 from luisramos0/backend_ctrl_payments
Bring spree_backend payments controller to OFN
2020-02-04 11:46:23 +00:00
Matt-Yorkley
7d71f21753 Add frozen_string_literal comment to new class 2020-02-04 11:11:24 +01:00
Matt-Yorkley
285c78a5e4 Remove use of #pluck and ensure subquery does not include all columns 2020-02-04 11:10:13 +01:00
luisramos0
6e78ae762a Make it work even if preferred_enterprise_id is null 2020-02-04 10:01:18 +00:00
luisramos0
9a2ad16926 Make explicit the dependency to font-awesome css rules 2020-02-04 09:34:59 +00:00
luisramos0
afec21eb3d Move imports to where they are needed 2020-02-04 09:34:59 +00:00
luisramos0
651ee720c6 Remove underscore from new jstree css file 2020-02-04 09:34:40 +00:00
luisramos0
2e6c5e1fad Add dependencies from spree_backend required by jstree 2020-02-04 09:34:40 +00:00
luisramos0
87366ae7fc Remove usage of jConfirm so that we dont have to bring dependency jquery.alerts from spree_backend 2020-02-04 09:33:58 +00:00
luisramos0
27aea0b277 Bring js code from spree_backend to make taxons admin work 2020-02-04 09:33:58 +00:00
luisramos0
d4edc9f20d Bring jstress css from spree_backend 2020-02-04 09:33:58 +00:00
luisramos0
6c7991be75 Bring jquery.jstree from spree_backend 2020-02-04 09:33:34 +00:00
luisramos0
3f81352df5 Bring jquery.cookie from spree_backend 2020-02-04 09:33:34 +00:00
Kristina Lim
9d0e26ae28 Wait for products panel to show in outgoing exchanges feature spec 2020-02-04 16:20:47 +08:00
Luis Ramos
d80554a14a Merge pull request #4744 from luisramos0/oc_pag_bug
Make pagination optional in the ExchangeProductsController
2020-02-03 17:19:06 +00:00
luisramos0
a5fe5fb448 Remove usage of deleted const DEFAULT_PAGE
If params[:page] is not in the request, the results will not be paginated now
2020-02-03 15:04:34 +00:00
luisramos0
4c51d60bfd Make pagination optional in the ExchangeProductsController 2020-02-03 13:11:26 +00:00
blainebillings
9218008530 Edit new_resource Partial 2020-02-02 11:22:54 -05:00
myersca1
f36c5b8938 Edit new_resource partial 2020-02-02 11:19:10 -05:00
dependabot-preview[bot]
67199fd2d6 Bump bugsnag from 6.12.2 to 6.13.0
Bumps [bugsnag](https://github.com/bugsnag/bugsnag-ruby) from 6.12.2 to 6.13.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.12.2...v6.13.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-31 19:15:09 +00:00
Transifex-Openfoodnetwork
18d17ec674 Updating translations for config/locales/fr_CA.yml 2020-02-01 04:02:53 +11:00
Transifex-Openfoodnetwork
3981ee7ec1 Updating translations for config/locales/en_CA.yml 2020-02-01 03:54:02 +11:00
Luis Ramos
a0475ee8a4 Merge pull request #4613 from luisramos0/autocomplete
Bring remaining variants autocomplete (and related) JS code from spree_backend
2020-01-31 16:08:50 +00:00
Luis Ramos
4cdc604f45 Merge pull request #4718 from luisramos0/variant_count
Make Order Cycle exchange tab summary not count inventory variants that are hidden
2020-01-31 16:03:21 +00:00
Luis Ramos
dbf44c41b2 Merge pull request #4657 from luisramos0/pi-xls
Remove Product import code for xls suppport
2020-01-31 12:12:25 +00:00
Maikel Linke
9535c5647f Make pluralisation code an independent lib
I considered moving the code to a service but I think that this code
can be completely independent of the Open Food Network use case. It
would be easy to move to a gem. The downcasing may need reconsidering
for general use.
2020-01-31 09:48:32 +11:00
Maikel Linke
6f8bb793e1 Add unit names commonly used in French 2020-01-31 09:48:32 +11:00
Maikel Linke
2476050f29 Remove usage count comments 2020-01-31 09:48:32 +11:00
Maikel Linke
1cce106977 Use our unit name pluralization in Ruby
This code will be used for the shop front and reports.
2020-01-31 09:48:32 +11:00
Maikel Linke
98b55287f1 Pluralize common variant unit names
This adds the most popular unit names as singular and plural to our
locale for translation. The added Javascript performs a reverse lookup
to find the right singular/plural form of a unit name in that language.
2020-01-31 09:48:32 +11:00
dependabot-preview[bot]
25c4aed368 Bump rack-mini-profiler from 1.1.4 to 1.1.6
Bumps [rack-mini-profiler](https://github.com/MiniProfiler/rack-mini-profiler) from 1.1.4 to 1.1.6.
- [Release notes](https://github.com/MiniProfiler/rack-mini-profiler/releases)
- [Changelog](https://github.com/MiniProfiler/rack-mini-profiler/blob/master/CHANGELOG.md)
- [Commits](https://github.com/MiniProfiler/rack-mini-profiler/compare/v1.1.4...v1.1.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-30 19:28:45 +00:00
dependabot-preview[bot]
c5a6ef673c Bump oj from 3.10.1 to 3.10.2
Bumps [oj](https://github.com/ohler55/oj) from 3.10.1 to 3.10.2.
- [Release notes](https://github.com/ohler55/oj/releases)
- [Changelog](https://github.com/ohler55/oj/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/ohler55/oj/compare/v3.10.1...v3.10.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-30 19:26:07 +00:00
Transifex-Openfoodnetwork
79ba15fe9a Updating translations for config/locales/en_GB.yml 2020-01-31 03:53:48 +11:00
luisramos0
e192207f4e Fix bug in before filters migration, needs to load payment for the show action 2020-01-30 10:27:26 +00:00
dependabot-preview[bot]
48a75c956f Bump oauth2 from 1.4.2 to 1.4.3
Bumps [oauth2](https://github.com/oauth-xx/oauth2) from 1.4.2 to 1.4.3.
- [Release notes](https://github.com/oauth-xx/oauth2/releases)
- [Changelog](https://github.com/oauth-xx/oauth2/blob/master/CHANGELOG.md)
- [Commits](https://github.com/oauth-xx/oauth2/compare/v1.4.2...v1.4.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-29 19:24:24 +00:00
lin-d-hop
baf1ecb436 Fixing incorrect payment and balance calculation
Corrections and added specs
2020-01-29 16:06:06 +00:00
luisramos0
947914724a Add frozen string literal magic comment 2020-01-28 18:02:58 +00:00
luisramos0
b5004f1cbf Add specs for ExchangeProductsRenderer#exchange_variants 2020-01-28 18:02:58 +00:00
luisramos0
4596399bc2 Extract logic from controller to renderer service
Re-using the filter_visible method for both products and variants
2020-01-28 18:02:58 +00:00
luisramos0
685abccb61 Make variant count consider oc config and not count variants that are hidden in the inventory of the coordinator of the OC 2020-01-28 18:02:58 +00:00
luisramos0
9254928656 Remove underscore from product_autocomplete css file 2020-01-28 13:53:04 +00:00
luisramos0
228997c35b Add handlebars dependency from spree_backend 2020-01-28 13:53:04 +00:00
luisramos0
667f44336d Remove unused split logic from variant autocomplete, the split functionality is not used in ofn because we only have one stock location 2020-01-28 13:53:04 +00:00
luisramos0
0a136ff2fb Comment out click event registration as this will duplicate events until the spree_backend code is there
These can be activated when spree_backend is removed
2020-01-28 13:53:04 +00:00
luisramos0
3f3577e73c Remove encoding tag from admin/spree/orders js files 2020-01-28 13:53:04 +00:00
luisramos0
cf1664bed3 Bring some variant autocomplete styling from spree_backend 2020-01-28 13:53:04 +00:00
luisramos0
b8aee4e857 Bring address_states as is from spre_backend 2020-01-28 13:53:04 +00:00
luisramos0
cfe3435851 Bring shipments.js as is from spree_backend 2020-01-28 13:53:04 +00:00
luisramos0
53e342ba1a Bring variant_autocomplete from spree_backend as is 2020-01-28 13:53:04 +00:00
luisramos0
6bdb14248c Require lodash.underscore to support _. calls in js
spree_backend relies on Underscore.js 1.4.4, from Jan 2013, in some auto complete functions, here we will be depending on Lo-Dash 2.4.1, from Dec 2013
2020-01-28 13:53:03 +00:00
luisramos0
8e27291b15 require handlebars extensions from spree_core to allow translations inside handlebar templates 2020-01-28 13:52:19 +00:00
Maikel Linke
ec67736dff Bump Code Climate's Rubocop version to their latest
Our used version is still higher than that.
2020-01-28 17:12:28 +11:00
luisramos0
766303b332 Add required payment_helper from spree_backend 2020-01-22 20:22:28 +00:00
luisramos0
74226fbdf8 Fix one rubocop issue and update rubocop todo manual for the new controller 2020-01-22 20:22:28 +00:00
luisramos0
dc5374e284 Merge filter_payment_methods and load_data 2020-01-22 20:21:21 +00:00
luisramos0
f6ecf57737 Make before filters easier to understand using the fact that there are only index, create, new and fire actions in this controller 2020-01-22 20:21:21 +00:00
luisramos0
940953b043 Add missing translations for payments 2020-01-22 20:21:21 +00:00
luisramos0
fbc5887fa6 Bring payments routes from spree_backend 2020-01-22 20:21:21 +00:00
luisramos0
61ce849546 Merge spree/admin/payments_controller with its decorator and fix a few rubocop issues 2020-01-22 20:21:21 +00:00
luisramos0
afddaed9fc Add empty but needed payments templates for check payment method 2020-01-22 20:21:21 +00:00
luisramos0
12158d73fa Add payments_controller from spree_backend so that we can now merge it with the OFN's decorator 2020-01-22 20:21:21 +00:00
Matt-Yorkley
5f3abbf00e Refactor BaseController 2020-01-22 12:17:23 +01:00
Matt-Yorkley
a02c58e231 Add join_table to enterprise groups relation
has_and_belongs_to_many relationships now require a join_table
2020-01-22 12:17:23 +01:00
Matt-Yorkley
59ebfb9bd4 Fix subquery errors triggered by #warn_invalid_order_cycles 2020-01-22 12:17:23 +01:00
Matt-Yorkley
57ca1d54bb Fix issue with each_serializer not being called in some cases in Rails 4. 2020-01-22 12:17:23 +01:00
luisramos0
138248e1c9 Product import only works with csv right now. Here we remove dead code
This can be reverted if we start suppporting xls and ods in the future
2020-01-16 09:59:27 +00:00
luisramos0
5fccd5fe58 Add rubocop exception for application controller class length and fix one line length issue 2020-01-12 19:42:07 +00:00
Maikel Linke
bec73adc89 Restore file logging for custom format logger
The new custom logger was directed to stdout instead of a file.
2020-01-08 15:06:19 +11:00
luisramos0
23ec66e338 Add timestamp to Rails logger in staging and prod so that info in logs can be accurately compared with data in the DB 2020-01-08 15:05:55 +11:00
luisramos0
4658b7a533 Fix rubocop issues in app/controllers/application_controller 2019-12-28 19:10:02 +00:00
luisramos0
d0f33e7c8a Avoid code in devise that is not needed and simply return the root path
This fixes a broken spec with error "No route matches {:controller=>"home"}"
2019-12-28 18:47:14 +00:00
luisramos0
55bb328d48 Prefix all calls to root_url with main_app 2019-12-28 18:46:50 +00:00
luisramos0
a8a6fce385 Prefix root_path with main_app so that ofn's route is used. The spree root path will no longer be defined when spree_backend is dropped 2019-12-28 18:45:57 +00:00
luisramos0
60677a2414 Make login nav use main_app router 2019-12-28 18:41:16 +00:00
265 changed files with 17931 additions and 1476 deletions

View File

@@ -2,7 +2,7 @@ version: "2"
plugins:
rubocop:
enabled: true
channel: "rubocop-0-57"
channel: "rubocop-0-76"
config:
file: ".rubocop_styleguide.yml"
scss-lint:

View File

@@ -1,7 +1,7 @@
---
name: Release task
about: Track the process of a new release
title: ''
title: 'Release v'
labels: ''
assignees: ''
@@ -10,10 +10,13 @@ assignees: ''
Steps:
- [ ] Include translations
- [ ] Draft: https://github.com/openfoodfoundation/openfoodnetwork/releases/new <!-- replace the URL -->
- [ ] [Draft new release]
- [ ] Notify #instance-managers of user-facing changes.
- [ ] Test: https://semaphoreci.com/openfoodfoundation/openfoodnetwork-2/branches/master <!-- replace the URL -->
- [ ] Publish and notify #global-community
- [ ] Deploy and notify #instance-managers
- [ ] Nudge next release manager
The full process is described at https://github.com/openfoodfoundation/openfoodnetwork/wiki/Releasing.
[Draft new release]: https://github.com/openfoodfoundation/openfoodnetwork/releases/new?tag=v&title=v+Code+Name&body=Congrats%0A%0ADescription%0A%0A%23%23+User+facing+changes+:eyes:%0A%0A%0A%0A%23%23+Technical+changes+:wrench:%0A%0A

View File

@@ -39,11 +39,8 @@ Layout/LineLength:
- app/controllers/admin/variant_overrides_controller.rb
- app/controllers/api/enterprise_attachment_controller.rb
- app/controllers/api/product_images_controller.rb
- app/controllers/application_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/spree/admin/adjustments_controller_decorator.rb
- app/controllers/spree/admin/orders_controller_decorator.rb
- app/controllers/spree/admin/payments_controller_decorator.rb
- app/controllers/spree/credit_cards_controller.rb
- app/controllers/spree/paypal_controller_decorator.rb
- app/controllers/stripe/callbacks_controller.rb
@@ -356,24 +353,22 @@ Metrics/AbcSize:
- app/controllers/api/variants_controller.rb
- app/controllers/base_controller.rb
- app/controllers/cart_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/discourse_sso_controller.rb
- app/controllers/enterprises_controller.rb
- app/controllers/spree/admin/adjustments_controller_decorator.rb
- app/controllers/spree/admin/image_settings_controller.rb
- app/controllers/spree/admin/orders/customer_details_controller_decorator.rb
- app/controllers/spree/admin/orders_controller_decorator.rb
- app/controllers/spree/admin/orders/customer_details_controller.rb
- app/controllers/spree/admin/orders_controller.rb
- app/controllers/spree/admin/overview_controller.rb
- app/controllers/spree/admin/payment_methods_controller.rb
- app/controllers/spree/admin/payments_controller_decorator.rb
- app/controllers/spree/admin/payments_controller.rb
- app/controllers/spree/admin/products_controller.rb
- app/controllers/spree/admin/reports_controller.rb
- app/controllers/spree/admin/resource_controller.rb
- app/controllers/spree/admin/products_controller.rb
- app/controllers/spree/admin/search_controller_decorator.rb
- app/controllers/spree/admin/search_controller.rb
- app/controllers/spree/admin/taxons_controller.rb
- app/controllers/spree/admin/users_controller.rb
- app/controllers/spree/admin/variants_controller.rb
- app/controllers/spree/checkout_controller.rb
- app/controllers/spree/credit_cards_controller.rb
- app/controllers/spree/orders_controller.rb
- app/controllers/spree/user_passwords_controller.rb
@@ -391,7 +386,6 @@ Metrics/AbcSize:
- app/helpers/spree/admin/base_helper.rb
- app/helpers/spree/admin/zones_helper.rb
- app/helpers/spree/orders_helper.rb
- app/jobs/subscription_placement_job.rb
- app/mailers/producer_mailer.rb
- app/models/calculator/flat_percent_per_item.rb
- app/models/column_preference.rb
@@ -418,6 +412,8 @@ Metrics/AbcSize:
- app/services/create_order_cycle.rb
- app/services/order_syncer.rb
- app/services/subscription_validator.rb
- lib/active_merchant/billing/gateways/stripe_decorator.rb
- lib/active_merchant/billing/gateways/stripe_payment_intents.rb
- lib/discourse/single_sign_on.rb
- lib/open_food_network/bulk_coop_report.rb
- lib/open_food_network/customers_report.rb
@@ -495,8 +491,6 @@ Metrics/CyclomaticComplexity:
Exclude:
- app/controllers/admin/enterprise_fees_controller.rb
- app/controllers/admin/enterprises_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/spree/admin/payments_controller_decorator.rb
- app/controllers/spree/admin/taxons_controller.rb
- app/controllers/spree/orders_controller.rb
- app/helpers/checkout_helper.rb
@@ -513,6 +507,7 @@ Metrics/CyclomaticComplexity:
- app/models/spree/product_decorator.rb
- app/models/variant_override_set.rb
- app/services/cart_service.rb
- lib/active_merchant/billing/gateways/stripe_payment_intents.rb
- lib/discourse/single_sign_on.rb
- lib/open_food_network/bulk_coop_report.rb
- lib/open_food_network/enterprise_issue_validator.rb
@@ -526,8 +521,6 @@ Metrics/PerceivedComplexity:
Exclude:
- app/controllers/admin/enterprises_controller.rb
- app/controllers/api/variants_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/spree/admin/payments_controller_decorator.rb
- app/controllers/spree/admin/taxons_controller.rb
- app/controllers/spree/orders_controller.rb
- app/helpers/checkout_helper.rb
@@ -540,6 +533,7 @@ Metrics/PerceivedComplexity:
- app/models/spree/ability_decorator.rb
- app/models/spree/order_decorator.rb
- app/models/spree/product_decorator.rb
- lib/active_merchant/billing/gateways/stripe_payment_intents.rb
- lib/discourse/single_sign_on.rb
- lib/open_food_network/bulk_coop_report.rb
- lib/open_food_network/enterprise_issue_validator.rb
@@ -564,16 +558,15 @@ Metrics/MethodLength:
- app/controllers/api/variants_controller.rb
- app/controllers/base_controller.rb
- app/controllers/cart_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/shop_controller.rb
- app/controllers/spree/admin/image_settings_controller.rb
- app/controllers/spree/admin/orders/customer_details_controller_decorator.rb
- app/controllers/spree/admin/orders/customer_details_controller.rb
- app/controllers/spree/admin/orders_controller.rb
- app/controllers/spree/admin/payment_methods_controller.rb
- app/controllers/spree/admin/payments_controller_decorator.rb
- app/controllers/spree/admin/payments_controller.rb
- app/controllers/spree/admin/products_controller.rb
- app/controllers/spree/admin/reports_controller.rb
- app/controllers/spree/admin/resource_controller.rb
- app/controllers/spree/admin/products_controller.rb
- app/controllers/spree/admin/search_controller_decorator.rb
- app/controllers/spree/admin/tax_categories_controller.rb
- app/controllers/spree/admin/taxons_controller.rb
- app/controllers/spree/admin/users_controller.rb
@@ -610,6 +603,7 @@ Metrics/MethodLength:
- app/serializers/api/cached_enterprise_serializer.rb
- app/services/order_cycle_form.rb
- engines/order_management/app/services/order_management/reports/enterprise_fee_summary/scope.rb
- lib/active_merchant/billing/gateways/stripe_payment_intents.rb
- lib/discourse/single_sign_on.rb
- lib/open_food_network/bulk_coop_report.rb
- lib/open_food_network/column_preference_defaults.rb
@@ -652,8 +646,10 @@ Metrics/ClassLength:
- app/controllers/admin/order_cycles_controller.rb
- app/controllers/admin/subscriptions_controller.rb
- app/controllers/api/products_controller.rb
- app/controllers/application_controller.rb
- app/controllers/checkout_controller.rb
- app/controllers/spree/admin/base_controller.rb
- app/controllers/spree/admin/orders_controller.rb
- app/controllers/spree/admin/payment_methods_controller.rb
- app/controllers/spree/admin/reports_controller.rb
- app/controllers/spree/admin/resource_controller.rb
@@ -671,6 +667,7 @@ Metrics/ClassLength:
- app/serializers/api/enterprise_shopfront_serializer.rb
- app/services/cart_service.rb
- engines/order_management/app/services/order_management/reports/enterprise_fee_summary/scope.rb
- lib/active_merchant/billing/gateways/stripe_payment_intents.rb
- lib/open_food_network/bulk_coop_report.rb
- lib/open_food_network/enterprise_fee_calculator.rb
- lib/open_food_network/order_cycle_form_applicator.rb

View File

@@ -117,6 +117,15 @@ Style/FormatString:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styleformatstring
Style/HashEachMethods:
Enabled: false
Style/HashTransformKeys:
Enabled: false
Style/HashTransformValues:
Enabled: false
Style/IfUnlessModifier:
Enabled: false
StyleGuide: http://relaxed.ruby.style/#styleifunlessmodifier

View File

@@ -335,6 +335,7 @@ Rails/OutputSafety:
- 'app/helpers/spree/admin/zones_helper.rb'
- 'app/helpers/spree/reports_helper.rb'
- 'app/helpers/spree/admin/navigation_helper.rb'
- 'app/helpers/spree/admin/orders_helper.rb'
- 'app/serializers/api/product_serializer.rb'
- 'lib/spree/money_decorator.rb'
- 'spec/features/admin/orders_spec.rb'

34
Gemfile
View File

@@ -3,7 +3,7 @@ ruby "2.3.7"
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
gem 'i18n', '~> 0.6.11'
gem 'i18n-js', '~> 3.5.1'
gem 'i18n-js', '~> 3.6.0'
gem 'rails', '~> 3.2.22'
gem 'rails-i18n', '~> 3.0.0'
gem 'rails_safe_tasks', '~> 1.0'
@@ -19,9 +19,8 @@ gem 'activerecord-postgresql-adapter'
gem 'pg', '~> 0.21.0'
# OFN-maintained and patched version of Spree v2.0.4. See
# https://github.com/openfoodfoundation/openfoodnetwork/wiki/Spree-2.0-upgrade
# https://github.com/openfoodfoundation/openfoodnetwork/wiki/Tech-Doc:-OFN's-Spree-fork%F0%9F%8D%B4
# for details.
gem 'spree_backend', github: 'openfoodfoundation/spree', branch: '2-0-4-stable'
gem 'spree_core', github: 'openfoodfoundation/spree', branch: '2-0-4-stable'
gem 'spree_i18n', github: 'spree/spree_i18n', branch: '1-3-stable'
@@ -39,7 +38,7 @@ gem 'activemerchant', '~> 1.78'
gem 'devise', '~> 2.2.5'
gem 'devise-encryptable', '0.2.0'
gem 'jwt', '~> 2.2'
gem 'oauth2', '~> 1.4.2' # Used for Stripe Connect
gem 'oauth2', '~> 1.4.4' # Used for Stripe Connect
gem 'daemons'
gem 'delayed_job_active_record'
@@ -62,7 +61,7 @@ gem 'haml'
gem 'rabl'
gem 'redcarpet'
gem 'sass', "~> 3.3"
gem 'sass-rails', '~> 3.2.3', groups: [:default, :assets]
gem 'sass-rails', '~> 3.2.3'
gem 'truncate_html'
gem 'unicorn'
@@ -93,34 +92,31 @@ gem 'wkhtmltopdf-binary'
gem 'foreigner'
gem 'immigrant'
gem 'roo', '~> 2.8.2'
gem 'roo-xls', '~> 1.1.0'
gem 'roo', '~> 2.8.3'
gem 'whenever', require: false
gem 'test-unit', '~> 3.3'
# Gems used only for assets and not required
# in production environments by default.
group :assets do
gem 'coffee-rails', '~> 3.2.1'
gem 'compass-rails'
gem 'coffee-rails', '~> 3.2.1'
gem 'compass-rails'
gem 'mini_racer', '0.2.9'
gem 'mini_racer', '0.2.9'
gem 'uglifier', '>= 1.0.3'
gem 'uglifier', '>= 1.0.3'
gem 'angular-rails-templates', '~> 0.3.0'
gem 'foundation-icons-sass-rails'
gem 'momentjs-rails'
gem 'turbo-sprockets-rails3'
end
gem 'angular-rails-templates', '~> 0.3.0'
gem 'foundation-icons-sass-rails'
gem 'momentjs-rails'
gem 'turbo-sprockets-rails3'
gem "foundation-rails"
gem 'foundation_rails_helper', github: 'willrjmarshall/foundation_rails_helper', branch: "rails3"
gem 'jquery-migrate-rails'
gem 'jquery-rails', '3.0.4'
gem 'jquery-ui-rails', '~> 4.0.0'
gem 'select2-rails', '~> 3.4.7'
gem 'ofn-qz', github: 'openfoodfoundation/ofn-qz', ref: '60da2ae4c44cbb4c8d602f59fb5fff8d0f21db3c'

View File

@@ -34,18 +34,6 @@ GIT
revision: 8a8585a43cd04d1a50dc65227f337a91b18d66d5
branch: 2-0-4-stable
specs:
spree_api (2.0.4)
rabl (= 0.8.4)
spree_core (= 2.0.4)
versioncake (= 1.0.0)
spree_backend (2.0.4)
deface (>= 0.9.0)
jquery-rails (~> 3.0.0)
jquery-ui-rails (~> 4.0.0)
rails (~> 3.2.8)
select2-rails (~> 3.4.7)
spree_api (= 2.0.4)
spree_core (= 2.0.4)
spree_core (2.0.4)
activemerchant (~> 1.34)
acts_as_list (= 0.2.0)
@@ -166,7 +154,7 @@ GEM
bcrypt-ruby (3.1.5)
bcrypt (>= 3.1.3)
blockenspiel (0.5.0)
bugsnag (6.12.2)
bugsnag (6.13.0)
concurrent-ruby (~> 1.0)
builder (3.0.4)
byebug (9.0.6)
@@ -223,7 +211,7 @@ GEM
activerecord (>= 3.2.0, < 5.0)
fog (~> 1.0)
rails (>= 3.2.0, < 5.0)
ddtrace (0.32.0)
ddtrace (0.33.1)
msgpack
debugger-linecache (1.2.0)
deface (1.0.2)
@@ -261,7 +249,7 @@ GEM
factory_bot_rails (4.10.0)
factory_bot (~> 4.10.0)
railties (>= 3.0.0)
faraday (0.17.1)
faraday (1.0.0)
multipart-post (>= 1.2, < 3)
ffaker (1.22.1)
ffi (1.11.3)
@@ -437,7 +425,7 @@ GEM
httparty (0.16.2)
multi_xml (>= 0.5.2)
i18n (0.6.11)
i18n-js (3.5.1)
i18n-js (3.6.0)
i18n (>= 0.6.6)
immigrant (0.3.6)
activerecord (>= 3.0)
@@ -458,7 +446,7 @@ GEM
kaminari (0.14.1)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
kgio (2.11.2)
kgio (2.11.3)
knapsack (1.18.0)
rake
launchy (2.4.3)
@@ -479,20 +467,20 @@ GEM
railties (>= 3.1)
money (5.1.1)
i18n (~> 0.6.0)
msgpack (1.3.1)
msgpack (1.3.3)
multi_json (1.14.1)
multi_xml (0.6.0)
multipart-post (2.1.1)
newrelic_rpm (3.18.1.330)
nokogiri (1.6.8.1)
mini_portile2 (~> 2.1.0)
oauth2 (1.4.2)
oauth2 (1.4.4)
faraday (>= 0.8, < 2.0)
jwt (>= 1.0, < 3.0)
multi_json (~> 1.3)
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
oj (3.10.1)
oj (3.10.5)
orm_adapter (0.5.0)
paper_trail (5.2.3)
activerecord (>= 3.0, < 6.0)
@@ -506,7 +494,7 @@ GEM
parallel (1.19.1)
paranoia (1.3.4)
activerecord (~> 3.1)
parser (2.7.0.2)
parser (2.7.0.4)
ast (~> 2.4.0)
paypal-sdk-core (0.2.10)
multi_json (~> 1.0)
@@ -530,7 +518,7 @@ GEM
rack (1.4.7)
rack-cache (1.9.0)
rack (>= 0.4)
rack-mini-profiler (1.1.4)
rack-mini-profiler (1.1.6)
rack (>= 1.2.0)
rack-protection (1.5.5)
rack
@@ -559,7 +547,7 @@ GEM
rdoc (~> 3.4)
thor (>= 0.14.6, < 2.0)
rainbow (3.0.0)
raindrops (0.19.0)
raindrops (0.19.1)
rake (13.0.0)
ransack (0.7.2)
actionpack (~> 3.0)
@@ -578,19 +566,16 @@ GEM
redcarpet (3.5.0)
request_store (1.4.1)
rack (>= 1.4)
rexml (3.2.4)
roadie (3.4.0)
css_parser (~> 1.4)
nokogiri (~> 1.5)
roadie-rails (1.3.0)
railties (>= 3.0, < 5.3)
roadie (~> 3.1)
roo (2.8.2)
roo (2.8.3)
nokogiri (~> 1)
rubyzip (>= 1.2.1, < 2.0.0)
roo-xls (1.1.0)
nokogiri
roo (>= 2.0.0beta1, < 3)
spreadsheet (> 0.9.0)
rubyzip (>= 1.3.0, < 3.0.0)
rspec (3.9.0)
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
@@ -614,17 +599,17 @@ GEM
rspec-retry (0.6.2)
rspec-core (> 3.3)
rspec-support (3.9.0)
rubocop (0.79.0)
rubocop (0.80.1)
jaro_winkler (~> 1.5.1)
parallel (~> 1.10)
parser (>= 2.7.0.1)
rainbow (>= 2.2.2, < 4.0)
rexml
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 1.7)
rubocop-rails (2.4.2)
rack (>= 1.1)
rubocop (>= 0.72.0)
ruby-ole (1.2.12.1)
ruby-progressbar (1.10.1)
ruby-rc4 (0.1.5)
rubyzip (1.3.0)
@@ -653,8 +638,6 @@ GEM
tilt (>= 1.3, < 3)
spinjs-rails (1.4)
rails (>= 3.1)
spreadsheet (1.1.7)
ruby-ole (>= 1.0)
spring (1.7.2)
spring-commands-rspec (1.0.4)
spring (>= 0.9.1)
@@ -665,7 +648,7 @@ GEM
tilt (~> 1.1, != 1.3.0)
state_machine (1.2.0)
stringex (1.5.1)
stripe (5.11.0)
stripe (5.15.0)
test-unit (3.3.5)
power_assert
thor (0.20.3)
@@ -683,24 +666,20 @@ GEM
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unicode-display_width (1.6.1)
unicorn (5.5.2)
unicorn (5.5.3)
kgio (~> 2.6)
raindrops (~> 0.7)
unicorn-rails (2.2.1)
rack
unicorn
uuidtools (2.1.5)
versioncake (1.0.0)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
warden (1.2.7)
rack (>= 1.0)
webdrivers (4.2.0)
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (>= 3.0, < 4.0)
webmock (3.8.0)
webmock (3.8.2)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
@@ -760,10 +739,11 @@ DEPENDENCIES
gmaps4rails
haml
i18n (~> 0.6.11)
i18n-js (~> 3.5.1)
i18n-js (~> 3.6.0)
immigrant
jquery-migrate-rails
jquery-rails (= 3.0.4)
jquery-ui-rails (~> 4.0.0)
json_spec (~> 1.1.4)
jwt (~> 2.2)
kaminari (~> 0.14.1)
@@ -773,7 +753,7 @@ DEPENDENCIES
momentjs-rails
newrelic_rpm (~> 3.0)
nokogiri (>= 1.6.7.1)
oauth2 (~> 1.4.2)
oauth2 (~> 1.4.4)
ofn-qz!
oj
order_management!
@@ -790,20 +770,19 @@ DEPENDENCIES
rails_safe_tasks (~> 1.0)
redcarpet
roadie-rails (~> 1.3.0)
roo (~> 2.8.2)
roo-xls (~> 1.1.0)
roo (~> 2.8.3)
rspec-rails (>= 3.5.2)
rspec-retry
rubocop
rubocop-rails
sass (~> 3.3)
sass-rails (~> 3.2.3)
select2-rails (~> 3.4.7)
selenium-webdriver
shoulda-matchers
simple_form!
simplecov
spinjs-rails
spree_backend!
spree_core!
spree_i18n!
spree_paypal_express!

View File

@@ -12,6 +12,11 @@
//= require jquery.ui.all
//= require jquery-ui-timepicker-addon
//= require jquery.powertip
//= require jquery.cookie
//= require jquery.jstree/jquery.jstree
//= require jquery.vAlign
//= require jquery.horizontalNav
//= require jquery.adaptivemenu
//= require angular
//= require angular-resource
//= require angular-animate
@@ -20,13 +25,18 @@
//= require ../shared/ng-infinite-scroll.min.js
//= require ../shared/ng-tags-input.min.js
//= require angular-rails-templates
//= require lodash.underscore.js
// spree
//= require admin/spree_backend
//= require spree
//= require admin/spree/spree-select2
//= require modernizr
//= require spin
//= require equalize
//= require css_browser_selector_dev
//= require responsive-tables
//= require admin/spree_paypal_express
//= require admin/handlebar_extensions
// OFN specific
//= require_tree ../templates/admin

View File

@@ -1,4 +1,4 @@
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $filter, $http, $window, BulkProducts, DisplayProperties, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, Columns, tax_categories, RequestMonitor) ->
angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout, $filter, $http, $window, BulkProducts, DisplayProperties, DirtyProducts, VariantUnitManager, StatusMessage, producers, Taxons, Columns, tax_categories, RequestMonitor, SortOptions, ErrorsParser) ->
$scope.StatusMessage = StatusMessage
$scope.columns = Columns.columns
@@ -38,6 +38,8 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.query = ""
$scope.DisplayProperties = DisplayProperties
$scope.sortOptions = SortOptions
$scope.initialise = ->
$scope.fetchProducts()
@@ -54,6 +56,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
'q[name_cont]': $scope.query,
'q[supplier_id_eq]': $scope.producerFilter,
'q[primary_taxon_id_eq]': $scope.categoryFilter,
'q[s]': $scope.sorting,
import_date: $scope.importDateFilter,
page: $scope.page,
per_page: $scope.per_page
@@ -103,9 +106,16 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.categoryFilter = "0"
$scope.importDateFilter = "0"
$scope.$watch 'sortOptions', (sort) ->
return unless sort && sort.predicate != ""
$scope.sorting = sort.getSortingExpr()
$scope.fetchProducts()
, true
confirm_unsaved_changes = () ->
(DirtyProducts.count() > 0 and confirm(t("unsaved_changes_confirmation"))) or (DirtyProducts.count() == 0)
editProductUrl = (product, variant) ->
"/admin/products/" + product.permalink_live + ((if variant then "/variants/" + variant.id else "")) + "/edit"
@@ -220,10 +230,9 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
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")
if status == 400 && data.errors?
errorsString = ErrorsParser.toString(data.errors, status)
$scope.displayFailure t("products_update_error") + "\n" + errorsString
else
$scope.displayFailure t("products_update_error_data") + status
@@ -274,7 +283,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
$scope.displayFailure = (failMessage) ->
StatusMessage.display 'failure', t("products_update_error_msg") + "#{failMessage}"
StatusMessage.display 'failure', t("products_update_error_msg") + " #{failMessage}"
$scope.displayDirtyProducts = ->

View File

@@ -3,6 +3,11 @@ angular.module("admin.indexUtils").factory 'SortOptions', ->
predicate: ""
reverse: true
getSortingExpr: () ->
sortingExpr = this.predicate + ' desc' if this.reverse
sortingExpr = this.predicate + ' asc' if !this.reverse
sortingExpr
toggle: (predicate) ->
@reverse = (@predicate == predicate) && !@reverse
@predicate = predicate

View File

@@ -48,13 +48,15 @@ angular.module('admin.orderCycles')
return if enterprise.last_page_loaded? && enterprise.last_page_loaded >= page
enterprise.last_page_loaded = page
enterprise.loaded_variants ?= 0
incoming = true if $scope.view == 'incoming'
params = { exchange_id: exchange.id, enterprise_id: exchange.enterprise_id, order_cycle_id: $scope.order_cycle.id, incoming: incoming, page: page}
ExchangeProduct.index params, (products, num_of_pages, num_of_products) ->
ExchangeProduct.index params, (products, num_of_pages) ->
enterprise.num_of_pages = num_of_pages
enterprise.num_of_products = num_of_products
enterprise.supplied_products.push products...
angular.forEach products, (product) ->
enterprise.loaded_variants += product.variants.length
$scope.loadMoreExchangeProducts = (exchange) ->
$scope.loadExchangeProducts(exchange, $scope.enterprises[exchange.enterprise_id].last_page_loaded + 1)

View File

@@ -8,7 +8,7 @@ angular.module('admin.orderCycles').factory('ExchangeProduct', ($resource) ->
index: (params={}, callback=null) ->
ExchangeProductResource.index params, (data) =>
(callback || angular.noop)(data.products, data.pagination.pages, data.pagination.results)
(callback || angular.noop)(data.products, data.pagination?.pages, data.pagination?.results)
countVariants: (params={}, callback=null) ->
ExchangeProductResource.variant_count params, (data) =>

View File

@@ -64,10 +64,10 @@ angular.module("admin.orders").controller "ordersCtrl", ($scope, $timeout, Reque
$scope.selected_orders.push order.id if $scope.select_all
$scope.$watch 'sortOptions', (sort) ->
if sort && sort.predicate != ""
$scope.sorting = sort.predicate + ' desc' if sort.reverse
$scope.sorting = sort.predicate + ' asc' if !sort.reverse
$scope.fetchResults()
return unless sort && sort.predicate != ""
$scope.sorting = sort.getSortingExpr()
$scope.fetchProducts()
, true
$scope.capturePayment = (order) ->

View File

@@ -3,6 +3,9 @@ angular.module("admin.orders").directive 'customerSearchOverride', ->
scope:
distributorId: '@'
link: (scope, element, attr) ->
if $('#customer_autocomplete_template').length > 0
customerTemplate = Handlebars.compile($('#customer_autocomplete_template').text())
formatCustomerResult = (customer) ->
customerTemplate
customer: customer

View File

@@ -21,7 +21,7 @@ angular.module('admin.payments').factory 'Payment', (AdminStripeElements, curren
year: @form_data.card_year
verification_value: @form_data.card_verification_value
}
when 'stripe'
when 'stripe', 'stripe_sca'
angular.extend munged_payment.payment, {
source_attributes:
gateway_payment_profile_id: @form_data.token
@@ -35,6 +35,8 @@ angular.module('admin.payments').factory 'Payment', (AdminStripeElements, curren
purchase: ->
if @paymentMethodType() == 'stripe'
AdminStripeElements.requestToken(@form_data, @submit)
else if @paymentMethodType() == 'stripe_sca'
AdminStripeElements.createPaymentMethod(@form_data, @submit)
else
@submit()

View File

@@ -5,7 +5,7 @@ angular.module("admin.payments").factory 'AdminStripeElements', ($rootScope, Sta
stripe: null
card: null
# New Stripe Elements method
# Create Token to be used with the Stripe Charges API
requestToken: (secrets, submit) ->
return unless @stripe? && @card?
@@ -20,6 +20,21 @@ angular.module("admin.payments").factory 'AdminStripeElements', ($rootScope, Sta
secrets.card = response.token.card
submit()
# Create Payment Method to be used with the Stripe Payment Intents API
createPaymentMethod: (secrets, submit) ->
return unless @stripe? && @card?
cardData = @makeCardData(secrets)
@stripe.createPaymentMethod({ type: 'card', card: @card }, @card, cardData).then (response) =>
if(response.error)
StatusMessage.display 'error', response.error.message
else
secrets.token = response.paymentMethod.id
secrets.cc_type = response.paymentMethod.card.brand
secrets.card = response.paymentMethod.card
submit()
# Maps the brand returned by Stripe to that required by activemerchant
mapCC: (ccType) ->
switch ccType

View File

@@ -21,9 +21,7 @@ angular.module("admin.products").factory "OptionValueNamer", (VariantUnitManager
else
value = @variant.unit_value
unit_name = @variant.product.variant_unit_name
# TODO needs to add pluralize to line below
# unit_name = unit_name if value > 1
unit_name = @pluralize(@variant.product.variant_unit_name, value)
value = parseInt(value, 10) if value == parseInt(value, 10)
@@ -32,6 +30,21 @@ angular.module("admin.products").factory "OptionValueNamer", (VariantUnitManager
[value, unit_name]
pluralize: (unit_name, count) ->
return unit_name if count == undefined
unit_key = @unit_key(unit_name)
return unit_name unless unit_key
I18n.t(["inflections", unit_key], {count: count, defaultValue: unit_name})
unit_key: (unit_name) ->
unless I18n.unit_keys
I18n.unit_keys = {}
for key, translations of I18n.t("inflections")
for quantifier, translation of translations
I18n.unit_keys[translation.toLowerCase()] = key
I18n.unit_keys[unit_name.toLowerCase()]
option_value_value_unit_scaled: ->
[unit_scale, unit_name] = @scale_for_unit_value()

View File

@@ -0,0 +1,252 @@
//= require_self
//= require admin/handlebar_extensions
//= require admin/spree/orders/variant_autocomplete
/**
This is a collection of javascript functions and whatnot
under the spree namespace that do stuff we find helpful.
Hopefully, this will evolve into a propper class.
**/
jQuery(function($) {
// Make main menu use full width
mainMenu = $('.fullwidth-menu')
if (typeof mainMenu.horizontalNav === 'function' )
mainMenu.horizontalNav({
tableDisplay: false,
responsiveDelay: 0
});
// Vertical align of checkbox fields
if (typeof $('.field.checkbox label').vAlign === 'function' )
$('.field.checkbox label').vAlign()
// We activate AdaptiveMenu only if not on webdriver
// Re-adjusting the admin menu during tests causes tests to fail.
if (!navigator.webdriver && typeof Spree !== 'undefined') {
$('.main-menu-wrapper ul').AdaptiveMenu({
text: "<a href='#'><i class='icon-chevron-down'></i> " + Spree.translations.more + "</a>",
klass: "dropdown"
});
}
// Add some tips
if (typeof $('.with-tip').powerTip === 'function' ) {
$('.with-tip').powerTip({
smartPlacement: true,
fadeInTime: 50,
fadeOutTime: 50,
intentPollInterval: 300
});
$('.with-tip').on({
powerTipPreRender: function(){
$('#powerTip').addClass($(this).attr("data-action"));
$('#powerTip').addClass($(this).attr("data-tip-color"));
},
powerTipClose: function(){
$('#powerTip').removeClass($(this).attr("data-action"))
}
});
}
// Make flash messages dissapear
setTimeout('$(".flash").fadeOut()', 5000);
// Highlight hovered table column
$('table tbody tr td.actions a').hover(function(){
var tr = $(this).closest('tr');
var klass = 'highlight action-' + $(this).attr('data-action')
tr.addClass(klass)
tr.prev().addClass('before-' + klass);
}, function(){
var tr = $(this).closest('tr');
var klass = 'highlight action-' + $(this).attr('data-action')
tr.removeClass(klass)
tr.prev().removeClass('before-' + klass);
});
// Trunkate text in page_title that didn't fit
var truncate_elements = $('.truncate');
truncate_elements.each(function(){
$(this).trunk8();
});
$(window).resize(function (event) {
truncate_elements.each(function(){
$(this).trunk8();
})
});
// Make height of dt/dd elements the same
if (typeof $("dl").equalize === 'function' )
$("dl").equalize('outerHeight');
});
$.fn.visible = function(cond) { this[cond ? 'show' : 'hide' ]() };
// Overriding a broken function in Spree. Bug report at
// https://github.com/spree/spree/issues/4032
show_flash_error = function(message) {
error_div = $('.flash.error');
if (error_div.length > 0) {
error_div.html(message);
error_div.show();
} else {
if ($("#content .toolbar").length > 0) {
$("#content .toolbar").before('<div class="flash error">' + message + '</div>');
} else {
$("#progress").before('<div class="flash error">' + message + '</div>');
}
}
}
// Apply to individual radio button that makes another element visible when checked
$.fn.radioControlsVisibilityOfElement = function(dependentElementSelector){
if(!this.get(0)){ return }
showValue = this.get(0).value;
radioGroup = $("input[name='" + this.get(0).name + "']");
radioGroup.each(function(){
$(this).click(function(){
$(dependentElementSelector).visible(this.checked && this.value == showValue)
});
if(this.checked){ this.click() }
});
}
$(document).ready(function() {
if (typeof Spree !== 'undefined') {
handle_date_picker_fields = function(){
$('.datepicker').datepicker({
dateFormat: Spree.translations.date_picker,
dayNames: Spree.translations.abbr_day_names,
dayNamesMin: Spree.translations.abbr_day_names,
monthNames: Spree.translations.month_names,
prevText: Spree.translations.previous,
nextText: Spree.translations.next,
showOn: "focus"
});
// Correctly display range dates
$('.date-range-filter .datepicker-from').datepicker('option', 'onSelect', function(selectedDate) {
$(".date-range-filter .datepicker-to" ).datepicker( "option", "minDate", selectedDate );
});
$('.date-range-filter .datepicker-to').datepicker('option', 'onSelect', function(selectedDate) {
$(".date-range-filter .datepicker-from" ).datepicker( "option", "maxDate", selectedDate );
});
}
handle_date_picker_fields();
}
$(".observe_field").on('change', function() {
target = $(this).attr("data-update");
ajax_indicator = $(this).attr("data-ajax-indicator") || '#busy_indicator';
$(target).hide();
$(ajax_indicator).show();
$.ajax({ dataType: 'html',
url: $(this).attr("data-base-url")+encodeURIComponent($(this).val()),
type: 'get',
success: function(data){
$(target).html(data);
$(ajax_indicator).hide();
$(target).show();
}
});
});
$('.spree_add_fields').click(function() {
var target = $(this).data("target");
var new_table_row = $(target + ' tr:visible:last').clone();
var new_id = new Date().getTime();
new_table_row.find("input, select").each(function () {
var el = $(this);
el.val("");
if (typeof el.attr("id") !== 'undefined') el.attr("id", el.attr("id").replace(/\d+/, new_id))
if (typeof el.attr("name") !== 'undefined') el.attr("name", el.attr("name").replace(/\d+/, new_id))
})
// When cloning a new row, set the href of all icons to be an empty "#"
// This is so that clicking on them does not perform the actions for the
// duplicated row
new_table_row.find("a").each(function () {
var el = $(this);
el.attr('href', '#');
})
$(target).prepend(new_table_row);
})
$('body').on('click', '.delete-resource', function() {
var el = $(this);
if (confirm(el.data("confirm"))) {
$.ajax({
type: 'POST',
url: $(this).attr("href"),
data: {
_method: 'delete',
authenticity_token: AUTH_TOKEN
},
dataType: 'html',
success: function(response) {
el.parents("tr").fadeOut('hide');
},
error: function(response, textStatus, errorThrown) {
show_flash_error(response.responseText);
}
});
}
return false;
});
// Fix sortable helper
var fixHelper = function(e, ui) {
ui.children().each(function() {
$(this).width($(this).width());
});
return ui;
};
$('table.sortable').ready(function(){
var td_count = $(this).find('tbody tr:first-child td').length
if (typeof $('table.sortable tbody').sortable !== 'function' )
return
$('table.sortable tbody').sortable(
{
handle: '.handle',
helper: fixHelper,
placeholder: 'ui-sortable-placeholder',
update: function(event, ui) {
$("#progress").show();
positions = {};
$.each($('table.sortable tbody tr'), function(position, obj){
reg = /spree_(\w+_?)+_(\d+)/;
parts = reg.exec($(obj).attr('id'));
if (parts) {
positions['positions['+parts[2]+']'] = position;
}
});
$.ajax({
type: 'POST',
dataType: 'script',
url: $(ui.item).closest("table.sortable").data("sortable-link"),
data: positions,
success: function(data){ $("#progress").hide(); }
});
},
start: function (event, ui) {
// Set correct height for placehoder (from dragged tr)
ui.placeholder.height(ui.item.height())
// Fix placeholder content to make it correct width
ui.placeholder.html("<td colspan='"+(td_count-1)+"'></td><td class='actions'></td>")
},
stop: function (event, ui) {
// Fix odd/even classes after reorder
$("table.sortable tr:even").removeClass("odd even").addClass("even");
$("table.sortable tr:odd").removeClass("odd even").addClass("odd");
}
});
});
});

View File

@@ -0,0 +1,16 @@
$(function() {
var calculator_select = $('select#calc_type')
var original_calc_type = calculator_select.attr('value');
$('.calculator-settings-warning').hide();
calculator_select.change(function() {
if (calculator_select.attr('value') == original_calc_type) {
$('div.calculator-settings').show();
$('.calculator-settings-warning').hide();
$('.calculator-settings').find('input,textarea').prop("disabled", false);
} else {
$('div.calculator-settings').hide();
$('.calculator-settings-warning').show();
$('.calculator-settings').find('input,texttarea').prop("disabled", true);
}
});
})

View File

@@ -0,0 +1,59 @@
$(document).ready(function() {
if ($('input#preferences_use_s3[type="checkbox"]:checked').length > 0) {
$('#s3_settings, #s3_headers').show();
}
// Toggle display of S3 settings based on value of use_s3 checkbox
$('input#preferences_use_s3[type="checkbox"]').click(function() {
$('#s3_settings, #s3_headers').toggle();
});
$(document).on('click', '.destroy_style', function(e) {
e.preventDefault();
$(this).parent().remove();
});
$(document).on('click', '.destroy_new_attachment_styles', function(e) {
e.preventDefault();
$(this).closest('.new_attachment_styles').remove();
});
$(document).on('click', '.destroy_new_s3_headers', function(e) {
e.preventDefault();
$(this).closest('.new_s3_headers').remove();
});
// Handle adding new styles
var styles_hash_index = 1;
$(document).on('click', '.add_new_style', function(e) {
e.preventDefault();
$('#new-styles').append(generate_html_for_hash("new_attachment_styles", styles_hash_index));
});
// Handle adding new headers
var headers_hash_index = 1;
$(document).on('click', '.add_header', function(e) {
e.preventDefault();
$('#headers_list').append(generate_html_for_hash("new_s3_headers", headers_hash_index));
});
// Generates html for new paperclip styles form fields
generate_html_for_hash = function(hash_name, index) {
var html = '<div class="' + hash_name + ' row"><div class="field">';
html += '<div class="five columns">';
html += '<label for="' + hash_name + '_' + index + '_name">';
html += Spree.translations.name + '</label>';
html += '<input id="' + hash_name + '_' + index + '_name" name="' + hash_name + '[' + index + '][name]" type="text" class="fullwidth"><br>';
html += '</div><div class="five columns">'
html += '<label for="' + hash_name + '_' + index + '_value">';
html += Spree.translations.value + '</label>';
html += '<input id="' + hash_name + '_' + index + '_value" name="' + hash_name + '[' + index + '][value]" type="text" class="fullwidth">';
html += '</div><div class="two columns">'
html += '<a href="#" title="' + Spree.translations.destroy + '" class="destroy_' + hash_name + ' with-tip button" style="margin-top: 19px;"><i class="icon-trash"></i> &nbsp; ' + Spree.translations.destroy + '</a>';
html += '</div></div></div>';
index += 1;
return html;
};
});

View File

@@ -0,0 +1,23 @@
//On page load
replace_ids = function(s){
var new_id = new Date().getTime();
return s.replace(/NEW_RECORD/g, new_id);
}
$(function() {
$('a[id*=nested]').click(function() {
var template = $(this).attr('href').replace(/.*#/, '');
html = replace_ids(eval(template));
$('#ul-' + $(this).attr('id')).append(html);
update_remove_links();
});
update_remove_links();
})
var update_remove_links = function() {
$('.remove').click(function() {
$(this).prevAll(':first').val(1);
$(this).parent().hide();
return false;
});
};

View File

@@ -0,0 +1,27 @@
var update_state = function(region) {
var country = $('span#' + region + 'country .select2').select2('val');
var state_select = $('span#' + region + 'state select.select2');
var state_input = $('span#' + region + 'state input.state_name');
$.get(Spree.routes.states_search + "?country_id=" + country, function(data) {
var states = data["states"]
if (states.length > 0) {
state_select.html('');
var states_with_blank = [{name: '', id: ''}].concat(states);
$.each(states_with_blank, function(pos,state) {
var opt = $(document.createElement('option'))
.attr('value', state.id)
.html(state.name);
state_select.append(opt);
});
state_select.prop("disabled", false).show();
state_select.select2();
state_input.hide().prop("disabled", true);
} else {
state_input.prop("disabled", false).show();
state_select.select2('destroy').hide();
}
})
};

View File

@@ -0,0 +1,64 @@
// Shipments AJAX API
$(document).ready(function() {
handle_ship_click = function(){
var link = $(this);
var shipment_number = link.data('shipment-number');
var url = Spree.url( Spree.routes.orders_api + "/" + order_number + "/shipments/" + shipment_number + "/ship.json");
$.ajax({
type: "PUT",
url: url
}).done(function( msg ) {
window.location.reload();
}).error(function( msg ) {
console.log(msg);
});
}
$('[data-hook=admin_order_edit_form] a.ship').click(handle_ship_click);
//handle shipping method edit click
$('a.edit-method').click(toggleMethodEdit);
$('a.cancel-method').click(toggleMethodEdit);
handle_shipping_method_save = function(){
var link = $(this);
var shipment_number = link.data('shipment-number');
var selected_shipping_rate_id = link.parents('tbody').find("select#selected_shipping_rate_id[data-shipment-number='" + shipment_number + "']").val();
var unlock = link.parents('tbody').find("input[name='open_adjustment'][data-shipment-number='" + shipment_number + "']:checked").val();
var url = Spree.url( Spree.routes.orders_api + "/" + order_number + "/shipments/" + shipment_number + ".json");
$.ajax({
type: "PUT",
url: url,
data: { shipment: { selected_shipping_rate_id: selected_shipping_rate_id, unlock: unlock } }
}).done(function( msg ) {
window.location.reload();
}).error(function( msg ) {
console.log(msg);
});
}
$('[data-hook=admin_order_edit_form] a.save-method').click(handle_shipping_method_save);
//handle tracking edit click
$('a.edit-tracking').click(toggleTrackingEdit);
$('a.cancel-tracking').click(toggleTrackingEdit);
handle_tracking_save = function(){
var link = $(this);
var shipment_number = link.data('shipment-number');
var tracking = link.parents('tbody').find('input#tracking').val();
var url = Spree.url( Spree.routes.orders_api + "/" + order_number + "/shipments/" + shipment_number + ".json");
$.ajax({
type: "PUT",
url: url,
data: { shipment: { tracking: tracking } }
}).done(function( msg ) {
window.location.reload();
}).error(function( msg ) {
console.log(msg);
});
}
$('[data-hook=admin_order_edit_form] a.save-tracking').click(handle_tracking_save);
});

View File

@@ -0,0 +1,141 @@
// variant autocompletion
$(document).ready(function() {
if ($('#variant_autocomplete_template').length > 0) {
window.variantTemplate = Handlebars.compile($('#variant_autocomplete_template').text());
window.variantStockTemplate = Handlebars.compile($('#variant_autocomplete_stock_template').text());
// handle variant selection, show stock level.
$('#add_variant_id').change(function(){
var variant_id = $(this).val();
var variant = _.find(window.variants, function(variant){
return variant.id == variant_id
})
$('#stock_details').html(variantStockTemplate({variant: variant}));
$('#stock_details').show();
$('button.add_variant').click(addVariantFromStockLocation);
// Add some tips
$('.with-tip').powerTip({
smartPlacement: true,
fadeInTime: 50,
fadeOutTime: 50,
intentPollInterval: 300
});
});
//handle edit click
$('a.edit-item').click(toggleItemEdit);
//handle cancel click
$('a.cancel-item').click(toggleItemEdit);
handle_save_click = function(){
var save = $(this);
var shipment_number = save.data('shipment-number');
var variant_id = save.data('variant-id');
var quantity = parseInt(save.parents('tr').find('input.line_item_quantity').val());
toggleItemEdit();
adjustItems(shipment_number, variant_id, quantity);
return false;
}
$('a.save-item').click(handle_save_click);
handle_delete_click = function(){
var del = $(this);
var shipment_number = del.data('shipment-number');
var variant_id = del.data('variant-id');
toggleItemEdit();
adjustItems(shipment_number, variant_id, 0);
}
$('a.delete-item').click(handle_delete_click);
}
});
adjustItems = function(shipment_number, variant_id, quantity){
var shipment = _.findWhere(shipments, {number: shipment_number + ''});
var inventory_units = _.where(shipment.inventory_units, {variant_id: variant_id});
var url = Spree.routes.orders_api + "/" + order_number + "/shipments/" + shipment_number;
var new_quantity = 0;
if(inventory_units.length<quantity){
url += "/add"
new_quantity = (quantity - inventory_units.length);
}else if(inventory_units.length>quantity){
url += "/remove"
new_quantity = (inventory_units.length - quantity);
}
url += '.json';
if(new_quantity!=0){
$.ajax({
type: "PUT",
url: Spree.url(url),
data: { variant_id: variant_id, quantity: new_quantity }
}).done(function( msg ) {
window.location.reload();
});
}
}
toggleTrackingEdit = function(){
var link = $(this);
link.parents('tbody').find('tr.edit-tracking').toggle();
link.parents('tbody').find('tr.show-tracking').toggle();
}
toggleMethodEdit = function(){
var link = $(this);
link.parents('tbody').find('tr.edit-method').toggle();
link.parents('tbody').find('tr.show-method').toggle();
}
toggleItemEdit = function(){
var link = $(this);
link.parent().find('a.edit-item').toggle();
link.parent().find('a.cancel-item').toggle();
link.parent().find('a.save-item').toggle();
link.parent().find('a.delete-item').toggle();
link.parents('tr').find('td.item-qty-show').toggle();
link.parents('tr').find('td.item-qty-edit').toggle();
return false;
}
addVariantFromStockLocation = function() {
$('#stock_details').hide();
var variant_id = $('input.variant_autocomplete').val();
var stock_location_id = $(this).data('stock-location-id');
var quantity = $("input.quantity[data-stock-location-id='" + stock_location_id + "']").val();
var shipment = _.find(shipments, function(shipment){
return shipment.stock_location_id == stock_location_id && (shipment.state == 'ready' || shipment.state == 'pending');
});
if(shipment==undefined){
$.ajax({
type: "POST",
url: Spree.url(Spree.routes.orders_api + "/" + order_number + "/shipments.json"),
data: { variant_id: variant_id, quantity: quantity, stock_location_id: stock_location_id }
}).done(function( msg ) {
window.location.reload();
}).error(function( msg ) {
console.log(msg);
});
}else{
//add to existing shipment
adjustItems(shipment.number, variant_id, quantity);
}
return 1
}

View File

@@ -0,0 +1,27 @@
$(document).ready ->
opts =
lines: 11
length: 2
width: 3
radius: 9
corners: 1
rotate: 0
color: '#fff'
speed: 0.8
trail: 48
shadow: false
hwaccel: true
className: 'spinner'
zIndex: 2e9
top: 'auto'
left: 'auto'
target = document.getElementById("spinner")
$(document).ajaxStart ->
$("#progress").fadeIn()
spinner = new Spinner(opts).spin(target)
$(document).ajaxStop ->
$("#progress").fadeOut()

View File

@@ -0,0 +1,8 @@
//= require select2
jQuery(function($) {
// Make select beautiful
if (typeof $('select.select2').select2 === 'function' )
$('select.select2').select2({
allowClear: true
});
})

View File

@@ -0,0 +1,8 @@
$(document).ready(function() {
$("#country").change(function() {
var new_state_link_href = $('#new_state_link a').attr('href');
var selected_country_id = $('#country option:selected').attr('value');
var new_link = new_state_link_href.replace(/countries\/(\d+)/, 'countries/'+selected_country_id);
$('#new_state_link a').attr('href', new_link);
});
});

View File

@@ -0,0 +1,22 @@
root = exports ? this
root.taxon_tree_menu = (obj, context) ->
base_url = Spree.url(Spree.routes.taxonomy_taxons_path)
admin_base_url = Spree.url(Spree.routes.admin_taxonomy_taxons_path)
edit_url = admin_base_url.clone()
edit_url.setPath(edit_url.path() + '/' + obj.attr("id") + "/edit");
create:
label: "<i class='icon-plus'></i> " + Spree.translations.add,
action: (obj) -> context.create(obj)
rename:
label: "<i class='icon-pencil'></i> " + Spree.translations.rename,
action: (obj) -> context.rename(obj)
remove:
label: "<i class='icon-trash'></i> " + Spree.translations.remove,
action: (obj) -> context.remove(obj)
edit:
separator_before: true,
label: "<i class='icon-edit'></i> " + Spree.translations.edit,
action: (obj) -> window.location = edit_url.toString()

View File

@@ -0,0 +1,127 @@
handle_ajax_error = (XMLHttpRequest, textStatus, errorThrown) ->
$.jstree.rollback(last_rollback)
$("#ajax_error").show().html("<strong>" + server_error + "</strong><br />" + taxonomy_tree_error)
handle_move = (e, data) ->
last_rollback = data.rlbk
position = data.rslt.cp
node = data.rslt.o
new_parent = data.rslt.np
url = Spree.url(base_url).clone()
url.setPath url.path() + '/' + node.attr("id")
$.ajax
type: "POST",
dataType: "json",
url: url.toString(),
data: ({_method: "put", "taxon[parent_id]": new_parent.attr("id"), "taxon[position]": position }),
error: handle_ajax_error
true
handle_create = (e, data) ->
last_rollback = data.rlbk
node = data.rslt.obj
name = data.rslt.name
position = data.rslt.position
new_parent = data.rslt.parent
$.ajax
type: "POST",
dataType: "json",
url: base_url.toString(),
data: ({"taxon[name]": name, "taxon[parent_id]": new_parent.attr("id"), "taxon[position]": position }),
error: handle_ajax_error,
success: (data,result) ->
node.attr('id', data.id)
handle_rename = (e, data) ->
last_rollback = data.rlbk
node = data.rslt.obj
name = data.rslt.new_name
url = Spree.url(base_url).clone()
url.setPath(url.path() + '/' + node.attr("id"))
$.ajax
type: "POST",
dataType: "json",
url: url.toString(),
data: {_method: "put", "taxon[name]": name },
error: handle_ajax_error
handle_delete = (e, data) ->
last_rollback = data.rlbk
node = data.rslt.obj
delete_url = base_url.clone()
delete_url.setPath delete_url.path() + '/' + node.attr("id")
if confirm(Spree.translations.are_you_sure_delete)
$.ajax
type: "POST",
dataType: "json",
url: delete_url.toString(),
data: {_method: "delete"},
error: handle_ajax_error
else
$.jstree.rollback(last_rollback)
last_rollback = null
root = exports ? this
root.setup_taxonomy_tree = (taxonomy_id) ->
if taxonomy_id != undefined
# this is defined within admin/taxonomies/edit
root.base_url = Spree.url(Spree.routes.taxonomy_taxons_path)
$.ajax
url: base_url.path().replace("/taxons", "/jstree"),
success: (taxonomy) ->
last_rollback = null
conf =
json_data:
data: taxonomy,
ajax:
url: (e) ->
base_url.path() + '/' + e.attr('id') + '/jstree'
themes:
theme: "apple",
url: "/assets/jquery.jstree/themes/apple/style.css"
strings:
new_node: new_taxon,
loading: Spree.translations.loading + "..."
crrm:
move:
check_move: (m) ->
position = m.cp
node = m.o
new_parent = m.np
# no parent or cant drag and drop
if !new_parent || node.attr("rel") == "root"
return false
# can't drop before root
if new_parent.attr("id") == "taxonomy_tree" && position == 0
return false
true
contextmenu:
items: (obj) ->
taxon_tree_menu(obj, this)
plugins: ["themes", "json_data", "dnd", "crrm", "contextmenu"]
$("#taxonomy_tree").jstree(conf)
.bind("move_node.jstree", handle_move)
.bind("remove.jstree", handle_delete)
.bind("create.jstree", handle_create)
.bind("rename.jstree", handle_rename)
.bind "loaded.jstree", ->
$(this).jstree("core").toggle_node($('.jstree-icon').first())
$("#taxonomy_tree a").on "dblclick", (e) ->
$("#taxonomy_tree").jstree("rename", this)
# surpress form submit on enter/return
$(document).keypress (e) ->
if e.keyCode == 13
e.preventDefault()

View File

@@ -0,0 +1,43 @@
$ ->
($ '#country_based').click ->
show_country()
($ '#state_based').click ->
show_state()
if ($ '#country_based').is(':checked')
show_country()
else if ($ '#state_based').is(':checked')
show_state()
else
show_state()
($ '#state_based').click()
show_country = ->
($ '#state_members :input').each ->
($ this).prop 'disabled', true
($ '#state_members').hide()
($ '#zone_members :input').each ->
($ this).prop 'disabled', true
($ '#zone_members').hide()
($ '#country_members :input').each ->
($ this).prop 'disabled', false
($ '#country_members').show()
show_state = ->
($ '#country_members :input').each ->
($ this).prop 'disabled', true
($ '#country_members').hide()
($ '#zone_members :input').each ->
($ this).prop 'disabled', true
($ '#zone_members').hide()
($ '#state_members :input').each ->
($ this).prop 'disabled', false
($ '#state_members').show()

View File

@@ -16,7 +16,7 @@ angular.module("admin.subscriptions").controller "DetailsController", ($scope, $
return if !newValue?
paymentMethod = ($scope.paymentMethods.filter (pm) -> pm.id == newValue)[0]
return unless paymentMethod?
$scope.cardRequired = (paymentMethod.type == "Spree::Gateway::StripeConnect")
$scope.cardRequired = (paymentMethod.type == "Spree::Gateway::StripeConnect" || paymentMethod.type == "Spree::Gateway::StripeSCA")
$scope.loadCustomer() if $scope.cardRequired && !$scope.customer
$scope.loadCustomer = ->

View File

@@ -16,22 +16,6 @@ $(document).ready(function() {
});
});
// Overriding a broken function in Spree. Bug report at
// https://github.com/spree/spree/issues/4032
show_flash_error = function(message) {
error_div = $('.flash.error');
if (error_div.length > 0) {
error_div.html(message);
error_div.show();
} else {
if ($("#content .toolbar").length > 0) {
$("#content .toolbar").before('<div class="flash error">' + message + '</div>');
} else {
$("#progress").before('<div class="flash error">' + message + '</div>');
}
}
}
$(document).ready(function(){
$('a.close').click(function(event){
event.preventDefault();

View File

@@ -1,10 +1,6 @@
angular.module("admin.utils").directive "variantAutocomplete", ($timeout) ->
restrict: 'C'
link: (scope, element, attrs) ->
# Make variantAutocomplete do nothing because it is called
# from core/app/assets/javascripts/admin/orders/edit.js
$.fn.variantAutocomplete = angular.noop
$timeout ->
if $("#variant_autocomplete_template").length > 0
variantTemplate = Handlebars.compile($("#variant_autocomplete_template").text())

View File

@@ -0,0 +1,21 @@
# Parses a structure of errors that came from the server
angular.module("admin.utils").factory "ErrorsParser", ->
new class ErrorsParser
toString: (errors, defaultContent = "") =>
return defaultContent unless errors?
errorsString = ""
if errors.length > 0
# it is an array of errors
errorsString = errors.join("\n") + "\n"
else
# it is a hash of errors
keys = Object.keys(errors)
for key in keys
errorsString += errors[key].join("\n") + "\n"
this.defaultIfEmpty(errorsString, defaultContent)
defaultIfEmpty: (content, defaultContent) =>
return defaultContent if content == ""
content

View File

@@ -7,6 +7,8 @@ Darkswarm.factory 'Checkout', ($injector, CurrentOrder, ShippingMethods, StripeE
purchase: ->
if @paymentMethod()?.method_type == 'stripe' && !@secrets.selected_card
StripeElements.requestToken(@secrets, @submit)
else if @paymentMethod()?.method_type == 'stripe_sca' && !@secrets.selected_card
StripeElements.createPaymentMethod(@secrets, @submit)
else
@submit()
@@ -59,7 +61,7 @@ Darkswarm.factory 'Checkout', ($injector, CurrentOrder, ShippingMethods, StripeE
last_name: @order.bill_address.lastname
}
if @paymentMethod()?.method_type == 'stripe'
if @paymentMethod()?.method_type == 'stripe' || @paymentMethod()?.method_type == 'stripe_sca'
if @secrets.selected_card
angular.extend munged_order, {
existing_card_id: @secrets.selected_card

View File

@@ -1,12 +1,10 @@
Darkswarm.factory 'StripeElements', ($rootScope, Loading, RailsFlashLoader) ->
new class StripeElements
# TODO: add locale here for translations of error messages etc. from Stripe
# These are both set from the StripeElements directive
stripe: null
card: null
# New Stripe Elements method
# Create Token to be used with the Stripe Charges API
requestToken: (secrets, submit, loading_message = t("processing_payment")) ->
return unless @stripe? && @card?
@@ -23,6 +21,23 @@ Darkswarm.factory 'StripeElements', ($rootScope, Loading, RailsFlashLoader) ->
secrets.card = response.token.card
submit()
# Create Payment Method to be used with the Stripe Payment Intents API
createPaymentMethod: (secrets, submit, loading_message = t("processing_payment")) ->
return unless @stripe? && @card?
Loading.message = loading_message
cardData = @makeCardData(secrets)
@stripe.createPaymentMethod({ type: 'card', card: @card }, @card, cardData).then (response) =>
if(response.error)
Loading.clear()
RailsFlashLoader.loadFlash({error: t("error") + ": #{response.error.message}"})
else
secrets.token = response.paymentMethod.id
secrets.cc_type = response.paymentMethod.card.brand
secrets.card = response.paymentMethod.card
submit()
# Maps the brand returned by Stripe to that required by activemerchant
mapCC: (ccType) ->
switch ccType

View File

@@ -9,7 +9,7 @@
'ng-model' => 'exchange.select_all_variants',
'ng-change' => 'setExchangeVariants(exchange, incomingExchangeVariantsFor(exchange.enterprise_id), exchange.select_all_variants)',
'id' => 'order_cycle_outgoing_exchange_{{ $parent.$index }}_select_all_variants' }
{{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }}
{{ 'js.admin.panels.exchange_products.select_all_variants' | t:{ total_number_of_variants: exchangeTotalVariants(exchange) } }}
.exchange-products{ 'ng-hide' => 'productsLoading()' }
.exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products | filter:visibleProducts:exchange:order_cycle.visible_variants_for_outgoing_exchanges' }

View File

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

View File

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

View File

@@ -9,7 +9,7 @@
'ng-model' => 'exchange.select_all_variants',
'ng-change' => 'selectAllVariants(exchange, exchange.select_all_variants)',
'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' }
{{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }}
{{ 'js.admin.panels.exchange_products.select_all_variants' | t:{ total_number_of_variants: exchangeTotalVariants(exchange) } }}
%div{ 'ng-include' => "'admin/panels/exchange_products_supplied_list.html'" }

View File

@@ -4,25 +4,45 @@
* the top of the compiled file, but it's generally better to create a new file per style scope.
*
*= require admin/spree_backend
*= require jquery.powertip
*= require normalize
*= require skeleton
*= require responsive-tables
*= require jquery.powertip
*= require jquery.ui.datepicker
*= require jquery-ui-timepicker-addon
*= require shared/textAngular
*= require shared/ng-tags-input.min
*= require select2
*= require_self
*/
//************************************************************************//
//************************************************************************//
@import 'globals/functions';
@import 'globals/variables';
@import 'variables';
@import 'globals/mixins';
@import 'shared/typography';
@import 'shared/tables';
@import 'shared/icons';
@import 'shared/forms';
@import 'shared/layout';
@import 'plugins/powertip';
@import 'plugins/jstree';
@import 'plugins/font-awesome';
@import 'plugins/select2';
@import 'sections/image_settings';
@import 'sections/orders';
@import 'sections/products';
@import 'hacks/mozilla';
@import 'hacks/opera';
@import 'hacks/ie';
@import 'variables';
@import 'components/*';
@import 'plugins/font-awesome';
@import 'pages/*';
@import '*';

View File

@@ -0,0 +1,33 @@
@import 'admin/globals/variables';
table tbody tr {
&.highlight {
@each $action in $actions {
&.action-#{$action} td {
background-color: get-value($actions, $actions-bg-colors, $action);
border-color: get-value($actions, $actions-brd-colors, $action);
}
}
&.action-remove td, &.action-void td {
text-decoration: line-through;
&.actions {
text-decoration: none;
}
}
}
&.before-highlight {
@each $action in $actions {
&.action-#{$action} td {
border-bottom-color: get-value($actions, $actions-brd-colors, $action);
}
}
}
td.actions {
background-color: transparent !important;
}
}

View File

@@ -1,12 +0,0 @@
#admin-menu {
li {
a {
font-weight: 600;
}
a::before {
font-weight: normal;
padding-top: 0;
}
}
}

View File

@@ -0,0 +1,158 @@
@import 'admin/globals/variables';
@import 'admin/globals/mixins';
@import 'admin/plugins/font-awesome';
.date-range-filter {
.range-divider {
padding: 0;
}
input.datepicker {
width: 96px !important;
}
}
#ui-datepicker-div {
@include border-radius($border-radius);
border-color: $color-3;
padding: 0;
margin-top: 10px;
&:before {
content: '';
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 10px solid $color-3;
top: 0px;
margin-top: -10px;
left: 25px;
z-index: 1;
}
.ui-datepicker-header {
padding: 0;
background-image: none;
background-color: $color-3;
border: none;
border-bottom: none;
border-radius: 0;
height: 32px;
.ui-datepicker-prev, .ui-datepicker-next {
border-radius: 0;
top: 0;
height: 32px;
&:hover {
border: none;
background-image: none;
background-color: $color-3;
cursor: pointer;
}
.ui-icon {
background-image: none;
text-indent: 0;
color: $color-1;
width: 10px;
margin-left: -5px;
@extend [class^="icon-"]:before;
&:hover {
color: very-light($color-2, 25);
}
}
}
.ui-datepicker-prev {
left: 0;
.ui-icon {
@extend .icon-arrow-left;
}
}
.ui-datepicker-next {
right: 0;
.ui-icon {
@extend .icon-arrow-right;
}
&:hover {
.ui-icon {
margin-left: -5px;
}
}
}
.ui-datepicker-title {
color: $color-1;
text-transform: uppercase;
font-size: 85% !important;
padding: 6px 10px;
}
}
table.ui-datepicker-calendar {
border: none;
thead {
th {
border-bottom: 1px solid $color-border;
border-right: 1px solid $color-border;
color: $color-body-text;
width: 33px;
&:last-child {
border-right: none;
}
}
}
tbody {
tr:hover {
td {
background-color: transparent !important;
}
}
&:last-child tr:last-child td {
border-bottom: none;
}
td {
a {
border: 1px solid transparent;
background-color: $color-1;
background-image: none;
font-size: 85%;
color: $color-body-text;
&.ui-state-active {
background-color: $color-2;
color: $color-1;
}
&:hover {
background-color: $color-2;
color: $color-1;
border-color: darken($color-2, 5);
}
}
&.ui-state-disabled {
.ui-state-default {
border: none;
background-image: none;
background-color: transparent;
}
}
&.ui-datepicker-today {
a {
background-color: $color-6;
color: $color-1;
border: 1px solid darken($color-6, 5);
}
}
}
}
}
}

View File

@@ -0,0 +1,45 @@
@import 'admin/globals/variables';
.errorExplanation {
padding: 5px;
border: 1px solid very-light($color-error, 12);
background-color: very-light($color-error, 6);
border-radius: 3px;
color: very-light($color-error, 30);
margin-bottom: 15px;
h2 {
font-size: 140%;
color: very-light($color-error, 30);
margin-bottom: 5px;
}
p {
padding: 10px 0;
}
ul {
list-style-position: inside;
li {
font-weight: $font-weight-bold;
}
}
}
.flash {
position: fixed;
top: 0;
left: 0;
width: 100%;
padding: 16px;
text-align: center;
z-index: 1000;
font-size: 120%;
color: $color-1;
font-weight: 600;
&.notice { background-color: rgba($color-notice, 0.8) }
&.success { background-color: rgba($color-success, 0.8) }
&.error { background-color: rgba($color-error, 0.8) }
}

View File

@@ -0,0 +1,162 @@
@import 'admin/globals/variables';
// Navigation
//---------------------------------------------------
.inline-menu {
margin: 0;
-webkit-margin-before: 0;
-webkit-padding-start: 0;
}
nav.menu {
ul {
list-style: none;
li {
a {
padding: 10px 0;
display: block;
position: relative;
text-align: left;
border: 1px solid transparent;
text-transform: uppercase;
font-weight: 600;
font-size: 90%;
}
&.active a {
color: $color-2;
border-left-width: 0;
border-bottom-color: $color-2;
}
&:hover a {
color: $color-2;
}
}
}
}
[data-hook="admin_login_navigation_bar"] {
ul {
text-align: right;
li {
padding: 5px 0 5px 10px;
text-align: right;
font-size: 90%;
color: $color-link;
margin-top: 8px;
&[data-hook="user-logged-in-as"] {
width: 50%;
color: $color-body-text;
}
&:hover {
i {
color: $color-2;
}
}
}
}
}
#admin-menu {
background-color: $color-3;
li {
min-width: 90px;
a {
display: block;
padding: 25px 20px;
color: $color-1 !important;
text-transform: uppercase;
position: relative;
text-align: center;
font-weight: 600;
i {
display: inline;
}
&:hover {
background-color: $color-2;
&:after {
content: '';
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 5px solid $color-2;
bottom: 0px;
margin-bottom: -5px;
left: 50%;
margin-left: -10px;
z-index: 1;
}
}
span.text {
font-weight: 600;
}
}
a::before {
font-weight: normal;
padding-top: 0;
}
.dropdown {
width: 300px;
background-color: $color-3;
width: 200px;
z-index: 100000;
> li {
width: 200px !important;
a:after {
display: none;
}
}
}
&.selected a {
@extend a:hover;
}
}
}
#sub-menu {
background-color: $color-2;
padding-bottom: 0;
li {
a {
display: block;
padding: 12px 20px;
color: $color-1;
text-align: center;
text-transform: uppercase;
position: relative;
font-size: 85%;
}
&.selected a, a:hover {
&:after {
content: '';
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 5px solid $color-2;
bottom: 0px;
margin-bottom: -5px;
left: 50%;
margin-left: -10px;
z-index: 1;
}
}
}
}

View File

@@ -1,8 +1,23 @@
@import 'admin/globals/variables';
@import "admin/variables";
.pagination {
text-align: center;
margin: 2em 0 1em;
padding: 10px 0;
.page {
padding: 5px 8px;
text-align: center;
display: inline-block;
text-align: center;
&.current {
background-color: $color-2;
border-radius: 3px;
color: $color-1;
}
}
button {
margin: 0 0.35em;

View File

@@ -0,0 +1,29 @@
.select2-result-label {
.variant-autocomplete-item {
.variant-details {
padding: 0 10px;
float: left;
}
.variant-image {
margin-top: 5px;
background-color: white;
float: left;
margin-right: 10px;
}
ul.variant-details {
li {
display: inline-block;
&:after {
content: ' / ';
}
&:last-child:after {
content: '';
}
}
}
}
}

View File

@@ -0,0 +1,38 @@
@import 'admin/globals/variables';
@import 'admin/globals/mixins';
#progress {
display: none;
position: fixed;
top: 0;
z-index: 1000;
opacity: 0.8;
width: 100%;
.wrapper {
@include border-radius(10px);
top: -10px;
position: absolute;
left: 50%;
width: 200px;
margin-left: -100px;
padding: 11px 0;
background-color: $color-3;
color: $color-1;
text-align: center;
}
#spinner {
position: absolute;
top: 10px;
left: 50%;
margin-left: -5px;
}
.progress-message {
font-size: 120%;
font-weight: $font-weight-bold;
margin-top: 20px;
text-transform: uppercase;
}
}

View File

@@ -0,0 +1,28 @@
@import 'admin/globals/variables';
// Sidebar
//---------------------------------------------------
#sidebar {
overflow: visible;
border-top: 1px solid $color-border;
margin-top: 17px;
.sidebar-title {
color: $color-2;
text-transform: uppercase;
text-align: center;
font-size: 14px;
font-weight: 600;
> span {
display: inline;
background: #fff;
padding: 5px 10px;
position: relative;
top: -14px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
}
}

View File

@@ -0,0 +1,36 @@
@import 'admin/globals/variables';
.state {
text-transform: uppercase;
font-size: 80%;
font-weight: 600;
&:before {
content: '';
position: relative;
display: inline-block;
margin-right: 3px;
border-radius: $body-font-size/2;
width: $body-font-size - 4px;
height: $body-font-size - 4px;
}
@each $state in $states {
&.#{$state}:before {
background-color: get-value($states, $states-bg-colors, $state);
// &, a {
// color: get-value($states, $states-text-colors, $state);
// }
}
}
}
table tbody tr {
&[class*="state"] td:first-child {
border-left-width: 3px;
}
&.state-complete td:first-child { border-left-color: $color-success }
&.state-cart td:first-child { border-left-color: very-light($color-notice, 6) }
&.state-canceled td:first-child { border-left-color: $color-error }
}

View File

@@ -0,0 +1,14 @@
#table-filter {
.field {
input[type="text"], input[type="phone"],
input[type="email"], input[type="number"],
input[type="url"] {
width: 100%;
}
}
.actions {
text-align: center;
}
}

View File

@@ -0,0 +1,25 @@
// Make color very close to white
@function very-light($color, $adjust: 3){
@if type-of($adjust) == 'number' and $adjust > 0 {
@for $i from 0 through 100 {
@if lighten($color, $i) == white and ($i - $adjust) > $adjust {
@return lighten($color, $i - $adjust);
}
}
}
@else {
@debug "Please correct $adjust value. It should be number and larger then 0. Currently it is '#{type-of($adjust)}' with value '#{$adjust}'"
}
};
// Quick fix for dynamic variables missing in SASS
@function get-value($prop, $val, $search) {
$n1: index($prop, $search);
$n2: index($val, $search);
@if($n1) {
@return nth($val, $n1);
} @else {
@return nth($prop, $n2);
}
}

View File

@@ -0,0 +1,135 @@
@import 'admin/globals/variables';
@import 'admin/globals/mixins';
@import 'admin/plugins/font-awesome';
#taxonomy_tree {
> ul, .jstree-icon {
background-image: none;
}
.jstree-icon {
@extend [class^="icon-"]:before;
}
.jstree-open > .jstree-icon {
@extend .icon-caret-down;
}
.jstree-closed > .jstree-icon {
@extend .icon-caret-right;
}
li {
background-image: none;
a {
background-color: very-light($color-3);
border: 1px solid $color-border;
color: $color-body-text;
font-weight: $font-weight-bold;
text-shadow: none;
width: 90%;
height: auto;
line-height: inherit;
padding: 5px 0 5px 10px;
margin-bottom: 10px;
.jstree-icon {
padding-left: 0px;
@extend .icon-move;
}
}
}
}
#vakata-dragged.jstree-apple .jstree-invalid,
#vakata-dragged.jstree-apple .jstree-ok,
#jstree-marker {
background-image: none !important;
background-color: transparent !important;
@extend [class^="icon-"]:before;
}
#vakata-dragged.jstree-apple .jstree-invalid {
@extend .icon-remove;
color: $color-5;
}
#vakata-dragged.jstree-apple .jstree-ok {
@extend .icon-ok;
color: $color-2;
}
#jstree-marker {
@extend .icon-caret-right;
color: $color-body-text !important;
width: 4px !important;
}
#jstree-marker-line {
@include border-radius($border-radius !important);
height: 0px !important;
margin-left: 5px !important;
margin-top: -2px !important;
border: none !important;
border-bottom: 1px solid $color-body-text !important;
background-color: very-light($color-3) !important;
-webkit-box-shadow: none !important;
-moz-box-shadow: none !important;
box-shadow: none !important;
}
#vakata-contextmenu {
background-color: $color-3 !important;
-moz-box-shadow: none !important;
-webkit-box-shadow: none !important;
box-shadow: none !important;
border: none !important;
@include border-radius($border-radius !important);
&:before {
content: '';
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 10px solid $color-3;
top: 0px;
margin-top: -10px;
left: 25px;
z-index: 1;
}
a {
color: $color-1 !important;
line-height: inherit !important;
padding: 5px 10px !important;
margin: 0 !important;
font-size: 90% !important;
&:hover {
@include border-radius($border-radius !important);
background-color: $color-2 !important;
border: none !important;
-moz-box-shadow: none !important;
-webkit-box-shadow: none !important;
line-height: inherit !important;
padding: 5px 10px !important;
margin: 0 !important;
}
}
li:first-child a:hover:before {
content: '';
position: absolute;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 10px solid $color-2;
top: 0px;
margin-top: -10px;
left: 25px;
z-index: 1;
}
li.vakata-separator {
display: none;
}
}

View File

@@ -0,0 +1,193 @@
@import 'admin/globals/functions';
@import 'admin/globals/variables';
@import 'admin/globals/mixins';
@import 'admin/shared/forms';
@import 'admin/plugins/font-awesome';
.select2-container {
&:hover .select2-choice, &.select2-container-active .select2-choice {
background-color: $color-sel-hover-bg !important;
border-color: $color-sel-hover-bg !important;
}
.select2-choice {
background-image: none !important;
background-color: $color-sel-bg;
border: none !important;
box-shadow: none !important;
@include border-radius($border-radius);
color: $color-1 !important;
font-size: 90%;
height: 31px;
line-height: inherit !important;
padding: 5px 15px 7px;
span {
display: block;
padding: 2px;
}
.select2-search-choice-close {
background-image: none !important;
font-size: 100% !important;
@extend .icon-remove;
@extend [class^="icon-"]:before;
margin-top: 2px;
}
}
&.select2-container-active {
.select2-choice {
box-shadow: none !important;
}
&.select2-dropdown-open .select2-choice div b {
@extend .icon-caret-up
}
}
}
.select2-drop {
border-color: $color-sel-hover-bg;
box-shadow: none !important;
z-index: 1000000;
&.select2-drop-above {
border-color: $color-sel-hover-bg;
}
}
.select2-search {
@extend .icon-search;
font-size: 100%;
color: darken($color-border, 15);
padding: 0 9px 0 0;
&:before {
@extend [class^="icon-"]:before;
position: absolute;
top: 13px;
left: 13px;
}
input {
@extend input[type="text"];
padding: 6px 0 6px 25px;
margin: 5px 0 0 5px;
font-family: $base-font-family;
font-size: 90%;
box-shadow: none;
background-image: none;
}
}
.select2-container .select2-choice .select2-arrow {
background-image: none;
background: transparent;
border: 0;
b {
padding-top: 7px;
display: block;
width: 100%;
height: 100%;
background: none;
font-family: FontAwesome;
font-weight: 200 !important;
&:before {
content: "\f0d7";
}
}
}
.select2-results {
padding-left: 0 !important;
li {
font-size: 85% !important;
&.select2-highlighted {
.select2-result-label {
&, h6 {
color: $color-1 !important;
}
}
}
.select2-result-label {
color: $color-body-text;
min-height: 22px;
clear: both;
overflow: auto;
}
&.select2-no-results, &.select2-searching {
padding: 5px;
background-color: transparent;
color: $color-body-text;
text-align: center;
font-weight: $font-weight-bold;
text-transform: uppercase;
}
}
.select2-highlighted {
background-color: $color-sel-bg;
}
}
.select2-container-multi {
&.select2-container-active, &.select2-dropdown-open {
.select2-choices {
border-color: $color-sel-hover-bg !important;
box-shadow: none;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
}
.select2-choices {
@extend input[type="text"];
padding: 6px 3px 3px 3px;
box-shadow: none;
background-image: none !important;
.select2-search-choice {
@include border-radius($border-radius);
margin: 0 0 3px 3px;
background-image: none;
background-color: $color-sel-bg;
border: none;
box-shadow: none;
color: $color-1 !important;
font-size: 85%;
&:hover {
background-color: $color-sel-hover-bg;
}
.select2-search-choice-close {
background-image: none !important;
font-size: 85% !important;
@extend .icon-remove;
@extend [class^="icon-"]:before;
margin-left: 2px;
color: $color-1;
}
}
}
}
label .select2-container {
margin-top: -6px;
.select2-choice {
span {
text-transform: none;
font-weight: normal;
}
}
}

View File

@@ -0,0 +1,3 @@
.destroy_style, .destroy_header {
float: right;
}

View File

@@ -0,0 +1,270 @@
@import 'admin/globals/variables';
@import 'admin/globals/mixins';
input[type="text"],
input[type="password"],
input[type="email"],
input[type="date"],
input[type="datetime"],
input[type="time"],
input[type="url"],
input[type="number"],
input[type="tel"],
textarea, fieldset {
@include border-radius($border-radius);
padding: 7px 10px;
border: 1px solid $color-txt-brd;
color: $color-txt-text;
font-size: 90%;
&:focus {
outline: none;
border-color: $color-txt-hover-brd;
}
&[disabled] {
opacity: 0.7;
}
}
textarea {
line-height: 19px;
}
.fullwidth {
width: 100%;
}
label {
font-weight: 600;
text-transform: uppercase;
font-size: 85%;
display: inline;
margin-bottom: 5px;
color: $color-4;
&.inline {
display: inline-block !important;
}
&.block {
display: block !important;
}
}
.label-block label { display: block }
input[type="submit"],
input[type="button"],
button, .button {
@include border-radius($border-radius);
display: inline-block;
padding: 8px 15px;
border: none;
background-color: $color-btn-bg;
color: $color-btn-text;
text-transform: uppercase;
font-weight: 600 !important;
&:before {
font-weight: normal !important;
}
&:visited, &:active, &:focus { color: $color-btn-text }
&:hover {
background-color: $color-btn-hover-bg;
color: $color-btn-hover-text;
}
&:active:focus {
box-shadow: 0 0 8px 0 darken($color-btn-hover-bg, 5) inset;
}
&.fullwidth {
width: 100%;
text-align: center;
}
}
span.info {
font-style: italic;
font-size: 85%;
color: lighten($color-body-text, 15);
display: block;
line-height: 20px;
margin: 5px 0;
}
.field {
padding: 10px 0;
&.checkbox {
min-height: 73px;
input[type="checkbox"] {
display: inline-block;
width: auto;
}
label {
cursor: pointer;
display: block;
}
}
ul {
border-top: 1px solid $color-border;
list-style: none;
padding-top: 5px;
li {
display: inline-block;
padding-right: 10px;
label {
font-weight: normal;
text-transform: none;
}
&.white-space-nowrap {
white-space: nowrap;
}
}
}
&.withError {
.field_with_errors {
label {
color: very-light($color-error, 30);
}
input {
border-color: very-light($color-error, 15);
}
}
.formError {
color: very-light($color-error, 30);
font-style: italic;
font-size: 85%;
}
}
}
fieldset {
box-shadow: none;
box-sizing: border-box;
border-color: $color-border;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
margin-left: 0;
margin-right: 0;
position: relative;
margin-bottom: 35px;
padding: 10px 0 15px 0;
background-color: transparent;
border-left: none;
border-right: none;
border-radius: 0;
&.no-border-bottom {
border-bottom: none;
margin-bottom: 0;
}
&.no-border-top {
border-top: none;
padding-top: 0;
}
legend {
background-color: $color-1;
color: $color-2;
font-size: 14px;
font-weight: 600;
text-transform: uppercase;
text-align: center;
padding: 8px 15px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
i {
color: $color-link;
}
}
label {
color: lighten($color-body-text, 8);
}
.filter-actions {
margin-bottom: -32px;
margin-top: 15px;
text-align: center;
form {
display: inline-block;
}
button, .button, input[type="submit"], input[type="button"], span.or {
@include border-radius($border-radius);
-webkit-box-shadow: 0 0 0 15px $color-1;
-moz-box-shadow: 0 0 0 15px $color-1;
-ms-box-shadow: 0 0 0 15px $color-1;
-o-box-shadow: 0 0 0 15px $color-1;
box-shadow: 0 0 0 15px $color-1;
&:hover {
border-color: $color-1;
}
}
span.or {
background-color: $color-1;
border-width: 5px;
margin-left: 5px;
margin-right: 5px;
position: relative;
-webkit-box-shadow: 0 0 0 5px $color-1;
-moz-box-shadow: 0 0 0 5px $color-1;
-ms-box-shadow: 0 0 0 5px $color-1;
-o-box-shadow: 0 0 0 5px $color-1;
box-shadow: 0 0 0 5px $color-1;
}
}
&.labels-inline {
.field {
margin-bottom: 0;
display: table;
width: 100%;
label, input {
display: table-cell !important;
}
input {
width: 100%;
}
&.checkbox {
input {
width: auto !important
}
}
}
.actions {
padding: 0;
text-align: right;
}
}
}
.form-actions {
margin-top: 18px;
}
.form-buttons {
text-align: center;
}

View File

@@ -0,0 +1,25 @@
@import 'admin/plugins/font-awesome';
// Some fixes for fontwesome stylesheets
[class^="icon-"], [class*=" icon-"] {
&:before {
padding-right: 5px;
}
&.button, &.icon_link {
width: auto;
&:before {
padding-top: 3px;
}
}
}
.icon-email:before { @extend .icon-envelope:before }
.icon-resume:before { @extend .icon-refresh:before }
.icon-cancel:before,
.icon-void:before { @extend .icon-remove:before }
.icon-capture:before { @extend .icon-ok:before }
.icon-credit:before { @extend .icon-ok:before }

View File

@@ -0,0 +1,92 @@
@import 'admin/globals/variables';
// Basics
//---------------------------------------------------
* {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
// Helpers
.block-table {
display: table;
width: 100%;
.table-cell {
display: table-cell;
vertical-align: middle;
padding: 0 10px;
&:first-child {
padding-left: 0;
}
&:last-child {
padding-right: 0;
}
}
}
.hidden {
display: none;
}
// For block grids
.frameless {
margin-left: -10px;
margin-right: -10px;
}
// Header
//---------------------------------------------------
#header {
background-color: $color-1;
padding: 5px 0;
}
#logo { height: 40px }
[data-hook="admin-title"] { font-size: 14px }
.page-title {
i {
color: $color-2;
}
}
// Content
//---------------------------------------------------
#content {
background-color: $color-1;
position: relative;
z-index: 0;
padding: 0;
margin-top: 15px;
}
#content-header {
padding: 15px 0;
background-color: very-light($color-3, 4);
border-bottom: 1px solid $color-border;
.page-title {
font-size: 20px;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.page-actions {
text-align: right;
form {
display: inline-block;
}
}
}
// Footer
//---------------------------------------------------
#footer {
margin-top: 15px;
border-top: 1px solid $color-border;
padding: 10px 0;
}

View File

@@ -0,0 +1,208 @@
@import 'admin/globals/variables';
@import 'admin/plugins/font-awesome';
table {
width: 100%;
margin-bottom: 15px;
border-collapse: separate;
th, td {
padding: 7px 5px;
border-right: 1px solid $color-border;
border-bottom: 1px solid $color-border;
vertical-align: middle;
text-overflow: ellipsis;
img {
border: 1px solid transparent;
}
&:first-child {
border-left: 1px solid $color-border;
}
a {
border-bottom: 1px dotted lighten($color-link, 10);
&:hover {
border-color: lighten($color-link-hover, 10);
}
}
.handle {
display: block !important;
text-align: center;
padding-right: 0;
}
&.actions {
background-color: transparent;
border: none !important;
text-align: center;
span.text {
font-size: $body-font-size;
}
[class*='icon-'].no-text {
font-size: 120%;
background-color: very-light($color-3);
border: 1px solid $color-border;
border-radius: 15px;
width: 29px;
height: 29px;
display: inline-block;
padding-top: 2px;
&:before {
text-align: center !important;
width: 27px;
display: inline-block;
}
&:hover {
border-color: transparent;
}
}
button[class*='icon-'] {
color: $color-link;
padding: 0 !important;
}
.icon-envelope-alt, .icon-eye-open {
color: $color-link;
padding-left: 0px;
&:hover {
background-color: $color-3;
color: $color-1;
}
}
.icon-trash:hover, .icon-void:hover {
background-color: $color-error;
color: $color-1;
}
.icon-cancel:hover {
background-color: $color-notice;
color: $color-1;
}
.icon-edit:hover, .icon-capture:hover, .icon-ok:hover, .icon-plus:hover {
background-color: $color-success;
color: $color-1;
}
.icon-copy:hover {
background-color: $color-notice;
color: $color-1;
}
}
input[type="number"],
input[type="text"] {
width: 100%;
}
&.no-border {
border-right: none;
}
.handle {
@extend [class^="icon-"]:before;
@extend .icon-reorder;
cursor: move;
}
}
&.no-borders {
td, th {
border: none !important;
}
}
thead {
th {
padding: 10px;
border-top: 1px solid $color-border;
border-bottom: none;
background-color: $color-tbl-thead;
text-transform: uppercase;
font-size: 85%;
font-weight: $font-weight-bold;
}
}
tbody {
tr {
&:first-child th,
&:first-child td {
border-top: 1px solid $color-border;
}
&.even td {
background-color: $color-tbl-even;
img {
border: 1px solid very-light($color-3, 6);
}
}
&:hover td {
background-color: very-light($color-3, 5);
img {
border: 1px solid $color-border;
}
}
&.deleted td {
background-color: very-light($color-error, 6);
border-color: very-light($color-error, 15);
}
&.ui-sortable-placeholder td {
border: 1px solid $color-2 !important;
visibility: visible !important;
&.actions {
background-color: transparent;
border-right: none !important;
border-top: none !important;
border-bottom: none !important;
border-left: 1px solid $color-2 !important;
}
}
&.ui-sortable-helper {
width: 100%;
td {
background-color: lighten($color-3, 33);
border-bottom: 1px solid $color-border;
&.actions {
display: none;
}
}
}
}
&.no-border-top tr:first-child td {
border-top: none;
}
&.grand-total {
td {
border-color: $color-2 !important;
text-transform: uppercase;
font-size: 110%;
font-weight: 600;
background-color: lighten($color-2, 50);
}
.total {
background-color: $color-2;
color: $color-1;
}
}
}
}

View File

@@ -0,0 +1,134 @@
@import 'admin/globals/variables';
// Base
//--------------------------------------------------------------
body, div, dl, dt, dd, ul, ol, li, h1, h2, h3, h4, h5, h6, pre, form, p, blockquote, th, td { margin: 0; padding: 0; font-size: 13px; }
body {
font-family: $base-font-family;
font-size: $body-font-size;
font-weight: 400;
color: $color-body-text;
text-rendering: optimizeLegibility;
}
hr {
border-top: 1px solid $color-border;
border-bottom: 1px solid white;
border-left: none;
}
strong, b {
font-weight: 600;
}
// links
//--------------------------------------------------------------
a {
color: $color-link;
text-decoration: none;
line-height: inherit;
&, &:hover, &:active, &:visited, &:focus {
outline: none;
}
&:visited {
color: $color-link-visited;
}
&:focus {
color: $color-link-focus;
}
&:active {
color: $color-link-active;
}
&:hover {
color: $color-link-hover;
}
}
// Headings
//--------------------------------------------------------------
h1,h2,h3,h4,h5,h6 {
font-weight: 600;
color: $color-headers;
line-height: 1.1;
}
h1 { font-size: $h1-size; line-height: $h1-size + 6 }
h2 { font-size: $h2-size; line-height: $h1-size + 4 }
h3 { font-size: $h3-size; line-height: $h1-size + 2 }
h4 { font-size: $h4-size; line-height: $h1-size }
h5 { font-size: $h5-size; line-height: $h1-size }
h6 { font-size: $h6-size; line-height: $h1-size }
// Lists
//--------------------------------------------------------------
ul {
&.inline-menu {
li {
display: inline-block;
}
}
&.fields {
list-style: none;
padding: 0;
margin: 0;
}
}
dl {
width: 100%;
overflow: hidden;
margin: 5px 0;
color: lighten($color-body-text, 15);
dt, dd {
float: left;
line-height: 16px;
padding: 5px;
text-align: justify;
}
dt {
width: 40%;
font-weight: 600;
padding-left: 0;
text-transform: uppercase;
font-size: 85%;
}
dd {
width: 60%;
padding-right: 0;
}
dd:after {
content: '';
clear: both;
}
}
// Helpers
.align-center { text-align: center }
.align-right { text-align: right }
.align-left { text-align: left }
.align-justify { text-align: justify }
.uppercase { text-transform: uppercase }
.green { color: $color-2 }
.blue { color: $color-3 }
.red { color: $color-5 }
.yellow { color: $color-6 }
.no-objects-found {
text-align: center;
font-size: 120%;
text-transform: uppercase;
padding: 40px 0px;
color: lighten($color-body-text, 15);
}

View File

@@ -1,5 +1,6 @@
require 'open_food_network/referer_parser'
require 'open_food_network/permissions'
require 'open_food_network/order_cycle_permissions'
module Admin
class EnterprisesController < ResourceController
@@ -22,7 +23,6 @@ module Admin
before_filter :setup_property, only: [:edit]
helper 'spree/products'
include ActionView::Helpers::TextHelper
include OrderCyclesHelper
def index
@@ -76,19 +76,12 @@ module Admin
def bulk_update
@enterprise_set = EnterpriseSet.new(collection, params[:enterprise_set])
touched_enterprises = @enterprise_set.collection.select(&:changed?)
if @enterprise_set.save
flash[:success] = I18n.t(:enterprise_bulk_update_success_notice)
# 18-3-2015: It seems that the form for this action sometimes loads bogus values for
# the 'sells' field, and submitting that form results in a bunch of enterprises with
# values that have mysteriously changed. This statement is here to help debug that
# issue, and should be removed (along with its display in index.html.haml) when the
# issue has been resolved.
flash[:action] = "#{I18n.t(:updated)} #{pluralize(touched_enterprises.count, 'enterprise')}: #{touched_enterprises.map(&:name).join(', ')}"
redirect_to main_app.admin_enterprises_path
else
touched_enterprises = @enterprise_set.collection.select(&:changed?)
@enterprise_set.collection.select! { |e| touched_enterprises.include? e }
flash[:error] = I18n.t(:enterprise_bulk_update_error)
render :index

View File

@@ -1,7 +1,10 @@
# frozen_string_literal: true
# This controller lists products that can be added to an exchange
#
# Pagination is optional and can be required by using param[:page]
module Api
class ExchangeProductsController < Api::BaseController
DEFAULT_PAGE = 1
DEFAULT_PER_PAGE = 100
skip_authorization_check only: [:index]
@@ -29,22 +32,28 @@ module Api
def render_variant_count
render text: {
count: Spree::Variant.
not_master.
where(product_id: products).
count
count: variants.count
}.to_json
end
def variants
renderer.exchange_variants(@incoming, @enterprise)
end
def products
ExchangeProductsRenderer.
new(@order_cycle, spree_current_user).
exchange_products(@incoming, @enterprise)
renderer.exchange_products(@incoming, @enterprise)
end
def renderer
@renderer ||= ExchangeProductsRenderer.
new(@order_cycle, spree_current_user)
end
def paginated_products
return products unless pagination_required?
products.
page(params[:page] || DEFAULT_PAGE).
page(params[:page]).
per(params[:per_page] || DEFAULT_PER_PAGE)
end
@@ -74,19 +83,23 @@ module Api
order_cycle: @order_cycle
)
render text: {
products: serializer,
pagination: pagination_data(paginated_products)
}.to_json
result = { products: serializer }
result = result.merge(pagination: pagination_data(paginated_products)) if pagination_required?
render text: result.to_json
end
def pagination_data(paginated_products)
{
results: paginated_products.total_count,
pages: paginated_products.num_pages,
page: (params[:page] || DEFAULT_PAGE).to_i,
page: params[:page].to_i,
per_page: (params[:per_page] || DEFAULT_PER_PAGE).to_i
}
end
def pagination_required?
params[:page].present?
end
end
end

View File

@@ -48,16 +48,22 @@ module Api
end
def bulk_products
product_query = OpenFoodNetwork::Permissions.new(current_api_user).
editable_products.merge(product_scope)
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
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)
@products = product_query.
ransack(query_params_with_defaults).
result.
page(params[:page] || DEFAULT_PAGE).
per(params[:per_page] || DEFAULT_PER_PAGE)
render_paged_products @products
end
@@ -136,6 +142,10 @@ module Api
}.to_json
end
def query_params_with_defaults
params[:q].to_h.reverse_merge(s: 'created_at desc')
end
def pagination_data(results)
{
results: results.total_count,

View File

@@ -1,5 +1,5 @@
require 'open_food_network/referer_parser'
require 'spree/authentication_helpers'
require_dependency 'spree/authentication_helpers'
class ApplicationController < ActionController::Base
protect_from_forgery
@@ -23,7 +23,11 @@ class ApplicationController < ActionController::Base
referer_path = OpenFoodNetwork::RefererParser.path(request.referer)
if referer_path
is_checkout_path_the_referer = [main_app.checkout_path].include?(referer_path)
session["spree_user_return_to"] = is_checkout_path_the_referer ? referer_path : root_path
session["spree_user_return_to"] = if is_checkout_path_the_referer
referer_path
else
main_app.root_path
end
end
end
@@ -48,11 +52,11 @@ class ApplicationController < ActionController::Base
def after_sign_in_path_for(resource_or_scope)
return session[:shopfront_redirect] if session[:shopfront_redirect]
stored_location_for(resource_or_scope) || signed_in_root_path(resource_or_scope)
stored_location_for(resource_or_scope) || main_app.root_path
end
def after_sign_out_path_for(_resource_or_scope)
session[:shopfront_redirect] || root_path
session[:shopfront_redirect] || main_app.root_path
end
private
@@ -74,7 +78,7 @@ class ApplicationController < ActionController::Base
def require_distributor_chosen
unless @distributor = current_distributor
redirect_to spree.root_path
redirect_to main_app.root_path
false
end
end
@@ -86,26 +90,29 @@ class ApplicationController < ActionController::Base
end
def check_hub_ready_for_checkout
# This condition is more rigourous than required by development to avoid coupling this
# condition to every controller spec
if current_distributor && current_order &&
current_distributor.respond_to?(:ready_for_checkout?) &&
!current_distributor.ready_for_checkout?
if current_distributor_closed?
current_order.empty!
current_order.set_distribution! nil, nil
flash[:info] = "The hub you have selected is temporarily closed for orders. Please try again later."
redirect_to root_url
flash[:info] = "The hub you have selected is temporarily closed for orders. "\
"Please try again later."
redirect_to main_app.root_url
end
end
def current_distributor_closed?
current_distributor &&
current_order &&
current_distributor.respond_to?(:ready_for_checkout?) &&
!current_distributor.ready_for_checkout?
end
def check_order_cycle_expiry
if current_order_cycle.andand.closed?
session[:expired_order_cycle_id] = current_order_cycle.id
current_order.empty!
current_order.set_order_cycle! nil
flash[:info] = "The order cycle you've selected has just closed. Please try again!"
redirect_to root_url
redirect_to main_app.root_url
end
end

View File

@@ -1,8 +1,16 @@
# frozen_string_literal: true
require 'open_food_network/address_finder'
class CheckoutController < Spree::CheckoutController
class CheckoutController < Spree::StoreController
layout 'darkswarm'
include CheckoutHelper
include OrderCyclesHelper
include EnterprisesHelper
ssl_required
# We need pessimistic locking to avoid race conditions.
# Otherwise we fail on duplicate indexes or end up with negative stock.
prepend_around_filter CurrentOrderLocker, only: :update
@@ -12,10 +20,19 @@ class CheckoutController < Spree::CheckoutController
prepend_before_filter :require_order_cycle
prepend_before_filter :require_distributor_chosen
before_filter :load_order
before_filter :ensure_order_not_completed
before_filter :ensure_checkout_allowed
before_filter :ensure_sufficient_stock_lines
before_filter :associate_user
before_filter :check_authorization
before_filter :enable_embedded_shopfront
include OrderCyclesHelper
include EnterprisesHelper
helper 'spree/orders'
rescue_from Spree::Core::GatewayError, with: :rescue_from_spree_gateway_error
def edit
# This is only required because of spree_paypal_express. If we implement
@@ -25,54 +42,16 @@ class CheckoutController < Spree::CheckoutController
end
def update
shipping_method_id = object_params.delete(:shipping_method_id)
params_adapter = Checkout::FormDataAdapter.new(params, @order, spree_current_user)
return update_failed unless @order.update_attributes(params_adapter.order_params)
return update_failed unless @order.update_attributes(object_params)
check_order_for_phantom_fees
fire_event('spree.checkout.update')
while @order.state != "complete"
if @order.state == "payment"
return if redirect_to_paypal_express_form_if_needed
end
if @order.state == "delivery"
@order.select_shipping_method(shipping_method_id)
end
next if advance_order_state(@order)
flash[:error] = if @order.errors.present?
@order.errors.full_messages.to_sentence
else
t(:payment_processing_failed)
end
update_failed
return
end
return update_failed unless @order.state == "complete" || @order.completed?
set_default_bill_address
set_default_ship_address
ResetOrderService.new(self, current_order).call
session[:access_token] = current_order.token
flash[:notice] = t(:order_processed_successfully)
respond_to do |format|
format.html do
respond_with(@order, location: order_path(@order))
end
format.json do
render json: { path: order_path(@order) }, status: :ok
end
end
rescue Spree::Core::GatewayError => error
# This is done for all actions in the Spree::CheckoutController.
rescue_from_spree_gateway_error(error)
rescue StandardError => error
Bugsnag.notify(error)
checkout_workflow(params_adapter.shipping_method_id)
rescue Spree::Core::GatewayError => e
rescue_from_spree_gateway_error(e)
rescue StandardError => e
Bugsnag.notify(e)
flash[:error] = I18n.t("checkout.failed")
update_failed
end
@@ -87,111 +66,38 @@ class CheckoutController < Spree::CheckoutController
private
def set_default_bill_address
if params[:order][:default_bill_address]
new_bill_address = @order.bill_address.clone.attributes
user_bill_address_id = spree_current_user.bill_address.andand.id
spree_current_user.update_attributes(
bill_address_attributes: new_bill_address.merge('id' => user_bill_address_id)
)
customer_bill_address_id = @order.customer.bill_address.andand.id
@order.customer.update_attributes(
bill_address_attributes: new_bill_address.merge('id' => customer_bill_address_id)
)
end
def check_authorization
authorize!(:edit, current_order, session[:access_token])
end
def set_default_ship_address
if params[:order][:default_ship_address]
new_ship_address = @order.ship_address.clone.attributes
user_ship_address_id = spree_current_user.ship_address.andand.id
spree_current_user.update_attributes(
ship_address_attributes: new_ship_address.merge('id' => user_ship_address_id)
)
customer_ship_address_id = @order.customer.ship_address.andand.id
@order.customer.update_attributes(
ship_address_attributes: new_ship_address.merge('id' => customer_ship_address_id)
)
end
def ensure_checkout_allowed
redirect_to main_app.cart_path unless @order.checkout_allowed?
end
def check_order_for_phantom_fees
phantom_fees = @order.adjustments.
joins("LEFT OUTER JOIN spree_line_items"\
" ON spree_line_items.id = spree_adjustments.source_id").
where("originator_type = 'EnterpriseFee'"\
" AND source_type = 'Spree::LineItem' AND spree_line_items.id IS NULL")
if phantom_fees.any?
Bugsnag.notify(RuntimeError.new("Phantom Fees"),
phantom_fees: {
phantom_total: phantom_fees.sum(&:amount).to_s,
phantom_fees: phantom_fees.as_json
})
end
def ensure_order_not_completed
redirect_to main_app.cart_path if @order.completed?
end
# Copied and modified from spree. Remove check for order state, since the state machine is
# progressed all the way in one go with the one page checkout.
def object_params
# For payment step, filter order parameters to produce the expected
# nested attributes for a single payment and its source,
# discarding attributes for payment methods other than the one selected
if params[:payment_source].present? && source_params = params.delete(:payment_source)[params[:order][:payments_attributes].first[:payment_method_id].underscore]
params[:order][:payments_attributes].first[:source_attributes] = source_params
end
if params[:order][:payments_attributes]
params[:order][:payments_attributes].first[:amount] = @order.total
end
if params[:order][:existing_card_id]
construct_saved_card_attributes
end
params[:order]
end
# Perform order.next, guarding against StaleObjectErrors
def advance_order_state(order)
tries ||= 3
order.next
rescue ActiveRecord::StaleObjectError
retry unless (tries -= 1).zero?
false
end
def update_failed
current_order.updater.shipping_address_from_distributor
RestartCheckout.new(@order).call
respond_to do |format|
format.html do
render :edit
end
format.json do
render json: { errors: @order.errors, flash: flash.to_hash }.to_json, status: :bad_request
end
def ensure_sufficient_stock_lines
if @order.insufficient_stock_lines.present?
flash[:error] = Spree.t(:inventory_error_flash_for_insufficient_quantity)
redirect_to main_app.cart_path
end
end
def load_order
@order = current_order
redirect_to(main_app.shop_path) && return unless @order && @order.checkout_allowed?
redirect_to(main_app.shop_path) && return if redirect_to_shop?
redirect_to_cart_path && return unless valid_order_line_items?
redirect_to(main_app.shop_path) && return if @order.completed?
before_address
setup_for_current_state
end
def before_address
associate_user
finder = OpenFoodNetwork::AddressFinder.new(@order.email, @order.customer, spree_current_user)
@order.bill_address = finder.bill_address
@order.ship_address = finder.ship_address
def redirect_to_shop?
!@order ||
!@order.checkout_allowed? ||
@order.completed?
end
def valid_order_line_items?
@@ -212,32 +118,29 @@ class CheckoutController < Spree::CheckoutController
end
end
def redirect_to_paypal_express_form_if_needed
return unless params[:order][:payments_attributes]
payment_method_id = params[:order][:payments_attributes].first[:payment_method_id]
payment_method = Spree::PaymentMethod.find(payment_method_id)
return unless payment_method.is_a?(Spree::Gateway::PayPalExpress)
render json: { path: spree.paypal_express_path(payment_method_id: payment_method.id) },
status: :ok
true
def setup_for_current_state
method_name = :"before_#{@order.state}"
__send__(method_name) if respond_to?(method_name, true)
end
def construct_saved_card_attributes
existing_card_id = params[:order].delete(:existing_card_id)
return if existing_card_id.blank?
def before_address
associate_user
credit_card = Spree::CreditCard.find(existing_card_id)
if credit_card.try(:user_id).blank? || credit_card.user_id != spree_current_user.try(:id)
raise Spree::Core::GatewayError, I18n.t(:invalid_credit_card)
end
finder = OpenFoodNetwork::AddressFinder.new(@order.email, @order.customer, spree_current_user)
# Not currently supported but maybe we should add it...?
credit_card.verification_value = params[:cvc_confirm] if params[:cvc_confirm].present?
@order.bill_address = finder.bill_address
@order.ship_address = finder.ship_address
end
params[:order][:payments_attributes].first[:source] = credit_card
params[:order][:payments_attributes].first.delete :source_attributes
def before_delivery
return if params[:order].present?
packages = @order.shipments.map(&:to_package)
@differentiator = Spree::Stock::Differentiator.new(@order, packages)
end
def before_payment
current_order.payments.destroy_all if request.put?
end
def rescue_from_spree_gateway_error(error)
@@ -247,4 +150,91 @@ class CheckoutController < Spree::CheckoutController
format.json { render json: { flash: flash.to_hash }, status: :bad_request }
end
end
def checkout_workflow(shipping_method_id)
while @order.state != "complete"
if @order.state == "payment"
return if redirect_to_payment_gateway
end
@order.select_shipping_method(shipping_method_id) if @order.state == "delivery"
next if advance_order_state(@order)
flash[:error] = order_workflow_error
return update_failed
end
update_result
end
def redirect_to_payment_gateway
redirect_path = Checkout::PaymentRedirect.new(params).path
return if redirect_path.blank?
render json: { path: redirect_path }, status: :ok
true
end
# Perform order.next, guarding against StaleObjectErrors
def advance_order_state(order)
tries ||= 3
order.next
rescue ActiveRecord::StaleObjectError
retry unless (tries -= 1).zero?
false
end
def order_workflow_error
if @order.errors.present?
@order.errors.full_messages.to_sentence
else
t(:payment_processing_failed)
end
end
def update_result
if @order.state == "complete" || @order.completed?
save_order_addresses_as_user_default
ResetOrderService.new(self, current_order).call
update_succeeded
else
update_failed
end
end
def save_order_addresses_as_user_default
user_default_address_setter = UserDefaultAddressSetter.new(@order, spree_current_user)
user_default_address_setter.set_default_bill_address if params[:order][:default_bill_address]
user_default_address_setter.set_default_ship_address if params[:order][:default_ship_address]
end
def update_succeeded
session[:access_token] = current_order.token
flash[:notice] = t(:order_processed_successfully)
respond_to do |format|
format.html do
respond_with(@order, location: order_path(@order))
end
format.json do
render json: { path: order_path(@order) }, status: :ok
end
end
end
def update_failed
current_order.updater.shipping_address_from_distributor
RestartCheckout.new(@order).call
respond_to do |format|
format.html do
render :edit
end
format.json do
render json: { errors: @order.errors, flash: flash.to_hash }.to_json, status: :bad_request
end
end
end
end

View File

@@ -63,8 +63,6 @@ class EnterprisesController < BaseController
end
def reset_order
distributor = Enterprise.is_distributor.find_by_permalink(params[:id]) ||
Enterprise.is_distributor.find(params[:id])
order = current_order(true)
reset_distributor(order, distributor)
@@ -74,6 +72,14 @@ class EnterprisesController < BaseController
reset_order_cycle(order, distributor)
order.save!
rescue ActiveRecord::RecordNotFound
flash[:error] = I18n.t(:enterprise_shop_show_error)
redirect_to shops_path
end
def distributor
@distributor ||= Enterprise.is_distributor.find_by_permalink(params[:id]) ||
Enterprise.is_distributor.find(params[:id])
end
def reset_distributor(order, distributor)

View File

@@ -15,11 +15,10 @@ module Spree
# Warn the user when they have an active order cycle with hubs that are not ready
# for checkout (ie. does not have valid shipping and payment methods).
def warn_invalid_order_cycles
distributors = active_distributors_not_ready_for_checkout
return if flash[:notice].present?
return if distributors.empty? || flash[:notice].present?
flash[:notice] = active_distributors_not_ready_for_checkout_message(distributors)
warning = OrderCycleWarning.new(spree_current_user).call
flash[:notice] = warning if warning.present?
end
# This is in Spree::Core::ControllerHelpers::Auth
@@ -30,7 +29,7 @@ module Spree
redirect_to '/unauthorized'
else
store_location
redirect_to root_path(anchor: "login?after_login=#{request.env['PATH_INFO']}")
redirect_to main_app.root_path(anchor: "login?after_login=#{request.env['PATH_INFO']}")
end
end
@@ -71,10 +70,6 @@ module Spree
Spree.t(event_sym, resource: resource_desc)
end
def render_js_for_destroy
render partial: '/spree/admin/shared/destroy'
end
# Index request for JSON needs to pass a CSRF token in order to prevent JSON Hijacking
def check_json_authenticity
return unless request.format.js? || request.format.json?
@@ -87,30 +82,8 @@ module Spree
raise(ActionController::InvalidAuthenticityToken)
end
def config_locale
Spree::Backend::Config[:locale]
end
private
def active_distributors_not_ready_for_checkout
ocs = OrderCycle.managed_by(spree_current_user).active
distributors = ocs.includes(:distributors).map(&:distributors).flatten.uniq
Enterprise.where('enterprises.id IN (?)', distributors).not_ready_for_checkout
end
def active_distributors_not_ready_for_checkout_message(distributors)
distributor_names = distributors.map(&:name).join ', '
if distributors.count > 1
I18n.t(:active_distributors_not_ready_for_checkout_message_plural,
distributor_names: distributor_names)
else
I18n.t(:active_distributors_not_ready_for_checkout_message_singular,
distributor_names: distributor_names)
end
end
def html_request?
request.format.html?
end
@@ -121,13 +94,17 @@ module Spree
def render_as_json(data, options = {})
ams_prefix = options.delete :ams_prefix
if [Array, ActiveRecord::Relation].include? data.class
if each_serializer_required?(data)
render options.merge(json: data, each_serializer: serializer(ams_prefix))
else
render options.merge(json: data, serializer: serializer(ams_prefix))
end
end
def each_serializer_required?(data)
['Array', 'ActiveRecord::Relation'].include?(data.class.name)
end
def serializer(ams_prefix)
unless ams_prefix.nil? || ams_prefix_whitelist.include?(ams_prefix.to_sym)
raise "Suffix '#{ams_prefix}' not found in ams_prefix_whitelist for #{self.class.name}."

View File

@@ -0,0 +1,71 @@
module Spree
module Admin
module Orders
class CustomerDetailsController < Spree::Admin::BaseController
before_filter :load_order
before_filter :check_authorization
before_filter :set_guest_checkout_status, only: :update
def show
edit
render action: :edit
end
def edit
country_id = Address.default.country.id
@order.build_bill_address(country_id: country_id) if @order.bill_address.nil?
@order.build_ship_address(country_id: country_id) if @order.ship_address.nil?
end
def update
if @order.update_attributes(params[:order])
if params[:guest_checkout] == "false"
@order.associate_user!(Spree.user_class.find_by_email(@order.email))
end
AdvanceOrderService.new(@order).call
@order.shipments.map(&:refresh_rates)
flash[:success] = Spree.t('customer_details_updated')
redirect_to admin_order_customer_path(@order)
else
render action: :edit
end
end
# Inherit CanCan permissions for the current order
def model_class
load_order unless @order
@order
end
private
def load_order
@order = Order.find_by_number!(params[:order_id], include: :adjustments)
end
def check_authorization
load_order
session[:access_token] ||= params[:token]
resource = @order
action = params[:action].to_sym
action = :edit if action == :show # show route renders :edit for this controller
authorize! action, resource, session[:access_token]
end
def set_guest_checkout_status
registered_user = Spree::User.find_by_email(params[:order][:email])
params[:order][:guest_checkout] = registered_user.nil?
return unless registered_user
@order.user_id = registered_user.id
end
end
end
end
end

View File

@@ -1,49 +0,0 @@
Spree::Admin::Orders::CustomerDetailsController.class_eval do
before_filter :check_authorization
before_filter :set_guest_checkout_status, only: :update
def update
if @order.update_attributes(params[:order])
if params[:guest_checkout] == "false"
@order.associate_user!(Spree.user_class.find_by_email(@order.email))
end
AdvanceOrderService.new(@order).call
@order.shipments.map &:refresh_rates
flash[:success] = Spree.t('customer_details_updated')
redirect_to admin_order_customer_path(@order)
else
render action: :edit
end
end
# Inherit CanCan permissions for the current order
def model_class
load_order unless @order
@order
end
private
def check_authorization
load_order
session[:access_token] ||= params[:token]
resource = @order
action = params[:action].to_sym
action = :edit if action == :show # show route renders :edit for this controller
authorize! action, resource, session[:access_token]
end
def set_guest_checkout_status
registered_user = Spree::User.find_by_email(params[:order][:email])
params[:order][:guest_checkout] = registered_user.nil?
return unless registered_user
@order.user_id = registered_user.id
end
end

View File

@@ -0,0 +1,150 @@
require 'open_food_network/spree_api_key_loader'
module Spree
module Admin
class OrdersController < Spree::Admin::BaseController
require 'spree/core/gateway_error'
include OpenFoodNetwork::SpreeApiKeyLoader
helper CheckoutHelper
before_filter :load_order, only: [:edit, :update, :fire, :resend,
:invoice, :print, :print_ticket]
before_filter :load_distribution_choices, only: [:new, :edit, :update]
# Ensure that the distributor is set for an order when
before_filter :ensure_distribution, only: :new
# After updating an order, the fees should be updated as well
# Currently, adding or deleting line items does not trigger updating the
# fees! This is a quick fix for that.
# TODO: update fees when adding/removing line items
# instead of the update_distribution_charge method.
after_filter :update_distribution_charge, only: :update
before_filter :require_distributor_abn, only: :invoice
respond_to :html, :json
def new
@order = Order.create
@order.created_by = try_spree_current_user
@order.save
redirect_to edit_admin_order_url(@order)
end
def edit
@order.shipments.map(&:refresh_rates)
AdvanceOrderService.new(@order).call
# The payment step shows an error of 'No pending payments'
# Clearing the errors from the order object will stop this error
# appearing on the edit page where we don't want it to.
@order.errors.clear
end
def update
unless @order.update_attributes(params[:order]) && @order.line_items.present?
if @order.line_items.empty?
@order.errors.add(:line_items, Spree.t('errors.messages.blank'))
end
return redirect_to(edit_admin_order_path(@order),
flash: { error: @order.errors.full_messages.join(', ') })
end
@order.update!
if @order.complete?
redirect_to edit_admin_order_path(@order)
else
# Jump to next step if order is not complete
redirect_to admin_order_customer_path(@order)
end
end
def bulk_management
load_spree_api_key
end
def fire
event = params[:e]
if @order.public_send(event.to_s)
flash[:success] = Spree.t(:order_updated)
else
flash[:error] = Spree.t(:cannot_perform_operation)
end
rescue Spree::Core::GatewayError => e
flash[:error] = e.message.to_s
ensure
redirect_to :back
end
def resend
Spree::OrderMailer.confirm_email_for_customer(@order.id, true).deliver
flash[:success] = t(:order_email_resent)
respond_with(@order) { |format| format.html { redirect_to :back } }
end
def invoice
pdf = InvoiceRenderer.new.render_to_string(@order)
Spree::OrderMailer.invoice_email(@order.id, pdf).deliver
flash[:success] = t('admin.orders.invoice_email_sent')
respond_with(@order) { |format| format.html { redirect_to edit_admin_order_path(@order) } }
end
def print
render InvoiceRenderer.new.args(@order)
end
def print_ticket
render template: "spree/admin/orders/ticket", layout: false
end
def update_distribution_charge
@order.update_distribution_charge!
end
private
def load_order
@order = Order.find_by_number!(params[:id], include: :adjustments) if params[:id]
authorize! action, @order
end
def model_class
Spree::Order
end
def require_distributor_abn
return if @order.distributor.abn.present?
flash[:error] = t(:must_have_valid_business_number,
enterprise_name: @order.distributor.name)
respond_with(@order) { |format| format.html { redirect_to edit_admin_order_path(@order) } }
end
def load_distribution_choices
@shops = Enterprise.is_distributor.managed_by(spree_current_user).by_name
ocs = OrderCycle.managed_by(spree_current_user)
@order_cycles = ocs.soonest_closing +
ocs.soonest_opening +
ocs.closed +
ocs.undated
end
def ensure_distribution
unless @order
@order = Spree::Order.new
@order.generate_order_number
@order.save!
end
return if @order.distribution_set?
render 'set_distribution', locals: { order: @order }
end
end
end
end

View File

@@ -1,120 +0,0 @@
require 'open_food_network/spree_api_key_loader'
Spree::Admin::OrdersController.class_eval do
include OpenFoodNetwork::SpreeApiKeyLoader
helper CheckoutHelper
before_filter :load_order, only: %i[show edit update fire resend invoice print print_ticket]
before_filter :load_distribution_choices, only: [:new, :edit, :update]
# Ensure that the distributor is set for an order when
before_filter :ensure_distribution, only: :new
# After updating an order, the fees should be updated as well
# Currently, adding or deleting line items does not trigger updating the
# fees! This is a quick fix for that.
# TODO: update fees when adding/removing line items
# instead of the update_distribution_charge method.
after_filter :update_distribution_charge, only: :update
before_filter :require_distributor_abn, only: :invoice
respond_to :html, :json
def index
# Overriding the action so we only render the page template. An angular request
# 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
AdvanceOrderService.new(@order).call
# The payment step shows an error of 'No pending payments'
# Clearing the errors from the order object will stop this error
# appearing on the edit page where we don't want it to.
@order.errors.clear
end
# Re-implement spree method so that it redirects to edit instead of rendering edit
# This allows page reloads while adding variants to the order (/edit), without being redirected to customer details page (/update)
def update
unless @order.update_attributes(params[:order]) && @order.line_items.present?
@order.errors.add(:line_items, Spree.t('errors.messages.blank')) if @order.line_items.empty?
return redirect_to edit_admin_order_path(@order), flash: { error: @order.errors.full_messages.join(', ') }
end
@order.update!
if @order.complete?
redirect_to edit_admin_order_path(@order)
else
# Jump to next step if order is not complete
redirect_to admin_order_customer_path(@order)
end
end
# Overwrite to use confirm_email_for_customer instead of confirm_email.
# This uses a new template. See mailers/spree/order_mailer_decorator.rb.
def resend
Spree::OrderMailer.confirm_email_for_customer(@order.id, true).deliver
flash[:success] = t(:order_email_resent)
respond_with(@order) { |format| format.html { redirect_to :back } }
end
def invoice
pdf = InvoiceRenderer.new.render_to_string(@order)
Spree::OrderMailer.invoice_email(@order.id, pdf).deliver
flash[:success] = t('admin.orders.invoice_email_sent')
respond_with(@order) { |format| format.html { redirect_to edit_admin_order_path(@order) } }
end
def print
render InvoiceRenderer.new.args(@order)
end
def print_ticket
render template: "spree/admin/orders/ticket", layout: false
end
def update_distribution_charge
@order.update_distribution_charge!
end
private
def require_distributor_abn
if @order.distributor.abn.blank?
flash[:error] = t(:must_have_valid_business_number, enterprise_name: @order.distributor.name)
respond_with(@order) { |format| format.html { redirect_to edit_admin_order_path(@order) } }
end
end
def load_distribution_choices
@shops = Enterprise.is_distributor.managed_by(spree_current_user).by_name
ocs = OrderCycle.managed_by(spree_current_user)
@order_cycles = ocs.soonest_closing +
ocs.soonest_opening +
ocs.closed +
ocs.undated
end
def ensure_distribution
unless @order
@order = Spree::Order.new
@order.generate_order_number
@order.save!
end
unless @order.distribution_set?
render 'set_distribution', locals: { order: @order }
end
end
end

View File

@@ -110,7 +110,7 @@ module Spree
else
Gateway.providers.reject{ |p| p.name.include? "Bogus" }.sort_by(&:name)
end
@providers.reject!{ |p| p.name.ends_with? "StripeConnect" } unless show_stripe?
@providers.reject!{ |provider| stripe_provider?(provider) } unless show_stripe?
@calculators = PaymentMethod.calculators.sort_by(&:name)
end
@@ -134,12 +134,12 @@ module Spree
# current payment_method is already a Stripe method
def show_stripe?
Spree::Config.stripe_connect_enabled ||
@payment_method.try(:type) == "Spree::Gateway::StripeConnect"
stripe_payment_method?
end
def restrict_stripe_account_change
return unless @payment_method
return unless @payment_method.type == "Spree::Gateway::StripeConnect"
return unless stripe_payment_method?
return unless @payment_method.preferred_enterprise_id.andand > 0
@stripe_account_holder = Enterprise.find(@payment_method.preferred_enterprise_id)
@@ -147,6 +147,15 @@ module Spree
params[:payment_method][:preferred_enterprise_id] = @stripe_account_holder.id
end
def stripe_payment_method?
["Spree::Gateway::StripeConnect",
"Spree::Gateway::StripeSCA"].include? @payment_method.try(:type)
end
def stripe_provider?(provider)
provider.name.ends_with?("StripeConnect", "StripeSCA")
end
end
end
end

View File

@@ -0,0 +1,129 @@
# frozen_string_literal: true
module Spree
module Admin
class PaymentsController < Spree::Admin::BaseController
before_filter :load_order, except: [:show]
before_filter :load_payment, only: [:fire, :show]
before_filter :load_data
before_filter :can_transition_to_payment
respond_to :html
def index
@payments = @order.payments
redirect_to new_admin_order_payment_url(@order) if @payments.empty?
end
def new
@payment = @order.payments.build
end
def create
@payment = @order.payments.build(object_params)
load_payment_source
begin
unless @payment.save
redirect_to admin_order_payments_path(@order)
return
end
if @order.completed?
@payment.process!
flash[:success] = flash_message_for(@payment, :successfully_created)
redirect_to admin_order_payments_path(@order)
else
AdvanceOrderService.new(@order).call!
flash[:success] = Spree.t(:new_order_completed)
redirect_to edit_admin_order_url(@order)
end
rescue Spree::Core::GatewayError => e
flash[:error] = e.message.to_s
redirect_to new_admin_order_payment_path(@order)
end
end
# When a user fires an event, take them back to where they came from
# (we can't use respond_override because Spree no longer uses respond_with)
def fire
event = params[:e]
return unless event && @payment.payment_source
# Because we have a transition method also called void, we do this to avoid conflicts.
event = "void_transaction" if event == "void"
if @payment.public_send("#{event}!")
flash[:success] = t(:payment_updated)
else
flash[:error] = t(:cannot_perform_operation)
end
rescue Spree::Core::GatewayError => e
flash[:error] = e.message
ensure
redirect_to request.referer
end
private
def load_payment_source
if @payment.payment_method.is_a?(Spree::Gateway) &&
@payment.payment_method.payment_profiles_supported? &&
params[:card].present? &&
(params[:card] != 'new')
@payment.source = CreditCard.find_by_id(params[:card])
end
end
def object_params
if params[:payment] &&
params[:payment_source] &&
source_params = params.delete(:payment_source)[params[:payment][:payment_method_id]]
params[:payment][:source_attributes] = source_params
end
params[:payment]
end
def load_data
@amount = params[:amount] || load_order.total
# Only show payments for the order's distributor
@payment_methods = PaymentMethod.
available(:back_end).
select{ |pm| pm.has_distributor? @order.distributor }
@payment_method = if @payment && @payment.payment_method
@payment.payment_method
else
@payment_methods.first
end
@previous_cards = @order.credit_cards.with_payment_profile
end
# At this point admin should have passed through Customer Details step
# where order.next is called which leaves the order in payment step
#
# Orders in complete step also allows to access this controller
#
# Otherwise redirect user to that step
def can_transition_to_payment
return if @order.payment? || @order.complete?
flash[:notice] = Spree.t(:fill_in_customer_info)
redirect_to edit_admin_order_customer_url(@order)
end
def load_order
@order = Order.find_by_number!(params[:order_id])
authorize! action, @order
@order
end
def load_payment
@payment = Payment.find(params[:id])
end
end
end
end

View File

@@ -1,59 +0,0 @@
Spree::Admin::PaymentsController.class_eval do
append_before_filter :filter_payment_methods
def create
@payment = @order.payments.build(object_params)
if @payment.payment_method.is_a?(Spree::Gateway) && @payment.payment_method.payment_profiles_supported? && params[:card].present? && (params[:card] != 'new')
@payment.source = CreditCard.find_by_id(params[:card])
end
begin
unless @payment.save
redirect_to admin_order_payments_path(@order)
return
end
if @order.completed?
@payment.process!
flash[:success] = flash_message_for(@payment, :successfully_created)
redirect_to admin_order_payments_path(@order)
else
AdvanceOrderService.new(@order).call!
flash[:success] = Spree.t(:new_order_completed)
redirect_to edit_admin_order_url(@order)
end
rescue Spree::Core::GatewayError => e
flash[:error] = e.message.to_s
redirect_to new_admin_order_payment_path(@order)
end
end
# When a user fires an event, take them back to where they came from
# (we can't use respond_override because Spree no longer uses respond_with)
def fire
event = params[:e]
return unless event && @payment.payment_source
# Because we have a transition method also called void, we do this to avoid conflicts.
event = "void_transaction" if event == "void"
if @payment.public_send("#{event}!")
flash[:success] = t(:payment_updated)
else
flash[:error] = t(:cannot_perform_operation)
end
rescue Spree::Core::GatewayError => e
flash[:error] = e.message
ensure
redirect_to request.referer
end
private
# Only show payments for the order's distributor
def filter_payment_methods
@payment_methods = @payment_methods.select{ |pm| pm.has_distributor? @order.distributor }
@payment_method ||= @payment_methods.first
end
end

View File

@@ -217,7 +217,11 @@ module Spree
end
def render_report(header, table, create_csv, csv_file_name)
send_data csv_report(header, table), filename: csv_file_name if create_csv
if create_csv
@csv_report = csv_report(header, table)
send_data @csv_report, filename: csv_file_name
end
@header = header
@table = table
# Rendering HTML is the default.

View File

@@ -0,0 +1,43 @@
module Spree
module Admin
class SearchController < Spree::Admin::BaseController
# http://spreecommerce.com/blog/2010/11/02/json-hijacking-vulnerability/
before_filter :check_json_authenticity, only: :index
respond_to :json
def known_users
@users = if exact_match = Spree.user_class.find_by_email(params[:q])
[exact_match]
else
spree_current_user.known_users.ransack(ransack_hash).result.limit(10)
end
render json: @users, each_serializer: ::Api::Admin::UserSerializer
end
def customers
@customers = []
if spree_current_user.enterprises.pluck(:id).include? params[:distributor_id].to_i
@customers = Customer.
ransack(m: 'or', email_start: params[:q], name_start: params[:q]).
result.
where(enterprise_id: params[:distributor_id])
end
render json: @customers, each_serializer: ::Api::Admin::CustomerSerializer
end
private
def ransack_hash
{
m: 'or',
email_start: params[:q],
ship_address_firstname_start: params[:q],
ship_address_lastname_start: params[:q],
bill_address_firstname_start: params[:q],
bill_address_lastname_start: params[:q]
}
end
end
end
end

View File

@@ -1,36 +0,0 @@
Spree::Admin::SearchController.class_eval do
def known_users
@users = if exact_match = Spree.user_class.find_by_email(params[:q])
[exact_match]
else
spree_current_user.known_users.ransack(
m: 'or',
email_start: params[:q],
ship_address_firstname_start: params[:q],
ship_address_lastname_start: params[:q],
bill_address_firstname_start: params[:q],
bill_address_lastname_start: params[:q]
).result.limit(10)
end
render json: @users, each_serializer: Api::Admin::UserSerializer
end
def customers
@customers = if spree_current_user.enterprises.pluck(:id).include? params[:distributor_id].to_i
Customer.ransack(m: 'or', email_start: params[:q], name_start: params[:q])
.result.where(enterprise_id: params[:distributor_id])
else
[]
end
render json: @customers, each_serializer: Api::Admin::CustomerSerializer
end
def users_with_ams
users_without_ams
render json: @users, each_serializer: Api::Admin::UserSerializer
end
alias_method_chain :users, :ams
end

View File

@@ -1,93 +1,16 @@
require 'open_food_network/address_finder'
# frozen_string_literal: true
# This controller (and respective route in the Spree engine)
# is only needed for the spree_paypal_express gem that redirects here explicitly.
#
# According to the rails docs it would be possible to redirect
# to CheckoutController directly in the routes
# with a slash like "to: '/checkout#edit'", but it does not work in this case.
module Spree
class CheckoutController < Spree::StoreController
include CheckoutHelper
ssl_required
before_filter :load_order
before_filter :ensure_order_not_completed
before_filter :ensure_checkout_allowed
before_filter :ensure_sufficient_stock_lines
before_filter :associate_user
before_filter :check_authorization
before_filter :enable_embedded_shopfront
helper 'spree/orders'
rescue_from Spree::Core::GatewayError, with: :rescue_from_spree_gateway_error
def edit
flash.keep
redirect_to main_app.checkout_path
end
private
def load_order
@order = current_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])
@order.state = params[:state]
end
setup_for_current_state
end
def ensure_checkout_allowed
redirect_to main_app.cart_path unless @order.checkout_allowed?
end
def ensure_order_not_completed
redirect_to main_app.cart_path if @order.completed?
end
def ensure_sufficient_stock_lines
if @order.insufficient_stock_lines.present?
flash[:error] = Spree.t(:inventory_error_flash_for_insufficient_quantity)
redirect_to main_app.cart_path
end
end
def setup_for_current_state
method_name = :"before_#{@order.state}"
send(method_name) if respond_to?(method_name, true)
end
# Adapted from spree_last_address gem: https://github.com/TylerRick/spree_last_address
# Originally, we used a forked version of this gem, but encountered strange errors where
# it worked in dev but only intermittently in staging/prod.
def before_address
associate_user
finder = OpenFoodNetwork::AddressFinder.new(@order.email)
@order.bill_address = finder.bill_address
@order.ship_address = finder.ship_address
end
def before_delivery
return if params[:order].present?
packages = @order.shipments.map(&:to_package)
@differentiator = Spree::Stock::Differentiator.new(@order, packages)
end
def before_payment
current_order.payments.destroy_all if request.put?
end
def rescue_from_spree_gateway_error
flash[:error] = Spree.t(:spree_gateway_error_flash_for_checkout)
render :edit
end
def check_authorization
authorize!(:edit, current_order, session[:access_token])
end
end
end

View File

@@ -10,10 +10,14 @@ module Spree
render json: @credit_card, serializer: ::Api::CreditCardSerializer, status: :ok
else
message = t(:card_could_not_be_saved)
render json: { flash: { error: I18n.t(:spree_gateway_error_flash_for_checkout, error: message) } }, status: :bad_request
render json: { flash: { error: I18n.t(:spree_gateway_error_flash_for_checkout,
error: message) } },
status: :bad_request
end
rescue Stripe::CardError => e
render json: { flash: { error: I18n.t(:spree_gateway_error_flash_for_checkout, error: e.message) } }, status: :bad_request
render json: { flash: { error: I18n.t(:spree_gateway_error_flash_for_checkout,
error: e.message) } },
status: :bad_request
end
def update
@@ -52,12 +56,19 @@ module Spree
private
# Currently can only destroy the whole customer object
# It destroys the whole customer object
def destroy_at_stripe
stripe_customer = Stripe::Customer.retrieve(@credit_card.gateway_customer_profile_id)
stripe_customer = Stripe::Customer.retrieve(@credit_card.gateway_customer_profile_id, {})
stripe_customer.delete if stripe_customer
end
def stripe_account_id
StripeAccount.
find_by_enterprise_id(@credit_card.payment_method.preferred_enterprise_id).
andand.
stripe_user_id
end
def create_customer(token)
Stripe::Customer.create(email: spree_current_user.email, source: token)
end

View File

@@ -71,7 +71,7 @@ module Spree
@order = order_to_update
unless @order
flash[:error] = t(:order_not_found)
redirect_to(root_path) && return
redirect_to(main_app.root_path) && return
end
if @order.update_attributes(params[:order])

View File

@@ -32,7 +32,7 @@ module Spree
session[:guest_token] = nil
end
redirect_back_or_default(root_url)
redirect_back_or_default(main_app.root_url)
else
render :new
end

View File

@@ -1,3 +1,5 @@
# frozen_string_literal: false
module Spree
module Admin
module NavigationHelper
@@ -34,7 +36,9 @@ module Spree
end
selected = if options[:match_path]
request.fullpath.starts_with?("#{spree.root_path}admin#{options[:match_path]}")
request.
fullpath.
starts_with?("#{main_app.root_path}admin#{options[:match_path]}")
else
args.include?(controller.controller_name.to_sym)
end

View File

@@ -1,6 +1,17 @@
module Spree
module Admin
module OrdersHelper
def event_links
links = []
links << event_link("cancel") if @order.can_cancel?
links << event_link("resume") if @order.can_resume?
links.join('&nbsp;').html_safe
end
def line_item_shipment_price(line_item, quantity)
Spree::Money.new(line_item.price * quantity, currency: line_item.currency)
end
def order_links(order)
@order ||= order
links = []
@@ -100,6 +111,14 @@ module Spree
icon: 'icon-trash',
confirm: t(:are_you_sure) }
end
def event_link(event)
button_link_to(Spree.t(event),
fire_admin_order_url(@order, e: event),
method: :put,
icon: "icon-#{event}",
data: { confirm: Spree.t(:order_sure_want_to, event: Spree.t(event)) })
end
end
end
end

View File

@@ -0,0 +1,11 @@
module Spree
module Admin
module PaymentsHelper
def payment_method_name(payment)
# hack to allow us to retrieve the name of a "deleted" payment method
id = payment.payment_method_id
Spree::PaymentMethod.find_with_destroyed(id).name
end
end
end
end

View File

@@ -6,6 +6,7 @@ class SubscriptionConfirmJob
ids = proxy_orders.pluck(:id)
proxy_orders.update_all(confirmed_at: Time.zone.now)
ProxyOrder.where(id: ids).each do |proxy_order|
Rails.logger.info "Confirming Order for Proxy Order #{proxy_order.id}"
@order = proxy_order.order
process!
end

View File

@@ -5,8 +5,7 @@ class SubscriptionPlacementJob
ids = proxy_orders.pluck(:id)
proxy_orders.update_all(placed_at: Time.zone.now)
ProxyOrder.where(id: ids).each do |proxy_order|
proxy_order.initialise_order!
process(proxy_order.order)
place_order_for(proxy_order)
end
send_placement_summary_emails
@@ -28,16 +27,18 @@ class SubscriptionPlacementJob
.joins(:subscription).merge(Subscription.not_canceled.not_paused)
end
def process(order)
def place_order_for(proxy_order)
Rails.logger.info "Placing Order for Proxy Order #{proxy_order.id}"
proxy_order.initialise_order!
place_order(proxy_order.order)
end
def place_order(order)
record_order(order)
return record_issue(:complete, order) if order.completed?
changes = cap_quantity_and_store_changes(order)
if order.line_items.where('quantity > 0').empty?
order.reload.adjustments.destroy_all
order.update!
return send_empty_email(order, changes)
end
return handle_empty_order(order, changes) if order.line_items.where('quantity > 0').empty?
move_to_completion(order)
send_placement_email(order, changes)
@@ -58,12 +59,18 @@ class SubscriptionPlacementJob
changes
end
def handle_empty_order(order, changes)
order.reload.adjustments.destroy_all
order.update!
send_empty_email(order, changes)
end
def move_to_completion(order)
AdvanceOrderService.new(order).call!
end
def unavailable_stock_lines_for(order)
order.line_items.where('variant_id NOT IN (?)', available_variants_for(order))
order.line_items.where('variant_id NOT IN (?)', available_variants_for(order).select(&:id))
end
def available_variants_for(order)

View File

@@ -9,6 +9,6 @@ Spree::BaseMailer.class_eval do
def roadie_options
# This lets us specify assets using relative paths in email templates
super.merge(url_options: { host: URI(spree.root_url).host })
super.merge(url_options: { host: URI(main_app.root_url).host })
end
end

View File

@@ -25,7 +25,8 @@ class Enterprise < ActiveRecord::Base
has_many :relationships_as_child, class_name: 'EnterpriseRelationship',
foreign_key: 'child_id',
dependent: :destroy
has_and_belongs_to_many :groups, class_name: 'EnterpriseGroup'
has_and_belongs_to_many :groups, join_table: 'enterprise_groups_enterprises',
class_name: 'EnterpriseGroup'
has_many :producer_properties, foreign_key: 'producer_id'
has_many :properties, through: :producer_properties
has_many :supplied_products, class_name: 'Spree::Product',
@@ -115,7 +116,10 @@ class Enterprise < ActiveRecord::Base
scope :not_ready_for_checkout, lambda {
# When ready_for_checkout is empty, return all rows when there are no enterprises ready for
# checkout.
ready_enterprises = Enterprise.ready_for_checkout.select('enterprises.id')
ready_enterprises = Enterprise.ready_for_checkout.
except(:select).
select('DISTINCT enterprises.id')
if ready_enterprises.present?
where("enterprises.id NOT IN (?)", ready_enterprises)
else
@@ -317,7 +321,7 @@ class Enterprise < ActiveRecord::Base
def distributed_taxons
Spree::Taxon.
joins(:products).
where('spree_products.id IN (?)', Spree::Product.in_distributor(self)).
where('spree_products.id IN (?)', Spree::Product.in_distributor(self).select(&:id)).
select('DISTINCT spree_taxons.*')
end
@@ -333,7 +337,7 @@ class Enterprise < ActiveRecord::Base
def supplied_taxons
Spree::Taxon.
joins(:products).
where('spree_products.id IN (?)', Spree::Product.in_supplier(self)).
where('spree_products.id IN (?)', Spree::Product.in_supplier(self).select(&:id)).
select('DISTINCT spree_taxons.*')
end

View File

@@ -27,7 +27,7 @@ class EnterpriseFee < ActiveRecord::Base
if user.has_spree_role?('admin')
scoped
else
where('enterprise_id IN (?)', user.enterprises)
where('enterprise_id IN (?)', user.enterprises.select(&:id))
end
}

View File

@@ -5,7 +5,7 @@ class EnterpriseGroup < ActiveRecord::Base
include PermalinkGenerator
acts_as_list
has_and_belongs_to_many :enterprises
has_and_belongs_to_many :enterprises, join_table: 'enterprise_groups_enterprises'
belongs_to :owner, class_name: 'Spree::User', foreign_key: :owner_id, inverse_of: :owned_groups
belongs_to :address, class_name: 'Spree::Address'
accepts_nested_attributes_for :address

View File

@@ -22,7 +22,7 @@ class EnterpriseRelationship < ActiveRecord::Base
}
scope :involving_enterprises, ->(enterprises) {
where('parent_id IN (?) OR child_id IN (?)', enterprises, enterprises)
where('parent_id IN (?) OR child_id IN (?)', enterprises.select(&:id), enterprises.select(&:id))
}
scope :permitting, ->(enterprise_ids) { where('child_id IN (?)', enterprise_ids) }

View File

@@ -49,7 +49,7 @@ class Exchange < ActiveRecord::Base
}
scope :with_product, lambda { |product|
joins(:exchange_variants).
where('exchange_variants.variant_id IN (?)', product.variants_including_master)
where('exchange_variants.variant_id IN (?)', product.variants_including_master.select(&:id))
}
scope :by_enterprise_name, -> {
joins('INNER JOIN enterprises AS sender ON (sender.id = exchanges.sender_id)').

View File

@@ -17,6 +17,7 @@ class OrderCycle < ActiveRecord::Base
has_many :distributors, source: :receiver, through: :cached_outgoing_exchanges, uniq: true
has_and_belongs_to_many :schedules, join_table: 'order_cycle_schedules'
has_paper_trail meta: { custom_data: :schedule_ids }
attr_accessor :incoming_exchanges, :outgoing_exchanges
@@ -63,7 +64,7 @@ class OrderCycle < ActiveRecord::Base
if user.has_spree_role?('admin')
scoped
else
where('coordinator_id IN (?)', user.enterprises.map(&:id))
where(coordinator_id: user.enterprises)
end
}

View File

@@ -122,7 +122,6 @@ module ProductImport
def save_new_inventory_item(entry)
new_item = entry.product_object
assign_defaults(new_item, entry)
new_item.import_date = @import_time
if new_item.valid? && new_item.save
@@ -136,7 +135,6 @@ module ProductImport
def save_existing_inventory_item(entry)
existing_item = entry.product_object
assign_defaults(existing_item, entry)
existing_item.import_date = @import_time
if existing_item.valid? && existing_item.save
@@ -164,7 +162,6 @@ module ProductImport
product = Spree::Product.new
product.assign_attributes(entry.attributes.except('id', 'on_hand', 'on_demand'))
product.supplier_id = entry.producer_id
assign_defaults(product, entry)
if product.save
ensure_variant_updated(product, entry)
@@ -179,7 +176,6 @@ module ProductImport
def save_variant(entry)
variant = entry.product_object
assign_defaults(variant, entry)
variant.import_date = @import_time
if variant.valid? && variant.save
@@ -199,37 +195,6 @@ module ProductImport
)
end
def assign_defaults(object, entry)
# Assigns a default value for a specified field e.g. category='Vegetables', setting this value
# either for all entries (overwrite_all), or only for those entries where the field was blank
# in the spreadsheet (overwrite_empty), depending on selected import settings
return unless settings.defaults(entry)
settings.defaults(entry).each do |attribute, setting|
next unless setting['active']
case setting['mode']
when 'overwrite_all'
object.assign_attributes(attribute => setting['value'])
# In case of new products, some attributes are saved on the variant.
# We write them to the entry here to be copied to the variant later.
if entry.respond_to? "#{attribute}="
entry.public_send("#{attribute}=", setting['value'])
end
when 'overwrite_empty'
if object.public_send(attribute).blank? ||
((attribute == 'on_hand') &&
entry.on_hand_nil)
object.assign_attributes(attribute => setting['value'])
if entry.respond_to? "#{attribute}="
entry.public_send("#{attribute}=", setting['value'])
end
end
end
end
end
def display_in_inventory(variant_override, is_new = false)
unless is_new
existing_item = InventoryItem.where(

View File

@@ -1,5 +1,7 @@
class Schedule < ActiveRecord::Base
has_and_belongs_to_many :order_cycles, join_table: 'order_cycle_schedules'
has_paper_trail meta: { custom_data: :order_cycle_ids }
has_many :coordinators, uniq: true, through: :order_cycles
attr_accessible :name, :order_cycle_ids

View File

@@ -9,12 +9,6 @@ module Spree
attr_accessible :preferred_enterprise_id
CARD_TYPE_MAPPING = {
'American Express' => 'american_express',
'Diners Club' => 'diners_club',
'Visa' => 'visa'
}.freeze
def method_type
'stripe'
end
@@ -77,11 +71,6 @@ module Spree
[money, creditcard, options]
end
def update_source!(source)
source.cc_type = CARD_TYPE_MAPPING[source.cc_type] if CARD_TYPE_MAPPING.include?(source.cc_type)
source
end
def token_from_card_profile_ids(creditcard)
token_or_card_id = creditcard.gateway_payment_profile_id
customer = creditcard.gateway_customer_profile_id

View File

@@ -0,0 +1,91 @@
# frozen_string_literal: true
require 'stripe/profile_storer'
require 'stripe/credit_card_cloner'
require 'active_merchant/billing/gateways/stripe_payment_intents'
require 'active_merchant/billing/gateways/stripe_decorator'
module Spree
class Gateway
class StripeSCA < Gateway
preference :enterprise_id, :integer
validate :ensure_enterprise_selected
attr_accessible :preferred_enterprise_id
def method_type
'stripe_sca'
end
def provider_class
ActiveMerchant::Billing::StripePaymentIntentsGateway
end
def payment_profiles_supported?
true
end
def stripe_account_id
StripeAccount.find_by_enterprise_id(preferred_enterprise_id).andand.stripe_user_id
end
# NOTE: the name of this method is determined by Spree::Payment::Processing
def purchase(money, creditcard, gateway_options)
provider.purchase(*options_for_purchase_or_auth(money, creditcard, gateway_options))
rescue Stripe::StripeError => e
# This will be an error caused by generating a stripe token
failed_activemerchant_billing_response(e.message)
end
# NOTE: the name of this method is determined by Spree::Payment::Processing
def void(response_code, _creditcard, gateway_options)
gateway_options[:stripe_account] = stripe_account_id
provider.void(response_code, gateway_options)
end
# NOTE: the name of this method is determined by Spree::Payment::Processing
def credit(money, _creditcard, response_code, gateway_options)
gateway_options[:stripe_account] = stripe_account_id
provider.refund(money, response_code, gateway_options)
end
def create_profile(payment)
return unless payment.source.gateway_customer_profile_id.nil?
profile_storer = Stripe::ProfileStorer.new(payment, provider)
profile_storer.create_customer_from_token
end
private
# In this gateway, what we call 'secret_key' is the 'login'
def options
options = super
options.merge(login: Stripe.api_key)
end
def options_for_purchase_or_auth(money, creditcard, gateway_options)
options = {}
options[:description] = "Spree Order ID: #{gateway_options[:order_id]}"
options[:currency] = gateway_options[:currency]
options[:stripe_account] = stripe_account_id
customer_id, payment_method_id = Stripe::CreditCardCloner.new.clone(creditcard,
stripe_account_id)
options[:customer] = customer_id
[money, payment_method_id, options]
end
def failed_activemerchant_billing_response(error_message)
ActiveMerchant::Billing::Response.new(false, error_message)
end
def ensure_enterprise_selected
return if preferred_enterprise_id.andand.positive?
errors.add(:stripe_account_owner, I18n.t(:error_required))
end
end
end
end

View File

@@ -56,7 +56,9 @@ Spree::Order.class_eval do
# Find orders that are distributed by the user or have products supplied by the user
# WARNING: This only filters orders, you'll need to filter line items separately using LineItem.managed_by
with_line_items_variants_and_products_outer.
where('spree_orders.distributor_id IN (?) OR spree_products.supplier_id IN (?)', user.enterprises, user.enterprises).
where('spree_orders.distributor_id IN (?) OR spree_products.supplier_id IN (?)',
user.enterprises.select(&:id),
user.enterprises.select(&:id)).
select('DISTINCT spree_orders.*')
end
}
@@ -65,7 +67,7 @@ Spree::Order.class_eval do
if user.has_spree_role?('admin')
scoped
else
where('spree_orders.distributor_id IN (?)', user.enterprises)
where('spree_orders.distributor_id IN (?)', user.enterprises.select(&:id))
end
}
@@ -75,6 +77,10 @@ Spree::Order.class_eval do
joins('LEFT OUTER JOIN spree_products ON (spree_products.id = spree_variants.product_id)')
}
scope :with_line_items_variants_and_products, lambda {
joins(line_items: { variant: :product })
}
scope :not_state, lambda { |state|
where("state != ?", state)
}

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