mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-20 19:56:48 +00:00
Compare commits
257 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9642e8295e | ||
|
|
1424d44eab | ||
|
|
0a5f0a518d | ||
|
|
ff1672e411 | ||
|
|
32d8368990 | ||
|
|
e7f8102eb9 | ||
|
|
24e1d0b775 | ||
|
|
ceadd386aa | ||
|
|
d42dc2b286 | ||
|
|
e9c8e17710 | ||
|
|
bfd845915c | ||
|
|
b7976a2356 | ||
|
|
cd744dab68 | ||
|
|
02e3aac3f0 | ||
|
|
50075f02a0 | ||
|
|
05d8cd09e3 | ||
|
|
02fd87158e | ||
|
|
165af4b812 | ||
|
|
dba8e36752 | ||
|
|
a245590114 | ||
|
|
5ecae39051 | ||
|
|
2508234a7c | ||
|
|
da5f9e7ebc | ||
|
|
0d483882de | ||
|
|
9e40502876 | ||
|
|
c38e58159f | ||
|
|
acf0919bfa | ||
|
|
bca409bfe4 | ||
|
|
1fe10b4b25 | ||
|
|
768378b147 | ||
|
|
1fcbf6b44d | ||
|
|
f96502c369 | ||
|
|
c031b0e52b | ||
|
|
6006952603 | ||
|
|
e5fb8712d7 | ||
|
|
508dfa4f23 | ||
|
|
65d176f533 | ||
|
|
089c754f62 | ||
|
|
aae8f1cbc4 | ||
|
|
7194db40ee | ||
|
|
f2ad087be5 | ||
|
|
0b8b5e694e | ||
|
|
01f9fd3232 | ||
|
|
99cac20725 | ||
|
|
068dbe5013 | ||
|
|
ed375a1e2c | ||
|
|
4345285164 | ||
|
|
eb7cb02f33 | ||
|
|
f22dd7513d | ||
|
|
c54119f482 | ||
|
|
23d2b3a664 | ||
|
|
c747bb5305 | ||
|
|
d147d2035d | ||
|
|
4dd71c1240 | ||
|
|
6ad7c7b835 | ||
|
|
10bbc5f9ef | ||
|
|
b8a124b99e | ||
|
|
28b1ea2d9f | ||
|
|
2b989f49ea | ||
|
|
bdc701f880 | ||
|
|
7af154d675 | ||
|
|
2552b5faac | ||
|
|
d8e3052575 | ||
|
|
3c797d3b86 | ||
|
|
46ca3bc950 | ||
|
|
75ec77dc31 | ||
|
|
a09a54e4cb | ||
|
|
e486dbd4f8 | ||
|
|
db5503dd80 | ||
|
|
dd3d205536 | ||
|
|
90007d7114 | ||
|
|
7ba99c0fe0 | ||
|
|
ba61f94906 | ||
|
|
7c82fa3d44 | ||
|
|
665749d0c5 | ||
|
|
d3566f9303 | ||
|
|
7d2deca969 | ||
|
|
0f19be4db4 | ||
|
|
393a4efbf6 | ||
|
|
34b109cbb7 | ||
|
|
4785f3eacc | ||
|
|
e14b017f1f | ||
|
|
d2096cf6d1 | ||
|
|
fbda1a27ad | ||
|
|
098afc62c1 | ||
|
|
1cd1e9dc37 | ||
|
|
0bbaafbd41 | ||
|
|
0e42c1cf30 | ||
|
|
620721c8cb | ||
|
|
5cba635783 | ||
|
|
08c723b10f | ||
|
|
61feb2b27d | ||
|
|
a2dee8d3d8 | ||
|
|
a74c502fd9 | ||
|
|
f6c3a2a46e | ||
|
|
4464a85a74 | ||
|
|
22bbe29f3d | ||
|
|
9832966b77 | ||
|
|
19213a5ca8 | ||
|
|
3a0b47c451 | ||
|
|
0cd43987de | ||
|
|
ca1987fc87 | ||
|
|
2f153d799b | ||
|
|
742dd0b5dd | ||
|
|
ecef905444 | ||
|
|
dd56e03be1 | ||
|
|
7b456461f3 | ||
|
|
e4872172c8 | ||
|
|
2ed5e144ca | ||
|
|
f9df4d4c93 | ||
|
|
1aa477c57c | ||
|
|
69385370ee | ||
|
|
65ab83a9a5 | ||
|
|
746c2ffef9 | ||
|
|
6690f2e9e7 | ||
|
|
74a7cb82bc | ||
|
|
15ed4c32d9 | ||
|
|
56ff877b25 | ||
|
|
926f196b96 | ||
|
|
5b7e2f7ca8 | ||
|
|
0a12f78444 | ||
|
|
da5c907e0f | ||
|
|
f065cbe251 | ||
|
|
511afa0ddc | ||
|
|
d5ab9eb675 | ||
|
|
cb08011450 | ||
|
|
41b7be900c | ||
|
|
6133b302af | ||
|
|
4fb1c7fd92 | ||
|
|
b31881baa5 | ||
|
|
4e96487da9 | ||
|
|
98317e96d0 | ||
|
|
4865533f26 | ||
|
|
1f8890b430 | ||
|
|
11daf89005 | ||
|
|
fab893e60b | ||
|
|
a04116466e | ||
|
|
2f6493bb86 | ||
|
|
589c2a1500 | ||
|
|
8cae874109 | ||
|
|
7c406f7c3a | ||
|
|
862443ed6d | ||
|
|
3b78179dea | ||
|
|
f317cee9e9 | ||
|
|
35912605c3 | ||
|
|
8901af897a | ||
|
|
ee92f46bd5 | ||
|
|
44ba499ad9 | ||
|
|
44d172f3b4 | ||
|
|
d2b6ba4330 | ||
|
|
576e4db9be | ||
|
|
692ccf0598 | ||
|
|
ce65a9d063 | ||
|
|
ffc99df373 | ||
|
|
5c58d30ca7 | ||
|
|
3efabf5c50 | ||
|
|
919e39f950 | ||
|
|
0e14704572 | ||
|
|
e9d062a8c2 | ||
|
|
f3af36deca | ||
|
|
ecb78233d9 | ||
|
|
a68ae1fe2d | ||
|
|
28ba05ec6b | ||
|
|
5b675cbaba | ||
|
|
42dd58426e | ||
|
|
c83755f901 | ||
|
|
ae2d3d3fd9 | ||
|
|
e6eb45b453 | ||
|
|
01ce092ebc | ||
|
|
5d77ef52c5 | ||
|
|
e8636c0cbf | ||
|
|
f890927423 | ||
|
|
6499d17cb1 | ||
|
|
1d1e581c85 | ||
|
|
64009a2c9e | ||
|
|
14f6ea4c01 | ||
|
|
fdca1f6606 | ||
|
|
63a15ec392 | ||
|
|
356dad73ba | ||
|
|
fb5784fbda | ||
|
|
4ef97aa418 | ||
|
|
b9d72ce4cf | ||
|
|
9733bb3a77 | ||
|
|
532dc57725 | ||
|
|
f4c3fbf8bc | ||
|
|
778526af2e | ||
|
|
1aebee0583 | ||
|
|
ed5c650456 | ||
|
|
b8c6da301c | ||
|
|
269a60b36f | ||
|
|
25907f97a8 | ||
|
|
d1779b9457 | ||
|
|
ddac179f9b | ||
|
|
25f48d944c | ||
|
|
c9c4680ef6 | ||
|
|
1449169b16 | ||
|
|
c6e50a3f7f | ||
|
|
56295e5ffb | ||
|
|
33a3db8698 | ||
|
|
c4f9a5a234 | ||
|
|
627899bbd4 | ||
|
|
12f4f2d17a | ||
|
|
300dc3084c | ||
|
|
50c3d1367d | ||
|
|
a1cad82564 | ||
|
|
298fd057f5 | ||
|
|
33b570b117 | ||
|
|
3b05b76b80 | ||
|
|
c97a140471 | ||
|
|
7c831c9844 | ||
|
|
5c16fefe41 | ||
|
|
5ad88f992c | ||
|
|
f87f4310f0 | ||
|
|
987ad0df6c | ||
|
|
d500c20d3f | ||
|
|
99a7665edc | ||
|
|
37f60bf7a1 | ||
|
|
b5a6bcdf9d | ||
|
|
858852123d | ||
|
|
ae72ebef5e | ||
|
|
1450bfd726 | ||
|
|
22e4a50807 | ||
|
|
a039286240 | ||
|
|
9ac638f8ba | ||
|
|
da335703b4 | ||
|
|
d374ab569d | ||
|
|
47df2dc20b | ||
|
|
5c43c75b00 | ||
|
|
f83c7a88df | ||
|
|
5ae473e07f | ||
|
|
e69b27a3c4 | ||
|
|
e52e04ba29 | ||
|
|
1dcffa790d | ||
|
|
f22278db51 | ||
|
|
0280e04008 | ||
|
|
41607c5846 | ||
|
|
1c69f2c670 | ||
|
|
05a69ff0c6 | ||
|
|
758f57a889 | ||
|
|
eed11faa62 | ||
|
|
7fd8c5956d | ||
|
|
8ed983cf03 | ||
|
|
b6292e2723 | ||
|
|
8bdf57d0d9 | ||
|
|
03f590ccc4 | ||
|
|
06279848c6 | ||
|
|
3623325cab | ||
|
|
df18329233 | ||
|
|
1db0bbef09 | ||
|
|
09aed63cd4 | ||
|
|
757f886af5 | ||
|
|
f73f0d4bf9 | ||
|
|
d4f7efd08a | ||
|
|
a1aac7643a | ||
|
|
d3d4628e29 | ||
|
|
942ab55ddc | ||
|
|
1b151ee015 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,5 +1,6 @@
|
||||
.bundle
|
||||
.rbenv-version
|
||||
.byebug_history
|
||||
.swp
|
||||
*.swo
|
||||
*.swp
|
||||
|
||||
1
.node-version
Normal file
1
.node-version
Normal file
@@ -0,0 +1 @@
|
||||
5.12.0
|
||||
@@ -143,6 +143,10 @@ Style/WordArray:
|
||||
Enabled: false
|
||||
StyleGuide: http://relaxed.ruby.style/#stylewordarray
|
||||
|
||||
Style/SymbolArray:
|
||||
Enabled: false
|
||||
StyleGuide: https://rubocop.readthedocs.io/en/latest/cops_style/#stylesymbolarray
|
||||
|
||||
Lint/AmbiguousRegexpLiteral:
|
||||
Enabled: false
|
||||
StyleGuide: http://relaxed.ruby.style/#lintambiguousregexpliteral
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config --exclude-limit 100`
|
||||
# on 2017-07-12 10:36:44 +0200 using RuboCop version 0.49.1.
|
||||
# on 2017-08-25 14:27:48 +1000 using RuboCop version 0.49.1.
|
||||
# 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
|
||||
@@ -14,7 +14,7 @@ Bundler/OrderedGems:
|
||||
Exclude:
|
||||
- 'Gemfile'
|
||||
|
||||
# Offense count: 77
|
||||
# Offense count: 128
|
||||
# Cop supports --auto-correct.
|
||||
Layout/AlignArray:
|
||||
Exclude:
|
||||
@@ -59,7 +59,7 @@ Layout/AlignHash:
|
||||
- 'spec/models/spree/shipping_method_spec.rb'
|
||||
- 'spec/models/spree/variant_spec.rb'
|
||||
|
||||
# Offense count: 42
|
||||
# Offense count: 43
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
||||
# SupportedStyles: with_first_parameter, with_fixed_indentation
|
||||
@@ -113,11 +113,12 @@ Layout/CaseIndentation:
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/product_importer.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Offense count: 3
|
||||
# Cop supports --auto-correct.
|
||||
Layout/ClosingParenthesisIndentation:
|
||||
Exclude:
|
||||
- 'app/overrides/add_capture_order_shortcut.rb'
|
||||
- 'spec/serializers/variant_serializer_spec.rb'
|
||||
|
||||
# Offense count: 8
|
||||
# Cop supports --auto-correct.
|
||||
@@ -137,7 +138,7 @@ Layout/ElseAlignment:
|
||||
- 'app/serializers/api/admin/order_cycle_serializer.rb'
|
||||
- 'lib/open_food_network/sales_tax_report.rb'
|
||||
|
||||
# Offense count: 223
|
||||
# Offense count: 215
|
||||
# Cop supports --auto-correct.
|
||||
Layout/EmptyLines:
|
||||
Enabled: false
|
||||
@@ -152,7 +153,7 @@ Layout/EmptyLinesAroundAccessModifier:
|
||||
- 'spec/helpers/products_helper_spec.rb'
|
||||
- 'spec/support/request/web_helper.rb'
|
||||
|
||||
# Offense count: 73
|
||||
# Offense count: 70
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: empty_lines, no_empty_lines
|
||||
@@ -170,7 +171,6 @@ Layout/EmptyLinesAroundBlockBody:
|
||||
- 'app/models/spree/calculator_decorator.rb'
|
||||
- 'app/models/spree/money_decorator.rb'
|
||||
- 'app/models/spree/option_value_decorator.rb'
|
||||
- 'app/models/spree/payment_decorator.rb'
|
||||
- 'lib/open_food_network/group_buy_report.rb'
|
||||
- 'lib/spree/money_decorator.rb'
|
||||
- 'lib/tasks/dev.rake'
|
||||
@@ -188,10 +188,10 @@ Layout/EmptyLinesAroundBlockBody:
|
||||
- 'spec/features/admin/orders_spec.rb'
|
||||
- 'spec/features/admin/reports_spec.rb'
|
||||
- 'spec/features/admin/variant_overrides_spec.rb'
|
||||
- 'spec/features/consumer/shopping/embedded_shopfronts_spec.rb'
|
||||
- 'spec/features/consumer/shopping/shopping_spec.rb'
|
||||
- 'spec/features/consumer/shopping/variant_overrides_spec.rb'
|
||||
- 'spec/helpers/admin/business_model_configuration_helper_spec.rb'
|
||||
- 'spec/helpers/injection_helper_spec.rb'
|
||||
- 'spec/helpers/shared_helper_spec.rb'
|
||||
- 'spec/helpers/shop_helper_spec.rb'
|
||||
- 'spec/helpers/spree/orders_helper_spec.rb'
|
||||
@@ -212,8 +212,7 @@ Layout/EmptyLinesAroundBlockBody:
|
||||
- 'spec/models/tag_rule/filter_shipping_methods_spec.rb'
|
||||
- 'spec/serializers/admin/for_order_cycle/enterprise_serializer_spec.rb'
|
||||
- 'spec/serializers/admin/for_order_cycle/supplied_product_serializer_spec.rb'
|
||||
- 'spec/serializers/order_serializer_spec.rb'
|
||||
- 'spec/serializers/orders_by_distributor_serializer_spec.rb'
|
||||
- 'spec/serializers/variant_serializer_spec.rb'
|
||||
- 'spec/support/matchers/delegate_matchers.rb'
|
||||
- 'spec/support/matchers/select2_matchers.rb'
|
||||
- 'spec/support/matchers/table_matchers.rb'
|
||||
@@ -270,7 +269,7 @@ Layout/EmptyLinesAroundMethodBody:
|
||||
- 'app/serializers/api/product_serializer.rb'
|
||||
- 'lib/open_food_network/orders_and_fulfillments_report.rb'
|
||||
|
||||
# Offense count: 13
|
||||
# Offense count: 12
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines
|
||||
@@ -278,7 +277,6 @@ Layout/EmptyLinesAroundModuleBody:
|
||||
Exclude:
|
||||
- 'app/helpers/add_to_cart_helper.rb'
|
||||
- 'app/helpers/groups_helper.rb'
|
||||
- 'app/helpers/injection_helper.rb'
|
||||
- 'app/helpers/spree/admin/base_helper_decorator.rb'
|
||||
- 'lib/open_food_network/column_preference_defaults.rb'
|
||||
- 'lib/open_food_network/group_buy_report.rb'
|
||||
@@ -289,7 +287,7 @@ Layout/EmptyLinesAroundModuleBody:
|
||||
- 'spec/support/request/distribution_helper.rb'
|
||||
- 'spec/support/request/ui_component_helper.rb'
|
||||
|
||||
# Offense count: 54
|
||||
# Offense count: 55
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowForAlignment, ForceEqualSignAlignment.
|
||||
Layout/ExtraSpacing:
|
||||
@@ -326,29 +324,28 @@ Layout/ExtraSpacing:
|
||||
- 'spec/models/enterprise_spec.rb'
|
||||
- 'spec/models/order_cycle_spec.rb'
|
||||
- 'spec/models/spree/adjustment_spec.rb'
|
||||
- 'spec/models/spree/gateway/stripe_connect_spec.rb'
|
||||
- 'spec/models/spree/order_spec.rb'
|
||||
- 'spec/models/variant_override_spec.rb'
|
||||
- 'spec/serializers/admin/for_order_cycle/enterprise_serializer_spec.rb'
|
||||
- 'spec/serializers/admin/for_order_cycle/supplied_product_serializer_spec.rb'
|
||||
- 'spec/support/request/web_helper.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
||||
# SupportedStyles: consistent, special_for_inner_method_call, special_for_inner_method_call_in_parentheses
|
||||
Layout/FirstParameterIndentation:
|
||||
Exclude:
|
||||
- 'lib/open_food_network/permissions.rb'
|
||||
- 'spec/serializers/variant_serializer_spec.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# Offense count: 4
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
||||
# Configuration parameters: SupportedStyles, IndentationWidth.
|
||||
# SupportedStyles: special_inside_parentheses, consistent, align_brackets
|
||||
Layout/IndentArray:
|
||||
Exclude:
|
||||
- 'lib/open_food_network/users_and_enterprises_report.rb'
|
||||
- 'spec/features/admin/reports_spec.rb'
|
||||
- 'spec/lib/open_food_network/products_and_inventory_report_spec.rb'
|
||||
EnforcedStyle: consistent
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
@@ -403,7 +400,7 @@ Layout/IndentationConsistency:
|
||||
- 'spec/models/spree/line_item_spec.rb'
|
||||
- 'spec/models/spree/product_spec.rb'
|
||||
|
||||
# Offense count: 20
|
||||
# Offense count: 18
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: Width, IgnoredPatterns.
|
||||
Layout/IndentationWidth:
|
||||
@@ -411,13 +408,11 @@ Layout/IndentationWidth:
|
||||
- 'app/controllers/admin/invoice_settings_controller.rb'
|
||||
- 'app/controllers/admin/order_cycles_controller.rb'
|
||||
- 'app/controllers/api/order_cycles_controller.rb'
|
||||
- 'app/controllers/spree/admin/reports_controller_decorator.rb'
|
||||
- 'app/models/spree/line_item_decorator.rb'
|
||||
- 'app/serializers/api/admin/for_order_cycle/enterprise_serializer.rb'
|
||||
- 'app/serializers/api/admin/for_order_cycle/supplied_product_serializer.rb'
|
||||
- 'app/serializers/api/admin/order_cycle_serializer.rb'
|
||||
- 'lib/discourse/single_sign_on.rb'
|
||||
- 'lib/open_food_network/last_used_address.rb'
|
||||
- 'spec/features/consumer/shopping/variant_overrides_spec.rb'
|
||||
- 'spec/helpers/admin/business_model_configuration_helper_spec.rb'
|
||||
- 'spec/helpers/groups_helper_spec.rb'
|
||||
@@ -525,7 +520,15 @@ Layout/MultilineMethodCallBraceLayout:
|
||||
- 'lib/open_food_network/products_renderer.rb'
|
||||
- 'spec/lib/open_food_network/products_and_inventory_report_spec.rb'
|
||||
|
||||
# Offense count: 34
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
||||
# SupportedStyles: aligned, indented, indented_relative_to_receiver
|
||||
Layout/MultilineMethodCallIndentation:
|
||||
Exclude:
|
||||
- 'spec/serializers/variant_serializer_spec.rb'
|
||||
|
||||
# Offense count: 33
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, IndentationWidth.
|
||||
# SupportedStyles: aligned, indented
|
||||
@@ -538,7 +541,6 @@ Layout/MultilineOperationIndentation:
|
||||
- 'app/models/producer_property.rb'
|
||||
- 'app/models/product_importer.rb'
|
||||
- 'app/models/spree/ability_decorator.rb'
|
||||
- 'app/models/spree/order_decorator.rb'
|
||||
- 'app/models/spree/product_set.rb'
|
||||
- 'app/models/variant_override_set.rb'
|
||||
- 'lib/open_food_network/accounts_and_billing_settings_validator.rb'
|
||||
@@ -558,20 +560,18 @@ Layout/SpaceAfterColon:
|
||||
- 'spec/models/variant_override_spec.rb'
|
||||
- 'spec/spec_helper.rb'
|
||||
|
||||
# Offense count: 58
|
||||
# Offense count: 53
|
||||
# Cop supports --auto-correct.
|
||||
Layout/SpaceAfterComma:
|
||||
Exclude:
|
||||
- 'app/controllers/admin/order_cycles_controller.rb'
|
||||
- 'app/controllers/spree/admin/products_controller_decorator.rb'
|
||||
- 'app/controllers/spree/admin/reports_controller_decorator.rb'
|
||||
- 'app/controllers/spree/orders_controller_decorator.rb'
|
||||
- 'app/models/column_preference.rb'
|
||||
- 'app/models/product_importer.rb'
|
||||
- 'lib/discourse/single_sign_on.rb'
|
||||
- 'lib/open_food_network/accounts_and_billing_settings_validator.rb'
|
||||
- 'lib/open_food_network/business_model_configuration_validator.rb'
|
||||
- 'lib/open_food_network/order_and_distributor_report.rb'
|
||||
- 'lib/open_food_network/order_cycle_form_applicator.rb'
|
||||
- 'lib/open_food_network/users_and_enterprises_report.rb'
|
||||
- 'spec/controllers/admin/enterprises_controller_spec.rb'
|
||||
@@ -648,7 +648,7 @@ Layout/SpaceAroundEqualsInParameterDefault:
|
||||
- 'spec/support/request/distribution_helper.rb'
|
||||
- 'spec/support/request/web_helper.rb'
|
||||
|
||||
# Offense count: 58
|
||||
# Offense count: 60
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: AllowForAlignment.
|
||||
Layout/SpaceAroundOperators:
|
||||
@@ -677,6 +677,7 @@ Layout/SpaceAroundOperators:
|
||||
- 'spec/helpers/order_cycles_helper_spec.rb'
|
||||
- 'spec/jobs/update_billable_periods_spec.rb'
|
||||
- 'spec/lib/open_food_network/order_grouper_spec.rb'
|
||||
- 'spec/lib/stripe/account_connector_spec.rb'
|
||||
- 'spec/models/calculator/weight_spec.rb'
|
||||
- 'spec/support/cancan_helper.rb'
|
||||
- 'spec/support/seeds.rb'
|
||||
@@ -715,7 +716,7 @@ Layout/SpaceInLambdaLiteral:
|
||||
- 'app/models/spree/product_decorator.rb'
|
||||
- 'app/models/spree/variant_decorator.rb'
|
||||
|
||||
# Offense count: 194
|
||||
# Offense count: 187
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SupportedStylesForEmptyBraces, SpaceBeforeBlockParameters.
|
||||
# SupportedStyles: space, no_space
|
||||
@@ -765,11 +766,9 @@ Layout/SpaceInsideBlockBraces:
|
||||
- 'spec/models/spree/order_spec.rb'
|
||||
- 'spec/models/spree/payment_spec.rb'
|
||||
- 'spec/models/spree/product_spec.rb'
|
||||
- 'spec/models/spree/user_spec.rb'
|
||||
- 'spec/models/tag_rule/discount_order_spec.rb'
|
||||
- 'spec/serializers/admin/for_order_cycle/enterprise_serializer_spec.rb'
|
||||
- 'spec/serializers/admin/for_order_cycle/supplied_product_serializer_spec.rb'
|
||||
- 'spec/serializers/orders_by_distributor_serializer_spec.rb'
|
||||
- 'spec/spec_helper.rb'
|
||||
- 'spec/support/cancan_helper.rb'
|
||||
|
||||
@@ -796,7 +795,7 @@ Layout/SpaceInsideBrackets:
|
||||
- 'spec/lib/open_food_network/users_and_enterprises_report_spec.rb'
|
||||
- 'spec/performance/orders_controller_spec.rb'
|
||||
|
||||
# Offense count: 729
|
||||
# Offense count: 766
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, EnforcedStyleForEmptyBraces, SupportedStylesForEmptyBraces.
|
||||
# SupportedStyles: space, no_space, compact
|
||||
@@ -823,12 +822,11 @@ Layout/Tab:
|
||||
- 'spec/lib/spree/product_filters_spec.rb'
|
||||
- 'spec/models/spree/line_item_spec.rb'
|
||||
|
||||
# Offense count: 32
|
||||
# Offense count: 42
|
||||
# Cop supports --auto-correct.
|
||||
Layout/TrailingWhitespace:
|
||||
Exclude:
|
||||
- 'app/models/distributor_shipping_method.rb'
|
||||
- 'app/models/product_importer.rb'
|
||||
- 'app/models/spree/money_decorator.rb'
|
||||
- 'app/serializers/api/image_serializer.rb'
|
||||
- 'app/serializers/api/shipping_method_serializer.rb'
|
||||
@@ -836,7 +834,6 @@ Layout/TrailingWhitespace:
|
||||
- 'app/views/json/_enterprises.rabl'
|
||||
- 'app/views/json/_producer.rabl'
|
||||
- 'app/views/json/partials/_producer.rabl'
|
||||
- 'lib/open_food_network/group_buy_report.rb'
|
||||
- 'lib/tasks/dev.rake'
|
||||
- 'spec/controllers/spree/store_controller_spec.rb'
|
||||
- 'spec/features/admin/enterprise_user_spec.rb'
|
||||
@@ -844,17 +841,16 @@ Layout/TrailingWhitespace:
|
||||
- 'spec/lib/open_food_network/option_value_namer_spec.rb'
|
||||
- 'spec/lib/open_food_network/order_grouper_spec.rb'
|
||||
- 'spec/serializers/admin/enterprise_serializer_spec.rb'
|
||||
- 'spec/serializers/variant_serializer_spec.rb'
|
||||
- 'spec/support/request/menu_helper.rb'
|
||||
- 'spec/views/json/producers.json.rabl_spec.rb'
|
||||
|
||||
# Offense count: 8
|
||||
# Offense count: 6
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyleAlignWith, SupportedStylesAlignWith.
|
||||
# SupportedStylesAlignWith: either, start_of_block, start_of_line
|
||||
Lint/BlockAlignment:
|
||||
Exclude:
|
||||
- 'app/controllers/spree/admin/reports_controller_decorator.rb'
|
||||
- 'lib/open_food_network/last_used_address.rb'
|
||||
- 'spec/lib/open_food_network/enterprise_fee_calculator_spec.rb'
|
||||
- 'spec/models/enterprise_spec.rb'
|
||||
- 'spec/models/spree/calculator/flat_percent_item_total_spec.rb'
|
||||
@@ -1011,7 +1007,7 @@ Lint/UselessAccessModifier:
|
||||
- 'lib/open_food_network/reports/bulk_coop_report.rb'
|
||||
- 'spec/lib/open_food_network/reports/report_spec.rb'
|
||||
|
||||
# Offense count: 340
|
||||
# Offense count: 341
|
||||
Lint/Void:
|
||||
Exclude:
|
||||
- 'app/serializers/api/enterprise_serializer.rb'
|
||||
@@ -1080,7 +1076,7 @@ Lint/Void:
|
||||
- 'spec/serializers/enterprise_serializer_spec.rb'
|
||||
- 'spec/support/request/web_helper.rb'
|
||||
|
||||
# Offense count: 706
|
||||
# Offense count: 747
|
||||
# Configuration parameters: CountComments, ExcludedMethods.
|
||||
Metrics/BlockLength:
|
||||
Max: 711
|
||||
@@ -1165,7 +1161,7 @@ Rails/Delegate:
|
||||
- 'app/serializers/api/admin/tag_rule_serializer.rb'
|
||||
- 'app/serializers/api/variant_serializer.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# Offense count: 7
|
||||
Rails/FilePath:
|
||||
Exclude:
|
||||
- 'lib/tasks/karma.rake'
|
||||
@@ -1203,7 +1199,7 @@ Rails/HasAndBelongsToMany:
|
||||
- 'app/models/spree/line_item_decorator.rb'
|
||||
- 'app/models/spree/payment_method_decorator.rb'
|
||||
|
||||
# Offense count: 11
|
||||
# Offense count: 10
|
||||
Rails/OutputSafety:
|
||||
Exclude:
|
||||
- 'app/controllers/spree/admin/reports_controller_decorator.rb'
|
||||
@@ -1211,7 +1207,6 @@ Rails/OutputSafety:
|
||||
- 'app/helpers/spree/reports_helper.rb'
|
||||
- 'app/serializers/api/product_serializer.rb'
|
||||
- 'lib/spree/money_decorator.rb'
|
||||
- 'lib/tasks/karma.rake'
|
||||
|
||||
# Offense count: 6
|
||||
# Cop supports --auto-correct.
|
||||
@@ -1302,15 +1297,16 @@ Rails/Validation:
|
||||
- 'app/models/spree/variant_decorator.rb'
|
||||
- 'app/models/variant_override.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# Offense count: 7
|
||||
Style/AccessorMethodName:
|
||||
Exclude:
|
||||
- 'app/models/product_importer.rb'
|
||||
- 'app/models/spree/adjustment_decorator.rb'
|
||||
- 'app/models/spree/order_decorator.rb'
|
||||
- 'spec/support/request/shop_workflow.rb'
|
||||
- 'spec/support/request/web_helper.rb'
|
||||
|
||||
# Offense count: 35
|
||||
# Offense count: 34
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: always, conditionals
|
||||
@@ -1326,7 +1322,6 @@ Style/AndOr:
|
||||
- 'app/models/product_importer.rb'
|
||||
- 'app/models/spreadsheet_entry.rb'
|
||||
- 'app/models/spree/adjustment_decorator.rb'
|
||||
- 'app/models/spree/order_decorator.rb'
|
||||
- 'app/models/spree/product_set.rb'
|
||||
- 'app/views/json/partials/_enterprise.rabl'
|
||||
- 'lib/spree/core/controller_helpers/respond_with_decorator.rb'
|
||||
@@ -1340,7 +1335,7 @@ Style/BarePercentLiterals:
|
||||
- 'spec/features/admin/variants_spec.rb'
|
||||
- 'spec/support/request/web_helper.rb'
|
||||
|
||||
# Offense count: 209
|
||||
# Offense count: 208
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: braces, no_braces, context_dependent
|
||||
@@ -1410,7 +1405,6 @@ Style/BracesAroundHashParameters:
|
||||
- 'spec/models/spree/product_spec.rb'
|
||||
- 'spec/models/spree/taxon_spec.rb'
|
||||
- 'spec/serializers/admin/customer_serializer_spec.rb'
|
||||
- 'spec/serializers/orders_by_distributor_serializer_spec.rb'
|
||||
- 'spec/spec_helper.rb'
|
||||
- 'spec/support/cancan_helper.rb'
|
||||
- 'spec/support/request/authentication_workflow.rb'
|
||||
@@ -1422,7 +1416,7 @@ Style/CaseEquality:
|
||||
- 'app/helpers/angular_form_helper.rb'
|
||||
- 'spec/models/spree/payment_spec.rb'
|
||||
|
||||
# Offense count: 86
|
||||
# Offense count: 88
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
||||
# SupportedStyles: nested, compact
|
||||
Style/ClassAndModuleChildren:
|
||||
@@ -1468,7 +1462,9 @@ Style/ClassAndModuleChildren:
|
||||
- 'app/serializers/api/admin/line_item_serializer.rb'
|
||||
- 'app/serializers/api/admin/order_cycle_serializer.rb'
|
||||
- 'app/serializers/api/admin/order_serializer.rb'
|
||||
- 'app/serializers/api/admin/payment_method_serializer.rb'
|
||||
- 'app/serializers/api/admin/payment_method/base_serializer.rb'
|
||||
- 'app/serializers/api/admin/payment_method/payment_method_serializer.rb'
|
||||
- 'app/serializers/api/admin/payment_method/stripe_serializer.rb'
|
||||
- 'app/serializers/api/admin/product_serializer.rb'
|
||||
- 'app/serializers/api/admin/shipping_method_serializer.rb'
|
||||
- 'app/serializers/api/admin/tag_rule_serializer.rb'
|
||||
@@ -1601,7 +1597,7 @@ Style/FileName:
|
||||
Style/FormatStringToken:
|
||||
EnforcedStyle: template
|
||||
|
||||
# Offense count: 88
|
||||
# Offense count: 89
|
||||
# Configuration parameters: MinBodyLength.
|
||||
Style/GuardClause:
|
||||
Exclude:
|
||||
@@ -1655,7 +1651,7 @@ Style/GuardClause:
|
||||
- 'spec/support/request/distribution_helper.rb'
|
||||
- 'spec/support/request/shop_workflow.rb'
|
||||
|
||||
# Offense count: 1241
|
||||
# Offense count: 1255
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, SupportedStyles, UseHashRocketsWithSymbolValues, PreferHashRocketsForNonAlnumEndingSymbols.
|
||||
# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
|
||||
@@ -1685,11 +1681,10 @@ Style/InverseMethods:
|
||||
- 'app/controllers/admin/column_preferences_controller.rb'
|
||||
- 'spec/support/cancan_helper.rb'
|
||||
|
||||
# Offense count: 9
|
||||
# Offense count: 5
|
||||
# Cop supports --auto-correct.
|
||||
Style/LineEndConcatenation:
|
||||
Exclude:
|
||||
- 'app/controllers/spree/admin/base_controller_decorator.rb'
|
||||
- 'lib/spree/core/controller_helpers/respond_with_decorator.rb'
|
||||
- 'spec/controllers/spree/admin/base_controller_spec.rb'
|
||||
|
||||
@@ -1736,11 +1731,10 @@ Style/MultilineIfModifier:
|
||||
- 'lib/open_food_network/enterprise_issue_validator.rb'
|
||||
- 'lib/spree/core/controller_helpers/respond_with_decorator.rb'
|
||||
|
||||
# Offense count: 8
|
||||
# Offense count: 7
|
||||
# Cop supports --auto-correct.
|
||||
Style/MutableConstant:
|
||||
Exclude:
|
||||
- 'app/controllers/spree/admin/reports_controller_decorator.rb'
|
||||
- 'app/models/enterprise.rb'
|
||||
- 'app/models/enterprise_fee.rb'
|
||||
- 'app/models/spree/payment_method_decorator.rb'
|
||||
@@ -1798,7 +1792,7 @@ Style/NumericLiteralPrefix:
|
||||
Exclude:
|
||||
- 'spec/features/admin/order_cycles_spec.rb'
|
||||
|
||||
# Offense count: 16
|
||||
# Offense count: 15
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: Strict.
|
||||
Style/NumericLiterals:
|
||||
@@ -2025,7 +2019,7 @@ Style/StructInheritance:
|
||||
Exclude:
|
||||
- 'lib/open_food_network/enterprise_fee_applicator.rb'
|
||||
|
||||
# Offense count: 182
|
||||
# Offense count: 183
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, MinSize, SupportedStyles.
|
||||
# SupportedStyles: percent, brackets
|
||||
@@ -2069,7 +2063,7 @@ Style/SymbolArray:
|
||||
- 'spec/models/exchange_spec.rb'
|
||||
- 'spec/models/spree/ability_spec.rb'
|
||||
|
||||
# Offense count: 97
|
||||
# Offense count: 96
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: IgnoredMethods.
|
||||
# IgnoredMethods: respond_to, define_method
|
||||
@@ -2101,7 +2095,6 @@ Style/SymbolProc:
|
||||
- 'spec/features/admin/order_cycles_spec.rb'
|
||||
- 'spec/lib/open_food_network/group_buy_report_spec.rb'
|
||||
- 'spec/lib/open_food_network/order_grouper_spec.rb'
|
||||
- 'spec/models/spree/user_spec.rb'
|
||||
|
||||
# Offense count: 6
|
||||
# Cop supports --auto-correct.
|
||||
|
||||
10
Gemfile
10
Gemfile
@@ -10,7 +10,7 @@ gem 'i18n-js', '~> 3.0.0'
|
||||
gem 'nokogiri', '>= 1.6.7.1'
|
||||
|
||||
gem 'pg'
|
||||
gem 'spree', github: 'openfoodfoundation/spree', branch: 'step-6-adjustment-state-migration', ref: '48febb2'
|
||||
gem 'spree', github: 'openfoodfoundation/spree', branch: 'step-6a', ref: '5a76d45'
|
||||
gem 'spree_i18n', github: 'spree/spree_i18n', branch: '1-3-stable'
|
||||
gem 'spree_auth_devise', github: 'openfoodfoundation/spree_auth_devise', branch: 'spree-upgrade-intermediate'
|
||||
|
||||
@@ -19,6 +19,11 @@ gem 'spree_auth_devise', github: 'openfoodfoundation/spree_auth_devise', branch:
|
||||
# - Change type of password from string to password to hide it in the form
|
||||
gem 'spree_paypal_express', :github => "openfoodfoundation/better_spree_paypal_express", :branch => "spree-upgrade-intermediate"
|
||||
#gem 'spree_paypal_express', :github => "spree-contrib/better_spree_paypal_express", :branch => "1-3-stable"
|
||||
gem 'stripe', '~> 3.3.1'
|
||||
gem 'activemerchant', '~> 1.71.0'
|
||||
|
||||
gem 'oauth2', '~> 1.2.0' # Used for Stripe Connect
|
||||
gem 'jwt', '~> 1.5'
|
||||
|
||||
gem 'delayed_job_active_record'
|
||||
gem 'daemons'
|
||||
@@ -121,7 +126,8 @@ group :test do
|
||||
end
|
||||
|
||||
group :development do
|
||||
gem 'pry-byebug'
|
||||
gem 'byebug', '~> 9.0.0' # 9.1 requires ruby 2.2
|
||||
gem 'pry-byebug', '>= 3.4.3'
|
||||
gem 'debugger-linecache'
|
||||
gem 'guard'
|
||||
gem 'guard-livereload'
|
||||
|
||||
54
Gemfile.lock
54
Gemfile.lock
@@ -30,9 +30,9 @@ GIT
|
||||
|
||||
GIT
|
||||
remote: git://github.com/openfoodfoundation/spree.git
|
||||
revision: 48febb250a3b1eb2d42812b27b93457e89cde589
|
||||
ref: 48febb2
|
||||
branch: step-6-adjustment-state-migration
|
||||
revision: 5a76d456ff70aea7aae3d25156558d71eb7febf2
|
||||
ref: 5a76d45
|
||||
branch: step-6a
|
||||
specs:
|
||||
spree (1.3.99)
|
||||
spree_api (= 1.3.99)
|
||||
@@ -57,7 +57,7 @@ GIT
|
||||
spree_cmd (1.3.99)
|
||||
thor (>= 0.14.6)
|
||||
spree_core (1.3.99)
|
||||
activemerchant (~> 1.50.0)
|
||||
activemerchant (~> 1.50)
|
||||
acts_as_list (= 0.1.9)
|
||||
awesome_nested_set (= 2.1.5)
|
||||
aws-sdk (~> 1.11.1)
|
||||
@@ -151,8 +151,8 @@ GEM
|
||||
sprockets (~> 2.2.1)
|
||||
active_model_serializers (0.8.3)
|
||||
activemodel (>= 3.0)
|
||||
activemerchant (1.50.0)
|
||||
activesupport (>= 3.2.14, < 5.0.0)
|
||||
activemerchant (1.71.0)
|
||||
activesupport (>= 3.2.14, < 6.x)
|
||||
builder (>= 2.1.2, < 4.0.0)
|
||||
i18n (>= 0.6.9)
|
||||
nokogiri (~> 1.4)
|
||||
@@ -198,9 +198,7 @@ GEM
|
||||
blockenspiel (0.4.5)
|
||||
bugsnag (4.1.0)
|
||||
builder (3.0.4)
|
||||
byebug (2.7.0)
|
||||
columnize (~> 0.3)
|
||||
debugger-linecache (~> 1.2)
|
||||
byebug (9.0.6)
|
||||
cancan (1.6.8)
|
||||
capybara (2.7.1)
|
||||
addressable
|
||||
@@ -217,7 +215,7 @@ GEM
|
||||
cliver (0.3.2)
|
||||
cocaine (0.5.8)
|
||||
climate_control (>= 0.0.3, < 1.0)
|
||||
coderay (1.0.9)
|
||||
coderay (1.1.2)
|
||||
coffee-rails (3.2.2)
|
||||
coffee-script (>= 2.2.0)
|
||||
railties (~> 3.2.0)
|
||||
@@ -226,7 +224,6 @@ GEM
|
||||
execjs
|
||||
coffee-script-source (1.10.0)
|
||||
colorize (0.8.1)
|
||||
columnize (0.9.0)
|
||||
compass (1.0.3)
|
||||
chunky_png (~> 1.2)
|
||||
compass-core (~> 1.0.2)
|
||||
@@ -283,6 +280,8 @@ GEM
|
||||
factory_girl_rails (3.3.0)
|
||||
factory_girl (~> 3.3.0)
|
||||
railties (>= 3.0.0)
|
||||
faraday (0.9.2)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffaker (1.15.0)
|
||||
ffi (1.9.3)
|
||||
figaro (0.7.0)
|
||||
@@ -450,6 +449,7 @@ GEM
|
||||
json_spec (1.1.1)
|
||||
multi_json (~> 1.0)
|
||||
rspec (~> 2.0)
|
||||
jwt (1.5.4)
|
||||
kaminari (0.13.0)
|
||||
actionpack (>= 3.0.0)
|
||||
activesupport (>= 3.0.0)
|
||||
@@ -471,7 +471,7 @@ GEM
|
||||
mail (2.5.4)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
method_source (0.8.2)
|
||||
method_source (0.9.0)
|
||||
mime-types (1.25.1)
|
||||
mini_portile2 (2.1.0)
|
||||
momentjs-rails (2.5.1)
|
||||
@@ -480,9 +480,16 @@ GEM
|
||||
i18n (~> 0.6.0)
|
||||
multi_json (1.12.1)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.0.0)
|
||||
newrelic_rpm (3.12.0.288)
|
||||
nokogiri (1.6.8.1)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
oauth2 (1.2.0)
|
||||
faraday (>= 0.8, < 0.10)
|
||||
jwt (~> 1.0)
|
||||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
rack (>= 1.2, < 3)
|
||||
oj (2.1.2)
|
||||
orm_adapter (0.5.0)
|
||||
paper_trail (3.0.8)
|
||||
@@ -513,13 +520,12 @@ GEM
|
||||
activerecord (~> 3.0)
|
||||
polyglot (0.3.5)
|
||||
powerpack (0.1.1)
|
||||
pry (0.9.12.2)
|
||||
coderay (~> 1.0.5)
|
||||
method_source (~> 0.8)
|
||||
slop (~> 3.4)
|
||||
pry-byebug (1.3.2)
|
||||
byebug (~> 2.7)
|
||||
pry (~> 0.9.12)
|
||||
pry (0.11.1)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.9.0)
|
||||
pry-byebug (3.4.3)
|
||||
byebug (>= 9.0, < 9.1)
|
||||
pry (~> 0.10)
|
||||
rabl (0.7.2)
|
||||
activesupport (>= 2.3.14)
|
||||
multi_json (~> 1.0)
|
||||
@@ -619,7 +625,6 @@ GEM
|
||||
thor (~> 0.14)
|
||||
shoulda-matchers (1.1.0)
|
||||
activesupport (>= 3.0.0)
|
||||
slop (3.4.5)
|
||||
spinjs-rails (1.3)
|
||||
rails (>= 3.1)
|
||||
sprockets (2.2.3)
|
||||
@@ -629,6 +634,8 @@ GEM
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
state_machine (1.2.0)
|
||||
stringex (1.3.3)
|
||||
stripe (3.3.1)
|
||||
faraday (~> 0.9)
|
||||
therubyracer (0.12.0)
|
||||
libv8 (~> 3.16.14.0)
|
||||
ref
|
||||
@@ -684,6 +691,7 @@ PLATFORMS
|
||||
|
||||
DEPENDENCIES
|
||||
active_model_serializers
|
||||
activemerchant (~> 1.71.0)
|
||||
acts-as-taggable-on (~> 3.4)
|
||||
andand
|
||||
angular-rails-templates (~> 0.2.0)
|
||||
@@ -694,6 +702,7 @@ DEPENDENCIES
|
||||
aws-sdk
|
||||
blockenspiel
|
||||
bugsnag
|
||||
byebug (~> 9.0.0)
|
||||
capybara
|
||||
coffee-rails (~> 3.2.1)
|
||||
compass-rails
|
||||
@@ -728,11 +737,13 @@ DEPENDENCIES
|
||||
jquery-migrate-rails
|
||||
jquery-rails
|
||||
json_spec
|
||||
jwt (~> 1.5)
|
||||
knapsack
|
||||
letter_opener
|
||||
momentjs-rails
|
||||
newrelic_rpm
|
||||
nokogiri (>= 1.6.7.1)
|
||||
oauth2 (~> 1.2.0)
|
||||
ofn-qz!
|
||||
oj
|
||||
paper_trail (~> 3.0.8)
|
||||
@@ -740,7 +751,7 @@ DEPENDENCIES
|
||||
parallel_tests
|
||||
pg
|
||||
poltergeist
|
||||
pry-byebug
|
||||
pry-byebug (>= 3.4.3)
|
||||
rabl
|
||||
rack-livereload
|
||||
rack-ssl
|
||||
@@ -762,6 +773,7 @@ DEPENDENCIES
|
||||
spree_auth_devise!
|
||||
spree_i18n!
|
||||
spree_paypal_express!
|
||||
stripe (~> 3.3.1)
|
||||
therubyracer
|
||||
timecop
|
||||
truncate_html
|
||||
|
||||
26
README.md
26
README.md
@@ -72,18 +72,22 @@ createuser -s -P ofn
|
||||
```
|
||||
|
||||
Create the development and test databases, using the settings specified in `config/database.yml`, and populate them with a schema and seed data:
|
||||
|
||||
rake db:setup
|
||||
|
||||
```
|
||||
bundle exec rake db:setup
|
||||
```
|
||||
Load some default data for your environment:
|
||||
|
||||
rake openfoodnetwork:dev:load_sample_data
|
||||
|
||||
```
|
||||
bundle exec rake openfoodnetwork:dev:load_sample_data
|
||||
```
|
||||
At long last, your dreams of spinning up a development server can be realised:
|
||||
|
||||
rails server
|
||||
|
||||
|
||||
```
|
||||
bundle exec rails server
|
||||
```
|
||||
To login as Spree default user, use:
|
||||
```
|
||||
email: spree@example.com
|
||||
password: spree123
|
||||
```
|
||||
### Testing
|
||||
|
||||
Tests, both unit and integration, are based on RSpec. To run the test suite, first prepare the test database:
|
||||
@@ -123,7 +127,7 @@ Do not forget to run `rake tmp:cache:clear` after locales are updated to reload
|
||||
* Maikel Linke (https://github.com/mkllnk)
|
||||
* Lynne Davis (https://github.com/lin-d-hop)
|
||||
* Paul Mackay (https://github.com/pmackay)
|
||||
* Steve Petitt (https://github.com/stveep)
|
||||
* Steve Pettitt (https://github.com/stveep)
|
||||
|
||||
|
||||
## Licence
|
||||
|
||||
@@ -22,7 +22,7 @@ angular.module("admin.enterprises")
|
||||
{ name: 'users', label: t('users'), icon_class: "icon-user" }
|
||||
]
|
||||
|
||||
$scope.select(0)
|
||||
SideMenu.init()
|
||||
|
||||
$scope.showItem = (item) ->
|
||||
if item.show?
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
angular.module("admin.paymentMethods").controller "StripeController", ($scope, $http, shops) ->
|
||||
$scope.shops = shops
|
||||
$scope.stripe_account = {}
|
||||
|
||||
$scope.$watch "paymentMethod.preferred_enterprise_id", (newID, oldID) ->
|
||||
return unless newID?
|
||||
$scope.stripe_account = {}
|
||||
$http.get("/admin/stripe_accounts/status.json?enterprise_id=#{newID}").success (data) ->
|
||||
angular.extend($scope.stripe_account, data)
|
||||
.error (response) ->
|
||||
$scope.stripe_account.status = "request_failed"
|
||||
|
||||
$scope.current_enterprise_stripe_path = ->
|
||||
return unless $scope.paymentMethod.preferred_enterprise_id?
|
||||
permalink = shops.filter((shop) ->
|
||||
shop.id == $scope.paymentMethod.preferred_enterprise_id
|
||||
)[0].permalink
|
||||
"/admin/enterprises/#{permalink}/edit#/payment_methods"
|
||||
33
app/assets/javascripts/admin/payments/new.js
Normal file
33
app/assets/javascripts/admin/payments/new.js
Normal file
@@ -0,0 +1,33 @@
|
||||
// Override of Spree's logic in the file of the same name
|
||||
// Changes made as per https://github.com/spree/spree/commit/8a3a80b08abf80fbed2fcee4b429ba1caf68baf1
|
||||
// which allows the form partial in admin/payments/new to be switched using radio buttons
|
||||
// We can remove this file when we reach 2.3.0
|
||||
|
||||
$(document).ready(function() {
|
||||
if ($("#new_payment").is("*")) {
|
||||
$('.payment_methods_radios').click(
|
||||
function() {
|
||||
$('.payment-methods').hide();
|
||||
if (this.checked) {
|
||||
$('#payment_method_' + this.value).show();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$('.payment_methods_radios').each(
|
||||
function() {
|
||||
if (this.checked) {
|
||||
$('#payment_method_' + this.value).show();
|
||||
} else {
|
||||
$('#payment_method_' + this.value).hide();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
$(".card_new").radioControlsVisibilityOfElement('.card_form');
|
||||
|
||||
$('select.jump_menu').change(function(){
|
||||
window.location = this.options[this.selectedIndex].value;
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -12,11 +12,10 @@ angular.module("admin.products").factory "VariantUnitManager", ->
|
||||
|
||||
@variantUnitOptions: ->
|
||||
options = for unit_type, scale_with_name of @unitNames
|
||||
unit_type_cap = unit_type[0].toUpperCase() + unit_type[1..-1]
|
||||
for scale in @unitScales(unit_type)
|
||||
name = @getUnitName(scale, unit_type)
|
||||
["#{unit_type_cap} (#{name})", "#{unit_type}_#{scale}"]
|
||||
options.push [['Items', 'items']]
|
||||
["#{I18n.t(unit_type)} (#{name})", "#{unit_type}_#{scale}"]
|
||||
options.push [[I18n.t('items'), 'items']]
|
||||
[].concat options...
|
||||
|
||||
@getScale: (value, unitType) ->
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
angular.module("admin.side_menu")
|
||||
.factory "SideMenu", ->
|
||||
.factory "SideMenu", ($location) ->
|
||||
new class SideMenu
|
||||
items: []
|
||||
selected: null
|
||||
|
||||
|
||||
# Checks for path and uses it to set the view
|
||||
# If no path, loads first view
|
||||
init: =>
|
||||
path = $location.path()?.match(/^\/\w+$/)?[0]
|
||||
index = if path
|
||||
name = path[1..]
|
||||
@items.indexOf(@find_by_name(name))
|
||||
else
|
||||
0
|
||||
@select(index)
|
||||
|
||||
setItems: (items) =>
|
||||
@items = items
|
||||
item.visible = true for item in @items
|
||||
@@ -13,6 +25,7 @@ angular.module("admin.side_menu")
|
||||
@selected.selected = false if @selected
|
||||
@selected = @items[index]
|
||||
@selected.selected = true
|
||||
$location.path(@selected.name)
|
||||
|
||||
find_by_name: (name) =>
|
||||
for item in @items when item.name is name
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("admin.indexUtils").directive "ofnSelect2", ($sanitize, $timeout, $filter) ->
|
||||
angular.module("admin.utils").directive "ofnSelect2", ($sanitize, $timeout, $filter) ->
|
||||
require: 'ngModel'
|
||||
restrict: 'C'
|
||||
scope:
|
||||
@@ -22,6 +22,6 @@ Darkswarm.controller "CheckoutCtrl", ($scope, localStorageService, Checkout, Cur
|
||||
event.preventDefault()
|
||||
$scope.submitted = true
|
||||
if form.$valid
|
||||
$scope.Checkout.submit()
|
||||
$scope.Checkout.purchase()
|
||||
else
|
||||
$scope.$broadcast 'purchaseFormInvalid', form
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
Darkswarm.controller "PaymentCtrl", ($scope, $timeout) ->
|
||||
Darkswarm.controller "PaymentCtrl", ($scope, $timeout, savedCreditCards, Dates) ->
|
||||
angular.extend(this, new FieldsetMixin($scope))
|
||||
|
||||
$scope.savedCreditCards = savedCreditCards
|
||||
$scope.name = "payment"
|
||||
$scope.months = Dates.months
|
||||
$scope.years = Dates.years
|
||||
|
||||
$scope.months = [
|
||||
{key: t("january"), value: "1"},
|
||||
{key: t("february"), value: "2"},
|
||||
{key: t("march"), value: "3"},
|
||||
{key: t("april"), value: "4"},
|
||||
{key: t("may"), value: "5"},
|
||||
{key: t("june"), value: "6"},
|
||||
{key: t("july"), value: "7"},
|
||||
{key: t("august"), value: "8"},
|
||||
{key: t("september"), value: "9"},
|
||||
{key: t("october"), value: "10"},
|
||||
{key: t("november"), value: "11"},
|
||||
{key: t("december"), value: "12"},
|
||||
]
|
||||
|
||||
$scope.years = [moment().year()..(moment().year()+15)]
|
||||
$scope.secrets.card_month = "1"
|
||||
$scope.secrets.card_year = moment().year()
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
Darkswarm.controller "CreditCardsCtrl", ($scope, $timeout, CreditCard, CreditCards, Dates) ->
|
||||
angular.extend(this, new FieldsetMixin($scope))
|
||||
$scope.savedCreditCards = CreditCards.saved
|
||||
$scope.CreditCard = CreditCard
|
||||
$scope.secrets = CreditCard.secrets
|
||||
$scope.showForm = CreditCard.show
|
||||
$scope.storeCard = ->
|
||||
if $scope.new_card_form.$valid
|
||||
CreditCard.requestToken()
|
||||
|
||||
$scope.allow_name_change = true
|
||||
$scope.disable_fields = false
|
||||
@@ -1,9 +0,0 @@
|
||||
Darkswarm.controller "DistributorNodeCtrl", ($scope, HashNavigation, $anchorScroll) ->
|
||||
$scope.toggle = ->
|
||||
HashNavigation.toggle $scope.distributor.hash
|
||||
|
||||
$scope.open = ->
|
||||
HashNavigation.active($scope.distributor.hash)
|
||||
|
||||
if $scope.open()
|
||||
$anchorScroll()
|
||||
@@ -1,2 +1,2 @@
|
||||
Darkswarm.controller "OrdersCtrl", ($scope, $rootScope, $timeout, Orders, Search, $document, HashNavigation, FilterSelectorsService, EnterpriseModal, enterpriseMatchesNameQueryFilter, distanceWithinKmFilter) ->
|
||||
Darkswarm.controller "OrdersCtrl", ($scope, Orders) ->
|
||||
$scope.Orders = Orders
|
||||
|
||||
@@ -1,15 +1,23 @@
|
||||
Darkswarm.controller "RegistrationFormCtrl", ($scope, RegistrationService, EnterpriseRegistrationService) ->
|
||||
$scope.submitted = false
|
||||
$scope.isDisabled = false
|
||||
|
||||
$scope.valid = (form) ->
|
||||
$scope.submitted = !form.$valid
|
||||
form.$valid
|
||||
|
||||
$scope.create = (form) ->
|
||||
EnterpriseRegistrationService.create() if $scope.valid(form)
|
||||
$scope.disableButton()
|
||||
EnterpriseRegistrationService.create($scope.enableButton) if $scope.valid(form)
|
||||
|
||||
$scope.update = (nextStep, form) ->
|
||||
EnterpriseRegistrationService.update(nextStep) if $scope.valid(form)
|
||||
|
||||
$scope.selectIfValid = (nextStep, form) ->
|
||||
RegistrationService.select(nextStep) if $scope.valid(form)
|
||||
|
||||
$scope.disableButton = ->
|
||||
$scope.isDisabled = true
|
||||
|
||||
$scope.enableButton = ->
|
||||
$scope.isDisabled = false
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
Darkswarm.controller "ShopNodeCtrl", ($scope, HashNavigation, $anchorScroll) ->
|
||||
$scope.toggle = ->
|
||||
HashNavigation.toggle $scope.shop.hash
|
||||
|
||||
$scope.open = ->
|
||||
HashNavigation.active($scope.shop.hash)
|
||||
|
||||
if $scope.open()
|
||||
$anchorScroll()
|
||||
@@ -0,0 +1,35 @@
|
||||
Darkswarm.directive "stripeElements", ($injector, StripeElements) ->
|
||||
restrict: 'E'
|
||||
template: "<label for='card-element'>\
|
||||
<div id='card-element'></div>\
|
||||
<div id='card-errors' class='error'></div>\
|
||||
</label>"
|
||||
|
||||
link: (scope, elem, attr)->
|
||||
if $injector.has('stripeObject')
|
||||
stripe = $injector.get('stripeObject')
|
||||
|
||||
card = stripe.elements().create 'card',
|
||||
hidePostalCode: false
|
||||
style:
|
||||
base:
|
||||
fontFamily: "Roboto, Arial, sans-serif"
|
||||
fontSize: '16px'
|
||||
color: '#5c5c5c'
|
||||
'::placeholder':
|
||||
color: '#6c6c6c'
|
||||
card.mount('#card-element')
|
||||
|
||||
# Elements validates user input as it is typed. To help your customers
|
||||
# catch mistakes, you should listen to change events on the card Element
|
||||
# and display any errors:
|
||||
card.addEventListener 'change', (event) ->
|
||||
displayError = document.getElementById('card-errors')
|
||||
if event.error
|
||||
displayError.textContent = event.error.message
|
||||
else
|
||||
displayError.textContent = ''
|
||||
return
|
||||
|
||||
StripeElements.stripe = stripe
|
||||
StripeElements.card = card
|
||||
12
app/assets/javascripts/darkswarm/directives/tab.js.coffee
Normal file
12
app/assets/javascripts/darkswarm/directives/tab.js.coffee
Normal file
@@ -0,0 +1,12 @@
|
||||
Darkswarm.directive "tab", ->
|
||||
restrict: "C"
|
||||
require: "^^tabsetCtrl"
|
||||
scope:
|
||||
name: "@"
|
||||
link: (scope, element, attrs, ctrl) ->
|
||||
element.on "click", ->
|
||||
scope.$apply ->
|
||||
ctrl.toggle(scope.name)
|
||||
|
||||
ctrl.registerSelectionListener (prefix, selection) ->
|
||||
element.toggleClass('selected', selection == scope.name)
|
||||
15
app/assets/javascripts/darkswarm/directives/tab_view.coffee
Normal file
15
app/assets/javascripts/darkswarm/directives/tab_view.coffee
Normal file
@@ -0,0 +1,15 @@
|
||||
Darkswarm.directive "tabView", ->
|
||||
restrict: "C"
|
||||
require: "^^tabsetCtrl"
|
||||
template: "<div ng-include='template'></div>"
|
||||
scope:
|
||||
templates: "="
|
||||
link: (scope, element, attrs, ctrl) ->
|
||||
scope.template = null
|
||||
|
||||
ctrl.registerSelectionListener (prefix, selection) ->
|
||||
if selection?
|
||||
selection = "#{prefix}/#{selection}" if prefix?
|
||||
scope.template = "#{selection}.html"
|
||||
else
|
||||
scope.template = null
|
||||
@@ -0,0 +1,28 @@
|
||||
Darkswarm.directive "tabsetCtrl", (Tabsets, $location) ->
|
||||
restrict: "C"
|
||||
scope:
|
||||
id: "@"
|
||||
selected: "@"
|
||||
navigate: "="
|
||||
prefix: "@?"
|
||||
controller: ($scope, $element) ->
|
||||
if $scope.navigate
|
||||
path = $location.path()?.match(/^\/\w+$/)?[0]
|
||||
$scope.selected = path[1..] if path
|
||||
|
||||
this.toggle = (name) ->
|
||||
Tabsets.toggle($scope.id, name)
|
||||
|
||||
this.select = (selection) ->
|
||||
$scope.$broadcast("selection:changed", selection)
|
||||
$element.toggleClass("expanded", selection?)
|
||||
$location.path(selection) if $scope.navigate
|
||||
|
||||
this.registerSelectionListener = (callback) ->
|
||||
$scope.$on "selection:changed", (event, selection) ->
|
||||
callback($scope.prefix, selection)
|
||||
|
||||
this
|
||||
|
||||
link: (scope, element, attrs, ctrl) ->
|
||||
Tabsets.register(ctrl, scope.id, scope.selected)
|
||||
@@ -3,13 +3,12 @@ Darkswarm.filter "localizeCurrency", (currencyConfig)->
|
||||
(amount) ->
|
||||
# Set country code (eg. "US").
|
||||
currency_code = if currencyConfig.display_currency then " " + currencyConfig.currency else ""
|
||||
# Set decimal points, 2 or 0 if hide_cents.
|
||||
# Set decimal points, 2 or 0 if hide_cents.
|
||||
decimals = if currencyConfig.hide_cents == "true" then 0 else 2
|
||||
# We need to use parseFloat before toFixed as the amount should come in as a string.
|
||||
amount_fixed = parseFloat(amount).toFixed(decimals)
|
||||
# Set format if the currency symbol should come after the number, otherwise (default) use the locale setting.
|
||||
format = if currencyConfig.symbol_position == "after" then "%n %u" else undefined
|
||||
# We need to use parseFloat as the amount should come in as a string.
|
||||
amount = parseFloat(amount)
|
||||
|
||||
# Build the final price string. TODO use spree decimal point and spacer character settings.
|
||||
if currencyConfig.symbol_position == 'before'
|
||||
currencyConfig.symbol + amount_fixed + currency_code
|
||||
else
|
||||
amount_fixed + " " + currencyConfig.symbol + currency_code
|
||||
# Build the final price string.
|
||||
I18n.toCurrency(amount, {precision: decimals, unit: currencyConfig.symbol, format: format}) + currency_code
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
Darkswarm.factory 'Checkout', (CurrentOrder, ShippingMethods, PaymentMethods, $http, Navigation, CurrentHub, RailsFlashLoader, Loading)->
|
||||
Darkswarm.factory 'Checkout', ($injector, CurrentOrder, ShippingMethods, StripeElements, PaymentMethods, $http, Navigation, CurrentHub, RailsFlashLoader, Loading)->
|
||||
new class Checkout
|
||||
errors: {}
|
||||
secrets: {}
|
||||
order: CurrentOrder.order
|
||||
|
||||
submit: ->
|
||||
purchase: ->
|
||||
if @paymentMethod()?.method_type == 'stripe' && !@secrets.selected_card
|
||||
StripeElements.requestToken(@secrets, @submit)
|
||||
else
|
||||
@submit()
|
||||
|
||||
submit: =>
|
||||
Loading.message = t 'submitting_order'
|
||||
$http.put('/checkout', {order: @preprocess()}).success (data, status)=>
|
||||
$http.put('/checkout.json', {order: @preprocess()}).success (data, status)=>
|
||||
Navigation.go data.path
|
||||
.error (response, status)=>
|
||||
if response.path
|
||||
@@ -53,6 +59,23 @@ Darkswarm.factory 'Checkout', (CurrentOrder, ShippingMethods, PaymentMethods, $h
|
||||
last_name: @order.bill_address.lastname
|
||||
}
|
||||
|
||||
if @paymentMethod()?.method_type == 'stripe'
|
||||
if @secrets.selected_card
|
||||
angular.extend munged_order, {
|
||||
existing_card_id: @secrets.selected_card
|
||||
}
|
||||
else
|
||||
angular.extend munged_order.payments_attributes[0], {
|
||||
source_attributes:
|
||||
gateway_payment_profile_id: @secrets.token
|
||||
cc_type: @secrets.cc_type
|
||||
last_digits: @secrets.card.last4
|
||||
month: @secrets.card.exp_month
|
||||
year: @secrets.card.exp_year
|
||||
first_name: @order.bill_address.firstname
|
||||
last_name: @order.bill_address.lastname
|
||||
save_requested_by_customer: @secrets.save_requested_by_customer
|
||||
}
|
||||
munged_order
|
||||
|
||||
shippingMethod: ->
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
Darkswarm.factory 'CreditCard', ($injector, $rootScope, CreditCards, StripeElements, Navigation, $http, RailsFlashLoader, Loading)->
|
||||
new class CreditCard
|
||||
visible: false
|
||||
errors: {}
|
||||
secrets: {}
|
||||
|
||||
requestToken: =>
|
||||
@setFullName()
|
||||
StripeElements.requestToken(@secrets, @submit, t("saving_credit_card"))
|
||||
|
||||
submit: =>
|
||||
params = @process_params()
|
||||
$http.put('/credit_cards/new_from_token', params )
|
||||
.success (data, status) =>
|
||||
Loading.clear()
|
||||
@reset()
|
||||
CreditCards.add(data)
|
||||
.error (response, status) =>
|
||||
if response.path
|
||||
Navigation.go response.path
|
||||
else
|
||||
Loading.clear()
|
||||
@errors = response.errors
|
||||
RailsFlashLoader.loadFlash(response.flash)
|
||||
|
||||
setFullName: ->
|
||||
@secrets.name = "#{@secrets.first_name} #{@secrets.last_name}"
|
||||
|
||||
process_params: ->
|
||||
{"exp_month": @secrets.card.exp_month,
|
||||
"exp_year": @secrets.card.exp_year,
|
||||
"last4": @secrets.card.last4,
|
||||
"token": @secrets.token,
|
||||
"cc_type": @secrets.cc_type}
|
||||
|
||||
show: => @visible = true
|
||||
|
||||
reset: =>
|
||||
@visible = false
|
||||
delete @secrets[k] for k, v of @secrets
|
||||
delete @errors[k] for k, v of @errors
|
||||
@@ -0,0 +1,6 @@
|
||||
Darkswarm.factory 'CreditCards', (savedCreditCards)->
|
||||
new class CreditCard
|
||||
saved: savedCreditCards
|
||||
|
||||
add: (card) ->
|
||||
@saved.push card
|
||||
18
app/assets/javascripts/darkswarm/services/dates.js.coffee
Normal file
18
app/assets/javascripts/darkswarm/services/dates.js.coffee
Normal file
@@ -0,0 +1,18 @@
|
||||
Darkswarm.factory "Dates", ->
|
||||
new class Dates
|
||||
months: [
|
||||
{key: t("january"), value: "1"},
|
||||
{key: t("february"), value: "2"},
|
||||
{key: t("march"), value: "3"},
|
||||
{key: t("april"), value: "4"},
|
||||
{key: t("may"), value: "5"},
|
||||
{key: t("june"), value: "6"},
|
||||
{key: t("july"), value: "7"},
|
||||
{key: t("august"), value: "8"},
|
||||
{key: t("september"), value: "9"},
|
||||
{key: t("october"), value: "10"},
|
||||
{key: t("november"), value: "11"},
|
||||
{key: t("december"), value: "12"},
|
||||
]
|
||||
|
||||
years: [moment().year()..(moment().year()+15)]
|
||||
@@ -11,7 +11,11 @@ Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService,
|
||||
for key, value of enterpriseAttributes
|
||||
@enterprise[key] = value
|
||||
|
||||
create: =>
|
||||
# Creates the enterprise and redirects to the about step on success.
|
||||
#
|
||||
# @param callback [Function] executed at the end of the operation both in
|
||||
# case of success or failure.
|
||||
create: (callback) =>
|
||||
Loading.message = t('creating') + " " + @enterprise.name
|
||||
$http(
|
||||
method: "POST"
|
||||
@@ -33,6 +37,7 @@ Darkswarm.factory "EnterpriseRegistrationService", ($http, RegistrationService,
|
||||
else
|
||||
alert(t('failed_to_create_enterprise_unknown'))
|
||||
)
|
||||
callback.call() if callback?
|
||||
|
||||
update: (step) =>
|
||||
Loading.message = t('updating') + " " + @enterprise.name
|
||||
|
||||
@@ -21,3 +21,6 @@ Darkswarm.factory 'Navigation', ($location, $window) ->
|
||||
$window.location.href = path
|
||||
else
|
||||
$window.location.pathname = path
|
||||
|
||||
reload: ->
|
||||
$window.location.reload()
|
||||
|
||||
@@ -1,22 +1,25 @@
|
||||
Darkswarm.factory 'Orders', (orders_by_distributor, currencyConfig, CurrentHub, Taxons, Dereferencer, visibleFilter, Matcher, Geo, $rootScope)->
|
||||
Darkswarm.factory 'Orders', (orders, shops, currencyConfig)->
|
||||
new class Orders
|
||||
all: orders
|
||||
changeable: []
|
||||
shops: shops
|
||||
shopsByID: {}
|
||||
currencySymbol = currencyConfig.symbol
|
||||
|
||||
constructor: ->
|
||||
# Populate Orders.orders from json in page.
|
||||
@orders_by_distributor = orders_by_distributor
|
||||
@changeable_orders = []
|
||||
@currency_symbol = currencyConfig.symbol
|
||||
for shop in @shops
|
||||
shop.orders = []
|
||||
shop.balance = 0.0
|
||||
@shopsByID[shop.id] = shop
|
||||
|
||||
for distributor in @orders_by_distributor
|
||||
@findChangeableOrders(distributor.distributed_orders)
|
||||
@updateRunningBalance(distributor.distributed_orders)
|
||||
for order in @all by -1
|
||||
shop = @shopsByID[order.shop_id]
|
||||
shop.orders.unshift order
|
||||
|
||||
@changeable.unshift(order) if order.changes_allowed
|
||||
|
||||
updateRunningBalance: (orders) ->
|
||||
for order, i in orders
|
||||
balances = orders.slice(i,orders.length).map (o) -> parseFloat(o.outstanding_balance)
|
||||
running_balance = balances.reduce (a,b) -> a+b
|
||||
order.running_balance = running_balance.toFixed(2)
|
||||
@updateRunningBalance(shop, order)
|
||||
|
||||
findChangeableOrders: (orders) ->
|
||||
for order in orders when order.changes_allowed
|
||||
@changeable_orders.push(order)
|
||||
updateRunningBalance: (shop, order) ->
|
||||
shop.balance += parseFloat(order.outstanding_balance)
|
||||
order.runningBalance = shop.balance.toFixed(2)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
Darkswarm.factory 'StripeElements', ($rootScope, Loading, RailsFlashLoader) ->
|
||||
new class StripeElements
|
||||
# TODO: add locale here for translations of error messages etc. from Stripe
|
||||
|
||||
# These are both set from the StripeElements directive
|
||||
stripe: null
|
||||
card: null
|
||||
|
||||
# New Stripe Elements method
|
||||
requestToken: (secrets, submit, loading_message = t("processing_payment")) ->
|
||||
return unless @stripe? && @card?
|
||||
|
||||
Loading.message = loading_message
|
||||
cardData = @makeCardData(secrets)
|
||||
|
||||
@stripe.createToken(@card, cardData).then (response) =>
|
||||
if(response.error)
|
||||
Loading.clear()
|
||||
RailsFlashLoader.loadFlash({error: t("error") + ": #{response.error.message}"})
|
||||
else
|
||||
secrets.token = response.token.id
|
||||
secrets.cc_type = @mapCC(response.token.card.brand)
|
||||
secrets.card = response.token.card
|
||||
submit()
|
||||
|
||||
# Maps the brand returned by Stripe to that required by activemerchant
|
||||
mapCC: (ccType) ->
|
||||
if ccType == 'MasterCard'
|
||||
return 'master'
|
||||
else if ccType == 'Visa'
|
||||
return 'visa'
|
||||
else if ccType == 'American Express'
|
||||
return 'american_express'
|
||||
else if ccType == 'Discover'
|
||||
return 'discover'
|
||||
else if ccType == 'JCB'
|
||||
return 'jcb'
|
||||
else if ccType == 'Diners Club'
|
||||
return 'diners_club'
|
||||
return
|
||||
|
||||
# It doesn't matter if any of these are nil, all are optional.
|
||||
makeCardData: (secrets) ->
|
||||
{'name': secrets.name,
|
||||
'address1': secrets.address1,
|
||||
'city': secrets.city,
|
||||
'zipcode': secrets.zipcode}
|
||||
22
app/assets/javascripts/darkswarm/services/tabsets.js.coffee
Normal file
22
app/assets/javascripts/darkswarm/services/tabsets.js.coffee
Normal file
@@ -0,0 +1,22 @@
|
||||
Darkswarm.factory 'Tabsets', ->
|
||||
new class Tabsets
|
||||
tabsets: []
|
||||
|
||||
register: (ctrl, id, selected=null) ->
|
||||
if ctrl? && id?
|
||||
@tabsets.push { ctrl: ctrl, id: id, selected: selected }
|
||||
ctrl.select(selected) if selected?
|
||||
|
||||
toggle: (id, name, state=null) ->
|
||||
tabset = @findTabsetByObject(id)
|
||||
if tabset.selected == name
|
||||
@select(tabset, null) unless state == "open"
|
||||
else
|
||||
@select(tabset, name) unless state == "closed"
|
||||
|
||||
select: (tabset, name) ->
|
||||
tabset.selected = name
|
||||
tabset.ctrl.select(name)
|
||||
|
||||
findTabsetByObject: (id) ->
|
||||
(tabset for tabset in @tabsets when tabset.id == id)[0]
|
||||
80
app/assets/stylesheets/admin/components/alert-box.css.scss
Normal file
80
app/assets/stylesheets/admin/components/alert-box.css.scss
Normal file
@@ -0,0 +1,80 @@
|
||||
@import "../../darkswarm/mixins";
|
||||
|
||||
.alert-box {
|
||||
position: relative;
|
||||
display: block;
|
||||
background-color: #eff5dc;
|
||||
border: 1px solid #9fc820;
|
||||
color: #666;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
|
||||
@include border-radius(3px);
|
||||
|
||||
transition: opacity 300ms ease-out;
|
||||
padding: 0.77778em 1.33333em 0.77778em 0.77778em;
|
||||
|
||||
a.close {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
&.ok {
|
||||
border: 1px solid #9fc820;
|
||||
background-color: #fbffee;
|
||||
color: #9fc820;
|
||||
font-weight: bold;
|
||||
|
||||
a.button {
|
||||
padding: 3px 10px;
|
||||
background-color: #a7c44d;
|
||||
&:hover {
|
||||
background-color: #9fc820;
|
||||
}
|
||||
}
|
||||
|
||||
a.close {
|
||||
color: #9fc820;
|
||||
}
|
||||
}
|
||||
|
||||
&.error {
|
||||
border: 1px solid #c82020;
|
||||
background-color: #f5dcdc;
|
||||
color: #c82020;
|
||||
font-weight: bold;
|
||||
|
||||
a.button {
|
||||
padding: 3px 10px;
|
||||
background-color: #c85252;
|
||||
&:hover {
|
||||
background-color: #c82020;
|
||||
}
|
||||
}
|
||||
|
||||
a.close {
|
||||
color: #c82020;
|
||||
}
|
||||
}
|
||||
|
||||
&.warning {
|
||||
border: 1px solid #e6912e;
|
||||
background-color: #fff4e6;
|
||||
color: #e6912e;
|
||||
font-weight: bold;
|
||||
|
||||
a.button {
|
||||
padding: 3px 10px;
|
||||
background-color: #db9350;
|
||||
&:hover {
|
||||
background-color: #e6912e;
|
||||
}
|
||||
}
|
||||
|
||||
a.close {
|
||||
color: #e6912e;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,8 +24,6 @@ light: #ccc
|
||||
}
|
||||
}
|
||||
|
||||
/*.ui-dialog .ui-icon-closethick{background:url(/static/assets/dialogCloseButton.png);}*/
|
||||
|
||||
.ui-dialog .ui-widget-header{
|
||||
background-image: none;
|
||||
background-color: #ffffff;
|
||||
@@ -42,21 +40,18 @@ light: #ccc
|
||||
.ui-dialog .ui-corner-all{
|
||||
border-radius: 8px;
|
||||
}
|
||||
.ui-dialog {
|
||||
.ui-state-hover, .ui-state-focus{
|
||||
border: none;
|
||||
background: none;
|
||||
color: #545454;
|
||||
}
|
||||
}
|
||||
|
||||
.ui-state-hover, .ui-widget-header .ui-state-hover, .ui-widget-content .ui-state-hover {
|
||||
background-color: #ffffff;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.ui-dialog-titlebar-close {
|
||||
.ui-dialog .ui-dialog-titlebar .ui-dialog-titlebar-close {
|
||||
float: right;
|
||||
|
||||
border: none;
|
||||
background: none;
|
||||
|
||||
&:before {
|
||||
color: #000000;
|
||||
font-size: 2em;
|
||||
@@ -76,9 +71,18 @@ light: #ccc
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.ui-button-text {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.ui-widget-overlay {
|
||||
background: #000000;
|
||||
opacity: 0.5;
|
||||
position: fixed;
|
||||
height: 100vh;
|
||||
width: 100vw;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,27 +1,5 @@
|
||||
@import "../darkswarm/mixins";
|
||||
|
||||
.alert-box {
|
||||
position: relative;
|
||||
display: block;
|
||||
background-color: #eff5dc;
|
||||
border: 1px solid #9fc820;
|
||||
color: #666;
|
||||
margin-top: 1em;
|
||||
margin-bottom: 1em;
|
||||
|
||||
@include border-radius(3px);
|
||||
|
||||
transition: opacity 300ms ease-out;
|
||||
padding: 0.77778em 1.33333em 0.77778em 0.77778em;
|
||||
|
||||
a.close {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 0px;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
}
|
||||
|
||||
.dashboard_item.single-ent {
|
||||
.header {
|
||||
padding: 0.77778em 1.33333em 0.77778em 0.77778em;
|
||||
|
||||
@@ -43,6 +43,13 @@ input.red {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
a.button.red {
|
||||
&:not(:hover) {
|
||||
color: #fff;
|
||||
background-color: #DA5354;
|
||||
}
|
||||
}
|
||||
|
||||
input.orange {
|
||||
background-color: #FF9848;
|
||||
margin-right: 5px;
|
||||
|
||||
@@ -69,4 +69,10 @@ table#listing_products.bulk {
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
}
|
||||
|
||||
td.left-actions {
|
||||
a.view-variants, a.add-variant {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,9 +5,32 @@
|
||||
color: #4a4a4a;
|
||||
}
|
||||
|
||||
.credit_cards {
|
||||
.saved_cards {
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.saved_cards, .no_cards {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.new_card {
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 0.4s linear;
|
||||
transition: opacity 0.4s linear;
|
||||
&.visible {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
input.ng-invalid {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.orders {
|
||||
margin-top: 50px;
|
||||
margin-bottom: 100px;
|
||||
|
||||
a {
|
||||
@@ -24,6 +47,10 @@
|
||||
height: auto;
|
||||
}
|
||||
|
||||
&.active_table {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.active_table_row {
|
||||
h3 {
|
||||
margin-top: 0.5em;
|
||||
|
||||
@@ -68,7 +68,11 @@
|
||||
margin-right: 0;
|
||||
|
||||
&, & > a.row {
|
||||
display: block;
|
||||
display: -webkit-box;
|
||||
display: -moz-box;
|
||||
display: -ms-flexbox;
|
||||
display: -webkit-flex;
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +100,7 @@
|
||||
|
||||
&:hover, &:active, &:focus {
|
||||
// color: $dark-grey
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -81,3 +81,6 @@ checkout
|
||||
display: inline
|
||||
span.accordion-down
|
||||
display: none
|
||||
|
||||
.error
|
||||
color: #c82020
|
||||
|
||||
16
app/assets/stylesheets/darkswarm/stripe-elements.css.scss
Normal file
16
app/assets/stylesheets/darkswarm/stripe-elements.css.scss
Normal file
@@ -0,0 +1,16 @@
|
||||
stripe-elements {
|
||||
margin-bottom: 15px;
|
||||
display: block;
|
||||
|
||||
#card-element {
|
||||
background: white;
|
||||
box-sizing: border-box;
|
||||
font-weight: 400;
|
||||
padding: 0.6rem 0.5rem;
|
||||
border: 1px solid #cccccc;
|
||||
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||
border-radius: 0px;
|
||||
height: 42px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
71
app/assets/stylesheets/darkswarm/tabset.css.scss
Normal file
71
app/assets/stylesheets/darkswarm/tabset.css.scss
Normal file
@@ -0,0 +1,71 @@
|
||||
@import "typography";
|
||||
@import "mixins";
|
||||
@import "branding";
|
||||
|
||||
.tabset-ctrl {
|
||||
.tab-view {
|
||||
padding-top: 30px;
|
||||
}
|
||||
|
||||
.tab {
|
||||
text-align: center;
|
||||
|
||||
@media all and (max-width: 640px) {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
a {
|
||||
@include headingFont;
|
||||
|
||||
background: transparent;
|
||||
text-transform: uppercase;
|
||||
font-size: 1.5em;
|
||||
text-shadow: 0 -1px 1px #ffffff;
|
||||
padding: 1em;
|
||||
border: none;
|
||||
|
||||
@media all and (max-width: 640px) {
|
||||
padding: 0.35em 0 0.65em 0;
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
border-bottom: 4px solid transparent;
|
||||
|
||||
&:hover, &:focus, &:active {
|
||||
transition: all 0.4s ease-in-out;
|
||||
border-bottom: 4px solid $clr-brick-bright;
|
||||
cursor: pointer;
|
||||
|
||||
@media all and (max-width: 640px) {
|
||||
transition: none;
|
||||
color: white;
|
||||
background-color: $clr-brick-bright;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $clr-brick-bright;
|
||||
|
||||
@media all and (max-width: 640px) {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.selected {
|
||||
border-bottom: 4px solid $clr-brick;
|
||||
|
||||
@media all and (max-width: 640px) {
|
||||
background-color: $clr-brick;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $clr-brick;
|
||||
|
||||
@media all and (max-width: 640px) {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -408,3 +408,12 @@ ul {
|
||||
display: inline-block;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fix overlapping table header on second page of long invoices.
|
||||
* Problem description: https://github.com/openfoodfoundation/openfoodnetwork/issues/1738
|
||||
* Solution: https://github.com/wkhtmltopdf/wkhtmltopdf/issues/1770#issuecomment-73530576
|
||||
*/
|
||||
thead { display: table-header-group }
|
||||
tfoot { display: table-row-group }
|
||||
tr { page-break-inside: avoid }
|
||||
|
||||
49
app/controllers/admin/stripe_accounts_controller.rb
Normal file
49
app/controllers/admin/stripe_accounts_controller.rb
Normal file
@@ -0,0 +1,49 @@
|
||||
require 'stripe/account_connector'
|
||||
|
||||
module Admin
|
||||
class StripeAccountsController < Spree::Admin::BaseController
|
||||
def connect
|
||||
payload = params.slice(:enterprise_id)
|
||||
key = Openfoodnetwork::Application.config.secret_token
|
||||
url_params = { state: JWT.encode(payload, key, 'HS256'), scope: "read_write" }
|
||||
redirect_to Stripe::OAuth.authorize_url(url_params)
|
||||
end
|
||||
|
||||
def destroy
|
||||
stripe_account = StripeAccount.find(params[:id])
|
||||
authorize! :destroy, stripe_account
|
||||
|
||||
if stripe_account.deauthorize_and_destroy
|
||||
flash[:success] = "Stripe account disconnected."
|
||||
else
|
||||
flash[:error] = "Failed to disconnect Stripe."
|
||||
end
|
||||
|
||||
redirect_to main_app.edit_admin_enterprise_path(stripe_account.enterprise)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
flash[:error] = "Failed to disconnect Stripe."
|
||||
redirect_to spree.admin_path
|
||||
end
|
||||
|
||||
def status
|
||||
return render json: { status: :stripe_disabled } unless Spree::Config.stripe_connect_enabled
|
||||
stripe_account = StripeAccount.find_by_enterprise_id(params[:enterprise_id])
|
||||
return render json: { status: :account_missing } unless stripe_account
|
||||
authorize! :status, stripe_account
|
||||
|
||||
begin
|
||||
status = Stripe::Account.retrieve(stripe_account.stripe_user_id)
|
||||
attrs = %i[id business_name charges_enabled]
|
||||
render json: status.to_hash.slice(*attrs).merge( status: :connected)
|
||||
rescue Stripe::APIError
|
||||
render json: { status: :access_revoked }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def model_class
|
||||
StripeAccount
|
||||
end
|
||||
end
|
||||
end
|
||||
40
app/controllers/admin/stripe_connect_settings_controller.rb
Normal file
40
app/controllers/admin/stripe_connect_settings_controller.rb
Normal file
@@ -0,0 +1,40 @@
|
||||
# This controller is used by super admin users to update the settings the app is using
|
||||
|
||||
module Admin
|
||||
class StripeConnectSettingsController < Spree::Admin::BaseController
|
||||
StripeConnectSettings = Struct.new(:stripe_connect_enabled)
|
||||
|
||||
before_filter :load_settings, only: [:edit]
|
||||
|
||||
def edit
|
||||
return @stripe_account = { status: :empty_api_key_error_html } if Stripe.api_key.blank?
|
||||
attrs = %i[id business_name charges_enabled]
|
||||
@obfuscated_secret_key = obfuscated_secret_key
|
||||
@stripe_account = Stripe::Account.retrieve.to_hash.slice(*attrs).merge(status: :ok)
|
||||
rescue Stripe::AuthenticationError
|
||||
@stripe_account = { status: :auth_fail_error }
|
||||
end
|
||||
|
||||
def update
|
||||
Spree::Config.set(params[:settings])
|
||||
resource = t('admin.controllers.stripe_connect_settings.resource')
|
||||
flash[:success] = t(:successfully_updated, :resource => resource)
|
||||
redirect_to_edit
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_settings
|
||||
@settings = StripeConnectSettings.new(Spree::Config[:stripe_connect_enabled])
|
||||
end
|
||||
|
||||
def redirect_to_edit
|
||||
redirect_to main_app.edit_admin_stripe_connect_settings_path
|
||||
end
|
||||
|
||||
def obfuscated_secret_key
|
||||
key = Stripe.api_key
|
||||
key.first(8) + "****" + key.last(4)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -57,7 +57,7 @@ class ApplicationController < ActionController::Base
|
||||
def enable_embedded_shopfront
|
||||
whitelist = Spree::Config[:embedded_shopfronts_whitelist]
|
||||
return unless Spree::Config[:enable_embedded_shopfronts] && whitelist.present?
|
||||
return if request.referer && URI(request.referer).scheme != 'https' && !Rails.env.test?
|
||||
return if request.referer && URI(request.referer).scheme != 'https' && !Rails.env.test? && !Rails.env.development?
|
||||
|
||||
response.headers.delete 'X-Frame-Options'
|
||||
response.headers['Content-Security-Policy'] = "frame-ancestors #{whitelist}"
|
||||
|
||||
@@ -15,6 +15,10 @@ class CheckoutController < Spree::CheckoutController
|
||||
include EnterprisesHelper
|
||||
|
||||
def edit
|
||||
# This is only required because of spree_paypal_express. If we implement
|
||||
# a version of paypal that uses this controller, and more specifically
|
||||
# the #update_failed method, then we can remove this call
|
||||
restart_checkout
|
||||
end
|
||||
|
||||
def update
|
||||
@@ -48,7 +52,7 @@ class CheckoutController < Spree::CheckoutController
|
||||
format.html do
|
||||
respond_with(@order, :location => order_path(@order))
|
||||
end
|
||||
format.js do
|
||||
format.json do
|
||||
render json: {path: order_path(@order)}, status: 200
|
||||
end
|
||||
end
|
||||
@@ -119,6 +123,9 @@ class CheckoutController < Spree::CheckoutController
|
||||
if (params[:order][:payments_attributes])
|
||||
params[:order][:payments_attributes].first[:amount] = @order.total
|
||||
end
|
||||
if params[:order][:existing_card_id]
|
||||
construct_saved_card_attributes
|
||||
end
|
||||
params[:order]
|
||||
end
|
||||
|
||||
@@ -134,11 +141,12 @@ class CheckoutController < Spree::CheckoutController
|
||||
|
||||
def update_failed
|
||||
clear_ship_address
|
||||
restart_checkout
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
render :edit
|
||||
end
|
||||
format.js do
|
||||
format.json do
|
||||
render json: {errors: @order.errors, flash: flash.to_hash}.to_json, status: 400
|
||||
end
|
||||
end
|
||||
@@ -152,6 +160,15 @@ class CheckoutController < Spree::CheckoutController
|
||||
end
|
||||
end
|
||||
|
||||
def restart_checkout
|
||||
return if @order.state == 'cart'
|
||||
@order.restart_checkout! # resets state to 'cart'
|
||||
@order.update_attributes!(shipping_method_id: nil)
|
||||
@order.shipments.with_state(:pending).destroy_all
|
||||
@order.payments.with_state(:checkout).destroy_all
|
||||
@order.reload
|
||||
end
|
||||
|
||||
def skip_state_validation?
|
||||
true
|
||||
end
|
||||
@@ -202,4 +219,28 @@ class CheckoutController < Spree::CheckoutController
|
||||
render json: {path: spree.paypal_express_url(payment_method_id: payment_method.id)}, status: 200
|
||||
true
|
||||
end
|
||||
|
||||
def construct_saved_card_attributes
|
||||
existing_card_id = params[:order].delete(:existing_card_id)
|
||||
return if existing_card_id.blank?
|
||||
|
||||
credit_card = Spree::CreditCard.find(existing_card_id)
|
||||
if credit_card.try(:user_id).blank? || credit_card.user_id != spree_current_user.try(:id)
|
||||
raise Spree::Core::GatewayError, I18n.t(:invalid_credit_card)
|
||||
end
|
||||
|
||||
# Not currently supported but maybe we should add it...?
|
||||
credit_card.verification_value = params[:cvc_confirm] if params[:cvc_confirm].present?
|
||||
|
||||
params[:order][:payments_attributes].first[:source] = credit_card
|
||||
params[:order][:payments_attributes].first.delete :source_attributes
|
||||
end
|
||||
|
||||
def rescue_from_spree_gateway_error(error)
|
||||
flash[:error] = t(:spree_gateway_error_flash_for_checkout, error: error.message)
|
||||
respond_to do |format|
|
||||
format.html { render :edit }
|
||||
format.json { render json: { flash: flash.to_hash }, status: 400 }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,10 +15,11 @@ class EnterprisesController < BaseController
|
||||
respond_to :js, only: :permalink_checker
|
||||
|
||||
def relatives
|
||||
set_enterprise
|
||||
|
||||
respond_to do |format|
|
||||
format.json do
|
||||
enterprise = Enterprise.find(params[:id])
|
||||
enterprises = enterprise.andand.relatives.andand.activated
|
||||
enterprises = @enterprise.andand.relatives.andand.activated
|
||||
render(json: enterprises,
|
||||
each_serializer: Api::EnterpriseSerializer,
|
||||
data: OpenFoodNetwork::EnterpriseInjectionData.new)
|
||||
@@ -40,6 +41,10 @@ class EnterprisesController < BaseController
|
||||
|
||||
private
|
||||
|
||||
def set_enterprise
|
||||
@enterprise = Enterprise.find_by_id(params[:id])
|
||||
end
|
||||
|
||||
def clean_permalink
|
||||
params[:permalink] = params[:permalink].parameterize
|
||||
end
|
||||
|
||||
@@ -6,6 +6,8 @@ class GroupsController < BaseController
|
||||
end
|
||||
|
||||
def show
|
||||
enable_embedded_shopfront
|
||||
@hide_menu = true if @shopfront_layout == 'embedded'
|
||||
@group = EnterpriseGroup.find_by_permalink(params[:id]) || EnterpriseGroup.find(params[:id])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
module Spree
|
||||
module Admin
|
||||
PaymentMethodsController.class_eval do
|
||||
before_filter :restrict_stripe_account_change, only: [:update]
|
||||
before_filter :force_environment, only: [:create, :update]
|
||||
skip_before_filter :load_resource, only: [:show_provider_preferences]
|
||||
before_filter :load_hubs, only: [:new, :edit, :update]
|
||||
@@ -57,12 +58,30 @@ module Spree
|
||||
else
|
||||
@providers = Gateway.providers.reject{ |p| p.name.include? "Bogus" }.sort{|p1, p2| p1.name <=> p2.name }
|
||||
end
|
||||
@providers.reject!{ |p| p.name.ends_with? "StripeConnect" } unless show_stripe?
|
||||
@calculators = PaymentMethod.calculators.sort_by(&:name)
|
||||
end
|
||||
|
||||
def load_hubs
|
||||
@hubs = Enterprise.managed_by(spree_current_user).is_distributor.sort_by!{ |d| [(@payment_method.has_distributor? d) ? 0 : 1, d.name] }
|
||||
end
|
||||
|
||||
# Show Stripe as an option if enabled, or if the
|
||||
# current payment_method is already a Stripe method
|
||||
def show_stripe?
|
||||
Spree::Config.stripe_connect_enabled || @payment_method.try(:type) == "Spree::Gateway::StripeConnect"
|
||||
end
|
||||
|
||||
def restrict_stripe_account_change
|
||||
return unless @payment_method
|
||||
return unless @payment_method.type == "Spree::Gateway::StripeConnect"
|
||||
return unless @payment_method.preferred_enterprise_id.andand > 0
|
||||
|
||||
@stripe_account_holder = Enterprise.find(@payment_method.preferred_enterprise_id)
|
||||
return if spree_current_user.enterprises.include? @stripe_account_holder
|
||||
|
||||
params[:payment_method][:preferred_enterprise_id] = @stripe_account_holder.id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
69
app/controllers/spree/credit_cards_controller.rb
Normal file
69
app/controllers/spree/credit_cards_controller.rb
Normal file
@@ -0,0 +1,69 @@
|
||||
module Spree
|
||||
class CreditCardsController < BaseController
|
||||
def new_from_token
|
||||
# A new Customer is created for every credit card (same as via ActiveMerchant)
|
||||
# Note that default_source is the card represented by the token
|
||||
|
||||
@customer = create_customer(params[:token])
|
||||
@credit_card = build_card_from(stored_card_attributes)
|
||||
if @credit_card.save
|
||||
render json: @credit_card, serializer: ::Api::CreditCardSerializer, status: :ok
|
||||
else
|
||||
message = t(:card_could_not_be_saved)
|
||||
render json: { flash: { error: I18n.t(:spree_gateway_error_flash_for_checkout, error: message) } }, status: 400
|
||||
end
|
||||
rescue Stripe::CardError => e
|
||||
return render json: { flash: { error: I18n.t(:spree_gateway_error_flash_for_checkout, error: e.message) } }, status: 400
|
||||
end
|
||||
|
||||
def destroy
|
||||
@credit_card = Spree::CreditCard.find_by_id(params[:id])
|
||||
if @credit_card
|
||||
authorize! :destroy, @credit_card
|
||||
destroy_at_stripe
|
||||
end
|
||||
|
||||
# Using try because we may not have a card here
|
||||
if @credit_card.try(:destroy)
|
||||
flash[:success] = I18n.t(:card_has_been_removed, number: "x-#{@credit_card.last_digits}")
|
||||
else
|
||||
flash[:error] = I18n.t(:card_could_not_be_removed)
|
||||
end
|
||||
redirect_to account_path(anchor: 'cards')
|
||||
rescue Stripe::CardError
|
||||
flash[:error] = I18n.t(:card_could_not_be_removed)
|
||||
redirect_to account_path(anchor: 'cards')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Currently can only destroy the whole customer object
|
||||
def destroy_at_stripe
|
||||
stripe_customer = Stripe::Customer.retrieve(@credit_card.gateway_customer_profile_id)
|
||||
stripe_customer.delete if stripe_customer
|
||||
end
|
||||
|
||||
def create_customer(token)
|
||||
Stripe::Customer.create(email: spree_current_user.email, source: token)
|
||||
end
|
||||
|
||||
def stored_card_attributes
|
||||
return {} unless @customer.try(:default_source)
|
||||
{
|
||||
month: params[:exp_month],
|
||||
year: params[:exp_year],
|
||||
last_digits: params[:last4],
|
||||
gateway_payment_profile_id: @customer.default_source,
|
||||
gateway_customer_profile_id: @customer.id,
|
||||
cc_type: params[:cc_type]
|
||||
}
|
||||
end
|
||||
|
||||
def build_card_from(attrs)
|
||||
card = Spree::CreditCard.new(attrs)
|
||||
# Can't mass assign user:
|
||||
card.user_id = spree_current_user.id
|
||||
card
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2,4 +2,14 @@ Spree::UsersController.class_eval do
|
||||
layout 'darkswarm'
|
||||
|
||||
before_filter :enable_embedded_shopfront
|
||||
|
||||
# Override of spree_auth_devise default
|
||||
# Ignores invoice orders, only order where state: 'complete'
|
||||
def show
|
||||
@orders = @user.orders.where(state: 'complete').order('completed_at desc')
|
||||
|
||||
return unless Spree::Config.accounts_distributor_id
|
||||
|
||||
@orders = @orders.where('distributor_id != ?', Spree::Config.accounts_distributor_id)
|
||||
end
|
||||
end
|
||||
|
||||
21
app/controllers/stripe/callbacks_controller.rb
Normal file
21
app/controllers/stripe/callbacks_controller.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
require 'stripe/account_connector'
|
||||
|
||||
module Stripe
|
||||
class CallbacksController < BaseController
|
||||
# GET /stripe/callbacks
|
||||
def index
|
||||
connector = Stripe::AccountConnector.new(spree_current_user, params)
|
||||
|
||||
if connector.create_account
|
||||
flash[:success] = t('admin.controllers.enterprises.stripe_connect_success')
|
||||
elsif connector.connection_cancelled_by_user?
|
||||
flash[:notice] = t('admin.controllers.enterprises.stripe_connect_cancelled')
|
||||
else
|
||||
flash[:error] = t('admin.controllers.enterprises.stripe_connect_fail')
|
||||
end
|
||||
redirect_to main_app.edit_admin_enterprise_path(connector.enterprise, anchor: 'payment_methods')
|
||||
rescue Stripe::StripeError => e
|
||||
render text: e.message, status: 500
|
||||
end
|
||||
end
|
||||
end
|
||||
38
app/controllers/stripe/webhooks_controller.rb
Normal file
38
app/controllers/stripe/webhooks_controller.rb
Normal file
@@ -0,0 +1,38 @@
|
||||
require 'stripe/webhook_handler'
|
||||
|
||||
module Stripe
|
||||
class WebhooksController < BaseController
|
||||
protect_from_forgery except: :create
|
||||
before_filter :verify_webhook
|
||||
|
||||
# POST /stripe/webhooks
|
||||
def create
|
||||
handler = WebhookHandler.new(@event)
|
||||
result = handler.handle
|
||||
|
||||
render nothing: true, status: status_mappings[result] || 200
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def verify_webhook
|
||||
payload = request.raw_post
|
||||
signature = request.headers["HTTP_STRIPE_SIGNATURE"]
|
||||
@event = Webhook.construct_event(payload, signature, Stripe.endpoint_secret)
|
||||
rescue JSON::ParserError
|
||||
render nothing: true, status: 400
|
||||
rescue Stripe::SignatureVerificationError
|
||||
render nothing: true, status: 401
|
||||
end
|
||||
|
||||
# Stripe interprets a 4xx or 3xx response as a failure to receive the webhook,
|
||||
# and will stop sending events if too many of either of these are returned.
|
||||
def status_mappings
|
||||
{
|
||||
success: 200, # The event was handled successfully
|
||||
unknown: 202, # The event was of an unknown type
|
||||
ignored: 204 # No action was taken in response to the event
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -20,4 +20,10 @@ module ApplicationHelper
|
||||
super
|
||||
end
|
||||
end
|
||||
|
||||
def body_classes
|
||||
classes = []
|
||||
classes << "off-canvas" unless @hide_menu
|
||||
classes << @shopfront_layout
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
require 'open_food_network/available_payment_method_filter'
|
||||
|
||||
module EnterprisesHelper
|
||||
def current_distributor
|
||||
@current_distributor ||= current_order(false).andand.distributor
|
||||
@@ -22,6 +24,9 @@ module EnterprisesHelper
|
||||
return [] unless current_distributor.present?
|
||||
payment_methods = current_distributor.payment_methods.available(:front_end).all
|
||||
|
||||
filter = OpenFoodNetwork::AvailablePaymentMethodFilter.new
|
||||
filter.filter!(payment_methods)
|
||||
|
||||
applicator = OpenFoodNetwork::TagRuleApplicator.new(current_distributor, "FilterPaymentMethods", current_customer.andand.tag_list)
|
||||
applicator.filter!(payment_methods)
|
||||
|
||||
|
||||
@@ -64,9 +64,21 @@ module InjectionHelper
|
||||
render partial: "json/injection_ams", locals: {name: 'enterpriseAttributes', json: "#{@enterprise_attributes.to_json}"}
|
||||
end
|
||||
|
||||
def inject_orders_by_distributor
|
||||
data_array = spree_current_user.orders_by_distributor
|
||||
inject_json_ams "orders_by_distributor", data_array, Api::OrdersByDistributorSerializer
|
||||
def inject_orders
|
||||
inject_json_ams "orders", @orders.all, Api::OrderSerializer
|
||||
end
|
||||
|
||||
def inject_shops
|
||||
shops = Enterprise.where(id: @orders.pluck(:distributor_id).uniq)
|
||||
inject_json_ams "shops", shops.all, Api::ShopForOrdersSerializer
|
||||
end
|
||||
|
||||
def inject_saved_credit_cards
|
||||
if spree_current_user
|
||||
data = spree_current_user.credit_cards.with_payment_profile.all
|
||||
end
|
||||
|
||||
inject_json_ams "savedCreditCards", data, Api::CreditCardSerializer
|
||||
end
|
||||
|
||||
def inject_json(name, partial, opts = {})
|
||||
@@ -89,5 +101,4 @@ module InjectionHelper
|
||||
@enterprise_injection_data ||= OpenFoodNetwork::EnterpriseInjectionData.new
|
||||
{data: @enterprise_injection_data}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -42,6 +42,7 @@ class Enterprise < ActiveRecord::Base
|
||||
has_many :billable_periods
|
||||
has_many :inventory_items
|
||||
has_many :tag_rules
|
||||
has_one :stripe_account, dependent: :destroy
|
||||
|
||||
delegate :latitude, :longitude, :city, :state_name, :to => :address
|
||||
|
||||
@@ -66,7 +67,6 @@ class Enterprise < ActiveRecord::Base
|
||||
supports_s3 :logo
|
||||
supports_s3 :promo_image
|
||||
|
||||
|
||||
validates :name, presence: true
|
||||
validate :name_is_unique
|
||||
validates :sells, presence: true, inclusion: {in: SELLS}
|
||||
@@ -78,7 +78,6 @@ class Enterprise < ActiveRecord::Base
|
||||
validate :enforce_ownership_limit, if: lambda { owner_id_changed? && !owner_id.nil? }
|
||||
validates_length_of :description, :maximum => 255
|
||||
|
||||
|
||||
before_save :confirmation_check, if: lambda { email_changed? }
|
||||
|
||||
before_validation :initialize_permalink, if: lambda { permalink.nil? }
|
||||
@@ -95,7 +94,6 @@ class Enterprise < ActiveRecord::Base
|
||||
|
||||
after_rollback :restore_permalink
|
||||
|
||||
|
||||
scope :by_name, order('name')
|
||||
scope :visible, where(visible: true)
|
||||
scope :confirmed, where('confirmed_at IS NOT NULL')
|
||||
|
||||
@@ -56,9 +56,14 @@ class AbilityDecorator
|
||||
user == item.order.user &&
|
||||
item.order.changes_allowed?
|
||||
end
|
||||
|
||||
can [:cancel], Spree::Order do |order|
|
||||
order.user == user
|
||||
end
|
||||
|
||||
can [:destroy], Spree::CreditCard do |credit_card|
|
||||
credit_card.user == user
|
||||
end
|
||||
end
|
||||
|
||||
# New users can create an enterprise, and gain other permissions from doing this.
|
||||
@@ -118,12 +123,16 @@ class AbilityDecorator
|
||||
can [:admin, :bulk_update], ColumnPreference do |column_preference|
|
||||
column_preference.user == user
|
||||
end
|
||||
|
||||
can [:admin, :connect, :status, :destroy], StripeAccount do |stripe_account|
|
||||
user.enterprises.include? stripe_account.enterprise
|
||||
end
|
||||
end
|
||||
|
||||
def add_product_management_abilities(user)
|
||||
# Enterprise User can only access products that they are a supplier for
|
||||
can [:create], Spree::Product
|
||||
can [:admin, :read, :update, :product_distributions, :bulk_edit, :bulk_update, :clone, :delete, :destroy], Spree::Product do |product|
|
||||
can [:admin, :read, :update, :product_distributions, :seo, :group_buy_options, :bulk_edit, :bulk_update, :clone, :delete, :destroy], Spree::Product do |product|
|
||||
OpenFoodNetwork::Permissions.new(user).managed_product_enterprises.include? product.supplier
|
||||
end
|
||||
|
||||
|
||||
@@ -39,4 +39,7 @@ Spree::AppConfiguration.class_eval do
|
||||
# Invoices & Receipts
|
||||
preference :invoice_style2?, :boolean, default: false
|
||||
preference :enable_receipt_printing?, :boolean, default: false
|
||||
|
||||
# Stripe Connect
|
||||
preference :stripe_connect_enabled, :boolean, default: false
|
||||
end
|
||||
|
||||
28
app/models/spree/credit_card_decorator.rb
Normal file
28
app/models/spree/credit_card_decorator.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
Spree::CreditCard.class_eval do
|
||||
# Allows user to submit these attributes with checkout request
|
||||
# Required to be able to correctly store details for token-based charges
|
||||
# Obviously can be removed once we are using strong params
|
||||
attr_accessible :cc_type, :last_digits
|
||||
|
||||
# For holding customer preference in memory
|
||||
attr_accessible :save_requested_by_customer
|
||||
attr_writer :save_requested_by_customer
|
||||
|
||||
# Should be able to remove once we reach Spree v2.2.0
|
||||
# https://github.com/spree/spree/commit/411010f3975c919ab298cb63962ee492455b415c
|
||||
belongs_to :payment_method
|
||||
|
||||
belongs_to :user
|
||||
|
||||
# Allows us to use a gateway_payment_profile_id to store Stripe Tokens
|
||||
# Should be able to remove once we reach Spree v2.2.0
|
||||
# Commit: https://github.com/spree/spree/commit/5a4d690ebc64b264bf12904a70187e7a8735ef3f
|
||||
# See also: https://github.com/spree/spree_gateway/issues/111
|
||||
def has_payment_profile? # rubocop:disable Style/PredicateName
|
||||
gateway_customer_profile_id.present? || gateway_payment_profile_id.present?
|
||||
end
|
||||
|
||||
def save_requested_by_customer?
|
||||
!!@save_requested_by_customer
|
||||
end
|
||||
end
|
||||
106
app/models/spree/gateway/stripe_connect.rb
Normal file
106
app/models/spree/gateway/stripe_connect.rb
Normal file
@@ -0,0 +1,106 @@
|
||||
require 'stripe/profile_storer'
|
||||
|
||||
module Spree
|
||||
class Gateway
|
||||
class StripeConnect < Gateway
|
||||
preference :enterprise_id, :integer
|
||||
|
||||
validate :ensure_enterprise_selected
|
||||
|
||||
attr_accessible :preferred_enterprise_id
|
||||
|
||||
CARD_TYPE_MAPPING = {
|
||||
'American Express' => 'american_express',
|
||||
'Diners Club' => 'diners_club',
|
||||
'Visa' => 'visa'
|
||||
}.freeze
|
||||
|
||||
def method_type
|
||||
'stripe'
|
||||
end
|
||||
|
||||
def provider_class
|
||||
ActiveMerchant::Billing::StripeGateway
|
||||
end
|
||||
|
||||
def payment_profiles_supported?
|
||||
true
|
||||
end
|
||||
|
||||
def stripe_account_id
|
||||
StripeAccount.find_by_enterprise_id(preferred_enterprise_id).andand.stripe_user_id
|
||||
end
|
||||
|
||||
def purchase(money, creditcard, gateway_options)
|
||||
provider.purchase(*options_for_purchase_or_auth(money, creditcard, gateway_options))
|
||||
rescue Stripe::StripeError => e
|
||||
# This will be an error caused by generating a stripe token
|
||||
failed_activemerchant_billing_response(e.message)
|
||||
end
|
||||
|
||||
def void(response_code, _creditcard, gateway_options)
|
||||
gateway_options[:stripe_account] = stripe_account_id
|
||||
provider.void(response_code, gateway_options)
|
||||
end
|
||||
|
||||
def create_profile(payment)
|
||||
return unless payment.source.gateway_customer_profile_id.nil?
|
||||
|
||||
profile_storer = Stripe::ProfileStorer.new(payment, provider)
|
||||
profile_storer.create_customer_from_token
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# In this gateway, what we call 'secret_key' is the 'login'
|
||||
def options
|
||||
options = super
|
||||
options.merge(:login => Stripe.api_key)
|
||||
end
|
||||
|
||||
def options_for_purchase_or_auth(money, creditcard, gateway_options)
|
||||
options = {}
|
||||
options[:description] = "Spree Order ID: #{gateway_options[:order_id]}"
|
||||
options[:currency] = gateway_options[:currency]
|
||||
options[:stripe_account] = stripe_account_id
|
||||
|
||||
creditcard = token_from_card_profile_ids(creditcard)
|
||||
|
||||
[money, creditcard, options]
|
||||
end
|
||||
|
||||
def update_source!(source)
|
||||
source.cc_type = CARD_TYPE_MAPPING[source.cc_type] if CARD_TYPE_MAPPING.include?(source.cc_type)
|
||||
source
|
||||
end
|
||||
|
||||
def token_from_card_profile_ids(creditcard)
|
||||
token_or_card_id = creditcard.gateway_payment_profile_id
|
||||
customer = creditcard.gateway_customer_profile_id
|
||||
|
||||
return nil if token_or_card_id.blank?
|
||||
|
||||
# Assume the gateway_payment_profile_id is a token generated by StripeJS
|
||||
return token_or_card_id if customer.blank?
|
||||
|
||||
# Assume the gateway_payment_profile_id is a Stripe card_id
|
||||
# So generate a new token, using the customer_id and card_id
|
||||
tokenize_instance_customer_card(customer, token_or_card_id)
|
||||
end
|
||||
|
||||
def tokenize_instance_customer_card(customer, card)
|
||||
token = Stripe::Token.create({card: card, customer: customer}, stripe_account: stripe_account_id)
|
||||
token.id
|
||||
end
|
||||
|
||||
def failed_activemerchant_billing_response(error_message)
|
||||
ActiveMerchant::Billing::Response.new(false, error_message)
|
||||
end
|
||||
|
||||
def ensure_enterprise_selected
|
||||
return if preferred_enterprise_id.andand > 0
|
||||
errors.add(:stripe_account_owner, I18n.t(:error_required))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -37,7 +37,8 @@ Spree::Order.class_eval do
|
||||
end
|
||||
order.payment_required?
|
||||
}
|
||||
go_to_state :confirm, :if => lambda { |order| order.confirmation_required? }
|
||||
# NOTE: :confirm step was removed because we were not actually using it
|
||||
# go_to_state :confirm, :if => lambda { |order| order.confirmation_required? }
|
||||
go_to_state :complete
|
||||
remove_transition :from => :delivery, :to => :confirm
|
||||
end
|
||||
@@ -143,6 +144,8 @@ Spree::Order.class_eval do
|
||||
end
|
||||
|
||||
# After changing line items of a completed order
|
||||
# TODO: perhaps this should be triggered from a controller
|
||||
# rather than an after_save callback?
|
||||
def update_shipping_fees!
|
||||
shipments.each do |shipment|
|
||||
next if shipment.shipped?
|
||||
@@ -152,6 +155,8 @@ Spree::Order.class_eval do
|
||||
end
|
||||
|
||||
# After changing line items of a completed order
|
||||
# TODO: perhaps this should be triggered from a controller
|
||||
# rather than an after_save callback?
|
||||
def update_payment_fees!
|
||||
payments.each do |payment|
|
||||
next if payment.completed?
|
||||
@@ -293,6 +298,24 @@ Spree::Order.class_eval do
|
||||
complete? && distributor.andand.allow_order_changes? && order_cycle.andand.open?
|
||||
end
|
||||
|
||||
# Override of existing Spree method. Can remove when we reach 2-0-stable
|
||||
# See commit: https://github.com/spree/spree/commit/5fca58f658273451193d5711081d018c317814ed
|
||||
# Allows GatewayError to show useful error messages in checkout
|
||||
def process_payments!
|
||||
pending_payments.each do |payment|
|
||||
break if payment_total >= total
|
||||
|
||||
payment.process!
|
||||
|
||||
if payment.completed?
|
||||
self.payment_total += payment.amount
|
||||
end
|
||||
end
|
||||
rescue Spree::Core::GatewayError => e # This section changed
|
||||
result = !!Spree::Config[:allow_checkout_on_gateway_error]
|
||||
errors.add(:base, e.message) and return result
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def shipping_address_from_distributor
|
||||
@@ -348,6 +371,7 @@ Spree::Order.class_eval do
|
||||
end
|
||||
|
||||
def update_adjustment!(adjustment)
|
||||
return if adjustment.finalized?
|
||||
state = adjustment.state
|
||||
adjustment.state = 'open'
|
||||
adjustment.update!(self)
|
||||
@@ -357,11 +381,14 @@ Spree::Order.class_eval do
|
||||
# object_params sets the payment amount to the order total, but it does this before
|
||||
# the shipping method is set. This results in the customer not being charged for their
|
||||
# order's shipping. To fix this, we refresh the payment amount here.
|
||||
def charge_shipping!
|
||||
def charge_shipping_and_payment_fees!
|
||||
update_totals
|
||||
return unless payments.any?
|
||||
payments.first.update_attribute :amount, total
|
||||
end
|
||||
end
|
||||
|
||||
Spree::Order.state_machine.after_transition to: :payment, do: :charge_shipping!
|
||||
Spree::Order.state_machine.after_transition to: :payment, do: :charge_shipping_and_payment_fees!
|
||||
Spree::Order.state_machine.event :restart_checkout do
|
||||
transition :to => :cart, unless: :completed?
|
||||
end
|
||||
|
||||
41
app/models/spree/order_updater_decorator.rb
Normal file
41
app/models/spree/order_updater_decorator.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
module Spree
|
||||
OrderUpdater.class_eval do
|
||||
# TODO: This logic adapted from Spree 2.4, remove when we get there
|
||||
# Handles state updating in a much more logical way than < 2.4
|
||||
# Specifically, doesn't depend on payments.last to determine payment state
|
||||
# Also swapped: == 0 for .zero?, .size == 0 for empty? and .size > 0 for !empty?
|
||||
# See:
|
||||
# https://github.com/spree/spree/commit/38b8456183d11fc1e00e395e7c9154c76ef65b85
|
||||
# https://github.com/spree/spree/commit/7b264acff7824f5b3dc6651c106631d8f30b147a
|
||||
def update_payment_state
|
||||
last_state = order.payment_state
|
||||
if payments.present? && payments.valid.empty?
|
||||
order.payment_state = 'failed'
|
||||
elsif order.state == 'canceled' && order.payment_total.zero?
|
||||
order.payment_state = 'void'
|
||||
else
|
||||
# This part added so that we don't need to override order.outstanding_balance
|
||||
balance = order.outstanding_balance
|
||||
balance = -1 * order.payment_total if canceled_and_paid_for?
|
||||
order.payment_state = 'balance_due' if balance > 0
|
||||
order.payment_state = 'credit_owed' if balance < 0
|
||||
order.payment_state = 'paid' if balance.zero?
|
||||
|
||||
# Original logic
|
||||
# order.payment_state = 'balance_due' if order.outstanding_balance > 0
|
||||
# order.payment_state = 'credit_owed' if order.outstanding_balance < 0
|
||||
# order.payment_state = 'paid' if !order.outstanding_balance?
|
||||
end
|
||||
order.state_changed('payment') if last_state != order.payment_state
|
||||
order.payment_state
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Taken from order.outstanding_balance in Spree 2.4
|
||||
# See: https://github.com/spree/spree/commit/7b264acff7824f5b3dc6651c106631d8f30b147a
|
||||
def canceled_and_paid_for?
|
||||
order.canceled? && order.payments.present? && !order.payments.completed.empty?
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,13 +4,13 @@ module Spree
|
||||
|
||||
after_save :ensure_correct_adjustment, :update_order
|
||||
|
||||
attr_accessible :source
|
||||
|
||||
def ensure_correct_adjustment
|
||||
# Don't charge for invalid payments.
|
||||
# PayPalExpress always creates a payment that is invalidated later.
|
||||
# Unknown: What about failed payments?
|
||||
if state == "invalid"
|
||||
adjustment.andand.destroy
|
||||
elsif adjustment
|
||||
revoke_adjustment_eligibility if ['failed', 'invalid'].include?(state)
|
||||
return if adjustment.try(:finalized?)
|
||||
|
||||
if adjustment
|
||||
adjustment.originator = payment_method
|
||||
adjustment.label = adjustment_label
|
||||
adjustment.save
|
||||
@@ -73,6 +73,15 @@ module Spree
|
||||
end
|
||||
end
|
||||
|
||||
# Import from future Spree v.2.3.0 d470b31798f37
|
||||
def build_source
|
||||
return if source_attributes.nil?
|
||||
return unless payment_method.andand.payment_source_class
|
||||
|
||||
self.source = payment_method.payment_source_class.new(source_attributes)
|
||||
source.payment_method_id = payment_method.id
|
||||
source.user_id = order.user_id if order
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -80,5 +89,26 @@ module Spree
|
||||
refund_amount ||= credit_allowed >= order.outstanding_balance.abs ? order.outstanding_balance.abs : credit_allowed.abs
|
||||
refund_amount.to_f
|
||||
end
|
||||
|
||||
def create_payment_profile
|
||||
return unless source.is_a?(CreditCard)
|
||||
return unless source.try(:save_requested_by_customer?)
|
||||
return unless source.number || source.gateway_payment_profile_id
|
||||
return unless source.gateway_customer_profile_id.nil?
|
||||
payment_method.create_profile(self)
|
||||
rescue ActiveMerchant::ConnectionError => e
|
||||
gateway_error e
|
||||
end
|
||||
|
||||
# Don't charge fees for invalid or failed payments.
|
||||
# This is called twice for failed payments, because the persistence of the 'failed'
|
||||
# state is acheived through some trickery using an after_rollback callback on the
|
||||
# payment model. See Spree::Payment#persist_invalid
|
||||
def revoke_adjustment_eligibility
|
||||
return unless adjustment.try(:reload)
|
||||
return if adjustment.finalized?
|
||||
adjustment.update_attribute(:eligible, false)
|
||||
adjustment.finalize!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -6,6 +6,7 @@ Spree::PaymentMethod.class_eval do
|
||||
acts_as_taggable
|
||||
|
||||
has_and_belongs_to_many :distributors, join_table: 'distributors_payment_methods', :class_name => 'Enterprise', association_foreign_key: 'distributor_id'
|
||||
has_many :credit_cards, class_name: "Spree::CreditCard" # from Spree v.2.3.0 d470b31798f37
|
||||
|
||||
attr_accessible :distributor_ids, :tag_list
|
||||
|
||||
@@ -58,6 +59,8 @@ Spree::PaymentMethod.class_eval do
|
||||
"MasterCard Internet Gateway Service (MIGS)"
|
||||
when "Spree::Gateway::Pin"
|
||||
"Pin Payments"
|
||||
when "Spree::Gateway::StripeConnect"
|
||||
"Stripe"
|
||||
when "Spree::Gateway::PayPalExpress"
|
||||
"PayPal Express"
|
||||
else
|
||||
|
||||
@@ -11,6 +11,7 @@ Spree.user_class.class_eval do
|
||||
has_many :billable_periods, foreign_key: :owner_id, inverse_of: :owner
|
||||
has_one :cart
|
||||
has_many :customers
|
||||
has_many :credit_cards
|
||||
|
||||
accepts_nested_attributes_for :enterprise_roles, :allow_destroy => true
|
||||
|
||||
@@ -53,32 +54,6 @@ Spree.user_class.class_eval do
|
||||
owned_enterprises(:reload).size < enterprise_limit
|
||||
end
|
||||
|
||||
# Returns Enterprise IDs for distributors that the user has shopped at
|
||||
def enterprises_ordered_from
|
||||
enterprise_ids = orders.where(state: :complete).map(&:distributor_id).uniq
|
||||
# Exclude the accounts distributor
|
||||
if Spree::Config.accounts_distributor_id
|
||||
enterprise_ids = enterprise_ids.keep_if { |a| a != Spree::Config.accounts_distributor_id }
|
||||
end
|
||||
enterprise_ids
|
||||
end
|
||||
|
||||
# Returns orders and their associated payments for all distributors that have been ordered from
|
||||
def complete_orders_by_distributor
|
||||
Enterprise
|
||||
.includes(distributed_orders: { payments: :payment_method })
|
||||
.where(enterprises: { id: enterprises_ordered_from },
|
||||
spree_orders: { state: 'complete', user_id: id })
|
||||
.order('spree_orders.completed_at DESC')
|
||||
end
|
||||
|
||||
def orders_by_distributor
|
||||
# Remove uncompleted payments as these will not be reflected in order balance
|
||||
data_array = complete_orders_by_distributor.to_a
|
||||
remove_payments_in_checkout(data_array)
|
||||
data_array.sort! { |a, b| b.distributed_orders.length <=> a.distributed_orders.length }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def limit_owned_enterprises
|
||||
|
||||
21
app/models/stripe_account.rb
Normal file
21
app/models/stripe_account.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
class StripeAccount < ActiveRecord::Base
|
||||
belongs_to :enterprise
|
||||
validates :stripe_user_id, :stripe_publishable_key, presence: true
|
||||
validates :enterprise_id, uniqueness: true
|
||||
|
||||
def deauthorize_and_destroy
|
||||
accounts = StripeAccount.where(stripe_user_id: stripe_user_id)
|
||||
|
||||
# Only deauthorize the user if it is not linked to multiple accounts
|
||||
return destroy if accounts.count > 1
|
||||
|
||||
destroy && Stripe::OAuth.deauthorize(stripe_user_id: stripe_user_id)
|
||||
rescue Stripe::OAuth::OAuthError
|
||||
Bugsnag.notify(
|
||||
RuntimeError.new("StripeDeauthorizeFailure"),
|
||||
stripe_account: stripe_user_id,
|
||||
enterprise_id: enterprise_id
|
||||
)
|
||||
true
|
||||
end
|
||||
end
|
||||
@@ -1,5 +0,0 @@
|
||||
Deface::Override.new(:virtual_path => "spree/admin/products/_form",
|
||||
:insert_top => "[data-hook='admin_product_form_right']",
|
||||
:partial => "spree/admin/products/group_buy_form",
|
||||
:name => "add_group_buy_to_admin_product_edit",
|
||||
:original => '0c0e8d714989e48ee246a8253fb2b362f108621a')
|
||||
@@ -1,6 +1,7 @@
|
||||
/ replace "div[data-hook='admin_payment_method_form_fields']"
|
||||
|
||||
= admin_inject_payment_method
|
||||
= admin_inject_json_ams_array "admin.paymentMethods", "shops", @hubs, Api::Admin::BasicEnterpriseSerializer
|
||||
%div.alpha.eleven.columns{ "ng-app" => "admin.paymentMethods", "ng-controller" => "paymentMethodCtrl" }
|
||||
.row
|
||||
.alpha.three.columns
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
/ insert_bottom "[data-hook='admin_product_form_additional_fields']"
|
||||
|
||||
= f.field_container :notes do
|
||||
= f.label :notes, t(:notes)
|
||||
= f.text_area :notes, { :class => 'fullwidth', rows: 5 }
|
||||
= f.error_message_on :notes
|
||||
@@ -1,3 +1,3 @@
|
||||
/ insert_top "[data-hook='admin_product_form_right']"
|
||||
/ insert_after "div[class='variant_units_form']"
|
||||
|
||||
= render 'spree/admin/products/primary_taxon_form', f: f
|
||||
@@ -1,7 +1,6 @@
|
||||
/ insert_top "[data-hook='admin_product_form_right']"
|
||||
|
||||
/ insert_before "code[erb-loud]:contains('f.field_container :price')"
|
||||
= f.field_container :supplier do
|
||||
= f.label :supplier, t(:spree_admin_supplier)
|
||||
%br
|
||||
= f.collection_select(:supplier_id, @producers, :id, :name, {:include_blank => true}, {:class => "select2"})
|
||||
= f.error_message_on :supplier
|
||||
= f.error_message_on :supplier
|
||||
@@ -0,0 +1,2 @@
|
||||
remove "code[erb-loud]:contains('f.label :available_on')"
|
||||
closing_selector("code[erb-loud]:contains('f.text_field :available_on')")
|
||||
@@ -0,0 +1,2 @@
|
||||
remove "code[erb-loud]:contains('f.field_container :cost_currency')"
|
||||
closing_selector("code[erb-silent]:contains('end')")
|
||||
@@ -0,0 +1,2 @@
|
||||
remove "code[erb-loud]:contains('f.field_container :cost_price')"
|
||||
closing_selector("code[erb-silent]:contains('end')")
|
||||
@@ -0,0 +1 @@
|
||||
remove "div[data-hook='admin_product_form_meta']"
|
||||
@@ -0,0 +1 @@
|
||||
remove "div[class='twelve columns alpha omega']"
|
||||
@@ -0,0 +1,2 @@
|
||||
/ replace "[data-hook=admin_product_form_right] code[erb-loud]:contains('f.label :price')"
|
||||
= f.label :price, raw(t(:price) + content_tag(:span, ' *', :class => 'required'))
|
||||
@@ -0,0 +1,5 @@
|
||||
/ insert_bottom "[data-hook=admin_product_form_left]"
|
||||
= f.field_container :taxons do
|
||||
= f.label :taxon_ids, t(:taxons)
|
||||
%br
|
||||
= f.hidden_field :taxon_ids, :value => @product.taxon_ids.join(',')
|
||||
@@ -0,0 +1,4 @@
|
||||
// insert_bottom "[data-hook='admin_configurations_sidebar_menu']"
|
||||
|
||||
%li
|
||||
= link_to t('.stripe_connect'), main_app.edit_admin_stripe_connect_settings_path
|
||||
@@ -0,0 +1,5 @@
|
||||
/ insert_bottom "[data-hook='admin_product_tabs']"
|
||||
|
||||
- klass = current == 'Group Buy Options' ? 'active' : ''
|
||||
%li{:class => klass}
|
||||
= link_to_with_icon 'icon-tasks', 'Group Buy Options', group_buy_options_admin_product_url(@product)
|
||||
@@ -0,0 +1,5 @@
|
||||
/ insert_bottom "[data-hook='admin_product_tabs']"
|
||||
|
||||
- klass = current == 'SEO' ? 'active' : ''
|
||||
%li{:class => klass}
|
||||
= link_to_with_icon 'icon-tasks', 'SEO', seo_admin_product_url(@product)
|
||||
@@ -1,4 +1,4 @@
|
||||
class Api::Admin::BasicEnterpriseSerializer < ActiveModel::Serializer
|
||||
attributes :name, :id, :is_primary_producer, :is_distributor, :sells, :category, :payment_method_ids, :shipping_method_ids
|
||||
attributes :producer_profile_only
|
||||
attributes :producer_profile_only, :permalink
|
||||
end
|
||||
|
||||
13
app/serializers/api/admin/payment_method/base_serializer.rb
Normal file
13
app/serializers/api/admin/payment_method/base_serializer.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
module Api::Admin::PaymentMethod
|
||||
class BaseSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name, :type, :tag_list, :tags
|
||||
|
||||
def tag_list
|
||||
object.tag_list.join(",")
|
||||
end
|
||||
|
||||
def tags
|
||||
object.tag_list.map{ |t| { text: t } }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
module Api::Admin::PaymentMethod
|
||||
class StripeSerializer < BaseSerializer
|
||||
attributes :preferred_enterprise_id
|
||||
end
|
||||
end
|
||||
@@ -1,11 +1,15 @@
|
||||
class Api::Admin::PaymentMethodSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name, :type, :tag_list, :tags
|
||||
module Api
|
||||
module Admin
|
||||
class PaymentMethodSerializer < ActiveModel::Serializer
|
||||
delegate :serializable_hash, to: :method_serializer
|
||||
|
||||
def tag_list
|
||||
object.tag_list.join(",")
|
||||
end
|
||||
|
||||
def tags
|
||||
object.tag_list.map{ |t| { text: t } }
|
||||
def method_serializer
|
||||
if object.type == 'Spree::Gateway::StripeConnect'
|
||||
Api::Admin::PaymentMethod::StripeSerializer.new(object)
|
||||
else
|
||||
Api::Admin::PaymentMethod::BaseSerializer.new(object)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
27
app/serializers/api/credit_card_serializer.rb
Normal file
27
app/serializers/api/credit_card_serializer.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
module Api
|
||||
class CreditCardSerializer < ActiveModel::Serializer
|
||||
attributes :id, :brand, :number, :expiry, :formatted, :delete_link
|
||||
|
||||
def brand
|
||||
object.cc_type.capitalize
|
||||
end
|
||||
|
||||
def number
|
||||
"x-#{object.last_digits}"
|
||||
end
|
||||
|
||||
def expiry
|
||||
m = object.month.to_i
|
||||
m = m < 10 ? "0#{m}" : m.to_s
|
||||
"#{m}/#{object.year}"
|
||||
end
|
||||
|
||||
def formatted
|
||||
"#{brand} #{number} #{I18n.t(:card_expiry_abbreviation)}:#{expiry}"
|
||||
end
|
||||
|
||||
def delete_link
|
||||
Spree::Core::Engine.routes.url_helpers.credit_card_path(object.id)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,13 +1,18 @@
|
||||
module Api
|
||||
class OrderSerializer < ActiveModel::Serializer
|
||||
attributes :number, :completed_at, :total, :state, :shipment_state, :payment_state
|
||||
attributes :outstanding_balance, :payments, :path, :cancel_path, :changes_allowed, :changes_allowed_until
|
||||
attributes :shop_name, :item_count
|
||||
attributes :outstanding_balance, :payments, :path, :cancel_path
|
||||
attributes :changes_allowed, :changes_allowed_until, :item_count
|
||||
attributes :shop_id
|
||||
|
||||
has_many :payments, serializer: Api::PaymentSerializer
|
||||
|
||||
def shop_name
|
||||
object.distributor.andand.name
|
||||
def payments
|
||||
object.payments.joins(:payment_method).completed
|
||||
end
|
||||
|
||||
def shop_id
|
||||
object.distributor_id
|
||||
end
|
||||
|
||||
def item_count
|
||||
@@ -23,10 +28,6 @@ module Api
|
||||
I18n.l(object.order_cycle.andand.orders_close_at, format: "%b %d, %Y %H:%M")
|
||||
end
|
||||
|
||||
def total
|
||||
object.total.to_money.to_s
|
||||
end
|
||||
|
||||
def shipment_state
|
||||
object.shipment_state ? object.shipment_state : nil
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@ module Api
|
||||
has_many :distributed_orders, serializer: Api::OrderSerializer
|
||||
|
||||
def balance
|
||||
object.distributed_orders.map(&:outstanding_balance).reduce(:+).to_money.to_s
|
||||
object.distributed_orders.map(&:outstanding_balance).reduce(:+)
|
||||
end
|
||||
|
||||
def hash
|
||||
|
||||
@@ -2,15 +2,11 @@ module Api
|
||||
class PaymentSerializer < ActiveModel::Serializer
|
||||
attributes :amount, :updated_at, :payment_method, :state
|
||||
def payment_method
|
||||
object.payment_method.name
|
||||
end
|
||||
|
||||
def amount
|
||||
object.amount.to_money.to_s
|
||||
object.payment_method.try(:name)
|
||||
end
|
||||
|
||||
def updated_at
|
||||
I18n.l(object.updated_at, format: :long)
|
||||
I18n.l(object.updated_at, format: "%b %d, %Y %H:%M")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
13
app/serializers/api/shop_for_orders_serializer.rb
Normal file
13
app/serializers/api/shop_for_orders_serializer.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
module Api
|
||||
class ShopForOrdersSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name, :hash, :logo
|
||||
|
||||
def hash
|
||||
object.to_param
|
||||
end
|
||||
|
||||
def logo
|
||||
object.logo(:small) if object.logo?
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,7 +4,7 @@
|
||||
= form_for [main_app, :admin, @enterprise], html: { name: "enterprise_form",
|
||||
"ng-controller" => 'enterpriseCtrl',
|
||||
'onchange' => 'angular.element(enterprise_form).scope().setFormDirty()',
|
||||
} do |f|
|
||||
"ng-cloak" => true } do |f|
|
||||
|
||||
%save-bar{ dirty: "enterprise_form.$dirty", persist: "true" }
|
||||
%input.red{ type: "button", value: t(:update), ng: { click: "submit()", disabled: "!enterprise_form.$dirty" } }
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
- if Spree::Config.stripe_connect_enabled || @enterprise.stripe_account
|
||||
= render 'admin/enterprises/form/stripe_connect'
|
||||
|
||||
- if @payment_methods.count > 0
|
||||
%table
|
||||
%thead
|
||||
|
||||
15
app/views/admin/enterprises/form/_stripe_connect.html.haml
Normal file
15
app/views/admin/enterprises/form/_stripe_connect.html.haml
Normal file
@@ -0,0 +1,15 @@
|
||||
= render 'admin/enterprises/form/stripe_connect/confirm_modal'
|
||||
|
||||
- if @stripe_account = @enterprise.stripe_account
|
||||
.stripe-info
|
||||
.row
|
||||
= t('.stripe_account_connected')
|
||||
.row
|
||||
=link_to t('.disconnect'), main_app.admin_stripe_account_path(@stripe_account), method: :delete, class: 'button'
|
||||
- else
|
||||
.row.stripe-info
|
||||
.six.columns.alpha
|
||||
=t('.stripe_connect_intro')
|
||||
.five.columns.omega.text-right
|
||||
%a.stripe-connect.help-modal{ template: 'admin/modals/stripe_connect_confirm.html' }
|
||||
%span= t('.connect_with_stripe')
|
||||
@@ -0,0 +1,27 @@
|
||||
%script{ type: "text/ng-template", id: "admin/modals/stripe_connect_confirm.html" }
|
||||
-# Recommended info to impart (from Stripe Connect docs):
|
||||
-# indicate to the user what you’re responsible for and what they’ll be expected to do. It’s particularly important to communicate:
|
||||
-# That they’ll need to create and maintain their Stripe account.
|
||||
-# That they’ll need to handle chargebacks and all customer service issues.
|
||||
-# Who is responsible for paying the Stripe fees.
|
||||
-# What, if any, fees the platform charges.
|
||||
|
||||
#stripe-connect-confirm
|
||||
.margin-bottom-30.text-center
|
||||
.text-big
|
||||
= t('.title')
|
||||
|
||||
.margin-bottom-30
|
||||
%p= t('.part1')
|
||||
|
||||
.margin-bottom-30
|
||||
%p= t('.part2')
|
||||
|
||||
.margin-bottom-30
|
||||
%p= t('.part3')
|
||||
|
||||
.text-center
|
||||
%a.button.icon-ok{ href: main_app.connect_admin_stripe_accounts_path(enterprise_id: @enterprise) }
|
||||
= t('.i_agree')
|
||||
%a.button.red.icon-remove{ href: 'javascript:void(0)', ng: { click: 'close()' } }
|
||||
= t('.cancel')
|
||||
51
app/views/admin/stripe_connect_settings/edit.html.haml
Normal file
51
app/views/admin/stripe_connect_settings/edit.html.haml
Normal file
@@ -0,0 +1,51 @@
|
||||
= render :partial => 'spree/admin/shared/configuration_menu'
|
||||
|
||||
- content_for :page_title do
|
||||
= t('.title')
|
||||
|
||||
%fieldset.no-border-bottom
|
||||
%legend
|
||||
= t('.settings')
|
||||
= form_for @settings, as: :settings, url: main_app.admin_stripe_connect_settings_path, :method => :put do |f|
|
||||
.row
|
||||
.twelve.columns.alpha.omega
|
||||
.field
|
||||
- disabled = !@settings.stripe_connect_enabled && @stripe_account[:status] != :ok
|
||||
= f.label :stripe_connect_enabled, t('.stripe_connect_enabled')
|
||||
= f.check_box :stripe_connect_enabled, disabled: disabled
|
||||
.row
|
||||
.twelve.columns.alpha.omega.form-buttons{"data-hook" => "buttons"}
|
||||
= button t(:update), 'icon-refresh', value: "update"
|
||||
|
||||
%fieldset.no-border-bottom
|
||||
%legend= t('.status')
|
||||
%strong= t('.configuration_explanation_html')
|
||||
- if @stripe_account[:status] == :ok
|
||||
.alert-box.ok
|
||||
.status
|
||||
%strong= t(".status") + ":"
|
||||
= t(".ok")
|
||||
%i.icon-ok
|
||||
.business_name
|
||||
%strong= t(".business_name") + ":"
|
||||
= @stripe_account[:business_name]
|
||||
.charges_enabled
|
||||
%strong
|
||||
- enabled_text = t(@stripe_account[:charges_enabled] ? :say_yes : :say_no)
|
||||
= t(".charges_enabled") + ":"
|
||||
= enabled_text
|
||||
.account_id
|
||||
%strong= t(".account_id") + ":"
|
||||
= @stripe_account[:id]
|
||||
.secret_key
|
||||
%strong= t('.instance_secret_key') + ":"
|
||||
= @obfuscated_secret_key
|
||||
.publishable_key
|
||||
%strong= t('.instance_publishable_key') + ":"
|
||||
= Stripe.publishable_key
|
||||
- if !@stripe_account[:charges_enabled]
|
||||
.alert-box.warning
|
||||
= t(".charges_enabled_warning")
|
||||
- else
|
||||
.alert-box.error
|
||||
= t(".#{@stripe_account[:status]}")
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user