Compare commits

..

500 Commits

Author SHA1 Message Date
Maikel Linke
fddb76f002 Merge branch 'active-storage' into HEAD
Creating a seperate release off the master branch.
2022-06-08 12:05:56 +10:00
Maikel Linke
3e3fc4a5a2 Update translations 2022-06-03 10:43:36 +10:00
Filipe
4a2fd10bdb Merge pull request #9237 from mgrigoriev8109/bug/update-tracking-font
Fix shipped email tracking information font size
2022-06-02 18:37:27 +01:00
Filipe
1a2c1d004c Merge pull request #9239 from kvaithin/9233-spacing-between-btns
Add spacing between coordinator dropdown and continue button
2022-06-02 18:35:08 +01:00
Filipe
6ff2d4a9d5 Merge pull request #9109 from apricot12/8917-Link-to-enterprise-site
Adding a link to enterprise's own site from Order confirmation page.
2022-06-02 17:59:03 +01:00
Filipe
b3d81154e6 Merge pull request #9174 from georgethoppil/nan-items-subscription
Updating order cycle will ensure any $NaN subscription item prices to be recalculated
2022-06-02 17:28:54 +01:00
Filipe
4a15ed9b39 Merge pull request #9190 from georgethoppil/duplicate-transaction-fees
Destroy all adjustments on cart empty
2022-06-02 11:36:27 +01:00
jibees
1d8b8c3be8 Merge pull request #9253 from jibees/fix-deployment
add `@babel/preset` dependency
2022-06-02 10:42:18 +02:00
Jean-Baptiste Bellet
454a4e3435 add @babel/preset dependency
Add to dependencies (not dev ones)
2022-06-02 10:07:43 +02:00
Maikel Linke
076efd653d Correct checksum of big files stored on AWS S3 2022-06-02 12:28:52 +10:00
Maikel Linke
4facab0335 Guard against invariable file types
Australian production had one JPG image which was not recognised as
such. The `content_type` was missing and trying to generate a URL for a
variant raised an error and crashed the page.

Testing for `variable?` includes testing for `attached?` and is more
defensive.
2022-06-01 17:16:55 +10:00
Maikel Linke
bea080a9b1 Remove Paperclip
It has been replaced by Active Storage.
2022-06-01 17:16:55 +10:00
Maikel Linke
86731d7e30 Remove compatibility code for migrating files
The migration should be complete now.
2022-06-01 17:16:55 +10:00
Maikel Linke
b7efa1b018 Replace Paperclip on Spree::Image 2022-06-01 17:16:55 +10:00
Maikel Linke
4a0ed99919 Replace Paperclip on Enterprise model
We configured Paperclip to convert images to JPG in some cases but I
omitted that here because we don't need it. If an image is better
represented as PNG or another format then the user should be able to
choose that.

Some specs were also testing the generated URL but the Active Storage
URL doesn't contain a style name anymore and it's not helpful to test
the URL.
2022-06-01 17:16:55 +10:00
Maikel Linke
45995ac984 Replace Paperclip on EnterpriseGroup 2022-06-01 17:16:55 +10:00
Maikel Linke
421ffae78c Replace Paperclip on TermsOfServeFile 2022-06-01 17:16:54 +10:00
Maikel Linke
f29e569f1b Remove Paperclip migration code 2022-06-01 17:16:54 +10:00
Maikel Linke
727eef3c4f Replace Paperclippable ContentConfig
The old Paperclip configuration was very clever and easy to use but it
was also a complicated implementation building on the complicated Spree
preference system.

I simplified this with Active Storage, storing simple references to blob
ids and default URLs as backup.
2022-06-01 17:16:54 +10:00
jibees
ddd9ae6ce2 Merge pull request #9208 from openfoodfoundation/transifex
Transifex
2022-06-01 08:06:35 +02:00
Transifex-Openfoodnetwork
fd1cd4a28a Updating translations for config/locales/fr_CA.yml 2022-06-01 09:51:26 +10:00
Transifex-Openfoodnetwork
9261d7b8fe Updating translations for config/locales/en_CA.yml 2022-06-01 09:30:59 +10:00
Mikhail Grigoriev
b169f1baf1 Fix shipped email's tracking information font size using p.lead 2022-05-31 14:39:02 -04:00
Maikel Linke
2e05210596 Preview shipping emails with tracking if present 2022-05-31 14:36:28 -04:00
Maikel
8645277a05 Merge pull request #9204 from AgriculturaFamiliar/8755-fix-search-input
Select all text upon focus on map search input for Google Maps
2022-05-31 10:57:02 +10:00
Maikel
f3d9b3d7ed Merge pull request #9157 from jibees/SC-sort-shipping-methods-case-insenstive
Split Checkout: Sort shipping methods case insensitive
2022-05-31 10:54:43 +10:00
jibees
c22c1ddf32 Merge pull request #9243 from openfoodfoundation/dependabot/npm_and_yarn/storybook/addon-controls-6.5.6
Bump @storybook/addon-controls from 6.4.22 to 6.5.6
2022-05-30 17:41:12 +02:00
jibees
97f0d76fcd Merge pull request #9244 from openfoodfoundation/dependabot/npm_and_yarn/storybook/server-6.5.6
Bump @storybook/server from 6.4.22 to 6.5.6
2022-05-30 17:41:01 +02:00
dependabot[bot]
d70acb57b6 Bump @storybook/addon-controls from 6.4.22 to 6.5.6
Bumps [@storybook/addon-controls](https://github.com/storybookjs/storybook/tree/HEAD/addons/controls) from 6.4.22 to 6.5.6.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.6/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.5.6/addons/controls)

---
updated-dependencies:
- dependency-name: "@storybook/addon-controls"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-30 15:18:10 +00:00
dependabot[bot]
ab52028d1c Bump @storybook/server from 6.4.22 to 6.5.6
Bumps [@storybook/server](https://github.com/storybookjs/storybook/tree/HEAD/app/server) from 6.4.22 to 6.5.6.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.6/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.5.6/app/server)

---
updated-dependencies:
- dependency-name: "@storybook/server"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-30 15:17:03 +00:00
jibees
0544baa75c Merge pull request #9245 from openfoodfoundation/dependabot/npm_and_yarn/storybook/addon-docs-6.5.6
Bump @storybook/addon-docs from 6.4.22 to 6.5.6
2022-05-30 17:16:01 +02:00
dependabot[bot]
acda515c8a Bump @storybook/addon-docs from 6.4.22 to 6.5.6
Bumps [@storybook/addon-docs](https://github.com/storybookjs/storybook/tree/HEAD/addons/docs) from 6.4.22 to 6.5.6.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.5.6/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.5.6/addons/docs)

---
updated-dependencies:
- dependency-name: "@storybook/addon-docs"
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-30 09:05:55 +00:00
kvaithin
ad0effc565 spacing between co ordinator dropdown and continue btn 2022-05-28 11:13:16 +01:00
Maikel
b7cf397e15 Merge pull request #9227 from lin-d-hop/master
[Draft] Restore previous functionality for grouping product totals in Orders and Fulfilment reports
2022-05-26 10:18:11 +10:00
lin-d-hop
fb2279d26d Draft PR with potential fix to the reports S1. Untested. 2022-05-25 22:08:05 +01:00
Rachel Arnould
cb6cb05eca Merge pull request #9192 from jibees/9127-distinct-line-items-with-different-price
For all `orders_and_fulfillment` reports, distinct product by `variant`, `price` & `order_id`
2022-05-25 12:44:22 +02:00
Rachel Arnould
d0acd47935 Merge pull request #9219 from jibees/add-order-date-range-to-packing-reports
Add order date range to packing reports
2022-05-25 12:43:59 +02:00
Jean-Baptiste Bellet
e32797d2fd Do not group by order 2022-05-25 11:42:06 +02:00
Jean-Baptiste Bellet
f34b68a6e3 Add order date range to packing reports 2022-05-25 10:28:38 +02:00
jibees
f914a37a28 Merge pull request #9211 from openfoodfoundation/revert-9151-9140-fill-all-the-input-when-selecting-a-customer
Revert "When creating an order, and assigning a customer, fill all the customer inputs in the shipping/billing address form"
2022-05-24 10:35:46 +02:00
jibees
641df45fcd Revert "When creating an order, and assigning a customer, fill all the customer inputs in the shipping/billing address form" 2022-05-24 09:50:18 +02:00
georgethoppil
ec7d4b7c21 Restart checkout flow on cart empty if state of checkout is payment 2022-05-23 11:41:10 -04:00
Transifex-Openfoodnetwork
94f87b3bd7 Updating translations for config/locales/de_DE.yml 2022-05-23 22:33:33 +10:00
Maikel
a3d996d5f5 Merge pull request #9197 from openfoodfoundation/dependabot/npm_and_yarn/tom-select-2.0.3
Bump tom-select from 2.0.2 to 2.0.3
2022-05-23 16:47:13 +10:00
Diego de Araújo Martinez Camarinha
8a62d95c48 Select all text upon focus on map search input for Google Maps
On the map page, when we search a location and than want to search for
another, we would have to delete letter by letter of the previous search
text.

Now, when we click on the search input to type another search text, the
previous text will be all selected and we can remove everything with
just hitting the backspace once
2022-05-20 11:06:34 -03:00
Jean-Baptiste Bellet
7b2da4dbe4 Update all locales with the latest Transifex translations 2022-05-20 14:41:34 +02:00
jibees
0bb523c399 Merge pull request #9201 from openfoodfoundation/transifex
Transifex
2022-05-20 14:38:28 +02:00
Transifex-Openfoodnetwork
ca3c896b2e Updating translations for config/locales/nb.yml 2022-05-20 21:16:32 +10:00
Transifex-Openfoodnetwork
34286a8f8d Updating translations for config/locales/en_GB.yml 2022-05-20 21:13:33 +10:00
dependabot[bot]
533acda922 Bump tom-select from 2.0.2 to 2.0.3
Bumps [tom-select](https://github.com/orchidjs/tom-select) from 2.0.2 to 2.0.3.
- [Release notes](https://github.com/orchidjs/tom-select/releases)
- [Commits](https://github.com/orchidjs/tom-select/compare/v2.0.2...v2.0.3)

---
updated-dependencies:
- dependency-name: tom-select
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-20 09:05:25 +00:00
Jean-Baptiste Bellet
be88b95e8c orders_and_fulfillment reports, distinct product by variant & price 2022-05-19 10:42:53 +02:00
Maikel Linke
f4c7f24cce Remove old config option comment 2022-05-19 10:03:16 +10:00
Rachel Arnould
8779ef6b77 Merge pull request #9187 from jibees/9052-add-phone-number-to-alternative-invoice
Add phone number and email address to alternative invoice
2022-05-18 18:59:04 +02:00
Rachel Arnould
5dfc3c7a62 Merge pull request #9151 from jibees/9140-fill-all-the-input-when-selecting-a-customer
When creating an order, and assigning a customer, fill all the customer inputs in the shipping/billing address form
2022-05-18 17:41:59 +02:00
Rachel Arnould
9873380b94 Merge pull request #9185 from jibees/9184-remove-json-download-option-from-reports
Reports: Remove JSON as a download option
2022-05-18 10:11:33 +02:00
georgethoppil
a37f54e4b3 Find subscriptions in schedule to recalculate nil estimate price 2022-05-17 20:58:25 -04:00
georgethoppil
03b24bfc38 Destroy all adjustments on cart empty 2022-05-17 20:21:47 -04:00
Jean-Baptiste Bellet
cf687864cc Update specs to check on both invoice models presence of phone and email 2022-05-17 13:58:05 +02:00
Jean-Baptiste Bellet
d28545a7b2 Display both phone number and email to the alternative invoice 2022-05-17 12:10:41 +02:00
Jean-Baptiste Bellet
0b71f7298e Remove JSON as a download option 2022-05-17 10:47:19 +02:00
Maikel
9992f9c83b Merge pull request #9150 from mkllnk/active-storage-fix
Correct checksum in Paperclip migration task
2022-05-17 16:14:03 +10:00
jibees
f09b719af6 Merge pull request #9182 from openfoodfoundation/transifex
Transifex
2022-05-16 15:52:18 +02:00
Transifex-Openfoodnetwork
6b3ffddb74 Updating translations for config/locales/en_FR.yml 2022-05-16 20:35:31 +10:00
Transifex-Openfoodnetwork
0c7f962bf0 Updating translations for config/locales/fr.yml 2022-05-16 20:33:35 +10:00
Rachel Arnould
0f618dfbf9 Merge pull request #9032 from seballot/reports-improvement
Reports improvement
2022-05-16 10:29:28 +02:00
jibees
513b26f47c Merge pull request #9176 from openfoodfoundation/transifex
Transifex
2022-05-13 15:39:53 +02:00
jibees
2e3023eacc Merge pull request #9181 from openfoodfoundation/dependabot/npm_and_yarn/karma-6.3.20
Bump karma from 6.3.19 to 6.3.20
2022-05-13 15:38:29 +02:00
dependabot[bot]
2eeeb74374 Bump karma from 6.3.19 to 6.3.20
Bumps [karma](https://github.com/karma-runner/karma) from 6.3.19 to 6.3.20.
- [Release notes](https://github.com/karma-runner/karma/releases)
- [Changelog](https://github.com/karma-runner/karma/blob/master/CHANGELOG.md)
- [Commits](https://github.com/karma-runner/karma/compare/v6.3.19...v6.3.20)

---
updated-dependencies:
- dependency-name: karma
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-13 09:04:39 +00:00
Sebastian Castro
1be3b508bf Reports restore original results ordering 2022-05-12 16:54:14 +02:00
Sebastian Castro
294f7c2fb5 Reports restore original columns ordering 2022-05-12 16:54:14 +02:00
Sebastian Castro
89212736e9 Reports fix formatting cells 2022-05-12 16:54:14 +02:00
Sebastian Castro
35b5ca3a51 Csv Report: translate headers 2022-05-12 16:54:14 +02:00
Sebastian Castro
56fab26235 Reports: refactor to easily provide default_params 2022-05-12 16:54:14 +02:00
Sebastian Castro
b7991e5ae8 Packing Report: use field name as columns headers in spreadsheet export 2022-05-12 16:54:14 +02:00
Sebastian Castro
2008c10c6f Reports: use field name as header instead of translated value for raw renders (csv, json) 2022-05-12 16:54:14 +02:00
Sebastian Castro
0218f75f34 Packing Report: hide by default phone and price column to avoid breaking changes 2022-05-12 16:54:14 +02:00
Sebastian Castro
0545c9de28 Packing Report: revert column order change 2022-05-12 16:54:14 +02:00
Sebastian Castro
b54ec4354a Report TaxRate fix 2022-05-12 16:54:14 +02:00
Sebastian Castro
767afe1fba Reports Renderer: whitelist report formats 2022-05-12 16:54:14 +02:00
Sebastian Castro
2dd31d970e Reports Format cells: format some reports 2022-05-12 16:54:14 +02:00
Sebastian Castro
8a943f50ef Reports: Format cells for html, pdf, and spreadsheet
Currency, number format, dates
2022-05-12 16:54:14 +02:00
Sebastian Castro
3b01c44eae Reports: Improve Exports
Improve PDF style and encoding
Include header_row and summary_row, except for CSV and JSON
Style spreadsheets
Use only Xlsx no more Ods format
2022-05-12 16:54:14 +02:00
Sebastian Castro
5105ea345f Reports Refactor 4: Final Touch
Split report_template
Clean code
Adds spec
2022-05-12 16:54:14 +02:00
Sebastian Castro
b259f59d1e Packing Report: Adds new subreport "Pack by product" 2022-05-12 16:54:14 +02:00
Sebastian Castro
eeb525aedb Reports: Ability to hide columns 2022-05-12 16:54:14 +02:00
Sebastian Castro
9874c7996e Reports: Adds Print Button 2022-05-12 16:54:14 +02:00
Sebastian Castro
c7c5965eb5 Report Refactor 3 Clean
No longer need to handle old report class
Remove no longer used OrderGrouper service


sq
2022-05-12 16:54:14 +02:00
Sebastian Castro
cd30012334 Report Refactor 3: Xero Invoices
This one as actually not really been refactored, too much work to rewrite it so I just encapsulated the result within the new methods definitions
2022-05-12 16:54:14 +02:00
Sebastian Castro
42da443901 Report Refactor 3: Enterprise FeeSummary
This one as actually not really been refactored, too much work to rewrite it so I just encapsulated the result within the new methods definitions
2022-05-12 16:54:14 +02:00
Sebastian Castro
b3e1ffe9e2 Report Refactor 3: Products & Inventory 2022-05-12 16:54:14 +02:00
Sebastian Castro
71aca960ee Report Refactor 3: Order Cycle Management 2022-05-12 16:54:13 +02:00
Sebastian Castro
3808398807 Report Refactor 3: Payments 2022-05-12 16:54:13 +02:00
Sebastian Castro
93751f9ccb Report Refactor 3: Customers 2022-05-12 16:54:13 +02:00
Sebastian Castro
944d40e093 Report Refactor 3: BulkCoop 2022-05-12 16:54:13 +02:00
Sebastian Castro
22fe652e89 Report Refactor 3: Orders & Distributors 2022-05-12 16:54:13 +02:00
Sebastian Castro
7a9ed7a73c Report Refactor 3: Order & Fulfilment 2022-05-12 16:54:13 +02:00
Sebastian Castro
b25192c31d Report Refactor 3: Sales Tax 2022-05-12 16:54:13 +02:00
Sebastian Castro
529858946f Report Refactor 3: Packing
Stop using SQL for grouping, so we can use same grouping code than for other reports

Fix query builder default grouping_fields
2022-05-12 16:54:13 +02:00
Sebastian Castro
88bc417868 Report Refactor 3: User & Entreprises 2022-05-12 16:54:13 +02:00
Sebastian Castro
287e8f5845 Reports Refactor 3
Easily group and create header and summary row
Auto format cells when appropriate type (boolean, dates) and render_format (neither csv nor json)
2022-05-12 16:54:13 +02:00
Sebastian Castro
caccbb698b Reports Refactor 2: Fix linting 2022-05-12 16:54:13 +02:00
Sebastian Castro
452a3fa933 Reports Refactor 2: Merge Spree::reports into Admin::Reports 2022-05-12 16:54:13 +02:00
Sebastian Castro
288a35f062 Reports Refactor 2: New templates abstract classes 2022-05-12 16:54:13 +02:00
Sebastian Castro
5f78fdce8b Reports Refactor 2: Move all code to lib/reporting 2022-05-12 16:54:13 +02:00
Sebastian Castro
392166b57a Reports Refactor 2: Simplify render_content? method 2022-05-12 16:54:13 +02:00
Sebastian Castro
2985d2af15 Report Refactor 1 Cleaning
clean no longer used methods
Remove no longer needed require
Delete files not used
Fix Linting
2022-05-12 16:54:13 +02:00
Sebastian Castro
e9513f6172 Report Refactor 1: Enterprise Fee Summary
Disable enterprise fee summary spec for now

Will need to write them again
2022-05-12 16:54:13 +02:00
Sebastian Castro
4a99a7d1de Report Refactor 1: Xero Invoices 2022-05-12 16:54:13 +02:00
Sebastian Castro
41c11baa3f Report Refactor 1: Users & Entreprises 2022-05-12 16:54:13 +02:00
Sebastian Castro
3d1b61ae6e Report Refactor 1: Products & Inventory 2022-05-12 16:54:13 +02:00
Sebastian Castro
881a708ecf Report Refactor 1: Payments 2022-05-12 16:54:13 +02:00
Sebastian Castro
9d943625a3 Report Refactor 1: Sales Tax 2022-05-12 16:54:13 +02:00
Sebastian Castro
e20c2e3ced Report Refactor 1: Orders & Distributors 2022-05-12 16:54:13 +02:00
Sebastian Castro
01be6fb1f3 Report Refactor 1: Order Cycle Management 2022-05-12 16:54:13 +02:00
Sebastian Castro
1fee45035c Report Refactor 1: Customers 2022-05-12 16:54:12 +02:00
Sebastian Castro
e55462d18b Report Refactor 1: Orders & Fulfilment 2022-05-12 16:54:12 +02:00
Sebastian Castro
09247b21cd Reports Refactor 1
Use code closer to the new packing report controller
Handle nil @report_subtypes
2022-05-12 16:54:12 +02:00
Sebastian Castro
209b56ffd7 Packing Report: Better print 2022-05-12 16:54:12 +02:00
Sebastian Castro
cbb6bd63d4 Print: load css, hide navbar 2022-05-12 16:54:12 +02:00
Sebastian Castro
213c0dd060 Packing Report: add price and reorder columns
Adds price column
last_name column first because it's used for ordering
2022-05-12 16:54:12 +02:00
Sebastian Castro
d53d38906a Packing Report: Refactor view to be reusable by other reports
For now this view is used only in the context of packing, but later we would move all existing rpeort to use same view
2022-05-12 16:54:12 +02:00
Sebastian Castro
1ff98a1d8a Reports: Improve UI 2022-05-12 16:54:12 +02:00
Transifex-Openfoodnetwork
f012559ca8 Updating translations for config/locales/cy.yml 2022-05-12 21:06:24 +10:00
Maikel Linke
aafa416b9c Transifex update 2022-05-12 12:22:36 +10:00
Maikel
cae032a224 Merge pull request #9162 from openfoodfoundation/transifex
Transifex
2022-05-12 12:18:52 +10:00
Maikel Linke
94d8ada362 Use checksum of *original* image in Paperclip migration 2022-05-12 12:13:12 +10:00
Maikel Linke
92677385fa Correct checksum in Paperclip migration task
Active Storage needs a checksum for each file and AWS S3 provides this
checksum as "ETag". They are both MD5 but AWS stores it as hexdigest and
Active Storage as base64digest. We need to convert it from on to the
other to get a valid checksum for Active Storage.

Where the migration task has already run (only staging servers), delete all
Active Storage data first and then run the task again:

  bundle exec rake db:migrate:down VERSION=20220316055458
  bundle exec rake db:migrate

  bundle exec rake from_paperclip_to_active_storage:copy_content_config
  bundle exec rake from_paperclip_to_active_storage:migrate
2022-05-12 12:13:12 +10:00
Transifex-Openfoodnetwork
372939b260 Updating translations for config/locales/nb.yml 2022-05-12 11:26:47 +10:00
Transifex-Openfoodnetwork
8945d0cc33 Updating translations for config/locales/en_FR.yml 2022-05-12 11:23:43 +10:00
Transifex-Openfoodnetwork
8b05fb2210 Updating translations for config/locales/en_GB.yml 2022-05-12 11:23:40 +10:00
Maikel
c00a35b5a4 Merge pull request #9173 from jibees/9172-change-i18n-key-from-delivery-address-to-shipping-info
Split Checkout: Change i18n key on first step from delivery address to shipping info
2022-05-12 10:36:18 +10:00
georgethoppil
86a3f91ca2 When order cycle open/close times are updated, check to see if any subscription has line items that have price estimate as nil. Recalculate the price and save the column 2022-05-11 13:54:43 -04:00
georgethoppil
6a9fcbdd0c Adding a scope on subscription_line_item.rb to select records where price estimate is nil 2022-05-11 13:45:13 -04:00
Transifex-Openfoodnetwork
38d6b5d452 Updating translations for config/locales/ru.yml 2022-05-12 00:17:55 +10:00
Filipe
6141641c23 Merge pull request #9164 from jibees/9143-add-order-token-when-checkout-is-complete
Add `order_token` params to the redirect URL after checkout
2022-05-11 13:50:48 +01:00
Jean-Baptiste Bellet
d942adcdd0 Change i18n key on first step
Delivery address --> shipping info
2022-05-11 10:11:51 +02:00
Maikel
bfc3e385ba Merge pull request #9163 from openfoodfoundation/dependabot/npm_and_yarn/tom-select-2.0.2
Bump tom-select from 2.0.1 to 2.0.2
2022-05-11 14:02:25 +10:00
Nihal Mohammed
f5ecc6ffe4 Change gap between columns to fit new button 2022-05-09 23:29:40 +05:30
Jean-Baptiste Bellet
61f8dfd809 Add order_token params to the redirect URL after checkout 2022-05-09 17:45:52 +02:00
dependabot[bot]
51db3d5997 Bump tom-select from 2.0.1 to 2.0.2
Bumps [tom-select](https://github.com/orchidjs/tom-select) from 2.0.1 to 2.0.2.
- [Release notes](https://github.com/orchidjs/tom-select/releases)
- [Commits](https://github.com/orchidjs/tom-select/compare/v2.0.1...v2.0.2)

---
updated-dependencies:
- dependency-name: tom-select
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-09 09:56:35 +00:00
Transifex-Openfoodnetwork
87ec803fba Updating translations for config/locales/en_GB.yml 2022-05-09 18:37:33 +10:00
Transifex-Openfoodnetwork
37a9338d0c Updating translations for config/locales/nb.yml 2022-05-09 17:59:00 +10:00
Transifex-Openfoodnetwork
3eccb65407 Updating translations for config/locales/en_FR.yml 2022-05-09 17:50:50 +10:00
Transifex-Openfoodnetwork
c1864fb8e5 Updating translations for config/locales/fr.yml 2022-05-09 17:50:43 +10:00
Maikel
44965ff235 Fix MAPI conditional on master 2022-05-09 12:35:52 +10:00
Maikel
e59d753333 Merge pull request #9044 from georgethoppil/optional-restock-items
Optional restock items
2022-05-09 09:08:26 +10:00
GeorgeThoppil
8903496a1b Optional restocking items 2022-05-06 10:55:24 -04:00
Jean-Baptiste Bellet
edc0520ce3 Update all locales with the latest Transifex translations 2022-05-06 09:51:36 +02:00
jibees
bf5e7a12d1 Merge pull request #9142 from openfoodfoundation/transifex
Transifex
2022-05-06 09:48:47 +02:00
Jean-Baptiste Bellet
9c231a831d Replace Angular directive and use stimulus controller
+ Update specs as well
2022-05-05 14:53:32 +02:00
Jean-Baptiste Bellet
f2ac888f2c Sort shipping methods case insensitive 2022-05-05 14:37:27 +02:00
Filipe
fb834d3143 Merge pull request #9138 from jibees/9137-order-shipping-methods-alphabetically
Split checkout: Order shipping methods by name
2022-05-05 12:41:12 +01:00
Filipe
24acf21c6d Merge pull request #9139 from jibees/6139-handle-shipping-method-description-with-no-space
Split Checkout: Handle shipping/payment method description with no space
2022-05-05 11:21:13 +01:00
Maikel Linke
ec7d7b0ad8 Fix workflow conditional 2022-05-05 14:22:39 +10:00
Maikel
ae728caac6 Merge pull request #9156 from mkllnk/mapi-condition
Run Mayhem4API CI check only within organisation
2022-05-05 14:01:51 +10:00
Maikel Linke
2758f83a2a Run Mayhem4API only within organisation
The API key is not accessible outside.
2022-05-05 12:10:08 +10:00
Transifex-Openfoodnetwork
5162c5ecf9 Updating translations for config/locales/en_GB.yml 2022-05-03 20:19:09 +10:00
Maikel
5ff1c1c7c2 Merge pull request #9136 from mayhemheroes/mapi
add Mayhem for API as a github workflow
2022-05-03 16:00:26 +10:00
Jean-Baptiste Bellet
c98d669b92 Create a SelectCustomer controller
To be used in `/admin/orders/ORDER_ID/customer` page

 - Fetch `/admin/search/customers.json?` with query as params
 - Render each items response thanks to `renderOption()` method
 - `onItemSelect()` is here to fill the associated form in the page
2022-05-02 13:36:49 +02:00
Jean-Baptiste Bellet
11b224f805 Prepare tom-select controller to inherit others controllers 2022-05-02 13:33:57 +02:00
Filipe
664e2a5423 Merge pull request #9057 from jibees/9038-handle-payment-errors-on-split-checkout
Split checkout: handle cards that throws any errors
2022-05-02 12:20:02 +01:00
Transifex-Openfoodnetwork
183a6f8fc7 Updating translations for config/locales/nb.yml 2022-04-29 19:14:57 +10:00
Jean-Baptiste Bellet
d7df714280 Formatting file 2022-04-29 10:36:53 +02:00
Jean-Baptiste Bellet
132ab28070 Handle very long description without any space for shipping and ...
... payment methods
2022-04-29 10:15:50 +02:00
Jean-Baptiste Bellet
89aa76dbbc Handle long payment description with no space 2022-04-29 10:15:50 +02:00
Jean-Baptiste Bellet
4635e67707 Create mixins to force wrap
No need to pre-wrap since we break-word
2022-04-29 10:15:50 +02:00
Transifex-Openfoodnetwork
8945142149 Updating translations for config/locales/en_FR.yml 2022-04-29 17:58:47 +10:00
Transifex-Openfoodnetwork
7cb6afbd96 Updating translations for config/locales/fr.yml 2022-04-29 17:49:58 +10:00
Maikel Linke
30ea017fa2 Update translations 2022-04-29 10:23:58 +10:00
Maikel
126a6aa84a Merge pull request #9114 from openfoodfoundation/fix-docker-setup
Fix Docker setup to ease entry for new contributors
2022-04-29 10:18:56 +10:00
Maikel
e2eb92fd90 Merge pull request #9119 from mkllnk/active-storage-part1
Store files with Active Storage in addition to Paperclip
2022-04-29 10:10:36 +10:00
J. David Lowe
ff1b895286 switch to openfoodfoundation 2022-04-28 14:42:24 -07:00
J. David Lowe
da2e7b404f add Mayhem for API as a github workflow 2022-04-28 13:30:34 -07:00
Filipe
ce9bd37c9b Merge pull request #9117 from jibees/9085-add-additionnal-items-in-/cart-page-for-split-checkout
Split checkout: Unless order is complete, /cart could be updated
2022-04-28 19:59:08 +01:00
Filipe
d57d812ab4 Merge pull request #9110 from georgethoppil/update-subscription-deleted-product
Return if variant is deleted
2022-04-28 15:54:51 +01:00
Jean-Baptiste Bellet
99c0416cc7 Handle long shipping method description with no spaces 2022-04-28 10:40:28 +02:00
jibees
335de1d038 Merge pull request #9121 from openfoodfoundation/transifex
Transifex
2022-04-28 10:10:13 +02:00
Transifex-Openfoodnetwork
5b9a5c1df6 Updating translations for config/locales/fr_CA.yml 2022-04-28 07:38:59 +10:00
Transifex-Openfoodnetwork
72641ba317 Updating translations for config/locales/en_CA.yml 2022-04-28 07:26:44 +10:00
Jean-Baptiste Bellet
34fcb4a1f7 Order shipping methods by name
+ create spec
2022-04-27 16:37:37 +02:00
Jean-Baptiste Bellet
b370ee328a Click twice on "Next - Order summary" button
yes, this is a hack, but can't make it work as a normal behavior. For testing purpose, we use `spec/support/fixtures/stripejs-mock.js` and it seems not working with our `app/webpacker/controllers/stripe_controller.js`
2022-04-27 15:43:05 +02:00
Jean-Baptiste Bellet
5fe8060ea6 Actually don't use requestSubmit() as it is not supported by Safari
https://caniuse.com/?search=requestSubmit
2022-04-27 15:43:05 +02:00
Jean-Baptiste Bellet
a8afe7fee3 Use requestSubmit() method for actually submit the form with event
... that could be catch by turbo (and then handled by cable_ready)

`this.catchFormSubmit` avoid infinite loop then
2022-04-27 15:43:05 +02:00
Jean-Baptiste Bellet
8bbb80ef55 Catch GatewayError exception and handle by updating flash[:error] 2022-04-27 15:43:05 +02:00
François Turbelin
fe2ee57cb3 Use Install Bundler script in Dockerfile 2022-04-25 22:40:50 +02:00
Nihal Mohammed
af58ba523c Renamed groups_helper to link_helper and removed strip_url method, as well as updated specs and ApplicationHelper. Added "Back To Website" button and i18n. 2022-04-26 01:38:25 +05:30
Maikel Linke
9dc3c5a06c Add task for ContentConfig image migration 2022-04-25 13:00:31 +10:00
Maikel Linke
1c1f9d73a3 Add task to migrate existing files to Active Storage
Common migrations look for all models with *_file_name attributes but I
found that unreliable in our code base. It finds too many model classes
and doesn't allow us to be more selective in the migration. So I used
our own migration declaration to migrate exactly those attachments
specified.
2022-04-25 13:00:31 +10:00
Maikel Linke
0b885b3954 Protect terms of service from migration updates
Active Storage always touches associated records when attachments are
changed. But for the Terms of Service it's important to keep the
updated_at date because that's how we find out how new it is and if a
customer accepted those terms already.

And while we migrate files, the content of the files will stay the same
and we don't want customers to be asked to accept the same terms again.
2022-04-25 13:00:31 +10:00
Maikel Linke
7bcfda0a52 Duplicate all new Paperclip files to ActiveStorage
We do this for all models in the code base. There's one special case,
the ConentConfiguration which is not a model and we can't use the same
approach there. We will have to deal with that separately later.
2022-04-25 13:00:31 +10:00
Maikel Linke
92bbcbb7ce Process correct attachment when model has several
Luckily Paperclip has designated callbacks for processing each
attachment separately. We can just hook into that.
2022-04-25 13:00:31 +10:00
Maikel Linke
c36ad96acc Move file duplication code to concern to share
I chose `has_one_migrating` as method name for two reasons:

 1. It reflects Active Storage's method `has_one_attached`.
 2. And it has the same length as Paperclip's `has_attached_file`.
    Therefore the commits don't need any whitespace changes.

When we change it to `has_one_attached`, we will also remove the
Paperclip options which then don't need whitespace changes either.
2022-04-25 13:00:31 +10:00
Maikel Linke
ec64e5c8f7 Store images with Active Storage as well
While we migrate from Paperclip to Active Storage, we need to use both
at the same time to avoid any downtime or lost images.

Once the migration is complete, we want to use the same name for
attachment as before. Using Paperclip and Active Storage at the same
time creates a name conflict on a couple of methods.

I'm using alias_method as a temporary solution to access Active Storage
methods. We will remove that after the migration. I declare Paperclip
afterwards so that we have those methods declarations for backwards
compatibility now.
2022-04-25 13:00:31 +10:00
Maikel Linke
95cb6e93e7 Configure Active Storage
We are re-using the same config used for Paperclip except for disk
storage. Active Storage uses directory sharding on the local disk which
means that we can't create blob entries that point to the existing
Paperclip files. We will just copy them to the standard `storage/`
directory.
2022-04-25 13:00:30 +10:00
Maikel Linke
ce0e33fffa Install Active Storage database tables 2022-04-25 13:00:30 +10:00
Maikel Linke
b6cdb04a27 Activate Active Storage 2022-04-25 13:00:30 +10:00
Maikel Linke
92bb23d914 Add validation gem for Active Storage
We used validations with Paperclip and it would be nice to keep them.
2022-04-25 13:00:30 +10:00
Maikel Linke
4eb550431e Add gems required by Active Storage 2022-04-25 13:00:30 +10:00
Transifex-Openfoodnetwork
8330339046 Updating translations for config/locales/en_FR.yml 2022-04-22 23:23:38 +10:00
Transifex-Openfoodnetwork
e34d4c773c Updating translations for config/locales/fr.yml 2022-04-22 23:20:59 +10:00
Transifex-Openfoodnetwork
e669ed9620 Updating translations for config/locales/nb.yml 2022-04-22 23:04:37 +10:00
Jean-Baptiste Bellet
6262dc3a2e Update all locales with the latest Transifex translations 2022-04-22 12:09:03 +02:00
Filipe
cb540d66c6 Merge pull request #9084 from jibees/9046-property-filter-on-shopfront
Fix an issue which prevented filtering by properties and sorting by category on a shopfront.
2022-04-22 11:03:31 +01:00
Filipe
1f80c2add4 Merge pull request #9087 from georgethoppil/enterprise-invisible
Change enterprise visibility scope
2022-04-22 10:52:32 +01:00
GeorgeThoppil
898c470c00 Change enterprise visibility scope 2022-04-21 20:27:28 -04:00
GeorgeThoppil
2046317f16 Allow update of subscriptions containing deleted products 2022-04-21 20:23:34 -04:00
jibees
413c97cfa8 Merge pull request #9118 from openfoodfoundation/transifex
Transifex
2022-04-21 15:45:44 +02:00
Transifex-Openfoodnetwork
2b4d9be907 Updating translations for config/locales/fr.yml 2022-04-21 23:27:52 +10:00
Transifex-Openfoodnetwork
8f9c50a311 Updating translations for config/locales/it.yml 2022-04-21 23:24:47 +10:00
Jean-Baptiste Bellet
9306e054b8 Unless order is complete, /cart could be updated
Split_checkout introduced new state for an order

Update specs as well

Follow up #8944
2022-04-21 14:22:39 +02:00
Filipe
4ea1dd68af Merge pull request #9023 from apricot12/8908-Access-Enterprise-perms-from-setting-page
Enterprise can access permissions from enterprise edit page
2022-04-21 13:21:27 +01:00
jibees
9cb3dc4c42 Merge pull request #9102 from openfoodfoundation/transifex
Transifex
2022-04-21 13:44:26 +02:00
Filipe
2ddc64ce4d Merge pull request #9072 from mkllnk/remove-taxon-icons
Remove unused icons from Spree::Taxon
2022-04-21 11:46:57 +01:00
Transifex-Openfoodnetwork
1aae8bba99 Updating translations for config/locales/it.yml 2022-04-21 20:35:27 +10:00
Jean-Baptiste Bellet
3e5656e638 Remove distinct to make proper ORDER BY
Update specs as well to test match array and test duplication by adding property2 to product1
2022-04-21 11:03:22 +02:00
Jean-Baptiste Bellet
96f267eefe Create specs for filtering by properties when sorting is available
+ update product, supplier, taxon name to be more precise
2022-04-21 11:03:22 +02:00
Maikel
30e68450d2 Merge pull request #9116 from openfoodfoundation/dependabot/npm_and_yarn/babel-loader-8.2.5
Bump babel-loader from 8.2.4 to 8.2.5
2022-04-21 11:11:43 +10:00
Maikel
2b3db15505 Merge pull request #9115 from openfoodfoundation/dependabot/npm_and_yarn/karma-6.3.19
Bump karma from 6.3.18 to 6.3.19
2022-04-21 11:10:24 +10:00
Transifex-Openfoodnetwork
99beacf723 Updating translations for config/locales/en_FR.yml 2022-04-21 01:39:08 +10:00
Transifex-Openfoodnetwork
67453de649 Updating translations for config/locales/fr.yml 2022-04-21 01:38:45 +10:00
Filipe
f516b7056d Merge pull request #8863 from georgethoppil/payment-state-cancel-subscription-order
Setting payment state for subscription order
2022-04-20 13:14:57 +01:00
Filipe
1f6b5ef309 Merge pull request #8979 from jibees/6300-dont-submit-form-element-that-are-not-handled-by-backend
shipping fees on admin: avoid backend error when updating calculator type
2022-04-20 12:23:32 +01:00
dependabot[bot]
7528e878dc Bump babel-loader from 8.2.4 to 8.2.5
Bumps [babel-loader](https://github.com/babel/babel-loader) from 8.2.4 to 8.2.5.
- [Release notes](https://github.com/babel/babel-loader/releases)
- [Changelog](https://github.com/babel/babel-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel-loader/compare/v8.2.4...v8.2.5)

---
updated-dependencies:
- dependency-name: babel-loader
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-20 09:06:14 +00:00
dependabot[bot]
2981c35482 Bump karma from 6.3.18 to 6.3.19
Bumps [karma](https://github.com/karma-runner/karma) from 6.3.18 to 6.3.19.
- [Release notes](https://github.com/karma-runner/karma/releases)
- [Changelog](https://github.com/karma-runner/karma/blob/master/CHANGELOG.md)
- [Commits](https://github.com/karma-runner/karma/compare/v6.3.18...v6.3.19)

---
updated-dependencies:
- dependency-name: karma
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-20 09:05:58 +00:00
Maikel
06dbb3b545 Merge pull request #9108 from openfoodfoundation/dependabot/npm_and_yarn/tom-select-2.0.1
Bump tom-select from 2.0.0 to 2.0.1
2022-04-20 14:46:41 +10:00
Maikel
2da7e9ab44 Merge pull request #9107 from openfoodfoundation/dependabot/npm_and_yarn/moment-2.29.3
Bump moment from 2.29.2 to 2.29.3
2022-04-20 14:45:09 +10:00
Maikel
a145b97c28 Merge pull request #9103 from jibees/add-customer-id-to-order-endpoint-on-api
API: Add customer_id as an attribute to the GET /orders/ORDER_ID endpoint
2022-04-20 14:28:31 +10:00
Maikel
3985c9fb06 Merge pull request #9094 from openfoodfoundation/dependabot/npm_and_yarn/flatpickr-4.6.13
Bump flatpickr from 4.6.11 to 4.6.13
2022-04-20 14:24:49 +10:00
Maikel
67d3bd7414 Merge pull request #9040 from cillian/stimulus-js-help-modals
Switch help modals from angular templates to use ViewComponent and StimulusJs
2022-04-20 12:14:41 +10:00
Cillian O'Ruanaidh
4162830bee Switch help modals from angular templates to use ViewComponent and StimulusJs 2022-04-20 09:36:30 +10:00
François Turbelin
c004f16c9a Update Postgres version into Docker Compose configuration 2022-04-19 22:15:13 +02:00
Jean-Baptiste Bellet
e607d5c161 Shipping method: disabled form element to not submit them
As they're not handled by the backend
2022-04-19 15:16:07 +02:00
Jean-Baptiste Bellet
4b629eae11 Test that fee can be updated from weight to Flat Rate
+ Missing some spree i18n keys
2022-04-19 14:28:18 +02:00
Jean-Baptiste Bellet
6f5dd5ab0c Prepare to receive another test in the same context 2022-04-19 14:28:18 +02:00
Jean-Baptiste Bellet
a6c69c8530 Ensure that form element are well disabled to not submit them
As they're not handled by the backend
2022-04-19 14:28:18 +02:00
Transifex-Openfoodnetwork
6276a90258 Updating translations for config/locales/en_FR.yml 2022-04-19 18:27:52 +10:00
Transifex-Openfoodnetwork
4a65333a83 Updating translations for config/locales/fr.yml 2022-04-19 18:27:25 +10:00
Maikel
268a73a41d Merge pull request #9104 from jibees/get-rid-of-rubocop-MissingSuper-warning-on-ViewComponent-class
Exclude ViewComponents from Rubocop MissingSuper rule
2022-04-19 10:41:08 +10:00
Filipe
4dde49c881 Merge pull request #8991 from jibees/8985-Make-checkbox-for-Send-a-cancellation-email-to-the-customer-checked-by-default
Admin, editing order, on last item deletion modal: "Send a cancellation email to the customer" checked by default
2022-04-18 14:04:08 +01:00
Filipe
f831154b6f Merge pull request #8950 from jibees/5903-delete-coordinators_fees-linked-to-cloned-OC
Delete linked coordinators fees when deleting an order cycle
2022-04-18 11:55:53 +01:00
dependabot[bot]
91448c18f2 Bump tom-select from 2.0.0 to 2.0.1
Bumps [tom-select](https://github.com/orchidjs/tom-select) from 2.0.0 to 2.0.1.
- [Release notes](https://github.com/orchidjs/tom-select/releases)
- [Commits](https://github.com/orchidjs/tom-select/compare/v2.0.0...v2.0.1)

---
updated-dependencies:
- dependency-name: tom-select
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-18 09:05:16 +00:00
dependabot[bot]
d82f7c3c4d Bump moment from 2.29.2 to 2.29.3
Bumps [moment](https://github.com/moment/moment) from 2.29.2 to 2.29.3.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/2.29.3/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.29.2...2.29.3)

---
updated-dependencies:
- dependency-name: moment
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-18 09:05:03 +00:00
Transifex-Openfoodnetwork
7516cf6de3 Updating translations for config/locales/ar.yml 2022-04-17 04:18:27 +10:00
Transifex-Openfoodnetwork
0c2a3a9bb6 Updating translations for config/locales/de_DE.yml 2022-04-16 23:20:42 +10:00
Filipe
01e915800e Merge pull request #9037 from jibees/9028-last-item-of-order-cancellation
BOM: show custom modal on last item deletion of an order
2022-04-15 18:47:51 +01:00
dependabot[bot]
2c67d6d238 Bump flatpickr from 4.6.11 to 4.6.13
Bumps [flatpickr](https://github.com/chmln/flatpickr) from 4.6.11 to 4.6.13.
- [Release notes](https://github.com/chmln/flatpickr/releases)
- [Commits](https://github.com/chmln/flatpickr/compare/v4.6.11...v4.6.13)

---
updated-dependencies:
- dependency-name: flatpickr
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-15 17:08:50 +00:00
Filipe
4009f3313f Merge pull request #8814 from Matt-Yorkley/tom-select
Introduce new select/dropdown library
2022-04-15 18:08:08 +01:00
Filipe
54d64c1c2c Merge pull request #8841 from apricot12/8790_display_stock_left_shop
Display remaining stock in shopfront if enabled in shop preferences
2022-04-15 17:58:40 +01:00
Filipe
db3ca2e66e Merge pull request #9098 from mkllnk/toggle-api
Feature-toggle API also per API key
2022-04-15 16:14:48 +01:00
Jean-Baptiste Bellet
b60eeb8dc4 Exclude ViewComponents from MissingSuper rule as it's unnecessary
Source: https://viewcomponent.org/#whats-a-viewcomponent
2022-04-15 14:36:42 +02:00
Jean-Baptiste Bellet
d38e14ca5c Add customer_id as an attribute to order_detailed_serializer
Therefor customer_id will be available on the order object for `/api/v0/orders/[ORDER_ID].json` endpoint
2022-04-15 14:23:55 +02:00
Transifex-Openfoodnetwork
a75af09c58 Updating translations for config/locales/en_IE.yml 2022-04-15 20:46:33 +10:00
jibees
8825ff2711 Merge pull request #9099 from openfoodfoundation/dependabot/npm_and_yarn/async-2.6.4
Bump async from 2.6.3 to 2.6.4
2022-04-15 12:03:43 +02:00
dependabot[bot]
0b56cdabea Bump async from 2.6.3 to 2.6.4
Bumps [async](https://github.com/caolan/async) from 2.6.3 to 2.6.4.
- [Release notes](https://github.com/caolan/async/releases)
- [Changelog](https://github.com/caolan/async/blob/v2.6.4/CHANGELOG.md)
- [Commits](https://github.com/caolan/async/compare/v2.6.3...v2.6.4)

---
updated-dependencies:
- dependency-name: async
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-15 08:20:54 +00:00
jibees
1149278a48 Merge pull request #9093 from openfoodfoundation/dependabot/npm_and_yarn/storybook/server-6.4.22
Bump @storybook/server from 6.4.21 to 6.4.22
2022-04-15 10:19:53 +02:00
dependabot[bot]
3a4713b8c9 Bump @storybook/server from 6.4.21 to 6.4.22
Bumps [@storybook/server](https://github.com/storybookjs/storybook/tree/HEAD/app/server) from 6.4.21 to 6.4.22.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.4.22/app/server)

---
updated-dependencies:
- dependency-name: "@storybook/server"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-15 07:50:33 +00:00
jibees
5635f5ad46 Merge pull request #9096 from openfoodfoundation/dependabot/npm_and_yarn/storybook/addon-docs-6.4.22
Bump @storybook/addon-docs from 6.4.21 to 6.4.22
2022-04-15 09:49:35 +02:00
dependabot[bot]
c4431ccac6 Bump @storybook/addon-docs from 6.4.21 to 6.4.22
Bumps [@storybook/addon-docs](https://github.com/storybookjs/storybook/tree/HEAD/addons/docs) from 6.4.21 to 6.4.22.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.4.22/addons/docs)

---
updated-dependencies:
- dependency-name: "@storybook/addon-docs"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-15 07:27:47 +00:00
jibees
1e4f096639 Merge pull request #9095 from openfoodfoundation/dependabot/npm_and_yarn/storybook/addon-controls-6.4.22
Bump @storybook/addon-controls from 6.4.21 to 6.4.22
2022-04-15 09:26:55 +02:00
jibees
6ba255ce85 Merge pull request #9000 from filipefurtad0/adds_coverage_tags_on_details_step
Adds basic coverage on tag functionality on payment methods
2022-04-15 09:22:43 +02:00
Maikel Linke
2e989083bd Remove unused icons from Spree:Taxon
The icons are not used any more and the default icon file never existed
in our code base (only in Spree when we depended on that).

And it's better to remove this clutter before migrating those files to
Active Storage.

We are keeping the icon files in storage as a backup. The whole folder
`/spree/taxons` can be deleted when desired. But storage is cheap.
2022-04-15 16:50:28 +10:00
Maikel Linke
3e02db7bd9 Update translations 2022-04-15 13:06:31 +10:00
dependabot[bot]
86bd6cb102 Bump @storybook/addon-controls from 6.4.21 to 6.4.22
Bumps [@storybook/addon-controls](https://github.com/storybookjs/storybook/tree/HEAD/addons/controls) from 6.4.21 to 6.4.22.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.4.22/addons/controls)

---
updated-dependencies:
- dependency-name: "@storybook/addon-controls"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-15 02:57:43 +00:00
Maikel
5eca0a7811 Merge pull request #9090 from openfoodfoundation/dependabot/npm_and_yarn/karma-6.3.18
Bump karma from 6.3.17 to 6.3.18
2022-04-15 12:56:56 +10:00
Maikel Linke
ba1e21ad75 Feature-toggle API also per API key
We looked only at logged in users (session cookie) before.
2022-04-15 12:34:57 +10:00
Maikel
28de8bbb8d Merge pull request #9083 from filipefurtad0/updating_properties_specs
Updating properties specs
2022-04-15 11:25:32 +10:00
Nihal Mohammed
0327cc0d0b Update i18n to be more informative 2022-04-15 10:59:42 +10:00
Nihal Mohammed
15e7a5a4df Rename product_stock_display to product_low_stock_display
Rename product_stock_display to product_low_stock_display in enterprise_serializer and shop_variant_controller
2022-04-15 10:59:42 +10:00
Nihal Mohammed
66386683b6 Add system spec
Fix linter errors
2022-04-15 10:56:26 +10:00
Jean-Baptiste Bellet
1ea2656bfb i18n for shop preferences in admin 2022-04-15 10:53:28 +10:00
Jean-Baptiste Bellet
af69064d3a Add mocked shopfront 2022-04-15 10:53:28 +10:00
Jean-Baptiste Bellet
1c68293cac Display remaining stock for variant in the shopfront
Display only if all conditions are met:
 - Variant is not a bulk buy
 - Shop preference is true for `preferred_product_stock_display`
 - Only 3 (or less) items are remaining in stock
 - No item for this variant is already to cart
2022-04-15 10:53:28 +10:00
Jean-Baptiste Bellet
143c977a19 i18n for shop preferences 2022-04-15 10:53:28 +10:00
Nihal M. Kelanthodika
356d759dbe Add Display stock option to enterprises form 2022-04-15 10:53:28 +10:00
Nihal M. Kelanthodika
f7a767988c Add preferred_product_stock_display to Enterprise model, serializer and permitted attributes. (Fixed alignment of guest orders radio button as well) 2022-04-15 10:53:28 +10:00
filipefurtad0
029df03ee6 Improves naming and styling 2022-04-14 14:40:59 +01:00
jibees
c001463f8a Merge pull request #9091 from openfoodfoundation/transifex
Transifex
2022-04-14 15:27:22 +02:00
jibees
727aa553e7 Merge pull request #9088 from mkllnk/9024-setup-script
Update setup script for removed callbacks
2022-04-14 14:48:02 +02:00
GeorgeThoppil
8aa4631e21 Setting payment state for subscription order 2022-04-13 19:08:51 -04:00
filipefurtad0
c8b5ce64a4 Adds coverage for hiding payment methods with tags 2022-04-13 23:44:54 +01:00
filipefurtad0
aed757e349 Adds tests on shopfront ordering preference setting 2022-04-13 23:38:03 +01:00
filipefurtad0
18572cbbfa Adds sorting by product to reproduce #9046; sets assertion as pending 2022-04-13 23:38:03 +01:00
filipefurtad0
f3706bdb00 Adds taxon and property filtering 2022-04-13 21:55:23 +01:00
Filipe
cbb9e01a25 Merge pull request #8884 from Matt-Yorkley/image-format-errors
Patch keyword arguments syntax in Paperclip error handling
2022-04-13 19:38:07 +01:00
Filipe
94bba56726 Merge pull request #9063 from georgethoppil/select-all-variants
Add all variants for only one distributor
2022-04-13 19:37:31 +01:00
Filipe
0cc056ab7f Merge pull request #9071 from Matt-Yorkley/permissions-query-improvements
Improve permissions query building
2022-04-13 19:23:13 +01:00
Transifex-Openfoodnetwork
5444d0d0b9 Updating translations for config/locales/de_DE.yml 2022-04-13 23:16:53 +10:00
Nihal Mohammed
d23846bfa2 Add Enterprise Settings to admin enterprises edit side menu, adds redirect_function to side menu services. 2022-04-13 17:03:04 +05:30
Filipe
6b1dd00dec Merge pull request #9011 from cillian/validate-subscription-quantity
Don't allow subscriptions with no quantity to be saved
2022-04-13 12:03:34 +01:00
Transifex-Openfoodnetwork
aa75c2defe Updating translations for config/locales/en_FR.yml 2022-04-13 20:24:41 +10:00
Transifex-Openfoodnetwork
dd905e4388 Updating translations for config/locales/fr.yml 2022-04-13 20:24:38 +10:00
Filipe
fbe378d3b9 Merge pull request #9074 from hmurali01/translate-shipping-method
Fixed missing translation: "Shipping method"
2022-04-13 11:01:16 +01:00
Transifex-Openfoodnetwork
d5fbb40b93 Updating translations for config/locales/en_FR.yml 2022-04-13 19:45:33 +10:00
Transifex-Openfoodnetwork
1dc57a3518 Updating translations for config/locales/fr.yml 2022-04-13 19:44:14 +10:00
dependabot[bot]
c6e982b0f9 Bump karma from 6.3.17 to 6.3.18
Bumps [karma](https://github.com/karma-runner/karma) from 6.3.17 to 6.3.18.
- [Release notes](https://github.com/karma-runner/karma/releases)
- [Changelog](https://github.com/karma-runner/karma/blob/master/CHANGELOG.md)
- [Commits](https://github.com/karma-runner/karma/compare/v6.3.17...v6.3.18)

---
updated-dependencies:
- dependency-name: karma
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-13 09:04:15 +00:00
jibees
0d29fc78c3 Merge pull request #9089 from mkllnk/cuprite-host
Include port in URLs generated by system specs
2022-04-13 09:52:47 +02:00
Maikel Linke
4d8c44d890 Include port in URLs generated by system specs
This means that we can follow generated links, for example in emails and
reach the test app server.
2022-04-13 15:03:38 +10:00
Maikel Linke
4eb2b5d483 Reduce method complexity 2022-04-13 14:55:54 +10:00
Maikel Linke
a3a1e27cb1 Update setup script for removed callbacks
We removed some Spree magic a while back and that broke our sample data
script. This is now corrected.

I also added a spec so that we will notice broken seed data earlier.
2022-04-13 14:48:30 +10:00
Maikel
a4bffc61f1 Merge pull request #8997 from apricot12/8968-Group-products-by-supplier-P1
Sort products by supplier in invoice
2022-04-13 11:54:12 +10:00
Maikel
26d6969b5b Merge pull request #9045 from jibees/9043-send-email-cancelation-by-default
Send cancellation email by default when cancelling an order
2022-04-13 11:53:43 +10:00
Maikel
e6c65f524a Merge pull request #9033 from seballot/select2-multiple
select2: improve style
2022-04-13 09:37:13 +10:00
jibees
762b6fad65 Merge pull request #9079 from openfoodfoundation/dependabot/npm_and_yarn/storybook/addon-docs-6.4.21
Bump @storybook/addon-docs from 6.4.20 to 6.4.21
2022-04-12 14:14:47 +02:00
dependabot[bot]
48246117cd Bump @storybook/addon-docs from 6.4.20 to 6.4.21
Bumps [@storybook/addon-docs](https://github.com/storybookjs/storybook/tree/HEAD/addons/docs) from 6.4.20 to 6.4.21.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.4.21/addons/docs)

---
updated-dependencies:
- dependency-name: "@storybook/addon-docs"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-12 11:53:50 +00:00
jibees
bf8186bb84 Merge pull request #9077 from openfoodfoundation/dependabot/npm_and_yarn/storybook/addon-controls-6.4.21
Bump @storybook/addon-controls from 6.4.20 to 6.4.21
2022-04-12 13:53:02 +02:00
Maikel
fd804d819e Merge pull request #9078 from openfoodfoundation/dependabot/npm_and_yarn/storybook/server-6.4.21
Bump @storybook/server from 6.4.20 to 6.4.21
2022-04-12 11:05:41 +10:00
Maikel Linke
5e0c901790 Improve spec of sorted line items
The previous version wasn't actually testing the sorting option. There
was only one supplier and the items got sorted the same way in both
cases.
2022-04-12 10:45:40 +10:00
filipefurtad0
760e7ad6e2 Adds assertion on displaying/hidding the Properties tab 2022-04-11 22:30:54 +01:00
Nihal Mohammed
48613a4b42 Add test for sorted_line_items 2022-04-11 20:11:32 +05:30
dependabot[bot]
1aed6d0ee6 Bump @storybook/server from 6.4.20 to 6.4.21
Bumps [@storybook/server](https://github.com/storybookjs/storybook/tree/HEAD/app/server) from 6.4.20 to 6.4.21.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.4.21/app/server)

---
updated-dependencies:
- dependency-name: "@storybook/server"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-11 09:05:51 +00:00
dependabot[bot]
65faf33b87 Bump @storybook/addon-controls from 6.4.20 to 6.4.21
Bumps [@storybook/addon-controls](https://github.com/storybookjs/storybook/tree/HEAD/addons/controls) from 6.4.20 to 6.4.21.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/next/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.4.21/addons/controls)

---
updated-dependencies:
- dependency-name: "@storybook/addon-controls"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-11 09:05:36 +00:00
Jean-Baptiste Bellet
99161a19ea Update all locales with the latest Transifex translations 2022-04-11 09:43:00 +02:00
jibees
8b047cd449 Merge pull request #9073 from openfoodfoundation/transifex
Transifex
2022-04-11 09:36:08 +02:00
Transifex-Openfoodnetwork
b2b8ec8008 Updating translations for config/locales/ar.yml 2022-04-11 02:10:24 +10:00
Transifex-Openfoodnetwork
2087a17fa9 Updating translations for config/locales/de_DE.yml 2022-04-08 17:43:34 +10:00
Transifex-Openfoodnetwork
0eb77cf7d3 Updating translations for config/locales/en_FR.yml 2022-04-08 17:22:25 +10:00
Transifex-Openfoodnetwork
3fc71c0e99 Updating translations for config/locales/fr.yml 2022-04-08 17:21:35 +10:00
Filipe
afcdfce37d Merge pull request #8967 from mkllnk/api-customers-final
Serve customers data via first API v1 endpoint in JSON:API format behind feature toggle
2022-04-07 21:03:06 +01:00
hmurali01
d16b6fcad5 Fixed missing translation: "Shipping method" 2022-04-07 13:28:32 -04:00
Transifex-Openfoodnetwork
cb697599d4 Updating translations for config/locales/ru.yml 2022-04-07 19:12:28 +10:00
Maikel
d0a93fb512 Merge pull request #9070 from jibees/clean-yarn-lock-file
Clean yarn.lock due to failed update
2022-04-07 16:03:27 +10:00
Matt-Yorkley
eef59bbaae Improve permissions query building
For larger queries and especially where filtering and paginating, these simpler product queries are way more efficient. It cuts out some very large subqueries with large lists of product ids.
2022-04-05 22:28:09 +01:00
Matt-Yorkley
7181694401 Include the little search icon for dropdowns with a search box 2022-04-05 18:56:52 +01:00
Matt-Yorkley
7753d9e1ea Use TomSelect and dependent-select controller in admin order customer details form and remove ancient jQuery which uses global functions and inline scripts
🎉
2022-04-05 18:56:51 +01:00
Matt-Yorkley
be9156d40f Refactor dependant-selector further and (conditionally) update TomSelect if present
I'm also introducing a convention here of adding a `private` comment to visually demarcate which methods are meant to be part of the public interface of the class and which aren't. The methods aren't *actually* private in any technical sense, it's just a bit of syntactic sugar to allow the intention to be communicated more clearly in the code's structure.
2022-04-05 18:56:51 +01:00
Matt-Yorkley
09bd7126d8 Replace/remove a custom select2 Angular directive 2022-04-05 18:56:51 +01:00
Matt-Yorkley
9bce2ca64c Allow initializing with custom TomSelect configurations 2022-04-05 18:56:51 +01:00
Matt-Yorkley
fedfeb6dd3 Add dropdown "primary" style with blue instead of white 2022-04-05 18:56:51 +01:00
Matt-Yorkley
6459d9ea36 Replace some simple dropdowns 2022-04-05 18:56:51 +01:00
Matt-Yorkley
5e3e8c32c3 Create a simple Stimulus controller and add basic styling 2022-04-05 18:56:51 +01:00
Matt-Yorkley
ff3cc6e771 Add TomSelect package 2022-04-05 18:56:51 +01:00
Jean-Baptiste Bellet
ad19142042 Clean yarn.lock
Seems that dependant bot missed something at some point maybe from  #9061 or #9060
2022-04-05 14:47:13 +02:00
Maikel
5470dc6c68 Merge pull request #9065 from openfoodfoundation/dependabot/npm_and_yarn/moment-2.29.2
Bump moment from 2.29.1 to 2.29.2
2022-04-05 11:21:49 +10:00
GeorgeThoppil
706f6025e9 Add all variants for only one distributor 2022-04-04 19:59:42 -04:00
jibees
ea12fcb45f Merge pull request #9061 from openfoodfoundation/dependabot/npm_and_yarn/storybook/server-6.4.20
Bump @storybook/server from 6.4.19 to 6.4.20
2022-04-04 15:51:21 +02:00
jibees
47c59e6172 Merge pull request #9060 from openfoodfoundation/dependabot/npm_and_yarn/storybook/addon-controls-6.4.20
Bump @storybook/addon-controls from 6.4.19 to 6.4.20
2022-04-04 15:51:13 +02:00
dependabot[bot]
5b6c23780e Bump @storybook/addon-controls from 6.4.19 to 6.4.20
Bumps [@storybook/addon-controls](https://github.com/storybookjs/storybook/tree/HEAD/addons/controls) from 6.4.19 to 6.4.20.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.4.20/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.4.20/addons/controls)

---
updated-dependencies:
- dependency-name: "@storybook/addon-controls"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-04 13:15:54 +00:00
dependabot[bot]
374bc31a60 Bump @storybook/server from 6.4.19 to 6.4.20
Bumps [@storybook/server](https://github.com/storybookjs/storybook/tree/HEAD/app/server) from 6.4.19 to 6.4.20.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.4.20/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.4.20/app/server)

---
updated-dependencies:
- dependency-name: "@storybook/server"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-04 13:15:48 +00:00
jibees
d34ab71efa Merge pull request #9059 from openfoodfoundation/dependabot/npm_and_yarn/storybook/addon-docs-6.4.20
Bump @storybook/addon-docs from 6.4.19 to 6.4.20
2022-04-04 15:14:58 +02:00
dependabot[bot]
abdab5a22a Bump moment from 2.29.1 to 2.29.2
Bumps [moment](https://github.com/moment/moment) from 2.29.1 to 2.29.2.
- [Release notes](https://github.com/moment/moment/releases)
- [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
- [Commits](https://github.com/moment/moment/compare/2.29.1...2.29.2)

---
updated-dependencies:
- dependency-name: moment
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-04 09:04:59 +00:00
Maikel Linke
e726d2d736 Update translations 2022-04-04 10:40:10 +10:00
Maikel
044bf35c81 Merge pull request #9062 from openfoodfoundation/transifex
Transifex
2022-04-04 10:35:45 +10:00
Transifex-Openfoodnetwork
010b39b671 Updating translations for config/locales/en_FR.yml 2022-04-02 00:31:06 +11:00
Transifex-Openfoodnetwork
4079e61beb Updating translations for config/locales/fr.yml 2022-04-02 00:28:05 +11:00
Transifex-Openfoodnetwork
dc00221dc4 Updating translations for config/locales/de_DE.yml 2022-04-02 00:28:01 +11:00
Transifex-Openfoodnetwork
eef9dc346d Updating translations for config/locales/en_CA.yml 2022-04-02 00:24:54 +11:00
Filipe
f29dc3f978 Merge pull request #9009 from jibees/9007-already-opened-cart
SplitCheckout: add already opened cart message on summary step when distributor allow order changes
2022-04-01 13:29:34 +01:00
dependabot[bot]
1a66c1148b Bump @storybook/addon-docs from 6.4.19 to 6.4.20
Bumps [@storybook/addon-docs](https://github.com/storybookjs/storybook/tree/HEAD/addons/docs) from 6.4.19 to 6.4.20.
- [Release notes](https://github.com/storybookjs/storybook/releases)
- [Changelog](https://github.com/storybookjs/storybook/blob/v6.4.20/CHANGELOG.md)
- [Commits](https://github.com/storybookjs/storybook/commits/v6.4.20/addons/docs)

---
updated-dependencies:
- dependency-name: "@storybook/addon-docs"
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-04-01 09:04:16 +00:00
Filipe
c4fc8e9396 Merge pull request #8988 from jibees/8963-sc-display-save-shipping-address-as-default-checkbox
SplitCheckout: Display checkbox that "save as default address" on the /details page
2022-03-31 16:43:52 +01:00
Filipe
e2b1c0d93f Merge pull request #9004 from jibees/8999-filter-shipping-methods-with-tag
SplitCheckout: filter shipping method with tag
2022-03-31 12:09:06 +01:00
Filipe
71b6c129d6 Merge pull request #9021 from filipefurtad0/improves_guest_checkout
[Split-Checkout] Hides "Save as default billing address" from guest-checkout
2022-03-31 10:45:47 +01:00
Jean-Baptiste Bellet
20142ca632 Add a spec on canceling an order, and check email is sent
Co-Authored-By: Maikel <maikel@email.org.au>
2022-03-31 09:18:43 +02:00
jibees
8929fa4dcd Merge pull request #9042 from openfoodfoundation/transifex
Transifex
2022-03-30 10:27:58 +02:00
filipefurtad0
843f57ad4f Removes checkbox attributes 2022-03-29 22:29:43 +01:00
filipefurtad0
95b1911f38 Hides the default address checkbox for guest customers 2022-03-29 22:09:39 +01:00
filipefurtad0
f8b8298fbe Adds spec on billing address checkbox 2022-03-29 22:09:39 +01:00
Jean-Baptiste Bellet
6a48bdbb82 Send email cancelation by default 2022-03-29 10:12:00 +02:00
Transifex-Openfoodnetwork
85ff203e3f Updating translations for config/locales/en_FR.yml 2022-03-29 00:27:46 +11:00
Transifex-Openfoodnetwork
f229479a1e Updating translations for config/locales/en_US.yml 2022-03-29 00:24:41 +11:00
Transifex-Openfoodnetwork
10685b4ca2 Updating translations for config/locales/en_CA.yml 2022-03-29 00:24:38 +11:00
Filipe
729e9eda66 Merge pull request #9013 from cillian/fix-order-cycle-advanced-settings-close-button
Fix order cycle advanced settings close button so it uses new remote toggle StimulusJs controller instead of old toggleSettings method
2022-03-28 14:10:11 +01:00
Nihal Mohammed
b2613f3331 Add translations 2022-03-28 18:26:39 +05:30
Nihal Mohammed
5f2f5456a0 Add code to sort order by supplier when Enterprise user chooses to 2022-03-28 18:12:39 +05:30
Filipe
be1c255067 Merge pull request #8892 from Matt-Yorkley/spree-login-routes
Fix issue with unconfirmed email messages
2022-03-28 13:38:17 +01:00
Filipe
a516193ca8 Merge pull request #9025 from MrFuku/fix-flash-message
Fix untranslated flash message
2022-03-28 13:18:47 +01:00
Filipe
6a71be2a6b Merge pull request #9029 from cbordei/ofn-8459-missing-translation-for-model
Added missing translation for model name.
2022-03-28 12:54:24 +01:00
Transifex-Openfoodnetwork
1c2a60d543 Updating translations for config/locales/en_GB.yml 2022-03-28 19:59:34 +11:00
Maikel
a4a5586345 Merge pull request #9035 from openfoodfoundation/dependabot/npm_and_yarn/minimist-1.2.6
Bump minimist from 1.2.5 to 1.2.6
2022-03-28 12:17:08 +11:00
Maikel Linke
742ae761a3 Move helper statement to controller
It's not available in concerns.
2022-03-28 11:34:37 +11:00
Maikel Linke
379eda7c41 Add feature toggle for API v1 use
Dev, test and staging need to activate the feature toggle now before
it's accessible.
2022-03-28 11:04:30 +11:00
Maikel Linke
3e00ab261e Spec customer relationships on API 2022-03-28 11:04:30 +11:00
Maikel Linke
5063f377c3 Enable relationship inclusion for customers#show
This will allow us to include address records.
2022-03-28 11:04:30 +11:00
Maikel Linke
d789fb32e9 Make customer's address writable on API 2022-03-28 11:04:30 +11:00
Maikel Linke
51420934f3 Add billing and shipping address to customer 2022-03-28 10:58:18 +11:00
Maikel Linke
adc7e97e62 Add tag list to customer endpoint 2022-03-28 10:55:58 +11:00
Maikel Linke
e5e8953a09 Add ToS acceptance to customer endpoint
It's another read-only attribute.

Please note that JSON:API specifies a format of `date-time` which we
don't adhere to because it uses a `Z` in front of the timezone offset
which doesn't seem to be included in the default json serialisation.

So I didn't add the format and left it as simple `string`. Problem?
2022-03-28 10:55:58 +11:00
Maikel Linke
aa6e5ae799 Report useful error message in missing parameter 2022-03-28 10:55:57 +11:00
Maikel Linke
8d12c7a692 Permit more customer attributes for update 2022-03-28 10:55:57 +11:00
Maikel Linke
41746459fa Restrict allow_charges attribute to read-only
We want people to use the UI to change this attribute.
2022-03-28 10:55:57 +11:00
Maikel Linke
3baed683b1 Add allow_charges attribute to customers endpoint 2022-03-28 10:55:57 +11:00
Transifex-Openfoodnetwork
5fb94dcb22 Updating translations for config/locales/en_US.yml 2022-03-28 01:54:20 +11:00
Matt-Yorkley
913a4560d1 Update all locales with the latest Transifex translations 2022-03-25 19:57:51 +00:00
Matt-Yorkley
cc19dc7d03 Merge pull request #9020 from openfoodfoundation/transifex
Transifex
2022-03-25 19:55:05 +00:00
Matt-Yorkley
ad5c834342 Merge pull request #8995 from apricot12/7853-deprecation-warnings-1
7853 deprecation warnings 1
2022-03-25 19:54:06 +00:00
Jean-Baptiste Bellet
17989b2f90 Update tests as well around order cancellation on item deletion
js specs are not that easy to code (needs to spy callback...). Use system spec instead.
2022-03-25 11:52:08 +01:00
Jean-Baptiste Bellet
c9248f872d Remplace window.confirm by ofnCancelOrderAlert
to prevent use that the order will be canceled
2022-03-25 11:28:10 +01:00
Jean-Baptiste Bellet
a71e95da27 ofnCancelOrderAlert can accept i18n key to customize message 2022-03-25 11:10:54 +01:00
Jean-Baptiste Bellet
b9efda9f64 Add custom confirm modal into the BOM interface 2022-03-25 10:58:33 +01:00
Transifex-Openfoodnetwork
4800abf324 Updating translations for config/locales/fr_CA.yml 2022-03-24 22:54:06 +11:00
Transifex-Openfoodnetwork
f73f3b17e1 Updating translations for config/locales/en_CA.yml 2022-03-24 22:49:05 +11:00
Sebastian Castro
66cdd56428 select2-light: make it looks like normal select 2022-03-24 10:44:18 +00:00
dependabot[bot]
d759409e38 Bump minimist from 1.2.5 to 1.2.6
Bumps [minimist](https://github.com/substack/minimist) from 1.2.5 to 1.2.6.
- [Release notes](https://github.com/substack/minimist/releases)
- [Commits](https://github.com/substack/minimist/compare/1.2.5...1.2.6)

---
updated-dependencies:
- dependency-name: minimist
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-24 08:46:20 +00:00
jibees
b9e18a1ec1 Merge pull request #9030 from openfoodfoundation/dependabot/npm_and_yarn/babel-loader-8.2.4
Bump babel-loader from 8.2.3 to 8.2.4
2022-03-24 09:19:42 +01:00
jibees
9a5318965c Use as an helper
Co-Authored-By: Maikel <maikel@email.org.au>
2022-03-24 09:11:58 +01:00
Maikel
9230329343 Merge pull request #9003 from mkllnk/old-conf
Remove old config comments
2022-03-24 11:48:20 +11:00
dependabot[bot]
3901a18b72 Bump babel-loader from 8.2.3 to 8.2.4
Bumps [babel-loader](https://github.com/babel/babel-loader) from 8.2.3 to 8.2.4.
- [Release notes](https://github.com/babel/babel-loader/releases)
- [Changelog](https://github.com/babel/babel-loader/blob/main/CHANGELOG.md)
- [Commits](https://github.com/babel/babel-loader/compare/v8.2.3...v8.2.4)

---
updated-dependencies:
- dependency-name: babel-loader
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-23 09:11:17 +00:00
Cristian Bordei
4730bbdc36 [OFN-8459] Added missing translation for model name. 2022-03-23 09:57:57 +02:00
Sebastian Castro
9e55a306ee select2-multiple: improve style 2022-03-22 16:32:29 +00:00
Transifex-Openfoodnetwork
2758097776 Updating translations for config/locales/ar.yml 2022-03-23 02:14:03 +11:00
Transifex-Openfoodnetwork
f5eb83c483 Updating translations for config/locales/en_FR.yml 2022-03-23 00:18:04 +11:00
Transifex-Openfoodnetwork
aafe7c90a8 Updating translations for config/locales/fr.yml 2022-03-23 00:17:35 +11:00
Transifex-Openfoodnetwork
64ba004e5d Updating translations for config/locales/de_DE.yml 2022-03-23 00:13:57 +11:00
Filipe
6d0d57a4d2 Merge pull request #8960 from filipefurtad0/covers_default_addresses
Covers default billing address checkbox behavior
2022-03-22 09:10:42 +00:00
MrFuku
7c1a4d6791 Fix untranslated flash message 2022-03-22 17:53:57 +09:00
Maikel
877002afd8 Merge pull request #8891 from mkllnk/api-customers
Create API v1 with customers endpoint
2022-03-22 19:37:23 +11:00
Nihal Mohammed
cc120aecb6 Add radio buttons to give Enterprise choice on sorting of items by name or supplier in invoice 2022-03-21 20:29:19 +05:30
Nihal Mohammed
992cb9d920 Add invoice_order_by_supplier attribute to enterprise 2022-03-21 20:29:19 +05:30
Transifex-Openfoodnetwork
b9d3eef381 Updating translations for config/locales/en_GB.yml 2022-03-21 21:48:11 +11:00
jibees
532d566308 Merge pull request #9014 from openfoodfoundation/transifex
Transifex
2022-03-21 09:32:27 +01:00
Transifex-Openfoodnetwork
eae8129435 Updating translations for config/locales/en_FR.yml 2022-03-19 02:50:56 +11:00
Transifex-Openfoodnetwork
ed0ed3240e Updating translations for config/locales/fr.yml 2022-03-19 02:47:16 +11:00
Transifex-Openfoodnetwork
5d8cdc3246 Updating translations for config/locales/de_DE.yml 2022-03-19 01:36:44 +11:00
Transifex-Openfoodnetwork
27e31ae09d Updating translations for config/locales/de_DE.yml 2022-03-19 01:36:01 +11:00
Transifex-Openfoodnetwork
f4ce08d39c Updating translations for config/locales/de_DE.yml 2022-03-19 01:31:31 +11:00
Filipe
87c79a5941 Merge pull request #8294 from guidoDutra/8131-cancel-empty-orders-on-BOM-page
Cancel empty orders on BOM page
2022-03-18 11:24:26 +00:00
filipefurtad0
7bdf814d7d Uses change helper to remove before block;
Adds a & - Safe Navigation Operator - to the customer object
2022-03-17 19:31:40 +00:00
Filipe
19270f1777 Merge pull request #8987 from jibees/8981-BOM-correct-value-for-current-and-max-fullfilled
BOM: correct max and current fulfilled units values
2022-03-17 18:15:59 +00:00
Filipe
f079fcb49a Merge pull request #8992 from openfoodfoundation/dependabot/npm_and_yarn/flatpickr-4.6.11
Bump flatpickr from 4.6.9 to 4.6.11
2022-03-17 16:52:49 +00:00
Cillian O'Ruanaidh
1c80e88758 Fix order cycle advanced settings close button so it uses new remote toggle StimulusJs controller instead of old toggleSettings method
Closes #9012
2022-03-17 16:30:26 +00:00
Filipe
c535ed5789 Merge pull request #8936 from cillian/language-metatags
Include language metatags in html template when more than one language available
2022-03-17 16:16:07 +00:00
Filipe
53544ee66a Merge pull request #8805 from cillian/remove-inline-advanced-settings-toggle-js
Replace inline JS for toggling order cycle advanced settings with StimulusJs controller
2022-03-17 16:05:46 +00:00
Jean-Baptiste Bellet
621933c727 Improve spec by creating its opposite
ie. when distributor don't allow order changes
2022-03-17 16:47:16 +01:00
Jean-Baptiste Bellet
df6cd5b266 Add already ordered panel only on summary step 2022-03-17 16:47:16 +01:00
filipefurtad0
790bcc9ff2 Adds spec on open order information 2022-03-17 16:47:16 +01:00
Jean-Baptiste Bellet
6f6ad05ac2 Factorize some css rules for panel 2022-03-17 16:47:16 +01:00
Jean-Baptiste Bellet
ac361d3b64 Add already_opened on each step 2022-03-17 16:47:16 +01:00
Jean-Baptiste Bellet
13a45557a4 Load cart already opened boolean
thanks to EnterprisesHelper
2022-03-17 16:47:16 +01:00
Filipe
0dd398abba Merge pull request #8926 from mkllnk/8925-invalid-param
Gracefully handle admin UI failure on updating enterprise notifications
2022-03-17 14:19:34 +00:00
jibees
56912bb807 Merge pull request #9010 from openfoodfoundation/transifex
Transifex
2022-03-17 14:21:41 +01:00
Cillian O'Ruanaidh
7446dfb0b7 Don't allow subscriptions with no quantity to be saved
Before you could save a subscription even if the line item(s) it contained had 0 quantity.

For #8903
2022-03-17 11:54:24 +00:00
Transifex-Openfoodnetwork
37801f1345 Updating translations for config/locales/en_IE.yml 2022-03-17 22:14:51 +11:00
jibees
43b284a175 Merge pull request #9005 from openfoodfoundation/transifex
Transifex
2022-03-17 11:04:47 +01:00
Maikel
ab5a323044 Merge pull request #8980 from openfoodfoundation/dependabot/npm_and_yarn/karma-chrome-launcher-3.1.1
Bump karma-chrome-launcher from 3.1.0 to 3.1.1
2022-03-17 09:47:11 +11:00
Transifex-Openfoodnetwork
08755acfd1 Updating translations for config/locales/hu.yml 2022-03-17 04:39:12 +11:00
Jean-Baptiste Bellet
c9e40d084c Add spec around shipping methods filter for a guest + logged user 2022-03-16 11:14:02 +01:00
Jean-Baptiste Bellet
0948ce47ed Use EnterprisesHelper to retrieve shipping methods
that apply tag filtering on shipping methods
2022-03-16 11:10:46 +01:00
jibees
3a0f50395f Merge pull request #8989 from openfoodfoundation/transifex
Transifex
2022-03-16 10:41:55 +01:00
Maikel Linke
4606d81a28 Remove old config comments
SSL is enforced via `config.force_ssl = true` in the same files. We
don't need that comment any more.
2022-03-16 17:29:59 +11:00
filipefurtad0
4bdce59648 Clarifies context 2022-03-15 16:30:38 +00:00
filipefurtad0
ba5bdf688c Removes new address assignment; uses change helper 2022-03-15 16:14:44 +00:00
Nihal Mohammed
df7227443a Replace deprecated any_instace syntax with allow_any_instance_of in spec/system/consumer/registration_spec.rb 2022-03-15 05:35:43 +05:30
Nihal Mohammed
b3771bb623 Use bypass_sign_in method instead of bypass option in app/controllers/spree/users_controller.rb 2022-03-15 05:35:43 +05:30
Nihal Mohammed
8ceeaaa7d4 Fix deprecated Object warning in lib/spree/localized_number 2022-03-15 05:35:43 +05:30
Nihal Mohammed
ad52805a0d Change errors to be accessed by a block with single paramter instead of hash 2022-03-15 05:35:22 +05:30
filipefurtad0
f09f6df181 Adds coverage on shipping address 2022-03-14 13:49:32 +00:00
filipefurtad0
13b7d80632 Saves address for user 2022-03-14 13:14:11 +00:00
Nihal Mohammed
ccc3322c12 Change deprecated file path upload path syntax in enterprises_controller_spec 2022-03-14 18:42:58 +05:30
Nihal Mohammed
0f6b335a22 Change deprecated syntax File.exists? to File.exist? 2022-03-14 18:41:00 +05:30
filipefurtad0
6ba351f68f Updates spec to consider bug fix #8958 2022-03-14 12:51:20 +00:00
filipefurtad0
4877f96b4b Adds coverage on default billing address checkbox 2022-03-14 12:48:00 +00:00
filipefurtad0
ffe2a3076c Cleans up helper file and spec 2022-03-14 11:52:24 +00:00
Transifex-Openfoodnetwork
fb83ae2ad4 Updating translations for config/locales/en_GB.yml 2022-03-14 22:48:06 +11:00
dependabot[bot]
b9e0a5ecf7 Bump flatpickr from 4.6.9 to 4.6.11
Bumps [flatpickr](https://github.com/chmln/flatpickr) from 4.6.9 to 4.6.11.
- [Release notes](https://github.com/chmln/flatpickr/releases)
- [Commits](https://github.com/chmln/flatpickr/compare/v4.6.9...v4.6.11)

---
updated-dependencies:
- dependency-name: flatpickr
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-14 09:05:55 +00:00
Jean-Baptiste Bellet
ea3e15f0c8 Max|Current fulfilled value is the max|current divided by group_buy_unit_size
+ improve testing with representative values
 + Update bulk_order_management_spec.rb and revert previously changed values
2022-03-14 09:06:05 +01:00
Jean-Baptiste Bellet
bcf6c7984e Display checkbox that "save as default address" 2022-03-14 09:05:45 +01:00
Jean-Baptiste Bellet
08d4aea2b9 "Send a cancellation email to the customer" checked by default 2022-03-14 09:05:17 +01:00
jibees
483ec42328 Merge pull request #8990 from jibees/8984-sc-test-failed
SplitCheckout: improve test that failed
2022-03-14 09:03:26 +01:00
Jean-Baptiste Bellet
65596f8467 Do not replace shipping_methods array but push into 2022-03-11 14:34:58 +01:00
Transifex-Openfoodnetwork
d273e97b88 Updating translations for config/locales/de_DE.yml 2022-03-12 00:29:23 +11:00
Transifex-Openfoodnetwork
b410585449 Updating translations for config/locales/en_FR.yml 2022-03-11 23:43:53 +11:00
Transifex-Openfoodnetwork
ac08602d94 Updating translations for config/locales/fr.yml 2022-03-11 23:43:14 +11:00
dependabot[bot]
0b1697c62b Bump karma-chrome-launcher from 3.1.0 to 3.1.1
Bumps [karma-chrome-launcher](https://github.com/karma-runner/karma-chrome-launcher) from 3.1.0 to 3.1.1.
- [Release notes](https://github.com/karma-runner/karma-chrome-launcher/releases)
- [Changelog](https://github.com/karma-runner/karma-chrome-launcher/blob/master/CHANGELOG.md)
- [Commits](https://github.com/karma-runner/karma-chrome-launcher/compare/v3.1.0...v3.1.1)

---
updated-dependencies:
- dependency-name: karma-chrome-launcher
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-03-10 09:05:18 +00:00
Jean-Baptiste Bellet
7ca6434b14 Improve the test to delete a cloned order_cycle 2022-03-04 11:34:19 +01:00
Jean-Baptiste Bellet
5fc7d72b09 Check destroying order_cycle will delete associated coordinator fees 2022-03-03 09:06:38 +01:00
Jean-Baptiste Bellet
771f7b0393 Delete coordinators_fees linked to an order_cycle when it is destroyed 2022-03-02 11:00:04 +01:00
Maikel Linke
12d989568e Safer API error reporting
We don't know what unknown errors would report. They could expose
sensitive data. So let's not pass that data on to the public while we
have the full details in Bugsnag.

Also, let's not catch Exception because that could catch interrupts to
gracefully shut down the application.
2022-03-02 11:59:35 +11:00
Maikel Linke
4aa70c1ffd Render pagination errors 2022-03-02 11:59:35 +11:00
Maikel Linke
b89715149c Sanitise pagination input for new API 2022-03-02 11:59:35 +11:00
Maikel Linke
75fc35574e Make json_response test helper deal with error response
It raised an error:

     NoMethodError:
       undefined method `map' for nil:NilClass
2022-03-02 11:59:35 +11:00
Maikel Linke
414bf5d074 Don't list guest customer records to guest users 2022-03-02 11:59:35 +11:00
Matt-Yorkley
bd9bed7323 Update schemas for relationships 2022-03-02 11:59:35 +11:00
Matt-Yorkley
2e59812bc1 Refactor to make more use of schema refs, and regenerate swagger file 2022-03-02 11:59:33 +11:00
Matt-Yorkley
d87e1805af Add relationships to resource serializers 2022-03-02 11:58:04 +11:00
Matt-Yorkley
d66d6d6bd6 Update use of links on relationships 2022-03-02 11:58:04 +11:00
Matt-Yorkley
3dbf00f302 Add pagination with Pagy using structure from JSON:API specification
https://jsonapi.org/examples/#pagination

Update schema for collections rendered with pagination data
2022-03-02 11:58:04 +11:00
Matt-Yorkley
c102ce8e7e Add RequestTimeout concern 2022-03-02 11:58:04 +11:00
Matt-Yorkley
8e61428cce Add 401 Unauthorized response test 2022-03-02 11:58:04 +11:00
Matt-Yorkley
a222b507fb Update and document authentication methods 2022-03-02 11:58:04 +11:00
Matt-Yorkley
56bc554f29 Regenerate swagger docs with rails rswag 2022-03-02 11:57:57 +11:00
Matt-Yorkley
028d02ccca Test serialized relationship data 2022-03-02 11:55:46 +11:00
Matt-Yorkley
46f9d3ef81 Test permissions combined with Ransack searches 2022-03-02 11:55:46 +11:00
Matt-Yorkley
76f14a03c6 Add specs and JSON schemas
Include test helpers
2022-03-02 11:55:46 +11:00
Matt-Yorkley
39f4feed4a Generate docs with rails rswag 2022-03-02 11:55:46 +11:00
Matt-Yorkley
cc4192047e Fill out customers controller
Add customer serializer
2022-03-02 11:55:46 +11:00
Matt-Yorkley
3128232d7e Create customers controller
And add new customers routes.

Disable them in production for now.
2022-03-02 11:55:46 +11:00
Matt-Yorkley
c4e2c8cb4c Tidy up error handling and update response formats for JSON:API standard
Update translation key namespacing
2022-03-02 11:55:46 +11:00
Matt-Yorkley
7d8ded5ab8 Bring simplified / cleaned up base controller into V1
- Inherits from ActionController::API
- Lots of superfluous junk removed
2022-03-02 11:55:46 +11:00
Cillian O'Ruanaidh
21affa6250 Include language metatags in html template when more than one language available
Fixes #8902

This is to help Google find pages in all languages, see https://developers.google.com/search/docs/advanced/crawling/localized-versions
2022-02-25 12:49:49 +00:00
Maikel Linke
8ffe6f6052 Sanitise user_id param on enterprise update 2022-02-24 14:51:23 +11:00
Maikel Linke
8e070f55ff Spec fail on bad enterprise param
It looks like some JS component can submit an invalid value here and it
causes a server error.
2022-02-24 14:46:42 +11:00
Matt-Yorkley
3effff8821 Show resent confirmation message in current tab 2022-02-18 09:42:49 +00:00
Matt-Yorkley
e72cc516a8 Drop spree prefix in path generation 2022-02-15 09:47:06 +00:00
Matt-Yorkley
4fbaa65534 Handle unconfirmed email message in UserSessionsController 2022-02-15 09:47:06 +00:00
Matt-Yorkley
0c2a267bea Patch keyword arguments syntax in Paperclip error handling 2022-02-14 11:58:22 +00:00
Cillian O'Ruanaidh
1b8c1bd27a Only initialise Stimulus app once in Jest tests in :beforeAll rather than :beforeEach
Before there was an issue with the remote_toggle_controller tests, which contains two tests. If you commented out one test and ran the other it would pass and vice versa but if both tests were uncommented only the first test would ever pass, the second one would fail. See https://github.com/openfoodfoundation/openfoodnetwork/pull/8805#discussion_r801464322

Co-authored-by: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com>
2022-02-11 10:21:26 +00:00
Cillian O'Ruanaidh
b43a68d717 Merge branch 'master' into remove-inline-advanced-settings-toggle-js 2022-02-04 12:24:17 +00:00
Cillian O'Ruanaidh
05756616dd Add a remote-toggle controller that can toggle elements outside of its scope
This is instead of adding the :data-controller attribute to the div#wrapper because that will wrap pretty much all content on the admin pages.

Co-authored-by: Matt-Yorkley <9029026+Matt-Yorkley@users.noreply.github.com>
2022-02-04 12:23:24 +00:00
Cillian O'Ruanaidh
d03b52a163 Revert "Replace inline JS for toggling order cycle advanced settings with StimulusJs controller"
This reverts commit 67ae2e72f3.
2022-02-04 11:47:38 +00:00
Cillian O'Ruanaidh
67ae2e72f3 Replace inline JS for toggling order cycle advanced settings with StimulusJs controller
Partially addresses #8699.

This adjusts the Stimulus toggle controller so you can toggle content in both directions via a single element. This is in addition to the previous behaviour for toggling via multiple elements like radio buttons when each element always toggles in one direction only.

If a toggle element contains a chevron icon this will automatically toggle the direction of that icon too.

Note, in order to not have to re-implement the animation provided by the slideToggle() function in standard JavaScript, this just switches the style :display between 'none' and 'block' so it is not as smooth. Perhaps it could be made more smooth later with a CSS transition.
2022-01-28 16:19:36 +00:00
Guido Oliveira
db45d7f4eb Cancel empty orders on BOM page 2021-11-06 10:25:34 -03:00
542 changed files with 14600 additions and 11242 deletions

7
.env
View File

@@ -61,10 +61,3 @@ SMTP_PASSWORD="f00d"
# STRIPE_INSTANCE_PUBLISHABLE_KEY="pk_test_xxxx" # This can be a test key or a live key
# STRIPE_CLIENT_ID="ca_xxxx" # This can be a development ID or a production ID
# STRIPE_ENDPOINT_SECRET="whsec_xxxx"
# Feature toggles
#
# Adding user emails separated by commas will enable them the use of certain features. See
# config/initializers/feature_toggles.rb for details.
#
# BETA_TESTERS="ofn@example.com,superadmin@example.com"

46
.github/workflows/mapi.yml vendored Normal file
View File

@@ -0,0 +1,46 @@
name: 'Mayhem for API'
on: [push]
jobs:
test:
if: ${{ github.repository_owner == 'openfoodfoundation' }}
runs-on: ubuntu-latest
strategy:
fail-fast: true
steps:
- uses: actions/checkout@v2
- run: docker/build
- run: docker-compose up --detach
- run: until curl -f -s http://localhost:3000; do echo "waiting for api server"; sleep 1; done
- run: docker-compose exec -T db psql postgresql://ofn:f00d@localhost:5432/open_food_network_dev --command="update spree_users set spree_api_key='testing' where login='ofn@example.com'"
# equivalent to Flipper.enable(:api_v1)
- run: docker-compose exec -T db psql postgresql://ofn:f00d@localhost:5432/open_food_network_dev --command="insert into flipper_features (key, created_at, updated_at) values ('api_v1', localtimestamp, localtimestamp)"
- run: docker-compose exec -T db psql postgresql://ofn:f00d@localhost:5432/open_food_network_dev --command="insert into flipper_gates (feature_key, key, value, created_at, updated_at) values ('api_v1', 'boolean', 'true', localtimestamp, localtimestamp)"
# Run Mayhem for API
- name: Run Mayhem for API
uses: ForAllSecure/mapi-action@v1
continue-on-error: true
with:
mapi-token: ${{ secrets.MAPI_TOKEN }}
api-url: http://localhost:3000
api-spec: swagger/v1/swagger.yaml
target: openfoodfoundation/openfoodnetwork
duration: 1min
sarif-report: mapi.sarif
html-report: mapi.html
run-args: |
--header-auth
X-Api-Token: testing
# Archive HTML report
- name: Archive Mayhem for API report
uses: actions/upload-artifact@v2
with:
name: mapi-report
path: mapi.html
# Upload SARIF file (only available on public repos or github enterprise)
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: mapi.sarif

1
.gitignore vendored
View File

@@ -15,6 +15,7 @@ db/*.csv
log/*.log
log/*.log.lck
log/*.log.*
/storage
tmp/
.idea/*
\#*

View File

@@ -27,11 +27,16 @@ Metrics/BlockLength:
"class_eval",
"collection",
"context",
"delete",
"describe",
"feature",
"get",
"it",
"member",
"namespace",
"path",
"post",
"put",
"resource",
"resources",
"scenario",
@@ -74,6 +79,11 @@ Lint/RaiseException:
Lint/StructNewOverride:
Enabled: true
Naming/VariableNumber:
AllowedIdentifiers:
- street_address_1
- street_address_2
Bundler/DuplicatedGem:
Enabled: false
@@ -95,6 +105,10 @@ Lint/UselessAssignment:
Exclude:
- spec/**/*
Lint/MissingSuper:
Exclude:
- 'app/components/**/*'
Metrics/AbcSize:
Max: 30 # default 17

View File

@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 1400`
# on 2022-02-25 01:04:47 UTC using RuboCop version 1.22.2.
# on 2022-03-29 16:07:39 UTC using RuboCop version 1.22.2.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@@ -53,7 +53,7 @@ Layout/LeadingCommentSpace:
Exclude:
- 'spec/system/admin/enterprises_spec.rb'
# Offense count: 828
# Offense count: 856
# Cop supports --auto-correct.
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https
@@ -108,7 +108,6 @@ Layout/LineLength:
- 'app/services/order_syncer.rb'
- 'app/services/products_renderer.rb'
- 'app/services/variant_units/variant_and_line_item_naming.rb'
- 'engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb'
- 'engines/order_management/app/services/order_management/subscriptions/validator.rb'
- 'engines/order_management/spec/services/order_management/order/updater_spec.rb'
- 'engines/web/app/helpers/web/cookies_policy_helper.rb'
@@ -117,15 +116,19 @@ Layout/LineLength:
- 'lib/open_food_network/enterprise_fee_applicator.rb'
- 'lib/open_food_network/enterprise_fee_calculator.rb'
- 'lib/open_food_network/enterprise_issue_validator.rb'
- 'lib/open_food_network/lettuce_share_report.rb'
- 'lib/open_food_network/order_cycle_form_applicator.rb'
- 'lib/open_food_network/order_cycle_management_report.rb'
- 'lib/open_food_network/order_cycle_permissions.rb'
- 'lib/open_food_network/payments_report.rb'
- 'lib/open_food_network/reports/line_items.rb'
- 'lib/open_food_network/sales_tax_report.rb'
- 'lib/open_food_network/scope_variants_for_search.rb'
- 'lib/open_food_network/xero_invoices_report.rb'
- 'lib/reporting/line_items.rb'
- 'lib/reporting/reports/bulk_coop/bulk_coop_report.rb'
- 'lib/reporting/reports/enterprise_fee_summary/report_data/enterprise_fee_type_total.rb'
- 'lib/reporting/reports/order_cycle_management/order_cycle_management_report.rb'
- 'lib/open_food_network/order_cycle_permissions.rb'
- 'lib/reporting/reports/orders_and_fulfillment/customer_totals_report.rb'
- 'lib/reporting/reports/orders_and_fulfillment/distributor_totals_by_supplier_report.rb'
- 'lib/reporting/reports/payments/payments_report.rb'
- 'lib/reporting/reports/products_and_inventory/lettuce_share_report.rb'
- 'lib/reporting/reports/sales_tax/sales_tax_report.rb'
- 'lib/reporting/reports/xero_invoices/base.rb'
- 'lib/spree/localized_number.rb'
- 'lib/tasks/data.rake'
- 'lib/tasks/enterprises.rake'
@@ -176,19 +179,20 @@ Layout/LineLength:
- 'spec/helpers/spree/admin/base_helper_spec.rb'
- 'spec/jobs/subscription_confirm_job_spec.rb'
- 'spec/jobs/subscription_placement_job_spec.rb'
- 'spec/lib/open_food_network/customers_report_spec.rb'
- 'spec/lib/open_food_network/enterprise_fee_calculator_spec.rb'
- 'spec/lib/open_food_network/group_buy_report_spec.rb'
- 'spec/lib/open_food_network/order_cycle_form_applicator_spec.rb'
- 'spec/lib/open_food_network/order_cycle_management_report_spec.rb'
- 'spec/lib/open_food_network/order_cycle_permissions_spec.rb'
- 'spec/lib/open_food_network/order_grouper_spec.rb'
- 'spec/lib/open_food_network/permissions_spec.rb'
- 'spec/lib/open_food_network/products_and_inventory_report_spec.rb'
- 'spec/lib/open_food_network/scope_variant_to_hub_spec.rb'
- 'spec/lib/open_food_network/tag_rule_applicator_spec.rb'
- 'spec/lib/open_food_network/users_and_enterprises_report_spec.rb'
- 'spec/lib/reports/customers_report_spec.rb'
- 'spec/lib/reports/order_cycle_management_report_spec.rb'
- 'spec/lib/reports/order_grouper_spec.rb'
- 'spec/lib/reports/orders_and_fulfillment/orders_and_fulfillment_report_spec.rb'
- 'spec/lib/reports/packing/packing_report_spec.rb'
- 'spec/lib/reports/products_and_inventory_report_spec.rb'
- 'spec/lib/reports/users_and_enterprises_report_spec.rb'
- 'spec/lib/reports/xero_invoices_report_spec.rb'
- 'spec/lib/stripe/authorize_response_patcher_spec.rb'
- 'spec/mailers/order_mailer_spec.rb'
- 'spec/mailers/producer_mailer_spec.rb'
@@ -309,7 +313,15 @@ Layout/MultilineMethodCallBraceLayout:
Exclude:
- 'lib/reporting/queries/joins.rb'
# Offense count: 17
# Offense count: 2
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, IndentationWidth.
# SupportedStyles: aligned, indented, indented_relative_to_receiver
Layout/MultilineMethodCallIndentation:
Exclude:
- 'lib/reporting/reports/customers/customers_report.rb'
# Offense count: 20
# Cop supports --auto-correct.
# Configuration parameters: AllowInHeredoc.
Layout/TrailingWhitespace:
@@ -331,7 +343,7 @@ Lint/ConstantDefinitionInBlock:
- 'lib/tasks/users.rake'
- 'spec/controllers/spree/admin/base_controller_spec.rb'
- 'spec/helpers/serializer_helper_spec.rb'
- 'spec/lib/open_food_network/reports/line_items_spec.rb'
- 'spec/lib/reports/line_items_spec.rb'
- 'spec/models/spree/ability_spec.rb'
- 'spec/models/spree/gateway_spec.rb'
- 'spec/models/spree/preferences/configuration_spec.rb'
@@ -366,11 +378,6 @@ Lint/IneffectiveAccessModifier:
Exclude:
- 'app/models/spree/user.rb'
# Offense count: 2
Lint/MissingSuper:
Exclude:
- 'app/components/distributor_title_component.rb'
- 'app/components/example_component.rb'
# Offense count: 1
# Cop supports --auto-correct.
@@ -403,7 +410,7 @@ Lint/UselessMethodDefinition:
- 'app/controllers/spree/user_registrations_controller.rb'
- 'app/models/spree/gateway.rb'
# Offense count: 39
# Offense count: 38
# Configuration parameters: IgnoredMethods, CountRepeatedAttributes, Max.
Metrics/AbcSize:
Exclude:
@@ -424,22 +431,20 @@ Metrics/AbcSize:
- 'app/models/spree/order/checkout.rb'
- 'app/models/spree/preferences/preferable_class_methods.rb'
- 'app/models/spree/return_authorization.rb'
- 'engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb'
- 'lib/discourse/single_sign_on.rb'
- 'lib/open_food_network/customers_report.rb'
- 'lib/open_food_network/group_buy_report.rb'
- 'lib/open_food_network/order_and_distributor_report.rb'
- 'lib/open_food_network/order_cycle_form_applicator.rb'
- 'lib/reporting/reports/bulk_coop/bulk_coop_report.rb'
- 'lib/reporting/reports/customers/customers_report.rb'
- 'lib/open_food_network/order_cycle_permissions.rb'
- 'lib/open_food_network/payments_report.rb'
- 'lib/open_food_network/sales_tax_report.rb'
- 'lib/reporting/reports/orders_and_distributors/orders_and_distributors_report.rb'
- 'lib/reporting/reports/packing/customer.rb'
- 'lib/reporting/reports/payments/payments_report.rb'
- 'lib/reporting/reports/sales_tax/sales_tax_report.rb'
- 'lib/spree/core/controller_helpers/order.rb'
- 'lib/spree/core/s3_support.rb'
- 'lib/tasks/enterprises.rake'
- 'spec/services/order_checkout_restart_spec.rb'
# Offense count: 45
# Offense count: 43
# Configuration parameters: CountComments, Max, CountAsOne, ExcludedMethods, IgnoredMethods.
# IgnoredMethods: refine
Metrics/BlockLength:
@@ -463,12 +468,12 @@ Metrics/BlockLength:
- 'spec/factories/subscription_factory.rb'
- 'spec/factories/user_factory.rb'
- 'spec/factories/variant_factory.rb'
- 'spec/lib/open_food_network/group_buy_report_spec.rb'
- 'spec/requests/api/orders_spec.rb'
- 'spec/spec_helper.rb'
- 'spec/support/cancan_helper.rb'
- 'spec/support/matchers/select2_matchers.rb'
- 'spec/support/matchers/table_matchers.rb'
- 'spec/swagger_helper.rb'
- 'spec/system/admin/order_cycles/complex_updating_specific_time_spec.rb'
- 'spec/system/consumer/shopping/checkout_spec.rb'
@@ -478,7 +483,7 @@ Metrics/BlockNesting:
Exclude:
- 'app/models/spree/payment/processing.rb'
# Offense count: 49
# Offense count: 50
# Configuration parameters: CountComments, Max, CountAsOne.
Metrics/ClassLength:
Exclude:
@@ -522,18 +527,17 @@ Metrics/ClassLength:
- 'app/services/cart_service.rb'
- 'app/services/order_syncer.rb'
- 'engines/order_management/app/services/order_management/order/updater.rb'
- 'engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb'
- 'engines/order_management/app/services/order_management/reports/enterprise_fee_summary/scope.rb'
- 'lib/open_food_network/enterprise_fee_calculator.rb'
- 'lib/open_food_network/order_cycle_form_applicator.rb'
- 'lib/open_food_network/order_cycle_management_report.rb'
- 'lib/open_food_network/order_cycle_permissions.rb'
- 'lib/open_food_network/payments_report.rb'
- 'lib/open_food_network/permissions.rb'
- 'lib/open_food_network/users_and_enterprises_report.rb'
- 'lib/open_food_network/xero_invoices_report.rb'
- 'lib/reporting/reports/bulk_coop/bulk_coop_report.rb'
- 'lib/reporting/reports/enterprise_fee_summary/scope.rb'
- 'lib/reporting/reports/order_cycle_management/order_cycle_management_report.rb'
- 'lib/open_food_network/order_cycle_permissions.rb'
- 'lib/reporting/reports/payments/payments_report.rb'
- 'lib/reporting/reports/xero_invoices/base.rb'
# Offense count: 40
# Offense count: 39
# Configuration parameters: IgnoredMethods, Max.
Metrics/CyclomaticComplexity:
Exclude:
@@ -559,20 +563,19 @@ Metrics/CyclomaticComplexity:
- 'app/models/spree/tax_rate.rb'
- 'app/models/spree/variant.rb'
- 'app/models/spree/zone.rb'
- 'engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb'
- 'lib/discourse/single_sign_on.rb'
- 'lib/open_food_network/customers_report.rb'
- 'lib/open_food_network/enterprise_issue_validator.rb'
- 'lib/open_food_network/group_buy_report.rb'
- 'lib/open_food_network/orders_and_fulfillments_report/customer_totals_report.rb'
- 'lib/open_food_network/payments_report.rb'
- 'lib/open_food_network/xero_invoices_report.rb'
- 'lib/reporting/reports/bulk_coop/bulk_coop_report.rb'
- 'lib/reporting/reports/customers/customers_report.rb'
- 'lib/reporting/reports/orders_and_fulfillment/customer_totals_report.rb'
- 'lib/reporting/reports/payments/payments_report.rb'
- 'lib/reporting/reports/xero_invoices/base.rb'
- 'lib/spree/core/controller_helpers/order.rb'
- 'lib/spree/core/controller_helpers/respond_with.rb'
- 'lib/spree/localized_number.rb'
- 'spec/models/product_importer_spec.rb'
# Offense count: 31
# Offense count: 32
# Configuration parameters: CountComments, Max, CountAsOne, ExcludedMethods, IgnoredMethods.
Metrics/MethodLength:
Exclude:
@@ -582,22 +585,23 @@ Metrics/MethodLength:
- 'app/controllers/spree/orders_controller.rb'
- 'app/helpers/checkout_helper.rb'
- 'app/helpers/spree/admin/navigation_helper.rb'
- 'app/json_schemas/json_api_schema.rb'
- 'app/models/spree/ability.rb'
- 'app/models/spree/gateway/pay_pal_express.rb'
- 'app/models/spree/order/checkout.rb'
- 'app/models/spree/payment/processing.rb'
- 'app/models/spree/preferences/preferable_class_methods.rb'
- 'engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb'
- 'engines/order_management/app/services/order_management/reports/enterprise_fee_summary/scope.rb'
- 'lib/discourse/single_sign_on.rb'
- 'lib/open_food_network/order_cycle_form_applicator.rb'
- 'lib/open_food_network/order_cycle_management_report.rb'
- 'lib/reporting/reports/bulk_coop/bulk_coop_report.rb'
- 'lib/reporting/reports/enterprise_fee_summary/scope.rb'
- 'lib/reporting/reports/order_cycle_management/order_cycle_management_report.rb'
- 'lib/open_food_network/order_cycle_permissions.rb'
- 'lib/open_food_network/payments_report.rb'
- 'lib/open_food_network/xero_invoices_report.rb'
- 'lib/reporting/reports/payments/payments_report.rb'
- 'lib/reporting/reports/xero_invoices/base.rb'
- 'lib/tasks/sample_data/product_factory.rb'
# Offense count: 51
# Offense count: 54
# Configuration parameters: CountComments, Max, CountAsOne.
Metrics/ModuleLength:
Exclude:
@@ -628,17 +632,20 @@ Metrics/ModuleLength:
- 'spec/controllers/spree/admin/adjustments_controller_spec.rb'
- 'spec/controllers/spree/admin/payment_methods_controller_spec.rb'
- 'spec/lib/open_food_network/address_finder_spec.rb'
- 'spec/lib/open_food_network/customers_report_spec.rb'
- 'spec/lib/open_food_network/enterprise_fee_calculator_spec.rb'
- 'spec/lib/open_food_network/order_cycle_form_applicator_spec.rb'
- 'spec/lib/open_food_network/order_cycle_management_report_spec.rb'
- 'spec/lib/open_food_network/order_cycle_permissions_spec.rb'
- 'spec/lib/open_food_network/order_grouper_spec.rb'
- 'spec/lib/open_food_network/permissions_spec.rb'
- 'spec/lib/open_food_network/products_and_inventory_report_spec.rb'
- 'spec/lib/open_food_network/scope_variant_to_hub_spec.rb'
- 'spec/lib/open_food_network/tag_rule_applicator_spec.rb'
- 'spec/lib/open_food_network/users_and_enterprises_report_spec.rb'
- 'spec/lib/reports/customers_report_spec.rb'
- 'spec/lib/reports/enterprise_fee_summary/authorizer_spec.rb'
- 'spec/lib/reports/order_cycle_management_report_spec.rb'
- 'spec/lib/reports/order_grouper_spec.rb'
- 'spec/lib/reports/orders_and_fulfillment/customer_totals_report_spec.rb'
- 'spec/lib/reports/orders_and_fulfillment/orders_and_fulfillment_report_spec.rb'
- 'spec/lib/reports/products_and_inventory_report_spec.rb'
- 'spec/lib/reports/users_and_enterprises_report_spec.rb'
- 'spec/models/spree/adjustment_spec.rb'
- 'spec/models/spree/credit_card_spec.rb'
- 'spec/models/spree/line_item_spec.rb'
@@ -659,11 +666,11 @@ Metrics/ParameterLists:
Exclude:
- 'app/helpers/angular_form_builder.rb'
- 'app/models/product_import/entry_processor.rb'
- 'lib/open_food_network/xero_invoices_report.rb'
- 'lib/reporting/reports/xero_invoices/base.rb'
- 'spec/support/controller_requests_helper.rb'
- 'spec/system/admin/reports_spec.rb'
# Offense count: 8
# Offense count: 7
# Configuration parameters: IgnoredMethods, Max.
Metrics/PerceivedComplexity:
Exclude:
@@ -672,9 +679,8 @@ Metrics/PerceivedComplexity:
- 'app/models/enterprise_relationship.rb'
- 'app/models/spree/ability.rb'
- 'app/models/spree/order/checkout.rb'
- 'engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb'
- 'lib/open_food_network/group_buy_report.rb'
- 'lib/open_food_network/payments_report.rb'
- 'lib/reporting/reports/bulk_coop/bulk_coop_report.rb'
- 'lib/reporting/reports/payments/payments_report.rb'
# Offense count: 9
Naming/AccessorMethodName:
@@ -719,7 +725,7 @@ Naming/VariableNumber:
- 'app/controllers/spree/orders_controller.rb'
- 'app/models/content_configuration.rb'
- 'app/models/preference_sections/main_links_section.rb'
- 'lib/open_food_network/orders_and_fulfillments_report/customer_totals_report.rb'
- 'lib/reporting/reports/orders_and_fulfillment/customer_totals_report.rb'
- 'lib/spree/core/controller_helpers/common.rb'
- 'spec/controllers/spree/admin/search_controller_spec.rb'
- 'spec/factories/stock_location_factory.rb'
@@ -898,7 +904,7 @@ Rails/LexicallyScopedActionFilter:
- 'app/controllers/spree/admin/zones_controller.rb'
- 'app/controllers/spree/users_controller.rb'
# Offense count: 18
# Offense count: 19
Rails/OutputSafety:
Exclude:
- 'app/controllers/spree/admin/reports_controller.rb'
@@ -1095,9 +1101,9 @@ Style/MissingRespondToMissing:
# Offense count: 1
Style/MixinUsage:
Exclude:
- 'lib/open_food_network/orders_and_fulfillments_report.rb'
- 'lib/reporting/reports/orders_and_fulfillment/orders_and_fulfillment_report.rb'
# Offense count: 2
# Offense count: 3
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: literals, strict
@@ -1121,7 +1127,7 @@ Style/NestedModifier:
- 'spec/system/admin/payments_stripe_spec.rb'
- 'spec/system/admin/reports_spec.rb'
# Offense count: 25
# Offense count: 26
# Configuration parameters: AllowedMethods.
# AllowedMethods: respond_to_missing?
Style/OptionalBooleanParameter:
@@ -1135,16 +1141,7 @@ Style/OptionalBooleanParameter:
- 'app/models/spree/order_contents.rb'
- 'app/models/spree/preferences/file_configuration.rb'
- 'app/models/spree/shipment.rb'
- 'engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb'
- 'engines/order_management/app/services/order_management/stock/estimator.rb'
- 'lib/open_food_network/customers_report.rb'
- 'lib/open_food_network/order_and_distributor_report.rb'
- 'lib/open_food_network/order_cycle_management_report.rb'
- 'lib/open_food_network/orders_and_fulfillments_report.rb'
- 'lib/open_food_network/payments_report.rb'
- 'lib/open_food_network/products_and_inventory_report_base.rb'
- 'lib/open_food_network/users_and_enterprises_report.rb'
- 'lib/open_food_network/xero_invoices_report.rb'
- 'lib/spree/core/controller_helpers/order.rb'
- 'lib/spree/core/delegate_belongs_to.rb'
- 'spec/support/request/web_helper.rb'
@@ -1164,11 +1161,10 @@ Style/RedundantReturn:
Exclude:
- 'app/controllers/spree/admin/shipping_methods_controller.rb'
# Offense count: 213
# Offense count: 205
Style/Send:
Exclude:
- 'app/controllers/split_checkout_controller.rb'
- 'engines/order_management/spec/services/order_management/reports/bulk_coop/bulk_coop_report_spec.rb'
- 'spec/controllers/admin/subscriptions_controller_spec.rb'
- 'spec/controllers/checkout_controller_spec.rb'
- 'spec/controllers/payment_gateways/paypal_controller_spec.rb'
@@ -1180,13 +1176,10 @@ Style/Send:
- 'spec/lib/open_food_network/address_finder_spec.rb'
- 'spec/lib/open_food_network/enterprise_fee_applicator_spec.rb'
- 'spec/lib/open_food_network/enterprise_fee_calculator_spec.rb'
- 'spec/lib/open_food_network/lettuce_share_report_spec.rb'
- 'spec/lib/open_food_network/order_cycle_form_applicator_spec.rb'
- 'spec/lib/open_food_network/permissions_spec.rb'
- 'spec/lib/open_food_network/products_and_inventory_report_spec.rb'
- 'spec/lib/open_food_network/sales_tax_report_spec.rb'
- 'spec/lib/open_food_network/tag_rule_applicator_spec.rb'
- 'spec/lib/open_food_network/xero_invoices_report_spec.rb'
- 'spec/lib/reports/xero_invoices_report_spec.rb'
- 'spec/lib/stripe/webhook_handler_spec.rb'
- 'spec/models/calculator/weight_spec.rb'
- 'spec/models/enterprise_spec.rb'
@@ -1211,7 +1204,7 @@ Style/SingleArgumentDig:
Exclude:
- 'app/services/checkout/form_data_adapter.rb'
# Offense count: 5
# Offense count: 4
# Cop supports --auto-correct.
Style/SlicingWithRange:
Exclude:
@@ -1219,9 +1212,8 @@ Style/SlicingWithRange:
- 'app/services/embedded_page_service.rb'
- 'engines/order_management/app/services/order_management/subscriptions/validator.rb'
- 'lib/discourse/single_sign_on.rb'
- 'spec/lib/open_food_network/order_grouper_spec.rb'
# Offense count: 31
# Offense count: 28
# Cop supports --auto-correct.
# Configuration parameters: Mode.
Style/StringConcatenation:
@@ -1238,11 +1230,8 @@ Style/StringConcatenation:
- 'app/serializers/api/enterprise_shopfront_list_serializer.rb'
- 'app/services/embedded_page_service.rb'
- 'app/services/products_renderer.rb'
- 'engines/order_management/app/services/order_management/reports/bulk_coop/bulk_coop_report.rb'
- 'lib/open_food_network/orders_and_fulfillments_report/customer_totals_report.rb'
- 'lib/spree/api/controller_setup.rb'
- 'lib/spree/core/environment_extension.rb'
- 'spec/lib/open_food_network/order_grouper_spec.rb'
- 'spec/models/spree/line_item_spec.rb'
- 'spec/models/spree/product_spec.rb'
- 'spec/models/spree/variant_spec.rb'

View File

@@ -23,7 +23,9 @@ RUN apt-get update && apt-get install -y \
imagemagick \
unzip \
libjemalloc-dev \
libssl-dev
libssl-dev \
ca-certificates \
gnupg
# Setup ENV variables
ENV PATH /usr/local/src/rbenv/shims:/usr/local/src/rbenv/bin:$PATH
@@ -40,14 +42,13 @@ RUN git clone --depth 1 https://github.com/rbenv/rbenv.git ${RBENV_ROOT} && \
git clone --depth 1 https://github.com/rbenv/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build && \
echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh && \
RUBY_CONFIGURE_OPTS=--with-jemalloc rbenv install $(cat .ruby-version) && \
rbenv global $(cat .ruby-version) && \
gem install bundler --version=1.17.3
rbenv global $(cat .ruby-version)
# Install Postgres
RUN sh -c "echo 'deb https://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main' > /etc/apt/sources.list.d/pgdg.list" && \
wget --quiet -O - https://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | apt-key add - && \
RUN sh -c "echo 'deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -cs`-pgdg main' >> /etc/apt/sources.list.d/pgdg.list" && \
curl https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor | tee /etc/apt/trusted.gpg.d/apt.postgresql.org.gpg >/dev/null && \
apt-get update && \
apt-get install -yqq --no-install-recommends postgresql-client-9.5 libpq-dev
apt-get install -yqq --no-install-recommends postgresql-client-10 libpq-dev
# Install NodeJs and yarn
RUN curl -sL https://deb.nodesource.com/setup_14.x | bash - \
@@ -68,6 +69,9 @@ RUN wget https://chromedriver.storage.googleapis.com/2.41/chromedriver_linux64.z
# Copy code and install app dependencies
COPY . /usr/src/app/
# Install Bundler
RUN ./script/install-bundler
# Install front-end dependencies
RUN yarn install

View File

@@ -8,6 +8,11 @@ gem 'dotenv-rails', require: 'dotenv/rails-now' # Load ENV vars before other gem
gem 'rails', '>= 6.1.4'
# Active Storage
gem "active_storage_validations"
gem "aws-sdk-s3", require: false
gem "image_processing"
gem 'activemerchant', '>= 1.78.0'
gem 'rexml'
gem 'angular-rails-templates', '>= 0.3.0'
@@ -57,6 +62,7 @@ gem 'devise-token_authenticatable'
gem 'jwt', '~> 2.3'
gem 'oauth2', '~> 1.4.7' # Used for Stripe Connect
gem 'jsonapi-serializer'
gem 'pagy', '~> 5.1'
gem 'rswag-api'
@@ -80,7 +86,6 @@ gem 'bootsnap', require: false
gem 'geocoder'
gem 'gmaps4rails'
gem 'mimemagic', '> 0.3.5'
gem 'paperclip', '~> 3.4.1'
gem 'paper_trail', '~> 12.1.0'
gem 'rack-rewrite'
gem 'rack-ssl', require: 'rack/ssl'

View File

@@ -101,6 +101,11 @@ GEM
rails-html-sanitizer (~> 1.1, >= 1.2.0)
active_model_serializers (0.8.4)
activemodel (>= 3.0)
active_storage_validations (0.9.7)
activejob (>= 5.2.0)
activemodel (>= 5.2.0)
activestorage (>= 5.2.0)
activesupport (>= 5.2.0)
activejob (6.1.4.4)
activesupport (= 6.1.4.4)
globalid (>= 0.3.6)
@@ -158,11 +163,27 @@ GEM
awesome_nested_set (3.4.0)
activerecord (>= 4.0.0, < 7.0)
awesome_print (1.9.2)
aws-eventstream (1.2.0)
aws-partitions (1.570.0)
aws-sdk (1.67.0)
aws-sdk-v1 (= 1.67.0)
aws-sdk-core (3.130.0)
aws-eventstream (~> 1, >= 1.0.2)
aws-partitions (~> 1, >= 1.525.0)
aws-sigv4 (~> 1.1)
jmespath (~> 1.0)
aws-sdk-kms (1.55.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sigv4 (~> 1.1)
aws-sdk-s3 (1.113.0)
aws-sdk-core (~> 3, >= 3.127.0)
aws-sdk-kms (~> 1)
aws-sigv4 (~> 1.4)
aws-sdk-v1 (1.67.0)
json (~> 1.4)
nokogiri (~> 1)
aws-sigv4 (1.4.0)
aws-eventstream (~> 1, >= 1.0.2)
axlsx_styler (1.1.0)
activesupport (>= 3.1)
caxlsx (>= 2.0.2)
@@ -198,10 +219,7 @@ GEM
rubyzip (>= 1.3.0, < 3)
childprocess (4.1.0)
chronic (0.10.2)
climate_control (0.2.0)
cliver (0.3.2)
cocaine (0.5.8)
climate_control (>= 0.0.3, < 1.0)
coderay (1.1.3)
coffee-rails (5.0.0)
coffee-script (>= 2.2.0)
@@ -331,9 +349,13 @@ GEM
concurrent-ruby (~> 1.0)
i18n-js (3.9.0)
i18n (>= 0.6.6)
image_processing (1.12.2)
mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3)
immigrant (0.3.6)
activerecord (>= 3.0)
ipaddress (0.8.3)
jmespath (1.6.1)
jquery-rails (4.4.0)
rails-dom-testing (>= 1, < 3)
railties (>= 4.2.0)
@@ -346,6 +368,8 @@ GEM
json_spec (1.1.5)
multi_json (~> 1.0)
rspec (>= 2.0, < 4.0)
jsonapi-serializer (2.2.0)
activesupport (>= 4.2)
jwt (2.3.0)
knapsack (4.0.0)
rake
@@ -365,12 +389,10 @@ GEM
marcel (1.0.2)
matrix (0.4.2)
method_source (1.0.0)
mime-types (3.3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2021.0225)
mimemagic (0.4.3)
nokogiri (~> 1)
rake
mini_magick (4.11.0)
mini_mime (1.1.2)
mini_portile2 (2.8.0)
mini_racer (0.4.0)
@@ -399,12 +421,6 @@ GEM
paper_trail (12.1.0)
activerecord (>= 5.2)
request_store (~> 1.1)
paperclip (3.4.2)
activemodel (>= 3.0.0)
activerecord (>= 3.0.0)
activesupport (>= 3.0.0)
cocaine (~> 0.5.0)
mime-types
parallel (1.21.0)
paranoia (2.4.3)
activerecord (>= 4.0, < 6.2)
@@ -558,6 +574,8 @@ GEM
rubocop (>= 1.7.0, < 2.0)
ruby-progressbar (1.11.0)
ruby-rc4 (0.1.5)
ruby-vips (2.1.4)
ffi (~> 1.12)
ruby2_keywords (0.0.4)
rubyzip (2.3.2)
rufus-scheduler (3.7.0)
@@ -681,6 +699,7 @@ PLATFORMS
DEPENDENCIES
actionpack-action_caching
active_model_serializers (= 0.8.4)
active_storage_validations
activemerchant (>= 1.78.0)
activerecord-import
activerecord-postgresql-adapter
@@ -695,6 +714,7 @@ DEPENDENCIES
awesome_nested_set
awesome_print
aws-sdk (= 1.67.0)
aws-sdk-s3
bigdecimal (= 3.0.2)
bootsnap
bugsnag
@@ -734,11 +754,13 @@ DEPENDENCIES
hiredis
i18n
i18n-js (~> 3.9.0)
image_processing
immigrant
jquery-rails (= 4.4.0)
jquery-ui-rails (~> 4.2)
json
json_spec (~> 1.1.4)
jsonapi-serializer
jwt (~> 2.3)
knapsack
letter_opener (>= 1.4.1)
@@ -751,7 +773,6 @@ DEPENDENCIES
order_management!
pagy (~> 5.1)
paper_trail (~> 12.1.0)
paperclip (~> 3.4.1)
paranoia (~> 2.4)
paypal-sdk-merchant (= 1.117.2)
pdf-reader

View File

@@ -1,6 +0,0 @@
angular.module("ofn.admin").directive "select2NoSearch", ($timeout) ->
restrict: 'CA'
link: (scope, element, attrs) ->
$timeout ->
element.select2
minimumResultsForSearch: Infinity

View File

@@ -9,9 +9,9 @@ angular.module("admin.enterpriseFees").directive 'spreeEnsureCalculatorPreferenc
settings = element.parent().parent().find('div.calculator-settings')
if value == orig_calculator_type
settings.show()
settings.find('input').prop 'disabled', false
settings.find('input, select').prop 'disabled', false
else
settings.hide()
settings.find('input').prop 'disabled', true
settings.find('input, select').prop 'disabled', true
return
return

View File

@@ -16,6 +16,7 @@ angular.module("admin.enterprises")
{ name: 'shipping_methods', label: t('shipping_methods'), icon_class: "icon-truck", show: "showShippingMethods()" }
{ name: 'payment_methods', label: t('payment_methods'), icon_class: "icon-money", show: "showPaymentMethods()" }
{ name: 'enterprise_fees', label: t('enterprise_fees'), icon_class: "icon-tasks", show: "showEnterpriseFees()" }
{ name: 'enterprise_permissions', label: t('enterprise_permissions'), icon_class: "icon-plug" }
{ name: 'inventory_settings', label: t('inventory_settings'), icon_class: "icon-list-ol", show: "enterpriseIsShop()" }
{ name: 'tag_rules', label: t('tag_rules'), icon_class: "icon-random", show: "enterpriseIsShop()" }
{ name: 'shop_preferences', label: t('shop_preferences'), icon_class: "icon-shopping-cart", show: "enterpriseIsShop()" }
@@ -44,3 +45,5 @@ angular.module("admin.enterprises")
$scope.enterpriseIsShop = ->
$scope.Enterprise.sells != "none"
$scope.menu.redirect_function('enterprise_permissions', '/admin/enterprise_relationships')

View File

@@ -104,15 +104,45 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
else
StatusMessage.display 'failure', t "unsaved_changes_error"
$scope.cancelOrder = (order, sendEmailCancellation) ->
return $http(
method: 'GET'
url: "/admin/orders/#{order.number}/fire?e=cancel&send_cancellation_email=#{sendEmailCancellation}")
$scope.deleteLineItem = (lineItem) ->
if ($scope.confirmDelete && confirm(t "are_you_sure")) || !$scope.confirmDelete
LineItems.delete lineItem
if lineItem.order.item_count == 1
ofnCancelOrderAlert((confirm, sendEmailCancellation) ->
if confirm
$scope.cancelOrder(lineItem.order, sendEmailCancellation).then(->
$scope.refreshData()
)
else
$scope.refreshData()
, "js.admin.deleting_item_will_cancel_order")
else if ($scope.confirmDelete && confirm(t "are_you_sure")) || !$scope.confirmDelete
LineItems.delete(lineItem, () -> $scope.refreshData())
$scope.deleteLineItems = (lineItemsToDelete) ->
existingState = $scope.confirmDelete
$scope.confirmDelete = false
$scope.deleteLineItem lineItem for lineItem in lineItemsToDelete when lineItem.checked
$scope.confirmDelete = existingState
$scope.deleteLineItems = (lineItems) ->
lineItemsToDelete = lineItems.filter (item) -> item.checked
willCancelOrders = false
itemsPerOrder = new Map()
for item in lineItemsToDelete
{ order } = item
if itemsPerOrder.has(order)
itemsPerOrder.get(order).push(item)
else
itemsPerOrder.set(order, [item])
willCancelOrders = true if (order.item_count == itemsPerOrder.get(order).length)
if willCancelOrders
ofnCancelOrderAlert((confirm, sendEmailCancellation) ->
if confirm
itemsPerOrder.forEach (items, order) =>
if order.item_count == items.length
$scope.cancelOrder(order, sendEmailCancellation).then(-> $scope.refreshData())
else
Promise.all(LineItems.delete(item) for item in items).then(-> $scope.refreshData())
, "js.admin.deleting_item_will_cancel_order")
$scope.allBoxesChecked = ->
checkedCount = $scope.filteredLineItems.reduce (count,lineItem) ->
@@ -182,9 +212,9 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
if $scope.selectedUnitsProduct.hasOwnProperty("group_buy_unit_size") && $scope.selectedUnitsProduct.group_buy_unit_size > 0 &&
$scope.selectedUnitsProduct.hasOwnProperty("variant_unit") &&
( $scope.selectedUnitsProduct.variant_unit == "weight" || $scope.selectedUnitsProduct.variant_unit == "volume" )
scale = $scope.getScale($scope.selectedUnitsProduct, $scope.selectedUnitsVariant)
sumOfUnitValues = sumOfUnitValues / scale if scale == 28.35 || scale == 453.6 # divide by scale if smallest unit
$scope.roundToThreeDecimals(sumOfUnitValues / $scope.selectedUnitsProduct.group_buy_unit_size * $scope.selectedUnitsVariant.unit_value)
scale = $scope.selectedUnitsProduct.variant_unit_scale
sumOfUnitValues = sumOfUnitValues * scale unless scale == 28.35 || scale == 453.6
$scope.roundToThreeDecimals(sumOfUnitValues / $scope.selectedUnitsProduct.group_buy_unit_size)
else
''

View File

@@ -1,4 +1,4 @@
angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, $timeout, StatusMessage, Panels) ->
angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, $timeout, StatusMessage, Panels, Enterprise) ->
OrderCycleResource = $resource '/admin/order_cycles/:action_name/:order_cycle_id.json', {}, {
'index': { method: 'GET', isArray: true}
'new' : { method: 'GET', params: { action_name: "new" } }
@@ -50,7 +50,14 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, $
(callback || angular.noop)()
addDistributor: (new_distributor_id, callback) ->
this.order_cycle.outgoing_exchanges.push({ enterprise_id: new_distributor_id, incoming: false, active: true, variants: {}, enterprise_fees: [] })
exchange = { enterprise_id: new_distributor_id, incoming: false, active: true, variants: {}, enterprise_fees: [] }
if (Enterprise.hub_enterprises.length == 1)
editable = this.order_cycle["editable_variants_for_outgoing_exchanges"][new_distributor_id] || []
variants = this.incomingExchangesVariants()
for variant in variants when variant in editable
exchange.variants[variant] = true
this.order_cycle.outgoing_exchanges.push(exchange)
$timeout ->
(callback || angular.noop)()

View File

@@ -43,7 +43,7 @@ angular.module("admin.resources").factory 'OrderCycles', ($q, $injector, OrderCy
angular.extend(@byID[orderCycle.id], orderCycle)
angular.extend(@pristineByID[orderCycle.id], orderCycle)
form.$setPristine() if form?
StatusMessage.display('success', "Order cycles have been updated.")
StatusMessage.display('success', t('order_cycles_bulk_update_notice'))
, (response) =>
if response.data.errors?
StatusMessage.display('failure', response.data.errors[0])

View File

@@ -30,3 +30,14 @@ angular.module("admin.side_menu")
for item in @items when item.name is name
return item
null
redirect_function: (elementID , href) =>
window.addEventListener 'load', ->
element = document.getElementById(elementID)
if !element
return
element.addEventListener 'click', ->
window.location.replace(href)
return
return

View File

@@ -7,11 +7,11 @@ $(function() {
if (calculator_select.val() === original_calc_type) {
$('div.calculator-settings').show();
$('.calculator-settings-warning').hide();
$('.calculator-settings').find('input,textarea').prop("disabled", false);
$('.calculator-settings').find('input,textarea,select').prop("disabled", false);
} else {
$('div.calculator-settings').hide();
$('.calculator-settings-warning').show();
$('.calculator-settings').find('input,textarea').prop("disabled", true);
$('.calculator-settings').find('input,textarea,select').prop("disabled", true);
}
});
})

View File

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

View File

@@ -4,6 +4,7 @@ $(document).ready(function() {
initAlert()
initConfirm()
initCancelOrder()
if ($('#variant_autocomplete_template').length > 0) {
window.variantTemplate = Handlebars.compile($('#variant_autocomplete_template').text());
@@ -52,12 +53,12 @@ $(document).ready(function() {
}
toggleItemEdit();
adjustItems(shipment_number, variant_id, quantity);
adjustItems(shipment_number, variant_id, quantity, true);
return false;
}
$('a.save-item').click(handle_save_click);
handle_delete_click = function(elementSelector){
handle_delete_click = function(elementSelector, restock_item){
var del = $(elementSelector);
del.hide()
var shipment_number = del.data('shipment-number');
@@ -65,26 +66,37 @@ $(document).ready(function() {
toggleItemEdit();
adjustItems(shipment_number, variant_id, 0);
adjustItems(shipment_number, variant_id, 0, restock_item);
}
$('a.delete-item').click((event) => {
ofnConfirm(() => {
handle_delete_click('#custom-confirm');
});
try {
var del = $('a.delete-item');
var shipment_number = del.data('shipment-number');
var variant_id = del.data('variant-id');
var shipment = _.findWhere(shipments, {number: shipment_number + ''});
var inventory_units = _.where(shipment.inventory_units, {variant_id: variant_id});
if (inventory_units.length !== shipment.inventory_units.length) {
ofnConfirm((reStockItem) => {
handle_delete_click('#custom-confirm', reStockItem);
});
} else {
adjustItems(shipment_number, variant_id, 0);
}
} catch (e) {
}
});
}
});
adjustItems = function(shipment_number, variant_id, quantity){
adjustItems = function(shipment_number, variant_id, quantity, restock_item){
var shipment = _.findWhere(shipments, {number: shipment_number + ''});
var inventory_units = _.where(shipment.inventory_units, {variant_id: variant_id});
if (quantity == 0 && inventory_units.length == shipment.inventory_units.length) {
ofnCancelOrderAlert((confirm, sendEmailCancellation) => {
if (quantity === 0 && inventory_units.length === shipment.inventory_units.length) {
ofnCancelOrderAlert((confirm, sendEmailCancellation, restock_item) => {
if (confirm) {
doAdjustItems(shipment_number, variant_id, quantity, inventory_units, () => {
doAdjustItems(shipment_number, variant_id, quantity, inventory_units, restock_item, () => {
var redirectTo = new URL(Spree.routes.cancel_order.toString());
redirectTo.searchParams.append("send_cancellation_email", sendEmailCancellation);
window.location.href = redirectTo.toString();
@@ -93,23 +105,26 @@ adjustItems = function(shipment_number, variant_id, quantity){
});
return;
}
doAdjustItems(shipment_number, variant_id, quantity, inventory_units, () => {
doAdjustItems(shipment_number, variant_id, quantity, inventory_units, restock_item, () => {
window.location.reload();
});
}
doAdjustItems = function(shipment_number, variant_id, quantity, inventory_units, callback) {
doAdjustItems = function(shipment_number, variant_id, quantity, inventory_units, restock_item, callback) {
var url = Spree.routes.orders_api + "/" + order_number + "/shipments/" + shipment_number;
var new_quantity = 0;
var data = { variant_id: variant_id };
if (inventory_units.length < quantity) {
url += "/add";
new_quantity = (quantity - inventory_units.length);
} else if (inventory_units.length > quantity) {
url += "/remove"
new_quantity = (inventory_units.length - quantity);
data.restock_item = restock_item;
}
url += '.json';
data.quantity = new_quantity;
if (new_quantity == 0) {
ofnAlert(t("js.admin.orders.quantity_unchanged"));
@@ -117,7 +132,7 @@ doAdjustItems = function(shipment_number, variant_id, quantity, inventory_units,
$.ajax({
type: "PUT",
url: Spree.url(url),
data: { variant_id: variant_id, quantity: new_quantity }
data: data
}).done(function( msg ) {
callback();
});
@@ -171,7 +186,7 @@ addVariantFromStockLocation = function() {
});
}else{
//add to existing shipment
adjustItems(shipment.number, variant_id, quantity);
adjustItems(shipment.number, variant_id, quantity, true);
}
return 1
}
@@ -194,16 +209,21 @@ ofnAlert = function(message) {
$('#custom-alert').show();
}
ofnCancelOrderAlert = function(callback) {
ofnCancelOrderAlert = function(callback, i18nKey) {
if (i18nKey == undefined) {
i18nKey = "js.admin.orders.cancel_the_order_html";
}
$('#custom-confirm .message').html(
` ${t("js.admin.orders.cancel_the_order_html")}
` ${t(i18nKey)}
<div class="form">
<input type="checkbox" name="send_cancellation_email" value="1" id="send_cancellation_email" />
<label for="send_cancellation_email">${t("js.admin.orders.cancel_the_order_send_cancelation_email")}</label>
<input type="checkbox" name="send_cancellation_email" value="1" id="send_cancellation_email" checked="true" />
<label for="send_cancellation_email">${t("js.admin.orders.cancel_the_order_send_cancelation_email")}</label><br />
<input type="checkbox" name="restock_items" id="restock_items" checked="checked"/>
<label for="restock_items">${t("js.admin.orders.restock_items")}</label>
</div>`);
$('#custom-confirm button.confirm').unbind( "click" ).click(() => {
$('#custom-confirm').hide();
callback(true, $('#send_cancellation_email').is(':checked'));
callback(true, $('#send_cancellation_email').is(':checked'), $('#restock_items').is(':checked'));
});
$('#custom-confirm button.cancel').click(() => {
$('#custom-confirm').hide();
@@ -213,7 +233,30 @@ ofnCancelOrderAlert = function(callback) {
}
ofnConfirm = function(callback) {
$('#custom-confirm .message').html(
` ${t("are_you_sure")}
<div class="form">
<input type="checkbox" name="restock_items" id="restock_items" checked="checked"/>
<label for="restock_items">${t("js.admin.orders.restock_item")}</label>
</div>`);
$('#custom-confirm').data($(event.target).data());
$('#custom-confirm button.confirm').click(callback);
$('#custom-confirm button.confirm').click(() => {
callback($('#restock_items').is(':checked'));
});
$('#custom-confirm').show();
}
initCancelOrder = function() {
$('#cancel_order_form').submit(function(e){
ofnCancelOrderAlert((confirm, sendEmailCancellation, restock_items) => {
if (confirm) {
var redirectTo = new URL(Spree.routes.cancel_order.toString());
redirectTo.searchParams.append("send_cancellation_email", sendEmailCancellation);
redirectTo.searchParams.append("restock_items", restock_items);
window.location.href = redirectTo.toString();
}
});
e.preventDefault();
return false;
});
}

View File

@@ -1,20 +0,0 @@
angular.module("admin.utils").directive 'helpModal', ($rootScope, $compile, $templateCache, $window, DialogDefaults) ->
restrict: 'C'
scope:
template: '@'
link: (scope, element, attr) ->
# Compile modal template
template = $compile($templateCache.get(scope.template))(scope)
# Load Dialog Options
template.dialog(DialogDefaults)
# Link opening of dialog to click event on element
element.bind 'click', (e) ->
template.dialog('open')
$rootScope.$evalAsync()
scope.close = ->
template.dialog('close')
$rootScope.$evalAsync()
return

View File

@@ -1,4 +1,4 @@
angular.module('Darkswarm').controller "ShopVariantCtrl", ($scope, $modal, Cart) ->
angular.module('Darkswarm').controller "ShopVariantCtrl", ($scope, $modal, Cart, Shopfront) ->
$scope.updateCart = (line_item) ->
Cart.adjust($scope.variant.line_item)
@@ -69,3 +69,6 @@ angular.module('Darkswarm').controller "ShopVariantCtrl", ($scope, $modal, Cart)
$scope.addBulk = (quantity) ->
$scope.add(quantity)
$modal.open(templateUrl: "bulk_buy_modal.html", scope: $scope, windowClass: "product-bulk-modal")
$scope.displayRemainingInStock = ->
Shopfront.shopfront.preferred_product_low_stock_display && $scope.available() <= 3 && !$scope.variant.line_item.quantity

View File

@@ -1,13 +0,0 @@
angular.module('Darkswarm').directive "helpModal", ($modal, $compile, $templateCache)->
restrict: 'A'
scope:
helpText: "@helpModal"
link: (scope, elem, attrs, ctrl)->
compiled = $compile($templateCache.get('help-modal.html'))(scope)
elem.on "click", =>
$modal.open(controller: ctrl, template: compiled, scope: scope, windowClass: 'help-modal small')
scope.$on "$destroy", ->
elem.off("click")

View File

@@ -3,7 +3,7 @@ angular.module('Darkswarm').directive 'mapSearch', ($timeout, Search) ->
restrict: 'E'
require: ['^uiGmapGoogleMap', 'ngModel']
replace: true
template: '<input id="pac-input" ng-model="query" placeholder="' + t('location_placeholder') + '"></input>'
template: '<input id="pac-input" ng-model="query" placeholder="' + t('location_placeholder') + '" onfocus="this.select()"></input>'
scope: {}
controller: ($scope) ->

View File

@@ -1,7 +0,0 @@
%div
.margin-bottom-30
%p
{{ 'js.admin.modals.business_address_info.message' | t }}
.text-center
%input.button.red.icon-plus{ type: 'button', value: '{{ "js.admin.modals.got_it" | t }}', ng: { click: 'close()' } }

View File

@@ -1,19 +0,0 @@
#invite-manager-modal{ng: {app: 'admin.enterprises', controller: 'enterpriseCtrl'}}
.margin-bottom-30.text-center
.text-big
= t('js.admin.modals.invite_title')
%p.alert-box.ok{ng: {show: 'invite_success'}}
{{invite_success}}
%p.alert-box.error{ng: {show: 'invite_errors'}}
{{invite_errors}}
%input#invite_email.fullwidth.margin-bottom-20{ng: {model: 'newUser'}}
.margin-bottom-20.text-center
%button.text-center.margin-top-10{ng: {show: '!invite_success', click: 'inviteManager()'}}
= t('js.admin.modals.invite')
%button.text-center.margin-top-10{ng: {show: 'invite_success', click: 'resetModal(); close()'}}
= t('js.admin.modals.close')

View File

@@ -1,25 +0,0 @@
#tag-rule-help
.margin-bottom-30.text-center
.text-big
{{ 'js.admin.modals.tag_rule_help.title' | t }}
.margin-bottom-30
.text-normal
{{ 'js.admin.modals.tag_rule_help.overview' | t }}
%p
{{ 'js.admin.modals.tag_rule_help.overview_text' | t }}
.margin-bottom-30
.text-normal
{{ 'js.admin.modals.tag_rule_help.by_default_rules' | t }}
%p
{{ 'js.admin.modals.tag_rule_help.by_default_rules_text' | t }}
.margin-bottom-30
.text-normal
{{ 'js.admin.modals.tag_rule_help.customer_tagged_rules' | t }}
%p
{{ 'js.admin.modals.tag_rule_help.customer_tagged_rules_text' | t }}
.text-center
%input.button.red.icon-plus{ type: 'button', value: t('js.admin.modals.got_it'), ng: { click: 'close()' } }

View File

@@ -1,13 +0,0 @@
%div
.margin-bottom-30.text-center
.text-big
{{ 'js.admin.modals.terms_and_conditions_info.title' | t }}
.margin-bottom-30
%p
{{ 'js.admin.modals.terms_and_conditions_info.message_1' | t }}
.margin-bottom-30
%p
{{ 'js.admin.modals.terms_and_conditions_info.message_2' | t }}
.text-center
%input.button.red.icon-plus{ type: 'button', value: t('js.admin.modals.got_it'), ng: { click: 'close()' } }

View File

@@ -0,0 +1,26 @@
# frozen_string_literal: true
class HelpModalComponent < ViewComponent::Base
def initialize(id:, close_button: true)
@id = id
@close_button = close_button
end
private
def close_button_class
if namespace == "admin"
"red"
else
"primary"
end
end
def close_button?
!!@close_button
end
def namespace
helpers.controller_path.split("/").first
end
end

View File

@@ -0,0 +1,8 @@
%div{ id: @id, "data-controller": "help-modal", "data-action": "keyup@document->help-modal#closeIfEscapeKey" }
.reveal-modal-bg.fade{ "data-help-modal-target": "background", "data-action": "click->help-modal#close" }
.reveal-modal.fade.small.help-modal{ "data-help-modal-target": "modal" }
= content
- if close_button?
.text-center
%input{ class: "button icon-plus #{close_button_class}", type: 'button', value: t('js.admin.modals.got_it'), "data-action": "click->help-modal#close" }

View File

@@ -0,0 +1,10 @@
.help-modal {
visibility: visible;
position: fixed;
top: 3em;
}
/* prevent arrow on selected admin menu item appearing above modal */
body.modal-open #admin-menu li.selected a::after {
z-index: 0;
}

View File

@@ -10,14 +10,14 @@ module Admin
def update
params.each do |name, value|
if ContentConfig.has_preference?(name) || ContentConfig.has_attachment?(name)
ContentConfig.public_send("#{name}=", value)
if value.is_a?(ActionDispatch::Http::UploadedFile)
blob = store_file(value)
update_preference("#{name}_blob_id", blob.id)
else
update_preference(name, value)
end
end
# Save any uploaded images
ContentConfig.save
flash[:success] =
t(:successfully_updated, resource: I18n.t('admin.contents.edit.your_content'))
@@ -26,6 +26,22 @@ module Admin
private
def store_file(attachable)
ActiveStorage::Blob.create_and_upload!(
io: attachable.open,
filename: attachable.original_filename,
content_type: attachable.content_type,
service_name: :local,
identify: false,
)
end
def update_preference(name, value)
return unless ContentConfig.has_preference?(name)
ContentConfig.public_send("#{name}=", value)
end
def preference_sections
[
PreferenceSections::HeaderSection.new,

View File

@@ -234,8 +234,10 @@ module Admin
end
def update_enterprise_notifications
if params.key? :receives_notifications
@enterprise.update_contact params[:receives_notifications]
user_id = params[:receives_notifications].to_i
if user_id.positive? && @enterprise.user_ids.include?(user_id)
@enterprise.update_contact(user_id)
end
end

View File

@@ -64,6 +64,7 @@ module Admin
@order_cycle_form = OrderCycleForm.new(@order_cycle, order_cycle_params, spree_current_user)
if @order_cycle_form.save
update_nil_subscription_line_items_price_estimate(@order_cycle)
respond_to do |format|
flash[:notice] = I18n.t(:order_cycles_update_notice) if params[:reloading] == '1'
format.html { redirect_back(fallback_location: root_path) }
@@ -76,6 +77,7 @@ module Admin
def bulk_update
if order_cycle_set&.save
bulk_update_nil_subscription_line_items_price_estimate
render_as_json @order_cycles,
ams_prefix: 'index',
current_user: spree_current_user,
@@ -86,6 +88,27 @@ module Admin
end
end
def bulk_update_nil_subscription_line_items_price_estimate
@collection.upcoming.each do |order_cycle|
update_nil_subscription_line_items_price_estimate(order_cycle)
end
end
def update_nil_subscription_line_items_price_estimate(order_cycle)
order_cycle.schedules.each do |schedule|
Subscription.where(schedule_id: schedule.id).each do |subscription|
shop = Enterprise.managed_by(spree_current_user).find_by(id: subscription.shop_id)
subscription.subscription_line_items.nil_price_estimate.each do |line_item|
variant = OrderManagement::Subscriptions::
VariantsList.eligible_variants(shop).find_by(id: line_item.variant_id)
fee_calculator = OpenFoodNetwork::EnterpriseFeeCalculator.new(shop, order_cycle)
price = variant.price + fee_calculator.indexed_fees_for(variant)
line_item.update_column(:price_estimate, price)
end
end
end
end
def clone
@order_cycle = OrderCycle.find params[:id]
@order_cycle.clone!

View File

@@ -5,14 +5,23 @@ module Admin
include ReportsActions
helper ReportsHelper
before_action :authorize_report
before_action :authorize_report, only: [:show]
# Define model class for Can? permissions
def model_class
Admin::ReportsController
end
def index
@reports = reports.select do |report_type, _description|
can? report_type, :report
end
end
def show
render_report && return if ransack_params.blank?
@report = report_class.new(spree_current_user, params, request)
@report = report_class.new(spree_current_user, ransack_params, report_options)
if export_spreadsheet?
if report_format.present?
export_report
else
render_report
@@ -22,33 +31,23 @@ module Admin
private
def export_report
render report_format.to_sym => @report.public_send("to_#{report_format}"),
:filename => report_filename
send_data @report.render_as(report_format, controller: self), filename: report_filename
end
def render_report
assign_view_data
load_form_options
render report_type
render "show"
end
def assign_view_data
@report_type = report_type
@report_subtype = report_subtype || report_loader.default_report_subtype
@report_subtypes = report_class.report_subtypes.map do |subtype|
[t("packing.#{subtype}_report", scope: i18n_scope), subtype]
end
end
@report_subtypes = report_subtypes
@report_subtype = report_subtype
def load_form_options
return unless form_options_required?
# Initialize data
params[:display_summary_row] = true if request.get?
form_options = Reporting::FrontendData.new(spree_current_user)
@distributors = form_options.distributors.to_a
@suppliers = form_options.suppliers.to_a
@order_cycles = form_options.order_cycles.to_a
@data = Reporting::FrontendData.new(spree_current_user)
end
end
end

View File

@@ -14,7 +14,7 @@ module Api
respond_to :json
def destroy
unless @enterprise.public_send("#{attachment_name}?")
unless @enterprise.public_send(attachment_name).attached?
return respond_with_conflict(error: destroy_attachment_does_not_exist_error_message)
end

View File

@@ -44,9 +44,9 @@ module Api
authorize! :update, @enterprise
if params[:logo] && @enterprise.update( logo: params[:logo] )
render html: @enterprise.logo.url(:medium), status: :ok
elsif params[:promo] && @enterprise.update( promo_image: params[:promo] )
render html: @enterprise.promo_image.url(:medium), status: :ok
render(html: @enterprise.logo_url(:medium), status: :ok)
elsif params[:promo] && @enterprise.update!( promo_image: params[:promo] )
render(html: @enterprise.promo_image_url(:medium), status: :ok)
else
invalid_resource!(@enterprise)
end

View File

@@ -10,7 +10,8 @@ module Api
before_action :validate_report, :authorize_report, :validate_query
def show
@report = report_class.new(current_api_user, ransack_params, report_options)
params[:report_format] = 'json'
@report = report_class.new(current_api_user, params)
render_report
end

View File

@@ -79,8 +79,9 @@ module Api
def remove
variant = scoped_variant(params[:variant_id])
quantity = params[:quantity].to_i
restock_item = params.fetch(:restock_item, "true") == "true"
@order.contents.remove(variant, quantity, @shipment)
@order.contents.remove(variant, quantity, @shipment, restock_item)
@shipment.reload if @shipment.persisted?
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok

View File

@@ -0,0 +1,119 @@
# frozen_string_literal: true
module Api
module V1
class BaseController < ActionController::API
include CanCan::ControllerAdditions
include RequestTimeouts
include Pagy::Backend
include JsonApiPagination
include RaisingParameters
check_authorization
attr_accessor :current_api_user
before_action :authenticate_user
before_action :restrict_feature
rescue_from StandardError, with: :error_during_processing
rescue_from CanCan::AccessDenied, with: :unauthorized
rescue_from ActiveRecord::RecordNotFound, with: :not_found
rescue_from Pagy::VariableError, with: :invalid_pagination
rescue_from ActionController::ParameterMissing, with: :missing_parameter
rescue_from ActionController::UnpermittedParameters, with: :unpermitted_parameters
private
def authenticate_user
return if (@current_api_user = request.env['warden'].user)
if api_key.blank?
# An anonymous user
@current_api_user = Spree::User.new
return
end
return if (@current_api_user = Spree::User.find_by(spree_api_key: api_key.to_s))
invalid_api_key
end
def restrict_feature
not_found unless Flipper.enabled?(:api_v1, @current_api_user)
end
def current_ability
Spree::Ability.new(current_api_user)
end
def api_key
request.headers["X-Api-Token"] || params[:token]
end
def error_during_processing(exception)
Bugsnag.notify(exception)
if Rails.env.development? || Rails.env.test?
render status: :unprocessable_entity,
json: json_api_error(exception.message, meta: exception.backtrace)
else
render status: :unprocessable_entity,
json: json_api_error(I18n.t(:unknown_error, scope: "api"))
end
end
def invalid_pagination(exception)
render status: :unprocessable_entity,
json: json_api_error(exception.message)
end
def missing_parameter(error)
message = I18n.t(:missing_parameter, param: error.param, scope: :api)
render status: :unprocessable_entity,
json: json_api_error(message)
end
def unpermitted_parameters(error)
message = I18n.t(:unpermitted_parameters, params: error.params.join(", "), scope: :api)
render status: :unprocessable_entity,
json: json_api_error(message)
end
def invalid_resource!(resource = nil)
render status: :unprocessable_entity,
json: json_api_invalid(
I18n.t(:invalid_resource, scope: "api"),
resource&.errors
)
end
def invalid_api_key
render status: :unauthorized,
json: json_api_error(I18n.t(:invalid_api_key, key: api_key, scope: "api"))
end
def unauthorized
render status: :unauthorized,
json: json_api_error(I18n.t(:unauthorized, scope: "api"))
end
def not_found
render status: :not_found,
json: json_api_error(I18n.t(:resource_not_found, scope: "api"))
end
def json_api_error(message, **options)
{ errors: [{ detail: message }] }.merge(options)
end
def json_api_invalid(message, errors)
error_response = { errors: [{ detail: message }] }
error_response.merge!(meta: { validation_errors: errors.to_a }) if errors.any?
error_response
end
end
end
end

View File

@@ -0,0 +1,136 @@
# frozen_string_literal: true
require 'open_food_network/permissions'
module Api
module V1
class CustomersController < Api::V1::BaseController
skip_authorization_check only: :index
before_action :set_customer, only: [:show, :update, :destroy]
before_action :authorize_action, only: [:show, :update, :destroy]
def index
@pagy, customers = pagy(search_customers, pagy_options)
render json: Api::V1::CustomerSerializer.new(customers, pagination_options)
end
def show
render json: Api::V1::CustomerSerializer.new(@customer, include_options)
end
def create
authorize! :update, Enterprise.find(customer_params[:enterprise_id])
@customer = Customer.new(customer_params)
if @customer.save
render json: Api::V1::CustomerSerializer.new(@customer), status: :created
else
invalid_resource! @customer
end
end
def update
if @customer.update(customer_params)
render json: Api::V1::CustomerSerializer.new(@customer)
else
invalid_resource! @customer
end
end
def destroy
if @customer.destroy
render json: Api::V1::CustomerSerializer.new(@customer)
else
invalid_resource! @customer
end
end
private
def set_customer
@customer = Customer.find(params[:id])
end
def authorize_action
authorize! action_name.to_sym, @customer
end
def search_customers
customers = visible_customers.includes(:bill_address, :ship_address)
customers = customers.where(enterprise_id: params[:enterprise_id]) if params[:enterprise_id]
customers.ransack(params[:q]).result
end
def visible_customers
current_api_user.customers.or(
Customer.where(enterprise_id: editable_enterprises)
)
end
def customer_params
attributes = params.require(:customer).permit(
:email, :enterprise_id,
:code, :first_name, :last_name,
:billing_address, shipping_address: [
:phone, :latitude, :longitude,
:first_name, :last_name,
:street_address_1, :street_address_2,
:postal_code, :locality, :region, :country,
]
).to_h
attributes.merge!(tag_list: params[:tags]) if params.key?(:tags)
transform_address!(attributes, :billing_address, :bill_address)
transform_address!(attributes, :shipping_address, :ship_address)
attributes
end
def transform_address!(attributes, from, to)
return unless attributes.key?(from)
address = attributes.delete(from)
if address.nil?
attributes[to] = nil
return
end
address.transform_keys! do |key|
{
phone: :phone, latitude: :latitude, longitude: :longitude,
first_name: :firstname, last_name: :lastname,
street_address_1: :address1, street_address_2: :address2,
postal_code: :zipcode,
locality: :city,
region: :state_name,
country: :country,
}.with_indifferent_access[key]
end
if address[:state_name].present?
address[:state] = Spree::State.find_by(name: address[:state_name])
end
if address[:country].present?
address[:country] = Spree::Country.find_by(name: address[:country])
end
attributes["#{to}_attributes"] = address
end
def editable_enterprises
OpenFoodNetwork::Permissions.new(current_api_user).editable_enterprises.select(:id)
end
def include_options
fields = [params.fetch(:include, [])].flatten
{ include: fields.map(&:to_s) }
end
end
end
end

View File

@@ -29,6 +29,7 @@ class ApplicationController < ActionController::Base
helper 'footer_links'
helper 'discourse'
helper 'checkout'
helper 'link'
helper 'terms_and_conditions'
protect_from_forgery

View File

@@ -2,6 +2,7 @@
module CheckoutCallbacks
extend ActiveSupport::Concern
include EnterprisesHelper
included do
# We need pessimistic locking to avoid race conditions.
@@ -46,10 +47,7 @@ module CheckoutCallbacks
end
def load_shipping_methods
@shipping_methods = Spree::ShippingMethod.
for_distributor(@order.distributor).
display_on_checkout.
order(:name)
@shipping_methods = available_shipping_methods.sort { |a, b| a.name.casecmp(b.name) }
end
def redirect_to_shop?

View File

@@ -0,0 +1,74 @@
# frozen_string_literal: true
module JsonApiPagination
extend ActiveSupport::Concern
DEFAULT_PER_PAGE = 50
MAX_PER_PAGE = 200
def pagination_options
{
is_collection: true,
meta: meta_options,
links: links_options,
}
end
def pagy_options
{ items: final_per_page_value }
end
private
def meta_options
{
pagination: {
results: @pagy.count,
pages: total_pages,
page: current_page,
per_page: final_per_page_value
}
}
end
def links_options
{
self: pagination_url(current_page),
first: pagination_url(1),
prev: pagination_url(previous_page),
next: pagination_url(next_page),
last: pagination_url(total_pages)
}
end
def pagination_url(page_number)
return if page_number.nil?
url_for(only_path: false, params: request.query_parameters.merge(page: page_number))
end
# User-specified value, or DEFAULT_PER_PAGE, capped at MAX_PER_PAGE
def final_per_page_value
(params[:per_page] || DEFAULT_PER_PAGE).to_i.clamp(1, MAX_PER_PAGE)
end
def current_page
(params[:page] || 1).to_i
end
def total_pages
@pagy.pages
end
def previous_page
return nil if current_page < 2
current_page - 1
end
def next_page
return nil if current_page >= total_pages
current_page + 1
end
end

View File

@@ -0,0 +1,23 @@
# frozen_string_literal: true
# The API uses strict parameter checking.
#
# We want to raise errors when unused or unpermitted parameters are given
# to the API. You then know straight away when a parameter isn't used.
module RaisingParameters
extend ActiveSupport::Concern
# ActionController manages this config on a per-class basis. The subclass
# enables us to raise errors only here and not in the rest of the app.
class Parameters < ActionController::Parameters
def self.action_on_unpermitted_parameters
:raise
end
end
# We override the params method so that we always use the strict parameters.
# We could rename this method if we need access to the orginal as well.
def params
Parameters.new(super.to_unsafe_hash)
end
end

View File

@@ -3,10 +3,14 @@
module ReportsActions
extend ActiveSupport::Concern
def reports
Reporting::Reports::List.all
end
private
def authorize_report
authorize! report_type&.to_sym, :report
authorize! report_type.to_sym, :report
end
def report_class
@@ -23,31 +27,26 @@ module ReportsActions
params[:report_type]
end
def report_subtypes
reports[report_type.to_sym] || []
end
def report_subtypes_codes
report_subtypes.map(&:second).map(&:to_s)
end
def report_subtype
params[:report_subtype]
params[:report_subtype] || report_subtypes_codes.first
end
def ransack_params
raw_params[:q]
end
def report_options
raw_params[:options]
end
def report_format
params[:report_format]
end
def export_spreadsheet?
['xlsx', 'ods', 'csv'].include?(report_format)
end
def form_options_required?
[:packing, :customers, :products_and_inventory, :order_cycle_management].
include? report_type.to_sym
end
def report_filename
"#{report_type || action_name}_#{file_timestamp}.#{report_format}"
end

View File

@@ -14,6 +14,7 @@ class SplitCheckoutController < ::BaseController
helper 'terms_and_conditions'
helper 'checkout'
helper 'spree/orders'
helper EnterprisesHelper
helper OrderHelper
before_action :set_checkout_redirect
@@ -30,12 +31,16 @@ class SplitCheckoutController < ::BaseController
advance_order_state
redirect_to_step
else
flash.now[:error] = I18n.t('split_checkout.errors.global')
flash.now[:error] ||= I18n.t('split_checkout.errors.global')
render status: :unprocessable_entity, operations: cable_car.
replace("#checkout", partial("split_checkout/checkout")).
replace("#flashes", partial("shared/flashes", locals: { flashes: flash }))
end
rescue Spree::Core::GatewayError => e
flash[:error] = I18n.t(:spree_gateway_error_flash_for_checkout, error: e.message)
@order.update_column(:state, "payment")
render operations: cable_car.redirect_to(url: checkout_step_path(:payment))
end
private
@@ -127,7 +132,7 @@ class SplitCheckoutController < ::BaseController
when "confirmation"
redirect_to checkout_step_path(:summary)
else
redirect_to order_path(@order)
redirect_to order_path(@order, order_token: @order.token)
end
end

View File

@@ -65,7 +65,9 @@ module Spree
def fire
event = params[:e]
@order.send_cancellation_email = params[:send_cancellation_email] == "true"
@order.send_cancellation_email = params[:send_cancellation_email] != "false"
@order.restock_items = params.fetch(:restock_items, "true") == "true"
if @order.public_send(event.to_s)
flash[:success] = Spree.t(:order_updated)
else

View File

@@ -39,9 +39,6 @@ module Spree
render :new
end
end
rescue Paperclip::Errors::NotIdentifiedByImageMagickError
@object.errors.add(:base, t('spree.admin.products.image_upload_error'))
respond_with(@object)
end
def show

View File

@@ -1,310 +0,0 @@
# frozen_string_literal: true
require 'csv'
require 'open_food_network/reports/list'
require 'open_food_network/order_and_distributor_report'
require 'open_food_network/products_and_inventory_report'
require 'open_food_network/lettuce_share_report'
require 'open_food_network/group_buy_report'
require 'open_food_network/order_grouper'
require 'open_food_network/customers_report'
require 'open_food_network/users_and_enterprises_report'
require 'open_food_network/order_cycle_management_report'
require 'open_food_network/sales_tax_report'
require 'open_food_network/xero_invoices_report'
require 'open_food_network/payments_report'
require 'open_food_network/orders_and_fulfillments_report'
module Spree
module Admin
class ReportsController < Spree::Admin::BaseController
include Spree::ReportsHelper
helper ::ReportsHelper
ORDER_MANAGEMENT_ENGINE_REPORTS = [
:bulk_coop,
:enterprise_fee_summary
].freeze
helper_method :render_content?
before_action :cache_search_state
# Fetches user's distributors, suppliers and order_cycles
before_action :load_basic_data, only: [:customers, :products_and_inventory, :order_cycle_management]
before_action :load_associated_data, only: [:orders_and_fulfillment]
respond_to :html
def report_types
OpenFoodNetwork::Reports::List.all
end
def index
@reports = authorized_reports
respond_with(@reports)
end
def customers
@report_types = report_types[:customers]
@report_type = params[:report_type]
@report = OpenFoodNetwork::CustomersReport.new spree_current_user, raw_params,
render_content?
render_report(@report.header, @report.table, params[:csv], "customers_#{timestamp}.csv")
end
def order_cycle_management
raw_params[:q] ||= {}
@report_types = report_types[:order_cycle_management]
@report_type = params[:report_type]
# -- Build Report with Order Grouper
@report = OpenFoodNetwork::OrderCycleManagementReport.new spree_current_user,
raw_params,
render_content?
@table = @report.table_items
render_report(@report.header, @table, params[:csv],
"order_cycle_management_#{timestamp}.csv")
end
def orders_and_distributors
@report = OpenFoodNetwork::OrderAndDistributorReport.new spree_current_user,
raw_params,
render_content?
@search = @report.search
csv_file_name = "orders_and_distributors_#{timestamp}.csv"
render_report(@report.header, @report.table, params[:csv], csv_file_name)
end
def sales_tax
@distributors = my_distributors
@report_type = params[:report_type]
@report = OpenFoodNetwork::SalesTaxReport.new spree_current_user, raw_params,
render_content?
render_report(@report.header, @report.table, params[:csv], "sales_tax.csv")
end
def payments
# -- Prepare Form Options
@distributors = my_distributors
@report_type = params[:report_type]
# -- Build Report with Order Grouper
@report = OpenFoodNetwork::PaymentsReport.new spree_current_user, raw_params,
render_content?
@table = order_grouper_table
csv_file_name = "payments_#{timestamp}.csv"
render_report(@report.header, @table, params[:csv], csv_file_name)
end
def orders_and_fulfillment
raw_params[:q] ||= orders_and_fulfillment_default_filters
@report_types = report_types[:orders_and_fulfillment]
@report_type = params[:report_type]
@include_blank = I18n.t(:all)
# -- Build Report with Order Grouper
@report = OpenFoodNetwork::OrdersAndFulfillmentsReport.new spree_current_user,
raw_params,
render_content?
@table = order_grouper_table
csv_file_name = "#{params[:report_type]}_#{timestamp}.csv"
render_report(@report.header, @table, params[:csv], csv_file_name)
end
def products_and_inventory
@report_types = report_types[:products_and_inventory]
@report = if params[:report_type] != 'lettuce_share'
OpenFoodNetwork::ProductsAndInventoryReport.new spree_current_user,
raw_params,
render_content?
else
OpenFoodNetwork::LettuceShareReport.new spree_current_user,
raw_params,
render_content?
end
render_report @report.header,
@report.table,
params[:csv],
"products_and_inventory_#{timestamp}.csv"
end
def users_and_enterprises
@report = OpenFoodNetwork::UsersAndEnterprisesReport.new raw_params, render_content?
render_report(@report.header, @report.table, params[:csv],
"users_and_enterprises_#{timestamp}.csv")
end
def xero_invoices
raw_params[:q] ||= {}
@distributors = my_distributors
@order_cycles = my_order_cycles
@report = OpenFoodNetwork::XeroInvoicesReport.new(spree_current_user,
raw_params,
render_content?)
render_report(@report.header, @report.table, params[:csv], "xero_invoices_#{timestamp}.csv")
end
private
def model_class
Spree::Admin::ReportsController
end
# Some actions are changing the `params` object. That is unfortunate Spree
# behavior and we are building on it. So we have to look at `params` early
# to check if we are searching or just displaying a report search form.
def cache_search_state
search_keys = [
# search parameter for ransack
:q,
# common in all reports, only set for CSV rendering
:csv,
# `button` is included in all forms. It's not important for searching,
# but the Users & Enterprises report doesn't have any other parameter
# for an empty search. So we use this one to display data.
:button,
# Some reports use filtering by enterprise or order cycle
:distributor_id,
:supplier_id,
:order_cycle_id,
# Xero Invoices can be filtered by date
:invoice_date,
:due_date
]
@searching = search_keys.any? { |key| raw_params.key? key }
end
# We don't want to render data unless search params are supplied.
# Compiling data can take a long time.
def render_content?
@searching
end
def render_report(header, table, create_csv, csv_file_name)
send_data csv_report(header, table), filename: csv_file_name if create_csv
@header = header
@table = table
# Rendering HTML is the default.
end
def load_associated_data
form_options = Reporting::FrontendData.new(spree_current_user)
@distributors = form_options.distributors
@suppliers = form_options.suppliers
@order_cycles = form_options.order_cycles
end
def csv_report(header, table)
CSV.generate do |csv|
csv << header
table.each { |row| csv << row }
end
end
def load_basic_data
@distributors = my_distributors
@suppliers = my_suppliers | suppliers_of_products_distributed_by(@distributors)
@order_cycles = my_order_cycles
end
# Load managed distributor enterprises of current user
def my_distributors
Enterprise.is_distributor.managed_by(spree_current_user)
end
# Load managed producer enterprises of current user
def my_suppliers
Enterprise.is_primary_producer.managed_by(spree_current_user)
end
def suppliers_of_products_distributed_by(distributors)
supplier_ids = Spree::Product.in_distributors(distributors.select('enterprises.id')).
select('spree_products.supplier_id')
Enterprise.where(id: supplier_ids)
end
# Load order cycles the current user has access to
def my_order_cycles
OrderCycle.
active_or_complete.
visible_by(spree_current_user).
order('orders_close_at DESC')
end
def order_grouper_table
order_grouper = OpenFoodNetwork::OrderGrouper.new @report.rules, @report.columns, @report
order_grouper.table(@report.table_items)
end
def authorized_reports
all_reports = [
:orders_and_distributors,
:bulk_coop,
:payments,
:orders_and_fulfillment,
:customers,
:products_and_inventory,
:users_and_enterprises,
:enterprise_fee_summary,
:order_cycle_management,
:sales_tax,
:xero_invoices,
:packing
]
reports = all_reports.select { |action| can? action, Spree::Admin::ReportsController }
reports.map { |report| [report, describe_report(report)] }.to_h
end
def describe_report(report)
name = I18n.t(:name, scope: [:admin, :reports, report])
description = begin
I18n.t!(:description, scope: [:admin, :reports, report])
rescue I18n::MissingTranslationData
render_to_string(
partial: "#{report}_description",
layout: false,
locals: { report_types: report_types[report] }
).html_safe
end
{ name: name, url: url_for_report(report), description: description }
end
def url_for_report(report)
if report_in_order_management_engine?(report)
main_app.public_send("new_order_management_reports_#{report}_url".to_sym)
else
spree.public_send("#{report}_admin_reports_url".to_sym)
end
rescue NoMethodError
main_app.admin_reports_url(report_type: report)
end
# List of reports that have been moved to the Order Management engine
def report_in_order_management_engine?(report)
ORDER_MANAGEMENT_ENGINE_REPORTS.include?(report)
end
def timestamp
Time.zone.now.strftime("%Y%m%d")
end
def orders_and_fulfillment_default_filters
now = Time.zone.now
{ completed_at_gt: (now - 1.month).beginning_of_day,
completed_at_lt: (now + 1.day).beginning_of_day }
end
end
end
end

View File

@@ -13,6 +13,7 @@ module Spree
helper 'spree/base'
prepend_before_action :handle_unconfirmed_email
before_action :set_checkout_redirect, only: :create
after_action :ensure_valid_locale_persisted, only: :create
@@ -49,6 +50,22 @@ module Spree
Spree.t(:login)
end
def handle_unconfirmed_email
render_unconfirmed_response if email_unconfirmed?
end
def email_unconfirmed?
Spree::User.where(email: params.dig(:spree_user, :email), confirmed_at: nil).exists?
end
def render_unconfirmed_response
render status: :unprocessable_entity, operations: cable_car.inner_html(
"#login-feedback",
partial("layouts/alert", locals: { type: "alert", message: t(:email_unconfirmed),
unconfirmed: true, tab: "login" })
)
end
def ensure_valid_locale_persisted
# When creating a new user session we have to wait until after a successful
# login to be able to persist a selected locale on the current user

View File

@@ -62,8 +62,7 @@ module Spree
if params[:user][:password].present?
# this logic needed b/c devise wants to log us out after password changes
Spree::User.reset_password_by_token(params[:user])
sign_in(@user, event: :authentication,
bypass: true)
bypass_sign_in(@user)
end
redirect_to spree.account_url, notice: Spree.t(:account_updated)
else

View File

@@ -23,7 +23,7 @@ class UserConfirmationsController < DeviseController
end
else
render operations: cable_car.inner_html(
"#forgot-feedback",
"##{params[:tab] || 'forgot'}-feedback",
partial("layouts/alert", locals: { type: "success", message: t("devise.confirmations.send_instructions") })
)
return

View File

@@ -29,7 +29,8 @@ class UserPasswordsController < Spree::UserPasswordsController
render status: :unprocessable_entity, operations: cable_car.inner_html(
"#forgot-feedback",
partial("layouts/alert",
locals: { type: "alert", message: t(:email_unconfirmed), unconfirmed: true })
locals: { type: "alert", message: t(:email_unconfirmed),
unconfirmed: true, tab: "forgot" })
)
end

View File

@@ -27,6 +27,17 @@ module ApplicationHelper
OpenFoodNetwork::FeatureToggle.enabled?(feature, user)
end
def language_meta_tags
return if I18n.available_locales.one?
I18n.available_locales.map do |locale|
tag.link(
hreflang: locale.to_s.gsub("_", "-").downcase,
href: "#{request.protocol}#{request.host_with_port}/locales/#{locale}"
)
end.join("\n").html_safe
end
def ng_form_for(name, *args, &block)
options = args.extract_options!

View File

@@ -1,6 +1,6 @@
# frozen_string_literal: true
module GroupsHelper
module LinkHelper
def link_to_service(baseurl, name, html_options = {}, &block)
return if name.blank?
@@ -15,8 +15,4 @@ module GroupsHelper
prefix + url
end
end
def strip_url(url)
url&.sub(%r{^https?://}i, '')
end
end

View File

@@ -9,7 +9,24 @@ module ReportsHelper
end
end
def report_subtypes(report)
Reporting::ReportLoader.new(report).report_subtypes
def report_payment_method_options(orders)
orders.map do |order|
payment_method = order.payments.last&.payment_method
next unless payment_method
[payment_method.name, payment_method.id]
end.compact.uniq
end
def report_shipping_method_options(orders)
orders.map do |o|
sm = o.shipping_method
[sm&.name, sm&.id]
end.uniq
end
def currency_symbol
Spree::Money.currency_symbol
end
end

View File

@@ -77,7 +77,7 @@ module Spree
klass = EnterpriseGroup if klass == :group
klass = VariantOverride if klass == :Inventory
klass = ProductImport::ProductImporter if klass == :import
klass = Spree::Admin::ReportsController if klass == :report
klass = ::Admin::ReportsController if klass == :report
klass
end
@@ -115,7 +115,7 @@ module Spree
if html_options[:method] &&
html_options[:method].to_s.downcase != 'get' &&
!html_options[:remote]
form_tag(url, method: html_options.delete(:method)) do
form_tag(url, method: html_options.delete(:method), id: html_options.delete(:form_id)) do
button(text, html_options.delete(:icon), nil, html_options)
end
else

View File

@@ -5,8 +5,8 @@ module Spree
module OrdersHelper
def event_links
links = []
links << event_link("cancel") if @order.can_cancel?
links << event_link("resume") if @order.can_resume?
links << cancel_event_link if @order.can_cancel?
links << resume_event_link if @order.can_resume?
links.join('&nbsp;').html_safe
end
@@ -114,12 +114,19 @@ module Spree
confirm: t(:are_you_sure) }
end
def event_link(event)
event_label = I18n.t(event, scope: "actions")
def cancel_event_link
event_label = I18n.t("cancel", scope: "actions")
button_link_to(event_label,
fire_admin_order_url(@order, e: "cancel"),
method: :put, icon: "icon-cancel", form_id: "cancel_order_form")
end
def resume_event_link
event_label = I18n.t("resume", scope: "actions")
confirm_message = I18n.t("admin.orders.edit.order_sure_want_to", event: event_label)
button_link_to(event_label,
fire_admin_order_url(@order, e: event),
method: :put, icon: "icon-#{event}",
fire_admin_order_url(@order, e: "resume"),
method: :put, icon: "icon-resume",
data: { confirm: confirm_message })
end

View File

@@ -1,33 +0,0 @@
# frozen_string_literal: true
require 'spree/money'
module Spree
module ReportsHelper
def report_payment_method_options(orders)
orders.map do |order|
payment_method = order.payments.last&.payment_method
next unless payment_method
[payment_method.name, payment_method.id]
end.compact.uniq
end
def report_shipping_method_options(orders)
orders.map do |o|
sm = o.shipping_method
[sm&.name, sm&.id]
end.uniq
end
def xero_report_types
[[I18n.t(:summary), 'summary'],
[I18n.t(:detailed), 'detailed']]
end
def currency_symbol
Spree::Money.currency_symbol
end
end
end

View File

@@ -0,0 +1,64 @@
# frozen_string_literal: true
class CustomerSchema < JsonApiSchema
def self.object_name
"customer"
end
def self.attributes
{
id: { type: :integer, example: 1 },
enterprise_id: { type: :integer, example: 2 },
first_name: { type: :string, nullable: true, example: "Alice" },
last_name: { type: :string, nullable: true, example: "Springs" },
code: { type: :string, nullable: true, example: "BUYER1" },
email: { type: :string, example: "alice@example.com" },
allow_charges: { type: :boolean, example: false },
tags: { type: :array, items: { type: :string }, example: ["staff", "discount"] },
terms_and_conditions_accepted_at: {
type: :string, format: "date-time", nullable: true,
example: "2022-03-12T15:55:00.000+11:00",
},
billing_address: {
type: :object, nullable: true,
example: nil,
},
shipping_address: {
type: :object, nullable: true,
example: address_example,
},
}
end
def self.address_example
{
phone: "0404 333 222 111",
latitude: -37.817375100000,
longitude: 144.964803195704,
first_name: "Alice",
last_name: "Springs",
street_address_1: "1 Flinders Street",
street_address_2: "",
postal_code: "1234",
locality: "Melbourne",
region: "Victoria",
country: "Australia",
}
end
def self.required_attributes
[:enterprise_id, :email]
end
def self.writable_attributes
attributes.except(
:id,
:allow_charges,
:terms_and_conditions_accepted_at,
)
end
def self.relationships
[:enterprise]
end
end

View File

@@ -0,0 +1,24 @@
# frozen_string_literal: true
class ErrorsSchema
def self.schema
{
type: :object,
properties: {
errors: {
type: :array,
items: {
type: :object,
properties: {
title: { type: :string },
detail: { type: :string },
source: { type: :object }
},
required: [:detail]
}
}
},
required: [:errors]
}
end
end

View File

@@ -0,0 +1,114 @@
# frozen_string_literal: true
class JsonApiSchema
class << self
def attributes
{}
end
def required_attributes
[]
end
def relationships
[]
end
def all_attributes
attributes.keys
end
def schema(options = {})
{
type: :object,
properties: {
data: {
type: :object,
properties: data_properties(**options)
},
meta: { type: :object },
links: { type: :object }
},
required: [:data]
}
end
def collection(options)
{
type: :object,
properties: {
data: {
type: :array,
items: {
type: :object,
properties: data_properties(**options)
}
},
meta: {
type: :object,
properties: {
pagination: {
type: :object,
properties: {
results: { type: :integer, example: 250 },
pages: { type: :integer, example: 5 },
page: { type: :integer, example: 2 },
per_page: { type: :integer, example: 50 },
}
}
},
required: [:pagination]
},
links: {
type: :object,
properties: {
self: { type: :string },
first: { type: :string },
prev: { type: :string, nullable: true },
next: { type: :string, nullable: true },
last: { type: :string }
}
}
},
required: [:data, :meta, :links]
}
end
private
def data_properties(require_all: false)
required = require_all ? all_attributes : required_attributes
{
id: { type: :string, example: "1" },
type: { type: :string, example: object_name },
attributes: {
type: :object,
properties: attributes,
required: required
},
relationships: {
type: :object,
properties: relationships.to_h do |name|
[
name,
relationship_schema(name)
]
end
}
}
end
def relationship_schema(name)
if is_singular?(name)
RelationshipSchema.schema(name)
else
RelationshipSchema.collection(name)
end
end
def is_singular?(name)
name.to_s.singularize == name.to_s
end
end
end

View File

@@ -0,0 +1,48 @@
# frozen_string_literal: true
class RelationshipSchema
def self.schema(resource_name = nil)
{
type: :object,
properties: {
data: {
type: :object,
properties: {
id: { type: :string },
type: { type: :string, example: resource_name }
}
},
links: {
type: :object,
properties: {
related: { type: :string }
}
}
}
}
end
def self.collection(resource_name = nil)
{
type: :object,
properties: {
data: {
type: :array,
items: {
type: :object,
properties: {
id: { type: :string },
type: { type: :string, example: resource_name }
}
}
},
links: {
type: :object,
properties: {
related: { type: :string }
}
}
}
}
end
end

View File

@@ -0,0 +1,43 @@
# frozen_string_literal: true
module FilePreferences
extend ActiveSupport::Concern
included do
@default_urls = {}
end
class_methods do
def file_preference(name, default_url: nil)
preference "#{name}_blob_id", :integer
@default_urls[name] = default_url if default_url
end
def default_url(name)
@default_urls[name]
end
end
def preference_type(key)
if has_preference?("#{key}_blob_id")
:file
else
super(key)
end
end
def url_for(name)
blob = blob_for(name)
if blob
Rails.application.routes.url_helpers.url_for(blob)
else
self.class.default_url(name)
end
end
def blob_for(name)
blob_id = get_preference("#{name}_blob_id")
ActiveStorage::Blob.find_by(id: blob_id) if blob_id
end
end

View File

@@ -1,23 +1,17 @@
# frozen_string_literal: true
require 'open_food_network/paperclippable'
class ContentConfiguration < Spree::Preferences::FileConfiguration
include OpenFoodNetwork::Paperclippable
class ContentConfiguration < Spree::Preferences::Configuration
include FilePreferences
# Header
preference :logo, :file
preference :logo_mobile, :file
preference :logo_mobile_svg, :file
has_attached_file :logo, default_url: "/default_images/ofn-logo.png"
has_attached_file :logo_mobile
has_attached_file :logo_mobile_svg, default_url: "/default_images/ofn-logo-mobile.svg"
file_preference :logo, default_url: "/default_images/ofn-logo.png"
file_preference :logo_mobile
file_preference :logo_mobile_svg, default_url: "/default_images/ofn-logo-mobile.svg"
# Home page
preference :home_page_alert_html, :text
preference :home_hero, :file
file_preference :home_hero, default_url: "/default_images/home.jpg"
preference :home_show_stats, :boolean, default: true
has_attached_file :home_hero, default_url: "/default_images/home.jpg"
# Map
preference :open_street_map_enabled, :boolean, default: false
@@ -66,8 +60,7 @@ class ContentConfiguration < Spree::Preferences::FileConfiguration
preference :menu_7_icon_name, :string, default: "ofn-i_013-help"
# Footer
preference :footer_logo, :file
has_attached_file :footer_logo, default_url: "/default_images/ofn-logo-footer.png"
file_preference :footer_logo, default_url: "/default_images/ofn-logo-footer.png"
# Other
preference :footer_facebook_url, :string, default: "https://www.facebook.com/OpenFoodNet"

View File

@@ -1,12 +1,20 @@
# frozen_string_literal: false
require 'spree/core/s3_support'
class Enterprise < ApplicationRecord
include Spree::Core::S3Support
SELLS = %w(unspecified none own any).freeze
ENTERPRISE_SEARCH_RADIUS = 100
# The next Rails version will have named variants but we need to store them
# ourselves for now.
LOGO_SIZES = {
thumb: { resize_to_limit: [100, 100] },
small: { resize_to_limit: [180, 180] },
medium: { resize_to_limit: [300, 300] },
}.freeze
PROMO_IMAGE_SIZES = {
thumb: { resize_to_limit: [100, 100] },
medium: { resize_to_fill: [720, 156] },
large: { resize_to_fill: [1200, 260] },
}.freeze
searchable_attributes :sells, :is_primary_producer
searchable_associations :properties
@@ -19,6 +27,8 @@ class Enterprise < ApplicationRecord
preference :shopfront_producer_order, :string, default: ""
preference :shopfront_order_cycle_order, :string, default: "orders_close_at"
preference :shopfront_product_sorting_method, :string, default: "by_category"
preference :invoice_order_by_supplier, :boolean, default: false
preference :product_low_stock_display, :boolean, default: false
# Allow hubs to restrict visible variants to only those in their inventory
preference :product_selection_from_inventory_only, :boolean, default: false
@@ -70,31 +80,16 @@ class Enterprise < ApplicationRecord
tag_rule[:preferred_customer_tags].blank?
}
has_attached_file :logo,
styles: { medium: "300x300>", small: "180x180>", thumb: "100x100>" },
url: '/images/enterprises/logos/:id/:style/:basename.:extension',
path: 'public/images/enterprises/logos/:id/:style/:basename.:extension'
has_one_attached :logo
has_one_attached :promo_image
has_one_attached :terms_and_conditions
has_attached_file :promo_image,
styles: {
large: ["1200x260#", :jpg],
medium: ["720x156#", :jpg],
thumb: ["100x100>", :jpg]
},
url: '/images/enterprises/promo_images/:id/:style/:basename.:extension',
path: 'public/images/enterprises/promo_images/:id/:style/:basename.:extension'
validates_attachment_content_type :logo, content_type: %r{\Aimage/.*\Z}
validates_attachment_content_type :promo_image, content_type: %r{\Aimage/.*\Z}
has_attached_file :terms_and_conditions,
url: '/files/enterprises/terms_and_conditions/:id/:basename.:extension',
path: 'public/files/enterprises/terms_and_conditions/:id/:basename.:extension'
validates_attachment_content_type :terms_and_conditions,
content_type: "application/pdf",
message: I18n.t(:enterprise_terms_and_conditions_type_error)
supports_s3 :logo
supports_s3 :promo_image
validates :logo, content_type: %r{\Aimage/.*\Z}
validates :promo_image, content_type: %r{\Aimage/.*\Z}
validates :terms_and_conditions, content_type: {
in: "application/pdf",
message: I18n.t(:enterprise_terms_and_conditions_type_error),
}
validates :name, presence: true
validate :name_is_unique
@@ -118,7 +113,8 @@ class Enterprise < ApplicationRecord
after_rollback :restore_permalink
scope :by_name, -> { order('name') }
scope :visible, -> { where(visible: true) }
scope :visible, -> { where(visible: "public") }
scope :not_hidden, -> { where.not(visible: "hidden") }
scope :activated, -> { where("sells != 'unspecified'") }
scope :ready_for_checkout, lambda {
joins(:shipping_methods).
@@ -265,7 +261,7 @@ class Enterprise < ApplicationRecord
def plus_relatives_and_oc_producers(order_cycles)
oc_producer_ids = Exchange.in_order_cycle(order_cycles).incoming.pluck :sender_id
Enterprise.is_primary_producer.relatives_of_one_union_others(id, oc_producer_ids | [id])
Enterprise.not_hidden.is_primary_producer.relatives_of_one_union_others(id, oc_producer_ids | [id])
end
def relatives_including_self
@@ -280,6 +276,22 @@ class Enterprise < ApplicationRecord
relatives_including_self.is_primary_producer
end
def logo_url(name)
return unless logo.variable?
Rails.application.routes.url_helpers.url_for(
logo.variant(LOGO_SIZES[name])
)
end
def promo_image_url(name)
return unless promo_image.variable?
Rails.application.routes.url_helpers.url_for(
promo_image.variant(PROMO_IMAGE_SIZES[name])
)
end
def website
strip_url self[:website]
end
@@ -399,6 +411,10 @@ class Enterprise < ApplicationRecord
abn.present?
end
def public?
visible == "public"
end
protected
def devise_mailer

View File

@@ -1,11 +1,9 @@
# frozen_string_literal: true
require 'open_food_network/locking'
require 'spree/core/s3_support'
class EnterpriseGroup < ApplicationRecord
include PermalinkGenerator
include Spree::Core::S3Support
acts_as_list
@@ -27,21 +25,11 @@ class EnterpriseGroup < ApplicationRecord
delegate :phone, :address1, :address2, :city, :zipcode, :state, :country, to: :address
has_attached_file :logo,
styles: { medium: "100x100" },
url: '/images/enterprise_groups/logos/:id/:style/:basename.:extension',
path: 'public/images/enterprise_groups/logos/:id/:style/:basename.:extension'
has_one_attached :logo
has_one_attached :promo_image
has_attached_file :promo_image,
styles: { large: ["1200x260#", :jpg] },
url: '/images/enterprise_groups/promo_images/:id/:style/:basename.:extension',
path: 'public/images/enterprise_groups/promo_images/:id/:style/:basename.:extension'
validates_attachment_content_type :logo, content_type: %r{\Aimage/.*\Z}
validates_attachment_content_type :promo_image, content_type: %r{\Aimage/.*\Z}
supports_s3 :logo
supports_s3 :promo_image
validates :logo, content_type: %r{\Aimage/.*\Z}
validates :promo_image, content_type: %r{\Aimage/.*\Z}
scope :by_position, -> { order('position ASC') }
scope :on_front_page, -> { where(on_front_page: true) }

View File

@@ -10,7 +10,8 @@ class OrderCycle < ApplicationRecord
belongs_to :coordinator, class_name: 'Enterprise'
has_many :coordinator_fee_refs, class_name: 'CoordinatorFee'
has_many :coordinator_fees, through: :coordinator_fee_refs, source: :enterprise_fee
has_many :coordinator_fees, through: :coordinator_fee_refs, source: :enterprise_fee,
dependent: :destroy
has_many :exchanges, dependent: :destroy

View File

@@ -236,12 +236,10 @@ module Spree
:validate_data, :reset_absent_products], ProductImport::ProductImporter
# Reports page
can [:admin, :index, :customers, :orders_and_distributors, :group_buys, :payments,
:orders_and_fulfillment, :products_and_inventory, :order_cycle_management, :packing],
Spree::Admin::ReportsController
can [:admin, :show, :packing], :report
add_bulk_coop_abilities
add_enterprise_fee_summary_abilities
can [:admin, :index, :show], ::Admin::ReportsController
can [:admin, :show, :customers, :orders_and_distributors, :group_buys, :payments,
:orders_and_fulfillment, :products_and_inventory, :order_cycle_management,
:packing, :enterprise_fee_summary, :bulk_coop], :report
end
def add_order_cycle_management_abilities(user)
@@ -317,11 +315,10 @@ module Spree
end
# Reports page
can [:admin, :index, :customers, :group_buys, :sales_tax, :payments,
can [:admin, :index, :show], ::Admin::ReportsController
can [:admin, :customers, :group_buys, :sales_tax, :payments,
:orders_and_distributors, :orders_and_fulfillment, :products_and_inventory,
:order_cycle_management, :xero_invoices], Spree::Admin::ReportsController
add_bulk_coop_abilities
add_enterprise_fee_summary_abilities
:order_cycle_management, :xero_invoices, :enterprise_fee_summary, :bulk_coop], :report
can [:create], Customer
can [:admin, :index, :update,
@@ -346,19 +343,5 @@ module Spree
user.enterprises.include?(enterprise_relationship.child)
end
end
def add_bulk_coop_abilities
# Reveal the report link in spree/admin/reports#index
can [:bulk_coop], Spree::Admin::ReportsController
# Allow direct access to the report resource
can [:admin, :new, :create], :bulk_coop
end
def add_enterprise_fee_summary_abilities
# Reveal the report link in spree/admin/reports#index
can [:enterprise_fee_summary], Spree::Admin::ReportsController
# Allow direct access to the report resource
can [:admin, :new, :create], :enterprise_fee_summary
end
end
end

View File

@@ -105,6 +105,10 @@ module Spree
render_address([city, zipcode, state&.name])
end
def address_and_city
[address1, address2, city].select(&:present?).join(' ')
end
private
def require_zipcode?

View File

@@ -1,101 +1,39 @@
# frozen_string_literal: true
require 'spree/core/s3_support'
module Spree
class Image < Asset
validates_attachment_presence :attachment
SIZES = {
mini: { resize_to_fill: [48, 48] },
small: { resize_to_fill: [227, 227] },
product: { resize_to_limit: [240, 240] },
large: { resize_to_limit: [600, 600] },
}.freeze
has_one_attached :attachment
validates :attachment, attached: true, content_type: %r{\Aimage/.*\Z}
validate :no_attachment_errors
# This is where the styles are used in the app:
# - mini: used in the BackOffice: Bulk Product Edit page and Order Cycle edit page
# - small: used in the FrontOffice: Product List page
# - product: used in the BackOffice: Product Image upload modal in the Bulk Product Edit page
# and Product image edit page
# - large: used in the FrontOffice: product modal
has_attached_file :attachment,
styles: { mini: "48x48#", small: "227x227#",
product: "240x240>", large: "600x600>" },
default_style: :product,
url: '/spree/products/:id/:style/:basename.:extension',
path: ':rails_root/public/spree/products/:id/:style/:basename.:extension',
convert_options: { all: '-strip -auto-orient -colorspace sRGB' }
# save the w,h of the original image (from which others can be calculated)
# we need to look at the write-queue for images which have not been saved yet
after_post_process :find_dimensions
include Spree::Core::S3Support
supports_s3 :attachment
# used by admin products autocomplete
def mini_url
attachment.url(:mini, false)
def variant(name)
attachment.variant(SIZES[name])
end
def find_dimensions
return if attachment.errors.present?
def url(size)
return unless attachment.variable?
geometry = Paperclip::Geometry.from_file(local_filename_of_original)
self.attachment_width = geometry.width
self.attachment_height = geometry.height
end
def local_filename_of_original
temporary = attachment.queued_for_write[:original]
if temporary&.path.present?
temporary.path
else
attachment.path
end
Rails.application.routes.url_helpers.url_for(variant(size))
end
# if there are errors from the plugin, then add a more meaningful message
def no_attachment_errors
return if attachment.errors.empty?
return if errors[:attachment].empty?
if errors.all? { |e| e.type == "Paperclip::Errors::NotIdentifiedByImageMagickError" }
if errors.all? { |e| e.type == :content_type_invalid }
attachment.errors.clear
errors.add :base, I18n.t('spree.admin.products.image_upload_error')
else
errors.add :attachment,
I18n.t('spree.admin.products.paperclip_image_error', attachment_file_name: attachment_file_name)
end
false
end
def self.set_attachment_attribute(attribute_name, attribute_value)
attachment_definitions[:attachment][attribute_name] = attribute_value
end
def self.set_storage_attachment_attributes
if Spree::Config[:use_s3]
set_s3_attachment_attributes
else
attachment_definitions[:attachment].delete(:storage)
end
end
def self.set_s3_attachment_attributes
set_attachment_attribute(:storage, :s3)
set_attachment_attribute(:s3_credentials, s3_credentials)
set_attachment_attribute(:s3_headers,
ActiveSupport::JSON.decode(Spree::Config[:s3_headers]))
set_attachment_attribute(:bucket, Spree::Config[:s3_bucket])
# We use :s3_alias_url (virtual host url style) and set the URL on property s3_host_alias
set_attachment_attribute(:s3_host_alias, attachment_definitions[:attachment][:url])
set_attachment_attribute(:url, ":s3_alias_url")
end
private_class_method :set_s3_attachment_attributes
def self.s3_credentials
{ access_key_id: Spree::Config[:s3_access_key],
secret_access_key: Spree::Config[:s3_secret],
bucket: Spree::Config[:s3_bucket] }
end
private_class_method :s3_credentials
end
end

View File

@@ -50,6 +50,8 @@ module Spree
attr_accessor :skip_stock_check, :target_shipment # Allows manual skipping of Stock::AvailabilityValidator
attribute :restock_item, type: :boolean, default: true
# -- Scopes
scope :managed_by, lambda { |user|
if user.has_spree_role?('admin')

View File

@@ -106,6 +106,7 @@ module Spree
after_save_commit DefaultAddressUpdater
attribute :send_cancellation_email, type: :boolean, default: true
attribute :restock_items, type: :boolean, default: true
# -- Scopes
scope :not_empty, -> {
left_outer_joins(:line_items).where.not(spree_line_items: { id: nil })
@@ -429,9 +430,10 @@ module Spree
def empty!
line_items.destroy_all
adjustments.destroy_all
all_adjustments.destroy_all
payments.clear
shipments.destroy_all
restart_checkout_flow if state == "payment"
end
def state_changed(name)
@@ -609,6 +611,14 @@ module Spree
address
end
def sorted_line_items
if distributor.preferred_invoice_order_by_supplier
line_items.sort_by { |li| [li.supplier.name, li.product.name] }
else
line_items.sort_by { |li| [li.product.name] }
end
end
private
def fee_handler
@@ -661,11 +671,12 @@ module Spree
shipments.each(&:cancel!)
OrderMailer.cancel_email(id).deliver_later if send_cancellation_email
self.payment_state = 'credit_owed' unless shipped?
update(payment_state: updater.update_payment_state)
end
def after_resume
shipments.each(&:resume!)
update(payment_state: updater.update_payment_state)
end
def use_billing?

View File

@@ -19,8 +19,8 @@ module Spree
# Get current line item for variant
# Remove variant qty from line_item
def remove(variant, quantity = nil, shipment = nil)
line_item = remove_from_line_item(variant, quantity, shipment)
def remove(variant, quantity = nil, shipment = nil, restock_item = true)
line_item = remove_from_line_item(variant, quantity, shipment, restock_item)
update_shipment(shipment)
order.update_order_fees! if order.completed?
update_order
@@ -97,9 +97,9 @@ module Spree
line_item
end
def remove_from_line_item(variant, quantity, shipment = nil)
def remove_from_line_item(variant, quantity, shipment = nil, restock_item = true)
line_item = find_line_item_by_variant(variant, true)
line_item.restock_item = restock_item
quantity.present? ? line_item.quantity += -quantity : line_item.quantity = 0
line_item.target_shipment = shipment

View File

@@ -44,12 +44,15 @@ module Spree
quantity = variant_units.size - line_item.quantity
if shipment.present?
remove_from_shipment(shipment, line_item.variant, quantity)
remove_from_shipment(shipment, line_item.variant, quantity, line_item.restock_item)
else
order.shipments.each do |each_shipment|
break if quantity == 0
quantity -= remove_from_shipment(each_shipment, line_item.variant, quantity)
quantity -= remove_from_shipment(each_shipment,
line_item.variant,
quantity,
line_item.restock_item)
end
end
end
@@ -83,7 +86,7 @@ module Spree
quantity
end
def remove_from_shipment(shipment, variant, quantity)
def remove_from_shipment(shipment, variant, quantity, restock_item)
return 0 if quantity == 0 || shipment.shipped?
shipment_units = shipment.inventory_units_for(variant).reject do |variant_unit|
@@ -101,7 +104,7 @@ module Spree
shipment.destroy if shipment.inventory_units.reload.count == 0
# removing this from shipment, and adding to stock_location
if order.completed?
if order.completed? && restock_item
shipment.stock_location.restock variant, removed_quantity, shipment
end

View File

@@ -183,9 +183,11 @@ module Spree
def validate_source
if source && !skip_source_validation && !source.valid?
source.errors.each do |field, error|
field_name = I18n.t("activerecord.attributes.#{source.class.to_s.underscore}.#{field}")
errors.add(Spree.t(source.class.to_s.demodulize.underscore), "#{field_name} #{error}")
source.errors.each do |error|
field_name =
I18n.t("activerecord.attributes.#{source.class.to_s.underscore}.#{error.attribute}")
errors.add(Spree.t(source.class.to_s.demodulize.underscore),
"#{field_name} #{error.message}")
end
end
errors.blank?

View File

@@ -1,49 +0,0 @@
# frozen_string_literal: true
module Spree
module Preferences
class FileConfiguration < Configuration
def self.preference(name, type, *args)
if type == :file
super "#{name}_file_name", :string, *args
super "#{name}_content_type", :string, *args
super "#{name}_file_size", :integer, *args
super "#{name}_updated_at", :string, *args
else
super name, type, *args
end
end
def get_preference(key)
if !has_preference?(key) && has_attachment?(key)
public_send key
else
super key
end
end
alias :[] :get_preference
def preference_type(name)
if has_attachment? name
:file
else
super name
end
end
# Spree's Configuration responds to preference methods via method_missing, but doesn't
# override respond_to?, which consequently reports those methods as unavailable. Paperclip
# errors if respond_to? isn't correct, so we override it here.
def respond_to?(method, include_all = false)
name = method.to_s.delete('=')
super(self.class.preference_getter_method(name), include_all) || super(method, include_all)
end
def has_attachment?(name)
self.class.respond_to?(:attachment_definitions) &&
self.class.attachment_definitions.key?(name.to_sym)
end
end
end
end

View File

@@ -78,8 +78,7 @@ module Spree
where(producer_properties: { property_id: property_ids }).
or(
where(spree_product_properties: { property_id: property_ids })
).
distinct
)
}
delegate_belongs_to :master, :sku, :price, :currency, :display_amount, :display_price, :weight,

View File

@@ -192,7 +192,7 @@ module Spree
end
def after_cancel
manifest.each { |item| manifest_restock(item) }
manifest.each { |item| manifest_restock(item) } if order.restock_items
end
def after_resume

View File

@@ -2,8 +2,6 @@
module Spree
class Taxon < ApplicationRecord
include Spree::Core::S3Support
acts_as_nested_set dependent: :destroy
belongs_to :taxonomy, class_name: 'Spree::Taxonomy', touch: true
@@ -14,15 +12,6 @@ module Spree
validates :name, presence: true
has_attached_file :icon,
styles: { mini: '32x32>', normal: '128x128>' },
default_style: :mini,
url: '/spree/taxons/:id/:style/:basename.:extension',
path: ':rails_root/public/spree/taxons/:id/:style/:basename.:extension',
default_url: '/assets/default_taxon.png'
supports_s3 :icon
# Indicate which filters should be used for this taxon
def applicable_filters
[]

View File

@@ -9,6 +9,7 @@ class SubscriptionLineItem < ApplicationRecord
validates :quantity, presence: true, numericality: { only_integer: true }
default_scope { order('id ASC') }
scope :nil_price_estimate, -> { where(price_estimate: nil) }
def total_estimate
(price_estimate || 0) * (quantity || 0)

View File

@@ -1,9 +1,9 @@
# frozen_string_literal: true
class TermsOfServiceFile < ApplicationRecord
has_attached_file :attachment
has_one_attached :attachment
validates :attachment, presence: true
validates :attachment, attached: true
# The most recently uploaded file is the current one.
def self.current
@@ -11,7 +11,11 @@ class TermsOfServiceFile < ApplicationRecord
end
def self.current_url
current&.attachment&.url || Spree::Config.footer_tos_url
if current
Rails.application.routes.url_helpers.url_for(current.attachment)
else
Spree::Config.footer_tos_url
end
end
# If no file has been uploaded, we don't know when the old terms have

View File

@@ -12,7 +12,9 @@ module Api
:preferred_shopfront_product_sorting_method, :owner, :contact, :users, :tag_groups,
:default_tag_group, :require_login, :allow_guest_orders, :allow_order_changes,
:logo, :promo_image, :terms_and_conditions,
:terms_and_conditions_file_name, :terms_and_conditions_updated_at
:terms_and_conditions_file_name, :terms_and_conditions_updated_at,
:preferred_invoice_order_by_supplier, :preferred_product_low_stock_display,
:visible
has_one :owner, serializer: Api::Admin::UserSerializer
has_many :users, serializer: Api::Admin::UserSerializer
@@ -20,21 +22,26 @@ module Api
has_one :business_address, serializer: Api::AddressSerializer
def logo
attachment_urls(object.logo, [:thumb, :small, :medium])
attachment_urls(object.logo, Enterprise::LOGO_SIZES)
end
def promo_image
attachment_urls(object.promo_image, [:thumb, :medium, :large])
attachment_urls(object.promo_image, Enterprise::PROMO_IMAGE_SIZES)
end
def terms_and_conditions
return unless object.terms_and_conditions.file?
return unless object.terms_and_conditions.attached?
object.terms_and_conditions.url
Rails.application.routes.url_helpers.
url_for(object.terms_and_conditions)
end
def terms_and_conditions_file_name
object.terms_and_conditions_blob&.filename
end
def terms_and_conditions_updated_at
object.terms_and_conditions_updated_at&.to_s
object.terms_and_conditions_blob&.created_at&.to_s
end
def tag_groups
@@ -74,19 +81,19 @@ module Api
# Returns a hash of URLs for specified versions of an attachment.
#
# Example:
# Example result:
#
# attachment_urls(object.logo, [:thumb, :small, :medium])
# # {
# # thumb: LOGO_THUMB_URL,
# # small: LOGO_SMALL_URL,
# # medium: LOGO_MEDIUM_URL
# # }
def attachment_urls(attachment, versions)
return unless attachment.file?
# {
# thumb: LOGO_THUMB_URL,
# small: LOGO_SMALL_URL,
# medium: LOGO_MEDIUM_URL
# }
def attachment_urls(attachment, styles)
return unless attachment.variable?
versions.each_with_object({}) do |version, urls|
urls[version] = attachment.url(version)
styles.transform_values do |transformation|
Rails.application.routes.url_helpers.
url_for(attachment.variant(transformation))
end
end
end

View File

@@ -11,7 +11,7 @@ module Api
end
def image_url
object.images.present? ? object.images.first.attachment.url(:mini) : nil
object.images.first&.url(:mini)
end
def master_id

View File

@@ -7,7 +7,7 @@ module Api
:edit_path, :state, :payment_state, :shipment_state,
:payments_path, :ready_to_ship, :ready_to_capture, :created_at,
:distributor_name, :special_instructions, :display_outstanding_balance,
:item_total, :adjustment_total, :payment_total, :total
:item_total, :adjustment_total, :payment_total, :total, :item_count
has_one :distributor, serializer: Api::Admin::IdSerializer
has_one :order_cycle, serializer: Api::Admin::IdSerializer
@@ -69,6 +69,10 @@ module Api
object.completed_at.blank? ? "" : I18n.l(object.completed_at, format: '%B %d, %Y')
end
def item_count
object.line_items.count
end
private
def spree_routes_helper

View File

@@ -13,19 +13,11 @@ module Api
has_one :master, serializer: Api::Admin::VariantSerializer
def image_url
if object.images.present?
object.images.first.attachment.url(:product)
else
"/noimage/product.png"
end
object.images.first&.url(:product) || "/noimage/product.png"
end
def thumb_url
if object.images.present?
object.images.first.attachment.url(:mini)
else
"/noimage/mini.png"
end
object.images.first&.url(:mini) || "/noimage/mini.png"
end
def on_hand

View File

@@ -33,9 +33,7 @@ module Api
end
def image
return if object.product.images.empty?
object.product.images.first.mini_url
object.product.images.first&.url(:mini)
end
def in_stock

View File

@@ -44,11 +44,11 @@ module Api
end
def logo
enterprise.logo(:medium) if enterprise.logo?
enterprise.logo_url(:medium)
end
def promo_image
enterprise.promo_image(:large) if enterprise.promo_image?
enterprise.promo_image_url(:large)
end
def path

View File

@@ -9,7 +9,7 @@ module Api
:instagram, :linkedin, :twitter, :facebook, :is_primary_producer, :is_distributor,
:phone, :visible, :email_address, :hash, :logo, :promo_image, :path, :category,
:active, :producers, :orders_close_at, :hubs, :taxons, :supplied_taxons, :pickup,
:delivery
:delivery, :preferred_product_low_stock_display
has_one :address, serializer: Api::AddressSerializer
has_many :supplied_properties, serializer: Api::PropertySerializer
@@ -41,11 +41,11 @@ module Api
end
def logo
enterprise.logo(:medium) if enterprise.logo?
enterprise.logo_url(:medium)
end
def promo_image
enterprise.promo_image(:large) if enterprise.promo_image?
enterprise.promo_image_url(:large)
end
def path

View File

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

View File

@@ -10,7 +10,7 @@ module Api
has_many :payments, serializer: Api::PaymentSerializer
attributes :adjustments
attributes :adjustments, :customer_id
def adjustments
adjustments = object.all_adjustments.where(

View File

@@ -9,7 +9,7 @@ module Api
end
def logo
object.logo(:small) if object.logo?
object.logo_url(:small)
end
end
end

View File

@@ -0,0 +1,18 @@
# frozen_string_literal: true
module Api
module V1
class AddressSerializer < BaseSerializer
attributes :phone, :latitude, :longitude
attribute :first_name, &:firstname
attribute :last_name, &:lastname
attribute :street_address_1, &:address1
attribute :street_address_2, &:address2
attribute :postal_code, &:zipcode
attribute :locality, &:city
attribute :region, &:state_name
attribute :country, ->(object, _) { object.country.name }
end
end
end

View File

@@ -0,0 +1,13 @@
# frozen_string_literal: true
module Api
module V1
class BaseSerializer
include JSONAPI::Serializer
def self.url_helpers
Rails.application.routes.url_helpers
end
end
end
end

View File

@@ -0,0 +1,30 @@
# frozen_string_literal: true
module Api
module V1
class CustomerSerializer < BaseSerializer
attributes :id, :enterprise_id, :first_name, :last_name, :code, :email,
:allow_charges, :terms_and_conditions_accepted_at
attribute :tags, &:tag_list
attribute :billing_address do |object|
address(object.billing_address)
end
attribute :shipping_address do |object|
address(object.shipping_address)
end
belongs_to :enterprise, links: {
related: ->(object) {
url_helpers.api_v1_enterprise_url(id: object.enterprise_id)
}
}
def self.address(record)
AddressSerializer.new(record).serializable_hash.dig(:data, :attributes)
end
end
end
end

View File

@@ -0,0 +1,15 @@
# frozen_string_literal: true
module Api
module V1
class EnterpriseSerializer < BaseSerializer
attributes :id, :name
has_many :customers, links: {
related: ->(object) {
url_helpers.api_v1_enterprise_customers_url(enterprise_id: object.id)
}
}
end
end
end

View File

@@ -35,11 +35,7 @@ class Api::VariantSerializer < ActiveModel::Serializer
end
def thumb_url
if object.product.images.present?
object.product.images.first.attachment.url(:mini)
else
"/noimage/mini.png"
end
object.product.images.first&.url(:mini) || "/noimage/mini.png"
end
def unit_price_price

View File

@@ -2,21 +2,12 @@
class ImageImporter
def import(url, product)
attach(download(url), product)
end
valid_url = URI.parse(url)
file = open(valid_url.to_s)
filename = File.basename(valid_url.path)
private
def download(url)
local_file = Tempfile.new
remote_file = open(url)
IO.copy_stream(remote_file, local_file)
local_file
end
def attach(file, product)
Spree::Image.create(
attachment: file,
attachment: { io: file, filename: filename },
viewable_id: product.master.id,
viewable_type: Spree::Variant,
)

View File

@@ -33,6 +33,8 @@ module PermittedAttributes
:preferred_shopfront_closed_message, :preferred_shopfront_taxon_order,
:preferred_shopfront_producer_order, :preferred_shopfront_order_cycle_order,
:show_customer_names_to_suppliers, :preferred_shopfront_product_sorting_method,
:preferred_invoice_order_by_supplier,
:preferred_product_low_stock_display
]
end
end

View File

@@ -5,7 +5,7 @@ class TermsOfService
return false unless accepted_at = customer&.terms_and_conditions_accepted_at
accepted_at > if distributor
distributor.terms_and_conditions_updated_at
distributor.terms_and_conditions_blob.created_at
else
TermsOfServiceFile.updated_at
end
@@ -20,6 +20,6 @@ class TermsOfService
end
def self.distributor_terms_required?(distributor)
distributor.terms_and_conditions.file?
distributor.terms_and_conditions.attached?
end
end

View File

@@ -38,8 +38,13 @@
# post.valid? # => false
# post.errors[:published_at] # => ["must be valid"]
class DateTimeStringValidator < ActiveModel::EachValidator
NOT_STRING_ERROR = I18n.t("validators.date_time_string_validator.not_string_error")
INVALID_FORMAT_ERROR = I18n.t("validators.date_time_string_validator.invalid_format_error")
def self.not_string_error
I18n.t("validators.date_time_string_validator.not_string_error")
end
def self.invalid_format_error
I18n.t("validators.date_time_string_validator.invalid_format_error")
end
def validate_each(record, attribute, value)
return if value.nil? || value == ""
@@ -53,13 +58,13 @@ class DateTimeStringValidator < ActiveModel::EachValidator
def validate_attribute_is_string(record, attribute, value)
return if value.is_a?(String)
record.errors.add(attribute, NOT_STRING_ERROR)
record.errors.add(attribute, DateTimeStringValidator.not_string_error)
end
def validate_attribute_is_datetime_string(record, attribute, value)
return unless value.is_a?(String)
datetime = Time.zone.parse(value)
record.errors.add(attribute, INVALID_FORMAT_ERROR) if datetime.blank?
record.errors.add(attribute, DateTimeStringValidator.invalid_format_error) if datetime.blank?
end
end

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