Compare commits

...

154 Commits

Author SHA1 Message Date
Andy Brett
dfabc5fa06 Update all locales with the latest Transifex translations 2020-12-02 21:41:18 -08:00
Luis Ramos
7a5a4f956a Replace use of Faker with FFaker 2020-12-02 11:40:50 -08:00
Luis Ramos
720edb4b05 Relax ffaker version requirement so that upgrades come as possible 2020-12-02 11:40:50 -08:00
dependabot-preview[bot]
3ec1af104f Bump ffaker from 1.32.1 to 2.11.0
Bumps [ffaker](https://github.com/ffaker/ffaker) from 1.32.1 to 2.11.0.
- [Release notes](https://github.com/ffaker/ffaker/releases)
- [Changelog](https://github.com/ffaker/ffaker/blob/master/Changelog.md)
- [Commits](https://github.com/ffaker/ffaker/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-02 11:40:50 -08:00
dependabot-preview[bot]
80d034706c Bump test-unit from 3.3.6 to 3.3.7
Bumps [test-unit](https://github.com/test-unit/test-unit) from 3.3.6 to 3.3.7.
- [Release notes](https://github.com/test-unit/test-unit/releases)
- [Commits](https://github.com/test-unit/test-unit/compare/3.3.6...3.3.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-02 11:40:04 -08:00
Andy Brett
902f8caea9 direct specifically to shop tab 2020-12-02 11:39:02 -08:00
Andy Brett
14091cd106 fix #6415 2020-12-02 11:39:02 -08:00
Andy Brett
936f5c1a0c remove extraneous page call 2020-12-02 11:38:10 -08:00
Andy Brett
8963a787d6 only validate unit_value presence if "items" is not chosen 2020-12-02 11:38:10 -08:00
Andy Brett
59cab902f0 add numericality validation 2020-12-02 11:38:10 -08:00
Andy Brett
4d2c93930b resolve merge conflict 2020-12-02 11:38:10 -08:00
Tsara Sudrajat
fb769d37f9 Fix error when setting stock for new product 2020-12-02 11:38:10 -08:00
Andy Brett
65f6f1febf rearrange css 2020-12-02 11:37:25 -08:00
Andy Brett
99b5d9e0c5 use white-space: nowrap on variant prices 2020-12-02 11:37:25 -08:00
Andy Brett
c4cd574242 fix currency spec 2020-12-02 11:37:25 -08:00
Andy Brett
a3a6205343 fix #6252 2020-12-02 11:37:25 -08:00
Maikel
25c363feba Merge pull request #6356 from openfoodfoundation/dependabot/bundler/stringex-2.8.5
Bump stringex from 1.5.1 to 2.8.5
2020-12-02 16:39:00 +11:00
Luis Ramos
839278fc75 Add dependendabot config to increase limit to 10 PRs 2020-12-01 12:40:24 -08:00
Matt-Yorkley
1cab9e473b Merge pull request #6378 from openfoodfoundation/dependabot/bundler/webmock-3.10.0
Bump webmock from 3.9.5 to 3.10.0
2020-12-01 11:58:01 +01:00
dependabot-preview[bot]
93a73b4823 Bump stringex from 1.5.1 to 2.8.5
Bumps [stringex](https://github.com/rsl/stringex) from 1.5.1 to 2.8.5.
- [Release notes](https://github.com/rsl/stringex/releases)
- [Commits](https://github.com/rsl/stringex/compare/v1.5.1...v2.8.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-12-01 09:58:08 +00:00
Matt-Yorkley
7408c45980 Merge pull request #6297 from openfoodfoundation/rails-4-1
[Rails 4.1] Merge Rails 4.1 branch into master
2020-12-01 10:56:08 +01:00
Matt-Yorkley
fe4b20dd7b Merge pull request #6354 from openfoodfoundation/rails-4-2-rebased
Rails 4.2 upgrade
2020-12-01 10:55:25 +01:00
Pau Pérez Fabregat
3c71b7f6be Merge pull request #6428 from coopdevs/upgrade-brakeman-dependencies
Upgrade Ruby and Ubuntu to latest in GH action
2020-11-30 21:13:25 +01:00
Pau Perez
259e139c47 Update all locales with the latest Transifex translations 2020-11-30 09:21:13 +01:00
Pau Perez
8c1e222788 Upgrade Ruby and Ubuntu to latest in GH action
It was asked for in
https://github.com/openfoodfoundation/openfoodnetwork/pull/6163/ to use
the latest stable Ruby version. It's also better to use Ubuntu's latest
as well.
2020-11-30 09:11:41 +01:00
Pau Pérez Fabregat
4ca930bdad Merge pull request #6163 from openfoodfoundation/luisramos0-patch-2
Add brakeman config
2020-11-30 09:08:32 +01:00
Pau Pérez Fabregat
f0a052b65b Merge pull request #6357 from Matt-Yorkley/secret-key-base
Update secret key base
2020-11-27 17:32:14 +01:00
Pau Pérez Fabregat
07a72eccd4 Merge pull request #6391 from Matt-Yorkley/paypal-stock-clashes
Paypal stock clashes
2020-11-27 17:08:15 +01:00
Matt-Yorkley
b04a76e8bf Update payments_report totals 2020-11-27 14:00:29 +00:00
Matt-Yorkley
1ceb6ac916 Update orders_and_fulfilment report totals 2020-11-27 14:00:29 +00:00
Andy Brett
049f66c2aa address #6411 2020-11-27 14:00:29 +00:00
Matt-Yorkley
9c41c296e4 Remove default comments from ApplicationResponder 2020-11-27 14:00:29 +00:00
Matt-Yorkley
d299c8cf01 Update test setup in Packer spec.
This is the correct way to set a variant's weight.
2020-11-27 14:00:29 +00:00
Matt-Yorkley
2b2f1ac0cd Improve specificity of expectation in reset password email test 2020-11-27 14:00:29 +00:00
Matt-Yorkley
d2998f1190 Remove spaces in payments report 2020-11-27 14:00:29 +00:00
Matt-Yorkley
c6c20dc0f6 Add ActionController::ConditionalGet to Api::BaseController
This was added in Spree around the time of Rails 4.2 and seems to fix some of the response errors around the `responders` gem.
2020-11-27 14:00:29 +00:00
Matt-Yorkley
60aaf8100a Fix some Rubocop offences 2020-11-27 14:00:29 +00:00
Matt-Yorkley
98f42a1f81 Fix output of Package#inspect 2020-11-27 14:00:29 +00:00
Matt-Yorkley
f589d278cf Add failing spec for Package#inspect 2020-11-27 14:00:29 +00:00
Matt-Yorkley
2b884be8dd Update specs to work with ActionMailer::DeliveryJob 2020-11-27 14:00:29 +00:00
Matt-Yorkley
64153c5072 Remove #handle_asyncronously and update to recommended asyncronous devise mail method 2020-11-27 14:00:29 +00:00
Matt-Yorkley
9de3370a8a Fix precision in adjustment form display
The tests here were looking for values with a format like "10.00" but the output had changed to "10.0"
2020-11-27 14:00:29 +00:00
Matt-Yorkley
63fb46f440 Delete some dead code
There are some really weird issues in the spec here, and this module is not in use anywhere.
2020-11-27 14:00:29 +00:00
Matt-Yorkley
aa718824d8 Fix touch spec
The behavior in #change blocks ironically seems to have changed
2020-11-27 14:00:29 +00:00
Matt-Yorkley
4394d2fe43 Fix tag_rules ForbiddenAttributes errors
Example error:
Tag Rules creating allows creation of rules of each type
     Failure/Error: expect(tag_rule.preferred_shipping_method_tags).to eq "volunteers-only"

       expected: "volunteers-only"
            got: ""

       (compared using ==)
     # ./spec/features/admin/tag_rules_spec.rb:81:in `block (3 levels) in <top (required)>'
2020-11-27 14:00:29 +00:00
Matt-Yorkley
ea5c7c5990 Fix broken redirect after bulk product update
Error:
As an Administrator
  I want to be able to manage products in bulk
 updating when a filter has been applied
     Failure/Error: expect(page.find("#status-message")).to have_content "Changes saved."
       expected to find text "Changes saved." in "Saving.."
     # ./spec/features/admin/bulk_product_update_spec.rb:451:in `block (2 levels) in <top (required)>'
2020-11-27 14:00:29 +00:00
Matt-Yorkley
2905267142 Fix broken variant weight assignment in spec
OrderManagement::Stock::Packer builds a package with all the items
     Failure/Error: expect(package.weight).to be_positive
       expected `0.0 (#<BigDecimal:7f156c99fda8,'0.0',9(18)>).positive?` to be truthy, got false
     # ./engines/order_management/spec/services/order_management/stock/packer_spec.rb:19:in `block (2 levels) in <module:Stock>'
2020-11-27 14:00:29 +00:00
Matt-Yorkley
71c6cee94c Fix "modifying frozen string" error in Package#inspect 2020-11-27 14:00:29 +00:00
Matt-Yorkley
7ef0056225 Fix invoice rendering issue
Setting `locals: { :@order => order }` no longer works; `@order` is not set as expected in the partial. Fixes various errors eg:

Failure/Error: = "#{@order.number}"

     ActionView::Template::Error:
       undefined method `number' for nil:NilClass
     # ./app/views/spree/admin/orders/invoice.html.haml:14:in `_app_views_spree_admin_orders_invoice_html_haml__1740595365701113578_70025078036080'
     # ./app/services/invoice_renderer.rb:3:in `render_to_string'
     # ./app/controllers/spree/admin/orders_controller.rb:89:in `invoice'
2020-11-27 14:00:29 +00:00
Matt-Yorkley
b512d3ce21 Fix column preferences spec
Failure/Error: expect(preferences.map(&:column_name)).to eq [:col1, :col2, :col3]

        expected: [:col1, :col2, :col3]
             got: ["col1", "col2", "col3"]

        (compared using ==)

        Diff:
        @@ -1 +1 @@
        -[:col1, :col2, :col3]
        +["col1", "col2", "col3"]

      # ./spec/models/column_preference_spec.rb:56:in `block (4 levels) in <top (required)>'
2020-11-27 14:00:29 +00:00
Matt-Yorkley
98c99de835 Use ActiveJob::Testhelper where needed 2020-11-27 14:00:29 +00:00
Matt-Yorkley
1aa2b7274b Fix test mailer delivery 2020-11-27 14:00:29 +00:00
Matt-Yorkley
ae33df946e Fix StateMachine specs 2020-11-27 14:00:29 +00:00
Matt-Yorkley
54ad90e071 Replace deprecated ActiveRecord::ConnectionAdapters::Column#value_to_boolean
This method has been removed in Rails 4.2
2020-11-27 14:00:29 +00:00
Matt-Yorkley
e1c1574931 Refactor BulkInvoiceService to use ActiveJob
Removes use of #handle_asynchronously, which we need to do elsewhere. Fixes:
BulkInvoiceService#start_pdf_job starts a background process to create a pdf with multiple invoices
      Failure/Error:
        expect do
          service.start_pdf_job [1, 2]
        end.to enqueue_job Delayed::PerformableMethod

        expected to enqueue exactly 1 jobs, but enqueued 0
      # ./spec/services/bulk_invoice_service_spec.rb:8:in `block (3 levels) in <top (required)>'
2020-11-27 14:00:29 +00:00
Matt-Yorkley
8f8973b6f9 Call #deliver in user_mailer_spec so mail is sent 2020-11-27 14:00:29 +00:00
Matt-Yorkley
3c74541145 Fix misbehaving params in Api::ProductsController
In some cases the given params were being deleted here.
2020-11-27 14:00:29 +00:00
Matt-Yorkley
1ab62fddcb Patch Paranoia#delete to resolve ActiveRecord::ConnectionAdapters::NullTransaction errors
Patches Paranoia gem to fix a conflict with transactions in Rspec: https://github.com/rubysherpas/paranoia/issues/274

Example error:
```
Failure/Error: order.line_items.first.variant.tap(&:delete)
NoMethodError:
       undefined method `state' for #<ActiveRecord::ConnectionAdapters::NullTransaction:0x0000564117dddd18>
```
2020-11-27 14:00:29 +00:00
Matt-Yorkley
1e8d400534 Add Paranoia#delete (original) 2020-11-27 14:00:29 +00:00
Matt-Yorkley
1a4e292178 Fix json "empty body" expectations 2020-11-27 14:00:29 +00:00
Matt-Yorkley
49081e171e Fix PG::UndefinedTable errors
The logic of #includes has changed slightly in Rails 4.2 and now usually needs the #references method as well.

PG::UndefinedTable:
     #   ERROR:  missing FROM-clause entry for table "enterprises"
     #   LINE 1: SELECT "spree_users".* FROM "spree_users" WHERE (enterprises...
     #                                                            ^
     #   ./spec/models/spree/user_spec.rb:125:in `block (4 levels) in <top (required)>'
2020-11-27 14:00:29 +00:00
Matt-Yorkley
a5472d6b64 Convert ConfirmSignupJob to ActiveJob 2020-11-27 14:00:29 +00:00
Matt-Yorkley
62b80043ba Fix mailer specs
These methods are not actually called now until the email is being delivered.
2020-11-27 14:00:29 +00:00
Matt-Yorkley
eb040de422 Fix expectation in base_helper_spec
The attribute on this element are now rendered in alphabetical order
2020-11-27 14:00:29 +00:00
Matt-Yorkley
b36b0eddee Fix Rubocop issues 2020-11-27 14:00:29 +00:00
Matt-Yorkley
aaf7a90f8b Convert OrderCycleNotificationJob to ActiveJob 2020-11-27 14:00:29 +00:00
Matt-Yorkley
9e334a4c1e Convert ConfirmOrderJob to ActiveJob 2020-11-27 14:00:29 +00:00
Matt-Yorkley
56f2d38714 Use "raise_in_transactional_callbacks"
https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#error-handling-in-transaction-callbacks
2020-11-27 14:00:29 +00:00
Matt-Yorkley
6b3da4ac89 Fix "PG::ProtocolViolation: ERROR: bind message supplies 0 parameters" errors 2020-11-27 14:00:28 +00:00
Matt-Yorkley
31415d00e6 TEMP - Fix deprecated cache store naming 2020-11-27 14:00:28 +00:00
Matt-Yorkley
e155b00ab9 Fix undefined constant Spree::Responder 2020-11-27 14:00:28 +00:00
Matt-Yorkley
3c0172c507 Fix Spree::Preferences cache issue
In some cases this method was trying to delete a Rails.cache entry with `nil` as the key, leading to lots of errors.
2020-11-27 14:00:28 +00:00
Matt-Yorkley
3cba9a16aa Use ActionController::Base for Api::BaseController
It looks like ActionController::Metal does not play nicely with the big changes to controller responders: https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#responders
2020-11-27 14:00:28 +00:00
Matt-Yorkley
58350ed338 Set ActiveJob configs and convert WelcomeEnterpriseJob to new format
This needs to be done for all jobs.

Docs: https://guides.rubyonrails.org/v4.2/active_job_basics.html
2020-11-27 14:00:28 +00:00
Matt-Yorkley
54a4952dc5 Fix ForbiddenAttributesError on tag rules 2020-11-27 14:00:28 +00:00
Matt-Yorkley
34bfd877cc Fix #bulk_update in EnterprisesController 2020-11-27 14:00:28 +00:00
Matt-Yorkley
16cc0afe8f Replace removed method #retrieve_collector_from_mimes
https://apidock.com/rails/v4.1.8/ActionController/MimeResponds/retrieve_collector_from_mimes
2020-11-27 14:00:28 +00:00
Matt-Yorkley
ccaff08928 Re-add ForbiddenAttributesError debugging helper 2020-11-27 14:00:28 +00:00
Matt-Yorkley
91908a0e4c Switch from state_machine to state_machines gem
The old version is completely unmaintained and does not work with Rails 4.2
2020-11-27 14:00:28 +00:00
Matt-Yorkley
6b45208cf1 Define Capybara server
The server type now has to be set explicitly for Capybara
2020-11-27 14:00:28 +00:00
Matt-Yorkley
fb333c37e7 Fix Api controller setup for responders gem 2020-11-27 14:00:28 +00:00
Matt-Yorkley
3090cfa909 Add setup for responders gem 2020-11-27 14:00:28 +00:00
Matt-Yorkley
9205c85d4d Run rake db:migrate 2020-11-27 14:00:28 +00:00
Matt-Yorkley
ff9f6c3317 Remove foreigner gem
https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#foreign-key-support
2020-11-27 14:00:28 +00:00
Matt-Yorkley
25dd47e511 Add responders gem
https://guides.rubyonrails.org/upgrading_ruby_on_rails.html#responders
2020-11-27 14:00:28 +00:00
Matt-Yorkley
ece3e7aa69 Update gems to Rails 4.2 2020-11-27 14:00:28 +00:00
Luis Ramos
ff8d935699 Fix problem in enterprises controller 2020-11-27 13:59:46 +00:00
Luis Ramos
1d32ecab98 Fix spec by adding necessary references statement 2020-11-27 13:59:46 +00:00
Luis Ramos
ff17ced101 Fix enterprises spec by adding needed references statement 2020-11-27 13:59:46 +00:00
Luis Ramos
fa6cf0f281 Fix prod importer spec in rails 4.1 2020-11-27 13:59:46 +00:00
Luis Ramos
7e39d78733 Fix Long Method rubocop issue 2020-11-27 13:59:46 +00:00
Luis Ramos
0152b4da55 Fix rubocop issues 2020-11-27 13:59:46 +00:00
Luis Ramos
2a03e42f2a Update deep_munge patch to rails 4.1 where the code is now in ActionDispatch::Request::Utils 2020-11-27 13:59:46 +00:00
Matt-Yorkley
01a726d9bd Fix stubbing of stock totals
Recent changes to the way count_on_hand is summed in Spree::Stock::Quantifier mean the old method here will not work. Error:
```
  2) Spree::Variant#in_stock? when stock_items are not backorderable when stock_items out of stock return false if stock_items out of stock
     Failure/Error: expect(variant.in_stock?).to be_falsy

       expected: falsey value
            got: true
     # ./spec/models/spree/variant_spec.rb:241:in `block (5 levels) in <module:Spree>'
  ```
2020-11-27 13:59:46 +00:00
Matt-Yorkley
93fe8dbc5f Replace #scoped, which is now deprecated and removed in Rails 4.1 2020-11-27 13:59:46 +00:00
Matt-Yorkley
5c5a6361bf Fix nasty json encoding issue
The enterprise id returned by these json endpoints was being returned in *unicode* format, so where Angular was expecting a simple integer it was instead getting strings like: "\u0017"
2020-11-27 13:59:46 +00:00
Matt-Yorkley
0f2cbe8a52 Fix API exception response handling
For some reason when using `render text:` instead of `render json:` for this response, the status code being returned was 200 instead of the clearly explicitly defined 422 (:unprocessable_entity). I absolutely have no idea why!
2020-11-27 13:59:46 +00:00
Matt-Yorkley
f1002b953d Disable Javascript CSRF protection on EnterprisesController#check_permalink route
This route checks if an enterprise permalink is taken or not. Allowing the route to be accessed via Javascript without strict CSRF protection is reasonable. Fixes the following errors:

ActionController::InvalidCrossOriginRequest: Security warning: an embedded <script> tag on another site requested protected JavaScript. If you know what you're doing, go ahead and disable forgery protection on this action to permit cross-origin JavaScript embedding.
2020-11-27 13:59:46 +00:00
Luis Ramos
3ebc8145df Avoid calling update with nil values 2020-11-27 13:59:46 +00:00
Luis Ramos
edc1773676 Fix some calls to sum in reports code 2020-11-27 13:59:46 +00:00
Luis Ramos
6814eb663f Fix respond_with error 2020-11-27 13:59:46 +00:00
Luis Ramos
78cfcd905f Adapt more & and no & when using sum 2020-11-27 13:59:46 +00:00
Luis Ramos
9bbef16804 Converting all calls to ActiveRelation#sum to use a symbol with &
This is only applicable to database columns, if we are summing using a method in the model than the & is required!
2020-11-27 13:59:46 +00:00
Luis Ramos
974240fd4b Fix two sum calls in checkout helper 2020-11-27 13:59:46 +00:00
Luis Ramos
7472b7cc27 Fix sum call in quantifier 2020-11-27 13:59:46 +00:00
Eduardo
a8a933d73a change from render json to render plain due to template missing issue 2020-11-27 13:59:46 +00:00
Luis Ramos
bcd07e1791 Upgrade to rails 4.1 2020-11-27 13:59:46 +00:00
Luis Ramos
ecb29ec830 Add state machine patch to fix error with state machine
See here for details: https://github.com/pluginaweek/state_machine/issues/251#issuecomment-32133267
2020-11-27 13:59:46 +00:00
Luis Ramos
202aa3e5b7 Use reflections instead of, now gone, reflections 2020-11-27 13:59:46 +00:00
Luis Ramos
a05f43000a ActionView was extracted from ActionPack in rails 4.1 so we need to use ActionView 2020-11-27 13:59:46 +00:00
Luis Ramos
61708e5deb AbstractController::ViewPaths was moved to ActionView::ViewPaths in rails 4.1 2020-11-27 13:59:46 +00:00
Matt-Yorkley
27586d072d Merge pull request #6423 from openfoodfoundation/revert-6277-controllers
Revert "Move Spree::Admin::BaseController to Admin::BaseController"
2020-11-27 14:29:15 +01:00
Matt-Yorkley
3bfa903912 Revert "Move Spree::Admin::BaseController to Admin::BaseController" 2020-11-27 14:11:57 +01:00
Matt-Yorkley
0ba670b180 Ensure order is cleanly reset to cart state when redirecting to cart 2020-11-27 11:42:46 +00:00
Matt-Yorkley
c4cfc1dc05 Improve order test in paypal controller spec 2020-11-27 11:42:06 +00:00
Pau Pérez Fabregat
17957ed6c0 Merge pull request #6408 from openfoodfoundation/transifex
Transifex
2020-11-27 10:31:56 +01:00
Pau Pérez Fabregat
8b6a08457a Merge pull request #6293 from luisramos0/subs_debug
Add task to print Subscriptions debug info
2020-11-27 10:17:57 +01:00
Maikel
9e2a3d6973 Merge pull request #6277 from luisramos0/controllers
Move Spree::Admin::BaseController to Admin::BaseController
2020-11-27 16:13:55 +11:00
Icker
55b21310e4 Added introductory information for testing. 2020-11-25 09:44:02 -08:00
Transifex-Openfoodnetwork
1266a37ac5 Updating translations for config/locales/en_NZ.yml 2020-11-25 05:39:17 +11:00
Transifex-Openfoodnetwork
54feb2f57d Updating translations for config/locales/en_AU.yml 2020-11-24 07:31:32 +11:00
Transifex-Openfoodnetwork
e9eb90507e Updating translations for config/locales/ca.yml 2020-11-24 07:22:28 +11:00
Transifex-Openfoodnetwork
ee44159c83 Updating translations for config/locales/es.yml 2020-11-24 07:19:47 +11:00
Transifex-Openfoodnetwork
8861f5c6aa Updating translations for config/locales/ca.yml 2020-11-24 07:19:18 +11:00
Matt-Yorkley
b089404891 Merge pull request #6362 from coopdevs/remove-unused-truncate-html-gem
Remove unused truncate_html gem
2020-11-23 00:49:34 +01:00
Matt-Yorkley
2fa2a30c67 Add spec coverage, refactor, avoid double-render errors
👍
2020-11-22 18:37:31 +00:00
Matt-Yorkley
cabec7e73f Fix Rubocop warnings and tidy up 2020-11-22 18:02:54 +00:00
Matt-Yorkley
87df44764f Extract stock-check logic to controller concern and inject prior to final Paypal payment confirmation. 2020-11-22 18:02:52 +00:00
Andy Brett
8f25568530 Merge pull request #6390 from jhsu802701/qtest
SIMPLE: added scripts for running test suite in quiet mode
2020-11-20 12:15:04 -08:00
Andy Brett
b1b422b90e fix/silence rubocop styles 2020-11-20 10:41:31 -08:00
Andy Brett
85d99f3bf2 Merge branch 'master' into controllers 2020-11-20 08:12:03 -08:00
Andy Brett
c6b3a615f1 Merge pull request #6385 from jhsu802701/update_db_schema
SIMPLE: updated db/schema.rb with 'bundle exec rake db:migrate'
2020-11-20 08:03:27 -08:00
Matt-Yorkley
242c1a2715 Add new Paypal feature spec 2020-11-19 01:44:53 +00:00
Matt-Yorkley
21d67a0723 Extract some more paypal-specific test code to new helper 2020-11-19 01:44:38 +00:00
Jason Hsu
59b3bfa161 Added scripts for running test suite in quiet mode and updated docker/README.md 2020-11-18 16:25:03 -06:00
Matt-Yorkley
41a5787830 Extract paypal response stubbing to helper 2020-11-18 15:39:01 +00:00
Matt-Yorkley
010c1c799d Add some notes on paypal checkout flow 2020-11-18 14:55:29 +00:00
Matt-Yorkley
2faea65f82 Bring in Spree::PaypalController#confirm method
Original method from the gem. This handles the post-payment response from paypal.
2020-11-18 14:51:23 +00:00
Matt-Yorkley
dd8f139c1b Memoize Spree::PaypalController#payment_method
This gets called 4 or 5 times in a single request just to read basic attributes from the object. The query doesn't need to be repeated each time
2020-11-18 13:45:14 +00:00
Matt-Yorkley
6d0d4b5096 Bring in Spree::PaypalController#payment_method
Original method from the gem. Modified in preceding commit.
2020-11-18 13:45:13 +00:00
Jason Hsu
b85f8d4b45 Updated db/schema.rb with 'bundle exec rake db:migrate' 2020-11-16 18:23:00 -06:00
dependabot-preview[bot]
66799bad46 Bump webmock from 3.9.5 to 3.10.0
Bumps [webmock](https://github.com/bblimke/webmock) from 3.9.5 to 3.10.0.
- [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.9.5...v3.10.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-13 19:16:37 +00:00
Pau Perez
f9869d4360 Remove unused truncate_html gem
It seems that we don't use this gem in OFN. It was used in Spree in
https://github.com/openfoodfoundation/spree/blob/2-1-0-stable/core/app/helpers/spree/orders_helper.rb
to truncate the product description. We don't because we show it in
the product modal, and there's no trace of that helper method in our
codebase nor I see the gem used at all.
2020-11-11 13:18:23 +01:00
Matt-Yorkley
1cad631bdb Replace secret_token and update comments
`secret_token` is apparently still called directly in other places...
2020-11-11 01:30:52 +00:00
Matt-Yorkley
03d49c7987 Update secret key base
`secret_token` is no longer used in Rails 4+
2020-11-10 20:46:15 +00:00
Luis Ramos
c07215552e Add log entries to log 2020-11-02 20:59:57 +00:00
Luis Ramos
2b01c80c54 Add subs debug task that prints out basic info about a specific Order Cycle 2020-11-02 20:59:57 +00:00
Luis Ramos
fa77204e14 Adapt spec to the move of the controller, in prod the call to request.env['PATH_INFO'] will work correctly 2020-10-31 10:44:19 +00:00
Luis Ramos
af713385d8 Add frozen string literal 2020-10-31 10:16:37 +00:00
Luis Ramos
c9972189d0 Change usage of Spree::Admin::BaseController to Admin::BaseController 2020-10-31 09:56:59 +00:00
Luis Ramos
eb07a91acb Adapt code from Spree::Admin::BaseController to Admin::BaseController 2020-10-31 09:52:34 +00:00
Luis Ramos
66ba9ff73d Move Spree::Admin::BaseController to Admin::BaseController 2020-10-31 09:51:37 +00:00
Luis Ramos
dbd41e9d31 Use ruby 2.4 as github actions do not support ruby 2.3. 2020-10-13 10:31:26 +01:00
Luis Ramos
87327dcf57 Add brakeman config 2020-10-13 10:31:13 +01:00
125 changed files with 1764 additions and 1070 deletions

44
.github/workflows/brakeman-analysis.yml vendored Normal file
View File

@@ -0,0 +1,44 @@
# This workflow integrates Brakeman with GitHub's Code Scanning feature
# Brakeman is a static analysis security vulnerability scanner for Ruby on Rails applications
name: Brakeman Scan
# This section configures the trigger for the workflow. Feel free to customize depending on your convention
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
brakeman-scan:
name: Brakeman Scan
runs-on: ubuntu-latest
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout
uses: actions/checkout@v2
# Customize the ruby version depending on your needs
- name: Setup Ruby
uses: actions/setup-ruby@v1
with:
ruby-version: '2.7'
- name: Setup Brakeman
env:
BRAKEMAN_VERSION: '4.10' # SARIF support is provided in Brakeman version 4.10+
run: |
gem install brakeman --version $BRAKEMAN_VERSION
# Execute Brakeman CLI and generate a SARIF output with the security issues identified during the analysis
- name: Scan
continue-on-error: true
run: |
brakeman -f sarif -o output.sarif.json .
# Upload the SARIF file generated in the previous step
- name: Upload SARIF
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: output.sarif.json

19
Gemfile
View File

@@ -2,13 +2,14 @@ source 'https://rubygems.org'
ruby "2.3.7"
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
gem 'i18n', '~> 0.6.11'
gem 'i18n'
gem 'i18n-js', '~> 3.8.0'
gem 'rails', '~> 4.0.13'
gem 'rails-i18n', '~> 4.0'
gem 'rails', '~> 4.2'
gem 'rails-i18n'
gem 'rails_safe_tasks', '~> 1.0'
gem "activerecord-import"
gem 'responders', '~> 2.0'
gem "catalog", path: "./engines/catalog"
gem 'dfc_provider', path: './engines/dfc_provider'
@@ -21,14 +22,14 @@ gem 'pg', '~> 0.21.0'
gem 'acts_as_list', '= 0.3.0'
gem 'awesome_nested_set', '~> 3.2.1'
gem 'cancan', '~> 1.6.10'
gem 'ffaker', '~> 1.16'
gem 'ffaker'
gem 'highline', '2.0.3' # Necessary for the install generator
gem 'json', '>= 1.7.7'
gem 'money', '5.1.1'
gem 'json'
gem 'money', '< 6.1.0'
gem 'paranoia', '~> 2.0'
gem 'ransack', '~> 1.8.10'
gem 'state_machine', '1.2.0'
gem 'stringex', '~> 1.5.1'
gem 'state_machines-activerecord'
gem 'stringex', '~> 2.8.5'
gem 'spree_i18n', github: 'openfoodfoundation/spree_i18n', branch: '1-3-stable'
@@ -65,7 +66,6 @@ gem 'haml'
gem 'redcarpet'
gem 'sass'
gem 'sass-rails'
gem 'truncate_html', '0.9.2'
gem 'unicorn'
gem 'actionpack-action_caching'
@@ -91,7 +91,6 @@ gem 'combine_pdf'
gem 'wicked_pdf'
gem 'wkhtmltopdf-binary'
gem 'foreigner'
gem 'immigrant'
gem 'roo', '~> 2.8.3'

View File

@@ -55,33 +55,44 @@ GEM
remote: https://rubygems.org/
specs:
CFPropertyList (2.3.6)
actionmailer (4.0.13)
actionpack (= 4.0.13)
actionmailer (4.2.11.3)
actionpack (= 4.2.11.3)
actionview (= 4.2.11.3)
activejob (= 4.2.11.3)
mail (~> 2.5, >= 2.5.4)
actionpack (4.0.13)
activesupport (= 4.0.13)
builder (~> 3.1.0)
erubis (~> 2.7.0)
rack (~> 1.5.2)
rails-dom-testing (~> 1.0, >= 1.0.5)
actionpack (4.2.11.3)
actionview (= 4.2.11.3)
activesupport (= 4.2.11.3)
rack (~> 1.6)
rack-test (~> 0.6.2)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionpack-action_caching (1.2.1)
actionpack (>= 4.0.0)
actionview (4.2.11.3)
activesupport (= 4.2.11.3)
builder (~> 3.1)
erubis (~> 2.7.0)
rails-dom-testing (~> 1.0, >= 1.0.5)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
active_model_serializers (0.8.4)
activemodel (>= 3.0)
activejob (4.2.11.3)
activesupport (= 4.2.11.3)
globalid (>= 0.3.0)
activemerchant (1.78.0)
activesupport (>= 3.2.14, < 6.x)
builder (>= 2.1.2, < 4.0.0)
i18n (>= 0.6.9)
nokogiri (~> 1.4)
activemodel (4.0.13)
activesupport (= 4.0.13)
builder (~> 3.1.0)
activerecord (4.0.13)
activemodel (= 4.0.13)
activerecord-deprecated_finders (~> 1.0.2)
activesupport (= 4.0.13)
arel (~> 4.0.0)
activerecord-deprecated_finders (1.0.4)
activemodel (4.2.11.3)
activesupport (= 4.2.11.3)
builder (~> 3.1)
activerecord (4.2.11.3)
activemodel (= 4.2.11.3)
activesupport (= 4.2.11.3)
arel (~> 6.0)
activerecord-import (1.0.7)
activerecord (>= 3.2)
activerecord-postgresql-adapter (0.0.1)
@@ -92,18 +103,20 @@ GEM
multi_json (~> 1.11, >= 1.11.2)
rack (>= 1.5.2, < 3)
railties (>= 4.0)
activesupport (4.0.13)
i18n (~> 0.6, >= 0.6.9)
minitest (~> 4.2)
multi_json (~> 1.3)
thread_safe (~> 0.1)
tzinfo (~> 0.3.37)
activesupport (4.2.11.3)
i18n (~> 0.7)
minitest (~> 5.1)
thread_safe (~> 0.3, >= 0.3.4)
tzinfo (~> 1.1)
acts-as-taggable-on (4.0.0)
activerecord (>= 4.0)
acts_as_list (0.3.0)
activerecord (>= 3.0)
addressable (2.7.0)
public_suffix (>= 2.0.2, < 5.0)
aliyun-sdk (0.8.0)
nokogiri (~> 1.6)
rest-client (~> 2.0)
andand (1.3.3)
angular-rails-templates (0.3.0)
railties (>= 3.1)
@@ -111,7 +124,7 @@ GEM
tilt
angularjs-file-upload-rails (2.4.1)
angularjs-rails (1.5.5)
arel (4.0.2)
arel (6.0.4)
ast (2.4.0)
atomic (1.1.101)
awesome_nested_set (3.2.1)
@@ -122,10 +135,10 @@ GEM
aws-sdk-v1 (1.67.0)
json (~> 1.4)
nokogiri (~> 1)
bcrypt (3.1.13)
bcrypt (3.1.16)
bugsnag (6.18.0)
concurrent-ruby (~> 1.0)
builder (3.1.4)
builder (3.2.4)
byebug (11.0.1)
cancan (1.6.10)
capybara (2.18.0)
@@ -137,7 +150,7 @@ GEM
xpath (>= 2.0, < 4.0)
childprocess (3.0.0)
chronic (0.10.2)
chunky_png (1.3.11)
chunky_png (1.3.14)
climate_control (0.2.0)
cocaine (0.5.8)
climate_control (>= 0.0.3, < 1.0)
@@ -169,6 +182,7 @@ GEM
sprockets (< 4.0)
concurrent-ruby (1.1.7)
crack (0.4.4)
crass (1.0.6)
css_parser (1.7.1)
addressable
daemons (1.3.1)
@@ -202,24 +216,26 @@ GEM
devise (>= 2.1.0)
devise-token_authenticatable (0.4.10)
devise (>= 3.5.2, < 4.0.0)
diff-lcs (1.3)
diff-lcs (1.4.4)
docile (1.3.2)
domain_name (0.5.20190701)
unf (>= 0.0.5, < 1.0.0)
dry-inflector (0.1.2)
erubis (2.7.0)
eventmachine (1.2.7)
excon (0.71.1)
excon (0.78.0)
execjs (2.7.0)
factory_bot (4.10.0)
activesupport (>= 3.0.0)
factory_bot_rails (4.10.0)
factory_bot (~> 4.10.0)
railties (>= 3.0.0)
faraday (1.0.0)
faraday (1.0.1)
multipart-post (>= 1.2, < 3)
ffaker (1.32.1)
ffi (1.12.2)
figaro (1.1.1)
thor (~> 0.14)
ffaker (2.11.0)
ffi (1.13.1)
figaro (1.2.0)
thor (>= 0.14.0, < 2)
fission (0.5.0)
CFPropertyList (~> 2.2)
fog (1.41.0)
@@ -256,7 +272,8 @@ GEM
fog-xml (~> 0.1.1)
ipaddress (~> 0.5)
json (>= 1.8, < 2.0)
fog-aliyun (0.3.5)
fog-aliyun (0.3.19)
aliyun-sdk (~> 0.8.0)
fog-core
fog-json
ipaddress (~> 0.8)
@@ -302,7 +319,7 @@ GEM
fog-core
fog-json
fog-xml
fog-internet-archive (0.0.1)
fog-internet-archive (0.0.2)
fog-core
fog-json
fog-xml
@@ -359,7 +376,7 @@ GEM
fog-voxel (0.1.0)
fog-core
fog-xml
fog-vsphere (3.2.1)
fog-vsphere (3.4.0)
fog-core
rbvmomi (>= 1.9, < 3)
fog-xenserver (1.0.0)
@@ -369,8 +386,6 @@ GEM
fog-xml (0.1.3)
fog-core
nokogiri (>= 1.5.11, < 2.0.0)
foreigner (1.7.4)
activerecord (>= 3.0.0)
formatador (0.2.5)
foundation-icons-sass-rails (3.0.0)
railties (>= 3.1.1)
@@ -382,8 +397,10 @@ GEM
rspec-core (~> 3.0)
ruby-progressbar (~> 1.4)
geocoder (1.6.4)
get_process_mem (0.2.5)
get_process_mem (0.2.7)
ffi (~> 1.0)
globalid (0.4.2)
activesupport (>= 4.2.0)
gmaps4rails (2.1.2)
haml (5.2.0)
temple (>= 0.8.0)
@@ -391,7 +408,11 @@ GEM
hashdiff (1.0.1)
highline (2.0.3)
hike (1.2.3)
i18n (0.6.11)
http-accept (1.7.0)
http-cookie (1.0.3)
domain_name (~> 0.5)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
i18n-js (3.8.0)
i18n (>= 0.6.6)
immigrant (0.3.6)
@@ -422,6 +443,9 @@ GEM
letter_opener (1.7.0)
launchy (~> 2.2)
libv8 (7.3.492.27.1)
loofah (2.7.0)
crass (~> 1.0.2)
nokogiri (>= 1.5.9)
mail (2.7.1)
mini_mime (>= 0.1.1)
method_source (0.9.2)
@@ -432,15 +456,17 @@ GEM
mini_portile2 (2.4.0)
mini_racer (0.2.15)
libv8 (> 7.3)
minitest (4.7.5)
money (5.1.1)
i18n (~> 0.6.0)
minitest (5.14.2)
money (5.0.0)
i18n (~> 0.4)
json
msgpack (1.3.3)
multi_json (1.15.0)
multi_xml (0.6.0)
multipart-post (2.1.1)
netrc (0.11.0)
newrelic_rpm (3.18.1.330)
nokogiri (1.10.9)
nokogiri (1.10.10)
mini_portile2 (~> 2.4.0)
oauth2 (1.4.4)
faraday (>= 0.8, < 2.0)
@@ -449,7 +475,7 @@ GEM
multi_xml (~> 0.5)
rack (>= 1.2, < 3)
oj (3.10.8)
optimist (3.0.0)
optimist (3.0.1)
orm_adapter (0.5.0)
paper_trail (7.1.3)
activerecord (>= 4.0, < 5.2)
@@ -479,7 +505,7 @@ GEM
byebug (~> 11.0)
pry (~> 0.10)
public_suffix (4.0.6)
rack (1.5.5)
rack (1.6.13)
rack-mini-profiler (2.0.2)
rack (>= 1.2.0)
rack-protection (1.5.5)
@@ -489,21 +515,32 @@ GEM
rack
rack-test (0.6.3)
rack (>= 1.0)
rails (4.0.13)
actionmailer (= 4.0.13)
actionpack (= 4.0.13)
activerecord (= 4.0.13)
activesupport (= 4.0.13)
rails (4.2.11.3)
actionmailer (= 4.2.11.3)
actionpack (= 4.2.11.3)
actionview (= 4.2.11.3)
activejob (= 4.2.11.3)
activemodel (= 4.2.11.3)
activerecord (= 4.2.11.3)
activesupport (= 4.2.11.3)
bundler (>= 1.3.0, < 2.0)
railties (= 4.0.13)
sprockets-rails (~> 2.0)
rails-i18n (4.0.5)
i18n (~> 0.6)
railties (= 4.2.11.3)
sprockets-rails
rails-deprecated_sanitizer (1.0.3)
activesupport (>= 4.2.0.alpha)
rails-dom-testing (1.0.9)
activesupport (>= 4.2.0, < 5.0)
nokogiri (~> 1.6)
rails-deprecated_sanitizer (>= 1.0.1)
rails-html-sanitizer (1.3.0)
loofah (~> 2.3)
rails-i18n (4.0.9)
i18n (~> 0.7)
railties (~> 4.0)
rails_safe_tasks (1.0.0)
railties (4.0.13)
actionpack (= 4.0.13)
activesupport (= 4.0.13)
railties (4.2.11.3)
actionpack (= 4.2.11.3)
activesupport (= 4.2.11.3)
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rainbow (3.0.0)
@@ -514,10 +551,10 @@ GEM
activerecord (>= 3.0, < 5.2)
activesupport (>= 3.0, < 5.2)
i18n
rb-fsevent (0.10.3)
rb-fsevent (0.10.4)
rb-inotify (0.10.1)
ffi (~> 1.0)
rbvmomi (2.2.0)
rbvmomi (2.4.1)
builder (~> 3.0)
json (>= 1.8)
nokogiri (~> 1.5)
@@ -525,41 +562,47 @@ GEM
redcarpet (3.5.0)
request_store (1.5.0)
rack (>= 1.4)
responders (1.1.2)
railties (>= 3.2, < 4.2)
responders (2.4.1)
actionpack (>= 4.2.0, < 6.0)
railties (>= 4.2.0, < 6.0)
rest-client (2.1.0)
http-accept (>= 1.7.0, < 2.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
rexml (3.2.4)
roadie (3.4.0)
roadie (3.5.1)
css_parser (~> 1.4)
nokogiri (~> 1.5)
nokogiri (~> 1.8)
roadie-rails (1.3.0)
railties (>= 3.0, < 5.3)
roadie (~> 3.1)
roo (2.8.3)
nokogiri (~> 1)
rubyzip (>= 1.3.0, < 3.0.0)
rspec (3.9.0)
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
rspec-mocks (~> 3.9.0)
rspec-core (3.9.1)
rspec-support (~> 3.9.1)
rspec-expectations (3.9.0)
rspec (3.10.0)
rspec-core (~> 3.10.0)
rspec-expectations (~> 3.10.0)
rspec-mocks (~> 3.10.0)
rspec-core (3.10.0)
rspec-support (~> 3.10.0)
rspec-expectations (3.10.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-mocks (3.9.1)
rspec-support (~> 3.10.0)
rspec-mocks (3.10.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.9.0)
rspec-rails (3.9.1)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.9.0)
rspec-expectations (~> 3.9.0)
rspec-mocks (~> 3.9.0)
rspec-support (~> 3.9.0)
rspec-support (~> 3.10.0)
rspec-rails (4.0.1)
actionpack (>= 4.2)
activesupport (>= 4.2)
railties (>= 4.2)
rspec-core (~> 3.9)
rspec-expectations (~> 3.9)
rspec-mocks (~> 3.9)
rspec-support (~> 3.9)
rspec-retry (0.6.2)
rspec-core (> 3.3)
rspec-support (3.9.2)
rspec-support (3.10.0)
rswag (2.3.1)
rswag-api (= 2.3.1)
rswag-specs (= 2.3.1)
@@ -601,8 +644,8 @@ GEM
selenium-webdriver (3.142.7)
childprocess (>= 0.5, < 4.0)
rubyzip (>= 1.2.2)
shoulda-matchers (3.1.3)
activesupport (>= 4.0.0)
shoulda-matchers (4.0.1)
activesupport (>= 4.2.0)
simplecov (0.17.1)
docile (~> 1.1)
json (>= 1.8, < 3)
@@ -624,21 +667,30 @@ GEM
actionpack (>= 3.0)
activesupport (>= 3.0)
sprockets (>= 2.8, < 4.0)
state_machine (1.2.0)
stringex (1.5.1)
stripe (5.25.0)
state_machines (0.5.0)
state_machines-activemodel (0.7.1)
activemodel (>= 4.1)
state_machines (>= 0.5.0)
state_machines-activerecord (0.6.0)
activerecord (>= 4.1)
state_machines-activemodel (>= 0.5.0)
stringex (2.8.5)
stripe (5.28.0)
temple (0.8.2)
test-prof (0.7.5)
test-unit (3.3.6)
test-unit (3.3.7)
power_assert
thor (0.20.3)
thread_safe (0.3.6)
tilt (1.4.1)
timecop (0.9.2)
truncate_html (0.9.2)
tzinfo (0.3.57)
tzinfo (1.2.8)
thread_safe (~> 0.1)
uglifier (4.2.0)
execjs (>= 0.3.0, < 3)
unf (0.1.4)
unf_ext
unf_ext (0.0.7.7)
unicode-display_width (1.7.0)
unicorn (5.7.0)
kgio (~> 2.6)
@@ -655,7 +707,7 @@ GEM
nokogiri (~> 1.6)
rubyzip (>= 1.3.0)
selenium-webdriver (>= 3.0, < 4.0)
webmock (3.9.5)
webmock (3.10.0)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff (>= 0.4.0, < 2.0.0)
@@ -666,8 +718,8 @@ GEM
wkhtmltopdf-binary (0.12.5)
xml-simple (1.1.5)
xmlrpc (0.3.0)
xpath (2.1.0)
nokogiri (~> 1.3)
xpath (3.2.0)
nokogiri (~> 1.8)
PLATFORMS
ruby
@@ -712,9 +764,8 @@ DEPENDENCIES
dfc_provider!
eventmachine (>= 1.2.3)
factory_bot_rails (= 4.10.0)
ffaker (~> 1.16)
ffaker
figaro
foreigner
foundation-icons-sass-rails
foundation-rails (= 5.5.2.1)
fuubar (~> 2.5.0)
@@ -722,20 +773,20 @@ DEPENDENCIES
gmaps4rails
haml
highline (= 2.0.3)
i18n (~> 0.6.11)
i18n
i18n-js (~> 3.8.0)
immigrant
jquery-migrate-rails
jquery-rails (= 3.1.5)
jquery-ui-rails (~> 4.2)
json (>= 1.7.7)
json
json_spec (~> 1.1.4)
jwt (~> 2.2)
kaminari (~> 0.17.0)
knapsack
letter_opener (>= 1.4.1)
mini_racer (= 0.2.15)
money (= 5.1.1)
money (< 6.1.0)
newrelic_rpm (~> 3.0)
oauth2 (~> 1.4.4)
ofn-qz!
@@ -750,11 +801,12 @@ DEPENDENCIES
rack-mini-profiler (< 3.0.0)
rack-rewrite
rack-ssl
rails (~> 4.0.13)
rails-i18n (~> 4.0)
rails (~> 4.2)
rails-i18n
rails_safe_tasks (~> 1.0)
ransack (~> 1.8.10)
redcarpet
responders (~> 2.0)
roadie-rails (~> 1.3.0)
roo (~> 2.8.3)
rspec-rails (>= 3.5.2)
@@ -772,13 +824,12 @@ DEPENDENCIES
spree_paypal_express!
spring
spring-commands-rspec
state_machine (= 1.2.0)
stringex (~> 1.5.1)
state_machines-activerecord
stringex (~> 2.8.5)
stripe
test-prof
test-unit (~> 3.3)
timecop
truncate_html (= 0.9.2)
uglifier (>= 1.0.3)
unicorn
unicorn-rails

View File

@@ -33,7 +33,9 @@ We also have a [Super Admin Guide][super-admin-guide] to help with configuration
## Testing
We use [BrowserStack](https://www.browserstack.com/) as a manual testing tool. BrowserStack provides open source projects with unlimited and free of charge accounts. A big thanks to them!
If you'd like to help out with testing, please introduce yourself on the #testing channel on [Slack][slack-invite] and download the [ZenHub browser extension][zenhub] to view the development pipeline.
We use [BrowserStack](https://www.browserstack.com/) as a manual testing tool. BrowserStack provides open source projects with unlimited and free of charge accounts. A big thanks to them!
## Licence
@@ -45,3 +47,4 @@ Copyright (c) 2012 - 2020 Open Food Foundation, released under the AGPL licence.
[ofn-install]: https://github.com/openfoodfoundation/ofn-install
[super-admin-guide]: https://ofn-user-guide.gitbook.io/ofn-super-admin-guide
[welcome-dev]: https://github.com/openfoodfoundation/openfoodnetwork/projects/27
[zenhub]: https://www.zenhub.com/extension

View File

@@ -6,7 +6,7 @@ Darkswarm.filter "localizeCurrency", (currencyConfig)->
# Set decimal points, 2 or 0 if hide_cents.
decimals = if currencyConfig.hide_cents == "true" then 0 else 2
# Set format if the currency symbol should come after the number, otherwise (default) use the locale setting.
format = if currencyConfig.symbol_position == "after" then "%n %u" else undefined
format = if currencyConfig.symbol_position == "after" then "%n%u" else undefined
# We need to use parseFloat as the amount should come in as a string.
amount = parseFloat(amount)

View File

@@ -14,8 +14,9 @@
{{'hubs_delivery' | t}}
.row
.columns.small-12
%a.cta-hub{"ng-href" => "{{::enterprise.path}}", "ng-attr-target" => "{{ embedded_layout ? '_blank' : undefined}}",
%a.cta-hub{"ng-href" => "{{::enterprise.path}}#/shop", "ng-attr-target" => "{{ embedded_layout ? '_blank' : undefined}}",
"ng-class" => "{primary: enterprise.active, secondary: !enterprise.active}",
"ng-click" => "$close()",
"ofn-change-hub" => "enterprise"}
.hub-name{"ng-bind" => "::enterprise.name"}
%span{"ng-if" => "::enterprise.active"} ({{'maps_open' | t}})

View File

@@ -12,8 +12,9 @@
.row
.columns.small-12
%a.cta-hub{"ng-repeat" => "hub in enterprise.hubs | filter:{id: '!'+enterprise.id} | orderBy:'-active'",
"ng-href" => "{{::hub.path}}", "ofn-empties-cart" => "hub",
"ng-class" => "::{primary: hub.active, secondary: !hub.active}"}
"ng-href" => "{{::hub.path}}#/shop", "ofn-empties-cart" => "hub",
"ng-class" => "::{primary: hub.active, secondary: !hub.active}",
"ng-click" => "$close()"}
.hub-name{"ng-bind" => "::hub.name"}
%span{"ng-if" => "::hub.active"} ({{'maps_open' | t}})
%span{"ng-if" => "::!hub.active"} ({{'maps_closed' | t}})

View File

@@ -59,6 +59,7 @@
// Variant price
.variant-price {
white-space: nowrap;
@include breakpoint(phablet) {
padding-left: 1rem;
}

View File

@@ -81,14 +81,14 @@ module Admin
end
def bulk_update
@enterprise_set = EnterpriseSet.new(collection, params[:enterprise_set])
@enterprise_set = EnterpriseSet.new(collection, bulk_params)
if @enterprise_set.save
flash[:success] = I18n.t(:enterprise_bulk_update_success_notice)
redirect_to main_app.admin_enterprises_path
else
touched_enterprises = @enterprise_set.collection.select(&:changed?)
@enterprise_set.collection.select! { |e| touched_enterprises.include? e }
@enterprise_set.collection.to_a.select! { |e| touched_enterprises.include? e }
flash[:error] = I18n.t(:enterprise_bulk_update_error)
render :index
end
@@ -214,7 +214,8 @@ module Admin
rule = @object.tag_rules.find_by(id: attrs.delete(:id)) ||
attrs[:type].constantize.new(enterprise: @object)
create_calculator_for(rule, attrs) if rule.type == "TagRule::DiscountOrder" && rule.calculator.nil?
rule.update(attrs)
rule.update(attrs.permit(PermittedAttributes::TagRules.attributes))
end
end
end
@@ -319,6 +320,12 @@ module Admin
PermittedAttributes::Enterprise.new(params).call
end
def bulk_params
params.require(:enterprise_set).permit(
collection_attributes: PermittedAttributes::Enterprise.attributes
)
end
# Used in ResourceController#create
def permitted_resource_params
enterprise_params

View File

@@ -91,7 +91,7 @@ module Admin
# Send notifications to all producers who are part of the order cycle
def notify_producers
Delayed::Job.enqueue OrderCycleNotificationJob.new(params[:id].to_i)
OrderCycleNotificationJob.perform_later params[:id].to_i
redirect_to main_app.admin_order_cycles_path,
notice: I18n.t(:order_cycles_email_to_producers_notice)

View File

@@ -5,11 +5,11 @@ require "spree/core/controller_helpers/ssl"
module Api
class BaseController < ActionController::Metal
include ActionController::StrongParameters
include ActionController::RespondWith
include Spree::Api::ControllerSetup
include Spree::Core::ControllerHelpers::SSL
include ::ActionController::Head
respond_to :json
include ::ActionController::ConditionalGet
attr_accessor :current_api_user
@@ -73,7 +73,7 @@ module Api
end
def error_during_processing(exception)
render(text: { exception: exception.message }.to_json,
render(json: { exception: exception.message },
status: :unprocessable_entity) && return
end

View File

@@ -15,7 +15,7 @@ module Api
@enterprise = Enterprise.new(enterprise_params)
if @enterprise.save
@enterprise.user_ids = user_ids
render text: @enterprise.id, status: :created
render json: @enterprise.id, status: :created
else
invalid_resource!(@enterprise)
end
@@ -26,7 +26,7 @@ module Api
authorize! :update, @enterprise
if @enterprise.update(enterprise_params)
render text: @enterprise.id, status: :ok
render json: @enterprise.id, status: :ok
else
invalid_resource!(@enterprise)
end

View File

@@ -20,7 +20,7 @@ module Api
search_params
).products_json
render json: products
render plain: products, content_type: "application/json"
rescue ProductsRenderer::NoProducts
render_no_products
end
@@ -31,13 +31,15 @@ module Api
where(spree_products: { id: distributed_products }).
select('DISTINCT spree_taxons.*')
render json: ActiveModel::ArraySerializer.new(taxons, each_serializer: Api::TaxonSerializer)
render plain: ActiveModel::ArraySerializer.new(
taxons, each_serializer: Api::TaxonSerializer
).to_json, content_type: "application/json"
end
def properties
render json: ActiveModel::ArraySerializer.new(
render plain: ActiveModel::ArraySerializer.new(
product_properties | producer_properties, each_serializer: Api::PropertySerializer
)
).to_json, content_type: "application/json"
end
private

View File

@@ -145,7 +145,7 @@ module Api
end
def query_params_with_defaults
params[:q].to_h.reverse_merge(s: 'created_at desc')
(params[:q] || {}).reverse_merge(s: 'created_at desc')
end
def pagination_data(results)

View File

@@ -1,7 +1,13 @@
# frozen_string_literal: true
require "application_responder"
require 'open_food_network/referer_parser'
require_dependency 'spree/authentication_helpers'
class ApplicationController < ActionController::Base
self.responder = ApplicationResponder
respond_to :html
protect_from_forgery
prepend_before_action :restrict_iframes
@@ -10,6 +16,12 @@ class ApplicationController < ActionController::Base
include EnterprisesHelper
include Spree::AuthenticationHelpers
# Helper for debugging strong_parameters
rescue_from ActiveModel::ForbiddenAttributesError, with: :print_params
def print_params
raise ActiveModel::ForbiddenAttributesError, params.to_s
end
def redirect_to(options = {}, response_status = {})
::Rails.logger.error("Redirected by #{begin
caller(1).first

View File

@@ -1,5 +1,3 @@
require 'spree/core/controller_helpers/order'
class CartController < BaseController
before_action :check_authorization

View File

@@ -5,6 +5,7 @@ require 'open_food_network/address_finder'
class CheckoutController < Spree::StoreController
layout 'darkswarm'
include OrderStockCheck
include CheckoutHelper
include OrderCyclesHelper
include EnterprisesHelper
@@ -24,7 +25,7 @@ class CheckoutController < Spree::StoreController
before_action :ensure_order_not_completed
before_action :ensure_checkout_allowed
before_action :ensure_sufficient_stock_lines
before_action :handle_insufficient_stock
before_action :associate_user
before_action :check_authorization
@@ -77,13 +78,6 @@ class CheckoutController < Spree::StoreController
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 load_order
@order = current_order

View File

@@ -0,0 +1,18 @@
# frozen_string_literal: true
module OrderStockCheck
extend ActiveSupport::Concern
def handle_insufficient_stock
return if sufficient_stock?
flash[:error] = Spree.t(:inventory_error_flash_for_insufficient_quantity)
redirect_to main_app.cart_path
end
private
def sufficient_stock?
@sufficient_stock ||= @order.insufficient_stock_lines.blank?
end
end

View File

@@ -6,6 +6,8 @@ class EnterprisesController < BaseController
include OrderCyclesHelper
include SerializerHelper
protect_from_forgery except: :check_permalink
# These prepended filters are in the reverse order of execution
prepend_before_action :set_order_cycles, :require_distributor_chosen, :reset_order, only: :shop

View File

@@ -43,7 +43,7 @@ module Spree
end
def update
unless @order.update(order_params) && @order.line_items.present?
unless order_params.present? && @order.update(order_params) && @order.line_items.present?
if @order.line_items.empty?
@order.errors.add(:line_items, Spree.t('errors.messages.blank'))
end

View File

@@ -179,7 +179,7 @@ module Spree
end
def bulk_index_query(params)
params[:filters].to_h.merge(page: params[:page], per_page: params[:per_page])
(params[:filters] || {}).merge(page: params[:page], per_page: params[:per_page])
end
def load_form_data

View File

@@ -1,6 +1,3 @@
require 'spree/core/controller_helpers/order'
require 'spree/core/controller_helpers/auth'
module Spree
class OrdersController < Spree::StoreController
include OrderCyclesHelper

View File

@@ -1,6 +1,8 @@
# frozen_string_literal: true
Spree::PaypalController.class_eval do
include OrderStockCheck
before_action :enable_embedded_shopfront
before_action :destroy_orphaned_paypal_payments, only: :confirm
after_action :reset_order_when_complete, only: :confirm
@@ -40,6 +42,9 @@ Spree::PaypalController.class_eval do
begin
pp_response = provider.set_express_checkout(pp_request)
if pp_response.success?
# At this point Paypal has *provisionally* accepted that the payment can now be placed,
# and the user will be redirected to a Paypal payment page. On completion, the user is
# sent back and the response is handled in the #confirm action in this controller.
redirect_to provider.express_checkout_url(pp_response, useraction: 'commit')
else
flash[:error] = Spree.t('flash.generic_error', scope: 'paypal', reasons: pp_response.errors.map(&:long_message).join(" "))
@@ -51,6 +56,32 @@ Spree::PaypalController.class_eval do
end
end
def confirm
@order = current_order || raise(ActiveRecord::RecordNotFound)
# At this point the user has come back from the Paypal form, and we get one
# last chance to interact with the payment process before the money moves...
return reset_to_cart unless sufficient_stock?
@order.payments.create!({
source: Spree::PaypalExpressCheckout.create({
token: params[:token],
payer_id: params[:PayerID]
}),
amount: @order.total,
payment_method: payment_method
})
@order.next
if @order.complete?
flash.notice = Spree.t(:order_processed_successfully)
flash[:commerce_tracking] = "nothing special"
session[:order_id] = nil
redirect_to completion_route(@order)
else
redirect_to checkout_state_path(@order.state)
end
end
def cancel
flash[:notice] = Spree.t('flash.cancel', scope: 'paypal')
redirect_to main_app.checkout_path
@@ -66,6 +97,10 @@ Spree::PaypalController.class_eval do
private
def payment_method
@payment_method ||= Spree::PaymentMethod.find(params[:payment_method_id])
end
def permit_parameters!
params.permit(:token, :payment_method_id, :PayerID)
end
@@ -79,6 +114,11 @@ Spree::PaypalController.class_eval do
end
end
def reset_to_cart
OrderCheckoutRestart.new(@order).call
handle_insufficient_stock
end
# See #1074 and #1837 for more detail on why we need this
# An 'orphaned' Spree::Payment is created for every call to CheckoutController#update
# for orders that are processed using a Spree::Gateway::PayPalExpress payment method

View File

@@ -18,7 +18,9 @@ module CheckoutHelper
enterprise_fee_adjustments = adjustments.select { |a| a.originator_type == 'EnterpriseFee' && a.source_type != 'Spree::LineItem' }
adjustments.reject! { |a| a.originator_type == 'EnterpriseFee' && a.source_type != 'Spree::LineItem' }
unless exclude.include? :admin_and_handling
adjustments << Spree::Adjustment.new(label: I18n.t(:orders_form_admin), amount: enterprise_fee_adjustments.sum(&:amount))
adjustments << Spree::Adjustment.new(
label: I18n.t(:orders_form_admin), amount: enterprise_fee_adjustments.map(&:amount).sum
)
end
adjustments
@@ -26,7 +28,7 @@ module CheckoutHelper
def display_checkout_admin_and_handling_adjustments_total_for(order)
adjustments = order.adjustments.eligible.where('originator_type = ? AND source_type != ? ', 'EnterpriseFee', 'Spree::LineItem')
Spree::Money.new adjustments.sum(&:amount), currency: order.currency
Spree::Money.new adjustments.map(&:amount).sum, currency: order.currency
end
def checkout_line_item_adjustments(order)
@@ -34,7 +36,7 @@ module CheckoutHelper
end
def checkout_subtotal(order)
order.item_total + checkout_line_item_adjustments(order).sum(&:amount)
order.item_total + checkout_line_item_adjustments(order).map(&:amount).sum
end
def display_checkout_subtotal(order)

View File

@@ -1,21 +0,0 @@
module HtmlHelper
def strip_html(html)
strip_surrounding_whitespace substitute_entities strip_tags add_linebreaks html
end
def substitute_entities(html)
html.andand.gsub(/&nbsp;/i, ' ').andand.gsub(/&amp;/i, '&')
end
def add_linebreaks(html)
# I know Cthulu is coming for me. Forgive me.
# http://stackoverflow.com/a/1732454/2720566
html.
andand.gsub(%r{</h[^>]>|</p>|</div>}, "\\1\n\n").
andand.gsub(/<br[^>]*>/, "\\1\n")
end
def strip_surrounding_whitespace(html)
html.andand.strip
end
end

View File

@@ -0,0 +1,25 @@
# frozen_string_literal: true
class BulkInvoiceJob < ActiveJob::Base
def perform(order_ids, filepath)
pdf = CombinePDF.new
orders_from(order_ids).each do |order|
invoice = renderer.render_to_string(order)
pdf << CombinePDF.parse(invoice)
end
pdf.save filepath
end
private
def orders_from(order_ids)
Spree::Order.where(id: order_ids).order("completed_at DESC")
end
def renderer
@renderer ||= InvoiceRenderer.new
end
end

View File

@@ -1,5 +1,7 @@
ConfirmOrderJob = Struct.new(:order_id) do
def perform
# frozen_string_literal: true
class ConfirmOrderJob < ActiveJob::Base
def perform(order_id)
Spree::OrderMailer.confirm_email_for_customer(order_id).deliver
Spree::OrderMailer.confirm_email_for_shop(order_id).deliver
end

View File

@@ -1,5 +1,7 @@
ConfirmSignupJob = Struct.new(:user_id) do
def perform
# frozen_string_literal: true
class ConfirmSignupJob < ActiveJob::Base
def perform(user_id)
user = Spree::User.find user_id
Spree::UserMailer.signup_confirmation(user).deliver
end

View File

@@ -1,6 +1,8 @@
# frozen_string_literal: true
# Delivers an email with a report of the order cycle to each of its suppliers
OrderCycleNotificationJob = Struct.new(:order_cycle_id) do
def perform
class OrderCycleNotificationJob < ActiveJob::Base
def perform(order_cycle_id)
order_cycle = OrderCycle.find(order_cycle_id)
order_cycle.suppliers.each do |supplier|
ProducerMailer.order_cycle_report(supplier, order_cycle).deliver

View File

@@ -1,5 +1,7 @@
WelcomeEnterpriseJob = Struct.new(:enterprise_id) do
def perform
# frozen_string_literal: true
class WelcomeEnterpriseJob < ActiveJob::Base
def perform(enterprise_id)
enterprise = Enterprise.find enterprise_id
EnterpriseMailer.welcome(enterprise).deliver
end

View File

@@ -2,7 +2,6 @@
module Spree
class OrderMailer < BaseMailer
helper HtmlHelper
helper ::CheckoutHelper
helper SpreeCurrencyHelper
helper Spree::Admin::PaymentsHelper

View File

@@ -9,7 +9,7 @@ module ApiActionCaching
included do
include ActionController::Caching
include ActionController::Caching::Actions
include AbstractController::Layouts
include ActionView::Layouts
# These configs are not assigned to the controller automatically with ActionController::Metal
self.cache_store = Rails.configuration.cache_store

View File

@@ -132,7 +132,7 @@ class Enterprise < ActiveRecord::Base
where(nil)
end
}
scope :is_primary_producer, -> { where(is_primary_producer: true) }
scope :is_primary_producer, -> { where("enterprises.is_primary_producer IS TRUE") }
scope :is_distributor, -> { where('sells != ?', 'none') }
scope :is_hub, -> { where(sells: 'any') }
scope :supplying_variant_in, lambda { |variants|
@@ -400,7 +400,7 @@ class Enterprise < ActiveRecord::Base
end
def send_welcome_email
Delayed::Job.enqueue WelcomeEnterpriseJob.new(id)
WelcomeEnterpriseJob.perform_later(id)
end
def strip_url(url)

View File

@@ -178,7 +178,7 @@ module Spree
end
def included_tax
adjustments.included_tax.sum(&:included_tax)
adjustments.included_tax.sum(:included_tax)
end
def tax_rates

View File

@@ -466,7 +466,7 @@ module Spree
def deliver_order_confirmation_email
return if subscription.present?
Delayed::Job.enqueue ConfirmOrderJob.new(id)
ConfirmOrderJob.perform_later(id)
end
# Helper methods for checkout steps
@@ -729,15 +729,15 @@ module Spree
end
def shipping_tax
adjustments(:reload).shipping.sum(&:included_tax)
adjustments(:reload).shipping.sum(:included_tax)
end
def enterprise_fee_tax
adjustments(:reload).enterprise_fee.sum(&:included_tax)
adjustments(:reload).enterprise_fee.sum(:included_tax)
end
def total_tax
(adjustments + price_adjustments).sum(&:included_tax)
(adjustments.to_a + price_adjustments.to_a).sum(&:included_tax)
end
def price_adjustments

View File

@@ -34,7 +34,7 @@ module Spree
klass = self
# To avoid a ton of warnings when the state machine is re-defined
StateMachine::Machine.ignore_method_conflicts = true
StateMachines::Machine.ignore_method_conflicts = true
# To avoid multiple occurrences of the same transition being defined
# On first definition, state_machines will not be defined
state_machines.clear if respond_to?(:state_machines)

View File

@@ -98,7 +98,7 @@ module Spree
end
def init
unless reflections.key?(:calculator)
unless _reflections.key?(:calculator)
self.class.include Spree::Core::CalculatedAdjustments
end

View File

@@ -61,6 +61,8 @@ module Spree
end
def delete(key)
return if key.nil?
@cache.delete(key)
destroy(key)
end

View File

@@ -95,6 +95,7 @@ module Spree
validates :tax_category_id, presence: true, if: "Spree::Config.products_require_tax_category"
validates :variant_unit, presence: true
validates :unit_value, presence: { if: ->(p) { %w(weight volume).include? p.variant_unit } }
validates :variant_unit_scale,
presence: { if: ->(p) { %w(weight volume).include? p.variant_unit } }
validates :variant_unit_name,

View File

@@ -15,7 +15,7 @@ module Spree
# may still be in an active cart after it's deleted, so this will mark it as out of stock.
return 0 if @variant.deleted?
stock_items.sum(&:count_on_hand)
stock_items.sum(:count_on_hand)
end
def backorderable?

View File

@@ -58,9 +58,11 @@ module Spree
has_spree_role?('admin')
end
# handle_asynchronously will define send_reset_password_instructions_with_delay.
# If handle_asynchronously is called twice, we get an infinite job loop.
handle_asynchronously :send_reset_password_instructions unless method_defined? :send_reset_password_instructions_with_delay
# Send devise-based user emails asyncronously via ActiveJob
# See: https://github.com/heartcombo/devise/tree/v3.5.10#activejob-integration
def send_devise_notification(notification, *args)
devise_mailer.public_send(notification, self, *args).deliver_later
end
def regenerate_reset_password_token
set_reset_password_token
@@ -72,6 +74,7 @@ module Spree
else
Spree::User
.includes(:enterprises)
.references(:enterprises)
.where("enterprises.id IN (SELECT enterprise_id FROM enterprise_roles WHERE user_id = ?)",
id)
end
@@ -100,7 +103,7 @@ module Spree
end
def send_signup_confirmation
Delayed::Job.enqueue ConfirmSignupJob.new(id)
ConfirmSignupJob.perform_later(id)
end
def associate_customers

View File

@@ -136,7 +136,7 @@ module Spree
end
def self.indexed
scoped.index_by(&:id)
where(nil).index_by(&:id)
end
def self.active(currency = nil)

View File

@@ -16,7 +16,7 @@ module Api
end
def item_count
object.line_items.sum(&:quantity)
object.line_items.sum(:quantity)
end
def completed_at

View File

@@ -6,17 +6,8 @@ class BulkInvoiceService
end
def start_pdf_job(order_ids)
pdf = CombinePDF.new
orders_from(order_ids).each do |order|
invoice = renderer.render_to_string(order)
pdf << CombinePDF.parse(invoice)
end
pdf.save "#{file_directory}/#{@id}.pdf"
BulkInvoiceJob.perform_later order_ids, "#{file_directory}/#{@id}.pdf"
end
handle_asynchronously :start_pdf_job
def invoice_created?(invoice_id)
File.exist? filepath(invoice_id)
@@ -28,10 +19,6 @@ class BulkInvoiceService
private
def orders_from(order_ids)
Spree::Order.where(id: order_ids).order("completed_at DESC")
end
def new_invoice_id
Time.zone.now.to_i.to_s
end
@@ -40,10 +27,6 @@ class BulkInvoiceService
'tmp/invoices'
end
def renderer
@renderer ||= InvoiceRenderer.new
end
def file_directory
Dir.mkdir(directory) unless File.exist?(directory)
directory

View File

@@ -1,5 +1,6 @@
class InvoiceRenderer
def render_to_string(order)
renderer.instance_variable_set(:@order, order)
renderer.render_to_string(args(order))
end
@@ -8,15 +9,14 @@ class InvoiceRenderer
pdf: "invoice-#{order.number}.pdf",
template: invoice_template,
formats: [:html],
encoding: "UTF-8",
locals: { :@order => order }
encoding: "UTF-8"
}
end
private
def renderer
ApplicationController.new
@renderer ||= ApplicationController.new
end
def invoice_template

View File

@@ -1,7 +1,7 @@
# This class allows orders with eager-loaded adjustment objects to calculate various adjustment
# types without triggering additional queries.
#
# For example; `order.adjustments.shipping.sum(&:amount)` would normally trigger a new query
# For example; `order.adjustments.shipping.sum(:amount)` would normally trigger a new query
# regardless of whether or not adjustments have been preloaded, as `#shipping` is an adjustment
# scope, eg; `scope :shipping, where(originator_type: 'Spree::ShippingMethod')`.
#

View File

@@ -9,19 +9,19 @@ module PermittedAttributes
def call
return @params[:enterprise] if @params[:enterprise].blank?
@params.require(:enterprise).permit(
basic_permitted_attributes + [
group_ids: [], user_ids: [],
shipping_method_ids: [], payment_method_ids: [],
address_attributes: PermittedAttributes::Address.attributes,
producer_properties_attributes: [:id, :property_name, :value, :_destroy]
]
)
@params.require(:enterprise).permit(self.class.attributes)
end
private
def self.attributes
basic_permitted_attributes + [
group_ids: [], user_ids: [],
shipping_method_ids: [], payment_method_ids: [],
address_attributes: PermittedAttributes::Address.attributes,
producer_properties_attributes: [:id, :property_name, :value, :_destroy]
]
end
def basic_permitted_attributes
def self.basic_permitted_attributes
[
:id, :name, :visible, :permalink, :owner_id, :contact_name, :email_address, :phone,
:is_primary_producer, :sells, :website, :facebook, :instagram, :linkedin, :twitter,

View File

@@ -0,0 +1,16 @@
# frozen_string_literal: true
module PermittedAttributes
class TagRules
def self.attributes
[
:id, :type, :priority, :is_default, :preferred_customer_tags, :preferred_exchange_tags,
:preferred_matched_order_cycles_visibility, :preferred_shipping_method_tags,
:preferred_matched_shipping_methods_visibility, :preferred_payment_method_tags,
:preferred_matched_payment_methods_visibility, :preferred_variant_tags,
:preferred_matched_variants_visibility, :calculator_type,
{ calculator_attributes: [:id, :preferred_flat_percent] }
]
end
end
end

View File

@@ -8,7 +8,8 @@
.four.columns
= f.field_container :included_tax do
= f.label :included_tax, t(:included_tax)
= text_field :adjustment, :included_tax, disabled: true, class: 'fullwidth'
= f.text_field :included_tax, disabled: true, class: 'fullwidth',
value: number_with_precision(f.object.included_tax, precision: 2)
= f.error_message_on :included_tax
.omega.four.columns

View File

@@ -199,5 +199,9 @@ module Openfoodnetwork
config.assets.precompile += ['*.jpg', '*.jpeg', '*.png', '*.gif' '*.svg']
config.active_support.escape_html_entities_in_json = true
config.active_job.queue_adapter = :delayed_job
config.active_record.raise_in_transactional_callbacks = true
end
end

View File

@@ -44,7 +44,7 @@ Openfoodnetwork::Application.configure do
# Use a different cache store in production
memcached_value_max_megabytes = ENV.fetch("MEMCACHED_VALUE_MAX_MEGABYTES", 1).to_i
memcached_value_max_bytes = memcached_value_max_megabytes * 1024 * 1024
config.cache_store = :dalli_store, { value_max_bytes: memcached_value_max_bytes }
config.cache_store = :mem_cache_store, { value_max_bytes: memcached_value_max_bytes }
# Enable serving of images, stylesheets, and JavaScripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"

View File

@@ -44,7 +44,7 @@ Openfoodnetwork::Application.configure do
# Use a different cache store in production
memcached_value_max_megabytes = ENV.fetch("MEMCACHED_VALUE_MAX_MEGABYTES", 1).to_i
memcached_value_max_bytes = memcached_value_max_megabytes * 1024 * 1024
config.cache_store = :dalli_store, { value_max_bytes: memcached_value_max_bytes }
config.cache_store = :mem_cache_store, { value_max_bytes: memcached_value_max_bytes }
# Enable serving of images, stylesheets, and JavaScripts from an asset server
# config.action_controller.asset_host = "http://assets.example.com"

View File

@@ -51,6 +51,8 @@ Openfoodnetwork::Application.configure do
require 'open_food_network/rack_request_blocker'
# Make sure the middleware is inserted first in middleware chain
config.middleware.insert_before('ActionDispatch::Static', 'RackRequestBlocker')
config.active_job.queue_adapter = :test
end
# Allows us to use _url helpers in Rspec

View File

@@ -0,0 +1,15 @@
module Paranoia
def paranoia_delete
raise ActiveRecord::ReadOnlyRecord, "#{self.class} is marked as readonly" if readonly?
if persisted?
# if a transaction exists, add the record so that after_commit
# callbacks can be run
add_to_transaction unless self.class.connection.current_transaction.closed?
update_columns(paranoia_destroy_attributes)
elsif !frozen?
assign_attributes(paranoia_destroy_attributes)
end
self
end
alias_method :delete, :paranoia_delete
end

View File

@@ -3,11 +3,16 @@
# Your secret key for verifying the integrity of signed cookies.
# If you change this key, all old signed cookies will become invalid!
# Make sure the secret is at least 30 characters and all random,
# no regular words or you'll be exposed to dictionary attacks.
Openfoodnetwork::Application.config.secret_token = if Rails.env.development? or Rails.env.test?
# no regular words or you'll be exposed to dictionary attacks.
secret_key = if Rails.env.development? or Rails.env.test?
('x' * 30) # Meets basic minimum of 30 chars.
else
ENV["SECRET_TOKEN"]
end
Openfoodnetwork::Application.config.secret_key_base = 'ceb1eb86c50285e696f899b2e7ea306d1ec1e81fe5c7af0e5cbc238bebe3fd60f19df7b9076fab836182821ebe14e41b64bdcdb4370520dc5bb711c1bc0ae616'
# Rails 4+ key for signing and encrypting cookies.
Openfoodnetwork::Application.config.secret_key_base = secret_key
# Legacy secret_token variable. This is still used directly for encryption.
Openfoodnetwork::Application.config.secret_token = secret_key

View File

@@ -1282,13 +1282,13 @@ ar:
footer_logo: "الشعار (220 × 76)"
footer_facebook_url: "رابط الفيسبوك"
footer_twitter_url: "رابط تويتر"
footer_instagram_url: "عنوان انستغرام"
footer_instagram_url: "رابط انستغرام"
footer_linkedin_url: "رابط لينكدن"
footer_googleplus_url: "رابط جوجل بلس"
footer_pinterest_url: "رابط بنتيريست"
footer_email: "البريد الإلكتروني"
footer_links_md: "الروابط"
footer_about_url: "حول الرابط "
footer_about_url: "رابط نحن"
user_guide_link: "رابط دليل المستخدم"
name: اسم
first_name: الاسم الاول
@@ -3006,7 +3006,7 @@ ar:
landing_page: "الصفحة المقصودة"
server: "الخادم"
test_mode: "وضع الاختبار"
logourl: "وحدة"
logourl: "رابط الشعار"
are_you_sure_delete: "هل أنت متأكد أنك تريد حذف هذا السجل؟"
confirm_delete: "تأكيد الحذف"
configurations: "تهيئة"
@@ -3472,10 +3472,10 @@ ar:
edit:
legal_settings: "الإعدادات القانونية"
cookies_consent_banner_toggle: "عرض راية موافقة ملفات تعريف الارتباط"
privacy_policy_url: "URL سياسة الخصوصية"
privacy_policy_url: "رابط سياسة الخصوصية"
enterprises_require_tos: "يجب على المؤسسات قبول شروط الخدمة"
cookies_policy_matomo_section: "عرض قسم Matomo في صفحة سياسة ملفات تعريف الارتباط"
footer_tos_url: "شروط الخدمة URL"
footer_tos_url: "رابط شروط الخدمة "
checkout:
payment:
stripe:
@@ -3492,7 +3492,7 @@ ar:
remember_this_card: تذكر هذه البطاقة؟
date_picker:
format: '٪ س-٪ م-%d'
js_format: 'يوم-شهر-سنة'
js_format: 'yy-mm-dd'
orders:
error_flash_for_unavailable_items: "عنصر في سلة التسوق الخاصة بك أصبح غير متوفر. يرجى تحديث الكميات المحددة."
edit:

View File

@@ -2888,6 +2888,8 @@ ca:
delete: "Suprimir"
cannot_set_shipping_method_without_address: "No es pot establir el mètode d'enviament fins que no es proporcionin les dades del client."
no_tracking_present: "No es proporcionen dades de seguiment."
tracking: "Seguiment"
tracking_number: "Número de seguiment"
order_total: "Total comanda"
customer_details: "Detalls de la consumidora"
customer_search: "Cerca la consumidora"

View File

@@ -14,6 +14,7 @@ en_AU:
spree/payment:
amount: Amount
state: State
source: Source
spree/product:
primary_taxon: "Product Category"
supplier: "Supplier"
@@ -23,6 +24,9 @@ en_AU:
spree/credit_card:
base: "Credit Card"
number: "Number"
month: "Month"
verification_value: "Verification Value"
year: "Year"
order_cycle:
orders_close_at: Close date
variant_override:
@@ -35,6 +39,10 @@ en_AU:
taken: "There's already an account for this email. Please login or reset your password."
spree/order:
no_card: There are no authorised credit cards available to charge
spree/credit_card:
attributes:
base:
card_expired: "has expired"
order_cycle:
attributes:
orders_close_at:
@@ -56,6 +64,8 @@ en_AU:
shipping_method_ids: "Shipping Methods"
payment_method_ids: "Payment Methods"
errors:
messages:
inclusion: "is not included in the list"
models:
order_management/subscriptions/validator:
attributes:
@@ -115,6 +125,8 @@ en_AU:
not_array_error: "must be an array"
invalid_element_error: "must contain only valid integers"
datetime_picker_ui:
current_text: Now
close_text: Done
time_text: Time
enterprise_mailer:
confirmation_instructions:
@@ -180,6 +192,7 @@ en_AU:
explainer: Automatic processing of these orders failed for an unknown reason. This should not occur, please contact us if you are seeing this.
home: "OFN"
title: "Open Food Network"
welcome_to: "Welcome to"
site_meta_description: "We begin from the ground up. With farmers and growers ready to tell their stories proudly and truly. With distributors ready to connect people with products fairly and honestly. With buyers who believe that better weekly shopping decisions can…"
search_by_name: Search by name or suburb...
producers_join: Australian producers are now welcome to join the Open Food Network.
@@ -222,6 +235,7 @@ en_AU:
enterprises: Enterprises
enterprise_groups: Groups
reports: Reports
listing_reports: Listing Reports
variant_overrides: Inventory
import: Import
spree_products: Spree Products
@@ -251,6 +265,8 @@ en_AU:
notes: Notes
error: Error
processing_payment: "Processing payment..."
no_pending_payments: "No pending payments"
invalid_payment_state: "Invalid payment state"
filter_results: Filter Results
quantity: Quantity
pick_up: Pick up
@@ -266,15 +282,23 @@ en_AU:
on hand: "On Hand"
ship: "Ship"
shipping_category: "Shipping Category"
height: "Height"
width: "Width"
depth: "Depth"
actions:
create_and_add_another: "Create and Add Another"
create: "Create"
cancel: "Cancel"
resume: "Resume"
save: "Save"
edit: "Edit"
update: "Update"
delete: "Delete"
add: "Add"
cut: "Cut"
paste: "Paste"
destroy: "Destroy"
rename: "Rename"
admin:
begins_at: Begins At
begins_on: Begins On
@@ -322,6 +346,7 @@ en_AU:
show_n_more: Show %{num} more
choose: "Choose..."
please_select: Please select...
column_save_as_default: Save As Default
columns: Columns
actions: Actions
viewing: "Viewing: %{current_view_name}"
@@ -332,6 +357,7 @@ en_AU:
has_n_rules: "has %{num} rules"
unsaved_confirm_leave: "There are unsaved changed on this page. Continue without saving?"
unsaved_changes: "You have unsaved changes"
available_units: "Available Units"
shopfront_settings:
embedded_shopfront_settings: "Embedded Shopfront Settings"
enable_embedded_shopfronts: "Enable Embedded Shopfronts"
@@ -366,7 +392,10 @@ en_AU:
title: "Matomo Settings"
matomo_url: "Matomo URL"
matomo_site_id: "Matomo Site ID"
matomo_tag_manager_url: "Matomo Tag Manager URL"
info_html: "Matomo is a Web and Mobile Analytics application. You can either host Matomo on-premises or use a cloud-hosted service. See <a href='http://matomo.org' target='_blank'>matomo.org</a> for more information."
config_instructions_html: "Here you can configure the OFN Matomo integration. The Matomo URL below should point to the Matomo instance where the user tracking information will be sent to; if it is left empty, Matomo user tracking will be disabled. The Site ID field is not mandatory but useful if you are tracking more than one website on a single Matomo instance; it can be found on the Matomo instance console."
config_instructions_tag_manager_html: "Setting the Matomo Tag Manager URL enables Matomo Tag Manager. This tool allows you to set up analytics events. The Matomo Tag Manager URL is copied from the Install Code section of Matomo Tag Manager. Ensure you select the right container and environment as these options change the URL."
customers:
index:
new_customer: "New Customer"
@@ -387,6 +416,8 @@ en_AU:
confirm_delete: "Sure to delete?"
search_by_email: "Search by email/code..."
guest_label: "Guest checkout"
credit_owed: "Credit Owed"
balance_due: "Balance Due"
destroy:
has_associated_orders: "Delete failed: customer has associated orders with his shop"
contents:
@@ -473,6 +504,7 @@ en_AU:
line_number: "Line %{number}:"
encoding_error: "Please check the language setting of your source file and ensure it is saved with UTF-8 encoding"
unexpected_error: "Product Import encountered an unexpected error whilst opening the file: %{error_message}"
malformed_csv: "Product Import encountered a malformed CSV: %{error_message}"
index:
notice: "Notice"
beta_notice: "This feature is still in beta: you may experience some errors while using it. Please don't hesitate to contact support."
@@ -574,6 +606,8 @@ en_AU:
controls:
back_to_my_inventory: Back to my inventory
orders:
edit:
order_sure_want_to: Are you sure you want to %{event} this order?
invoice_email_sent: 'Invoice email has been sent'
order_email_resent: 'Order email has been resent'
bulk_management:
@@ -583,6 +617,7 @@ en_AU:
order_date: "Completed at"
max: "Max"
product_unit: "Product: Unit"
weight_volume: "Weight/Volume (g)"
ask: "Ask?"
page_title: "Bulk Order Management"
actions_delete: "Delete Selected"
@@ -619,6 +654,9 @@ en_AU:
acn_placeholder: eg. 123 456 789
display_invoice_logo: Display logo in invoices
invoice_text: Add customized text at the end of invoices
terms_and_conditions: "Terms and Conditions"
remove_terms_and_conditions: "Remove File"
uploaded_on: "uploaded on"
contact:
name: Name
name_placeholder: eg. Gustav Plum
@@ -686,6 +724,7 @@ en_AU:
ofn_uid_tip: The unique id used to identify the enterprise on Open Food Network.
shipping_methods:
name: "Name"
applies: "Active?"
manage: "Manage Shipping Methods"
create_button: "Create New Shipping Method"
create_one_button: "Create One Now"
@@ -708,6 +747,8 @@ en_AU:
enable_subscriptions_tip: "Enable subscriptions functionality?"
enable_subscriptions_false: "Disabled"
enable_subscriptions_true: "Enabled"
customer_names_in_reports: "Customer Names in Reports"
customer_names_tip: "Enable your suppliers to see your customers names in reports"
customer_names_false: "Disabled"
customer_names_true: "Enabled"
shopfront_message: "\"Home\" message"
@@ -727,6 +768,7 @@ en_AU:
is displayed on your shop only when you have no active order cycles
(ie. shop is closed).
shopfront_category_ordering: "Shopfront Category Ordering"
shopfront_category_ordering_note: "(top to bottom)"
open_date: "Open Date"
close_date: "Close Date"
social:
@@ -868,6 +910,7 @@ en_AU:
incoming: "Incoming"
supplier: "Supplier"
products: "Products"
receival_details: "Receival Details"
fees: "Fees"
save: "Save"
save_and_next: "Save and Next"
@@ -879,6 +922,7 @@ en_AU:
distributor: "Distributor"
products: "Products"
tags: "Tags"
delivery_details: "Delivery Details"
fees: "Fees"
previous: "Previous"
save: "Save"
@@ -1132,10 +1176,18 @@ en_AU:
destroy_attachment_does_not_exist: "Logo does not exist"
enterprise_promo_image:
destroy_attachment_does_not_exist: "Promo image does not exist"
enterprise_terms_and_conditions:
destroy_attachment_does_not_exist: "Terms and Conditions file does not exist"
orders:
failed_to_update: "Failed to update order"
checkout:
already_ordered:
cart: "cart"
message_html: "You have an order for this order cycle already. Check the %{cart} to see the items you ordered before. You can also cancel items as long as the order cycle is open."
terms_and_conditions:
message_html: "I agree to the seller's %{terms_and_conditions_link}."
link_text: "Terms and Conditions"
failed: "The checkout failed. Please let us know so that we can process your order."
shops:
hubs:
show_closed_shops: "Show closed shops"
@@ -1147,7 +1199,12 @@ en_AU:
cart: "Cart"
cart_sidebar:
checkout: "Checkout"
edit_cart: "Edit cart"
items_in_cart_singular: "%{num} item in your cart"
items_in_cart_plural: "%{num} items in your cart"
close: "Close"
cart_empty: "Your cart is empty"
take_me_shopping: "Take me shopping!"
signed_in:
profile: "Profile"
mobile_menu:
@@ -1179,7 +1236,11 @@ en_AU:
signup: "signup"
contact: "contact"
require_customer_login: "Only approved customers can access this shop."
require_login_html: "If you're already an approved customer, %{login} or %{signup} to proceed."
require_login_2_html: "Want to start shopping here? Please %{contact} %{enterprise} and ask about joining."
require_customer_html: "If you'd like to start shopping here, please %{contact} %{enterprise} to ask about joining."
select_oc:
select_oc_html: "Please <span class='highlighted'>choose when you want your order</span>, to see what products are available."
products:
summary:
bulk: "Bulk"
@@ -1311,6 +1372,7 @@ en_AU:
saving_credit_card: Saving credit card...
card_has_been_removed: "Your card has been removed (number: %{number})"
card_could_not_be_removed: Sorry, the card could not be removed
invalid_credit_card: "Invalid credit card"
ie_warning_headline: "Your browser is out of date :-("
ie_warning_text: "For the best Open Food Network experience, we strongly recommend upgrading your browser:"
ie_warning_chrome: Download Chrome
@@ -1506,6 +1568,7 @@ en_AU:
shopping_oc_closed_description: "Please wait until the next cycle opens (or contact us directly to see if we can accept any late orders)"
shopping_oc_last_closed: "The last cycle closed %{distance_of_time} ago"
shopping_oc_next_open: "The next cycle opens in %{distance_of_time}"
shopping_oc_select: "Select..."
shopping_tabs_home: "Home"
shopping_tabs_shop: "Shop"
shopping_tabs_about: "About"
@@ -1537,18 +1600,24 @@ en_AU:
hubs_distance: Closest to
hubs_distance_filter: "Show me shops near %{location}"
shop_changeable_orders_alert_html:
one: Your order with <a href='%{path}' target='_blank'>%{shop} / %{order}</a> is open for review. You can make changes until %{oc_close}.
few: You have <a href='%{path}' target='_blank'>%{count} orders with %{shop}</a> currently open for review. You can make changes until %{oc_close}.
many: You have <a href='%{path}' target='_blank'>%{count} orders with %{shop}</a> currently open for review. You can make changes until %{oc_close}.
other: You have <a href='%{path}' target='_blank'>%{count} orders with %{shop}</a> currently open for review. You can make changes until %{oc_close}.
orders_changeable_orders_alert_html: This order has been confirmed, but you can make changes until <strong>%{oc_close}</strong>.
products_clear: Clear
products_showing: "Showing:"
products_results_for: "Results for"
products_or: "or"
products_and: "and"
products_filters_in: "in"
products_with: with
products_search: "Search..."
products_filter_by: "Filter by"
products_filter_selected: "selected"
products_filter_heading: "Filters"
products_filter_clear: "Clear"
products_filter_done: "Done"
products_loading: "Loading products..."
products_updating_cart: "Updating cart..."
products_cart_empty: "Cart empty"
@@ -1559,6 +1628,8 @@ en_AU:
products_update_error_msg: "Saving failed."
products_update_error_data: "Save failed due to invalid data:"
products_changes_saved: "Changes saved."
products_no_results_html: "Sorry, no results found for %{query}"
products_clear_search: "Clear search"
search_no_results_html: "Sorry, no results found for %{query}. Try another search?"
components_profiles_popover: "Profiles do not have a shopfront on the Open Food Network, but may have their own physical or online shop elsewhere"
components_profiles_show: "Show profiles"
@@ -1677,6 +1748,7 @@ en_AU:
orders_could_not_cancel: "Sorry, the order could not be cancelled"
orders_cannot_remove_the_final_item: "Cannot remove the final item from an order, please cancel the order instead."
orders_bought_items_notice:
one: An additional item is already confirmed for this order cycle
few: "%{count} additional items already confirmed for this order cycle"
many: "%{count} additional items already confirmed for this order cycle"
other: "%{count} additional items already confirmed for this order cycle"
@@ -1700,6 +1772,7 @@ en_AU:
remember_me: Remember Me
are_you_sure: "Are you sure?"
orders_open: "Orders open"
closing: "Closing"
going_back_to_home_page: "Taking you back to the home page"
creating: Creating
updating: Updating
@@ -1867,6 +1940,7 @@ en_AU:
headline: "Youre all set up! "
thanks: "Thanks for filling out the details for %{enterprise}."
login: "To manage your new Enterprise, go to openfoodnetwork.org.au/admin\n\nYou can also get to your Admin page in the top righthand corner of the Open Food Network homepage, just to the left of the shopping cart symbol."
action: "Go to Enterprise Dashboard"
back: "Back"
continue: "Continue"
action_or: "OR"
@@ -1912,6 +1986,7 @@ en_AU:
admin_enterprise_relationships_permits: "permits"
admin_enterprise_relationships_seach_placeholder: "Search"
admin_enterprise_relationships_button_create: "Create"
admin_enterprise_relationships_to: "to"
admin_enterprise_groups: "Enterprise Groups"
admin_enterprise_groups_name: "Name"
admin_enterprise_groups_owner: "Owner"
@@ -1940,6 +2015,7 @@ en_AU:
supplier: "Supplier"
product_name: "Product Name"
product_description: "Product Description"
permalink: "Permalink"
shipping_categories: "Shipping Categories"
units: "Unit Size"
coordinator: "Coordinator"
@@ -1952,6 +2028,8 @@ en_AU:
tax_category: "Tax Category"
calculator: "Calculator"
calculator_values: "Calculator values"
calculator_settings_warning: "If you are changing the calculator type, you must save first before you can edit the calculator settings"
calculator_preferred_unit_error: "must be kg or lb"
flat_percent_per_item: "Flat Percent (per item)"
flat_rate_per_item: "Flat Rate (per item)"
flat_rate_per_order: "Flat Rate (per order)"
@@ -2035,6 +2113,7 @@ en_AU:
remove_tax: "Remove tax"
first_name_begins_with: "First name begins with"
last_name_begins_with: "Last name begins with"
shipping_method: "Shipping method"
new_order: "New Order"
enterprise_tos_link: "Enterprise Terms of Service link"
enterprise_tos_message: "We want to work with people that share our aims and values. As such we ask new enterprises to agree to our "
@@ -2054,6 +2133,7 @@ en_AU:
hub_sidebar_at_least: "At least one hub must be selected"
hub_sidebar_blue: "blue"
hub_sidebar_red: "red"
order_cycles_closed_for_hub: "The hub you have selected is temporarily closed for orders. Please try again later."
report_customers_distributor: "Distributor"
report_customers_supplier: "Supplier"
report_customers_cycle: "Order Cycle"
@@ -2259,6 +2339,7 @@ en_AU:
enterprise_name_error: "has already been taken. If this is your enterprise and you would like to claim ownership, or if you would like to trade with this enterprise please contact the current manager of this profile at %{email}."
enterprise_owner_error: "^%{email} is not permitted to own any more enterprises (limit is %{enterprise_limit})."
enterprise_role_uniqueness_error: "^That role is already present."
enterprise_terms_and_conditions_type_error: "Only PDFs are allowed"
inventory_item_visibility_error: must be true or false
product_importer_file_error: "error: no file uploaded"
product_importer_spreadsheet_error: "could not process file: invalid filetype"
@@ -2282,6 +2363,7 @@ en_AU:
enterprise_register_success_notice: "Congratulations! Registration for %{enterprise} is complete!"
enterprise_bulk_update_success_notice: "Enterprises updated successfully"
enterprise_bulk_update_error: 'Update failed'
enterprise_shop_show_error: "The shop you are looking for doesn't exist or is inactive on OFN. Please check other shops."
order_cycles_create_notice: 'Your order cycle has been created.'
order_cycles_update_notice: 'Your order cycle has been updated.'
order_cycles_bulk_update_notice: 'Order cycles have been updated.'
@@ -2289,6 +2371,7 @@ en_AU:
order_cycles_email_to_producers_notice: 'Emails to be sent to producers have been queued for sending.'
order_cycles_no_permission_to_coordinate_error: "None of your enterprises have permission to coordinate an order cycle"
order_cycles_no_permission_to_create_error: "You don't have permission to create an order cycle coordinated by that enterprise"
order_cycle_closed: "The order cycle you've selected has just closed. Please try again!"
back_to_orders_list: "Back to order list"
no_orders_found: "No Orders Found"
order_information: "Order Information"
@@ -2316,6 +2399,10 @@ en_AU:
resolve_errors: Please resolve the following errors
more_items: "+ %{count} More"
default_card_updated: Default Card Updated
cart:
add_to_cart_failed: >
There was a problem adding this product to the cart. Perhaps it has become
unavailable or the shop is closing.
admin:
enterprise_limit_reached: "You have reached the standard limit of enterprises per account. Write to %{contact_email} if you need to increase it."
modals:
@@ -2341,6 +2428,14 @@ en_AU:
By creating rules related to a specific customer tag, you can override
the default behaviour (whether it be to show or to hide items) for customers
with the specified tag.
terms_and_conditions_info:
title: "Uploading Terms and Conditions"
message_1: "Terms and Conditions are the contract between you, the seller, and the shopper. If you upload a file here shoppers must accept your Terms and Conditions in order to complete checkout. For the shopper this will appear as a checkbox at checkout that must be checked in order to proceed with checkout. We highly recommend you upload Terms and Conditions in alignment with national legislation."
message_2: "Shoppers will only be required to accept Terms and Conditions once. However if you change you Terms and Conditions shoppers will again be required to accept them before they can checkout."
terms_and_conditions_warning:
title: "Uploading Terms and Conditions"
message_1: "All your buyers will have to agree to them once at checkout. If you update the file, all your buyers will have to agree to them again at checkout."
message_2: "For buyers with subscriptions, you need to email them the Terms and Conditions (or the changes to them) for now, nothing will notify them about these new Terms and Conditions."
panels:
save: SAVE
saved: SAVED
@@ -2434,6 +2529,12 @@ en_AU:
severity: Severity
description: Description
resolve: Resolve
exchange_products:
load_more_variants: "Load More Variants"
load_all_variants: "Load All Variants"
select_all_variants: "Select All %{total_number_of_variants} Variants"
variants_loaded: "%{num_of_variants_loaded} of %{total_number_of_variants} Variants Loaded"
loading_variants: "Loading Variants"
tag_rules:
shipping_method_tagged_top: "Shipping methods tagged"
shipping_method_tagged_bottom: "are:"
@@ -2516,6 +2617,7 @@ en_AU:
customer_placeholder: "customer@example.org"
valid_email_error: "Please enter a valid email address"
subscriptions:
error_saving: "Error saving subscription"
new:
please_select_a_shop: "Please select a shop"
enterprises:
@@ -2525,6 +2627,8 @@ en_AU:
immediate_logo_removal_warning: "The logo will be removed immediately after you confirm."
removed_promo_image_successfully: "Promo image removed successfully"
immediate_promo_image_removal_warning: "The promo image will be removed immediately after you confirm."
immediate_terms_and_conditions_removal_warning: "The Terms and Conditions file will be removed immediately after you confirm."
removed_terms_and_conditions_successfully: "Terms and Conditions file removed successfully"
insufficient_stock: "Insufficient stock available, only %{on_hand} remaining"
out_of_stock:
reduced_stock_available: Reduced stock available
@@ -2536,8 +2640,12 @@ en_AU:
shopfront:
variant:
add_to_cart: "Add"
in_cart: "in cart"
quantity_in_cart: "%{quantity} in cart"
bulk_buy_modal:
min_quantity: "Min quantity"
max_quantity: "Max quantity"
price_breakdown: "Price breakdown"
variants:
on_demand:
'yes': "On demand"
@@ -2603,6 +2711,84 @@ en_AU:
signup_or_login: "Start By Signing Up (or logging in)"
have_an_account: "Already have an account?"
action_login: "Log in now."
stripe_elements:
unknown_error_from_stripe: |
There was a problem setting up your card in our payments gateway.
Please refresh the page and try again, if it fails a second time,
please contact us for support.
inflections:
each:
one: "each"
other: "each"
bunch:
one: "bunch"
other: "bunches"
pack:
one: "pack"
other: "packs"
box:
one: "box"
other: "boxes"
bottle:
one: "bottle"
other: "bottles"
jar:
one: "jar"
other: "jars"
head:
one: "head"
other: "heads"
bag:
one: "bag"
other: "bags"
loaf:
one: "loaf"
other: "loaves"
single:
one: "single"
other: "singles"
tub:
one: "tub"
other: "tubs"
punnet:
one: "punnet"
other: "punnets"
packet:
one: "packet"
other: "packets"
item:
one: "item"
other: "items"
dozen:
one: "dozen"
other: "dozens"
unit:
one: "unit"
other: "units"
serve:
one: "serve"
other: "serves"
tray:
one: "tray"
other: "trays"
piece:
one: "piece"
other: "pieces"
pot:
one: "pot"
other: "pots"
bundle:
one: "bundle"
other: "bundles"
flask:
one: "flask"
other: "flasks"
basket:
one: "basket"
other: "baskets"
sack:
one: "sack"
other: "sacks"
producers:
signup:
start_free_profile: "Start with a free profile, and expand when you're ready!"
@@ -2660,6 +2846,8 @@ en_AU:
adjustments: "Adjustments"
payments: "Payments"
return_authorizations: "Return Authorizations"
credit_owed: "Credit Owed"
new_adjustment: "New Adjustment"
payment: "Payment"
payment_method: "Payment Method"
shipment: "Shipment"
@@ -2706,6 +2894,8 @@ en_AU:
delete: "Delete"
cannot_set_shipping_method_without_address: "Cannot set shipping method until customer details are provided."
no_tracking_present: "No tracking details provided."
tracking: "Tracking"
tracking_number: "Tracking Number"
order_total: "Order Total"
customer_details: "Customer Details"
customer_search: "Customer Search"
@@ -2733,6 +2923,14 @@ en_AU:
void: "Void"
login: "Login"
password: "Password"
signature: "Signature"
solution: "Solution"
landing_page: "Landing Page"
server: "Server"
test_mode: "Test Mode"
logourl: "Logourl"
are_you_sure_delete: "Are you sure you want to delete this record?"
confirm_delete: "Confirm Deletion"
configurations: "Configurations"
general_settings: "General Settings"
site_name: "Site Name"
@@ -2834,16 +3032,31 @@ en_AU:
inventory_error_flash_for_insufficient_quantity: "An item in your cart has become unavailable."
inventory: Inventory
zipcode: Postcode
weight: Weight (per kg or lb)
error_user_destroy_with_orders: "Users with completed orders may not be deleted"
cannot_create_payment_without_payment_methods: "You cannot create a payment for an order without any payment methods defined."
please_define_payment_methods: "Please define some payment methods first."
options: "Options"
has_no_shipped_units: "has no shipped units"
successfully_created: '%{resource} has been successfully created!'
successfully_updated: '%{resource} has been successfully updated!'
payment_method: "Payment Method"
payment_processing_failed: "Payment could not be processed, please check the details you entered"
not_available: "N/A"
order_populator:
out_of_stock: '%{item} is out of stock.'
actions:
update: "Update"
shared:
error_messages:
errors_prohibited_this_record_from_being_saved:
one: "1 error prohibited this record from being saved:"
few: "%{count} errors prohibited this record from being saved:"
many: "%{count} errors prohibited this record from being saved:"
other: "%{count} errors prohibited this record from being saved:"
there_were_problems_with_the_following_fields: "There were problems with the following fields"
payments_list:
date_time: "Date/time"
amount: "Amount"
payment_method: "Payment Method"
payment_state: "Payment State"
@@ -2930,6 +3143,7 @@ en_AU:
capture: "Capture"
ship: "Ship"
edit: "Edit"
order_not_updated: "The order could not be updated"
note: "Note"
first: "First"
last: "Last"
@@ -2952,6 +3166,8 @@ en_AU:
tax_invoice: "TAX INVOICE"
code: "Code"
from: "From"
to: "Bill to"
shipping: "Shipping"
form:
distribution_fields:
title: "Distribution"
@@ -2989,6 +3205,8 @@ en_AU:
zone: "Zone"
calculator: "Calculator"
display: "Display"
both: "Both Checkout and Back office"
back_end: "Back office only"
no_shipping_methods_found: "No shipping methods found"
new:
new_shipping_method: "New Shipping Method"
@@ -3000,6 +3218,9 @@ en_AU:
form:
categories: "Categories"
zones: "Zones"
both: "Both Checkout and Back office"
back_end: "Back office only"
deactivation_warning: "De-activating a shipping method can make the shipping method disappear from your list. Alternatively, you can hide a shipping method from the checkout page by setting the option 'Display' to 'back office only'."
payment_methods:
index:
payment_methods: "Payment Methods"
@@ -3011,8 +3232,11 @@ en_AU:
display: "Display"
active: "Active"
both: "Both"
front_end: "Checkout only"
back_end: "Back office only"
active_yes: "Yes"
active_no: "No"
no_payment_methods_found: "No payment methods found"
new:
new_payment_method: "New Payment Method"
back_to_payment_methods_list: "Back To Payment Methods List"
@@ -3041,7 +3265,11 @@ en_AU:
active: "Active"
active_yes: "Yes"
active_no: "No"
both: "Both Checkout and Back office"
front_end: "Checkout only"
back_end: "Back office only"
tags: "Tags"
deactivation_warning: "De-activating a payment method can make the payment method disappear from your list. Alternatively, you can hide a payment method from the checkout page by setting the option 'Display' to 'back office only'."
providers:
provider: "Provider"
payments:
@@ -3049,6 +3277,8 @@ en_AU:
stripe:
error_saving_payment: Error saving payment
submitting_payment: Submitting payment...
paypal:
no_payment_via_admin_backend: Paypal payments cannot be captured in the Backoffice
products:
image_upload_error: "The product image was not recognised. Please upload an image in PNG or JPG format."
new:
@@ -3102,6 +3332,8 @@ en_AU:
bulk_coop_allocation: 'Bulk Co-op - Allocation'
bulk_coop_packing_sheets: 'Bulk Co-op - Packing Sheets'
bulk_coop_customer_payments: 'Bulk Co-op - Customer Payments'
customer_names_message:
customer_names_tip: "If customer names are hidden for orders you have supplied, you can contact the distributor and ask if they can update their shop preferences to allow their suppliers to view customer names."
users:
index:
listing_users: "Listing Users"
@@ -3143,6 +3375,8 @@ en_AU:
price: "Price"
display_as: "Display As"
display_name: "Display Name"
display_as_placeholder: 'eg. 2 kg'
display_name_placeholder: 'eg. Tomatoes'
autocomplete:
out_of_stock: "Out of Stock"
producer_name: "Producer"
@@ -3182,6 +3416,7 @@ en_AU:
format: '%Y-%m-%d'
js_format: 'yy-mm-dd'
orders:
error_flash_for_unavailable_items: "An item in your cart has become unavailable. Please update the selected quantities."
edit:
login_to_view_order: "Please log in to view your order."
bought:
@@ -3209,6 +3444,14 @@ en_AU:
invalid: invalid
order_mailer:
cancel_email:
customer_greeting: "Dear %{name},"
instructions_html: "Your order with <strong>%{distributor}</strong> has been CANCELED. Please retain this cancellation information for your records."
dont_cancel: "If you have changed your mind or don't wish to cancel this order please contact %{email}"
order_summary_canceled_html: "<strong>Order Summary #%{number} [CANCELED]</strong>"
details: "Here are the details of what you ordered:"
unpaid_order: "Your order was unpaid so no refund has been made"
paid_order: "Your order was paid so %{distributor} has refunded the full amount"
credit_order: "Your order was paid so your account has been credited"
subject: "Cancellation of Order"
confirm_email:
subject: "Order Confirmation"
@@ -3225,6 +3468,7 @@ en_AU:
issue_text: |
If the above URL does not work try copying and pasting it into your browser.
If you continue to have problems please feel free to contact us.
subject: "Reset password instructions"
confirmation_instructions:
subject: "Please confirm your OFN account"
shipment_mailer:
@@ -3236,6 +3480,11 @@ en_AU:
thanks: "Thank you for your business."
track_information: "Tracking Information: %{tracking}"
track_link: "Tracking Link: %{url}"
test_mailer:
test_email:
greeting: "Congratulations!"
message: "If you have received this email, then your email settings are correct."
subject: "Test Mail"
order_state:
address: address
adjustments: adjustments
@@ -3318,3 +3567,8 @@ en_AU:
shipment:
cannot_ready: "Cannot ready shipment."
invalid_taxonomy_id: "Invalid taxonomy id."
activerecord:
models:
spree/payment:
one: Payment
other: Payments

View File

@@ -3446,7 +3446,7 @@ en_GB:
order_summary_canceled_html: "<strong>Order Summary #%{number} [CANCELED]</strong>"
details: "Here are the details of what you ordered:"
unpaid_order: "Your order was unpaid so no refund has been made"
paid_order: "Your order was paid so %{distributor} has refunded the full amount"
paid_order: "Your order was paid so %{distributor} will refund the full amount. Please don't hesitate to get in touch to notify them that you cancelled your order. Many business reconcile payments at the end of the month but will happily issue refunds sooner, if they are aware you are waiting."
credit_order: "Your order was paid so your account has been credited"
subject: "Cancellation of Order"
confirm_email:

View File

@@ -289,11 +289,16 @@ en_NZ:
create_and_add_another: "Create and Add Another"
create: "Create"
cancel: "Cancel"
resume: "Resume"
save: "Save"
edit: "Edit"
update: "Update"
delete: "Delete"
add: "Add"
cut: "Cut"
paste: "Paste"
destroy: "Destroy"
rename: "Rename"
admin:
begins_at: Begins At
begins_on: Begins On
@@ -601,6 +606,8 @@ en_NZ:
controls:
back_to_my_inventory: Back to my inventory
orders:
edit:
order_sure_want_to: Are you sure you want to %{event} this order?
invoice_email_sent: 'Invoice email has been sent'
order_email_resent: 'Order email has been resent'
bulk_management:
@@ -2877,6 +2884,8 @@ en_NZ:
delete: "Delete"
cannot_set_shipping_method_without_address: "Cannot set shipping method until customer details are provided."
no_tracking_present: "No tracking details provided."
tracking: "Tracking"
tracking_number: "Tracking Number"
order_total: "Order Total"
customer_details: "Customer Details"
customer_search: "Customer Search"
@@ -2910,6 +2919,8 @@ en_NZ:
server: "Server"
test_mode: "Test Mode"
logourl: "Logourl"
are_you_sure_delete: "Are you sure you want to delete this record?"
confirm_delete: "Confirm Deletion"
configurations: "Configurations"
general_settings: "General Settings"
site_name: "Site Name"

View File

@@ -2884,6 +2884,8 @@ en_US:
delete: "Delete"
cannot_set_shipping_method_without_address: "Cannot set shipping method until customer details are provided."
no_tracking_present: "No tracking details provided."
tracking: "Tracking"
tracking_number: "Tracking Number"
order_total: "Order Total"
customer_details: "Customer Details"
customer_search: "Customer Search"

View File

@@ -2888,6 +2888,8 @@ es:
delete: "Borrar"
cannot_set_shipping_method_without_address: "No se puede establecer el método de envío hasta que se proporcionen los detalles de la consumidora."
no_tracking_present: "No se han proporcionado detalles de seguimiento."
tracking: "Seguimiento"
tracking_number: "Número de seguimiento"
order_total: "Total del pedido"
customer_details: "Detalles de la consumidora"
customer_search: "Búsqueda de consumidores"

View File

@@ -829,17 +829,17 @@ pt_BR:
owner: Proprietário
producer: Produtor
change_type_form:
producer_profile: Perfil do produtor
producer_profile: Perfil Simples
connect_ofn: Conecte-se através da OFB
always_free: SEMPRE GRATUITO
producer_description_text: Adicione os seus produtos à Open Food Brasil, permitindo que as centrais os comercialize em suas lojas.
producer_shop: Loja do produtor
producer_shop: Loja de Produtor
sell_your_produce: 'Venda seus próprios produtos '
producer_shop_description_text: Venda seus produtos diretamente aos compradores através da sua própria loja virtual na Open Food Brasil.
producer_shop_description_text2: Uma loja de produtor é apenas para o seu produto, se você quiser vender produtos produzidos por outras pessoas ou locais, selecione 'Central de produtor'.
producer_shop_description_text2: Uma Loja de Produtor vende ou distribui apenas produtos próprios. Se você quiser vender produtos produzidos por outras pessoas ou iniciativas, selecione 'Central de Produtor'.
producer_hub: Central de produtor
producer_hub_text: Comercialize seus próprios produtos e de outros produtores
producer_hub_description_text: Sua iniciativa é a espinha dorsal do seu sistema de produção e consumo local. Você pode comercializar seus próprios bens, assim como produtos agregados de outras iniciativas e produtores, através da sua loja na Open Food Brasil.
producer_hub_description_text: Escolha este tipo de perfil se a sua iniciativa funciona como um intermediário, ou seja, ela vende / distribui produtos seus e de outros produtores também
profile: Perfil Simples
get_listing: Obter uma listagem
profile_description_text: As pessoas podem te encontrar e te contactar na Open Food Brasil. Sua iniciativa estará visível no mapa e poderá ser encontrada em buscas.
@@ -874,7 +874,7 @@ pt_BR:
next_step: Próximo passo
choose_starting_point: 'Escolha o seu tipo de perfil:'
profile: 'Perfil'
producer_profile: 'Perfil do produtor'
producer_profile: 'Perfil Simples'
invite_manager:
user_already_exists: "Usuário já existe"
error: "Algo deu errado"
@@ -1015,10 +1015,10 @@ pt_BR:
unitsize: Unidade de Medida
total: TOTAL
total_items: TOTAL DE ITEMS
supplier_totals: Total do fornecedor do ciclo de pedidos
supplier_totals_by_distributor: Total do fornecedor do ciclo de pedidos por distribuidor
totals_by_supplier: Total do distribuidor do ciclo da pedidos pelo fornecedor
customer_totals: Total do consumidor do ciclo de pedidos
supplier_totals: 'Fechamento do Ciclo: por Fornecedor'
supplier_totals_by_distributor: 'Fechamento do Ciclo: por Fornecedor / Distribuidor'
totals_by_supplier: 'Fechamento do Ciclo: por Distribuidor / Fornecedor'
customer_totals: 'Fechamento do Ciclo: por Consumidor'
all_products: Todos os produtos
inventory: Inventário (disponível)
lettuce_share: LettuceShare
@@ -1198,8 +1198,8 @@ pt_BR:
mobile_menu:
cart: "Carrinho"
register_call:
selling_on_ofn: "Interessado em registrar a sua iniciativa na Open Food Brasil?"
register: "Registre-se aqui"
selling_on_ofn: "Quer fazer parte da Open Food Brasil?"
register: "Registre aqui a sua iniciativa"
footer:
footer_secure: "Seguro e confiável."
footer_secure_text: "A Open Food Brasil utiliza a criptografia SSL (2048 bit RSA) para manter suas informações em segurança. Nossos servidores não guardam os detalhes do seu cartão de crédito e os pagamentos são processados por serviços compatíveis com PCI."
@@ -1812,7 +1812,7 @@ pt_BR:
steps:
introduction:
registration_greeting: "Olá!"
registration_intro: "Você pode criar um perfil de produtor ou central"
registration_intro: "Vamos criar um perfil para a sua iniciativa? "
registration_checklist: "O que eu preciso?"
registration_time: "5-10 minutos"
registration_enterprise_address: "Endereço da iniciativa"
@@ -1822,14 +1822,14 @@ pt_BR:
registration_about_us: "'Sobre Nós'"
registration_outcome_headline: "O que eu ganho?"
registration_outcome1_html: "Seu perfil ajuda as pessoas a te <strong>encontrarem</strong> e entrarem em <strong>contato</strong> com você na Open Food Brasil."
registration_outcome2: "Use esse espaço para contar a história da sua iniciativa e ajudar a impulsionar as conexões com sua presença social e online."
registration_outcome3: "Esse é também o primeiro passo para começar a comercializar na Open Food Brasil, ou abrir uma loja online."
registration_outcome2: "Use esse espaço para contar a história da sua iniciativa e divulgar o seu trabalho."
registration_outcome3: "Esse é também o primeiro passo para começar a fornecer ou comercializar seus produtos na Open Food Brasil."
registration_action: "Vamos começar!"
details:
title: "Detalhes"
headline: "Vamos começar"
enterprise: "Woot! Primeiro, você precisa conhecer um pouco da sua empresa:"
producer: "Primeiro precisamos saber mais sobre sua produção:"
enterprise: "Boa! Primeiro, precisamos saber um pouco mais sobre a sua iniciativa:"
producer: "Boa! Primeiro, precisamos saber um pouco mais sobre a sua produção:"
enterprise_name_field: "Nome da iniciativa:"
producer_name_field: "Nome da Produção"
producer_name_field_placeholder: "ex. Fazenda da Nina"
@@ -1863,9 +1863,9 @@ pt_BR:
yes_producer: "Sim, sou um produtor"
no_producer: "Não, não sou um produtor"
producer_field_error: "Por favor escolha um. Você é um produtor?"
yes_producer_help: "Produtores fazem coisas deliciosas de comer e beber. "
yes_producer_help: "Produtores são aqueles que cultivam, colhem, beneficiam, cozinham, preparam e produzem alimentos e/ou produtos artesanais. "
no_producer_help: "Se você não é um produtor, você provavelmente é alguém que vende e distribui alimentos. Você pode ser uma cooperativa, grupo de consumo, varejista, atacadista ou outro. Nos referimos a você como central, já que centraliza pessoas e produtos, independente do modelo organizacional. "
create_profile: "Crir perfil"
create_profile: "Criar perfil"
about:
title: "Sobre"
headline: "Boa!"
@@ -2468,15 +2468,14 @@ pt_BR:
profile_only_text3: >
Adicione seus produtos à Open Food Brasil, permitindo que as centrais
armazenem seus produtos em suas lojas.
producer_shop: Loja do produtor
producer_shop: Loja de Produtor
producer_shop_text1: >
Venda os seus produtos diretamente aos compradores através da sua própria
loja na Open Food Brasil.
producer_shop_text2: >
Uma loja de produtor é individual, somente para comercialização de produtos
feitos por você. Se quiser vender bens produzidos em outros lugares
e/ou pessoas, para além dos seus próprios, por favor selecione 'Central
de Produtor'.
Uma Loja de Produtor comercializa ou distribui somente produções próprias.
Se quiser movimentar bens produzidos por outras pessoas ou iniciativas,
além dos seus próprios, por favor selecione 'Central de Produtor'.
producer_hub: Central de produtor
producer_hub_text1: >
A sua iniciativa é a espinha dorsal do seu sistema de produção e consumo
@@ -2498,8 +2497,8 @@ pt_BR:
enterprise_producer:
producer: Produtor
producer_text1: >
Os produtores fazem coisas deliciosas para comer ou beber. Você é um
produtor se você cultiva, cria, prepara, cozinha, fermenta, ou ordenha.
Produtores são aqueles que cultivam, colhem, beneficiam, cozinham, preparam
e produzem alimentos e/ou produtos artesanais.
producer_text2: >
Os produtores também podem desempenhar outras funções, como agregar
alimentos de outras iniciativas e vendê-lo através de uma loja da Open

File diff suppressed because it is too large Load Diff

13
dependabot.yml Normal file
View File

@@ -0,0 +1,13 @@
version: 2
updates:
- package-ecosystem: "bundler"
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 10
- package-ecosystem: "yarn"
directory: "/"
schedule:
interval: "daily"

View File

@@ -49,6 +49,7 @@ If you are using Windows and having issues related to the ruby-build not finding
* docker/build: This script builds the Docker containers specified for this app, seeds the database, and logs the screen output for these operations. After you use "git clone" to download this repository, run the docker/build script to start the setup process.
* docker/server: Use this script to run this app in the Rails server. This script executes the "docker-compose up" command and logs the results. If all goes well, you will be able to view this app on your local browser at http://localhost:3000/.
* docker/test: Use this script to run the entire test suite.
* docker/qtest: Use this script to run the entire test suite in quiet mode. The deprecation warnings are removed to make the test results easier to read.
* docker/run: Use this script to run commands within the Docker container. If you want shell access, enter "docker/run bash". To execute "ls -l" within the Docker container, enter "docker/run ls -l".
* docker/seed: Use this script to seed the database. Please note that this process is not compatible with simultaneously running the Rails server or tests.
* docker/nuke: Use this script to delete all Docker images and containers. This fully resets your Docker setup and is useful for making sure that the setup procedure specified for this app is complete.

9
docker/qtest Executable file
View File

@@ -0,0 +1,9 @@
#!/bin/bash
set -e
# This script runs the entire test suite AND logs the screen output.
# This is the quiet version of docker/test.
# The deprecation warnings that obscure the test results are omitted.
DATE=`date +%Y%m%d-%H%M%S-%3N`
docker/qtest-log 2>&1 | tee log/qtest-$DATE.log

17
docker/qtest-log Executable file
View File

@@ -0,0 +1,17 @@
#!/bin/bash
echo '--------------------------------------------------------------'
echo 'BEGIN: docker-compose run web bundle exec rake db:test:prepare'
echo '--------------------------------------------------------------'
docker-compose run web bundle exec rake db:test:prepare
echo '------------------------------------------------------------'
echo 'END: docker-compose run web bundle exec rake db:test:prepare'
echo '------------------------------------------------------------'
echo '--------------------------------------'
echo 'BEGIN: running test suite (quiet mode)'
echo '--------------------------------------'
docker-compose run web bundle exec rspec spec | grep -v 'DEPRECATION WARNING' | grep -v 'Post.includes(:comments)' | grep -v 'Currently, Active Record recognizes the table in the string' | grep -v "If you don't rely on implicit join references"
echo '------------------------------------'
echo 'END: running test suite (quiet mode)'
echo '------------------------------------'

View File

@@ -101,10 +101,9 @@ module OrderManagement
def inspect
out = "#{order} - "
out << contents.map do |content_item|
out.dup << contents.map do |content_item|
"#{content_item.variant.name} #{content_item.quantity} #{content_item.state}"
end.join('/')
out
end
def to_shipment

View File

@@ -112,6 +112,13 @@ module OrderManagement
expect(shipment.shipping_method).to eq shipping_method
end
describe "#inpsect" do
it "prints the package contents" do
subject.add variant, 5
expect(subject.inspect).to match("#{variant.name} 5")
end
end
end
context "#shipping_methods and #shipping_categories" do

View File

@@ -10,7 +10,7 @@ module OrderManagement
subject { Packer.new(stock_location, order) }
before { order.line_items.first.variant.update(weight: 1) }
before { order.line_items.first.variant.update(unit_value: 100) }
it 'builds a package with all the items' do
package = subject.package

View File

@@ -28,22 +28,42 @@
# https://gist.github.com/victorblasco/f675b4cbaf9c0bc19f81
module ActionDispatch
class Request
def deep_munge(hash)
hash.each do |_k, v|
case v
when Array
v.grep(Hash) { |x| deep_munge(x) }
v.compact!
class Request < Rack::Request
class Utils # :nodoc:
mattr_accessor :perform_deep_munge
self.perform_deep_munge = true
# This patch removes the next line
# hash[k] = nil if v.empty?
when Hash
deep_munge(v)
class << self
# Remove nils from the params hash
def deep_munge(hash, keys = [])
return hash unless perform_deep_munge
hash.each do |key, value|
deep_munge_value(key, value, keys)
end
hash
end
def deep_munge_value(key, value, keys)
keys << key
case value
when Array
value.grep(Hash) { |x| deep_munge(x, keys) }
value.compact!
# This patch removes the following lines
# if v.empty?
# hash[k] = nil
# ActiveSupport::Notifications.instrument("deep_munge.action_controller",
# keys: keys)
# end
when Hash
deep_munge(value, keys)
end
keys.pop
end
end
hash
end
end
end

View File

@@ -0,0 +1,6 @@
# frozen_string_literal: true
class ApplicationResponder < ActionController::Responder
include Responders::FlashResponder
include Responders::HttpCacheResponder
end

View File

@@ -60,7 +60,11 @@ module OpenFoodNetwork
def filter_to_supplier(orders)
if params[:supplier_id].to_i > 0
orders.select do |order|
order.line_items.includes(:product).where("spree_products.supplier_id = ?", params[:supplier_id].to_i).count > 0
order.line_items.includes(:product)
.where("spree_products.supplier_id = ?", params[:supplier_id].to_i)
.references(:product)
.count
.positive?
end
else
orders

View File

@@ -38,7 +38,7 @@ module OpenFoodNetwork
# Cycle thorugh variant of a product
variant_groups = line_items_by_product.group_by(&:variant)
variant_groups.each do |variant, line_items_by_variant|
sum_quantities = line_items_by_variant.sum(&:quantity)
sum_quantities = line_items_by_variant.to_a.sum(&:quantity)
sum_max_quantities = line_items_by_variant.sum { |li| li.max_quantity || 0 }
variants_and_quantities << GroupBuyVariantRow.new(variant, sum_quantities, sum_max_quantities)
end

View File

@@ -134,7 +134,7 @@ module OpenFoodNetwork
proc { |line_items| line_items.first.variant.product.name },
proc { |line_items| line_items.first.variant.full_name },
proc { |line_items| line_items.sum(&:quantity) },
proc { |line_items| line_items.to_a.sum(&:quantity) },
proc { |line_items| line_items.sum(&:amount) },
proc { |line_items| line_items.sum(&:amount_with_adjustments) },
proc { |_line_items| "" },

View File

@@ -45,7 +45,7 @@ module OpenFoodNetwork
supplier_name,
product_name,
line_items_name,
proc { |line_items| line_items.sum(&:quantity) },
proc { |line_items| line_items.to_a.sum(&:quantity) },
proc { |line_items| line_items.first.price },
proc { |line_items| line_items.sum { |li| li.quantity * li.price } },
proc { |_line_items| "" },

View File

@@ -59,7 +59,7 @@ module OpenFoodNetwork
proc { |line_items| line_items.first.variant.product.supplier.name },
proc { |line_items| line_items.first.variant.product.name },
proc { |line_items| line_items.first.variant.full_name },
proc { |line_items| line_items.sum(&:quantity) },
proc { |line_items| line_items.to_a.sum(&:quantity) },
proc { |line_items| line_items.first.price },
proc { |line_items| line_items.sum(&:amount) },
proc { |_line_items| "" },

View File

@@ -60,7 +60,7 @@ module OpenFoodNetwork
proc { |line_items| line_items.first.variant.product.name },
proc { |line_items| line_items.first.variant.full_name },
proc { |line_items| line_items.first.order.distributor.name },
proc { |line_items| line_items.sum(&:quantity) },
proc { |line_items| line_items.to_a.sum(&:quantity) },
proc { |line_items| line_items.first.price },
proc { |line_items| line_items.sum(&:amount) },
proc { |_line_items| I18n.t(:report_header_shipping_method) }

View File

@@ -44,7 +44,7 @@ module OpenFoodNetwork
supplier_name,
product_name,
line_items_name,
proc { |line_items| line_items.sum(&:quantity) },
proc { |line_items| line_items.to_a.sum(&:quantity) },
proc { |line_items| total_units(line_items) },
proc { |line_items| line_items.first.price },
proc { |line_items| line_items.sum(&:amount) },

View File

@@ -96,18 +96,32 @@ module OpenFoodNetwork
when "itemised_payment_totals"
[proc { |orders| orders.first.payment_state },
proc { |orders| orders.first.distributor.name },
proc { |orders| orders.sum(&:item_total) },
proc { |orders| orders.to_a.sum(&:item_total) },
proc { |orders| orders.sum(&:ship_total) },
proc { |orders| orders.sum(&:outstanding_balance) },
proc { |orders| orders.sum(&:total) }]
proc { |orders| orders.map(&:total).sum }]
when "payment_totals"
[proc { |orders| orders.first.payment_state },
proc { |orders| orders.first.distributor.name },
proc { |orders| orders.sum(&:item_total) },
proc { |orders| orders.to_a.sum(&:item_total) },
proc { |orders| orders.sum(&:ship_total) },
proc { |orders| orders.sum(&:total) },
proc { |orders| orders.sum { |o| o.payments.select { |payment| payment.completed? && (payment.payment_method.name.to_s.include? "EFT") }.sum(&:amount) } },
proc { |orders| orders.sum { |o| o.payments.select { |payment| payment.completed? && (payment.payment_method.name.to_s.include? "PayPal") }.sum(&:amount) } },
proc { |orders| orders.map(&:total).sum },
proc { |orders|
orders.sum { |o|
o.payments.select { |payment|
payment.completed? &&
(payment.payment_method.name.to_s.include? "EFT")
}.sum(&:amount)
}
},
proc { |orders|
orders.sum { |o|
o.payments.select { |payment|
payment.completed? &&
(payment.payment_method.name.to_s.include? "PayPal")
}.sum(&:amount)
}
},
proc { |orders| orders.sum(&:outstanding_balance) }]
else
[proc { |payments| payments.first.order.payment_state },

View File

@@ -101,7 +101,7 @@ module OpenFoodNetwork
end
def tax_included_in(line_item)
line_item.adjustments.sum(&:included_tax)
line_item.adjustments.sum(:included_tax)
end
def shipment_inc_vat

View File

@@ -122,7 +122,7 @@ module OpenFoodNetwork
end
def to_bool(value)
ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
ActiveRecord::Type::Boolean.new.type_cast_from_database(value)
end
def to_local_datetime(date)

View File

@@ -188,32 +188,32 @@ module OpenFoodNetwork
end
def total_untaxable_fees(order)
order.adjustments.enterprise_fee.without_tax.sum(&:amount)
order.adjustments.enterprise_fee.without_tax.sum(:amount)
end
def total_taxable_fees(order)
order.adjustments.enterprise_fee.with_tax.sum(&:amount)
order.adjustments.enterprise_fee.with_tax.sum(:amount)
end
def total_shipping(order)
order.adjustments.shipping.sum(&:amount)
order.adjustments.shipping.sum(:amount)
end
def total_transaction(order)
order.adjustments.payment_fee.sum(&:amount)
order.adjustments.payment_fee.sum(:amount)
end
def tax_on_shipping_s(order)
tax_on_shipping = order.adjustments.shipping.sum(&:included_tax) > 0
tax_on_shipping = order.adjustments.shipping.sum(:included_tax) > 0
tax_on_shipping ? I18n.t(:report_header_gst_on_income) : I18n.t(:report_header_gst_free_income)
end
def total_untaxable_admin_adjustments(order)
order.adjustments.admin.without_tax.sum(&:amount)
order.adjustments.admin.without_tax.sum(:amount)
end
def total_taxable_admin_adjustments(order)
order.adjustments.admin.with_tax.sum(&:amount)
order.adjustments.admin.with_tax.sum(:amount)
end
def detail?

View File

@@ -4,7 +4,7 @@ module Spree
def self.included(klass)
klass.class_eval do
include AbstractController::Rendering
include AbstractController::ViewPaths
include ActionView::ViewPaths
include AbstractController::Callbacks
include AbstractController::Helpers
@@ -13,7 +13,6 @@ module Spree
include ActionController::Rendering
include ActionController::ImplicitRender
include ActionController::Rescue
include ActionController::MimeResponds
include ActionController::Head
include CanCan::ControllerAdditions
@@ -21,8 +20,6 @@ module Spree
prepend_view_path Rails.root + "app/views"
append_view_path File.expand_path("../../../app/views", File.dirname(__FILE__))
respond_to :json
end
end
end

View File

@@ -10,7 +10,7 @@ require 'mail'
require 'paperclip'
require 'paranoia'
require 'ransack'
require 'state_machine'
require 'state_machines'
module Spree
mattr_accessor :user_class

View File

@@ -30,6 +30,22 @@ module ActionController
(options.delete(:responder) || Spree::Responder).call(self, resources, options)
end
end
private
def retrieve_collector_from_mimes(mimes = nil, &block)
mimes ||= collect_mimes_from_class_level
collector = Collector.new(mimes, request.variant)
block.call(collector) if block_given?
format = collector.negotiate_format(request)
if format
_process_format(format)
collector
else
raise ActionController::UnknownFormat
end
end
end
end

View File

@@ -0,0 +1,64 @@
# frozen_string_literal: true
# rubocop:disable Metrics/BlockLength
namespace :ofn do
namespace :subs do
namespace :debug do
desc "Print standard info about a specific Order Cycle"
task order_cycle: :environment do
order_cycle_id = request_order_cycle_id
order_cycle = OrderCycle.find_by(id: order_cycle_id)
puts "Order Cycle #{order_cycle.name}"
order_cycle.schedules.each do |schedule|
puts "Schedule #{schedule.name}"
Subscription.where(schedule_id: schedule.id).each do |subscription|
puts
puts "Subscription #{subscription.id}"
puts subscription.shop.name
puts subscription.customer.email
puts subscription.payment_method.name
puts "Active from #{subscription.begins_at} to #{subscription.ends_at}"
puts "Last edited on #{subscription.updated_at}"
puts "Canceled at #{subscription.canceled_at} and paused at #{subscription.paused_at}"
ProxyOrder.where(order_cycle_id: order_cycle_id,
subscription_id: subscription.id).each do |proxy_order|
puts
puts "Proxy Order #{proxy_order.id}"
puts "Canceled at #{proxy_order.canceled_at}"
puts "Last updated at #{proxy_order.updated_at}"
puts "Placed at #{proxy_order.placed_at}"
puts "Confirmed at #{proxy_order.confirmed_at}"
puts
puts "Order #{proxy_order.order_id} - #{proxy_order.order.number}"
puts "Order is #{proxy_order.order.state} with total #{proxy_order.order.total}"
proxy_order.order.payments.each do |payment|
puts "Payment #{payment.id} with state #{payment.state}"
puts "Amount #{payment.amount}"
puts "Source #{payment.source_type} #{payment.source_id}"
if payment.source_type == "Spree::CreditCard"
puts "Source #{payment.source.to_json}"
end
Spree::LogEntry.where(source_type: "Spree::Payment",
source_id: payment.id).each do |log_entry|
puts "Log Entries found"
puts log_entry.details
end
end
end
end
end
end
def request_order_cycle_id
puts "Please input Order Cycle ID to debug"
input = STDIN.gets.chomp
exit if input.blank? || !Integer(input)
Integer(input)
end
end
end
end
# rubocop:enable Metrics/BlockLength

View File

@@ -195,7 +195,7 @@ describe Admin::BulkLineItemsController, type: :controller do
it "returns an empty JSON response" do
spree_put :update, params
expect(response.body).to eq ' '
expect(response.body).to eq ""
end
it 'returns a 204 response' do
@@ -273,7 +273,7 @@ describe Admin::BulkLineItemsController, type: :controller do
it 'returns an empty JSON response' do
spree_delete :destroy, params
expect(response.body).to eq ' '
expect(response.body).to eq ""
end
it 'returns a 204 response' do

View File

@@ -27,6 +27,23 @@ module Spree
spree_post :confirm, payment_method_id: payment_method.id
expect(session[:access_token]).to eq(controller.current_order.token)
end
context "if the stock ran out whilst the payment was being placed" do
before do
allow(controller.current_order).to receive(:insufficient_stock_lines).and_return(true)
end
it "redirects to the cart with out of stock error" do
expect(spree_post(:confirm, payment_method_id: payment_method.id)).
to redirect_to cart_path
order = controller.current_order.reload
# Order is in "cart" state and did not complete processing of the payment
expect(order.state).to eq "cart"
expect(order.payments.count).to eq 0
end
end
end
describe '#expire_current_order' do

View File

@@ -70,7 +70,9 @@ describe UserConfirmationsController, type: :controller do
performing_deliveries do
expect do
spree_post :create, spree_user: { email: unconfirmed_user.email }
end.to send_confirmation_instructions
end.to enqueue_job ActionMailer::DeliveryJob
expect(enqueued_jobs.last.to_s).to match "confirmation_instructions"
end
end
end

View File

@@ -1,9 +1,9 @@
require 'ffaker'
FactoryBot.define do
sequence(:random_string) { Faker::Lorem.sentence }
sequence(:random_description) { Faker::Lorem.paragraphs(Kernel.rand(1..5)).join("\n") }
sequence(:random_email) { Faker::Internet.email }
sequence(:random_string) { FFaker::Lorem.sentence }
sequence(:random_description) { FFaker::Lorem.paragraphs(Kernel.rand(1..5)).join("\n") }
sequence(:random_email) { FFaker::Internet.email }
factory :classification, class: Spree::Classification do
end
@@ -112,7 +112,7 @@ FactoryBot.define do
end
factory :customer, class: Customer do
email { Faker::Internet.email }
email { generate(:random_email) }
enterprise
code { SecureRandom.base64(150) }
user

View File

@@ -20,11 +20,11 @@ FactoryBot.define do
end
trait :randomized do
firstname { Faker::Name.first_name }
lastname { Faker::Name.last_name }
address1 { Faker::Address.street_address }
firstname { FFaker::Name.first_name }
lastname { FFaker::Name.last_name }
address1 { FFaker::Address.street_address }
address2 nil
phone { Faker::PhoneNumber.phone_number }
phone { FFaker::PhoneNumber.phone_number }
end
end
end

View File

@@ -112,6 +112,27 @@ feature '
variant = product.variants.first
expect(variant.on_demand).to be true
end
scenario "creating product with empty unit value", js: true do
login_as_admin_and_visit spree.admin_products_path
click_link 'New Product'
fill_in 'product_name', with: 'Hot Cakes'
select 'New supplier', from: 'product_supplier_id'
select "Weight (kg)", from: 'product_variant_unit_with_scale'
select taxon.name, from: "product_primary_taxon_id"
fill_in 'product_price', with: '1.99'
fill_in 'product_on_hand', with: 0
check 'product_on_demand'
select 'Test Tax Category', from: 'product_tax_category_id'
find("div[id^='taTextElement']").native.send_keys('In demand, and on_demand! The hottest cakes in town.')
click_button 'Create'
expect(current_path).to eq spree.admin_products_path
expect(page).to have_content "Unit value can't be blank"
end
end
context "as an enterprise user" do

View File

@@ -124,7 +124,7 @@ feature "Managing users" do
# The `a` element doesn't have an href, so we can't use click_link.
find("a", text: "Resend").click
expect(page).to have_text "Resend done"
end.to send_confirmation_instructions
end.to enqueue_job ActionMailer::DeliveryJob
end
end
end

View File

@@ -21,23 +21,23 @@ feature "Account Settings", js: true do
end
it "allows the user to update their email address" do
performing_deliveries do
fill_in 'user_email', with: 'new@email.com'
fill_in 'user_email', with: 'new@email.com'
performing_deliveries do
expect do
click_button I18n.t(:update)
end.to send_confirmation_instructions
sent_mail = ActionMailer::Base.deliveries.last
expect(sent_mail.to).to eq ['new@email.com']
expect(find(".alert-box.success").text.strip).to eq "#{I18n.t('spree.account_updated')} ×"
user.reload
expect(user.email).to eq 'old@email.com'
expect(user.unconfirmed_email).to eq 'new@email.com'
click_link I18n.t('spree.users.show.tabs.settings')
expect(page).to have_content I18n.t('spree.users.show.unconfirmed_email', unconfirmed_email: 'new@email.com')
end.to enqueue_job ActionMailer::DeliveryJob
end
expect(enqueued_jobs.last.to_s).to match "new@email.com"
expect(find(".alert-box.success").text.strip).to eq "#{I18n.t('spree.account_updated')} ×"
user.reload
expect(user.email).to eq 'old@email.com'
expect(user.unconfirmed_email).to eq 'new@email.com'
click_link I18n.t('spree.users.show.tabs.settings')
expect(page).to have_content I18n.t('spree.users.show.unconfirmed_email',
unconfirmed_email: 'new@email.com')
end
it "allows the user to change their password" do

View File

@@ -82,7 +82,7 @@ feature "Authentication", js: true do
expect do
click_signup_button
expect(page).to have_content I18n.t('devise.user_registrations.spree_user.signed_up_but_unconfirmed')
end.to send_confirmation_instructions
end.to enqueue_job ActionMailer::DeliveryJob
end
end
end
@@ -104,8 +104,9 @@ feature "Authentication", js: true do
expect do
click_reset_password_button
expect(page).to have_reset_password
end.to enqueue_job Delayed::PerformableMethod
expect(Delayed::Job.last.payload_object.method_name).to eq(:send_reset_password_instructions_without_delay)
end.to enqueue_job ActionMailer::DeliveryJob
expect(enqueued_jobs.last.to_s).to match "reset_password_instructions"
end
context "user with unconfirmed email" do

View File

@@ -3,6 +3,8 @@ require "spec_helper"
feature "Check out with Paypal", js: true do
include ShopWorkflow
include CheckoutHelper
include AuthenticationHelper
include PaypalHelper
let(:distributor) { create(:distributor_enterprise) }
let(:supplier) { create(:supplier_enterprise) }
@@ -34,6 +36,7 @@ feature "Check out with Paypal", js: true do
distributor_ids: [distributor.id]
)
end
let(:user) { create(:user) }
before do
distributor.shipping_methods << free_shipping
@@ -41,23 +44,43 @@ feature "Check out with Paypal", js: true do
add_product_to_cart order, product
end
describe "as a guest" do
context "as a guest" do
it "fails with an error message" do
visit checkout_path
checkout_as_guest
fill_out_form(free_shipping.name, paypal.name, save_default_addresses: false)
paypal_response = double(:response, success?: false, errors: [])
paypal_provider = double(
:provider,
build_set_express_checkout: nil,
set_express_checkout: paypal_response
)
allow_any_instance_of(Spree::PaypalController).to receive(:provider).
and_return(paypal_provider)
stub_paypal_response success: false
place_order
expect(page).to have_content "PayPal failed."
end
end
context "as a registered user" do
before { login_as user }
it "completes the checkout after successful Paypal payment" do
visit checkout_path
fill_out_details
fill_out_form(free_shipping.name, paypal.name, save_default_addresses: false)
# Normally the checkout would redirect to Paypal, a form would be filled out there, and the
# user would be redirected back to #confirm_paypal_path. Here we skip the PayPal part and
# jump straight to being redirected back to OFN with a "confirmed" payment.
stub_paypal_response(
success: true,
redirect: spree.confirm_paypal_path(
payment_method_id: paypal.id, token: "t123", PayerID: 'p123'
)
)
stub_paypal_confirm
place_order
expect(page).to have_content "Your order has been processed successfully"
expect(order.reload.state).to eq "complete"
expect(order.payments.count).to eq 1
end
end
end

View File

@@ -1,42 +0,0 @@
require 'spec_helper'
describe HtmlHelper, type: :helper do
describe "stripping html from a string" do
it "strips tags" do
expect(helper.strip_html('<p><b>Hello</b> <em>world</em>!</p>')).to eq("Hello world!")
end
it "removes nbsp and amp entities" do
expect(helper.strip_html('Hello&nbsp;world&amp;&amp;')).to eq('Hello world&&')
end
it "returns nil for nil input" do
expect(helper.strip_html(nil)).to be_nil
end
describe "line breaks" do
it "adds two line breaks after heading tags" do
expect(helper.strip_html("<h1>foo</h1>bar")).to eq("foo\n\nbar");
expect(helper.strip_html("<h2>foo</h2>bar")).to eq("foo\n\nbar");
end
it "adds two line breaks after p tags" do
expect(helper.strip_html("<p>foo</p>bar")).to eq("foo\n\nbar");
end
it "adds two line breaks after div tags" do
expect(helper.strip_html("<div>foo</div>bar")).to eq("foo\n\nbar");
end
it "adds a line break after br tags" do
expect(helper.strip_html("foo<br>bar")).to eq("foo\nbar");
expect(helper.strip_html("foo<br/>bar")).to eq("foo\nbar");
expect(helper.strip_html("foo<br />bar")).to eq("foo\nbar");
end
it "strips line breaks at the end of the string" do
expect(helper.strip_html("<div>foo</div><br />")).to eq("foo");
end
end
end
end

View File

@@ -9,7 +9,7 @@ describe Spree::BaseHelper, type: :helper do
subject { helper.link_to_remove_fields(name, form, options) }
it 'returns an `a` tag followed by a hidden `input` tag' do
expect(subject).to eq("<a class=\"remove_fields icon_link with-tip icon-trash\" data-action=\"remove\" href=\"#\" title=\"Remove\"><span class='text'>Hola</span></a>&lt;input type=&quot;hidden&quot; name=&quot;_method&quot; value=&quot;destroy&quot;&gt;")
expect(subject).to eq("<a class=\"remove_fields icon_link with-tip icon-trash\" data-action=\"remove\" title=\"Remove\" href=\"#\"><span class='text'>Hola</span></a>&lt;input type=&quot;hidden&quot; name=&quot;_method&quot; value=&quot;destroy&quot;&gt;")
end
end
end

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