mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-05 02:41:33 +00:00
Compare commits
271 Commits
v4.3.11
...
v4.4.0-mas
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd889133cb | ||
|
|
4ac3dda398 | ||
|
|
9d5d269f1f | ||
|
|
f4405775f6 | ||
|
|
3a38361857 | ||
|
|
68b59ab7a6 | ||
|
|
a56541216e | ||
|
|
05d9646f3e | ||
|
|
b1de64bf3e | ||
|
|
e976cc6d95 | ||
|
|
9a89b22364 | ||
|
|
1b304e2aa4 | ||
|
|
48cdca59fd | ||
|
|
9095abfed2 | ||
|
|
aa9fd682d8 | ||
|
|
5b73ccb213 | ||
|
|
dda3cfa58d | ||
|
|
9da649a296 | ||
|
|
2e53b9a0c6 | ||
|
|
527e305e2f | ||
|
|
89b59f97ee | ||
|
|
26d3cffba3 | ||
|
|
86703bb545 | ||
|
|
8e99f496ff | ||
|
|
2f2506e698 | ||
|
|
7ef9c2f56a | ||
|
|
ee4402f751 | ||
|
|
79a2d1228d | ||
|
|
da3202460c | ||
|
|
75ccc5c72f | ||
|
|
aca72e6071 | ||
|
|
2453084a6b | ||
|
|
39183547aa | ||
|
|
24000b2ce3 | ||
|
|
8e86f76278 | ||
|
|
4a91c180a3 | ||
|
|
d192024786 | ||
|
|
ec7de516aa | ||
|
|
47745b5e49 | ||
|
|
3301c7cabc | ||
|
|
35d9837f24 | ||
|
|
436deb9797 | ||
|
|
57451f2639 | ||
|
|
d56ad66ab8 | ||
|
|
fc5a53ebd9 | ||
|
|
f27472106e | ||
|
|
5729e33f69 | ||
|
|
584f6297f5 | ||
|
|
12bf17e21e | ||
|
|
7068df5d4b | ||
|
|
7a10edff82 | ||
|
|
5c0db892e5 | ||
|
|
598f69f42f | ||
|
|
ca5de6b0b2 | ||
|
|
b0c9c6e6e1 | ||
|
|
701fef84f3 | ||
|
|
cf3692e688 | ||
|
|
863fed56ce | ||
|
|
e6d42a0c4f | ||
|
|
64508d3c3d | ||
|
|
395cf7fb8d | ||
|
|
5ad37ce6a5 | ||
|
|
6e9721b64c | ||
|
|
4c7e947738 | ||
|
|
b510668ecf | ||
|
|
6f12d012ed | ||
|
|
551d0d3a93 | ||
|
|
a898915724 | ||
|
|
e54cff2274 | ||
|
|
91d0dabc1d | ||
|
|
bd11475fe1 | ||
|
|
ed231ec512 | ||
|
|
fc00a48d67 | ||
|
|
c02c90317f | ||
|
|
2d4cfd7548 | ||
|
|
d88781a083 | ||
|
|
989a88e252 | ||
|
|
9c42781ff1 | ||
|
|
73b2d37224 | ||
|
|
2654d3b866 | ||
|
|
5fa81d1333 | ||
|
|
4e7fab6914 | ||
|
|
8d633234f4 | ||
|
|
d5a625bdeb | ||
|
|
0e289a23c1 | ||
|
|
5487aa19fc | ||
|
|
345f540723 | ||
|
|
78617905c6 | ||
|
|
56204b2315 | ||
|
|
905187f3ce | ||
|
|
7e84579aa3 | ||
|
|
bd0e7cdfc8 | ||
|
|
907c65d98c | ||
|
|
c2aaf88e98 | ||
|
|
fc0cca2210 | ||
|
|
c379dcacc5 | ||
|
|
64e6d639c1 | ||
|
|
374904f473 | ||
|
|
fb7ae9fd58 | ||
|
|
19bd05ce5a | ||
|
|
f9abec4346 | ||
|
|
3e7ad17f69 | ||
|
|
b813879330 | ||
|
|
12bb8db7b3 | ||
|
|
c3846ad269 | ||
|
|
93c3241bb5 | ||
|
|
abd55b2104 | ||
|
|
47df9493ae | ||
|
|
694e46d1fb | ||
|
|
4564021f79 | ||
|
|
b85cf26907 | ||
|
|
02432ee2ec | ||
|
|
520ced350e | ||
|
|
e41d1f2205 | ||
|
|
c5ce49e08c | ||
|
|
e4c65ea87d | ||
|
|
f007cf3dad | ||
|
|
edcdcd3f74 | ||
|
|
16534319b6 | ||
|
|
d85ea628e2 | ||
|
|
821446e150 | ||
|
|
744f95809a | ||
|
|
fb17a679c0 | ||
|
|
2ae91bdbe2 | ||
|
|
3967f54533 | ||
|
|
6bd66585a9 | ||
|
|
11f84b5276 | ||
|
|
23239bad8b | ||
|
|
a207a445b1 | ||
|
|
16256ee114 | ||
|
|
15e9c4eb37 | ||
|
|
3e3ae5d8ae | ||
|
|
48c107bde1 | ||
|
|
80dd8755b0 | ||
|
|
791518988d | ||
|
|
149ec5511c | ||
|
|
351343fb6c | ||
|
|
6145413b1a | ||
|
|
d87e40bb69 | ||
|
|
d6859e0bf7 | ||
|
|
1f2f5e2eec | ||
|
|
b53aba3844 | ||
|
|
45dcdf1611 | ||
|
|
8c971f2efa | ||
|
|
8a8200a039 | ||
|
|
8a376e782a | ||
|
|
6ab1bfb2ab | ||
|
|
c2305615a6 | ||
|
|
ff0f81167a | ||
|
|
41b3ddae08 | ||
|
|
fc09f95fa1 | ||
|
|
13037d2d9d | ||
|
|
9125c730ed | ||
|
|
70170078d1 | ||
|
|
bd505bbee7 | ||
|
|
24200de8dd | ||
|
|
d0f4c44add | ||
|
|
5cde4de512 | ||
|
|
502b5e8664 | ||
|
|
35fef9e7ac | ||
|
|
24913476ac | ||
|
|
515a9a9b1c | ||
|
|
a65b43d32f | ||
|
|
9a8551e3ea | ||
|
|
a35a07b441 | ||
|
|
449430cabc | ||
|
|
252697b782 | ||
|
|
74fd1814e4 | ||
|
|
6803e0a8f9 | ||
|
|
71e4d2c6ed | ||
|
|
00e171a8f1 | ||
|
|
5d43285834 | ||
|
|
ca03e1596b | ||
|
|
c12415a340 | ||
|
|
f4261b85b8 | ||
|
|
7974e1eaa6 | ||
|
|
457d5a6c83 | ||
|
|
05104841cd | ||
|
|
d1d050e6a4 | ||
|
|
e2ba18f828 | ||
|
|
d6cb483f0d | ||
|
|
d7f7ff7436 | ||
|
|
905220a055 | ||
|
|
b865d8c1c0 | ||
|
|
51f47fc351 | ||
|
|
1b4236640d | ||
|
|
2057449dac | ||
|
|
ba98039e95 | ||
|
|
d51786ac9e | ||
|
|
ccd7466ede | ||
|
|
b163d4a584 | ||
|
|
a4d3011e27 | ||
|
|
dd48092728 | ||
|
|
5ee3550ebd | ||
|
|
eab46b67e3 | ||
|
|
e34f4a9971 | ||
|
|
dde775d2b7 | ||
|
|
3432e30465 | ||
|
|
12aa4f9970 | ||
|
|
b04879604a | ||
|
|
4ecbbae55e | ||
|
|
7cf68cd33b | ||
|
|
241b307762 | ||
|
|
7d26158e06 | ||
|
|
99fbf80b4c | ||
|
|
98f78927b7 | ||
|
|
bf051fc35b | ||
|
|
760bf269ca | ||
|
|
bed2fe69f6 | ||
|
|
c6b5eda85c | ||
|
|
b091a0ed1a | ||
|
|
fbf55cf7bd | ||
|
|
3ce48848f0 | ||
|
|
548a6f8d2e | ||
|
|
10c52959ad | ||
|
|
08dc3e3cbe | ||
|
|
fbf5862c66 | ||
|
|
01dcf068f9 | ||
|
|
b58b555e38 | ||
|
|
983353e078 | ||
|
|
968bf882c4 | ||
|
|
daf243996b | ||
|
|
7a7ab17db4 | ||
|
|
6daf29400f | ||
|
|
f3ee10dd5a | ||
|
|
cf0f148dba | ||
|
|
bb73d70e57 | ||
|
|
24343c769e | ||
|
|
2d28a57c6f | ||
|
|
1c9a09d88d | ||
|
|
1ebacf96ad | ||
|
|
acc34d1deb | ||
|
|
e1b37090be | ||
|
|
6e8ed1f612 | ||
|
|
c7bb24e2a0 | ||
|
|
e88843c733 | ||
|
|
67c3e09dba | ||
|
|
1b6147db30 | ||
|
|
2bfb57a1a1 | ||
|
|
8813edaed8 | ||
|
|
7dc8c4b891 | ||
|
|
a8b85a65e9 | ||
|
|
5c3e07db52 | ||
|
|
10ca09eaef | ||
|
|
daaeca88e8 | ||
|
|
77554e21fc | ||
|
|
7c72969792 | ||
|
|
a62e51c0d0 | ||
|
|
1a7d70772a | ||
|
|
3dd4e7ef03 | ||
|
|
8a27dd84fe | ||
|
|
05a715a43a | ||
|
|
17b10d10c0 | ||
|
|
10dbeb32b2 | ||
|
|
b3bd112cdb | ||
|
|
93cf562d59 | ||
|
|
5938577bd1 | ||
|
|
1594d1c718 | ||
|
|
abe63e5b04 | ||
|
|
40111910b6 | ||
|
|
4edb159ef8 | ||
|
|
ccb183d60b | ||
|
|
a785b4d5e0 | ||
|
|
16fba20686 | ||
|
|
1cbb45a618 | ||
|
|
38bd31d0e3 | ||
|
|
750b6b284d | ||
|
|
78338864d8 | ||
|
|
880ba85791 | ||
|
|
ced8f8aa58 | ||
|
|
2e0191e603 |
49
.github/workflows/stage.yml
vendored
Normal file
49
.github/workflows/stage.yml
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
name: "Deploy to Staging"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [labeled]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
server:
|
||||
description: "Staging Server"
|
||||
type: choice
|
||||
required: true
|
||||
options:
|
||||
- staging.openfoodnetwork.org.uk
|
||||
- staging.openfoodnetwork.org.au
|
||||
- staging.coopcircuits.fr
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
deploy_pr:
|
||||
if: contains(fromJSON('["pr-staged-uk", "pr-staged-au", "pr-staged-fr"]'), github.event.label.name)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Configure deployment key
|
||||
run: |
|
||||
install -m 600 -D /dev/null ~/.ssh/id_rsa
|
||||
echo "${{ secrets.DEPLOYMENT_KEY }}" > ~/.ssh/id_rsa
|
||||
echo "${{ secrets.DEPLOYMENT_HOSTS }}" > ~/.ssh/known_hosts
|
||||
|
||||
- name: Deploy to Staging
|
||||
env:
|
||||
LABEL: ${{ github.event.label.name }}
|
||||
run: |
|
||||
ssh ofn-deploy@${{ github.event.label.description }} -o LogLevel=ERROR "pull-request-${{ github.event.pull_request.number }} ."
|
||||
|
||||
deploy_branch:
|
||||
if: ${{ inputs.server }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Configure deployment key
|
||||
run: |
|
||||
install -m 600 -D /dev/null ~/.ssh/id_rsa
|
||||
echo "${{ secrets.DEPLOYMENT_KEY }}" > ~/.ssh/id_rsa
|
||||
echo "${{ secrets.DEPLOYMENT_HOSTS }}" > ~/.ssh/known_hosts
|
||||
|
||||
- name: Deploy to Staging
|
||||
run: |
|
||||
ssh ofn-deploy@${{ inputs.server }} -o LogLevel=ERROR "$GITHUB_REF_NAME $GITHUB_SHA"
|
||||
@@ -1,4 +1,4 @@
|
||||
# Basically, ignore everythings expect app/webpacker/controllers/*.js and app/webpacker/packs/*.js
|
||||
# Ignore a lot of things, but we should enable where it can be helpful.
|
||||
|
||||
*.md
|
||||
*.yml
|
||||
@@ -6,13 +6,21 @@
|
||||
*.json
|
||||
*.html
|
||||
|
||||
# JS
|
||||
# Enabled: app/webpacker/controllers/*.js and app/webpacker/packs/*.js
|
||||
babel.config.js
|
||||
postcss.config.js
|
||||
|
||||
# SCSS
|
||||
# Enabled: most of admin
|
||||
/app/webpacker/css/admin/globals/
|
||||
/app/webpacker/css/admin/shared/
|
||||
/app/webpacker/css/admin_v3/globals/variables.scss
|
||||
/app/webpacker/css/darkswarm/
|
||||
/app/webpacker/css/mail/
|
||||
/app/webpacker/css/shared/
|
||||
|
||||
# More
|
||||
/app/assets/
|
||||
/config/
|
||||
/coverage/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit 1400 --no-auto-gen-timestamp`
|
||||
# using RuboCop version 1.51.0.
|
||||
# using RuboCop version 1.52.0.
|
||||
# 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
|
||||
@@ -16,7 +16,7 @@ Gemspec/RequiredRubyVersion:
|
||||
- 'engines/order_management/order_management.gemspec'
|
||||
- 'engines/web/web.gemspec'
|
||||
|
||||
# Offense count: 28
|
||||
# Offense count: 31
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: EnforcedStyle, IndentationWidth.
|
||||
# SupportedStyles: with_first_argument, with_fixed_indentation
|
||||
@@ -62,11 +62,10 @@ Layout/BlockEndNewline:
|
||||
- 'spec/lib/open_food_network/enterprise_fee_calculator_spec.rb'
|
||||
- 'spec/system/admin/orders_spec.rb'
|
||||
|
||||
# Offense count: 3
|
||||
# Offense count: 2
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
Layout/ClosingParenthesisIndentation:
|
||||
Exclude:
|
||||
- 'lib/reporting/queries/joins.rb'
|
||||
- 'spec/system/admin/orders_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
@@ -141,7 +140,7 @@ Layout/LeadingCommentSpace:
|
||||
Exclude:
|
||||
- 'spec/system/admin/enterprises_spec.rb'
|
||||
|
||||
# Offense count: 115
|
||||
# Offense count: 114
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: space, no_space
|
||||
@@ -198,7 +197,7 @@ Layout/LineEndStringConcatenationIndentation:
|
||||
- 'spec/system/consumer/cookies_spec.rb'
|
||||
- 'spec/system/consumer/shopping/cart_spec.rb'
|
||||
|
||||
# Offense count: 643
|
||||
# Offense count: 606
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: Max, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns.
|
||||
# URISchemes: http, https
|
||||
@@ -206,28 +205,20 @@ Layout/LineLength:
|
||||
Exclude:
|
||||
- 'app/components/confirm_modal_component.rb'
|
||||
- 'app/controllers/admin/bulk_line_items_controller.rb'
|
||||
- 'app/controllers/admin/enterprise_fees_controller.rb'
|
||||
- 'app/controllers/admin/enterprise_relationships_controller.rb'
|
||||
- 'app/controllers/admin/enterprises_controller.rb'
|
||||
- 'app/controllers/admin/product_import_controller.rb'
|
||||
- 'app/controllers/admin/schedules_controller.rb'
|
||||
- 'app/controllers/admin/subscriptions_controller.rb'
|
||||
- 'app/controllers/api/v0/order_cycles_controller.rb'
|
||||
- 'app/controllers/payment_gateways/paypal_controller.rb'
|
||||
- 'app/helpers/angular_form_builder.rb'
|
||||
- 'app/helpers/angular_form_helper.rb'
|
||||
- 'app/helpers/enterprises_helper.rb'
|
||||
- 'app/helpers/order_cycles_helper.rb'
|
||||
- 'app/helpers/spree/orders_helper.rb'
|
||||
- 'app/jobs/subscription_confirm_job.rb'
|
||||
- 'app/mailers/subscription_mailer.rb'
|
||||
- 'app/models/column_preference.rb'
|
||||
- 'app/models/concerns/order_shipment.rb'
|
||||
- 'app/models/concerns/product_stock.rb'
|
||||
- 'app/models/concerns/variant_stock.rb'
|
||||
- 'app/models/customer.rb'
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/product_import/entry_processor.rb'
|
||||
- 'app/models/product_import/spreadsheet_entry.rb'
|
||||
- 'app/models/product_import/unit_converter.rb'
|
||||
- 'app/models/proxy_order.rb'
|
||||
@@ -236,17 +227,13 @@ Layout/LineLength:
|
||||
- 'app/models/spree/gateway/stripe_sca.rb'
|
||||
- 'app/models/spree/line_item.rb'
|
||||
- 'app/models/spree/order.rb'
|
||||
- 'app/models/spree/payment_method.rb'
|
||||
- 'app/models/spree/preferences/store.rb'
|
||||
- 'app/models/subscription.rb'
|
||||
- 'app/models/variant_override.rb'
|
||||
- 'app/serializers/api/admin/subscription_line_item_serializer.rb'
|
||||
- 'app/services/cart_service.rb'
|
||||
- 'app/services/checkout/post_checkout_actions.rb'
|
||||
- 'app/services/embedded_page_service.rb'
|
||||
- 'app/services/order_cycle_form.rb'
|
||||
- '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/subscriptions/validator.rb'
|
||||
- 'engines/order_management/spec/services/order_management/order/updater_spec.rb'
|
||||
@@ -260,7 +247,6 @@ Layout/LineLength:
|
||||
- 'lib/open_food_network/scope_variants_for_search.rb'
|
||||
- 'lib/reporting/line_items.rb'
|
||||
- 'lib/reporting/reports/enterprise_fee_summary/report_data/enterprise_fee_type_total.rb'
|
||||
- 'lib/reporting/reports/xero_invoices/base.rb'
|
||||
- 'lib/spree/localized_number.rb'
|
||||
- 'lib/tasks/data.rake'
|
||||
- 'lib/tasks/enterprises.rake'
|
||||
@@ -362,7 +348,6 @@ Layout/LineLength:
|
||||
- 'spec/support/cancan_helper.rb'
|
||||
- 'spec/support/features/datepicker_helper.rb'
|
||||
- 'spec/support/matchers/select2_matchers.rb'
|
||||
- 'spec/support/matchers/table_matchers.rb'
|
||||
- 'spec/support/request/web_helper.rb'
|
||||
- 'spec/system/admin/adjustments_spec.rb'
|
||||
- 'spec/system/admin/bulk_order_management_spec.rb'
|
||||
@@ -376,13 +361,12 @@ Layout/MultilineBlockLayout:
|
||||
Exclude:
|
||||
- 'engines/order_management/app/services/order_management/subscriptions/validator.rb'
|
||||
|
||||
# Offense count: 7
|
||||
# Offense count: 6
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: symmetrical, new_line, same_line
|
||||
Layout/MultilineMethodCallBraceLayout:
|
||||
Exclude:
|
||||
- 'lib/reporting/queries/joins.rb'
|
||||
- 'spec/system/admin/orders_spec.rb'
|
||||
- 'spec/system/admin/products_spec.rb'
|
||||
|
||||
@@ -414,7 +398,7 @@ Layout/TrailingEmptyLines:
|
||||
Exclude:
|
||||
- 'Rakefile'
|
||||
|
||||
# Offense count: 73
|
||||
# Offense count: 76
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: AllowInHeredoc.
|
||||
Layout/TrailingWhitespace:
|
||||
@@ -550,13 +534,17 @@ Lint/RedundantDirGlobSort:
|
||||
- 'spec/base_spec_helper.rb'
|
||||
- 'spec/system_helper.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Offense count: 6
|
||||
# This cop supports unsafe autocorrection (--autocorrect-all).
|
||||
# Configuration parameters: AllowedMethods.
|
||||
# AllowedMethods: instance_of?, kind_of?, is_a?, eql?, respond_to?, equal?
|
||||
Lint/RedundantSafeNavigation:
|
||||
Exclude:
|
||||
- 'app/models/report_blob.rb'
|
||||
- 'app/models/spree/payment.rb'
|
||||
- 'app/serializers/api/admin/subscription_line_item_serializer.rb'
|
||||
- 'lib/open_food_network/address_finder.rb'
|
||||
- 'lib/tasks/missing_payments.rake'
|
||||
|
||||
# Offense count: 2
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
@@ -640,11 +628,16 @@ Metrics/BlockLength:
|
||||
- 'spec/factories/user_factory.rb'
|
||||
- 'spec/factories/variant_factory.rb'
|
||||
- 'spec/requests/api/orders_spec.rb'
|
||||
- 'spec/requests/checkout/failed_checkout_spec.rb'
|
||||
- 'spec/requests/checkout/stripe_sca_spec.rb'
|
||||
- 'spec/support/cancan_helper.rb'
|
||||
- 'spec/support/matchers/select2_matchers.rb'
|
||||
- 'spec/support/matchers/table_matchers.rb'
|
||||
- 'spec/swagger_helper.rb'
|
||||
- 'spec/system/consumer/shopping/checkout_spec.rb'
|
||||
- 'spec/system/consumer/shopping/checkout_stripe_spec.rb'
|
||||
- 'spec/system/consumer/shopping/variant_overrides_spec.rb'
|
||||
- 'spec/system/consumer/split_checkout_tax_not_incl_spec.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Configuration parameters: CountBlocks, Max.
|
||||
@@ -688,6 +681,7 @@ Metrics/ClassLength:
|
||||
- 'app/models/spree/payment.rb'
|
||||
- 'app/models/spree/product.rb'
|
||||
- 'app/models/spree/shipment.rb'
|
||||
- 'app/models/spree/shipping_method.rb'
|
||||
- 'app/models/spree/user.rb'
|
||||
- 'app/models/spree/variant.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
@@ -900,7 +894,7 @@ Rails/ActionOrder:
|
||||
- 'app/controllers/spree/admin/variants_controller.rb'
|
||||
- 'app/controllers/user_confirmations_controller.rb'
|
||||
|
||||
# Offense count: 15
|
||||
# Offense count: 13
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/models/**/*.rb
|
||||
@@ -910,7 +904,6 @@ Rails/ActiveRecordCallbacksOrder:
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/enterprise_group.rb'
|
||||
- 'app/models/enterprise_relationship.rb'
|
||||
- 'app/models/spree/line_item.rb'
|
||||
- 'app/models/spree/order.rb'
|
||||
- 'app/models/spree/payment.rb'
|
||||
- 'app/models/spree/product.rb'
|
||||
@@ -991,7 +984,7 @@ Rails/FilePath:
|
||||
- 'spec/models/content_configuration_spec.rb'
|
||||
- 'spec/support/downloads_helper.rb'
|
||||
|
||||
# Offense count: 11
|
||||
# Offense count: 8
|
||||
# Configuration parameters: Include.
|
||||
# Include: app/models/**/*.rb
|
||||
Rails/HasAndBelongsToMany:
|
||||
@@ -999,12 +992,9 @@ Rails/HasAndBelongsToMany:
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/enterprise_group.rb'
|
||||
- 'app/models/order_cycle.rb'
|
||||
- 'app/models/spree/line_item.rb'
|
||||
- 'app/models/spree/option_value.rb'
|
||||
- 'app/models/spree/role.rb'
|
||||
- 'app/models/spree/shipping_method.rb'
|
||||
- 'app/models/spree/user.rb'
|
||||
- 'app/models/spree/variant.rb'
|
||||
- 'app/models/spree/zone.rb'
|
||||
|
||||
# Offense count: 47
|
||||
@@ -1071,7 +1061,7 @@ Rails/I18nLocaleTexts:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/stripe_accounts_controller.rb'
|
||||
|
||||
# Offense count: 27
|
||||
# Offense count: 26
|
||||
# Configuration parameters: IgnoreScopes, Include.
|
||||
# Include: app/models/**/*.rb
|
||||
Rails/InverseOf:
|
||||
@@ -1081,7 +1071,6 @@ Rails/InverseOf:
|
||||
- 'app/models/spree/country.rb'
|
||||
- 'app/models/spree/inventory_unit.rb'
|
||||
- 'app/models/spree/line_item.rb'
|
||||
- 'app/models/spree/option_type.rb'
|
||||
- 'app/models/spree/order.rb'
|
||||
- 'app/models/spree/payment.rb'
|
||||
- 'app/models/spree/price.rb'
|
||||
@@ -1480,7 +1469,7 @@ Style/GlobalStdStream:
|
||||
- 'lib/tasks/subscriptions/debug.rake'
|
||||
- 'lib/tasks/subscriptions/test.rake'
|
||||
|
||||
# Offense count: 39
|
||||
# Offense count: 38
|
||||
# This cop supports safe autocorrection (--autocorrect).
|
||||
# Configuration parameters: MinBodyLength, AllowConsecutiveConditionals.
|
||||
Style/GuardClause:
|
||||
@@ -1499,7 +1488,6 @@ Style/GuardClause:
|
||||
- 'app/models/spree/order.rb'
|
||||
- 'app/models/spree/preferences/preferable_class_methods.rb'
|
||||
- 'app/services/order_syncer.rb'
|
||||
- 'app/services/variant_units/variant_and_line_item_naming.rb'
|
||||
- 'engines/order_management/app/services/order_management/order/updater.rb'
|
||||
- 'lib/discourse/single_sign_on.rb'
|
||||
- 'lib/open_food_network/order_cycle_form_applicator.rb'
|
||||
|
||||
2
Gemfile
2
Gemfile
@@ -119,8 +119,6 @@ gem 'test-unit', '~> 3.5'
|
||||
|
||||
gem 'coffee-rails', '~> 5.0.0'
|
||||
|
||||
gem 'mini_racer'
|
||||
|
||||
gem 'angular_rails_csrf'
|
||||
|
||||
gem 'jquery-rails', '4.4.0'
|
||||
|
||||
169
Gemfile.lock
169
Gemfile.lock
@@ -44,73 +44,73 @@ GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
Ascii85 (1.1.0)
|
||||
actioncable (7.0.4.3)
|
||||
actionpack (= 7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
actioncable (7.0.5)
|
||||
actionpack (= 7.0.5)
|
||||
activesupport (= 7.0.5)
|
||||
nio4r (~> 2.0)
|
||||
websocket-driver (>= 0.6.1)
|
||||
actionmailbox (7.0.4.3)
|
||||
actionpack (= 7.0.4.3)
|
||||
activejob (= 7.0.4.3)
|
||||
activerecord (= 7.0.4.3)
|
||||
activestorage (= 7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
actionmailbox (7.0.5)
|
||||
actionpack (= 7.0.5)
|
||||
activejob (= 7.0.5)
|
||||
activerecord (= 7.0.5)
|
||||
activestorage (= 7.0.5)
|
||||
activesupport (= 7.0.5)
|
||||
mail (>= 2.7.1)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
actionmailer (7.0.4.3)
|
||||
actionpack (= 7.0.4.3)
|
||||
actionview (= 7.0.4.3)
|
||||
activejob (= 7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
actionmailer (7.0.5)
|
||||
actionpack (= 7.0.5)
|
||||
actionview (= 7.0.5)
|
||||
activejob (= 7.0.5)
|
||||
activesupport (= 7.0.5)
|
||||
mail (~> 2.5, >= 2.5.4)
|
||||
net-imap
|
||||
net-pop
|
||||
net-smtp
|
||||
rails-dom-testing (~> 2.0)
|
||||
actionpack (7.0.4.3)
|
||||
actionview (= 7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
rack (~> 2.0, >= 2.2.0)
|
||||
actionpack (7.0.5)
|
||||
actionview (= 7.0.5)
|
||||
activesupport (= 7.0.5)
|
||||
rack (~> 2.0, >= 2.2.4)
|
||||
rack-test (>= 0.6.3)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||
actionpack-action_caching (1.2.2)
|
||||
actionpack (>= 4.0.0)
|
||||
actiontext (7.0.4.3)
|
||||
actionpack (= 7.0.4.3)
|
||||
activerecord (= 7.0.4.3)
|
||||
activestorage (= 7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
actiontext (7.0.5)
|
||||
actionpack (= 7.0.5)
|
||||
activerecord (= 7.0.5)
|
||||
activestorage (= 7.0.5)
|
||||
activesupport (= 7.0.5)
|
||||
globalid (>= 0.6.0)
|
||||
nokogiri (>= 1.8.5)
|
||||
actionview (7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
actionview (7.0.5)
|
||||
activesupport (= 7.0.5)
|
||||
builder (~> 3.1)
|
||||
erubi (~> 1.4)
|
||||
rails-dom-testing (~> 2.0)
|
||||
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||
active_model_serializers (0.8.4)
|
||||
activemodel (>= 3.0)
|
||||
active_storage_validations (1.0.3)
|
||||
active_storage_validations (1.0.4)
|
||||
activejob (>= 5.2.0)
|
||||
activemodel (>= 5.2.0)
|
||||
activestorage (>= 5.2.0)
|
||||
activesupport (>= 5.2.0)
|
||||
activejob (7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
activejob (7.0.5)
|
||||
activesupport (= 7.0.5)
|
||||
globalid (>= 0.3.6)
|
||||
activemerchant (1.123.0)
|
||||
activesupport (>= 4.2)
|
||||
builder (>= 2.1.2, < 4.0.0)
|
||||
i18n (>= 0.6.9)
|
||||
nokogiri (~> 1.4)
|
||||
activemodel (7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
activerecord (7.0.4.3)
|
||||
activemodel (= 7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
activemodel (7.0.5)
|
||||
activesupport (= 7.0.5)
|
||||
activerecord (7.0.5)
|
||||
activemodel (= 7.0.5)
|
||||
activesupport (= 7.0.5)
|
||||
activerecord-import (1.4.1)
|
||||
activerecord (>= 4.2)
|
||||
activerecord-postgresql-adapter (0.0.1)
|
||||
@@ -121,14 +121,14 @@ GEM
|
||||
multi_json (~> 1.11, >= 1.11.2)
|
||||
rack (>= 2.0.8, < 3)
|
||||
railties (>= 5.2.4.1)
|
||||
activestorage (7.0.4.3)
|
||||
actionpack (= 7.0.4.3)
|
||||
activejob (= 7.0.4.3)
|
||||
activerecord (= 7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
activestorage (7.0.5)
|
||||
actionpack (= 7.0.5)
|
||||
activejob (= 7.0.5)
|
||||
activerecord (= 7.0.5)
|
||||
activesupport (= 7.0.5)
|
||||
marcel (~> 1.0)
|
||||
mini_mime (>= 1.1.0)
|
||||
activesupport (7.0.4.3)
|
||||
activesupport (7.0.5)
|
||||
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||
i18n (>= 1.6, < 2)
|
||||
minitest (>= 5.1)
|
||||
@@ -157,17 +157,17 @@ GEM
|
||||
awesome_nested_set (3.5.0)
|
||||
activerecord (>= 4.0.0, < 7.1)
|
||||
aws-eventstream (1.2.0)
|
||||
aws-partitions (1.760.0)
|
||||
aws-sdk-core (3.171.1)
|
||||
aws-partitions (1.779.0)
|
||||
aws-sdk-core (3.174.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
aws-partitions (~> 1, >= 1.651.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
aws-sdk-kms (1.64.0)
|
||||
aws-sdk-core (~> 3, >= 3.165.0)
|
||||
aws-sdk-kms (1.66.0)
|
||||
aws-sdk-core (~> 3, >= 3.174.0)
|
||||
aws-sigv4 (~> 1.1)
|
||||
aws-sdk-s3 (1.122.0)
|
||||
aws-sdk-core (~> 3, >= 3.165.0)
|
||||
aws-sdk-s3 (1.124.0)
|
||||
aws-sdk-core (~> 3, >= 3.174.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.4)
|
||||
aws-sigv4 (1.5.2)
|
||||
@@ -191,7 +191,7 @@ GEM
|
||||
railties (>= 5.2)
|
||||
thread-local (>= 1.1.0)
|
||||
cancancan (1.15.0)
|
||||
capybara (3.39.1)
|
||||
capybara (3.39.2)
|
||||
addressable
|
||||
matrix
|
||||
mini_mime (>= 0.1.3)
|
||||
@@ -237,12 +237,12 @@ GEM
|
||||
datafoodconsortium-connector (1.0.0.pre.alpha.6)
|
||||
virtual_assembly-semantizer (~> 1.0, >= 1.0.4)
|
||||
date (3.3.3)
|
||||
ddtrace (1.11.1)
|
||||
debase-ruby_core_source (>= 0.10.16, <= 3.2.0)
|
||||
ddtrace (1.12.1)
|
||||
debase-ruby_core_source (= 3.2.1)
|
||||
libdatadog (~> 2.0.0.1.0)
|
||||
libddwaf (~> 1.8.2.0.0)
|
||||
libddwaf (~> 1.9.0.0.0)
|
||||
msgpack
|
||||
debase-ruby_core_source (3.2.0)
|
||||
debase-ruby_core_source (3.2.1)
|
||||
debug (1.8.0)
|
||||
irb (>= 1.5.0)
|
||||
reline (>= 0.3.1)
|
||||
@@ -276,7 +276,7 @@ GEM
|
||||
factory_bot_rails (6.2.0)
|
||||
factory_bot (~> 6.2.0)
|
||||
railties (>= 5.0.0)
|
||||
faraday (2.7.5)
|
||||
faraday (2.7.6)
|
||||
faraday-net_http (>= 2.0, < 3.1)
|
||||
ruby2_keywords (>= 0.0.4)
|
||||
faraday-follow_redirects (0.3.0)
|
||||
@@ -340,7 +340,7 @@ GEM
|
||||
hiredis (0.6.3)
|
||||
htmlentities (4.3.4)
|
||||
httpclient (2.8.3)
|
||||
i18n (1.13.0)
|
||||
i18n (1.14.1)
|
||||
concurrent-ruby (~> 1.0)
|
||||
i18n-js (3.9.2)
|
||||
i18n (>= 0.6.6)
|
||||
@@ -382,17 +382,16 @@ GEM
|
||||
rspec (>= 2.0, < 4.0)
|
||||
jsonapi-serializer (2.2.0)
|
||||
activesupport (>= 4.2)
|
||||
jwt (2.7.0)
|
||||
knapsack_pro (4.1.0)
|
||||
jwt (2.7.1)
|
||||
knapsack_pro (5.1.0)
|
||||
rake
|
||||
launchy (2.5.0)
|
||||
addressable (~> 2.7)
|
||||
letter_opener (1.8.1)
|
||||
launchy (>= 2.2, < 3)
|
||||
libdatadog (2.0.0.1.0)
|
||||
libddwaf (1.8.2.0.0)
|
||||
libddwaf (1.9.0.0.1)
|
||||
ffi (~> 1.0)
|
||||
libv8-node (16.10.0.0)
|
||||
link_header (0.0.8)
|
||||
listen (3.8.0)
|
||||
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||
@@ -417,14 +416,12 @@ GEM
|
||||
mini_magick (4.11.0)
|
||||
mini_mime (1.1.2)
|
||||
mini_portile2 (2.8.2)
|
||||
mini_racer (0.6.3)
|
||||
libv8-node (~> 16.10.0.0)
|
||||
minitest (5.18.0)
|
||||
monetize (1.12.0)
|
||||
money (~> 6.12)
|
||||
money (6.16.0)
|
||||
i18n (>= 0.6.4, <= 2)
|
||||
msgpack (1.7.0)
|
||||
msgpack (1.7.1)
|
||||
multi_json (1.15.0)
|
||||
multi_xml (0.6.0)
|
||||
net-imap (0.3.4)
|
||||
@@ -474,10 +471,11 @@ GEM
|
||||
activerecord (>= 5.2)
|
||||
request_store (~> 1.1)
|
||||
parallel (1.23.0)
|
||||
paranoia (2.6.1)
|
||||
paranoia (2.6.2)
|
||||
activerecord (>= 5.1, < 7.1)
|
||||
parser (3.2.2.1)
|
||||
parser (3.2.2.3)
|
||||
ast (~> 2.4.1)
|
||||
racc
|
||||
paypal-sdk-core (0.3.4)
|
||||
multi_json (~> 1.0)
|
||||
xml-simple
|
||||
@@ -502,7 +500,7 @@ GEM
|
||||
activerecord (>= 4.2)
|
||||
railties (>= 4.2)
|
||||
raabro (1.4.0)
|
||||
racc (1.6.2)
|
||||
racc (1.7.0)
|
||||
rack (2.2.7)
|
||||
rack-mini-profiler (2.3.4)
|
||||
rack (>= 1.2.0)
|
||||
@@ -520,20 +518,20 @@ GEM
|
||||
rack-test (2.1.0)
|
||||
rack (>= 1.3)
|
||||
rack-timeout (0.6.3)
|
||||
rails (7.0.4.3)
|
||||
actioncable (= 7.0.4.3)
|
||||
actionmailbox (= 7.0.4.3)
|
||||
actionmailer (= 7.0.4.3)
|
||||
actionpack (= 7.0.4.3)
|
||||
actiontext (= 7.0.4.3)
|
||||
actionview (= 7.0.4.3)
|
||||
activejob (= 7.0.4.3)
|
||||
activemodel (= 7.0.4.3)
|
||||
activerecord (= 7.0.4.3)
|
||||
activestorage (= 7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
rails (7.0.5)
|
||||
actioncable (= 7.0.5)
|
||||
actionmailbox (= 7.0.5)
|
||||
actionmailer (= 7.0.5)
|
||||
actionpack (= 7.0.5)
|
||||
actiontext (= 7.0.5)
|
||||
actionview (= 7.0.5)
|
||||
activejob (= 7.0.5)
|
||||
activemodel (= 7.0.5)
|
||||
activerecord (= 7.0.5)
|
||||
activestorage (= 7.0.5)
|
||||
activesupport (= 7.0.5)
|
||||
bundler (>= 1.15.0)
|
||||
railties (= 7.0.4.3)
|
||||
railties (= 7.0.5)
|
||||
rails-controller-testing (1.0.5)
|
||||
actionpack (>= 5.0.1.rc1)
|
||||
actionview (>= 5.0.1.rc1)
|
||||
@@ -553,9 +551,9 @@ GEM
|
||||
i18n (>= 0.7, < 2)
|
||||
railties (>= 6.0.0, < 8)
|
||||
rails_safe_tasks (1.0.0)
|
||||
railties (7.0.4.3)
|
||||
actionpack (= 7.0.4.3)
|
||||
activesupport (= 7.0.4.3)
|
||||
railties (7.0.5)
|
||||
actionpack (= 7.0.5)
|
||||
activesupport (= 7.0.5)
|
||||
method_source
|
||||
rake (>= 12.2)
|
||||
thor (~> 1.0)
|
||||
@@ -575,7 +573,7 @@ GEM
|
||||
redis (4.8.1)
|
||||
redis-client (0.14.1)
|
||||
connection_pool
|
||||
regexp_parser (2.8.0)
|
||||
regexp_parser (2.8.1)
|
||||
reline (0.3.3)
|
||||
io-console (~> 0.5)
|
||||
request_store (1.5.1)
|
||||
@@ -629,17 +627,17 @@ GEM
|
||||
rswag-ui (2.9.0)
|
||||
actionpack (>= 3.1, < 7.1)
|
||||
railties (>= 3.1, < 7.1)
|
||||
rubocop (1.51.0)
|
||||
rubocop (1.52.1)
|
||||
json (~> 2.3)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 3.2.0.0)
|
||||
parser (>= 3.2.2.3)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
regexp_parser (>= 1.8, < 3.0)
|
||||
rexml (>= 3.2.5, < 4.0)
|
||||
rubocop-ast (>= 1.28.0, < 2.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 2.4.0, < 3.0)
|
||||
rubocop-ast (1.28.1)
|
||||
rubocop-ast (1.29.0)
|
||||
parser (>= 3.2.1.0)
|
||||
rubocop-rails (2.19.1)
|
||||
activesupport (>= 4.2.0)
|
||||
@@ -669,7 +667,7 @@ GEM
|
||||
semantic_range (3.0.0)
|
||||
shoulda-matchers (5.3.0)
|
||||
activesupport (>= 5.2.0)
|
||||
sidekiq (7.1.1)
|
||||
sidekiq (7.1.2)
|
||||
concurrent-ruby (< 2)
|
||||
connection_pool (>= 2.3.0)
|
||||
rack (>= 2.2.4)
|
||||
@@ -721,7 +719,7 @@ GEM
|
||||
attr_required (>= 0.0.5)
|
||||
httpclient (>= 2.4)
|
||||
temple (0.8.2)
|
||||
test-unit (3.5.9)
|
||||
test-unit (3.6.0)
|
||||
power_assert
|
||||
thor (1.2.2)
|
||||
thread-local (1.1.0)
|
||||
@@ -743,7 +741,7 @@ GEM
|
||||
activemodel (>= 3.0.0)
|
||||
public_suffix
|
||||
vcr (6.1.0)
|
||||
view_component (3.0.0)
|
||||
view_component (3.2.0)
|
||||
activesupport (>= 5.2.0, < 8.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
method_source (~> 1.0)
|
||||
@@ -861,7 +859,6 @@ DEPENDENCIES
|
||||
mime-types
|
||||
mimemagic (> 0.3.5)
|
||||
mini_portile2 (~> 2.8)
|
||||
mini_racer
|
||||
monetize (~> 1.11)
|
||||
oauth2 (~> 1.4.7)
|
||||
omniauth-rails_csrf_protection
|
||||
|
||||
@@ -9,6 +9,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
$scope.sharedResource = false
|
||||
$scope.columns = Columns.columns
|
||||
$scope.sorting = SortOptions
|
||||
$scope.sorting.toggle("order_date")
|
||||
$scope.pagination = LineItems.pagination
|
||||
$scope.per_page_options = [
|
||||
{id: 15, name: t('js.admin.orders.index.per_page', results: 15)},
|
||||
@@ -61,6 +62,8 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
$scope.dereferenceLoadedData()
|
||||
|
||||
$scope.loadOrders = ->
|
||||
return $scope.orders = [] unless $scope.line_items.length
|
||||
|
||||
RequestMonitor.load $scope.orders = Orders.index(
|
||||
"q[id_in][]": $scope.line_items.map((line_item) -> line_item.order.id)
|
||||
)
|
||||
@@ -79,6 +82,7 @@ angular.module("admin.lineItems").controller 'LineItemsCtrl', ($scope, $timeout,
|
||||
"q[order_order_cycle_id_eq]": $scope.orderCycleFilter,
|
||||
"q[order_completed_at_gteq]": if formattedStartDate then formattedStartDate else undefined,
|
||||
"q[order_completed_at_lt]": if formattedEndDate then formattedEndDate else undefined,
|
||||
"q[s]": "order_completed_at desc",
|
||||
"page": $scope.page,
|
||||
"per_page": $scope.per_page
|
||||
)
|
||||
|
||||
@@ -33,6 +33,4 @@ angular.module('admin.orderCycles').factory('Enterprise', ($resource) ->
|
||||
variantsOf: (product) ->
|
||||
if product.variants.length > 0
|
||||
variant.id for variant in product.variants
|
||||
else
|
||||
[product.master_id]
|
||||
})
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
$ ->
|
||||
($ '#new_image_link').click (event) ->
|
||||
event.preventDefault()
|
||||
|
||||
($ '.no-objects-found').hide()
|
||||
|
||||
($ this).hide()
|
||||
$.ajax
|
||||
type: 'GET'
|
||||
url: @href
|
||||
data: (
|
||||
authenticity_token: AUTH_TOKEN
|
||||
)
|
||||
success: (r) ->
|
||||
($ '#images').html r
|
||||
@@ -1,7 +0,0 @@
|
||||
($ '#cancel_link').click (event) ->
|
||||
event.preventDefault()
|
||||
|
||||
($ '.no-objects-found').show()
|
||||
|
||||
($ '#new_image_link').show()
|
||||
($ '#images').html('')
|
||||
@@ -10,6 +10,12 @@ angular.module("admin.utils").directive "variantAutocomplete", ($timeout) ->
|
||||
element.select2
|
||||
placeholder: t('admin.orders.select_variant')
|
||||
minimumInputLength: 3
|
||||
formatInputTooShort: ->
|
||||
t('admin.select2.minimal_search_length', count: 3)
|
||||
formatSearching: ->
|
||||
t('admin.select2.searching')
|
||||
formatNoMatches: ->
|
||||
t('admin.select2.no_matches')
|
||||
ajax:
|
||||
url: Spree.routes.variants_search
|
||||
datatype: "json"
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
angular.module('Darkswarm').controller "AccordionCtrl", ($scope, localStorageService, $timeout, $document, CurrentHub) ->
|
||||
$scope.accordionSections = ["details", "billing", "shipping", "payment"]
|
||||
$scope.accordion = { details: true, billing: true, shipping: true, payment: true }
|
||||
|
||||
$scope.show = (section) ->
|
||||
$scope.accordion[section] = true
|
||||
|
||||
$scope.scrollTo = (section) ->
|
||||
# Scrolling is confused by our position:fixed top bar - add an offset to scroll
|
||||
# to the correct location, plus 5px buffer
|
||||
offset_height = $("nav.top-bar").height() + 5
|
||||
$document.scrollTo($("##{section}"), offset_height, 400)
|
||||
|
||||
$scope.$on 'purchaseFormInvalid', (event, form) ->
|
||||
# Scroll to first invalid section
|
||||
for section in $scope.accordionSections
|
||||
if not form[section].$valid
|
||||
$scope.show section
|
||||
$timeout ->
|
||||
$scope.scrollTo(section)
|
||||
, 50
|
||||
break
|
||||
@@ -1,12 +0,0 @@
|
||||
angular.module('Darkswarm').controller "BillingCtrl", ($scope, $timeout, $controller) ->
|
||||
angular.extend this, $controller('FieldsetMixin', {$scope: $scope})
|
||||
|
||||
$scope.name = "billing"
|
||||
$scope.nextPanel = "shipping"
|
||||
|
||||
$scope.summary = ->
|
||||
[$scope.order.bill_address.address1,
|
||||
$scope.order.bill_address.city,
|
||||
$scope.order.bill_address.zipcode]
|
||||
|
||||
$timeout $scope.onTimeout
|
||||
@@ -1,43 +0,0 @@
|
||||
angular.module('Darkswarm').controller "CheckoutCtrl", ($scope, localStorageService, Checkout, CurrentUser, CurrentHub, $http) ->
|
||||
$scope.Checkout = Checkout
|
||||
$scope.submitted = false
|
||||
|
||||
# Bind to local storage
|
||||
$scope.fieldsToBind = ["bill_address", "email", "payment_method_id", "shipping_method_id", "ship_address"]
|
||||
prefix = "order_#{Checkout.order.id}#{CurrentUser.id or ""}#{CurrentHub.hub.id}"
|
||||
|
||||
for field in $scope.fieldsToBind
|
||||
localStorageService.bind $scope, "Checkout.order.#{field}", Checkout.order[field], "#{prefix}_#{field}"
|
||||
|
||||
localStorageService.bind $scope, "Checkout.ship_address_same_as_billing", true, "#{prefix}_sameasbilling"
|
||||
localStorageService.bind $scope, "Checkout.default_bill_address", false, "#{prefix}_defaultasbilladdress"
|
||||
localStorageService.bind $scope, "Checkout.default_ship_address", false, "#{prefix}_defaultasshipaddress"
|
||||
|
||||
$scope.order = Checkout.order # Ordering is important
|
||||
$scope.secrets = Checkout.secrets
|
||||
|
||||
$scope.enabled = !!CurrentUser.id?
|
||||
|
||||
$scope.purchase = (event, form) ->
|
||||
event.preventDefault()
|
||||
$scope.formdata = form
|
||||
$scope.submitted = true
|
||||
|
||||
if CurrentUser.id
|
||||
$scope.validateForm(form)
|
||||
else
|
||||
$scope.ensureUserIsGuest()
|
||||
|
||||
$scope.validateForm = ->
|
||||
if $scope.formdata.$valid
|
||||
$scope.Checkout.purchase()
|
||||
else
|
||||
$scope.$broadcast 'purchaseFormInvalid', $scope.formdata
|
||||
|
||||
$scope.ensureUserIsGuest = (callback = null) ->
|
||||
$http.post("/user/registered_email", {email: $scope.order.email})
|
||||
.then (response)->
|
||||
window.CableReady.perform(response.data)
|
||||
.catch ->
|
||||
$scope.validateForm() if $scope.submitted
|
||||
callback() if callback
|
||||
@@ -1,8 +0,0 @@
|
||||
angular.module('Darkswarm').controller "CountryCtrl", ($scope, availableCountries) ->
|
||||
|
||||
$scope.countries = availableCountries
|
||||
|
||||
$scope.countriesById = $scope.countries.reduce (obj, country) ->
|
||||
obj[country.id] = country
|
||||
obj
|
||||
, {}
|
||||
@@ -1,24 +0,0 @@
|
||||
angular.module('Darkswarm').controller "DetailsCtrl", ($scope, $timeout, $http, CurrentUser, SpreeUser, $controller) ->
|
||||
angular.extend this, $controller('FieldsetMixin', {$scope: $scope})
|
||||
|
||||
$scope.name = "details"
|
||||
$scope.nextPanel = "billing"
|
||||
|
||||
$scope.login_or_next = (event) ->
|
||||
event.preventDefault()
|
||||
unless CurrentUser.id
|
||||
$scope.ensureUserIsGuest($scope.next)
|
||||
return
|
||||
|
||||
$scope.next()
|
||||
|
||||
$scope.summary = ->
|
||||
[$scope.fullName(),
|
||||
$scope.order.email,
|
||||
$scope.order.bill_address.phone]
|
||||
|
||||
$scope.fullName = ->
|
||||
[$scope.order.bill_address.firstname ? null,
|
||||
$scope.order.bill_address.lastname ? null].join(" ").trim()
|
||||
|
||||
$timeout $scope.onTimeout
|
||||
@@ -1,19 +0,0 @@
|
||||
angular.module('Darkswarm').controller "PaymentCtrl", ($scope, $timeout, savedCreditCards, Dates, $controller) ->
|
||||
angular.extend this, $controller('FieldsetMixin', {$scope: $scope})
|
||||
|
||||
$scope.savedCreditCards = savedCreditCards
|
||||
$scope.name = "payment"
|
||||
$scope.months = Dates.months
|
||||
$scope.years = Dates.years
|
||||
|
||||
$scope.secrets.card_month = "1"
|
||||
$scope.secrets.card_year = moment().year()
|
||||
|
||||
for card in savedCreditCards when card.is_default
|
||||
$scope.secrets.selected_card = card.id
|
||||
break
|
||||
|
||||
$scope.summary = ->
|
||||
[$scope.Checkout.paymentMethod()?.name]
|
||||
|
||||
$timeout $scope.onTimeout
|
||||
@@ -1,11 +0,0 @@
|
||||
angular.module('Darkswarm').controller "ShippingCtrl", ($scope, $timeout, ShippingMethods, $controller) ->
|
||||
angular.extend this, $controller('FieldsetMixin', {$scope: $scope})
|
||||
|
||||
$scope.ShippingMethods = ShippingMethods
|
||||
$scope.name = "shipping"
|
||||
$scope.nextPanel = "payment"
|
||||
|
||||
$scope.summary = ->
|
||||
[$scope.Checkout.shippingMethod()?.name]
|
||||
|
||||
$timeout $scope.onTimeout
|
||||
@@ -33,9 +33,9 @@ angular.module('Darkswarm').factory 'Products', (OrderCycleResource, OrderCycle,
|
||||
prices = (v.price for v in product.variants)
|
||||
product.price = Math.min.apply(null, prices)
|
||||
product.hasVariants = product.variants?.length > 0
|
||||
product.primaryImage = product.images[0]?.small_url if product.images
|
||||
product.primaryImage = product.image?.small_url if product.image
|
||||
product.primaryImageOrMissing = product.primaryImage || "/noimage/small.png"
|
||||
product.largeImage = product.images[0]?.large_url if product.images
|
||||
product.largeImage = product.image?.large_url if product.image
|
||||
|
||||
dereference: ->
|
||||
for product in @fetched_products
|
||||
|
||||
@@ -15,6 +15,6 @@
|
||||
|
||||
.columns.small-12.medium-6.large-6.product-img
|
||||
%img{"ng-src" => "{{::product.largeImage}}", "ng-if" => "::product.largeImage"}
|
||||
%img.placeholder{ src: "/noimage/large.png", "ng-if" => "::!product.largeImage"}
|
||||
%img.placeholder{ src: Spree::Image.default_image_url(:large), "ng-if" => "::!product.largeImage"}
|
||||
|
||||
%ng-include{src: "'partials/close.html'"}
|
||||
|
||||
@@ -6,7 +6,7 @@ class ProductComponent < ViewComponentReflex::Component
|
||||
def initialize(product:, columns:)
|
||||
super
|
||||
@product = product
|
||||
@image = @product.images[0] if product.images.any?
|
||||
@image = @product.image if product.image.present?
|
||||
@columns = columns.map do |c|
|
||||
{
|
||||
id: c[:value],
|
||||
@@ -28,7 +28,7 @@ class ProductComponent < ViewComponentReflex::Component
|
||||
when 'price'
|
||||
@product.price
|
||||
when 'unit'
|
||||
"#{@product.unit_value} #{@product.variant_unit}"
|
||||
"#{@product.variants.first.unit_value} #{@product.variant_unit}"
|
||||
when 'producer'
|
||||
@product.supplier.name
|
||||
when 'category'
|
||||
|
||||
@@ -168,7 +168,7 @@ class ProductsTableComponent < ViewComponentReflex::Component
|
||||
|
||||
def product_query_includes
|
||||
[
|
||||
master: [:images],
|
||||
:image,
|
||||
variants: [
|
||||
:default_price,
|
||||
:stock_locations,
|
||||
|
||||
@@ -12,8 +12,7 @@ module Admin
|
||||
@line_items = order_permissions.
|
||||
editable_line_items.where(order_id: orders).
|
||||
includes(:variant).
|
||||
ransack(params[:q]).result.
|
||||
reorder('spree_line_items.order_id ASC, spree_line_items.id ASC')
|
||||
ransack(params[:q]).result
|
||||
|
||||
@pagy, @line_items = pagy(@line_items) if pagination_required?
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ module Admin
|
||||
format.json {
|
||||
render_as_json @collection, controller: self, include_calculators: @include_calculators
|
||||
}
|
||||
# format.json { @presented_collection = @collection.each_with_index.map { |ef, i| EnterpriseFeePresenter.new(self, ef, i) } }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -63,7 +62,9 @@ module Admin
|
||||
when :for_order_cycle
|
||||
order_cycle = OrderCycle.find_by(id: params[:order_cycle_id]) if params[:order_cycle_id]
|
||||
coordinator = Enterprise.find_by(id: params[:coordinator_id]) if params[:coordinator_id]
|
||||
order_cycle = OrderCycle.new(coordinator: coordinator) if order_cycle.nil? && coordinator.present?
|
||||
if order_cycle.nil? && coordinator.present?
|
||||
order_cycle = OrderCycle.new(coordinator: coordinator)
|
||||
end
|
||||
enterprises = OpenFoodNetwork::OrderCyclePermissions.new(spree_current_user,
|
||||
order_cycle).visible_enterprises
|
||||
EnterpriseFee.for_enterprises(enterprises).order('enterprise_id', 'fee_type', 'name')
|
||||
|
||||
@@ -178,7 +178,9 @@ module Admin
|
||||
when :for_order_cycle
|
||||
@order_cycle = OrderCycle.find_by(id: params[:order_cycle_id]) if params[:order_cycle_id]
|
||||
coordinator = Enterprise.find_by(id: params[:coordinator_id]) if params[:coordinator_id]
|
||||
@order_cycle = OrderCycle.new(coordinator: coordinator) if @order_cycle.nil? && coordinator.present?
|
||||
if @order_cycle.nil? && coordinator.present?
|
||||
@order_cycle = OrderCycle.new(coordinator: coordinator)
|
||||
end
|
||||
|
||||
enterprises = OpenFoodNetwork::OrderCyclePermissions.new(spree_current_user, @order_cycle)
|
||||
.visible_enterprises
|
||||
@@ -186,7 +188,7 @@ module Admin
|
||||
if enterprises.present?
|
||||
enterprises.includes(
|
||||
supplied_products:
|
||||
[:supplier, :variants, { master: [:images] }]
|
||||
[:supplier, :variants, :image]
|
||||
)
|
||||
end
|
||||
when :index
|
||||
@@ -195,7 +197,8 @@ module Admin
|
||||
editable_enterprises.
|
||||
order('is_primary_producer ASC, name')
|
||||
elsif json_request?
|
||||
OpenFoodNetwork::Permissions.new(spree_current_user).editable_enterprises.ransack(params[:q]).result
|
||||
OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
.editable_enterprises.ransack(params[:q]).result
|
||||
else
|
||||
Enterprise.where("1=0")
|
||||
end
|
||||
@@ -203,7 +206,6 @@ module Admin
|
||||
OpenFoodNetwork::Permissions.new(spree_current_user).visible_enterprises
|
||||
.includes(:shipping_methods, :payment_methods).ransack(params[:q]).result
|
||||
else
|
||||
# TODO was ordered with is_distributor DESC as well, not sure why or how we want to sort this now
|
||||
OpenFoodNetwork::Permissions.new(spree_current_user).
|
||||
editable_enterprises.
|
||||
order('is_primary_producer ASC, name')
|
||||
@@ -324,7 +326,9 @@ module Admin
|
||||
:producer_properties_attributes).nil?
|
||||
names = Spree::Property.pluck(:name)
|
||||
enterprise_params[:producer_properties_attributes].each do |key, property|
|
||||
enterprise_params[:producer_properties_attributes].delete key unless names.include? property[:property_name]
|
||||
unless names.include? property[:property_name]
|
||||
enterprise_params[:producer_properties_attributes].delete key
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -40,8 +40,11 @@ module Admin
|
||||
def index
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
render_as_json @collection, ams_prefix: params[:ams_prefix],
|
||||
editable_schedule_ids: permissions.editable_schedules.pluck(:id)
|
||||
render_as_json(
|
||||
@collection,
|
||||
ams_prefix: params[:ams_prefix],
|
||||
editable_schedule_ids: permissions.editable_schedules.pluck(:id)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -119,7 +122,8 @@ module Admin
|
||||
.pluck(:id)
|
||||
result = @existing_order_cycle_ids
|
||||
result |= (requested & permitted) # add any requested & permitted ids
|
||||
result -= ((result & permitted) - requested) # remove any existing and permitted ids that were not specifically requested
|
||||
# remove any existing and permitted ids that were not specifically requested
|
||||
result -= ((result & permitted) - requested)
|
||||
result
|
||||
end
|
||||
|
||||
|
||||
@@ -80,8 +80,12 @@ module Api
|
||||
end
|
||||
|
||||
def permitted_ransack_params
|
||||
[:name_or_meta_keywords_or_variants_display_as_or_variants_display_name_or_supplier_name_cont,
|
||||
:with_properties, :primary_taxon_id_in_any]
|
||||
[
|
||||
"#{[:name, :meta_keywords, :variants_display_as,
|
||||
:variants_display_name, :supplier_name]
|
||||
.join('_or_')}_cont",
|
||||
:with_properties, :primary_taxon_id_in_any
|
||||
]
|
||||
end
|
||||
|
||||
def distributor
|
||||
|
||||
@@ -9,9 +9,9 @@ module Api
|
||||
product = Spree::Product.find(params[:product_id])
|
||||
authorize! :update, product
|
||||
|
||||
image = product.images.first || Spree::Image.new(
|
||||
viewable_id: product.master.id,
|
||||
viewable_type: 'Spree::Variant'
|
||||
image = product.image || Spree::Image.new(
|
||||
viewable_id: product.id,
|
||||
viewable_type: 'Spree::Product'
|
||||
)
|
||||
|
||||
success_status = image.persisted? ? :ok : :created
|
||||
|
||||
@@ -116,7 +116,7 @@ module Api
|
||||
|
||||
def product_query_includes
|
||||
[
|
||||
master: { images: { attachment_attachment: :blob } },
|
||||
image: { attachment_attachment: :blob },
|
||||
variants: [:default_price, :stock_locations, :stock_items, :variant_overrides]
|
||||
]
|
||||
end
|
||||
|
||||
@@ -21,7 +21,9 @@ module Api
|
||||
@shipment.refresh_rates
|
||||
@shipment.save!
|
||||
|
||||
render json: @shipment.reload, serializer: Api::ShipmentSerializer, status: :ok
|
||||
OrderWorkflow.new(@order).advance_to_payment if @order.line_items.any?
|
||||
|
||||
render json: @shipment, serializer: Api::ShipmentSerializer, status: :ok
|
||||
end
|
||||
|
||||
def update
|
||||
@@ -32,7 +34,7 @@ module Api
|
||||
@shipment.fee_adjustment.fire_events(:open)
|
||||
|
||||
if @shipment.update(shipment_params)
|
||||
@order.updater.update_totals_and_states
|
||||
@order.update_totals_and_states
|
||||
end
|
||||
|
||||
@shipment.fee_adjustment.close
|
||||
|
||||
@@ -56,9 +56,9 @@ module Api
|
||||
def scope
|
||||
if @product
|
||||
variants = if current_api_user.has_spree_role?("admin") || params[:show_deleted]
|
||||
@product.variants_including_master.with_deleted
|
||||
@product.variants.with_deleted
|
||||
else
|
||||
@product.variants_including_master
|
||||
@product.variants
|
||||
end
|
||||
else
|
||||
variants = Spree::Variant.where(nil)
|
||||
|
||||
@@ -1,187 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'open_food_network/address_finder'
|
||||
|
||||
class CheckoutController < ::BaseController
|
||||
include OrderStockCheck
|
||||
include OrderCompletion
|
||||
include WhiteLabel
|
||||
|
||||
layout 'darkswarm'
|
||||
|
||||
helper 'terms_and_conditions'
|
||||
helper 'checkout'
|
||||
|
||||
# We need pessimistic locking to avoid race conditions.
|
||||
# Otherwise we fail on duplicate indexes or end up with negative stock.
|
||||
prepend_around_action CurrentOrderLocker, only: [:edit, :update]
|
||||
|
||||
prepend_before_action :check_hub_ready_for_checkout
|
||||
prepend_before_action :check_order_cycle_expiry
|
||||
prepend_before_action :require_order_cycle
|
||||
prepend_before_action :require_distributor_chosen
|
||||
|
||||
before_action :load_order
|
||||
|
||||
before_action :handle_insufficient_stock
|
||||
|
||||
before_action :associate_user
|
||||
before_action :check_authorization
|
||||
|
||||
before_action :hide_ofn_navigation, only: :edit
|
||||
|
||||
helper 'spree/orders'
|
||||
|
||||
def edit; end
|
||||
|
||||
def update
|
||||
params_adapter = Checkout::FormDataAdapter.new(permitted_params, @order, spree_current_user)
|
||||
return action_failed unless @order.update(params_adapter.params[:order] || {})
|
||||
|
||||
checkout_workflow(params_adapter.shipping_method_id)
|
||||
rescue Spree::Core::GatewayError => e
|
||||
gateway_error(e)
|
||||
action_failed(e)
|
||||
rescue StandardError => e
|
||||
flash[:error] = I18n.t("checkout.failed")
|
||||
action_failed(e)
|
||||
ensure
|
||||
@order.update_order!
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def check_authorization
|
||||
authorize!(:edit, current_order, session[:access_token])
|
||||
end
|
||||
|
||||
def load_order
|
||||
load_checkout_order
|
||||
|
||||
return handle_invalid_stock unless valid_order_line_items?
|
||||
|
||||
before_address
|
||||
setup_for_current_state
|
||||
end
|
||||
|
||||
def handle_invalid_stock
|
||||
reset_order_to_cart
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
redirect_to main_app.cart_path
|
||||
end
|
||||
|
||||
format.json do
|
||||
render json: { path: main_app.cart_path }, status: :bad_request
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def setup_for_current_state
|
||||
method_name = :"before_#{@order.state}"
|
||||
__send__(method_name) if respond_to?(method_name, true)
|
||||
end
|
||||
|
||||
def before_address
|
||||
associate_user
|
||||
|
||||
finder = OpenFoodNetwork::AddressFinder.new(@order.email, @order.customer, spree_current_user)
|
||||
|
||||
@order.bill_address = finder.bill_address
|
||||
@order.ship_address = finder.ship_address
|
||||
end
|
||||
|
||||
def before_payment
|
||||
current_order.payments.destroy_all if request.put?
|
||||
end
|
||||
|
||||
def checkout_workflow(shipping_method_id)
|
||||
while @order.state != "complete"
|
||||
if @order.state == "payment"
|
||||
update_payment_total
|
||||
return if redirect_to_payment_gateway
|
||||
|
||||
return action_failed if @order.errors.any?
|
||||
return action_failed unless @order.process_payments!
|
||||
end
|
||||
|
||||
next if OrderWorkflow.new(@order).next({ "shipping_method_id" => shipping_method_id })
|
||||
|
||||
return action_failed
|
||||
end
|
||||
|
||||
update_response
|
||||
end
|
||||
|
||||
def update_payment_total
|
||||
@order.updater.update_totals
|
||||
@order.updater.update_pending_payment
|
||||
end
|
||||
|
||||
def redirect_to_payment_gateway
|
||||
return unless selected_payment_method.external_gateway?
|
||||
return unless (redirect_url = selected_payment_method.external_payment_url(order: @order))
|
||||
|
||||
render json: { path: redirect_url }, status: :ok
|
||||
true
|
||||
end
|
||||
|
||||
def selected_payment_method
|
||||
@selected_payment_method ||= Spree::PaymentMethod.find(
|
||||
params.dig(:order, :payments_attributes, 0, :payment_method_id)
|
||||
)
|
||||
end
|
||||
|
||||
def update_response
|
||||
if order_complete?
|
||||
processing_succeeded
|
||||
update_succeeded_response
|
||||
else
|
||||
action_failed(RuntimeError.new("Order not complete after the checkout workflow"))
|
||||
end
|
||||
end
|
||||
|
||||
def order_complete?
|
||||
@order.state == "complete" || @order.completed?
|
||||
end
|
||||
|
||||
def update_succeeded_response
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
respond_with(@order, location: order_completion_route)
|
||||
end
|
||||
format.json do
|
||||
render json: { path: order_completion_route }, status: :ok
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def action_failed(error = RuntimeError.new(order_processing_error))
|
||||
processing_failed(error)
|
||||
action_failed_response
|
||||
end
|
||||
|
||||
def action_failed_response
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
render :edit
|
||||
end
|
||||
format.json do
|
||||
discard_flash_errors
|
||||
render json: { errors: @order.errors, flash: flash.to_hash }.to_json, status: :bad_request
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def permitted_params
|
||||
PermittedAttributes::Checkout.new(params).call
|
||||
end
|
||||
|
||||
def discard_flash_errors
|
||||
# Marks flash errors for deletion after the current action has completed.
|
||||
# This ensures flash errors generated during XHR requests are not persisted in the
|
||||
# session for longer than expected.
|
||||
flash.discard(:error)
|
||||
end
|
||||
end
|
||||
@@ -13,8 +13,6 @@ module OrderStockCheck
|
||||
def handle_insufficient_stock
|
||||
return if sufficient_stock?
|
||||
|
||||
reset_order_to_cart
|
||||
|
||||
flash[:error] = Spree.t(:inventory_error_flash_for_insufficient_quantity)
|
||||
redirect_to main_app.cart_path
|
||||
end
|
||||
@@ -43,10 +41,4 @@ module OrderStockCheck
|
||||
def sufficient_stock?
|
||||
@sufficient_stock ||= @order.insufficient_stock_lines.blank?
|
||||
end
|
||||
|
||||
def reset_order_to_cart
|
||||
return if OpenFoodNetwork::FeatureToggle.enabled? :split_checkout, spree_current_user
|
||||
|
||||
OrderCheckoutRestart.new(@order).call
|
||||
end
|
||||
end
|
||||
|
||||
@@ -29,11 +29,11 @@ module PaymentGateways
|
||||
flash[:error] =
|
||||
Spree.t('flash.generic_error', scope: 'paypal',
|
||||
reasons: pp_response.errors.map(&:long_message).join(" "))
|
||||
redirect_to main_app.checkout_state_path(:payment)
|
||||
redirect_to main_app.checkout_step_path(:payment)
|
||||
end
|
||||
rescue SocketError
|
||||
flash[:error] = Spree.t('flash.connection_failed', scope: 'paypal')
|
||||
redirect_to main_app.checkout_state_path(:payment)
|
||||
redirect_to main_app.checkout_step_path(:payment)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ class SplitCheckoutController < ::BaseController
|
||||
|
||||
@order.select_shipping_method(params[:shipping_method_id])
|
||||
@order.update(order_params)
|
||||
@order.updater.update_totals_and_states
|
||||
@order.update_totals_and_states
|
||||
|
||||
validate_current_step!
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ module Spree
|
||||
|
||||
def update_order
|
||||
@order.reload
|
||||
@order.updater.update_totals_and_states
|
||||
@order.update_totals_and_states
|
||||
end
|
||||
|
||||
def collection
|
||||
|
||||
@@ -25,6 +25,7 @@ module Spree
|
||||
set_viewable
|
||||
|
||||
@object.attributes = permitted_resource_params
|
||||
|
||||
if @object.save
|
||||
flash[:success] = flash_message_for(@object, :successfully_created)
|
||||
redirect_to spree.admin_product_images_url(params[:product_id], @url_filters)
|
||||
@@ -62,20 +63,28 @@ module Spree
|
||||
|
||||
private
|
||||
|
||||
def collection
|
||||
parent.image
|
||||
end
|
||||
|
||||
def find_resource
|
||||
parent.image
|
||||
end
|
||||
|
||||
def build_resource
|
||||
Spree::Image.new(viewable: parent)
|
||||
end
|
||||
|
||||
def location_after_save
|
||||
spree.admin_product_images_url(@product)
|
||||
end
|
||||
|
||||
def load_data
|
||||
@product = Product.find_by(permalink: params[:product_id])
|
||||
@variants = @product.variants.collect do |variant|
|
||||
[variant.options_text, variant.id]
|
||||
end
|
||||
@variants.insert(0, [Spree.t(:all), @product.master.id])
|
||||
end
|
||||
|
||||
def set_viewable
|
||||
@image.viewable_type = 'Spree::Variant'
|
||||
@image.viewable_type = 'Spree::Product'
|
||||
@image.viewable_id = params[:image][:viewable_id]
|
||||
end
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ module Spree
|
||||
@order.create_tax_charge!
|
||||
Spree::TaxRate.adjust(@order, @order.adjustments.admin)
|
||||
|
||||
@order.updater.update_totals_and_states
|
||||
@order.update_totals_and_states
|
||||
end
|
||||
|
||||
def order_params
|
||||
|
||||
@@ -8,9 +8,8 @@ module Spree
|
||||
include OpenFoodNetwork::SpreeApiKeyLoader
|
||||
helper CheckoutHelper
|
||||
|
||||
before_action :load_order, only: [:edit, :update, :fire, :resend,
|
||||
:invoice, :print, :distribution]
|
||||
before_action :load_distribution_choices, only: [:new, :edit, :update, :distribution]
|
||||
before_action :load_order, only: [:edit, :update, :fire, :resend, :invoice, :print]
|
||||
before_action :load_distribution_choices, only: [:new, :create, :edit, :update]
|
||||
before_action :require_distributor_abn, only: :invoice
|
||||
before_action :restore_saved_query!, only: :index
|
||||
|
||||
@@ -24,47 +23,35 @@ module Spree
|
||||
end
|
||||
|
||||
def new
|
||||
@order = Order.create
|
||||
@order.created_by = spree_current_user
|
||||
@order.generate_order_number
|
||||
@order.save
|
||||
redirect_to spree.distribution_admin_order_path(@order)
|
||||
end
|
||||
|
||||
def distribution
|
||||
return if order_params.blank?
|
||||
|
||||
on_update
|
||||
|
||||
@order.assign_attributes(order_params)
|
||||
return unless @order.save(context: :set_distribution_step)
|
||||
|
||||
redirect_to spree.admin_order_customer_path(@order)
|
||||
@order = Spree::Order.new
|
||||
end
|
||||
|
||||
def edit
|
||||
@order.shipments.map(&:refresh_rates)
|
||||
end
|
||||
|
||||
OrderWorkflow.new(@order).advance_to_payment
|
||||
@order.errors.clear
|
||||
def create
|
||||
@order = Spree::Order.new(order_params.merge(created_by: spree_current_user))
|
||||
|
||||
if @order.save(context: :require_distribution)
|
||||
redirect_to spree.admin_order_customer_path(@order)
|
||||
else
|
||||
render :new
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
on_update
|
||||
|
||||
if params[:set_distribution_step] && @order.update(order_params)
|
||||
return redirect_to spree.admin_order_customer_path(@order)
|
||||
end
|
||||
|
||||
unless order_params.present? && @order.update(order_params) && @order.line_items.present?
|
||||
if @order.line_items.empty? && !params[:suppress_error_msg]
|
||||
@order.errors.add(:line_items, Spree.t('errors.messages.blank'))
|
||||
end
|
||||
order_updated = order_params.present? && @order.update(order_params)
|
||||
|
||||
unless order_updated && line_items_present?
|
||||
flash[:error] = @order.errors.full_messages.join(', ') if @order.errors.present?
|
||||
return redirect_to spree.edit_admin_order_path(@order)
|
||||
end
|
||||
|
||||
OrderWorkflow.new(@order).advance_to_payment
|
||||
|
||||
if @order.complete?
|
||||
redirect_to spree.edit_admin_order_path(@order)
|
||||
else
|
||||
@@ -117,6 +104,13 @@ module Spree
|
||||
|
||||
private
|
||||
|
||||
def line_items_present?
|
||||
return true if @order.line_items.any?
|
||||
|
||||
@order.errors.add(:line_items, Spree.t('errors.messages.blank'))
|
||||
false
|
||||
end
|
||||
|
||||
def update_search_results
|
||||
session[:admin_orders_search] = search_params
|
||||
|
||||
|
||||
@@ -129,7 +129,8 @@ module Spree
|
||||
@payment_methods.first
|
||||
end
|
||||
|
||||
@previous_cards = @order.credit_cards.with_payment_profile
|
||||
credit_card_ids = @order.payments.from_credit_card.pluck(:source_id).uniq
|
||||
@previous_cards = CreditCard.where(id: credit_card_ids).with_payment_profile
|
||||
end
|
||||
|
||||
# At this point admin should have passed through Customer Details step
|
||||
|
||||
@@ -121,8 +121,7 @@ module Spree
|
||||
end
|
||||
|
||||
def product_includes
|
||||
[{ variants: [:images] },
|
||||
{ master: [:images, :default_price] }]
|
||||
[:image, { variants: [:images] }]
|
||||
end
|
||||
|
||||
def collection_actions
|
||||
@@ -182,7 +181,6 @@ module Spree
|
||||
joins(:product).
|
||||
where('spree_products.supplier_id IN (?)', editable_enterprises.collect(&:id)).
|
||||
where('spree_variants.import_date IS NOT NULL').
|
||||
where(spree_variants: { is_master: false }).
|
||||
where(spree_variants: { deleted_at: nil }).
|
||||
order('spree_variants.import_date DESC')
|
||||
end
|
||||
@@ -208,7 +206,7 @@ module Spree
|
||||
end
|
||||
|
||||
def set_stock_levels(product, on_hand, on_demand)
|
||||
variant = product_variant(product)
|
||||
variant = product.variants.first
|
||||
|
||||
begin
|
||||
variant.on_demand = on_demand if on_demand.present?
|
||||
@@ -228,14 +226,6 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
def product_variant(product)
|
||||
if product.variants.any?
|
||||
product.variants.first
|
||||
else
|
||||
product.master
|
||||
end
|
||||
end
|
||||
|
||||
def set_product_master_variant_price_to_zero
|
||||
@product.price = 0 if @product.price.nil?
|
||||
end
|
||||
|
||||
@@ -7,8 +7,6 @@ module Spree
|
||||
class VariantsController < ::Admin::ResourceController
|
||||
belongs_to 'spree/product', find_by: :permalink
|
||||
|
||||
before_action :assign_default_attributes, only: :new
|
||||
|
||||
def index
|
||||
@url_filters = ::ProductFilters.new.extract(request.query_parameters)
|
||||
end
|
||||
@@ -45,6 +43,7 @@ module Spree
|
||||
flash[:success] = flash_message_for(@object, :successfully_created)
|
||||
redirect_to spree.admin_product_variants_url(params[:product_id], @url_filters)
|
||||
else
|
||||
flash[:error] = @object.errors.full_messages.to_sentence if @object.errors.any?
|
||||
redirect_to spree.new_admin_product_variant_url(params[:product_id], @url_filters)
|
||||
end
|
||||
|
||||
@@ -83,13 +82,6 @@ module Spree
|
||||
@object.save
|
||||
end
|
||||
|
||||
def assign_default_attributes
|
||||
@object.attributes = @object.product.master.
|
||||
attributes.except('id', 'created_at', 'deleted_at', 'sku', 'is_master')
|
||||
# Shallow Clone of the default price to populate the price field.
|
||||
@object.default_price = @object.product.master.default_price.clone
|
||||
end
|
||||
|
||||
def collection
|
||||
@deleted = params.key?(:deleted) && params[:deleted] == "on" ? "checked" : ""
|
||||
|
||||
|
||||
@@ -78,7 +78,7 @@ module Spree
|
||||
format.html do
|
||||
if params.key?(:checkout)
|
||||
@order.next_transition.run_callbacks if @order.cart?
|
||||
redirect_to main_app.checkout_state_path(@order.checkout_steps.first)
|
||||
redirect_to main_app.checkout_step_path(@order.checkout_steps.first)
|
||||
elsif @order.complete?
|
||||
redirect_to main_app.order_path(@order)
|
||||
else
|
||||
|
||||
@@ -34,7 +34,13 @@ class AngularFormBuilder < ActionView::Helpers::FormBuilder
|
||||
options.reverse_merge!('id' => angular_id(method), 'ng-model' => angular_model(method).to_s)
|
||||
|
||||
@template.select_tag angular_name(method),
|
||||
@template.ng_options_from_collection_for_select(collection, value_method, text_method, angular_field), options
|
||||
@template.ng_options_from_collection_for_select(
|
||||
collection,
|
||||
value_method,
|
||||
text_method,
|
||||
angular_field
|
||||
),
|
||||
options
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -89,16 +89,6 @@ module InjectionHelper
|
||||
render partial: "json/injection_ams", locals: { name: "orderCycleData", json: json }
|
||||
end
|
||||
|
||||
def inject_available_shipping_methods
|
||||
inject_json_array "shippingMethods", available_shipping_methods,
|
||||
Api::ShippingMethodSerializer, current_order: current_order
|
||||
end
|
||||
|
||||
def inject_available_payment_methods
|
||||
inject_json_array "paymentMethods", available_payment_methods,
|
||||
Api::PaymentMethodSerializer, current_order: current_order
|
||||
end
|
||||
|
||||
def inject_taxons
|
||||
inject_json_array "taxons", Spree::Taxon.all.to_a, Api::TaxonSerializer
|
||||
end
|
||||
|
||||
@@ -53,7 +53,8 @@ module OrderCyclesHelper
|
||||
end
|
||||
|
||||
def simple_index
|
||||
@simple_index ||= !OpenFoodNetwork::Permissions.new(spree_current_user).can_manage_complex_order_cycles?
|
||||
@simple_index ||=
|
||||
!OpenFoodNetwork::Permissions.new(spree_current_user).can_manage_complex_order_cycles?
|
||||
end
|
||||
|
||||
def pickup_time(order_cycle = current_order_cycle)
|
||||
@@ -73,7 +74,8 @@ module OrderCyclesHelper
|
||||
def validated_enterprise_options(enterprises, options = {})
|
||||
enterprises.map do |e|
|
||||
disabled_message = nil
|
||||
if options[:shipping_and_payment_methods] && (e.shipping_methods.empty? || e.payment_methods.available.empty?)
|
||||
if options[:shipping_and_payment_methods] &&
|
||||
(e.shipping_methods.empty? || e.payment_methods.available.empty?)
|
||||
if e.shipping_methods.empty? && e.payment_methods.available.empty?
|
||||
disabled_message = I18n.t(:no_shipping_or_payment)
|
||||
elsif e.shipping_methods.empty?
|
||||
|
||||
@@ -5,11 +5,7 @@ module Spree
|
||||
module ImagesHelper
|
||||
def options_text_for(image)
|
||||
if image.viewable.is_a?(Spree::Variant)
|
||||
if image.viewable.is_master?
|
||||
I18n.t(:all)
|
||||
else
|
||||
image.viewable.options_text
|
||||
end
|
||||
image.viewable.options_text
|
||||
else
|
||||
I18n.t(:all)
|
||||
end
|
||||
|
||||
@@ -26,11 +26,11 @@ module Spree
|
||||
destination_url = options[:url] || spree.public_send("#{options[:route]}_path")
|
||||
titleized_label = Spree.t(options[:label],
|
||||
default: options[:label],
|
||||
scope: [:admin, :tab]).titleize
|
||||
scope: [:admin, :tab]).capitalize
|
||||
|
||||
css_classes = []
|
||||
|
||||
if options[:icon]
|
||||
if options[:icon] && !feature?(:admin_style_v3, spree_current_user)
|
||||
link = link_to_with_icon(options[:icon], titleized_label, destination_url)
|
||||
css_classes << 'tab-with-icon'
|
||||
else
|
||||
|
||||
@@ -18,7 +18,9 @@ module Spree
|
||||
def changeable_orders
|
||||
# Only returns open order for the current user + shop + oc combo
|
||||
return @changeable_orders unless @changeable_orders.nil?
|
||||
return @changeable_orders = [] unless spree_current_user && current_distributor && current_order_cycle
|
||||
unless spree_current_user && current_distributor && current_order_cycle
|
||||
return @changeable_orders = []
|
||||
end
|
||||
return @changeable_orders = [] unless current_distributor.allow_order_changes?
|
||||
|
||||
@changeable_orders = Spree::Order.complete.where(
|
||||
|
||||
@@ -6,16 +6,6 @@ module TermsAndConditionsHelper
|
||||
rel: "noopener")
|
||||
end
|
||||
|
||||
def render_terms_and_conditions
|
||||
if platform_terms_required? && distributor_terms_required?
|
||||
render("checkout/all_terms_and_conditions")
|
||||
elsif platform_terms_required?
|
||||
render "checkout/platform_terms_of_service"
|
||||
elsif distributor_terms_required?
|
||||
render "checkout/terms_and_conditions"
|
||||
end
|
||||
end
|
||||
|
||||
def any_terms_required?(distributor)
|
||||
TermsOfService.required?(distributor)
|
||||
end
|
||||
|
||||
@@ -13,6 +13,8 @@ class BulkInvoiceJob < ApplicationJob
|
||||
pdf << CombinePDF.parse(invoice)
|
||||
end
|
||||
|
||||
ensure_directory_exists filepath
|
||||
|
||||
pdf.save filepath
|
||||
|
||||
broadcast(filepath, options[:channel]) if options[:channel]
|
||||
@@ -41,4 +43,8 @@ class BulkInvoiceJob < ApplicationJob
|
||||
).
|
||||
broadcast
|
||||
end
|
||||
|
||||
def ensure_directory_exists(filepath)
|
||||
FileUtils.mkdir_p(File.dirname(filepath))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class AdjustmentMetadata < ApplicationRecord
|
||||
self.belongs_to_required_by_default = true
|
||||
|
||||
belongs_to :adjustment, class_name: 'Spree::Adjustment'
|
||||
belongs_to :enterprise
|
||||
end
|
||||
|
||||
@@ -10,4 +10,12 @@ class ApplicationRecord < ActiveRecord::Base
|
||||
include ArelHelpers::JoinAssociation
|
||||
|
||||
self.abstract_class = true
|
||||
|
||||
def self.image_service
|
||||
ENV["S3_BUCKET"].present? ? :amazon_public : :local
|
||||
end
|
||||
|
||||
def url_for(*args)
|
||||
Rails.application.routes.url_helpers.url_for(*args)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,6 +5,8 @@ require 'open_food_network/column_preference_defaults'
|
||||
class ColumnPreference < ApplicationRecord
|
||||
extend OpenFoodNetwork::ColumnPreferenceDefaults
|
||||
|
||||
self.belongs_to_required_by_default = true
|
||||
|
||||
# Non-persisted attributes that only have one
|
||||
# setting (ie. the default) for a given column
|
||||
attr_accessor :name
|
||||
@@ -48,6 +50,8 @@ class ColumnPreference < ApplicationRecord
|
||||
def self.filter(default_preferences, user, action_name)
|
||||
return unless action_name == 'order_cycles_index'
|
||||
|
||||
default_preferences.delete(:schedules) unless user.admin? || user.enterprises.where(enable_subscriptions: true).any?
|
||||
return if user.admin? || user.enterprises.where(enable_subscriptions: true).any?
|
||||
|
||||
default_preferences.delete(:schedules)
|
||||
end
|
||||
end
|
||||
|
||||
42
app/models/concerns/order_validations.rb
Normal file
42
app/models/concerns/order_validations.rb
Normal file
@@ -0,0 +1,42 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'active_support/concern'
|
||||
|
||||
module OrderValidations
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
private
|
||||
|
||||
def disallow_guest_order
|
||||
return unless using_guest_checkout? && registered_email?
|
||||
|
||||
errors.add(:email, I18n.t('devise.failure.already_registered'))
|
||||
end
|
||||
|
||||
# Check that line_items in the current order are available from a newly selected distribution
|
||||
def products_available_from_new_distribution
|
||||
return if OrderCycleDistributedVariants.new(order_cycle, distributor)
|
||||
.distributes_order_variants?(self)
|
||||
|
||||
errors.add(:base, I18n.t(:spree_order_availability_error))
|
||||
end
|
||||
|
||||
# Determine if email is required (we don't want validation errors before we hit the checkout)
|
||||
def require_email
|
||||
true unless (new_record? || cart?) && !checkout_processing
|
||||
end
|
||||
|
||||
def ensure_line_items_present
|
||||
return if line_items.present?
|
||||
|
||||
errors.add(:base, Spree.t(:there_are_no_items_for_this_order))
|
||||
false
|
||||
end
|
||||
|
||||
def ensure_available_shipping_rates
|
||||
return unless shipments.empty? || shipments.any? { |shipment| shipment.shipping_rates.blank? }
|
||||
|
||||
errors.add(:base, Spree.t(:items_cannot_be_shipped))
|
||||
false
|
||||
end
|
||||
end
|
||||
@@ -1,6 +1,8 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class CoordinatorFee < ApplicationRecord
|
||||
self.belongs_to_required_by_default = true
|
||||
|
||||
belongs_to :order_cycle
|
||||
belongs_to :enterprise_fee
|
||||
end
|
||||
|
||||
@@ -2,4 +2,6 @@
|
||||
|
||||
class CustomTab < ApplicationRecord
|
||||
belongs_to :enterprise, optional: false
|
||||
|
||||
validates :title, presence: true, length: { maximum: 20 }
|
||||
end
|
||||
|
||||
@@ -10,20 +10,22 @@
|
||||
class Customer < ApplicationRecord
|
||||
include SetUnusedAddressFields
|
||||
|
||||
self.belongs_to_required_by_default = true
|
||||
|
||||
acts_as_taggable
|
||||
|
||||
searchable_attributes :first_name, :last_name, :email, :code
|
||||
|
||||
belongs_to :enterprise, optional: false
|
||||
belongs_to :user, class_name: "Spree::User"
|
||||
belongs_to :enterprise
|
||||
belongs_to :user, class_name: "Spree::User", optional: true
|
||||
has_many :orders, class_name: "Spree::Order"
|
||||
before_destroy :update_orders_and_delete_canceled_subscriptions
|
||||
|
||||
belongs_to :bill_address, class_name: "Spree::Address"
|
||||
belongs_to :bill_address, class_name: "Spree::Address", optional: true
|
||||
alias_attribute :billing_address, :bill_address
|
||||
accepts_nested_attributes_for :bill_address
|
||||
|
||||
belongs_to :ship_address, class_name: "Spree::Address"
|
||||
belongs_to :ship_address, class_name: "Spree::Address", optional: true
|
||||
alias_attribute :shipping_address, :ship_address
|
||||
accepts_nested_attributes_for :ship_address
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
class DistributorPaymentMethod < ApplicationRecord
|
||||
self.table_name = "distributors_payment_methods"
|
||||
self.belongs_to_required_by_default = true
|
||||
|
||||
belongs_to :payment_method, class_name: "Spree::PaymentMethod", touch: true
|
||||
belongs_to :distributor, class_name: "Enterprise", touch: true
|
||||
end
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
class DistributorShippingMethod < ApplicationRecord
|
||||
self.table_name = "distributors_shipping_methods"
|
||||
self.belongs_to_required_by_default = true
|
||||
|
||||
belongs_to :shipping_method, class_name: "Spree::ShippingMethod", touch: true
|
||||
belongs_to :distributor, class_name: "Enterprise", touch: true
|
||||
end
|
||||
|
||||
@@ -5,20 +5,9 @@ class Enterprise < ApplicationRecord
|
||||
ENTERPRISE_SEARCH_RADIUS = 100
|
||||
# The next Rails version will have named variants but we need to store them
|
||||
# ourselves for now.
|
||||
LOGO_SIZES = {
|
||||
thumb: { gravity: "Center", resize: "100x100^", crop: '100x100+0+0' },
|
||||
small: { gravity: "Center", resize: "180x180^", crop: '180x180+0+0' },
|
||||
medium: { gravity: "Center", resize: "300x300^", crop: '300x300+0+0' },
|
||||
}.freeze
|
||||
PROMO_IMAGE_SIZES = {
|
||||
thumb: { resize_to_limit: [100, 100] },
|
||||
medium: { resize_to_fill: [720, 156] },
|
||||
large: { resize_to_fill: [1200, 260] },
|
||||
}.freeze
|
||||
WHITE_LABEL_LOGO_SIZES = {
|
||||
default: { gravity: "Center", resize_to_fill: [217, 44] },
|
||||
mobile: { gravity: "Center", resize_to_fill: [75, 26] },
|
||||
}.freeze
|
||||
LOGO_SIZES = [:thumb, :small, :medium].freeze
|
||||
PROMO_IMAGE_SIZES = [:thumb, :medium, :large].freeze
|
||||
WHITE_LABEL_LOGO_SIZES = [:default, :mobile].freeze
|
||||
VALID_INSTAGRAM_REGEX = %r{\A[a-zA-Z0-9._]{1,30}([^/-]*)\z}
|
||||
|
||||
searchable_attributes :sells, :is_primary_producer, :name
|
||||
@@ -61,8 +50,10 @@ class Enterprise < ApplicationRecord
|
||||
has_many :users, through: :enterprise_roles
|
||||
belongs_to :owner, class_name: 'Spree::User',
|
||||
inverse_of: :owned_enterprises
|
||||
has_many :distributor_payment_methods, foreign_key: :distributor_id
|
||||
has_many :distributor_shipping_methods, foreign_key: :distributor_id
|
||||
has_many :distributor_payment_methods,
|
||||
inverse_of: :distributor, foreign_key: :distributor_id
|
||||
has_many :distributor_shipping_methods,
|
||||
inverse_of: :distributor, foreign_key: :distributor_id
|
||||
has_many :payment_methods, through: :distributor_payment_methods
|
||||
has_many :shipping_methods, through: :distributor_shipping_methods
|
||||
has_many :customers
|
||||
@@ -87,10 +78,21 @@ class Enterprise < ApplicationRecord
|
||||
}
|
||||
accepts_nested_attributes_for :custom_tab
|
||||
|
||||
has_one_attached :logo
|
||||
has_one_attached :promo_image
|
||||
has_one_attached :terms_and_conditions
|
||||
has_one_attached :white_label_logo
|
||||
has_one_attached :logo, service: image_service do |attachment|
|
||||
attachment.variant :thumb, resize_to_fill: [100, 100], crop: [0, 0, 100, 100]
|
||||
attachment.variant :small, resize_to_fill: [180, 180], crop: [0, 0, 180, 180]
|
||||
attachment.variant :medium, resize_to_fill: [300, 300], crop: [0, 0, 300, 300]
|
||||
end
|
||||
has_one_attached :promo_image, service: image_service do |attachment|
|
||||
attachment.variant :thumb, resize_to_limit: [100, 100]
|
||||
attachment.variant :medium, resize_to_fill: [720, 156]
|
||||
attachment.variant :large, resize_to_fill: [1200, 260]
|
||||
end
|
||||
has_one_attached :white_label_logo, service: image_service do |attachment|
|
||||
attachment.variant :default, resize_to_fill: [217, 44]
|
||||
attachment.variant :mobile, resize_to_fill: [75, 26]
|
||||
end
|
||||
|
||||
validates :logo,
|
||||
processable_image: true,
|
||||
@@ -117,6 +119,7 @@ class Enterprise < ApplicationRecord
|
||||
with: VALID_INSTAGRAM_REGEX,
|
||||
message: Spree.t('errors.messages.invalid_instagram_url')
|
||||
}, allow_blank: true
|
||||
validate :validate_white_label_logo_link
|
||||
|
||||
before_validation :initialize_permalink, if: lambda { permalink.nil? }
|
||||
before_validation :set_unused_address_fields
|
||||
@@ -157,7 +160,7 @@ class Enterprise < ApplicationRecord
|
||||
scope :is_distributor, -> { where('sells != ?', 'none') }
|
||||
scope :is_hub, -> { where(sells: 'any') }
|
||||
scope :supplying_variant_in, lambda { |variants|
|
||||
joins(supplied_products: :variants_including_master).
|
||||
joins(supplied_products: :variants).
|
||||
where('spree_variants.id IN (?)', variants).
|
||||
select('DISTINCT enterprises.*')
|
||||
}
|
||||
@@ -294,27 +297,15 @@ class Enterprise < ApplicationRecord
|
||||
end
|
||||
|
||||
def logo_url(name)
|
||||
return unless logo.variable?
|
||||
|
||||
Rails.application.routes.url_helpers.url_for(
|
||||
logo.variant(LOGO_SIZES[name])
|
||||
)
|
||||
image_url_for(logo, 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])
|
||||
)
|
||||
image_url_for(promo_image, name)
|
||||
end
|
||||
|
||||
def white_label_logo_url(name = :default)
|
||||
return unless white_label_logo.variable?
|
||||
|
||||
Rails.application.routes.url_helpers.url_for(
|
||||
white_label_logo.variant(WHITE_LABEL_LOGO_SIZES[name])
|
||||
)
|
||||
image_url_for(white_label_logo, name)
|
||||
end
|
||||
|
||||
def website
|
||||
@@ -398,7 +389,7 @@ class Enterprise < ApplicationRecord
|
||||
def current_distributed_taxons
|
||||
Spree::Taxon
|
||||
.select("DISTINCT spree_taxons.*")
|
||||
.joins(products: :variants_including_master)
|
||||
.joins(products: :variants)
|
||||
.joins("INNER JOIN (#{current_exchange_variants.to_sql}) \
|
||||
AS exchange_variants ON spree_variants.id = exchange_variants.variant_id")
|
||||
end
|
||||
@@ -454,6 +445,29 @@ class Enterprise < ApplicationRecord
|
||||
|
||||
private
|
||||
|
||||
def validate_white_label_logo_link
|
||||
return if white_label_logo.blank?
|
||||
|
||||
return if white_label_logo_link.blank?
|
||||
|
||||
white_label_logo_link.strip!
|
||||
uri = URI(white_label_logo_link)
|
||||
self.white_label_logo_link = "http://#{white_label_logo_link}" if uri.scheme.nil?
|
||||
rescue URI::InvalidURIError
|
||||
errors.add(:white_label_logo_link, I18n.t(:invalid_url))
|
||||
end
|
||||
|
||||
def image_url_for(image, name)
|
||||
return unless image.variable?
|
||||
return image.variant(name).processed.url if image.attachment.service.name == :amazon_public
|
||||
|
||||
url_for(image.variant(name))
|
||||
rescue ActiveStorage::Error => e
|
||||
Rails.logger.error(e.message)
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def current_exchange_variants
|
||||
ExchangeVariant.joins(exchange: :order_cycle)
|
||||
.merge(Exchange.outgoing)
|
||||
|
||||
@@ -25,8 +25,8 @@ class EnterpriseGroup < ApplicationRecord
|
||||
|
||||
delegate :phone, :address1, :address2, :city, :zipcode, :state, :country, to: :address
|
||||
|
||||
has_one_attached :logo
|
||||
has_one_attached :promo_image
|
||||
has_one_attached :logo, service: image_service
|
||||
has_one_attached :promo_image, service: image_service
|
||||
|
||||
validates :logo,
|
||||
processable_image: true,
|
||||
|
||||
@@ -55,7 +55,7 @@ class Exchange < ApplicationRecord
|
||||
}
|
||||
scope :with_product, lambda { |product|
|
||||
joins(:exchange_variants).
|
||||
where('exchange_variants.variant_id IN (?)', product.variants_including_master.select(&:id))
|
||||
where('exchange_variants.variant_id IN (?)', product.variants.select(&:id))
|
||||
}
|
||||
scope :by_enterprise_name, -> {
|
||||
joins('INNER JOIN enterprises AS sender ON (sender.id = exchanges.sender_id)').
|
||||
|
||||
@@ -55,7 +55,6 @@ module ProductImport
|
||||
VariantOverride.for_hubs([enterprise_id]).count
|
||||
else
|
||||
Spree::Variant.
|
||||
not_master.
|
||||
joins(:product).
|
||||
where('spree_products.supplier_id IN (?)', enterprise_id).
|
||||
count
|
||||
@@ -90,7 +89,8 @@ module ProductImport
|
||||
end
|
||||
|
||||
def total_saved_count
|
||||
@products_created + @variants_created + @variants_updated + @inventory_created + @inventory_updated
|
||||
[@products_created, @variants_created, @variants_updated,
|
||||
@inventory_created, @inventory_updated].sum
|
||||
end
|
||||
|
||||
def permission_by_id?(enterprise_id)
|
||||
|
||||
@@ -167,7 +167,7 @@ module ProductImport
|
||||
def unit_fields_validation(entry)
|
||||
unit_types = ['g', 'oz', 'lb', 'kg', 't', 'ml', 'l', 'kl', '']
|
||||
|
||||
unless entry.units&.present?
|
||||
if entry.units.blank?
|
||||
mark_as_invalid(entry, attribute: 'units',
|
||||
error: I18n.t('admin.product_import.model.blank'))
|
||||
end
|
||||
@@ -180,7 +180,7 @@ module ProductImport
|
||||
return if import_into_inventory?
|
||||
|
||||
# unit_type must be valid type
|
||||
if entry.unit_type&.present?
|
||||
if entry.unit_type.present?
|
||||
unit_type = entry.unit_type.to_s.strip.downcase
|
||||
unless unit_types.include?(unit_type)
|
||||
mark_as_invalid(entry, attribute: 'unit_type',
|
||||
@@ -190,7 +190,7 @@ module ProductImport
|
||||
end
|
||||
|
||||
# variant_unit_name must be present if unit_type not present
|
||||
return if entry.variant_unit_name&.present?
|
||||
return if entry.variant_unit_name.present?
|
||||
|
||||
mark_as_invalid(entry, attribute: 'variant_unit_name',
|
||||
error: I18n.t('admin.product_import.model.conditional_blank'))
|
||||
|
||||
@@ -233,6 +233,8 @@ module ProductImport
|
||||
def rows
|
||||
return [] unless @sheet&.last_row
|
||||
|
||||
@sheet.parse(clean: true)
|
||||
|
||||
(2..@sheet.last_row).map do |i|
|
||||
@sheet.row(i)
|
||||
end
|
||||
|
||||
@@ -2,14 +2,12 @@
|
||||
|
||||
module Spree
|
||||
class Image < Asset
|
||||
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
|
||||
has_one_attached :attachment, service: image_service do |attachment|
|
||||
attachment.variant :mini, resize_to_fill: [48, 48]
|
||||
attachment.variant :small, resize_to_fill: [227, 227]
|
||||
attachment.variant :product, resize_to_limit: [240, 240]
|
||||
attachment.variant :large, resize_to_limit: [600, 600]
|
||||
end
|
||||
|
||||
validates :attachment,
|
||||
attached: true,
|
||||
@@ -17,20 +15,33 @@ module Spree
|
||||
content_type: %r{\Aimage/(png|jpeg|gif|jpg|svg\+xml|webp)\Z}
|
||||
validate :no_attachment_errors
|
||||
|
||||
def self.default_image_url(size)
|
||||
return "/noimage/product.png" unless size&.to_sym.in?([:mini, :small, :product, :large])
|
||||
|
||||
"/noimage/#{size}.png"
|
||||
end
|
||||
|
||||
def variant(name)
|
||||
if attachment.variable?
|
||||
attachment.variant(SIZES[name])
|
||||
attachment.variant(name)
|
||||
else
|
||||
attachment
|
||||
end
|
||||
end
|
||||
|
||||
def url(size)
|
||||
return unless attachment.attached?
|
||||
return self.class.default_image_url(size) unless attachment.attached?
|
||||
return variant(size).processed.url if attachment.service.name == :amazon_public
|
||||
|
||||
Rails.application.routes.url_helpers.url_for(variant(size))
|
||||
url_for(variant(size))
|
||||
rescue ActiveStorage::Error => e
|
||||
Rails.logger.error(e.message)
|
||||
|
||||
self.class.default_image_url(size)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# if there are errors from the plugin, then add a more meaningful message
|
||||
def no_attachment_errors
|
||||
return if errors[:attachment].empty?
|
||||
|
||||
@@ -8,6 +8,7 @@ require 'open_food_network/tag_rule_applicator'
|
||||
module Spree
|
||||
class Order < ApplicationRecord
|
||||
include OrderShipment
|
||||
include OrderValidations
|
||||
include Checkout
|
||||
include Balance
|
||||
include SetUnusedAddressFields
|
||||
@@ -24,9 +25,7 @@ module Spree
|
||||
order.update_totals
|
||||
order.payment_required?
|
||||
}
|
||||
go_to_state :confirmation, if: ->(order) {
|
||||
OpenFoodNetwork::FeatureToggle.enabled? :split_checkout, order.created_by
|
||||
}
|
||||
go_to_state :confirmation
|
||||
go_to_state :complete
|
||||
end
|
||||
|
||||
@@ -83,13 +82,13 @@ module Spree
|
||||
accepts_nested_attributes_for :shipments
|
||||
|
||||
delegate :admin_and_handling_total, :payment_fee, :ship_total, to: :adjustments_fetcher
|
||||
delegate :update_totals, to: :updater
|
||||
delegate :update_totals, :update_totals_and_states, to: :updater
|
||||
delegate :create_line_item_fees!, :create_order_fees!, :update_order_fees!,
|
||||
:update_line_item_fees!, :recreate_all_fees!, to: :fee_handler
|
||||
|
||||
# Needs to happen before save_permalink is called
|
||||
before_validation :set_currency
|
||||
before_validation :generate_order_number, on: :create
|
||||
before_validation :generate_order_number, if: :new_record?
|
||||
before_validation :clone_billing_address, if: :use_billing?
|
||||
before_validation :ensure_customer
|
||||
|
||||
@@ -104,8 +103,9 @@ module Spree
|
||||
validates :email, presence: true,
|
||||
format: /\A([\w.%+\-']+)@([\w\-]+\.)+(\w{2,})\z/i,
|
||||
if: :require_email
|
||||
validates :order_cycle, presence: true, on: :set_distribution_step
|
||||
validates :distributor, presence: true, on: :set_distribution_step
|
||||
|
||||
validates :order_cycle, presence: true, on: :require_distribution
|
||||
validates :distributor, presence: true, on: :require_distribution
|
||||
|
||||
make_permalink field: :number
|
||||
|
||||
@@ -290,8 +290,9 @@ module Spree
|
||||
created_by_id: created_by_id)
|
||||
end
|
||||
|
||||
# FIXME refactor this method and implement validation using validates_* utilities
|
||||
def generate_order_number
|
||||
return if number.present?
|
||||
|
||||
record = true
|
||||
while record
|
||||
random = "R#{Array.new(9){ rand(9) }.join}"
|
||||
@@ -301,10 +302,6 @@ module Spree
|
||||
number
|
||||
end
|
||||
|
||||
def shipped_shipments
|
||||
shipments.shipped
|
||||
end
|
||||
|
||||
def contains?(variant)
|
||||
find_line_item_by_variant(variant).present?
|
||||
end
|
||||
@@ -320,8 +317,7 @@ module Spree
|
||||
# Creates new tax charges if there are any applicable rates. If prices already
|
||||
# include taxes then price adjustments are created instead.
|
||||
def create_tax_charge!
|
||||
return if state.in?(["cart", "address", "delivery"]) &&
|
||||
OpenFoodNetwork::FeatureToggle.enabled?(:split_checkout)
|
||||
return if state.in?(["cart", "address", "delivery"])
|
||||
|
||||
clear_legacy_taxes!
|
||||
|
||||
@@ -341,11 +337,6 @@ module Spree
|
||||
complete? || resumed? || awaiting_return? || returned?
|
||||
end
|
||||
|
||||
def credit_cards
|
||||
credit_card_ids = payments.from_credit_card.pluck(:source_id).uniq
|
||||
CreditCard.where(id: credit_card_ids)
|
||||
end
|
||||
|
||||
# Finalizes an in progress order after checkout is complete.
|
||||
# Called after transition to complete state when payments will have been processed
|
||||
def finalize!
|
||||
@@ -374,13 +365,6 @@ module Spree
|
||||
)
|
||||
end
|
||||
|
||||
def deliver_order_confirmation_email
|
||||
return if subscription.present?
|
||||
|
||||
Spree::OrderMailer.confirm_email_for_customer(id).deliver_later(wait: 10.seconds)
|
||||
Spree::OrderMailer.confirm_email_for_shop(id).deliver_later(wait: 10.seconds)
|
||||
end
|
||||
|
||||
# Helper methods for checkout steps
|
||||
def paid?
|
||||
payment_state == 'paid' || payment_state == 'credit_owed'
|
||||
@@ -442,19 +426,6 @@ module Spree
|
||||
restart_checkout_flow if state.in?(["payment", "confirmation"])
|
||||
end
|
||||
|
||||
def state_changed(name)
|
||||
state = "#{name}_state"
|
||||
return unless persisted?
|
||||
|
||||
old_state = __send__("#{state}_was")
|
||||
state_changes.create(
|
||||
previous_state: old_state,
|
||||
next_state: __send__(state),
|
||||
name: name,
|
||||
user_id: user_id
|
||||
)
|
||||
end
|
||||
|
||||
def shipped?
|
||||
%w(partial shipped).include?(shipment_state)
|
||||
end
|
||||
@@ -508,24 +479,6 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
def refresh_shipment_rates
|
||||
shipments.map(&:refresh_rates)
|
||||
end
|
||||
|
||||
# Check that line_items in the current order are available from a newly selected distribution
|
||||
def products_available_from_new_distribution
|
||||
return if OrderCycleDistributedVariants.new(order_cycle, distributor)
|
||||
.distributes_order_variants?(self)
|
||||
|
||||
errors.add(:base, I18n.t(:spree_order_availability_error))
|
||||
end
|
||||
|
||||
def disallow_guest_order
|
||||
return unless using_guest_checkout? && registered_email?
|
||||
|
||||
errors.add(:email, I18n.t('devise.failure.already_registered'))
|
||||
end
|
||||
|
||||
# After changing line items of a completed order
|
||||
def update_shipping_fees!
|
||||
shipments.each do |shipment|
|
||||
@@ -587,10 +540,6 @@ module Spree
|
||||
save!
|
||||
end
|
||||
|
||||
def distribution_set?
|
||||
distributor && order_cycle
|
||||
end
|
||||
|
||||
def shipping_tax
|
||||
shipment_adjustments.reload.tax.sum(:amount)
|
||||
end
|
||||
@@ -627,6 +576,13 @@ module Spree
|
||||
|
||||
private
|
||||
|
||||
def deliver_order_confirmation_email
|
||||
return if subscription.present?
|
||||
|
||||
Spree::OrderMailer.confirm_email_for_customer(id).deliver_later(wait: 10.seconds)
|
||||
Spree::OrderMailer.confirm_email_for_shop(id).deliver_later(wait: 10.seconds)
|
||||
end
|
||||
|
||||
def fee_handler
|
||||
@fee_handler ||= OrderFeesHandler.new(self)
|
||||
end
|
||||
@@ -656,38 +612,6 @@ module Spree
|
||||
self.email = user.email if user
|
||||
end
|
||||
|
||||
# Determine if email is required (we don't want validation errors before we hit the checkout)
|
||||
def require_email
|
||||
return true unless (new_record? || cart?) && !checkout_processing
|
||||
end
|
||||
|
||||
def ensure_line_items_present
|
||||
return if line_items.present?
|
||||
|
||||
errors.add(:base, Spree.t(:there_are_no_items_for_this_order)) && (return false)
|
||||
end
|
||||
|
||||
def ensure_available_shipping_rates
|
||||
return unless shipments.empty? || shipments.any? { |shipment| shipment.shipping_rates.blank? }
|
||||
|
||||
errors.add(:base, Spree.t(:items_cannot_be_shipped)) && (return false)
|
||||
end
|
||||
|
||||
def after_cancel
|
||||
shipments.each(&:cancel!)
|
||||
payments.checkout.each(&:void!)
|
||||
|
||||
OrderMailer.cancel_email(id).deliver_later if send_cancellation_email
|
||||
update(payment_state: updater.update_payment_state)
|
||||
end
|
||||
|
||||
def after_resume
|
||||
shipments.each(&:resume!)
|
||||
payments.void.each(&:resume!)
|
||||
|
||||
update(payment_state: updater.update_payment_state)
|
||||
end
|
||||
|
||||
def use_billing?
|
||||
@use_billing == true || @use_billing == 'true' || @use_billing == '1'
|
||||
end
|
||||
@@ -725,7 +649,7 @@ module Spree
|
||||
return if adjustment.finalized?
|
||||
|
||||
adjustment.update_adjustment!(force: true)
|
||||
updater.update_totals_and_states
|
||||
update_totals_and_states
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -75,9 +75,9 @@ module Spree
|
||||
|
||||
before_transition to: :delivery, do: :create_proposed_shipments
|
||||
before_transition to: :delivery, do: :ensure_available_shipping_rates
|
||||
before_transition to: :payment, do: :create_tax_charge!
|
||||
before_transition to: :confirmation, do: :validate_payment_method!
|
||||
|
||||
after_transition to: :payment, do: :create_tax_charge!
|
||||
after_transition to: :complete, do: :finalize!
|
||||
after_transition to: :resumed, do: :after_resume
|
||||
after_transition to: :canceled, do: :after_cancel
|
||||
@@ -96,14 +96,6 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
def self.find_transition(options = {})
|
||||
return nil if options.nil? || !options.include?(:from) || !options.include?(:to)
|
||||
|
||||
next_event_transitions.detect do |transition|
|
||||
transition[options[:from].to_sym] == options[:to].to_sym
|
||||
end
|
||||
end
|
||||
|
||||
def self.next_event_transitions
|
||||
@next_event_transitions ||= []
|
||||
end
|
||||
@@ -136,8 +128,36 @@ module Spree
|
||||
)
|
||||
end
|
||||
|
||||
def state_changed(name)
|
||||
state = "#{name}_state"
|
||||
return unless persisted?
|
||||
|
||||
old_state = __send__("#{state}_was")
|
||||
state_changes.create(
|
||||
previous_state: old_state,
|
||||
next_state: __send__(state),
|
||||
name: name,
|
||||
user_id: user_id
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def after_cancel
|
||||
shipments.each(&:cancel!)
|
||||
payments.checkout.each(&:void!)
|
||||
|
||||
OrderMailer.cancel_email(id).deliver_later if send_cancellation_email
|
||||
update(payment_state: updater.update_payment_state)
|
||||
end
|
||||
|
||||
def after_resume
|
||||
shipments.each(&:resume!)
|
||||
payments.void.each(&:resume!)
|
||||
|
||||
update(payment_state: updater.update_payment_state)
|
||||
end
|
||||
|
||||
def validate_payment_method!
|
||||
return unless checkout_processing
|
||||
return if payments.any?
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "spree/localized_number"
|
||||
|
||||
module Spree
|
||||
class Payment < ApplicationRecord
|
||||
include Spree::Payment::Processing
|
||||
|
||||
@@ -50,9 +50,9 @@ module Spree
|
||||
scope :by_name, -> { order('spree_payment_methods.name ASC') }
|
||||
|
||||
scope :available, lambda { |display_on = 'both'|
|
||||
where(active: true).
|
||||
where('spree_payment_methods.display_on=? OR spree_payment_methods.display_on=? OR spree_payment_methods.display_on IS NULL', display_on, '').
|
||||
where('spree_payment_methods.environment=? OR spree_payment_methods.environment=? OR spree_payment_methods.environment IS NULL', Rails.env, '')
|
||||
where(active: true)
|
||||
.where(display_on: [display_on, "", nil])
|
||||
.where(environment: [Rails.env, "", nil])
|
||||
}
|
||||
|
||||
def self.providers
|
||||
|
||||
@@ -28,42 +28,73 @@ module Spree
|
||||
|
||||
acts_as_paranoid
|
||||
|
||||
searchable_attributes :supplier_id, :primary_taxon_id, :meta_keywords
|
||||
searchable_associations :supplier, :properties, :primary_taxon, :variants, :master
|
||||
searchable_attributes :supplier_id, :primary_taxon_id, :meta_keywords, :sku
|
||||
searchable_associations :supplier, :properties, :primary_taxon, :variants
|
||||
searchable_scopes :active, :with_properties
|
||||
|
||||
has_many :product_properties, dependent: :destroy
|
||||
has_many :properties, through: :product_properties
|
||||
|
||||
has_many :classifications, dependent: :delete_all
|
||||
has_many :taxons, through: :classifications
|
||||
|
||||
belongs_to :tax_category, class_name: 'Spree::TaxCategory'
|
||||
belongs_to :shipping_category, class_name: 'Spree::ShippingCategory'
|
||||
belongs_to :supplier, class_name: 'Enterprise', touch: true
|
||||
belongs_to :primary_taxon, class_name: 'Spree::Taxon', touch: true
|
||||
|
||||
has_one :master,
|
||||
-> { where is_master: true },
|
||||
class_name: 'Spree::Variant',
|
||||
dependent: :destroy
|
||||
has_one :image, class_name: "Spree::Image", as: :viewable, dependent: :destroy
|
||||
|
||||
has_many :variants, -> {
|
||||
where(is_master: false).order("spree_variants.position ASC")
|
||||
}, class_name: 'Spree::Variant'
|
||||
|
||||
has_many :variants_including_master,
|
||||
-> { order("spree_variants.position ASC") },
|
||||
class_name: 'Spree::Variant',
|
||||
dependent: :destroy
|
||||
has_many :product_properties, dependent: :destroy
|
||||
has_many :properties, through: :product_properties
|
||||
has_many :classifications, dependent: :delete_all
|
||||
has_many :taxons, through: :classifications
|
||||
has_many :variants, -> { order("spree_variants.position ASC") }, class_name: 'Spree::Variant',
|
||||
dependent: :destroy
|
||||
|
||||
has_many :prices, -> {
|
||||
order('spree_variants.position, spree_variants.id, currency')
|
||||
}, through: :variants
|
||||
|
||||
has_many :stock_items, through: :variants
|
||||
|
||||
has_many :supplier_properties, through: :supplier, source: :properties
|
||||
has_many :variant_images, -> { order(:position) }, source: :images,
|
||||
through: :variants
|
||||
|
||||
validates :name, presence: true
|
||||
validates :permalink, presence: true
|
||||
validates :shipping_category, presence: true
|
||||
|
||||
validates :supplier, presence: true
|
||||
validates :primary_taxon, presence: true
|
||||
validates :tax_category, presence: true,
|
||||
if: proc { Spree::Config[:products_require_tax_category] }
|
||||
|
||||
validates :variant_unit, presence: true
|
||||
validates :unit_value, presence:
|
||||
{ if: ->(p) { %w(weight volume).include?(p.variant_unit) && new_record? } }
|
||||
validates :variant_unit_scale,
|
||||
presence: { if: ->(p) { %w(weight volume).include? p.variant_unit } }
|
||||
validates :variant_unit_name,
|
||||
presence: { if: ->(p) { p.variant_unit == 'items' } }
|
||||
validate :validate_image
|
||||
|
||||
accepts_nested_attributes_for :variants, allow_destroy: true
|
||||
accepts_nested_attributes_for :image
|
||||
accepts_nested_attributes_for :product_properties,
|
||||
allow_destroy: true,
|
||||
reject_if: lambda { |pp| pp[:property_name].blank? }
|
||||
|
||||
# Transient attributes used temporarily when creating a new product,
|
||||
# these values are persisted on the product's variant
|
||||
attr_accessor :price, :display_as, :unit_value, :unit_description
|
||||
|
||||
make_permalink order: :name
|
||||
|
||||
after_initialize :set_available_on_to_now, if: :new_record?
|
||||
|
||||
before_validation :sanitize_permalink
|
||||
|
||||
before_save :add_primary_taxon_to_taxons
|
||||
before_destroy :punch_permalink
|
||||
|
||||
after_save :remove_previous_primary_taxon_from_taxons
|
||||
after_create :ensure_standard_variant
|
||||
after_save :update_units
|
||||
|
||||
scope :with_properties, ->(*property_ids) {
|
||||
left_outer_joins(:product_properties).
|
||||
@@ -75,58 +106,6 @@ module Spree
|
||||
)
|
||||
}
|
||||
|
||||
delegate_belongs_to :master, :sku, :price, :currency, :display_amount, :display_price, :weight,
|
||||
:height, :width, :depth, :is_master, :cost_currency,
|
||||
:price_in, :amount_in, :unit_value, :unit_description
|
||||
delegate :images_attributes=, :display_as=, to: :master
|
||||
|
||||
after_create :set_master_variant_defaults
|
||||
after_save :save_master
|
||||
|
||||
delegate :images, to: :master, prefix: true
|
||||
alias_method :images, :master_images
|
||||
|
||||
has_many :variant_images, -> { order(:position) }, source: :images,
|
||||
through: :variants_including_master
|
||||
|
||||
accepts_nested_attributes_for :variants, allow_destroy: true
|
||||
|
||||
validates :name, presence: true
|
||||
validates :permalink, presence: true
|
||||
validates :price, presence: true, if: proc { Spree::Config[:require_master_price] }
|
||||
validates :shipping_category, presence: true
|
||||
|
||||
validates :supplier, presence: true
|
||||
validates :primary_taxon, presence: true
|
||||
validates :tax_category, presence: true,
|
||||
if: proc { Spree::Config[:products_require_tax_category] }
|
||||
|
||||
validates :variant_unit, presence: true
|
||||
validates :unit_value, presence: { if: ->(p) { %w(weight volume).include? p.variant_unit } }
|
||||
validates :variant_unit_scale,
|
||||
presence: { if: ->(p) { %w(weight volume).include? p.variant_unit } }
|
||||
validates :variant_unit_name,
|
||||
presence: { if: ->(p) { p.variant_unit == 'items' } }
|
||||
validate :validate_image_for_master
|
||||
|
||||
accepts_nested_attributes_for :product_properties,
|
||||
allow_destroy: true,
|
||||
reject_if: lambda { |pp| pp[:property_name].blank? }
|
||||
|
||||
make_permalink order: :name
|
||||
|
||||
after_initialize :ensure_master
|
||||
after_initialize :set_available_on_to_now, if: :new_record?
|
||||
|
||||
before_validation :sanitize_permalink
|
||||
before_save :add_primary_taxon_to_taxons
|
||||
after_save :remove_previous_primary_taxon_from_taxons
|
||||
after_save :ensure_standard_variant
|
||||
after_save :update_units
|
||||
|
||||
before_destroy :punch_permalink
|
||||
|
||||
# -- Joins
|
||||
scope :with_order_cycles_outer, -> {
|
||||
joins("
|
||||
LEFT OUTER JOIN spree_variants AS o_spree_variants
|
||||
@@ -150,7 +129,7 @@ module Spree
|
||||
}
|
||||
|
||||
scope :with_order_cycles_inner, -> {
|
||||
joins(variants_including_master: { exchanges: :order_cycle })
|
||||
joins(variants: { exchanges: :order_cycle })
|
||||
}
|
||||
|
||||
scope :visible_for, lambda { |enterprise|
|
||||
@@ -283,13 +262,6 @@ module Spree
|
||||
stock_items.sum(&:count_on_hand)
|
||||
end
|
||||
|
||||
# Master variant may be deleted (i.e. when the product is deleted)
|
||||
# which would make AR's default finder return nil.
|
||||
# This is a stopgap for that little problem.
|
||||
def master
|
||||
super || variants_including_master.with_deleted.find_by(is_master: true)
|
||||
end
|
||||
|
||||
def properties_including_inherited
|
||||
# Product properties override producer properties
|
||||
ps = product_properties.all
|
||||
@@ -325,7 +297,7 @@ module Spree
|
||||
touch_distributors
|
||||
|
||||
ExchangeVariant.
|
||||
where('exchange_variants.variant_id IN (?)', variants_including_master.with_deleted.
|
||||
where('exchange_variants.variant_id IN (?)', variants.with_deleted.
|
||||
select(:id)).destroy_all
|
||||
|
||||
super
|
||||
@@ -334,39 +306,6 @@ module Spree
|
||||
|
||||
private
|
||||
|
||||
# ensures the master variant is flagged as such
|
||||
def set_master_variant_defaults
|
||||
master.is_master = true
|
||||
end
|
||||
|
||||
# Here we rescue errors when saving master variants (without the need for a
|
||||
# validates_associated on master) and we get more specific data about the errors
|
||||
def save_master
|
||||
if master && (
|
||||
master.changed? || master.new_record? || (
|
||||
master.default_price && (
|
||||
master.default_price.changed? || master.default_price.new_record?
|
||||
)
|
||||
)
|
||||
)
|
||||
master.save!
|
||||
end
|
||||
|
||||
# If the master cannot be saved, the Product object will get its errors
|
||||
# and will be destroyed
|
||||
rescue ActiveRecord::RecordInvalid
|
||||
master.errors.each do |error|
|
||||
errors.add error.attribute, error.message
|
||||
end
|
||||
raise
|
||||
end
|
||||
|
||||
def ensure_master
|
||||
return unless new_record?
|
||||
|
||||
self.master ||= Variant.new
|
||||
end
|
||||
|
||||
def punch_permalink
|
||||
# Punch permalink with date prefix
|
||||
update_attribute :permalink, "#{Time.now.to_i}_#{permalink}"
|
||||
@@ -379,7 +318,7 @@ module Spree
|
||||
def update_units
|
||||
return unless saved_change_to_variant_unit? || saved_change_to_variant_unit_name?
|
||||
|
||||
variants_including_master.each(&:update_units)
|
||||
variants.each(&:update_units)
|
||||
end
|
||||
|
||||
def touch_distributors
|
||||
@@ -397,11 +336,14 @@ module Spree
|
||||
end
|
||||
|
||||
def ensure_standard_variant
|
||||
return unless master.valid? && variants.empty?
|
||||
return unless variants.empty?
|
||||
|
||||
variant = master.dup
|
||||
variant = Spree::Variant.new
|
||||
variant.product = self
|
||||
variant.is_master = false
|
||||
variant.price = price
|
||||
variant.display_as = display_as
|
||||
variant.unit_value = unit_value
|
||||
variant.unit_description = unit_description
|
||||
variants << variant
|
||||
end
|
||||
|
||||
@@ -413,8 +355,8 @@ module Spree
|
||||
self.permalink = create_unique_permalink(requested.parameterize)
|
||||
end
|
||||
|
||||
def validate_image_for_master
|
||||
return if master.images.all?(&:valid?)
|
||||
def validate_image
|
||||
return if image.blank? || image.valid?
|
||||
|
||||
errors.add(:base, I18n.t('spree.admin.products.image_not_processable'))
|
||||
end
|
||||
|
||||
@@ -63,7 +63,7 @@ module Spree
|
||||
end
|
||||
|
||||
def returnable_inventory
|
||||
order.shipped_shipments.collect{ |s| s.inventory_units.to_a }.flatten
|
||||
order.shipments.shipped.collect{ |s| s.inventory_units.to_a }.flatten
|
||||
end
|
||||
|
||||
# Used when Adjustment#update_adjustment! wants to update the related adjustment
|
||||
@@ -74,7 +74,7 @@ module Spree
|
||||
private
|
||||
|
||||
def must_have_shipped_units
|
||||
return unless order.nil? || order.shipped_shipments.none?
|
||||
return unless order.nil? || order.shipments.shipped.none?
|
||||
|
||||
errors.add(:order, Spree.t(:has_no_shipped_units))
|
||||
end
|
||||
|
||||
@@ -8,6 +8,8 @@ module Spree
|
||||
back_end: "back_end"
|
||||
}.freeze
|
||||
|
||||
self.belongs_to_required_by_default = true
|
||||
|
||||
acts_as_paranoid
|
||||
acts_as_taggable
|
||||
|
||||
@@ -25,7 +27,7 @@ module Spree
|
||||
has_and_belongs_to_many :zones, join_table: 'spree_shipping_methods_zones',
|
||||
class_name: 'Spree::Zone'
|
||||
|
||||
belongs_to :tax_category, class_name: 'Spree::TaxCategory'
|
||||
belongs_to :tax_category, class_name: 'Spree::TaxCategory', optional: true
|
||||
|
||||
validates :name, presence: true
|
||||
validate :distributor_validation
|
||||
|
||||
@@ -79,7 +79,7 @@ module Spree
|
||||
|
||||
taxons = Spree::Taxon
|
||||
.select("DISTINCT spree_taxons.id, ents_and_vars.enterprise_id")
|
||||
.joins(products: :variants_including_master)
|
||||
.joins(products: :variants)
|
||||
.joins("
|
||||
INNER JOIN (#{ents_and_vars.to_sql}) AS ents_and_vars
|
||||
ON spree_variants.id = ents_and_vars.variant_id")
|
||||
|
||||
@@ -13,6 +13,8 @@ module Spree
|
||||
|
||||
acts_as_paranoid
|
||||
|
||||
self.ignored_columns = [:is_master]
|
||||
|
||||
searchable_attributes :sku, :display_as, :display_name
|
||||
searchable_associations :product, :default_price
|
||||
searchable_scopes :active, :deleted
|
||||
@@ -53,10 +55,9 @@ module Spree
|
||||
|
||||
localize_number :price, :weight
|
||||
|
||||
validate :check_price
|
||||
validate :check_currency
|
||||
validates :price, numericality: { greater_than_or_equal_to: 0 },
|
||||
presence: true,
|
||||
if: proc { Spree::Config[:require_master_price] }
|
||||
presence: true
|
||||
|
||||
validates :unit_value, presence: true, if: ->(variant) {
|
||||
%w(weight volume).include?(variant.product&.variant_unit)
|
||||
@@ -89,7 +90,6 @@ module Spree
|
||||
|
||||
scope :with_order_cycles_inner, -> { joins(exchanges: :order_cycle) }
|
||||
|
||||
scope :not_master, -> { where(is_master: false) }
|
||||
scope :in_order_cycle, lambda { |order_cycle|
|
||||
with_order_cycles_inner.
|
||||
merge(Exchange.outgoing).
|
||||
@@ -198,15 +198,7 @@ module Spree
|
||||
|
||||
private
|
||||
|
||||
# Ensures a new variant takes the product master price when price is not supplied
|
||||
def check_price
|
||||
if price.nil? && Spree::Config[:require_master_price]
|
||||
raise 'No master variant found to infer price' unless product&.master
|
||||
raise 'Must supply price for variant or master.price for product.' if self == product.master
|
||||
|
||||
self.price = product.master.price
|
||||
end
|
||||
|
||||
def check_currency
|
||||
return unless currency.nil?
|
||||
|
||||
self.currency = Spree::Config[:currency]
|
||||
|
||||
@@ -96,9 +96,9 @@ module Api
|
||||
def attachment_urls(attachment, styles)
|
||||
return unless attachment.variable?
|
||||
|
||||
styles.transform_values do |transformation|
|
||||
styles.index_with do |style|
|
||||
Rails.application.routes.url_helpers.
|
||||
url_for(attachment.variant(transformation))
|
||||
url_for(attachment.variant(style))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,18 +4,14 @@ module Api
|
||||
module Admin
|
||||
module ForOrderCycle
|
||||
class SuppliedProductSerializer < ActiveModel::Serializer
|
||||
attributes :name, :supplier_name, :image_url, :master_id, :variants
|
||||
attributes :name, :supplier_name, :image_url, :variants
|
||||
|
||||
def supplier_name
|
||||
object.supplier&.name
|
||||
end
|
||||
|
||||
def image_url
|
||||
object.images.first&.url(:mini)
|
||||
end
|
||||
|
||||
def master_id
|
||||
object.master.id
|
||||
object.image&.url(:mini)
|
||||
end
|
||||
|
||||
def variants
|
||||
|
||||
@@ -5,7 +5,7 @@ module Api
|
||||
class ProductSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name, :sku, :variant_unit, :variant_unit_scale, :variant_unit_name,
|
||||
:inherits_properties, :on_hand, :price, :available_on, :permalink_live,
|
||||
:tax_category_id, :import_date, :image_url, :thumb_url, :variants, :master
|
||||
:tax_category_id, :import_date, :image_url, :thumb_url, :variants
|
||||
|
||||
has_one :supplier, key: :producer_id, embed: :id
|
||||
has_one :primary_taxon, key: :category_id, embed: :id
|
||||
@@ -19,19 +19,12 @@ module Api
|
||||
)
|
||||
end
|
||||
|
||||
def master
|
||||
Api::Admin::VariantSerializer.new(
|
||||
object.master,
|
||||
image: thumb_url
|
||||
)
|
||||
end
|
||||
|
||||
def image_url
|
||||
object.images.first&.url(:product) || "/noimage/product.png"
|
||||
object.image&.url(:product) || Spree::Image.default_image_url(:product)
|
||||
end
|
||||
|
||||
def thumb_url
|
||||
object.images.first&.url(:mini) || "/noimage/mini.png"
|
||||
object.image&.url(:mini) || Spree::Image.default_image_url(:mini)
|
||||
end
|
||||
|
||||
def on_hand
|
||||
|
||||
@@ -15,9 +15,12 @@ module Api
|
||||
end
|
||||
|
||||
def in_open_and_upcoming_order_cycles
|
||||
OrderManagement::Subscriptions::VariantsList.in_open_and_upcoming_order_cycles?(option_or_assigned_shop,
|
||||
option_or_assigned_schedule,
|
||||
object.variant)
|
||||
OrderManagement::Subscriptions::VariantsList
|
||||
.in_open_and_upcoming_order_cycles?(
|
||||
option_or_assigned_shop,
|
||||
option_or_assigned_schedule,
|
||||
object.variant
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -33,7 +33,7 @@ module Api
|
||||
end
|
||||
|
||||
def image
|
||||
options[:image] || object.product.images.first&.url(:mini)
|
||||
options[:image] || object.product.image&.url(:mini)
|
||||
end
|
||||
|
||||
def in_stock
|
||||
|
||||
@@ -12,7 +12,7 @@ class Api::ProductSerializer < ActiveModel::Serializer
|
||||
has_one :primary_taxon, serializer: Api::TaxonSerializer
|
||||
has_many :taxons, serializer: Api::IdSerializer
|
||||
|
||||
has_many :images, serializer: Api::ImageSerializer
|
||||
has_one :image, serializer: Api::ImageSerializer
|
||||
has_one :supplier, serializer: Api::IdSerializer
|
||||
|
||||
# return an unformatted descripton
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
class Api::VariantSerializer < ActiveModel::Serializer
|
||||
attributes :id, :is_master, :product_name, :sku,
|
||||
attributes :id, :product_name, :sku,
|
||||
:options_text, :unit_value, :unit_description, :unit_to_display,
|
||||
:display_as, :display_name, :name_to_display,
|
||||
:price, :on_demand, :on_hand,
|
||||
@@ -40,7 +40,7 @@ class Api::VariantSerializer < ActiveModel::Serializer
|
||||
end
|
||||
|
||||
def thumb_url
|
||||
object.product.images.first&.url(:mini) || "/noimage/mini.png"
|
||||
object.product.image&.url(:mini) || Spree::Image.default_image_url(:mini)
|
||||
end
|
||||
|
||||
def unit_price_price
|
||||
|
||||
@@ -19,7 +19,7 @@ class CacheService
|
||||
# Gets the :updated_at value of the most recently updated record for a given class, and returns
|
||||
# it as a timestamp, eg: `1583836069`.
|
||||
def self.latest_timestamp_by_class(cached_class)
|
||||
cached_class.maximum(:updated_at).to_i
|
||||
cached_class.maximum(:updated_at).to_f
|
||||
end
|
||||
|
||||
def self.home_stats(statistic, &block)
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
# Adapts checkout form data (params) so that the order can be directly saved to the database
|
||||
module Checkout
|
||||
class FormDataAdapter
|
||||
attr_reader :params, :shipping_method_id
|
||||
|
||||
def initialize(params, order, current_user)
|
||||
@params = params.deep_dup.to_h.with_indifferent_access
|
||||
@order = order
|
||||
@current_user = current_user
|
||||
|
||||
move_payment_source_to_payment_attributes!
|
||||
|
||||
fill_in_card_type
|
||||
|
||||
set_amount_in_payments_attributes
|
||||
|
||||
construct_saved_card_attributes if @params.dig(:order, :existing_card_id)
|
||||
|
||||
@shipping_method_id = @params[:order]&.delete(:shipping_method_id)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# For payment step, filter order parameters to produce the expected
|
||||
# nested attributes for a single payment and its source,
|
||||
# discarding attributes for payment methods other than the one selected
|
||||
def move_payment_source_to_payment_attributes!
|
||||
return unless @params[:payment_source].present? &&
|
||||
payment_source_params = delete_payment_source_params!
|
||||
|
||||
@params.dig(:order, :payments_attributes).first[:source_attributes] = payment_source_params
|
||||
end
|
||||
|
||||
# Ensures cc_type is always passed to the model by inferring the type when
|
||||
# the frontend didn't provide it.
|
||||
def fill_in_card_type
|
||||
return unless payment_source_attributes
|
||||
|
||||
return if payment_source_attributes.dig(:number).blank?
|
||||
|
||||
payment_source_attributes[:cc_type] ||= card_brand(payment_source_attributes[:number])
|
||||
end
|
||||
|
||||
def payment_source_attributes
|
||||
@payment_source_attributes ||=
|
||||
@params.dig(:order, :payments_attributes)&.first&.dig(:source_attributes)
|
||||
end
|
||||
|
||||
def card_brand(number)
|
||||
ActiveMerchant::Billing::CreditCard.brand?(number)
|
||||
end
|
||||
|
||||
def delete_payment_source_params!
|
||||
@params.delete(:payment_source)[
|
||||
@params.dig(:order, :payments_attributes).first[:payment_method_id].underscore
|
||||
]
|
||||
end
|
||||
|
||||
def set_amount_in_payments_attributes
|
||||
return unless @params.dig(:order, :payments_attributes)
|
||||
|
||||
@params.dig(:order, :payments_attributes).first[:amount] = @order.total
|
||||
end
|
||||
|
||||
def construct_saved_card_attributes
|
||||
existing_card_id = @params[:order].delete(:existing_card_id)
|
||||
return if existing_card_id.blank?
|
||||
|
||||
add_to_payment_attributes(existing_card_id)
|
||||
|
||||
@params.dig(:order, :payments_attributes).first.delete :source_attributes
|
||||
end
|
||||
|
||||
def add_to_payment_attributes(existing_card_id)
|
||||
credit_card = Spree::CreditCard.find(existing_card_id)
|
||||
if credit_card.try(:user_id).blank? || credit_card.user_id != @current_user.try(:id)
|
||||
raise Spree::Core::GatewayError, I18n.t(:invalid_credit_card)
|
||||
end
|
||||
|
||||
@params.dig(:order, :payments_attributes).first[:source] = credit_card
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -30,7 +30,9 @@ module Checkout
|
||||
def set_customer_terms_and_conditions_accepted_at(params)
|
||||
return unless params[:order]
|
||||
|
||||
@order.customer.update(terms_and_conditions_accepted_at: Time.zone.now) if params[:order][:terms_and_conditions_accepted]
|
||||
return unless params[:order][:terms_and_conditions_accepted]
|
||||
|
||||
@order.customer.update(terms_and_conditions_accepted_at: Time.zone.now)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -18,7 +18,6 @@ class ExchangeProductsRenderer
|
||||
|
||||
def exchange_variants(incoming, enterprise)
|
||||
variants_relation = Spree::Variant.
|
||||
not_master.
|
||||
where(product_id: exchange_products(incoming, enterprise).select(&:id))
|
||||
|
||||
filter_visible(variants_relation)
|
||||
@@ -96,7 +95,7 @@ class ExchangeProductsRenderer
|
||||
return enterprises if enterprises.empty?
|
||||
|
||||
enterprises.includes(
|
||||
supplied_products: [:supplier, :variants, { master: [:images] }]
|
||||
supplied_products: [:supplier, :variants, :image]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,8 +8,8 @@ class ImageImporter
|
||||
|
||||
Spree::Image.create(
|
||||
attachment: { io: file, filename: filename },
|
||||
viewable_id: product.master.id,
|
||||
viewable_type: Spree::Variant,
|
||||
viewable_id: product.id,
|
||||
viewable_type: Spree::Product,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -24,6 +24,8 @@ class OrderWorkflow
|
||||
end
|
||||
|
||||
def advance_to_payment
|
||||
return unless order.state.in? ["cart", "address", "delivery"]
|
||||
|
||||
advance_to_state("payment", advance_order_options)
|
||||
end
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module PermittedAttributes
|
||||
class Checkout
|
||||
def initialize(params)
|
||||
@params = params
|
||||
end
|
||||
|
||||
def call
|
||||
@params.permit(
|
||||
order: [
|
||||
:email, :special_instructions,
|
||||
:existing_card_id, :shipping_method_id,
|
||||
{ payments_attributes: [
|
||||
:payment_method_id,
|
||||
{ source_attributes: PermittedAttributes::PaymentSource.attributes }
|
||||
],
|
||||
ship_address_attributes: PermittedAttributes::Address.attributes,
|
||||
bill_address_attributes: PermittedAttributes::Address.attributes }
|
||||
],
|
||||
payment_source: PermittedAttributes::PaymentSource.attributes
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -11,7 +11,7 @@ module PermittedAttributes
|
||||
:meta_keywords, :notes, :inherits_properties,
|
||||
{ product_properties_attributes: [:id, :property_name, :value],
|
||||
variants_attributes: [PermittedAttributes::Variant.attributes],
|
||||
images_attributes: [:attachment] }
|
||||
image_attributes: [:attachment] }
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -56,8 +56,9 @@ class ProcessPaymentIntent
|
||||
attr_reader :order, :payment_intent, :payment
|
||||
|
||||
def process_payment
|
||||
OrderWorkflow.new(order).next if order.state == "payment"
|
||||
order.process_payments!
|
||||
return unless order.process_payments!
|
||||
|
||||
OrderWorkflow.new(order).complete
|
||||
end
|
||||
|
||||
def ready_for_capture?
|
||||
|
||||
@@ -68,12 +68,14 @@ class ProductsRenderer
|
||||
end
|
||||
|
||||
def products_order
|
||||
if distributor.preferred_shopfront_product_sorting_method == "by_producer" && distributor.preferred_shopfront_producer_order.present?
|
||||
if (distributor.preferred_shopfront_product_sorting_method == "by_producer") &&
|
||||
distributor.preferred_shopfront_producer_order.present?
|
||||
distributor
|
||||
.preferred_shopfront_producer_order
|
||||
.split(",").map { |id| "spree_products.supplier_id=#{id} DESC" }
|
||||
.join(", ") + ", spree_products.name ASC, spree_products.id ASC"
|
||||
elsif distributor.preferred_shopfront_product_sorting_method == "by_category" && distributor.preferred_shopfront_taxon_order.present?
|
||||
elsif distributor.preferred_shopfront_product_sorting_method == "by_category" &&
|
||||
distributor.preferred_shopfront_taxon_order.present?
|
||||
distributor
|
||||
.preferred_shopfront_taxon_order
|
||||
.split(",").map { |id| "spree_products.primary_taxon_id=#{id} DESC" }
|
||||
@@ -95,7 +97,7 @@ class ProductsRenderer
|
||||
end
|
||||
|
||||
def variants_for_shop_by_id
|
||||
index_by_product_id variants_for_shop.reject(&:is_master)
|
||||
index_by_product_id variants_for_shop
|
||||
end
|
||||
|
||||
def index_by_product_id(variants)
|
||||
|
||||
@@ -100,7 +100,7 @@ module Sets
|
||||
end
|
||||
|
||||
def create_or_update_variant(product, variant_attributes)
|
||||
variant = find_model(product.variants_including_master, variant_attributes[:id])
|
||||
variant = find_model(product.variants, variant_attributes[:id])
|
||||
if variant.present?
|
||||
variant.update(variant_attributes.except(:id))
|
||||
else
|
||||
|
||||
@@ -22,7 +22,8 @@ module VariantUnits
|
||||
end
|
||||
|
||||
def product_and_full_name
|
||||
return "#{product.name} - #{full_name}" unless full_name.start_with? product.name
|
||||
return product.name if full_name.blank?
|
||||
return "#{product.name} - #{full_name}" unless full_name.start_with?(product.name)
|
||||
|
||||
full_name
|
||||
end
|
||||
@@ -51,7 +52,7 @@ module VariantUnits
|
||||
return display_as if has_attribute?(:display_as) && display_as.present?
|
||||
return variant.display_as if variant_display_as?
|
||||
|
||||
options_text
|
||||
options_text.to_s
|
||||
end
|
||||
|
||||
def assign_units
|
||||
|
||||
@@ -10,14 +10,15 @@
|
||||
.row
|
||||
.three.columns.alpha
|
||||
= f.label :white_label_logo, t('.upload_logo')
|
||||
%br
|
||||
217 x 44 pixels
|
||||
.thirteen.columns
|
||||
= image_tag @object.white_label_logo_url if @object.white_label_logo.present?
|
||||
%div
|
||||
= f.file_field :white_label_logo, accept: "image/*"
|
||||
%div
|
||||
- if @object.white_label_logo.present?
|
||||
%button.button.small{ type: "button", "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "remove_logo" }
|
||||
= t('.remove_logo')
|
||||
%br
|
||||
= f.file_field :white_label_logo, accept: "image/*"
|
||||
- if @object.white_label_logo.present?
|
||||
%button.button.small.red{ type: "button", "data-controller": "modal-link", "data-action": "click->modal-link#open", "data-modal-link-target-value": "remove_logo" }
|
||||
= t('.remove_logo')
|
||||
|
||||
- if @object.white_label_logo.present?
|
||||
.row
|
||||
@@ -59,4 +60,4 @@
|
||||
= custom_tab_form.label :content, t('.custom_tab_content')
|
||||
.thirteen.columns
|
||||
= custom_tab_form.hidden_field :content, id: "custom_tab_content"
|
||||
%trix-editor{ input: "custom_tab_content" }
|
||||
%trix-editor{ input: "custom_tab_content", "data-controller": "trixeditor" }
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
%accordion-heading
|
||||
.row
|
||||
.small-8.medium-9.columns
|
||||
%em
|
||||
%small
|
||||
{{ summary() | printArray }}
|
||||
.small-4.medium-3.columns.text-right
|
||||
%span.accordion-up
|
||||
%em
|
||||
%small
|
||||
= t :checkout_hide
|
||||
%i.ofn-i_053-point-up
|
||||
%span.accordion-down
|
||||
%em
|
||||
%small
|
||||
= t :checkout_expand
|
||||
%i.ofn-i_052-point-down
|
||||
@@ -1,4 +0,0 @@
|
||||
%p
|
||||
%input{ type: 'checkbox', id: 'accept_terms', ng: { model: "terms_and_conditions_accepted", init: "terms_and_conditions_accepted = #{all_terms_and_conditions_already_accepted?}" } }
|
||||
%label.small{for: "accept_terms"}
|
||||
= t('.message_html', terms_and_conditions_link: link_to( t(".terms_and_conditions"), current_order.distributor.terms_and_conditions, target: '_blank'), tos_link: link_to_platform_terms)
|
||||
@@ -1,2 +0,0 @@
|
||||
%p.alert-box.info
|
||||
= t '.message_html', cart: link_to(t('.cart'), "#{main_app.cart_path}#bought-products")
|
||||
@@ -1,19 +0,0 @@
|
||||
%section{"ng-show" => "!enabled"}
|
||||
.row
|
||||
.small-12.columns.text-center
|
||||
%h3.pad-top
|
||||
= t :checkout_headline
|
||||
.row.pad-top{ "data-controller": "login-modal" }
|
||||
- if guest_checkout_allowed?
|
||||
.small-5.columns.text-center
|
||||
%button.primary.expand{ "data-action": "click->login-modal#call" }
|
||||
= t :label_login
|
||||
.small-2.columns.text-center
|
||||
%p.pad-top= "#{t :action_or}"
|
||||
.small-5.columns.text-center
|
||||
%button.neutral-btn.dark.expand{"ng-click" => "enabled = true"}
|
||||
= t :checkout_as_guest
|
||||
- else
|
||||
.small-6.columns.small-centered
|
||||
%button.primary.expand{ "data-action": "click->login-modal#call" }
|
||||
= t :label_login
|
||||
@@ -1,46 +0,0 @@
|
||||
%fieldset#billing
|
||||
%ng-form{"ng-controller" => "BillingCtrl", name: "billing"}
|
||||
|
||||
%h5{"ng-class" => "{valid: billing.$valid, dirty: billing.$dirty || submitted}"}
|
||||
%span.right
|
||||
%label.label.round.alert.right
|
||||
%i.ofn-i_009-close
|
||||
%label.label.round.success.right
|
||||
%i.ofn-i_051-check-big
|
||||
= t :checkout_billing
|
||||
|
||||
%accordion-group{"is-open" => "accordion.billing",
|
||||
"ng-class" => "{valid: billing.$valid, open: accordion.billing}"}
|
||||
= render 'checkout/accordion_heading'
|
||||
|
||||
- if spree_current_user
|
||||
.small-12.columns
|
||||
%label
|
||||
%input{type: :checkbox, "ng-model" => "Checkout.default_bill_address"}
|
||||
= t :checkout_default_bill_address
|
||||
|
||||
%div{ "ng-controller" => "CountryCtrl" }
|
||||
= f.fields_for :bill_address, @order.bill_address do |ba|
|
||||
.row
|
||||
.small-12.columns
|
||||
= validated_input t(:address), "order.bill_address.address1", "ofn-focus" => "accordion['billing']"
|
||||
.row
|
||||
.small-12.columns
|
||||
= validated_input t(:address2), "order.bill_address.address2", required: false
|
||||
.row
|
||||
.small-6.columns
|
||||
= validated_input t(:city), "order.bill_address.city"
|
||||
|
||||
.small-6.columns
|
||||
= validated_select t(:state), "order.bill_address.state_id", {}, {"ng-options" => "s.id as s.name for s in countriesById[order.bill_address.country_id].states"}
|
||||
.row
|
||||
.small-6.columns
|
||||
= validated_input t(:postcode), "order.bill_address.zipcode"
|
||||
|
||||
.small-6.columns.right
|
||||
= validated_select t(:country), "order.bill_address.country_id", {}, {"ng-init" => "order.bill_address.country_id = order.bill_address.country_id || #{DefaultCountry.id}", "ng-options" => "c.id as c.name for c in countries"}
|
||||
|
||||
.row
|
||||
.small-12.columns.text-right
|
||||
%button.primary{"ng-disabled" => "billing.$invalid", "ng-click" => "next($event)"}
|
||||
= t :next
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user