mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-20 19:56:48 +00:00
Compare commits
441 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab9bc7b1dc | ||
|
|
cf4ccc268a | ||
|
|
7af17242f9 | ||
|
|
eb5e411a8e | ||
|
|
bdeca54377 | ||
|
|
20d59cf5a5 | ||
|
|
8b241f058b | ||
|
|
cb28843af1 | ||
|
|
d684a88697 | ||
|
|
d0f66a6053 | ||
|
|
d2fbf9f14d | ||
|
|
8d3f25bb39 | ||
|
|
abaaf05631 | ||
|
|
dd8c769ea9 | ||
|
|
864c9ec1da | ||
|
|
b0cfa6a17c | ||
|
|
51258b242c | ||
|
|
1a44e74a9d | ||
|
|
efbf2c7ffa | ||
|
|
6365434a94 | ||
|
|
d9f90be38a | ||
|
|
008b43b1fc | ||
|
|
5609354136 | ||
|
|
d9e8ce2f0e | ||
|
|
cce65aa462 | ||
|
|
44511b8b61 | ||
|
|
eb413ccc84 | ||
|
|
6cd6b751c8 | ||
|
|
af95181245 | ||
|
|
36fa4896ed | ||
|
|
7c723c04b6 | ||
|
|
c85d5b86eb | ||
|
|
1a97df1d21 | ||
|
|
a5716cf2c2 | ||
|
|
b4e990a081 | ||
|
|
eccd97fc28 | ||
|
|
c4d4d10873 | ||
|
|
1e5e009735 | ||
|
|
ea96759306 | ||
|
|
d967905b83 | ||
|
|
f698408d40 | ||
|
|
75b0b290ae | ||
|
|
21b18a8cc5 | ||
|
|
91bf588bcc | ||
|
|
a8de4dc039 | ||
|
|
c7cf9695bc | ||
|
|
b9a0579397 | ||
|
|
de6abc3464 | ||
|
|
881313edf9 | ||
|
|
381bfd383b | ||
|
|
266d6ef834 | ||
|
|
1e18f773f5 | ||
|
|
41792395aa | ||
|
|
98ff895f5f | ||
|
|
c3c1573f54 | ||
|
|
a0af22350d | ||
|
|
e3b660abb9 | ||
|
|
9a86e41942 | ||
|
|
b5ce056d06 | ||
|
|
574a215525 | ||
|
|
2cdab7af25 | ||
|
|
235bb009e8 | ||
|
|
dfb855bd14 | ||
|
|
9395f6c808 | ||
|
|
53fa71d1f3 | ||
|
|
61c08997a1 | ||
|
|
dd61034908 | ||
|
|
ec22f4c09f | ||
|
|
54894fb222 | ||
|
|
11f59c9f59 | ||
|
|
27a730ef6c | ||
|
|
10e5d09416 | ||
|
|
3b4d73760b | ||
|
|
89199ef30a | ||
|
|
67c77cea81 | ||
|
|
cc7d6cde1d | ||
|
|
0b636c1d89 | ||
|
|
2b9fef6aec | ||
|
|
3aa30af199 | ||
|
|
0212351d32 | ||
|
|
29653a5595 | ||
|
|
e6368af757 | ||
|
|
2c80be7e9e | ||
|
|
d194e74eda | ||
|
|
3f61a5412c | ||
|
|
0f3723a923 | ||
|
|
bbca674937 | ||
|
|
623882a2a1 | ||
|
|
371f966f63 | ||
|
|
be55f461d0 | ||
|
|
e6591be55c | ||
|
|
5b6bff1691 | ||
|
|
db2e5e7558 | ||
|
|
4867f45ee1 | ||
|
|
47b08269d6 | ||
|
|
76f234ee4d | ||
|
|
163035dcad | ||
|
|
503bd8f5dd | ||
|
|
6e800341c3 | ||
|
|
b097a62c7a | ||
|
|
cfa281478a | ||
|
|
f64684dc48 | ||
|
|
397697d17c | ||
|
|
c940a34ec9 | ||
|
|
fc63d8719c | ||
|
|
7ba366e2a6 | ||
|
|
b26c46d7db | ||
|
|
72a568ffad | ||
|
|
3ea7ff766a | ||
|
|
3d491d7b5e | ||
|
|
1710c8726e | ||
|
|
2a8ba0bf42 | ||
|
|
3279003fd3 | ||
|
|
f2a35e219e | ||
|
|
39c5f8febe | ||
|
|
87b1ab9a1a | ||
|
|
85b8adb1aa | ||
|
|
e8818c5191 | ||
|
|
c91699a11e | ||
|
|
8d6c8791bb | ||
|
|
31054c7bf4 | ||
|
|
5563d23beb | ||
|
|
8de6f983a2 | ||
|
|
53594b3a0f | ||
|
|
f8619092bd | ||
|
|
2c2352cd4e | ||
|
|
12bfb9301a | ||
|
|
ba0d4c2111 | ||
|
|
4eee86a240 | ||
|
|
587e4ae86d | ||
|
|
60c246f104 | ||
|
|
87842ecaf5 | ||
|
|
2ba632456f | ||
|
|
3beff77164 | ||
|
|
69fd3f0b60 | ||
|
|
ff4bd449a2 | ||
|
|
379b702b9b | ||
|
|
fa4741eb65 | ||
|
|
1f7aec0c1d | ||
|
|
122cf6c065 | ||
|
|
9daf7e3955 | ||
|
|
a3df4bf026 | ||
|
|
fdde55f631 | ||
|
|
f8153c07b1 | ||
|
|
eade689070 | ||
|
|
a522242e7a | ||
|
|
e05d64a0b4 | ||
|
|
985887334f | ||
|
|
3aa06ee1e4 | ||
|
|
3ab961a7e2 | ||
|
|
60b7a571c5 | ||
|
|
f8ca24c5cd | ||
|
|
f58219eb3d | ||
|
|
4554c0555d | ||
|
|
176db78e64 | ||
|
|
98063dae60 | ||
|
|
c01d45e3af | ||
|
|
d5c2abdd7e | ||
|
|
a7b723af93 | ||
|
|
6a29b830c2 | ||
|
|
8e83c6679a | ||
|
|
a0f0b3c93b | ||
|
|
ecd7b16ef5 | ||
|
|
718a5911a3 | ||
|
|
bbac5aa803 | ||
|
|
346a4e71d0 | ||
|
|
f83ceae5d1 | ||
|
|
08afcac1e5 | ||
|
|
9496987da6 | ||
|
|
224864a8d8 | ||
|
|
b9248d3e2c | ||
|
|
903bd21577 | ||
|
|
87686848bc | ||
|
|
32a898b6a2 | ||
|
|
636ed2ad0d | ||
|
|
1d61e91afd | ||
|
|
6b5a1255f8 | ||
|
|
12dc0b93aa | ||
|
|
5503760ce3 | ||
|
|
9fa5a9e766 | ||
|
|
a62f48441d | ||
|
|
5c09ebf138 | ||
|
|
ee5ab22501 | ||
|
|
ad1f837c44 | ||
|
|
dcb24cf06c | ||
|
|
b73619d168 | ||
|
|
dde1a27d3a | ||
|
|
57e838898f | ||
|
|
773a5480e9 | ||
|
|
0fdf313424 | ||
|
|
46aee6f77c | ||
|
|
ca558a4ecc | ||
|
|
edcef02017 | ||
|
|
211e9c33a7 | ||
|
|
2293623d2c | ||
|
|
9e51b19f98 | ||
|
|
90ba1d2198 | ||
|
|
78877f591b | ||
|
|
f292be8c92 | ||
|
|
755adf4287 | ||
|
|
9547f91f46 | ||
|
|
30601b9203 | ||
|
|
504a053693 | ||
|
|
148333467f | ||
|
|
242fb49276 | ||
|
|
37dbd376e9 | ||
|
|
b641de6ec9 | ||
|
|
313843d798 | ||
|
|
1b51ea0e3a | ||
|
|
f2e3d298fa | ||
|
|
e19aaf6be8 | ||
|
|
28b2dd40dd | ||
|
|
c9bbe80738 | ||
|
|
0f7b880409 | ||
|
|
78a8f8c1bb | ||
|
|
b1b1aa5b1e | ||
|
|
a7c2a73fa8 | ||
|
|
fce7714994 | ||
|
|
7ca9670073 | ||
|
|
22f6ece83f | ||
|
|
a7bb04b890 | ||
|
|
4c586d1b7e | ||
|
|
7ea143d19a | ||
|
|
25189d190b | ||
|
|
91b35d068c | ||
|
|
8d9f8beff3 | ||
|
|
c0a7d22a50 | ||
|
|
fafbfe8735 | ||
|
|
6fddb491db | ||
|
|
5ea3733c8a | ||
|
|
7ac888ae00 | ||
|
|
ed4d78bca8 | ||
|
|
d99a54accf | ||
|
|
fd363ff6c2 | ||
|
|
fcd9653a79 | ||
|
|
8e42f29bde | ||
|
|
a25bf32156 | ||
|
|
7a5c56cbca | ||
|
|
cbae7dcc8e | ||
|
|
9163b0c1ad | ||
|
|
fd9f65f1b6 | ||
|
|
713999c1d8 | ||
|
|
21db56ce6c | ||
|
|
adbe127e76 | ||
|
|
3c4ad4121f | ||
|
|
8e8f38e484 | ||
|
|
d93a8b6428 | ||
|
|
7a48d7fe22 | ||
|
|
b429be707c | ||
|
|
87b092fdf7 | ||
|
|
4829e59663 | ||
|
|
d12fdd23fb | ||
|
|
b0a29801b6 | ||
|
|
6ebd58b67d | ||
|
|
0791cc3c2a | ||
|
|
76acbb6159 | ||
|
|
d7ea81e821 | ||
|
|
9245af6a8f | ||
|
|
36430d3bad | ||
|
|
7520552fd7 | ||
|
|
6991e5e6b1 | ||
|
|
42d6695264 | ||
|
|
4d26b3d648 | ||
|
|
177181cd75 | ||
|
|
4baa205cf9 | ||
|
|
60313f7a6a | ||
|
|
3e5ea3fe63 | ||
|
|
b98c01b280 | ||
|
|
ff624e83eb | ||
|
|
48dc85cfc2 | ||
|
|
a0990c107f | ||
|
|
585c061fb0 | ||
|
|
83726eba63 | ||
|
|
7ad9fdf0be | ||
|
|
6b10a4a775 | ||
|
|
4088bdc236 | ||
|
|
9b78963d5a | ||
|
|
3ec3441cfa | ||
|
|
39889390ef | ||
|
|
c3659612ed | ||
|
|
7a6cd98646 | ||
|
|
9286c82b43 | ||
|
|
c330e49a7f | ||
|
|
e2268e53bb | ||
|
|
9f0aeb5adf | ||
|
|
0d9a0919e5 | ||
|
|
c1aa2f9b33 | ||
|
|
650e35c13e | ||
|
|
71de15b3e4 | ||
|
|
41e42c78c4 | ||
|
|
1753432f36 | ||
|
|
0f8809abfc | ||
|
|
1d80bee595 | ||
|
|
d04e843315 | ||
|
|
c0eb902eef | ||
|
|
2c307f09c3 | ||
|
|
23fc428d95 | ||
|
|
3bd77c74a5 | ||
|
|
8334ff736b | ||
|
|
51687b5c2c | ||
|
|
21108b34b6 | ||
|
|
2a21889216 | ||
|
|
b451b94fd1 | ||
|
|
d2d3a577ea | ||
|
|
b3e67fa164 | ||
|
|
ac34da4f24 | ||
|
|
d2277999cc | ||
|
|
cdd6c2daf2 | ||
|
|
4a881a5aa5 | ||
|
|
d5d218c450 | ||
|
|
f8622be21d | ||
|
|
676e7cb4d6 | ||
|
|
1dfbc88813 | ||
|
|
9db1c4c708 | ||
|
|
25a734b208 | ||
|
|
47a8731b8e | ||
|
|
932604bd69 | ||
|
|
4d7871a0bb | ||
|
|
51c8891fac | ||
|
|
9b258e075b | ||
|
|
891a9b06a8 | ||
|
|
4dc0701213 | ||
|
|
b5879d51ac | ||
|
|
dcc04ea538 | ||
|
|
83754a01ef | ||
|
|
2d82f76a43 | ||
|
|
d5437e1508 | ||
|
|
f0bd9c1065 | ||
|
|
642de2f65f | ||
|
|
f6e9c9494c | ||
|
|
90ad2e2b7d | ||
|
|
cfb69ae7d2 | ||
|
|
a93a824b83 | ||
|
|
2170c7ede1 | ||
|
|
06cf914119 | ||
|
|
3e5dfda324 | ||
|
|
13cbbcef40 | ||
|
|
949808e839 | ||
|
|
02a276b9c9 | ||
|
|
9f1a773a58 | ||
|
|
0e510998a4 | ||
|
|
307cc313df | ||
|
|
0431e0048c | ||
|
|
20bde803c8 | ||
|
|
6b43354386 | ||
|
|
494bb1f3b4 | ||
|
|
d52b6b34e3 | ||
|
|
4583e29ae3 | ||
|
|
a4d4622521 | ||
|
|
20f650b472 | ||
|
|
e013e1fe00 | ||
|
|
d40ffeef52 | ||
|
|
6200390369 | ||
|
|
e9f32f5329 | ||
|
|
27bc845b0b | ||
|
|
22cb8b7a71 | ||
|
|
c6db1d440c | ||
|
|
bc448e5156 | ||
|
|
6a42f62eb2 | ||
|
|
8db09d9590 | ||
|
|
7e55262ce9 | ||
|
|
bbc887a692 | ||
|
|
6f36c0463c | ||
|
|
592ac7856a | ||
|
|
261dea37e9 | ||
|
|
80c507cc66 | ||
|
|
1ad13f0359 | ||
|
|
532041c07b | ||
|
|
05bd0c4168 | ||
|
|
51b0d7e0eb | ||
|
|
d2e0d4f44a | ||
|
|
ab26902e4e | ||
|
|
6adb4194c2 | ||
|
|
b6f29c778e | ||
|
|
4839c00d62 | ||
|
|
a438216189 | ||
|
|
29f9b3bbd7 | ||
|
|
ac59665e3c | ||
|
|
e4efda2f96 | ||
|
|
a9b91bc52a | ||
|
|
f90ee33c89 | ||
|
|
087ccb52f9 | ||
|
|
4bf8716786 | ||
|
|
c0030ddb13 | ||
|
|
370133b875 | ||
|
|
3b9657eb17 | ||
|
|
9956b967f0 | ||
|
|
9310bc902a | ||
|
|
9798b05a24 | ||
|
|
586753015b | ||
|
|
6863dd75ef | ||
|
|
fafdb29fcb | ||
|
|
85882a73ff | ||
|
|
2bad590ef4 | ||
|
|
c3995ee4d5 | ||
|
|
94684e9963 | ||
|
|
1e1a070b2b | ||
|
|
d50f8dcd01 | ||
|
|
813ef463a2 | ||
|
|
72118f4e2e | ||
|
|
e9f04c3c15 | ||
|
|
6e0576235d | ||
|
|
27d646c0e8 | ||
|
|
0151ecbb32 | ||
|
|
d548515684 | ||
|
|
343af1f1e0 | ||
|
|
3b58d99abc | ||
|
|
4a30f27b3d | ||
|
|
c4b45bdbbf | ||
|
|
b0f5d0170c | ||
|
|
5fcb2982fa | ||
|
|
ead84aa9ff | ||
|
|
1d3800696e | ||
|
|
f5ee9ba2f3 | ||
|
|
e6eecd3ae2 | ||
|
|
0832a8f63d | ||
|
|
23c7715929 | ||
|
|
2ea7bdbec6 | ||
|
|
6c300431d2 | ||
|
|
91c500417b | ||
|
|
7e49bd634e | ||
|
|
eeae72352b | ||
|
|
079781576b | ||
|
|
f878e18037 | ||
|
|
633a8a49e2 | ||
|
|
a5ae1c490c | ||
|
|
c2c51a5531 | ||
|
|
35c27bf516 | ||
|
|
e4d1ae7548 | ||
|
|
4f153714a8 | ||
|
|
451dd3966f | ||
|
|
c3829ae64f | ||
|
|
b81bf60dc2 | ||
|
|
cc0da142b7 | ||
|
|
03b59eae75 | ||
|
|
e89184de02 | ||
|
|
cc3959467d | ||
|
|
15f29f4c8e | ||
|
|
932d571d2c | ||
|
|
9a5ee81431 | ||
|
|
6f6ae309c6 |
2
.mailmap
Normal file
2
.mailmap
Normal file
@@ -0,0 +1,2 @@
|
||||
Rob Harrington <oeoeaio@gmail.com>
|
||||
Laura Summers <summerscope@gmail.com>
|
||||
8
Gemfile
8
Gemfile
@@ -1,12 +1,13 @@
|
||||
source 'https://rubygems.org'
|
||||
ruby "1.9.3"
|
||||
|
||||
gem 'rails', '3.2.19'
|
||||
gem 'rails', '3.2.21'
|
||||
gem 'rails-i18n', '~> 3.0.0'
|
||||
gem 'i18n', '~> 0.6.11'
|
||||
|
||||
gem 'pg'
|
||||
gem 'spree', :github => 'openfoodfoundation/spree', :branch => '1-3-stable'
|
||||
gem 'spree_i18n', :github => 'spree/spree_i18n'
|
||||
gem 'spree_i18n', :github => 'spree/spree_i18n', :branch => '1-3-stable'
|
||||
gem 'spree_auth_devise', :github => 'spree/spree_auth_devise', :branch => '1-3-stable'
|
||||
|
||||
# Waiting on merge of PR #117
|
||||
@@ -21,7 +22,7 @@ gem 'comfortable_mexican_sofa'
|
||||
gem 'simple_form', :github => 'RohanM/simple_form'
|
||||
|
||||
gem 'unicorn'
|
||||
gem 'angularjs-rails'
|
||||
gem 'angularjs-rails', '1.2.13'
|
||||
gem 'bugsnag'
|
||||
gem 'newrelic_rpm'
|
||||
gem 'haml'
|
||||
@@ -78,6 +79,7 @@ gem 'jquery-rails'
|
||||
group :test, :development do
|
||||
# Pretty printed test output
|
||||
gem 'turn', '~> 0.8.3', :require => false
|
||||
gem 'fuubar'
|
||||
gem 'rspec-rails'
|
||||
gem 'shoulda-matchers'
|
||||
gem 'factory_girl_rails', :require => false
|
||||
|
||||
100
Gemfile.lock
100
Gemfile.lock
@@ -86,11 +86,13 @@ GIT
|
||||
|
||||
GIT
|
||||
remote: git://github.com/spree/spree_i18n.git
|
||||
revision: a96bee02340e008e60549295a4f09e047fd2e628
|
||||
revision: 752eb67204e9c5a4e22b62591a8fd55fe2285e43
|
||||
branch: 1-3-stable
|
||||
specs:
|
||||
spree_i18n (1.0.0)
|
||||
i18n (~> 0.5)
|
||||
spree (~> 1.1)
|
||||
rails-i18n
|
||||
spree_core (>= 1.1)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/willrjmarshall/foundation_rails_helper.git
|
||||
@@ -105,12 +107,12 @@ GIT
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actionmailer (3.2.19)
|
||||
actionpack (= 3.2.19)
|
||||
actionmailer (3.2.21)
|
||||
actionpack (= 3.2.21)
|
||||
mail (~> 2.5.4)
|
||||
actionpack (3.2.19)
|
||||
activemodel (= 3.2.19)
|
||||
activesupport (= 3.2.19)
|
||||
actionpack (3.2.21)
|
||||
activemodel (= 3.2.21)
|
||||
activesupport (= 3.2.21)
|
||||
builder (~> 3.0.0)
|
||||
erubis (~> 2.7.0)
|
||||
journey (~> 1.0.4)
|
||||
@@ -121,29 +123,23 @@ GEM
|
||||
active_link_to (1.0.0)
|
||||
active_model_serializers (0.8.1)
|
||||
activemodel (>= 3.0)
|
||||
active_utils (2.2.3)
|
||||
activesupport (>= 2.3.11)
|
||||
i18n
|
||||
activemerchant (1.44.1)
|
||||
active_utils (~> 2.2.0)
|
||||
activemerchant (1.46.0)
|
||||
activesupport (>= 3.2.14, < 5.0.0)
|
||||
builder (>= 2.1.2, < 4.0.0)
|
||||
i18n (>= 0.6.9)
|
||||
json (~> 1.7)
|
||||
nokogiri (~> 1.4)
|
||||
offsite_payments (~> 2.0.0)
|
||||
activemodel (3.2.19)
|
||||
activesupport (= 3.2.19)
|
||||
activemodel (3.2.21)
|
||||
activesupport (= 3.2.21)
|
||||
builder (~> 3.0.0)
|
||||
activerecord (3.2.19)
|
||||
activemodel (= 3.2.19)
|
||||
activesupport (= 3.2.19)
|
||||
activerecord (3.2.21)
|
||||
activemodel (= 3.2.21)
|
||||
activesupport (= 3.2.21)
|
||||
arel (~> 3.0.2)
|
||||
tzinfo (~> 0.3.29)
|
||||
activeresource (3.2.19)
|
||||
activemodel (= 3.2.19)
|
||||
activesupport (= 3.2.19)
|
||||
activesupport (3.2.19)
|
||||
activeresource (3.2.21)
|
||||
activemodel (= 3.2.21)
|
||||
activesupport (= 3.2.21)
|
||||
activesupport (3.2.21)
|
||||
i18n (~> 0.6, >= 0.6.4)
|
||||
multi_json (~> 1.0)
|
||||
acts_as_list (0.1.4)
|
||||
@@ -185,7 +181,7 @@ GEM
|
||||
climate_control (0.0.3)
|
||||
activesupport (>= 3.0)
|
||||
cliver (0.3.2)
|
||||
cocaine (0.5.4)
|
||||
cocaine (0.5.5)
|
||||
climate_control (>= 0.0.3, < 1.0)
|
||||
coderay (1.0.9)
|
||||
coffee-rails (3.2.2)
|
||||
@@ -195,7 +191,7 @@ GEM
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.3.3)
|
||||
colorize (0.7.3)
|
||||
colorize (0.7.5)
|
||||
columnize (0.3.6)
|
||||
comfortable_mexican_sofa (1.6.24)
|
||||
active_link_to (~> 1.0.0)
|
||||
@@ -269,6 +265,9 @@ GEM
|
||||
railties (>= 3.1.0)
|
||||
sass (>= 3.2.0)
|
||||
fssm (0.2.10)
|
||||
fuubar (1.3.3)
|
||||
rspec (>= 2.14.0, < 3.1.0)
|
||||
ruby-progressbar (~> 1.4)
|
||||
geocoder (1.1.8)
|
||||
gmaps4rails (1.5.6)
|
||||
guard (2.2.4)
|
||||
@@ -305,7 +304,7 @@ GEM
|
||||
jquery-rails (2.2.2)
|
||||
railties (>= 3.0, < 5.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
json (1.8.1)
|
||||
json (1.8.2)
|
||||
json_spec (1.1.1)
|
||||
multi_json (~> 1.0)
|
||||
rspec (~> 2.0)
|
||||
@@ -326,9 +325,9 @@ GEM
|
||||
mail (2.5.4)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
method_source (0.8.1)
|
||||
method_source (0.8.2)
|
||||
mime-types (1.25.1)
|
||||
mini_portile (0.6.1)
|
||||
mini_portile (0.6.2)
|
||||
momentjs-rails (2.5.1)
|
||||
railties (>= 3.1)
|
||||
money (5.1.1)
|
||||
@@ -339,16 +338,8 @@ GEM
|
||||
net-ssh (>= 2.6.5)
|
||||
net-ssh (2.6.8)
|
||||
newrelic_rpm (3.6.7.152)
|
||||
nokogiri (1.6.4.1)
|
||||
nokogiri (1.6.6.2)
|
||||
mini_portile (~> 0.6.0)
|
||||
offsite_payments (2.0.1)
|
||||
active_utils (~> 2.2.0)
|
||||
activesupport (>= 3.2.14, < 5.0.0)
|
||||
builder (>= 2.1.2, < 4.0.0)
|
||||
i18n (~> 0.5)
|
||||
json (~> 1.7)
|
||||
money (< 7.0.0)
|
||||
nokogiri (~> 1.4)
|
||||
oj (2.1.2)
|
||||
orm_adapter (0.5.0)
|
||||
paperclip (3.5.4)
|
||||
@@ -387,28 +378,28 @@ GEM
|
||||
rack
|
||||
rack-ssl (1.3.4)
|
||||
rack
|
||||
rack-test (0.6.2)
|
||||
rack-test (0.6.3)
|
||||
rack (>= 1.0)
|
||||
rails (3.2.19)
|
||||
actionmailer (= 3.2.19)
|
||||
actionpack (= 3.2.19)
|
||||
activerecord (= 3.2.19)
|
||||
activeresource (= 3.2.19)
|
||||
activesupport (= 3.2.19)
|
||||
rails (3.2.21)
|
||||
actionmailer (= 3.2.21)
|
||||
actionpack (= 3.2.21)
|
||||
activerecord (= 3.2.21)
|
||||
activeresource (= 3.2.21)
|
||||
activesupport (= 3.2.21)
|
||||
bundler (~> 1.0)
|
||||
railties (= 3.2.19)
|
||||
railties (= 3.2.21)
|
||||
rails-i18n (3.0.1)
|
||||
i18n (~> 0.5)
|
||||
rails (>= 3.0.0, < 4.0.0)
|
||||
railties (3.2.19)
|
||||
actionpack (= 3.2.19)
|
||||
activesupport (= 3.2.19)
|
||||
railties (3.2.21)
|
||||
actionpack (= 3.2.21)
|
||||
activesupport (= 3.2.21)
|
||||
rack-ssl (~> 1.3.2)
|
||||
rake (>= 0.8.7)
|
||||
rdoc (~> 3.4)
|
||||
thor (>= 0.14.6, < 2.0)
|
||||
raindrops (0.9.0)
|
||||
rake (10.3.2)
|
||||
rake (10.4.2)
|
||||
ransack (0.7.2)
|
||||
actionpack (~> 3.0)
|
||||
activerecord (~> 3.0)
|
||||
@@ -449,6 +440,7 @@ GEM
|
||||
rspec-expectations (~> 2.14.0)
|
||||
rspec-mocks (~> 2.14.0)
|
||||
ruby-hmac (0.4.0)
|
||||
ruby-progressbar (1.7.1)
|
||||
safe_yaml (0.9.5)
|
||||
sass (3.2.19)
|
||||
sass-rails (3.2.6)
|
||||
@@ -489,7 +481,7 @@ GEM
|
||||
sprockets (>= 2.0.0)
|
||||
turn (0.8.3)
|
||||
ansi
|
||||
tzinfo (0.3.42)
|
||||
tzinfo (0.3.43)
|
||||
uglifier (1.2.4)
|
||||
execjs (>= 0.3.0)
|
||||
multi_json (>= 1.0.2)
|
||||
@@ -517,7 +509,7 @@ GEM
|
||||
xml-simple (1.1.4)
|
||||
xpath (2.0.0)
|
||||
nokogiri (~> 1.3)
|
||||
zeus (0.13.3)
|
||||
zeus (0.15.4)
|
||||
method_source (>= 0.6.7)
|
||||
|
||||
PLATFORMS
|
||||
@@ -528,7 +520,7 @@ DEPENDENCIES
|
||||
andand
|
||||
angular-rails-templates
|
||||
angularjs-file-upload-rails (~> 1.1.0)
|
||||
angularjs-rails
|
||||
angularjs-rails (= 1.2.13)
|
||||
awesome_print
|
||||
aws-sdk
|
||||
bugsnag
|
||||
@@ -548,6 +540,7 @@ DEPENDENCIES
|
||||
foundation-icons-sass-rails
|
||||
foundation-rails
|
||||
foundation_rails_helper!
|
||||
fuubar
|
||||
geocoder
|
||||
gmaps4rails
|
||||
guard
|
||||
@@ -556,6 +549,7 @@ DEPENDENCIES
|
||||
guard-rspec
|
||||
guard-zeus
|
||||
haml
|
||||
i18n (~> 0.6.11)
|
||||
immigrant
|
||||
jquery-rails
|
||||
json_spec
|
||||
@@ -570,7 +564,7 @@ DEPENDENCIES
|
||||
rabl
|
||||
rack-livereload
|
||||
rack-ssl
|
||||
rails (= 3.2.19)
|
||||
rails (= 3.2.21)
|
||||
rails-i18n (~> 3.0.0)
|
||||
representative_view
|
||||
roadie-rails (~> 1.0.3)
|
||||
|
||||
@@ -53,14 +53,10 @@ Configure the site:
|
||||
cp config/application.yml.example config/application.yml
|
||||
edit config/application.yml
|
||||
|
||||
Create the development and test databases, using the settings specified in `config/database.yml`:
|
||||
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
|
||||
|
||||
Then load the schema and some seed data with the following command:
|
||||
|
||||
rake db:schema:load db:seed
|
||||
|
||||
Load some default data for your environment:
|
||||
|
||||
rake openfoodnetwork:dev:load_sample_data
|
||||
@@ -99,4 +95,4 @@ usage instructions.
|
||||
|
||||
## Licence
|
||||
|
||||
Copyright (c) 2012 - 2013 Open Food Foundation, released under the AGPL licence.
|
||||
Copyright (c) 2012 - 2015 Open Food Foundation, released under the AGPL licence.
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 44 KiB |
BIN
app/assets/images/noimage/group.png
Normal file
BIN
app/assets/images/noimage/group.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
BIN
app/assets/images/open-food-network-beta-black.png
Normal file
BIN
app/assets/images/open-food-network-beta-black.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 18 KiB |
55
app/assets/images/spinning-circles.svg
Executable file
55
app/assets/images/spinning-circles.svg
Executable file
@@ -0,0 +1,55 @@
|
||||
<!-- By Sam Herbert (@sherb), for everyone. More @ http://goo.gl/7AJzbL -->
|
||||
<svg width="58" height="58" viewBox="0 0 58 58" xmlns="http://www.w3.org/2000/svg">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<g transform="translate(2 1)" stroke="#0096ad" stroke-width="1.5">
|
||||
<circle cx="42.601" cy="11.462" r="5" fill-opacity="1" fill="#0096ad">
|
||||
<animate attributeName="fill-opacity"
|
||||
begin="0s" dur="1.3s"
|
||||
values="1;0;0;0;0;0;0;0" calcMode="linear"
|
||||
repeatCount="indefinite" />
|
||||
</circle>
|
||||
<circle cx="49.063" cy="27.063" r="5" fill-opacity="0" fill="#0096ad">
|
||||
<animate attributeName="fill-opacity"
|
||||
begin="0s" dur="1.3s"
|
||||
values="0;1;0;0;0;0;0;0" calcMode="linear"
|
||||
repeatCount="indefinite" />
|
||||
</circle>
|
||||
<circle cx="42.601" cy="42.663" r="5" fill-opacity="0" fill="#0096ad">
|
||||
<animate attributeName="fill-opacity"
|
||||
begin="0s" dur="1.3s"
|
||||
values="0;0;1;0;0;0;0;0" calcMode="linear"
|
||||
repeatCount="indefinite" />
|
||||
</circle>
|
||||
<circle cx="27" cy="49.125" r="5" fill-opacity="0" fill="#0096ad">
|
||||
<animate attributeName="fill-opacity"
|
||||
begin="0s" dur="1.3s"
|
||||
values="0;0;0;1;0;0;0;0" calcMode="linear"
|
||||
repeatCount="indefinite" />
|
||||
</circle>
|
||||
<circle cx="11.399" cy="42.663" r="5" fill-opacity="0" fill="#0096ad">
|
||||
<animate attributeName="fill-opacity"
|
||||
begin="0s" dur="1.3s"
|
||||
values="0;0;0;0;1;0;0;0" calcMode="linear"
|
||||
repeatCount="indefinite" />
|
||||
</circle>
|
||||
<circle cx="4.938" cy="27.063" r="5" fill-opacity="0" fill="#0096ad">
|
||||
<animate attributeName="fill-opacity"
|
||||
begin="0s" dur="1.3s"
|
||||
values="0;0;0;0;0;1;0;0" calcMode="linear"
|
||||
repeatCount="indefinite" />
|
||||
</circle>
|
||||
<circle cx="11.399" cy="11.462" r="5" fill-opacity="0" fill="#0096ad">
|
||||
<animate attributeName="fill-opacity"
|
||||
begin="0s" dur="1.3s"
|
||||
values="0;0;0;0;0;0;1;0" calcMode="linear"
|
||||
repeatCount="indefinite" />
|
||||
</circle>
|
||||
<circle cx="27" cy="5" r="5" fill-opacity="0" fill="#0096ad">
|
||||
<animate attributeName="fill-opacity"
|
||||
begin="0s" dur="1.3s"
|
||||
values="0;0;0;0;0;0;0;1" calcMode="linear"
|
||||
repeatCount="indefinite" />
|
||||
</circle>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
@@ -19,6 +19,7 @@
|
||||
//= require ../shared/ng-infinite-scroll.min.js
|
||||
//= require ./admin
|
||||
//= require ./enterprises/enterprises
|
||||
//= require ./enterprise_groups/enterprise_groups
|
||||
//= require ./payment_methods/payment_methods
|
||||
//= require ./products/products
|
||||
//= require ./shipping_methods/shipping_methods
|
||||
|
||||
@@ -17,7 +17,7 @@ angular.module("ofn.admin").controller "AdminVariantOverridesCtrl", ($scope, $ti
|
||||
|
||||
|
||||
$scope.fetchProducts = ->
|
||||
url = "/api/products/distributable?page=::page::;per_page=100"
|
||||
url = "/api/products/overridable?page=::page::;per_page=100"
|
||||
PagedFetcher.fetch url, (data) => $scope.addProducts data.products
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
angular.module("admin.enterprise_groups")
|
||||
.controller "enterpriseGroupCtrl", ($scope, SideMenu) ->
|
||||
$scope.menu = SideMenu
|
||||
@@ -0,0 +1,15 @@
|
||||
angular.module("admin.enterprise_groups")
|
||||
.controller "sideMenuCtrl", ($scope, SideMenu) ->
|
||||
$scope.menu = SideMenu
|
||||
$scope.select = SideMenu.select
|
||||
|
||||
$scope.menu.setItems [
|
||||
{ name: 'Primary Details', icon_class: "icon-user" }
|
||||
{ name: 'Users', icon_class: "icon-user" }
|
||||
{ name: 'About', icon_class: "icon-pencil" }
|
||||
{ name: 'Images', icon_class: "icon-picture" }
|
||||
{ name: 'Contact', icon_class: "icon-phone" }
|
||||
{ name: 'Web', icon_class: "icon-globe" }
|
||||
]
|
||||
|
||||
$scope.select(0)
|
||||
@@ -0,0 +1 @@
|
||||
angular.module("admin.enterprise_groups", ["admin.side_menu", "admin.users"])
|
||||
@@ -1,68 +1,34 @@
|
||||
angular.module("admin.enterprises")
|
||||
.controller "enterpriseCtrl", ($scope, NavigationCheck, Enterprise, PaymentMethods, ShippingMethods, SideMenu) ->
|
||||
.controller "enterpriseCtrl", ($scope, NavigationCheck, Enterprise, EnterprisePaymentMethods, EnterpriseShippingMethods, SideMenu) ->
|
||||
$scope.Enterprise = Enterprise.enterprise
|
||||
$scope.PaymentMethods = PaymentMethods.paymentMethods
|
||||
$scope.ShippingMethods = ShippingMethods.shippingMethods
|
||||
$scope.PaymentMethods = EnterprisePaymentMethods.paymentMethods
|
||||
$scope.ShippingMethods = EnterpriseShippingMethods.shippingMethods
|
||||
$scope.navClear = NavigationCheck.clear
|
||||
# htmlVariable is used by textAngular wysiwyg for the long descrtiption.
|
||||
$scope.pristineEmail = $scope.Enterprise.email
|
||||
$scope.menu = SideMenu
|
||||
$scope.newManager = { id: '', email: 'Add a manager...' }
|
||||
|
||||
# Provide a callback for generating warning messages displayed before leaving the page. This is passed in
|
||||
# from a directive "nav-check" in the page - if we pass it here it will be called in the test suite,
|
||||
# and on all new uses of this contoller, and we might not want that .
|
||||
$scope.enterpriseNavCallback = ->
|
||||
if $scope.enterprise.$dirty
|
||||
enterpriseNavCallback = ->
|
||||
if $scope.Enterprise.$dirty
|
||||
"Your changes to the enterprise are not saved yet."
|
||||
|
||||
for payment_method in $scope.PaymentMethods
|
||||
payment_method.selected = payment_method.id in $scope.Enterprise.payment_method_ids
|
||||
# Register the NavigationCheck callback
|
||||
NavigationCheck.register(enterpriseNavCallback)
|
||||
|
||||
$scope.paymentMethodsColor = ->
|
||||
if $scope.PaymentMethods.length > 0
|
||||
if $scope.selectedPaymentMethodsCount() > 0 then "blue" else "red"
|
||||
else
|
||||
"red"
|
||||
$scope.removeManager = (manager) ->
|
||||
if manager.id?
|
||||
for i, user of $scope.Enterprise.users when user.id == manager.id
|
||||
$scope.Enterprise.users.splice i, 1
|
||||
|
||||
$scope.selectedPaymentMethodsCount = ->
|
||||
$scope.PaymentMethods.reduce (count, payment_method) ->
|
||||
count++ if payment_method.selected
|
||||
count
|
||||
, 0
|
||||
|
||||
for shipping_method in $scope.ShippingMethods
|
||||
shipping_method.selected = shipping_method.id in $scope.Enterprise.shipping_method_ids
|
||||
|
||||
$scope.shippingMethodsColor = ->
|
||||
if $scope.ShippingMethods.length > 0
|
||||
if $scope.selectedShippingMethodsCount() > 0 then "blue" else "red"
|
||||
else
|
||||
"red"
|
||||
|
||||
$scope.selectedShippingMethodsCount = ->
|
||||
$scope.ShippingMethods.reduce (count, shipping_method) ->
|
||||
count++ if shipping_method.selected
|
||||
count
|
||||
, 0
|
||||
|
||||
$scope.$watch "Enterprise.is_primary_producer", (newValue, oldValue) ->
|
||||
if !newValue && $scope.Enterprise.sells == "none"
|
||||
$scope.menu.hide_item_by_name('Enterprise Fees')
|
||||
else
|
||||
$scope.menu.show_item_by_name('Enterprise Fees')
|
||||
|
||||
|
||||
$scope.$watch "Enterprise.sells", (newValue, oldValue) ->
|
||||
if newValue == "none"
|
||||
$scope.menu.hide_item_by_name('Shipping Methods')
|
||||
$scope.menu.hide_item_by_name('Payment Methods')
|
||||
$scope.menu.hide_item_by_name('Shop Preferences')
|
||||
if $scope.Enterprise.is_primary_producer
|
||||
$scope.menu.show_item_by_name('Enterprise Fees')
|
||||
$scope.addManager = (manager) ->
|
||||
if manager.id? and manager.email?
|
||||
manager =
|
||||
id: manager.id
|
||||
email: manager.email
|
||||
if (user for user in $scope.Enterprise.users when user.id == manager.id).length == 0
|
||||
$scope.Enterprise.users.push manager
|
||||
else
|
||||
$scope.menu.hide_item_by_name('Enterprise Fees')
|
||||
else
|
||||
$scope.menu.show_item_by_name('Shipping Methods')
|
||||
$scope.menu.show_item_by_name('Payment Methods')
|
||||
$scope.menu.show_item_by_name('Shop Preferences')
|
||||
$scope.menu.show_item_by_name('Enterprise Fees')
|
||||
alert "#{manager.email} is already a manager!"
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
angular.module("admin.enterprises")
|
||||
.controller "permalinkCtrl", ($scope, PermalinkChecker) ->
|
||||
# locals
|
||||
initialPermalink = $scope.Enterprise.permalink
|
||||
pendingRequest = null
|
||||
|
||||
# variables on $scope
|
||||
$scope.availablility = ""
|
||||
$scope.checking = false
|
||||
|
||||
$scope.$watch "Enterprise.permalink", (newValue, oldValue) ->
|
||||
$scope.checking = true
|
||||
pendingRequest = PermalinkChecker.check(newValue)
|
||||
|
||||
pendingRequest.then (data) ->
|
||||
if data.permalink == initialPermalink
|
||||
$scope.availability = ""
|
||||
else
|
||||
$scope.availability = data.available
|
||||
$scope.Enterprise.permalink = data.permalink
|
||||
$scope.checking = false
|
||||
, (data) ->
|
||||
# Do nothing (this is hopefully an aborted request)
|
||||
@@ -1,21 +1,41 @@
|
||||
angular.module("admin.enterprises")
|
||||
.controller "sideMenuCtrl", ($scope, Enterprise, SideMenu) ->
|
||||
.controller "sideMenuCtrl", ($scope, $parse, Enterprise, SideMenu, enterprisePermissions) ->
|
||||
$scope.Enterprise = Enterprise.enterprise
|
||||
$scope.menu = SideMenu
|
||||
$scope.select = SideMenu.select
|
||||
|
||||
$scope.menu.setItems [
|
||||
{ name: 'Primary Details', icon_class: "icon-user" }
|
||||
{ name: 'Primary Details', icon_class: "icon-home" }
|
||||
{ name: 'Users', icon_class: "icon-user" }
|
||||
{ name: 'Address', icon_class: "icon-map-marker" }
|
||||
{ name: 'Contact', icon_class: "icon-phone" }
|
||||
{ name: 'Social', icon_class: "icon-twitter" }
|
||||
{ name: 'About', icon_class: "icon-pencil" }
|
||||
{ name: 'Business Details', icon_class: "icon-briefcase" }
|
||||
{ name: 'Images', icon_class: "icon-picture" }
|
||||
{ name: "Shipping Methods", icon_class: "icon-truck" }
|
||||
{ name: "Payment Methods", icon_class: "icon-money" }
|
||||
{ name: "Enterprise Fees", icon_class: "icon-tasks" }
|
||||
{ name: "Shop Preferences", icon_class: "icon-shopping-cart" }
|
||||
{ name: "Shipping Methods", icon_class: "icon-truck", show: "showShippingMethods()" }
|
||||
{ name: "Payment Methods", icon_class: "icon-money", show: "showPaymentMethods()" }
|
||||
{ name: "Enterprise Fees", icon_class: "icon-tasks", show: "showEnterpriseFees()" }
|
||||
{ name: "Shop Preferences", icon_class: "icon-shopping-cart", show: "showShopPreferences()" }
|
||||
]
|
||||
|
||||
$scope.select(0)
|
||||
|
||||
|
||||
$scope.showItem = (item) ->
|
||||
if item.show?
|
||||
$parse(item.show)($scope)
|
||||
else
|
||||
true
|
||||
|
||||
$scope.showShippingMethods = ->
|
||||
enterprisePermissions.can_manage_shipping_methods && $scope.Enterprise.sells != "none"
|
||||
|
||||
$scope.showPaymentMethods = ->
|
||||
enterprisePermissions.can_manage_payment_methods && $scope.Enterprise.sells != "none"
|
||||
|
||||
$scope.showEnterpriseFees = ->
|
||||
enterprisePermissions.can_manage_enterprise_fees && ($scope.Enterprise.sells != "none" || $scope.Enterprise.is_primary_producer)
|
||||
|
||||
$scope.showShopPreferences = ->
|
||||
$scope.Enterprise.sells != "none"
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
angular.module("admin.enterprises")
|
||||
.factory "EnterprisePaymentMethods", (Enterprise, PaymentMethods) ->
|
||||
new class EnterprisePaymentMethods
|
||||
paymentMethods: PaymentMethods.paymentMethods
|
||||
|
||||
constructor: ->
|
||||
for payment_method in @paymentMethods
|
||||
payment_method.selected = payment_method.id in Enterprise.enterprise.payment_method_ids
|
||||
|
||||
displayColor: ->
|
||||
if @paymentMethods.length > 0 && @selectedCount() > 0
|
||||
"blue"
|
||||
else
|
||||
"red"
|
||||
|
||||
selectedCount: ->
|
||||
@paymentMethods.reduce (count, payment_method) ->
|
||||
count++ if payment_method.selected
|
||||
count
|
||||
, 0
|
||||
@@ -0,0 +1,20 @@
|
||||
angular.module("admin.enterprises")
|
||||
.factory "EnterpriseShippingMethods", (Enterprise, ShippingMethods) ->
|
||||
new class EnterpriseShippingMethods
|
||||
shippingMethods: ShippingMethods.shippingMethods
|
||||
|
||||
constructor: ->
|
||||
for shipping_method in @shippingMethods
|
||||
shipping_method.selected = shipping_method.id in Enterprise.enterprise.shipping_method_ids
|
||||
|
||||
displayColor: ->
|
||||
if @shippingMethods.length > 0 && @selectedCount() > 0
|
||||
"blue"
|
||||
else
|
||||
"red"
|
||||
|
||||
selectedCount: ->
|
||||
@shippingMethods.reduce (count, shipping_method) ->
|
||||
count++ if shipping_method.selected
|
||||
count
|
||||
, 0
|
||||
@@ -0,0 +1,36 @@
|
||||
angular.module("admin.enterprises").factory 'PermalinkChecker', ($q, $http) ->
|
||||
new class PermalinkChecker
|
||||
deferredRequest: null
|
||||
deferredAbort: null
|
||||
|
||||
check: (permalink) =>
|
||||
@abort(@deferredAbort) if @deferredRequest && @deferredRequest.promise
|
||||
@deferredRequest = deferredRequest = $q.defer()
|
||||
@deferredAbort = deferredAbort = $q.defer()
|
||||
request = $http(
|
||||
method: "GET"
|
||||
url: "/enterprises/check_permalink?permalink=#{permalink}"
|
||||
headers:
|
||||
Accept: 'application/javascript'
|
||||
timeout: deferredAbort.promise
|
||||
)
|
||||
.success( (data) =>
|
||||
deferredRequest.resolve
|
||||
permalink: data
|
||||
available: "Available"
|
||||
).error (data,status) =>
|
||||
if status == 409
|
||||
deferredRequest.resolve
|
||||
permalink: data
|
||||
available: "Unavailable"
|
||||
else
|
||||
# Something went wrong or request was aborted
|
||||
deferredRequest.reject()
|
||||
|
||||
deferredRequest.promise.finally ->
|
||||
request = deferredRequest.promise = null;
|
||||
|
||||
deferredRequest.promise
|
||||
|
||||
abort: (deferredAbort) ->
|
||||
deferredAbort.resolve()
|
||||
@@ -1,10 +1,11 @@
|
||||
angular.module('admin.order_cycles', ['ngResource'])
|
||||
.controller('AdminCreateOrderCycleCtrl', ['$scope', 'OrderCycle', 'Enterprise', 'EnterpriseFee', ($scope, OrderCycle, Enterprise, EnterpriseFee) ->
|
||||
.controller('AdminCreateOrderCycleCtrl', ['$scope', 'OrderCycle', 'Enterprise', 'EnterpriseFee', 'ocInstance', ($scope, OrderCycle, Enterprise, EnterpriseFee, ocInstance) ->
|
||||
$scope.enterprises = Enterprise.index()
|
||||
$scope.supplied_products = Enterprise.supplied_products
|
||||
$scope.enterprise_fees = EnterpriseFee.index()
|
||||
|
||||
$scope.order_cycle = OrderCycle.order_cycle
|
||||
$scope.order_cycle.coordinator_id = ocInstance.coordinator_id
|
||||
|
||||
$scope.loaded = ->
|
||||
Enterprise.loaded && EnterpriseFee.loaded
|
||||
@@ -74,7 +75,8 @@ angular.module('admin.order_cycles', ['ngResource'])
|
||||
$scope.removeDistributionOfVariant = (variant_id) ->
|
||||
OrderCycle.removeDistributionOfVariant(variant_id)
|
||||
|
||||
$scope.submit = ->
|
||||
$scope.submit = (event) ->
|
||||
event.preventDefault()
|
||||
OrderCycle.create()
|
||||
])
|
||||
|
||||
@@ -154,7 +156,8 @@ angular.module('admin.order_cycles', ['ngResource'])
|
||||
$scope.removeDistributionOfVariant = (variant_id) ->
|
||||
OrderCycle.removeDistributionOfVariant(variant_id)
|
||||
|
||||
$scope.submit = ->
|
||||
$scope.submit = (event) ->
|
||||
event.preventDefault()
|
||||
OrderCycle.update()
|
||||
])
|
||||
|
||||
|
||||
@@ -38,6 +38,7 @@ angular.module('admin.order_cycles').controller "AdminSimpleCreateOrderCycleCtrl
|
||||
$scope.enterpriseFeesForEnterprise = (enterprise_id) ->
|
||||
EnterpriseFee.forEnterprise(parseInt(enterprise_id))
|
||||
|
||||
$scope.submit = ->
|
||||
$scope.submit = (event) ->
|
||||
event.preventDefault()
|
||||
OrderCycle.mirrorIncomingToOutgoingProducts()
|
||||
OrderCycle.create()
|
||||
|
||||
@@ -32,6 +32,7 @@ angular.module('admin.order_cycles').controller "AdminSimpleEditOrderCycleCtrl",
|
||||
$event.preventDefault()
|
||||
OrderCycle.removeCoordinatorFee(index)
|
||||
|
||||
$scope.submit = ->
|
||||
$scope.submit = (event) ->
|
||||
event.preventDefault()
|
||||
OrderCycle.mirrorIncomingToOutgoingProducts()
|
||||
OrderCycle.update()
|
||||
|
||||
@@ -87,20 +87,21 @@ angular.module('admin.order_cycles').factory('OrderCycle', ($resource, $window)
|
||||
load: (order_cycle_id, callback=null) ->
|
||||
service = this
|
||||
OrderCycle.get {order_cycle_id: order_cycle_id}, (oc) ->
|
||||
angular.extend(service.order_cycle, oc)
|
||||
service.order_cycle.incoming_exchanges = []
|
||||
service.order_cycle.outgoing_exchanges = []
|
||||
for exchange in service.order_cycle.exchanges
|
||||
if exchange.incoming
|
||||
angular.extend(exchange, {enterprise_id: exchange.sender_id, active: true})
|
||||
delete(exchange.receiver_id)
|
||||
service.order_cycle.incoming_exchanges.push(exchange)
|
||||
|
||||
else
|
||||
angular.extend(exchange, {enterprise_id: exchange.receiver_id, active: true})
|
||||
delete(exchange.sender_id)
|
||||
service.order_cycle.outgoing_exchanges.push(exchange)
|
||||
|
||||
delete oc.$promise
|
||||
delete oc.$resolved
|
||||
angular.extend(service.order_cycle, oc)
|
||||
service.order_cycle.incoming_exchanges = []
|
||||
service.order_cycle.outgoing_exchanges = []
|
||||
for exchange in service.order_cycle.exchanges
|
||||
if exchange.incoming
|
||||
angular.extend(exchange, {enterprise_id: exchange.sender_id, active: true})
|
||||
delete(exchange.receiver_id)
|
||||
service.order_cycle.incoming_exchanges.push(exchange)
|
||||
else
|
||||
angular.extend(exchange, {enterprise_id: exchange.receiver_id, active: true})
|
||||
delete(exchange.sender_id)
|
||||
service.order_cycle.outgoing_exchanges.push(exchange)
|
||||
|
||||
delete(service.order_cycle.exchanges)
|
||||
service.loaded = true
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ angular.module("admin.payment_methods")
|
||||
.factory "PaymentMethods", (paymentMethods) ->
|
||||
new class PaymentMethods
|
||||
paymentMethods: paymentMethods
|
||||
|
||||
|
||||
findByID: (id) ->
|
||||
for paymentMethod in @paymentMethods
|
||||
return paymentMethod if paymentMethod.id is id
|
||||
|
||||
@@ -4,6 +4,8 @@ angular.module("ofn.admin").factory 'EnterpriseRelationships', ($http, enterpris
|
||||
all_permissions: [
|
||||
'add_to_order_cycle'
|
||||
'manage_products'
|
||||
'edit_profile'
|
||||
'create_variant_overrides'
|
||||
]
|
||||
|
||||
constructor: ->
|
||||
@@ -26,3 +28,5 @@ angular.module("ofn.admin").factory 'EnterpriseRelationships', ($http, enterpris
|
||||
switch permission
|
||||
when "add_to_order_cycle" then "to add to order cycle"
|
||||
when "manage_products" then "to manage products"
|
||||
when "edit_profile" then "to edit profile"
|
||||
when "create_variant_overrides" then "to override variant details"
|
||||
|
||||
@@ -2,7 +2,7 @@ angular.module("admin.shipping_methods")
|
||||
.factory "ShippingMethods", (shippingMethods) ->
|
||||
new class ShippingMethods
|
||||
shippingMethods: shippingMethods
|
||||
|
||||
|
||||
findByID: (id) ->
|
||||
for shippingMethod in @shippingMethods
|
||||
return shippingMethod if shippingMethod.id is id
|
||||
|
||||
@@ -13,7 +13,7 @@ angular.module("admin.taxons").factory "Taxons", (taxons, $filter) ->
|
||||
|
||||
# For finding multiple Taxons represented by comma delimited string
|
||||
findByIDs: (ids) ->
|
||||
@taxonsByID[taxon_id] for taxon_id in ids.split(",")
|
||||
@taxonsByID[taxon_id] for taxon_id in ids.split(",") when @taxonsByID[taxon_id]
|
||||
|
||||
findByTerm: (term) ->
|
||||
$filter('filter')(@taxons, term)
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
angular.module("admin.users").directive "ofnUserAutocomplete", ($http) ->
|
||||
angular.module("admin.users").directive "userSelect", ->
|
||||
scope:
|
||||
user: '&userSelect'
|
||||
model: '=ngModel'
|
||||
link: (scope,element,attrs) ->
|
||||
setTimeout ->
|
||||
element.select2
|
||||
multiple: false
|
||||
initSelection: (element, callback) ->
|
||||
callback { id: element.val(), email: attrs.email }
|
||||
callback {id: scope.user().id, email: scope.user().email}
|
||||
ajax:
|
||||
url: Spree.routes.user_search
|
||||
url: '/admin/search/known_users'
|
||||
datatype: 'json'
|
||||
data:(term, page) ->
|
||||
{ q: term }
|
||||
@@ -15,4 +18,6 @@ angular.module("admin.users").directive "ofnUserAutocomplete", ($http) ->
|
||||
formatResult: (user) ->
|
||||
user.email
|
||||
formatSelection: (user) ->
|
||||
user.email
|
||||
scope.$apply ->
|
||||
scope.model = user if scope.model?
|
||||
user.email
|
||||
@@ -1,10 +0,0 @@
|
||||
angular.module("admin.utils").directive "navCheckCallback", (NavigationCheck)->
|
||||
restrict: 'A'
|
||||
scope:
|
||||
navCheckCallback: '&'
|
||||
link: (scope,element,attributes) ->
|
||||
# Provide a callback, otherwise this default will be used:
|
||||
callback = scope.navCheckCallback()
|
||||
callback ||= ->
|
||||
"You will lose any unsaved work!"
|
||||
NavigationCheck.register(callback)
|
||||
@@ -11,9 +11,9 @@ $ ->
|
||||
|
||||
# Temporarily handles the cart showing stuff
|
||||
$(document).ready ->
|
||||
$('#cart_adjustments').hide()
|
||||
$('.cart_adjustment').hide()
|
||||
|
||||
$('th.cart-adjustment-header a').click ->
|
||||
$('#cart_adjustments').toggle()
|
||||
$('td.cart-adjustments a').click ->
|
||||
$('.cart_adjustment').toggle()
|
||||
$(this).html('Item Handling Fees (included in item totals)')
|
||||
false
|
||||
|
||||
@@ -4,7 +4,7 @@ Darkswarm.controller "CheckoutCtrl", ($scope, storage, Checkout, CurrentUser, Cu
|
||||
|
||||
# Bind to local storage
|
||||
$scope.fieldsToBind = ["bill_address", "email", "payment_method_id", "shipping_method_id", "ship_address"]
|
||||
prefix = "order_#{Checkout.order.id}#{CurrentUser?.id}#{CurrentHub.hub.id}"
|
||||
prefix = "order_#{Checkout.order.id}#{CurrentUser.id or ""}#{CurrentHub.hub.id}"
|
||||
|
||||
for field in $scope.fieldsToBind
|
||||
storage.bind $scope, "Checkout.order.#{field}",
|
||||
@@ -16,7 +16,7 @@ Darkswarm.controller "CheckoutCtrl", ($scope, storage, Checkout, CurrentUser, Cu
|
||||
$scope.order = Checkout.order # Ordering is important
|
||||
$scope.secrets = Checkout.secrets
|
||||
|
||||
$scope.enabled = !!CurrentUser
|
||||
$scope.enabled = !!CurrentUser.id?
|
||||
|
||||
$scope.purchase = (event, form) ->
|
||||
event.preventDefault()
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
Darkswarm.controller "GroupEnterpriseNodeCtrl", ($scope, CurrentHub) ->
|
||||
|
||||
$scope.active = false
|
||||
|
||||
$scope.toggle = ->
|
||||
$scope.active = !$scope.active
|
||||
|
||||
$scope.open = ->
|
||||
$scope.active
|
||||
|
||||
$scope.current = ->
|
||||
$scope.hub.id is CurrentHub.hub.id
|
||||
@@ -0,0 +1,13 @@
|
||||
Darkswarm.controller "GroupEnterprisesCtrl", ($scope, Enterprises, Search, FilterSelectorsService) ->
|
||||
$scope.Enterprises = Enterprises
|
||||
$scope.totalActive = FilterSelectorsService.totalActive
|
||||
$scope.clearAll = FilterSelectorsService.clearAll
|
||||
$scope.filterText = FilterSelectorsService.filterText
|
||||
$scope.FilterSelectorsService = FilterSelectorsService
|
||||
$scope.query = Search.search()
|
||||
$scope.activeTaxons = []
|
||||
$scope.show_profiles = false
|
||||
$scope.filtersActive = false
|
||||
|
||||
$scope.$watch "query", (query)->
|
||||
Search.search query
|
||||
@@ -1,3 +1,3 @@
|
||||
Darkswarm.controller "MapCtrl", ($scope, MapConfiguration, OfnMap)->
|
||||
$scope.OfnMap = OfnMap
|
||||
$scope.map = MapConfiguration.options
|
||||
$scope.map = angular.copy MapConfiguration.options
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
Darkswarm.controller "TabsCtrl", ($scope, $rootScope, $location, OrderCycle) ->
|
||||
Darkswarm.controller "TabsCtrl", ($scope, $rootScope, $location) ->
|
||||
# Return active if supplied path matches url hash path.
|
||||
$scope.active = (path)->
|
||||
$location.hash() == path
|
||||
|
||||
# Toggle tab selected status by setting the url hash path.
|
||||
# Select tab by setting the url hash path.
|
||||
$scope.select = (path)->
|
||||
$location.hash path
|
||||
|
||||
# Toggle tab selected status by setting the url hash path.
|
||||
$scope.toggle = (path)->
|
||||
if $scope.active(path)
|
||||
$location.hash ""
|
||||
else
|
||||
|
||||
@@ -8,6 +8,6 @@ Darkswarm.directive "ofnEmptiesCart", (CurrentHub, Cart, Navigation, storage) ->
|
||||
if CurrentHub.hub?.id and CurrentHub.hub.id isnt scope.hub.id and !Cart.empty()
|
||||
elm.bind 'click', (ev)->
|
||||
ev.preventDefault()
|
||||
if confirm "Are you sure? This will change your selected Hub and remove any items in you shopping cart."
|
||||
if confirm "Are you sure? This will change your selected Hub and remove any items in your shopping cart."
|
||||
storage.clearAll() # One day this will have to be moar GRANULAR
|
||||
Navigation.go scope.hub.path
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
Darkswarm.directive "linkToService", ->
|
||||
restrict: 'E'
|
||||
replace: true
|
||||
scope: {
|
||||
ref: '='
|
||||
service: '='
|
||||
}
|
||||
template: '<a href="{{ref | ext_url: service}}" target="_blank" ng-show="ref"></a>'
|
||||
@@ -0,0 +1,7 @@
|
||||
Darkswarm.filter "ext_url", ->
|
||||
urlPattern = /^https?:\/\//
|
||||
(url, prefix) ->
|
||||
if !url || url.match(urlPattern)
|
||||
url
|
||||
else
|
||||
prefix + url
|
||||
@@ -1,9 +1,10 @@
|
||||
Darkswarm.filter 'shipping', ()->
|
||||
Darkswarm.filter 'shipping', ()->
|
||||
(objects, options)->
|
||||
objects ||= []
|
||||
options ?= null
|
||||
|
||||
if options.pickup and !options.delivery
|
||||
|
||||
if !options
|
||||
objects
|
||||
else if options.pickup and !options.delivery
|
||||
objects.filter (obj)->
|
||||
obj.pickup
|
||||
else if options.delivery and !options.pickup
|
||||
|
||||
@@ -8,6 +8,7 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http)->
|
||||
for line_item in @line_items
|
||||
line_item.variant.line_item = line_item
|
||||
Variants.register line_item.variant
|
||||
line_item.variant.extended_name = @extendedVariantName(line_item.variant)
|
||||
|
||||
orderChanged: =>
|
||||
@unsaved()
|
||||
@@ -43,6 +44,11 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http)->
|
||||
@line_items.filter (li)->
|
||||
li.quantity > 0
|
||||
|
||||
total_item_count: =>
|
||||
@line_items_present().reduce (sum,li) ->
|
||||
sum = sum + li.quantity
|
||||
, 0
|
||||
|
||||
empty: =>
|
||||
@line_items_present().length == 0
|
||||
|
||||
@@ -58,8 +64,17 @@ Darkswarm.factory 'Cart', (CurrentOrder, Variants, $timeout, $http)->
|
||||
@create_line_item(variant) unless exists
|
||||
|
||||
create_line_item: (variant)->
|
||||
variant.extended_name = @extendedVariantName(variant)
|
||||
variant.line_item =
|
||||
variant: variant
|
||||
quantity: null
|
||||
max_quantity: null
|
||||
@line_items.push variant.line_item
|
||||
|
||||
extendedVariantName: (variant) =>
|
||||
if variant.product_name == variant.name_to_display
|
||||
variant.product_name
|
||||
else
|
||||
name = "#{variant.product_name} - #{variant.name_to_display}"
|
||||
name += " (#{variant.options_text})" if variant.options_text
|
||||
name
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
Darkswarm.factory 'CurrentUser', (user)-> # This is for the current user
|
||||
if user and !$.isEmptyObject(user)
|
||||
new class CurrentUser
|
||||
constructor: ->
|
||||
@[k] = v for k, v of user
|
||||
else
|
||||
undefined
|
||||
new class CurrentUser
|
||||
constructor: ->
|
||||
@[k] = v for k, v of user if user and !$.isEmptyObject(user)
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
Darkswarm.factory 'HashNavigation', ($location) ->
|
||||
new class HashNavigation
|
||||
hash: null
|
||||
hash: null
|
||||
|
||||
constructor: ->
|
||||
# Make sure we have a path as hashes
|
||||
# dont seem to work so well without them
|
||||
$location.path("") if !$location.path()
|
||||
|
||||
active: (hash)->
|
||||
$location.hash() == hash
|
||||
$location.hash() == hash
|
||||
|
||||
navigate: (hash)->
|
||||
@hash = hash
|
||||
|
||||
@@ -12,22 +12,22 @@
|
||||
%li.cost
|
||||
.right {{ variant.price | localizeCurrency }}
|
||||
Item cost
|
||||
%li{"bo-if" => "variant.fees.admin"}
|
||||
%li.admin-fee{"bo-if" => "variant.fees.admin"}
|
||||
.right {{ variant.fees.admin | localizeCurrency }}
|
||||
Admin fee
|
||||
%li{"bo-if" => "variant.fees.sales"}
|
||||
%li.sales-fee{"bo-if" => "variant.fees.sales"}
|
||||
.right {{ variant.fees.sales | localizeCurrency }}
|
||||
Sales fee
|
||||
%li{"bo-if" => "variant.fees.packing"}
|
||||
%li.packing-fee{"bo-if" => "variant.fees.packing"}
|
||||
.right {{ variant.fees.packing | localizeCurrency }}
|
||||
Packing fee
|
||||
%li{"bo-if" => "variant.fees.transport"}
|
||||
%li.transport-fee{"bo-if" => "variant.fees.transport"}
|
||||
.right {{ variant.fees.transport | localizeCurrency }}
|
||||
Transport fee
|
||||
%li{"bo-if" => "variant.fees.fundraising"}
|
||||
%li.fundraising-fee{"bo-if" => "variant.fees.fundraising"}
|
||||
.right {{ variant.fees.fundraising | localizeCurrency }}
|
||||
Fundraising fee
|
||||
%li
|
||||
%li.total
|
||||
%strong
|
||||
.right = {{ variant.price_with_fees | localizeCurrency }}
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
%button.graph-button{"ng-class" => "{open: tt_isOpen}"}
|
||||
%i.ofn-i_058-graph
|
||||
/ %i.ofn-i_058-graph
|
||||
|
||||
@@ -40,6 +40,6 @@
|
||||
.message{ ng: { hide: "imageSrc() || imageUploader.isUploading" } }
|
||||
Your logo will appear here for review once uploaded
|
||||
.loading{ ng: { hide: "!imageUploader.isUploading" } }
|
||||
%img.spinner{ src: "/assets/loading.gif" }
|
||||
%img.spinner{ src: "/assets/spinning-circles.svg" }
|
||||
%br/
|
||||
Uploading...
|
||||
|
||||
@@ -38,6 +38,6 @@
|
||||
.message{ ng: { hide: "imageSrc() || imageUploader.isUploading" } }
|
||||
Your logo will appear here for review once uploaded
|
||||
.loading{ ng: { hide: "!imageUploader.isUploading" } }
|
||||
%img.spinner{ src: "/assets/loading.gif" }
|
||||
%img.spinner{ src: "/assets/spinning-circles.svg" }
|
||||
%br/
|
||||
Uploading...
|
||||
|
||||
@@ -58,5 +58,5 @@
|
||||
|
||||
.small-12.medium-2.large-2.columns.total-price.text-right
|
||||
.table-cell
|
||||
%strong
|
||||
%strong{"ng-class" => "{filled: variant.totalPrice()}"}
|
||||
{{ variant.totalPrice() | localizeCurrency }}
|
||||
|
||||
14
app/assets/stylesheets/admin/enterprise_console.css.scss
Normal file
14
app/assets/stylesheets/admin/enterprise_console.css.scss
Normal file
@@ -0,0 +1,14 @@
|
||||
span.unavailable, span.available {
|
||||
font-weight: bold;
|
||||
i {
|
||||
font-size: 150%;
|
||||
}
|
||||
}
|
||||
|
||||
span.available {
|
||||
color: #9fc820;
|
||||
}
|
||||
|
||||
span.unavailable {
|
||||
color: #DA5354;
|
||||
}
|
||||
@@ -7,9 +7,9 @@
|
||||
font-size: 120%
|
||||
cursor: pointer
|
||||
text-transform: uppercase
|
||||
&.odd
|
||||
&:nth-child(odd)
|
||||
background-color: #ebf3fb
|
||||
&.even
|
||||
&:nth-child(even)
|
||||
background-color: #ffffff
|
||||
&:hover
|
||||
background-color: #eaf0f5
|
||||
|
||||
3
app/assets/stylesheets/admin/variant_overrides.css.sass
Normal file
3
app/assets/stylesheets/admin/variant_overrides.css.sass
Normal file
@@ -0,0 +1,3 @@
|
||||
.variant-override-unit
|
||||
float: right
|
||||
font-style: italic
|
||||
@@ -75,46 +75,38 @@ ordercycle
|
||||
|
||||
|
||||
button.graph-button
|
||||
z-index: 9999999
|
||||
// z-index: 9999999
|
||||
border: 1px solid transparent
|
||||
@include box-shadow(none)
|
||||
padding: 0
|
||||
margin: 0
|
||||
@include border-radius(999rem)
|
||||
display: inline
|
||||
background-color: rgba(255,255,255,0.5)
|
||||
padding: 5px
|
||||
@media all and (max-width: 768px)
|
||||
display: none
|
||||
// Hide for small
|
||||
|
||||
&:hover, &:active, &:focus
|
||||
background-color: rgba(255,255,255,1)
|
||||
i.ofn-i_058-graph
|
||||
color: $clr-brick-bright
|
||||
|
||||
i.ofn-i_058-graph
|
||||
padding: 4px
|
||||
@include box-shadow(none)
|
||||
@include border-radius(999rem)
|
||||
&:before
|
||||
@include icon-font
|
||||
content: '\e639'
|
||||
color: #999
|
||||
margin: 0
|
||||
padding: 0
|
||||
font-size: 1rem
|
||||
|
||||
@media all and (max-width: 640px)
|
||||
padding: 3px
|
||||
i.ofn-i_058-graph
|
||||
font-size: 0.75rem
|
||||
&:focus
|
||||
border: 1px solid #e0e0e0
|
||||
background-color: rgba(255,255,255,1)
|
||||
&:before
|
||||
color: #666
|
||||
&:hover, &:active
|
||||
background-color: rgba(255,255,255,1)
|
||||
border: 1px solid transparent
|
||||
&:before
|
||||
color: $clr-brick-bright
|
||||
@media all and (max-width: 768px)
|
||||
// Hide for small
|
||||
display: none
|
||||
|
||||
button.graph-button.open
|
||||
@include box-shadow(inset 0 1px 1px 0 rgba(0,0,0,0.35))
|
||||
border: 1px solid #999
|
||||
|
||||
&:hover, &:active, &:focus
|
||||
background-color: rgba(255,255,255,1)
|
||||
i.ofn-i_058-graph
|
||||
color: $clr-brick-bright
|
||||
|
||||
i.ofn-i_058-graph
|
||||
color: $clr-brick
|
||||
|
||||
border: 1px solid transparent
|
||||
background-color: $clr-brick-bright
|
||||
&:before
|
||||
content: '\e608'
|
||||
color: white
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@import branding.css.sass
|
||||
@import animations.sass
|
||||
|
||||
.darkswarm
|
||||
products
|
||||
@@ -71,9 +72,14 @@
|
||||
// Total price
|
||||
.total-price
|
||||
padding-left: 0rem
|
||||
color: $disabled-med
|
||||
.filled
|
||||
color: $med-drk-grey
|
||||
@media all and (max-width: 640px)
|
||||
background: #777
|
||||
color: white
|
||||
color: $disabled-med
|
||||
.filled
|
||||
color: white
|
||||
.table-cell
|
||||
height: 27px
|
||||
|
||||
@@ -97,17 +103,19 @@
|
||||
@media all and (max-width: 768px)
|
||||
padding-left: 4.9375rem
|
||||
@media all and (max-width: 640px)
|
||||
padding-left: 4.5rem
|
||||
@media all and (max-width:480px)
|
||||
padding-left: 0.9375rem
|
||||
small
|
||||
font-size: 80%
|
||||
h3
|
||||
font-size: 1.5rem
|
||||
margin: 0
|
||||
h3 a
|
||||
color: #222
|
||||
i
|
||||
@include csstrans
|
||||
font-size: 0.6em
|
||||
&:hover, &:focus, &:active
|
||||
color: black
|
||||
|
||||
|
||||
|
||||
color: $clr-brick
|
||||
i
|
||||
font-size: 0.8em
|
||||
|
||||
|
||||
@@ -1,26 +1,59 @@
|
||||
@import branding
|
||||
@import animations.sass
|
||||
|
||||
.darkswarm
|
||||
products
|
||||
product
|
||||
.product-thumb
|
||||
@include csstrans
|
||||
position: absolute
|
||||
top: 3px
|
||||
top: 2px
|
||||
left: 0px
|
||||
width: 7rem
|
||||
height: 7rem
|
||||
outline: 1px solid $disabled-bright
|
||||
float: left
|
||||
display: block
|
||||
z-index: 999999
|
||||
background-color: white
|
||||
overflow: hidden
|
||||
|
||||
i
|
||||
@include csstrans
|
||||
transition-delay: 150ms
|
||||
position: absolute
|
||||
left: 45%
|
||||
top: 45%
|
||||
z-index: 99999
|
||||
color: white
|
||||
font-size: 1rem
|
||||
opacity: 0
|
||||
img
|
||||
@include csstrans
|
||||
opacity: 1
|
||||
@include transform-scale(scale(1))
|
||||
|
||||
&:hover, &:focus, &:active
|
||||
background-color: $clr-brick
|
||||
i
|
||||
left: 32%
|
||||
top: 30%
|
||||
font-size: 3rem
|
||||
opacity: 1
|
||||
img
|
||||
opacity: 0.5
|
||||
@include transform-scale(scale(1.1))
|
||||
|
||||
@media all and (max-width: 768px)
|
||||
top: 2px
|
||||
width: 4rem
|
||||
height: 4rem
|
||||
|
||||
@media all and (max-width: 480px)
|
||||
&:hover, &:focus, &:active
|
||||
i
|
||||
left: 30%
|
||||
top: 30%
|
||||
font-size: 2rem
|
||||
@media all and (max-width: 640px)
|
||||
display: none
|
||||
width: 0rem
|
||||
height: 0rem
|
||||
height: 0rem
|
||||
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
margin-top: -1.1rem
|
||||
padding-top: 0.25rem
|
||||
z-index: 999999
|
||||
|
||||
@media all and (max-width: 768px)
|
||||
margin-top: -0.85rem
|
||||
@media all and (max-width: 480px)
|
||||
background-size: 28px 32px
|
||||
min-height: 32px
|
||||
width: 28px
|
||||
|
||||
render-svg
|
||||
svg
|
||||
@@ -19,3 +20,12 @@
|
||||
height: 24px
|
||||
path
|
||||
fill: #999
|
||||
|
||||
@media all and (max-width: 768px)
|
||||
margin-top: -0.85rem
|
||||
|
||||
@media all and (max-width: 480px)
|
||||
render-svg
|
||||
svg
|
||||
width: 18px
|
||||
height: 18px
|
||||
|
||||
@@ -66,10 +66,8 @@ products .filter-box
|
||||
table-layout: fixed
|
||||
text-transform: capitalize
|
||||
overflow: visible
|
||||
// width: 100%
|
||||
// height: 2rem
|
||||
line-height: 1
|
||||
color: #444
|
||||
color: $med-drk-grey
|
||||
font-size: 0.875rem
|
||||
span
|
||||
display: table-cell
|
||||
|
||||
@@ -51,6 +51,21 @@
|
||||
100%
|
||||
opacity: 1
|
||||
|
||||
@-webkit-keyframes spin
|
||||
0%
|
||||
-webkit-transform: rotate(0deg)
|
||||
transform: rotate(0deg)
|
||||
100%
|
||||
-webkit-transform: rotate(359deg)
|
||||
transform: rotate(359deg)
|
||||
@keyframes spin
|
||||
0%
|
||||
-webkit-transform: rotate(0deg)
|
||||
transform: rotate(0deg)
|
||||
100%
|
||||
-webkit-transform: rotate(359deg)
|
||||
transform: rotate(359deg)
|
||||
|
||||
// ANIMATION CLASSES
|
||||
|
||||
.fade
|
||||
|
||||
@@ -21,5 +21,7 @@ $disabled-med: #b3b3b3
|
||||
$disabled-dark: #999
|
||||
$disabled-v-dark: #808080
|
||||
$med-grey: #666
|
||||
$med-drk-grey: #444
|
||||
$dark-grey: #333
|
||||
$light-grey: #ddd
|
||||
$black: #000
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
@import branding
|
||||
@import animations
|
||||
|
||||
.order-summary
|
||||
background-color: #e1f0f5
|
||||
padding: 1em
|
||||
width: 100%
|
||||
|
||||
checkout
|
||||
display: block
|
||||
|
||||
@@ -55,7 +60,6 @@ checkout
|
||||
text-align: left
|
||||
|
||||
// Logic to swap out up / down accordion icons
|
||||
|
||||
//Foundation overrides
|
||||
dd > a
|
||||
@include csstrans
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@import branding
|
||||
@import mixins
|
||||
|
||||
// Search page
|
||||
#groups
|
||||
background-color: $clr-brick-light
|
||||
background-image: url("/assets/groups.svg")
|
||||
@@ -8,35 +9,97 @@
|
||||
background-repeat: no-repeat
|
||||
padding-bottom: 20px
|
||||
|
||||
a > .group-name
|
||||
&:hover, &:focus, &:active
|
||||
text-decoration: underline
|
||||
|
||||
.groups-icons
|
||||
text-align: right
|
||||
a
|
||||
font-size: 1.5em
|
||||
|
||||
.groups-header
|
||||
border: 2px solid $clr-brick-light-bright
|
||||
@include border-radius-mixed(0.5em, 0.5em, 0, 0)
|
||||
margin: -1rem 0 1rem
|
||||
padding: 1rem 0.9375rem
|
||||
@media screen and (min-width: 640px)
|
||||
border: 0 none
|
||||
@include border-radius(0)
|
||||
margin: 0
|
||||
padding: 0
|
||||
|
||||
.group
|
||||
padding-bottom: 40px
|
||||
hr
|
||||
border-bottom: 10px solid white
|
||||
outline: 0
|
||||
border-top: 0
|
||||
margin: 0
|
||||
padding-bottom: 0.5em
|
||||
.row div
|
||||
font-size: 110%
|
||||
.row a
|
||||
vertical-align: middle
|
||||
.ofn-i_035-groups
|
||||
font-size: 120%
|
||||
vertical-align: middle
|
||||
|
||||
// Individual Page
|
||||
#group-page
|
||||
.group-logo, .group-header
|
||||
text-align: center
|
||||
.group-logo
|
||||
padding-bottom: 1em
|
||||
max-height: 200px
|
||||
.group-name
|
||||
border-bottom: 1px solid #ccc
|
||||
@media screen and (min-width: 768px)
|
||||
.group-logo, .group-header
|
||||
text-align: left
|
||||
.group-logo
|
||||
max-height: 120px
|
||||
float: left
|
||||
padding-right: 1em
|
||||
background-color: white
|
||||
|
||||
.group-hero
|
||||
position: relative
|
||||
padding: 0
|
||||
border: 10px solid white
|
||||
background: white
|
||||
// Tabs
|
||||
.tabs dd a // Mobile first
|
||||
padding: 0.25rem 0.45rem 0rem
|
||||
font-size: 0.75rem
|
||||
border: none
|
||||
margin-bottom: -2px
|
||||
margin-right: 2px
|
||||
text-transform: capitalize
|
||||
@include avenir
|
||||
@include border-radius(1em 0.25em 0 0)
|
||||
@include gradient($disabled-light, $disabled-bright)
|
||||
@media screen and (min-width: 768px)
|
||||
.tabs dd a
|
||||
padding: 0.5rem 1rem 0.25em
|
||||
font-size: 0.875rem
|
||||
@include border-radius(1.5em 0.25em 0 0)
|
||||
@media screen and (min-width: 1024px)
|
||||
.tabs dd a
|
||||
padding: 0.75rem 1.5rem 0.5em
|
||||
font-size: 1rem
|
||||
@include border-radius(2em 0.25em 0 0)
|
||||
.tabs dd.active a
|
||||
@include gradient(white, white)
|
||||
margin-bottom: -1px
|
||||
border-top: 1px solid $light-grey
|
||||
border-left: 1px solid $light-grey
|
||||
border-right: 1px solid $light-grey
|
||||
border-bottom: 0
|
||||
.tabs-content
|
||||
border-top: 1px solid $light-grey
|
||||
border-left: 1px solid $light-grey
|
||||
border-right: 1px solid $light-grey
|
||||
border-bottom: 1px solid $light-grey
|
||||
padding: 1.5em
|
||||
|
||||
h3.group-name
|
||||
margin-top: 0.5em
|
||||
margin-bottom: 0.15em
|
||||
|
||||
img.group-logo
|
||||
max-width: 220px
|
||||
max-height: 86px
|
||||
float: right
|
||||
padding-top: 10px
|
||||
|
||||
|
||||
img.group-hero-img
|
||||
background-color: black
|
||||
width: 100%
|
||||
height: inherit
|
||||
max-height: 260px
|
||||
min-height: 120px
|
||||
overflow: hidden
|
||||
// Producers tab
|
||||
.producers
|
||||
background-image: none
|
||||
.active_table .active_table_node a.is_distributor, .active_table .active_table_node a.is_distributor i.ofn-i_059-producer
|
||||
color: $clr-turquoise
|
||||
// Hubs tab
|
||||
.hubs
|
||||
background-image: none
|
||||
padding-top: 0
|
||||
padding-bottom: 0
|
||||
|
||||
@@ -3,12 +3,10 @@
|
||||
@import branding
|
||||
|
||||
.product-img
|
||||
border-bottom: 40px white solid
|
||||
border-top: 20px white solid
|
||||
border-left: 20px white solid
|
||||
border-right: 20px white solid
|
||||
padding: 5px
|
||||
margin-bottom: 10px
|
||||
outline: 1px solid #ccc
|
||||
@include box-shadow(0 1px 2px 1px rgba(0,0,0,0.25))
|
||||
@include box-shadow(0 1px 2px 1px rgba(0,0,0,0.15))
|
||||
|
||||
.hero-img
|
||||
outline: 1px solid $disabled-bright
|
||||
|
||||
@@ -8,9 +8,10 @@
|
||||
|
||||
nav
|
||||
@include textpress
|
||||
|
||||
.joyride-tip-guide .button
|
||||
text-shadow: none
|
||||
|
||||
// Default overrides - big menu
|
||||
|
||||
.top-bar-section ul li.ofn-logo > a
|
||||
display: table-cell
|
||||
vertical-align: middle
|
||||
|
||||
@@ -120,5 +120,21 @@
|
||||
background-repeat: no-repeat
|
||||
background-size: 100% auto
|
||||
|
||||
|
||||
@mixin gradient($gradient-clr1, $gradient-clr2)
|
||||
background: $gradient-clr1
|
||||
// Old browsers
|
||||
background: -moz-linear-gradient(top, $gradient-clr1 0%, $gradient-clr2 100%)
|
||||
// FF3.6+
|
||||
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, $gradient-clr1), color-stop(100%, $gradient-clr2))
|
||||
// Chrome,Safari4+
|
||||
background: -webkit-linear-gradient(top, $gradient-clr1 0%, $gradient-clr2 100%)
|
||||
// Chrome10+,Safari5.1+
|
||||
background: -o-linear-gradient(top, $gradient-clr1 0%, $gradient-clr2 100%)
|
||||
// Opera 11.10+
|
||||
background: -ms-linear-gradient(top, $gradient-clr1 0%, $gradient-clr2 100%)
|
||||
// IE10+
|
||||
background: linear-gradient(to bottom, $gradient-clr1 0%, $gradient-clr2 100%)
|
||||
// W3C
|
||||
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='$gradient-clr1', endColorstr='$gradient-clr2',GradientType=0 )
|
||||
// IE6-8
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
font-size: 1rem
|
||||
font-weight: 400
|
||||
color: $disabled-dark
|
||||
border-bottom: 1px solid $disabled-dark
|
||||
border-bottom: 1px solid $light-grey
|
||||
margin-top: 0.75rem
|
||||
margin-bottom: 0.5rem
|
||||
|
||||
@@ -67,8 +67,8 @@
|
||||
margin-bottom: 0.5rem
|
||||
overflow-y: scroll
|
||||
overflow-x: hidden
|
||||
border-bottom: 1px solid #999
|
||||
@include box-shadow(0 2px 2px -2px #999)
|
||||
border-bottom: 1px solid $light-grey
|
||||
@include box-shadow(0 2px 2px -2px $light-grey)
|
||||
|
||||
.enterprise-logo, img
|
||||
float: left
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
@import mixins
|
||||
@import animations
|
||||
@import variables
|
||||
@import branding
|
||||
@import big-input
|
||||
@@ -25,6 +26,21 @@
|
||||
.add_to_cart
|
||||
margin-top: 2rem
|
||||
|
||||
form
|
||||
input.small.button.primary.right.add_to_cart
|
||||
&.dirty
|
||||
padding-left: 3.2rem
|
||||
i.cart-spinner
|
||||
position: absolute
|
||||
top: 14px
|
||||
right: 146px
|
||||
color: white
|
||||
font-size: 1.2em
|
||||
// Necessary to be below Z index of cart popover:
|
||||
z-index: 98
|
||||
-webkit-animation: spin 2s infinite linear
|
||||
animation: spin 2s infinite linear
|
||||
|
||||
product
|
||||
@include csstrans
|
||||
border-bottom: 1px solid #e5e5e5
|
||||
@@ -33,7 +49,7 @@
|
||||
margin-bottom: 20px !important
|
||||
position: relative
|
||||
display: block
|
||||
color: #444
|
||||
color: $med-drk-grey
|
||||
|
||||
&:hover, &:focus, &:active
|
||||
border-bottom: 1px solid $clr-brick-med-bright
|
||||
@@ -62,12 +78,14 @@
|
||||
@media all and (max-width: 640px)
|
||||
padding-right: 0.25rem
|
||||
|
||||
i.ofn-i_056-bulk, i.ofn-i_036-producers
|
||||
i.ofn-i_056-bulk
|
||||
font-size: 1rem
|
||||
padding-right: 0rem
|
||||
|
||||
i.ofn-i_036-producers
|
||||
padding-left: 0.5rem
|
||||
padding-left: 0.2rem
|
||||
padding-right: 0rem
|
||||
font-size: 0.8rem
|
||||
|
||||
.shopfront_message, .shopfront_closed_message
|
||||
padding: 15px
|
||||
|
||||
@@ -36,10 +36,22 @@
|
||||
li.product-cart
|
||||
border-top: 1px solid #424242
|
||||
|
||||
// Shopping cart
|
||||
#cart-detail
|
||||
.cart-item-delete
|
||||
a.delete
|
||||
font-size: 1.125em
|
||||
|
||||
.item-thumb-image
|
||||
display: none
|
||||
@media screen and (min-width: 640px)
|
||||
display: inline-block
|
||||
float: left
|
||||
padding-right: 0.5em
|
||||
width: 36px
|
||||
height: 36px
|
||||
|
||||
|
||||
|
||||
#edit-cart
|
||||
button, .button
|
||||
|
||||
@@ -16,27 +16,45 @@
|
||||
@font-face
|
||||
font-family: 'AvenirMed'
|
||||
src: url("/AvenirLTStd-Medium.otf") format("opentype")
|
||||
|
||||
body
|
||||
font-family: 'Open Sans', Calibri, Candara, Segoe, "Segoe UI", Optima, Arial, sans-serif
|
||||
|
||||
$font-helvetica: "Helvetica Neue", "HelveticaNeue", "Helvetica", Helvetica, Arial, sans-serif
|
||||
|
||||
a
|
||||
color: $clr-brick
|
||||
&:hover
|
||||
&:hover, &:focus, &:active
|
||||
text-decoration: none
|
||||
color: $clr-brick-bright
|
||||
|
||||
.text-big
|
||||
font-size: 1.5rem
|
||||
font-weight: 300
|
||||
|
||||
small, .small
|
||||
font-size: 0.75rem
|
||||
|
||||
.text-small
|
||||
font-size: 0.875rem
|
||||
margin-bottom: 0.5rem
|
||||
font-family: $font-helvetica
|
||||
&, & *
|
||||
font-size: 0.875rem
|
||||
|
||||
.text-normal
|
||||
font-weight: 400
|
||||
font-family: $font-helvetica
|
||||
|
||||
.text-skinny
|
||||
font-weight: 300
|
||||
font-family: $font-helvetica
|
||||
|
||||
.word-wrap
|
||||
word-wrap: break-word
|
||||
|
||||
.pre-wrap
|
||||
white-space: pre-wrap
|
||||
|
||||
.pre-line
|
||||
white-space: pre-line
|
||||
|
||||
.light
|
||||
color: #999
|
||||
@@ -81,6 +99,9 @@ ul.check-list
|
||||
.light-grey
|
||||
color: #666666
|
||||
|
||||
.pad
|
||||
padding: 1em
|
||||
|
||||
.pad-top
|
||||
padding-top: 1em
|
||||
|
||||
|
||||
@@ -56,6 +56,23 @@ table.social
|
||||
table.order-summary
|
||||
border-collapse: separate
|
||||
border-spacing: 0px 10px
|
||||
tbody tr td
|
||||
padding-left: 5px
|
||||
padding-right: 5px
|
||||
thead tr th
|
||||
background-color: #f2f2f2
|
||||
border-bottom: 1px solid black
|
||||
padding-left: 5px
|
||||
padding-right: 5px
|
||||
h4
|
||||
margin-top: 15px
|
||||
tfoot
|
||||
tr:first-child td
|
||||
border-top: 1px solid black
|
||||
padding-top: 5px
|
||||
tr td
|
||||
padding-left: 5px
|
||||
padding-right: 5px
|
||||
|
||||
.social .soc-btn
|
||||
padding: 3px 7px
|
||||
@@ -245,6 +262,10 @@ ul
|
||||
tr td
|
||||
padding: 15px
|
||||
|
||||
.pad
|
||||
tr td
|
||||
padding: 15px
|
||||
|
||||
.column-wrap
|
||||
padding: 0!important
|
||||
margin: 0 auto
|
||||
|
||||
@@ -59,6 +59,7 @@ module Admin
|
||||
|
||||
def load_data
|
||||
@calculators = EnterpriseFee.calculators.sort_by(&:name)
|
||||
@tax_categories = Spree::TaxCategory.order('is_default DESC, name ASC')
|
||||
end
|
||||
|
||||
def collection
|
||||
|
||||
@@ -1,22 +1,50 @@
|
||||
module Admin
|
||||
class EnterpriseGroupsController < ResourceController
|
||||
before_filter :load_data, except: :index
|
||||
before_filter :load_object_data, only: [:new, :edit, :create, :update]
|
||||
|
||||
def index
|
||||
@enterprise_groups = @enterprise_groups.managed_by(spree_current_user)
|
||||
end
|
||||
|
||||
def move_up
|
||||
@enterprise_group = EnterpriseGroup.find params[:enterprise_group_id]
|
||||
@enterprise_group.move_higher
|
||||
EnterpriseGroup.with_isolation_level_serializable do
|
||||
@enterprise_group = EnterpriseGroup.find params[:enterprise_group_id]
|
||||
@enterprise_group.move_higher
|
||||
end
|
||||
redirect_to main_app.admin_enterprise_groups_path
|
||||
end
|
||||
|
||||
def move_down
|
||||
@enterprise_group = EnterpriseGroup.find params[:enterprise_group_id]
|
||||
@enterprise_group.move_lower
|
||||
EnterpriseGroup.with_isolation_level_serializable do
|
||||
@enterprise_group = EnterpriseGroup.find params[:enterprise_group_id]
|
||||
@enterprise_group.move_lower
|
||||
end
|
||||
redirect_to main_app.admin_enterprise_groups_path
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def build_resource_with_address
|
||||
enterprise_group = build_resource_without_address
|
||||
enterprise_group.address = Spree::Address.new
|
||||
enterprise_group.address.country = Spree::Country.find_by_id(Spree::Config[:default_country_id])
|
||||
enterprise_group
|
||||
end
|
||||
alias_method_chain :build_resource, :address
|
||||
|
||||
private
|
||||
|
||||
def load_data
|
||||
@countries = Spree::Country.order(:name)
|
||||
@enterprises = Enterprise.activated
|
||||
end
|
||||
|
||||
def load_object_data
|
||||
@owner_email = @enterprise_group.andand.owner.andand.email || ""
|
||||
end
|
||||
|
||||
|
||||
def collection
|
||||
EnterpriseGroup.by_position
|
||||
end
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
module Admin
|
||||
class EnterprisesController < ResourceController
|
||||
before_filter :load_enterprise_set, :only => :index
|
||||
before_filter :load_countries, :except => :index
|
||||
before_filter :load_countries, :except => [:index, :set_sells, :check_permalink]
|
||||
before_filter :load_methods_and_fees, :only => [:new, :edit, :update, :create]
|
||||
before_filter :load_taxons, :only => [:new, :edit, :update, :create]
|
||||
before_filter :check_can_change_sells, only: :update
|
||||
before_filter :check_can_change_bulk_sells, only: :bulk_update
|
||||
before_filter :override_owner, only: :create
|
||||
before_filter :override_sells, only: :create
|
||||
before_filter :check_can_change_owner, only: :update
|
||||
before_filter :check_can_change_bulk_owner, only: :bulk_update
|
||||
before_filter :check_can_change_managers, only: :update
|
||||
|
||||
|
||||
helper 'spree/products'
|
||||
include ActionView::Helpers::TextHelper
|
||||
include OrderCyclesHelper
|
||||
|
||||
def for_order_cycle
|
||||
@@ -18,7 +22,7 @@ module Admin
|
||||
end
|
||||
|
||||
def set_sells
|
||||
enterprise = Enterprise.find(params[:id])
|
||||
enterprise = Enterprise.find_by_permalink(params[:id]) || Enterprise.find(params[:id])
|
||||
attributes = { sells: params[:sells] }
|
||||
attributes[:producer_profile_only] = params[:sells] == "none" && !!params[:producer_profile_only]
|
||||
attributes[:shop_trial_start_date] = Time.now if params[:sells] == "own"
|
||||
@@ -44,16 +48,25 @@ module Admin
|
||||
|
||||
def bulk_update
|
||||
@enterprise_set = EnterpriseSet.new(collection, params[:enterprise_set])
|
||||
touched_enterprises = @enterprise_set.collection.select(&:changed?)
|
||||
if @enterprise_set.save
|
||||
flash[:success] = 'Enterprises updated successfully'
|
||||
flash[:success] = "Enterprises updated successfully"
|
||||
|
||||
# 18-3-2015: It seems that the form for this action sometimes loads bogus values for
|
||||
# the 'sells' field, and submitting that form results in a bunch of enterprises with
|
||||
# values that have mysteriously changed. This statement is here to help debug that
|
||||
# issue, and should be removed (along with its display in index.html.haml) when the
|
||||
# issue has been resolved.
|
||||
flash[:action] = "Updated #{pluralize(touched_enterprises.count, 'enterprise')}: #{touched_enterprises.map(&:name).join(', ')}"
|
||||
|
||||
redirect_to main_app.admin_enterprises_path
|
||||
else
|
||||
@enterprise_set.collection.select! { |e| touched_enterprises.include? e }
|
||||
flash[:error] = 'Update failed'
|
||||
render :index
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
protected
|
||||
|
||||
def build_resource_with_address
|
||||
@@ -64,6 +77,11 @@ module Admin
|
||||
end
|
||||
alias_method_chain :build_resource, :address
|
||||
|
||||
# Overriding method on Spree's resource controller,
|
||||
# so that resources are found using permalink
|
||||
def find_resource
|
||||
Enterprise.find_by_permalink(params[:id])
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -76,8 +94,10 @@ module Admin
|
||||
end
|
||||
|
||||
def collection
|
||||
# TODO was ordered with is_distributor DESC as well, not sure why or how we want ot sort this now
|
||||
Enterprise.managed_by(spree_current_user).order('is_primary_producer ASC, name')
|
||||
# TODO was ordered with is_distributor DESC as well, not sure why or how we want to sort this now
|
||||
OpenFoodNetwork::Permissions.new(spree_current_user).
|
||||
editable_enterprises.
|
||||
order('is_primary_producer ASC, name')
|
||||
end
|
||||
|
||||
def collection_actions
|
||||
@@ -110,6 +130,13 @@ module Admin
|
||||
params[:enterprise][:owner_id] = spree_current_user.id unless spree_current_user.admin?
|
||||
end
|
||||
|
||||
def override_sells
|
||||
unless spree_current_user.admin?
|
||||
has_hub = spree_current_user.enterprises.is_hub.any?
|
||||
params[:enterprise][:sells] = has_hub ? 'any' : 'none'
|
||||
end
|
||||
end
|
||||
|
||||
def check_can_change_owner
|
||||
unless ( spree_current_user == @enterprise.owner ) || spree_current_user.admin?
|
||||
params[:enterprise].delete :owner_id
|
||||
@@ -124,6 +151,12 @@ module Admin
|
||||
end
|
||||
end
|
||||
|
||||
def check_can_change_managers
|
||||
unless ( spree_current_user == @enterprise.owner ) || spree_current_user.admin?
|
||||
params[:enterprise].delete :user_ids
|
||||
end
|
||||
end
|
||||
|
||||
# Overriding method on Spree's resource controller
|
||||
def location_after_save
|
||||
if params[:enterprise].key? :producer_properties_attributes
|
||||
|
||||
@@ -6,6 +6,7 @@ module Admin
|
||||
include OrderCyclesHelper
|
||||
|
||||
before_filter :load_order_cycle_set, :only => :index
|
||||
before_filter :require_coordinator, only: :new
|
||||
|
||||
def show
|
||||
respond_to do |format|
|
||||
@@ -85,5 +86,23 @@ module Admin
|
||||
def load_order_cycle_set
|
||||
@order_cycle_set = OrderCycleSet.new :collection => collection
|
||||
end
|
||||
|
||||
def require_coordinator
|
||||
if params[:coordinator_id] && @order_cycle.coordinator = order_cycle_coordinating_enterprises.find_by_id(params[:coordinator_id])
|
||||
return
|
||||
end
|
||||
|
||||
available_coordinators = order_cycle_coordinating_enterprises.select(&:confirmed?)
|
||||
case available_coordinators.count
|
||||
when 0
|
||||
flash[:error] = "None of your enterprises have permission to coordinate an order cycle"
|
||||
redirect_to main_app.admin_order_cycles_path
|
||||
when 1
|
||||
@order_cycle.coordinator = available_coordinators.first
|
||||
else
|
||||
flash[:error] = "You don't have permission to create an order cycle coordinated by that enterprise" if params[:coordinator_id]
|
||||
render :set_coordinator
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,7 +12,7 @@ module Admin
|
||||
end
|
||||
|
||||
def load_enterprise
|
||||
@enterprise = Enterprise.find params[:enterprise_id]
|
||||
@enterprise = Enterprise.find_by_permalink params[:enterprise_id]
|
||||
end
|
||||
|
||||
def load_properties
|
||||
|
||||
@@ -2,22 +2,19 @@ require 'open_food_network/spree_api_key_loader'
|
||||
|
||||
module Admin
|
||||
class VariantOverridesController < ResourceController
|
||||
include OpenFoodNetwork::SpreeApiKeyLoader
|
||||
include OrderCyclesHelper
|
||||
include OpenFoodNetwork::SpreeApiKeyLoader
|
||||
|
||||
before_filter :load_spree_api_key, only: :index
|
||||
before_filter :load_data
|
||||
|
||||
def index
|
||||
@hubs = order_cycle_hub_enterprises(without_validation: true)
|
||||
@producers = order_cycle_producer_enterprises
|
||||
@hub_permissions = OpenFoodNetwork::Permissions.new(spree_current_user).
|
||||
order_cycle_enterprises_per_hub
|
||||
@variant_overrides = VariantOverride.for_hubs(@hubs)
|
||||
end
|
||||
|
||||
|
||||
def bulk_update
|
||||
collection_hash = Hash[params[:variant_overrides].each_with_index.map { |vo, i| [i, vo] }]
|
||||
vo_set = VariantOverrideSet.new collection_attributes: collection_hash
|
||||
vo_set = VariantOverrideSet.new @variant_overrides, collection_attributes: collection_hash
|
||||
|
||||
# Ensure we're authorised to update all variant overrides
|
||||
vo_set.collection.each { |vo| authorize! :update, vo }
|
||||
@@ -35,6 +32,20 @@ module Admin
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def load_data
|
||||
@hubs = order_cycle_hub_enterprises
|
||||
|
||||
# Used in JS to look up the name of the producer of each product
|
||||
@producers = OpenFoodNetwork::Permissions.new(spree_current_user).
|
||||
variant_override_producers
|
||||
|
||||
@hub_permissions = OpenFoodNetwork::Permissions.new(spree_current_user).
|
||||
variant_override_enterprises_per_hub
|
||||
@variant_overrides = VariantOverride.for_hubs(@hubs)
|
||||
end
|
||||
|
||||
def collection
|
||||
end
|
||||
end
|
||||
|
||||
@@ -29,7 +29,7 @@ module Api
|
||||
end
|
||||
|
||||
def update
|
||||
@enterprise = Enterprise.find(params[:id])
|
||||
@enterprise = Enterprise.find_by_permalink(params[:id]) || Enterprise.find(params[:id])
|
||||
authorize! :update, @enterprise
|
||||
|
||||
if @enterprise.update_attributes(params[:enterprise])
|
||||
@@ -40,7 +40,7 @@ module Api
|
||||
end
|
||||
|
||||
def update_image
|
||||
@enterprise = Enterprise.find(params[:id])
|
||||
@enterprise = Enterprise.find_by_permalink(params[:id]) || Enterprise.find(params[:id])
|
||||
authorize! :update, @enterprise
|
||||
|
||||
if params[:logo] && @enterprise.update_attributes( { logo: params[:logo] } )
|
||||
|
||||
@@ -11,8 +11,19 @@ class BaseController < ApplicationController
|
||||
include Spree::ProductsHelper
|
||||
|
||||
before_filter :check_order_cycle_expiry
|
||||
|
||||
|
||||
def load_active_distributors
|
||||
@active_distributors ||= Enterprise.distributors_with_active_order_cycles
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_order_cycles
|
||||
@order_cycles = OrderCycle.with_distributor(@distributor).active
|
||||
|
||||
# And default to the only order cycle if there's only the one
|
||||
if @order_cycles.count == 1
|
||||
current_order(true).set_order_cycle! @order_cycles.first
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
class EnterprisesController < BaseController
|
||||
layout "darkswarm"
|
||||
helper Spree::ProductsHelper
|
||||
include OrderCyclesHelper
|
||||
|
||||
# These prepended filters are in the reverse order of execution
|
||||
prepend_before_filter :load_active_distributors, :set_order_cycles, :require_distributor_chosen, :reset_order, only: :shop
|
||||
before_filter :clean_permalink, only: :check_permalink
|
||||
|
||||
respond_to :js, only: :permalink_checker
|
||||
|
||||
def index
|
||||
@enterprises = Enterprise.all
|
||||
end
|
||||
@@ -24,7 +31,7 @@ class EnterprisesController < BaseController
|
||||
end
|
||||
|
||||
def show
|
||||
@enterprise = Enterprise.find params[:id]
|
||||
@enterprise = Enterprise.find_by_permalink(params[:id]) || Enterprise.find(params[:id])
|
||||
|
||||
# User can view this page if they've already chosen their distributor, or if this page
|
||||
# is for a supplier, they may use it to select a distributor that sells this supplier's
|
||||
@@ -52,8 +59,25 @@ class EnterprisesController < BaseController
|
||||
end
|
||||
end
|
||||
|
||||
def shop
|
||||
distributor = Enterprise.is_distributor.find params[:id]
|
||||
def check_permalink
|
||||
return render text: params[:permalink], status: 409 if Enterprise.find_by_permalink params[:permalink]
|
||||
|
||||
path = Rails.application.routes.recognize_path( "/#{ params[:permalink].to_s }" )
|
||||
if path && path[:controller] == "cms_content"
|
||||
render text: params[:permalink], status: 200
|
||||
else
|
||||
render text: params[:permalink], status: 409
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def clean_permalink
|
||||
params[:permalink] = params[:permalink].parameterize
|
||||
end
|
||||
|
||||
def reset_order
|
||||
distributor = Enterprise.is_distributor.find_by_permalink(params[:id]) || Enterprise.is_distributor.find(params[:id])
|
||||
order = current_order(true)
|
||||
|
||||
if order.distributor and order.distributor != distributor
|
||||
@@ -66,7 +90,5 @@ class EnterprisesController < BaseController
|
||||
order_cycle_options = OrderCycle.active.with_distributor(distributor)
|
||||
order.order_cycle = order_cycle_options.first if order_cycle_options.count == 1
|
||||
order.save!
|
||||
|
||||
redirect_to main_app.shop_path
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,4 +5,8 @@ class GroupsController < BaseController
|
||||
def index
|
||||
@groups = EnterpriseGroup.on_front_page.by_position
|
||||
end
|
||||
|
||||
def show
|
||||
@group = EnterpriseGroup.find params[:id]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -20,7 +20,7 @@ module OpenFoodNetwork
|
||||
|
||||
def add_variant
|
||||
@cart = Cart.find(params[:cart_id])
|
||||
distributor = Enterprise.find(params[:distributor_id])
|
||||
distributor = Enterprise.find_by_permalink(params[:distributor_id])
|
||||
order_cycle = OrderCycle.find(params[:order_cycle_id]) if params[:order_cycle_id]
|
||||
|
||||
if @cart.add_variant params[:variant_id], params[:quantity], distributor, order_cycle, current_currency
|
||||
@@ -36,4 +36,4 @@ module OpenFoodNetwork
|
||||
Spree::Config[:currency]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
require 'open_food_network/scope_product_to_hub'
|
||||
|
||||
class ShopController < BaseController
|
||||
layout "darkswarm"
|
||||
before_filter :require_distributor_chosen
|
||||
before_filter :set_order_cycles
|
||||
before_filter :load_active_distributors
|
||||
|
||||
def show
|
||||
redirect_to main_app.enterprise_shop_path(current_distributor)
|
||||
end
|
||||
|
||||
def products
|
||||
@@ -34,20 +36,14 @@ class ShopController < BaseController
|
||||
|
||||
private
|
||||
|
||||
def set_order_cycles
|
||||
@order_cycles = OrderCycle.with_distributor(@distributor).active
|
||||
|
||||
# And default to the only order cycle if there's only the one
|
||||
if @order_cycles.count == 1
|
||||
current_order(true).set_order_cycle! @order_cycles.first
|
||||
end
|
||||
end
|
||||
|
||||
def products_for_shop
|
||||
current_order_cycle.andand
|
||||
.valid_products_distributed_by(current_distributor).andand
|
||||
.order(taxon_order).andand
|
||||
.select { |p| !p.deleted? && p.has_stock_for_distribution?(current_order_cycle, current_distributor) }
|
||||
if current_order_cycle
|
||||
current_order_cycle.
|
||||
valid_products_distributed_by(current_distributor).
|
||||
order(taxon_order).
|
||||
each { |p| p.scope_to_hub current_distributor }.
|
||||
select { |p| !p.deleted? && p.has_stock_for_distribution?(current_order_cycle, current_distributor) }
|
||||
end
|
||||
end
|
||||
|
||||
def taxon_order
|
||||
|
||||
@@ -5,9 +5,13 @@ require 'open_food_network/group_buy_report'
|
||||
require 'open_food_network/order_grouper'
|
||||
require 'open_food_network/customers_report'
|
||||
require 'open_food_network/users_and_enterprises_report'
|
||||
require 'open_food_network/order_cycle_management_report'
|
||||
require 'open_food_network/sales_tax_report'
|
||||
|
||||
Spree::Admin::ReportsController.class_eval do
|
||||
|
||||
include Spree::ReportsHelper
|
||||
|
||||
REPORT_TYPES = {
|
||||
orders_and_fulfillment: [
|
||||
['Order Cycle Supplier Totals',:order_cycle_supplier_totals],
|
||||
@@ -22,11 +26,15 @@ Spree::Admin::ReportsController.class_eval do
|
||||
customers: [
|
||||
["Mailing List", :mailing_list],
|
||||
["Addresses", :addresses]
|
||||
],
|
||||
order_cycle_management: [
|
||||
["Payment Methods Report", :payment_methods],
|
||||
["Delivery Report", :delivery]
|
||||
]
|
||||
}
|
||||
|
||||
# Fetches user's distributors, suppliers and order_cycles
|
||||
before_filter :load_data, only: [:customers, :products_and_inventory]
|
||||
before_filter :load_data, only: [:customers, :products_and_inventory, :order_cycle_management]
|
||||
|
||||
# Render a partial for orders and fulfillment description
|
||||
respond_override :index => { :html => { :success => lambda {
|
||||
@@ -36,6 +44,8 @@ Spree::Admin::ReportsController.class_eval do
|
||||
render_to_string(partial: 'products_and_inventory_description', layout: false, locals: {report_types: REPORT_TYPES[:products_and_inventory]}).html_safe
|
||||
@reports[:customers][:description] =
|
||||
render_to_string(partial: 'customers_description', layout: false, locals: {report_types: REPORT_TYPES[:customers]}).html_safe
|
||||
@reports[:order_cycle_management][:description] =
|
||||
render_to_string(partial: 'order_cycle_management_description', layout: false, locals: {report_types: REPORT_TYPES[:order_cycle_management]}).html_safe
|
||||
} } }
|
||||
|
||||
|
||||
@@ -50,12 +60,22 @@ Spree::Admin::ReportsController.class_eval do
|
||||
@report_types = REPORT_TYPES[:customers]
|
||||
@report_type = params[:report_type]
|
||||
@report = OpenFoodNetwork::CustomersReport.new spree_current_user, params
|
||||
render_report(@report.header, @report.table, params[:csv], "customers_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
render_report(@report.header, @report.table, params[:csv], "customers.csv")
|
||||
def order_cycle_management
|
||||
@report_types = REPORT_TYPES[:order_cycle_management]
|
||||
@report_type = params[:report_type]
|
||||
@report = OpenFoodNetwork::OrderCycleManagementReport.new spree_current_user, params
|
||||
|
||||
@search = Spree::Order.complete.not_state(:canceled).managed_by(spree_current_user).search(params[:q])
|
||||
@orders = @search.result
|
||||
|
||||
render_report(@report.header, @report.table, params[:csv], "order_cycle_management_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
def orders_and_distributors
|
||||
params[:q] = {} unless params[:q]
|
||||
params[:q] ||= {}
|
||||
|
||||
if params[:q][:completed_at_gt].blank?
|
||||
params[:q][:completed_at_gt] = Time.zone.now.beginning_of_month
|
||||
@@ -79,12 +99,42 @@ Spree::Admin::ReportsController.class_eval do
|
||||
csv << @report.header
|
||||
@report.table.each { |row| csv << row }
|
||||
end
|
||||
send_data csv_string, :filename => "orders_and_distributors.csv"
|
||||
send_data csv_string, :filename => "orders_and_distributors_#{timestamp}.csv"
|
||||
end
|
||||
end
|
||||
|
||||
def sales_tax
|
||||
params[:q] ||= {}
|
||||
|
||||
if params[:q][:completed_at_gt].blank?
|
||||
params[:q][:completed_at_gt] = Time.zone.now.beginning_of_month
|
||||
else
|
||||
params[:q][:completed_at_gt] = Time.zone.parse(params[:q][:completed_at_gt]).beginning_of_day rescue Time.zone.now.beginning_of_month
|
||||
end
|
||||
|
||||
if params[:q] && !params[:q][:completed_at_lt].blank?
|
||||
params[:q][:completed_at_lt] = Time.zone.parse(params[:q][:completed_at_lt]).end_of_day rescue ""
|
||||
end
|
||||
params[:q][:meta_sort] ||= "completed_at.desc"
|
||||
|
||||
@search = Spree::Order.complete.not_state(:canceled).managed_by(spree_current_user).search(params[:q])
|
||||
orders = @search.result
|
||||
@distributors = Enterprise.is_distributor.managed_by(spree_current_user)
|
||||
|
||||
@report = OpenFoodNetwork::SalesTaxReport.new orders
|
||||
unless params[:csv]
|
||||
render :html => @report
|
||||
else
|
||||
csv_string = CSV.generate do |csv|
|
||||
csv << @report.header
|
||||
@report.table.each { |row| csv << row }
|
||||
end
|
||||
send_data csv_string, :filename => "sales_tax.csv"
|
||||
end
|
||||
end
|
||||
|
||||
def bulk_coop
|
||||
params[:q] = {} unless params[:q]
|
||||
params[:q] ||= {}
|
||||
|
||||
if params[:q][:completed_at_gt].blank?
|
||||
params[:q][:completed_at_gt] = Time.zone.now.beginning_of_month
|
||||
@@ -231,13 +281,13 @@ Spree::Admin::ReportsController.class_eval do
|
||||
|
||||
@header = header
|
||||
@table = order_grouper.table(@line_items)
|
||||
csv_file_name = "bulk_coop.csv"
|
||||
csv_file_name = "bulk_coop_#{timestamp}.csv"
|
||||
|
||||
render_report(@header, @table, params[:csv], csv_file_name)
|
||||
end
|
||||
|
||||
def payments
|
||||
params[:q] = {} unless params[:q]
|
||||
params[:q] ||= {}
|
||||
|
||||
if params[:q][:completed_at_gt].blank?
|
||||
params[:q][:completed_at_gt] = Time.zone.now.beginning_of_month
|
||||
@@ -262,7 +312,7 @@ Spree::Admin::ReportsController.class_eval do
|
||||
when "payments_by_payment_type"
|
||||
table_items = payments
|
||||
|
||||
header = ["Payment State", "Distributor", "Payment Type", "Total ($)"]
|
||||
header = ["Payment State", "Distributor", "Payment Type", "Total (#{currency_symbol})"]
|
||||
|
||||
columns = [ proc { |payments| payments.first.order.payment_state },
|
||||
proc { |payments| payments.first.order.distributor.name },
|
||||
@@ -279,7 +329,7 @@ Spree::Admin::ReportsController.class_eval do
|
||||
when "itemised_payment_totals"
|
||||
table_items = orders
|
||||
|
||||
header = ["Payment State", "Distributor", "Product Total ($)", "Shipping Total ($)", "Outstanding Balance ($)", "Total ($)"]
|
||||
header = ["Payment State", "Distributor", "Product Total (#{currency_symbol})", "Shipping Total (#{currency_symbol})", "Outstanding Balance (#{currency_symbol})", "Total (#{currency_symbol})"]
|
||||
|
||||
columns = [ proc { |orders| orders.first.payment_state },
|
||||
proc { |orders| orders.first.distributor.name },
|
||||
@@ -296,7 +346,7 @@ Spree::Admin::ReportsController.class_eval do
|
||||
when "payment_totals"
|
||||
table_items = orders
|
||||
|
||||
header = ["Payment State", "Distributor", "Product Total ($)", "Shipping Total ($)", "Total ($)", "EFT ($)", "PayPal ($)", "Outstanding Balance ($)"]
|
||||
header = ["Payment State", "Distributor", "Product Total (#{currency_symbol})", "Shipping Total (#{currency_symbol})", "Total (#{currency_symbol})", "EFT (#{currency_symbol})", "PayPal (#{currency_symbol})", "Outstanding Balance (#{currency_symbol})"]
|
||||
|
||||
columns = [ proc { |orders| orders.first.payment_state },
|
||||
proc { |orders| orders.first.distributor.name },
|
||||
@@ -315,7 +365,7 @@ Spree::Admin::ReportsController.class_eval do
|
||||
else
|
||||
table_items = payments
|
||||
|
||||
header = ["Payment State", "Distributor", "Payment Type", "Total ($)"]
|
||||
header = ["Payment State", "Distributor", "Payment Type", "Total (#{currency_symbol})"]
|
||||
|
||||
columns = [ proc { |payments| payments.first.order.payment_state },
|
||||
proc { |payments| payments.first.order.distributor.name },
|
||||
@@ -335,7 +385,7 @@ Spree::Admin::ReportsController.class_eval do
|
||||
|
||||
@header = header
|
||||
@table = order_grouper.table(table_items)
|
||||
csv_file_name = "payments.csv"
|
||||
csv_file_name = "payments_#{timestamp}.csv"
|
||||
|
||||
render_report(@header, @table, params[:csv], csv_file_name)
|
||||
|
||||
@@ -475,7 +525,7 @@ Spree::Admin::ReportsController.class_eval do
|
||||
table_items = @line_items
|
||||
@include_blank = 'All'
|
||||
|
||||
header = ["Hub", "Customer", "Email", "Phone", "Producer", "Product", "Variant", "Amount", "Item ($)", "Item + Fees ($)", "Dist ($)", "Ship ($)", "Total ($)", "Paid?",
|
||||
header = ["Hub", "Customer", "Email", "Phone", "Producer", "Product", "Variant", "Amount", "Item (#{currency_symbol})", "Item + Fees (#{currency_symbol})", "Dist (#{currency_symbol})", "Ship (#{currency_symbol})", "Total (#{currency_symbol})", "Paid?",
|
||||
"Shipping", "Delivery?", "Ship street", "Ship street 2", "Ship city", "Ship postcode", "Ship state", "Order notes"]
|
||||
|
||||
rsa = proc { |line_items| line_items.first.order.shipping_method.andand.require_ship_address }
|
||||
@@ -567,7 +617,7 @@ Spree::Admin::ReportsController.class_eval do
|
||||
|
||||
@header = header
|
||||
@table = order_grouper.table(table_items)
|
||||
csv_file_name = "#{__method__}.csv"
|
||||
csv_file_name = "#{params[:report_type]}_#{timestamp}.csv"
|
||||
|
||||
render_report(@header, @table, params[:csv], csv_file_name)
|
||||
|
||||
@@ -576,13 +626,13 @@ Spree::Admin::ReportsController.class_eval do
|
||||
def products_and_inventory
|
||||
@report_types = REPORT_TYPES[:products_and_inventory]
|
||||
@report = OpenFoodNetwork::ProductsAndInventoryReport.new spree_current_user, params
|
||||
render_report(@report.header, @report.table, params[:csv], "products_and_inventory.csv")
|
||||
render_report(@report.header, @report.table, params[:csv], "products_and_inventory_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
def users_and_enterprises
|
||||
# @report_types = REPORT_TYPES[:users_and_enterprises]
|
||||
@report = OpenFoodNetwork::UsersAndEnterprisesReport.new params
|
||||
render_report(@report.header, @report.table, params[:csv], "users_and_enterprises.csv")
|
||||
render_report(@report.header, @report.table, params[:csv], "users_and_enterprises_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
def render_report (header, table, create_csv, csv_file_name)
|
||||
@@ -620,7 +670,9 @@ Spree::Admin::ReportsController.class_eval do
|
||||
:customers => {:name => "Customers", :description => 'Customer details'},
|
||||
:products_and_inventory => {:name => "Products & Inventory", :description => ''},
|
||||
:sales_total => { :name => "Sales Total", :description => "Sales Total For All Orders" },
|
||||
:users_and_enterprises => { :name => "Users & Enterprises", :description => "Enterprise Ownership & Status" }
|
||||
:users_and_enterprises => { :name => "Users & Enterprises", :description => "Enterprise Ownership & Status" },
|
||||
:order_cycle_management => {:name => "Order Cycle Management", :description => ''},
|
||||
:sales_tax => { :name => "Sales Tax", :description => "Sales Tax For Orders" }
|
||||
}
|
||||
# Return only reports the user is authorized to view.
|
||||
reports.select { |action| can? action, :report }
|
||||
@@ -634,4 +686,8 @@ Spree::Admin::ReportsController.class_eval do
|
||||
end
|
||||
total_units.round(3)
|
||||
end
|
||||
|
||||
def timestamp
|
||||
Time.now.strftime("%Y%m%d")
|
||||
end
|
||||
end
|
||||
|
||||
18
app/controllers/spree/admin/search_controller_decorator.rb
Normal file
18
app/controllers/spree/admin/search_controller_decorator.rb
Normal file
@@ -0,0 +1,18 @@
|
||||
Spree::Admin::SearchController.class_eval do
|
||||
def known_users
|
||||
if exact_match = Spree.user_class.find_by_email(params[:q])
|
||||
@users = [exact_match]
|
||||
else
|
||||
@users = spree_current_user.known_users.ransack({
|
||||
:m => 'or',
|
||||
:email_start => params[:q],
|
||||
:ship_address_firstname_start => params[:q],
|
||||
:ship_address_lastname_start => params[:q],
|
||||
:bill_address_firstname_start => params[:q],
|
||||
:bill_address_lastname_start => params[:q]
|
||||
}).result.limit(10)
|
||||
end
|
||||
render :users
|
||||
|
||||
end
|
||||
end
|
||||
@@ -17,21 +17,25 @@ Spree::Api::ProductsController.class_eval do
|
||||
ransack(params[:q]).result.
|
||||
page(params[:page]).per(params[:per_page])
|
||||
|
||||
render text: { products: ActiveModel::ArraySerializer.new(@products, each_serializer: Spree::Api::ProductSerializer), pages: @products.num_pages }.to_json
|
||||
render_paged_products @products
|
||||
end
|
||||
|
||||
def distributable
|
||||
producers = OpenFoodNetwork::Permissions.new(current_api_user).
|
||||
order_cycle_enterprises.is_primary_producer.by_name
|
||||
|
||||
@products = Spree::Product.scoped.
|
||||
merge(product_scope).
|
||||
where(supplier_id: producers).
|
||||
by_producer.by_name.
|
||||
ransack(params[:q]).result.
|
||||
page(params[:page]).per(params[:per_page])
|
||||
@products = paged_products_for_producers producers
|
||||
|
||||
render text: { products: ActiveModel::ArraySerializer.new(@products, each_serializer: Spree::Api::ProductSerializer), pages: @products.num_pages }.to_json
|
||||
render_paged_products @products
|
||||
end
|
||||
|
||||
def overridable
|
||||
producers = OpenFoodNetwork::Permissions.new(current_api_user).
|
||||
variant_override_producers.by_name
|
||||
|
||||
@products = paged_products_for_producers producers
|
||||
|
||||
render_paged_products @products
|
||||
end
|
||||
|
||||
def soft_delete
|
||||
@@ -60,4 +64,17 @@ Spree::Api::ProductsController.class_eval do
|
||||
scope.includes(:master)
|
||||
end
|
||||
|
||||
def paged_products_for_producers(producers)
|
||||
Spree::Product.scoped.
|
||||
merge(product_scope).
|
||||
where(supplier_id: producers).
|
||||
by_producer.by_name.
|
||||
ransack(params[:q]).result.
|
||||
page(params[:page]).per(params[:per_page])
|
||||
end
|
||||
|
||||
def render_paged_products(products)
|
||||
render text: { products: ActiveModel::ArraySerializer.new(products, each_serializer: Spree::Api::ProductSerializer), pages: products.num_pages }.to_json
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -33,25 +33,6 @@ Spree::OrdersController.class_eval do
|
||||
end
|
||||
end
|
||||
|
||||
def select_distributor
|
||||
distributor = Enterprise.is_distributor.find params[:id]
|
||||
|
||||
order = current_order(true)
|
||||
order.distributor = distributor
|
||||
order.save!
|
||||
|
||||
redirect_to main_app.enterprise_path(distributor)
|
||||
end
|
||||
|
||||
def deselect_distributor
|
||||
order = current_order(true)
|
||||
|
||||
order.distributor = nil
|
||||
order.save!
|
||||
|
||||
redirect_to root_path
|
||||
end
|
||||
|
||||
def update_distribution
|
||||
@order = current_order(true)
|
||||
|
||||
|
||||
@@ -33,6 +33,15 @@ module Admin
|
||||
admin_inject_json_ams_array "ofn.admin", "producers", @producers, Api::Admin::IdNameSerializer
|
||||
end
|
||||
|
||||
def admin_inject_enterprise_permissions
|
||||
permissions =
|
||||
{can_manage_shipping_methods: can?(:manage_shipping_methods, @enterprise),
|
||||
can_manage_payment_methods: can?(:manage_payment_methods, @enterprise),
|
||||
can_manage_enterprise_fees: can?(:manage_enterprise_fees, @enterprise)}
|
||||
|
||||
render partial: "admin/json/injection_ams", locals: {ngModule: "admin.enterprises", name: "enterprisePermissions", json: permissions.to_json}
|
||||
end
|
||||
|
||||
def admin_inject_hub_permissions
|
||||
render partial: "admin/json/injection_ams", locals: {ngModule: "ofn.admin", name: "hubPermissions", json: @hub_permissions.to_json}
|
||||
end
|
||||
@@ -53,6 +62,10 @@ module Admin
|
||||
admin_inject_json_ams_array "ofn.admin", "variantOverrides", @variant_overrides, Api::Admin::VariantOverrideSerializer
|
||||
end
|
||||
|
||||
def admin_inject_order_cycle_instance
|
||||
render partial: "admin/json/injection_ams", locals: {ngModule: 'admin.order_cycles', name: 'ocInstance', json: "{coordinator_id: '#{@order_cycle.coordinator.id}'}"}
|
||||
end
|
||||
|
||||
def admin_inject_spree_api_key
|
||||
render partial: "admin/json/injection_ams", locals: {ngModule: 'ofn.admin', name: 'SpreeApiKey', json: "'#{@spree_api_key.to_s}'"}
|
||||
end
|
||||
|
||||
@@ -1,2 +1,23 @@
|
||||
module GroupsHelper
|
||||
|
||||
def link_to_service(baseurl, name, html_options = {})
|
||||
return if name.blank?
|
||||
html_options = html_options.merge target: '_blank'
|
||||
link_to ext_url(baseurl, name), html_options do
|
||||
yield
|
||||
end
|
||||
end
|
||||
|
||||
def ext_url(prefix, url)
|
||||
if url =~ /^https?:\/\//i
|
||||
url
|
||||
else
|
||||
prefix + url
|
||||
end
|
||||
end
|
||||
|
||||
def strip_url(url)
|
||||
url.andand.sub(/^https?:\/\//i, '')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -3,6 +3,10 @@ module OrderCyclesHelper
|
||||
@current_order_cycle ||= current_order(false).andand.order_cycle
|
||||
end
|
||||
|
||||
def order_cycle_permitted_in(enterprises)
|
||||
enterprises.merge(order_cycle_permitted_enterprises)
|
||||
end
|
||||
|
||||
def order_cycle_permitted_enterprises
|
||||
OpenFoodNetwork::Permissions.new(spree_current_user).order_cycle_enterprises
|
||||
end
|
||||
@@ -11,33 +15,24 @@ module OrderCyclesHelper
|
||||
order_cycle_permitted_enterprises.is_primary_producer.by_name
|
||||
end
|
||||
|
||||
def order_cycle_producer_enterprise_options
|
||||
validated_enterprise_options order_cycle_producer_enterprises, confirmed: true
|
||||
end
|
||||
|
||||
def order_cycle_coordinating_enterprises
|
||||
order_cycle_permitted_enterprises.is_distributor.by_name
|
||||
end
|
||||
|
||||
def order_cycle_hub_enterprises(options={})
|
||||
enterprises = order_cycle_permitted_enterprises.is_distributor.by_name
|
||||
def order_cycle_coordinating_enterprise_options
|
||||
validated_enterprise_options order_cycle_coordinating_enterprises, confirmed: true
|
||||
end
|
||||
|
||||
if options[:without_validation]
|
||||
enterprises
|
||||
else
|
||||
enterprises.map do |e|
|
||||
disabled_message = nil
|
||||
if e.shipping_methods.empty? && e.payment_methods.available.empty?
|
||||
disabled_message = 'no shipping or payment methods'
|
||||
elsif e.shipping_methods.empty?
|
||||
disabled_message = 'no shipping methods'
|
||||
elsif e.payment_methods.available.empty?
|
||||
disabled_message = 'no payment methods'
|
||||
end
|
||||
def order_cycle_hub_enterprises
|
||||
order_cycle_permitted_enterprises.is_hub.by_name
|
||||
end
|
||||
|
||||
if disabled_message
|
||||
["#{e.name} (#{disabled_message})", e.id, {disabled: true}]
|
||||
else
|
||||
[e.name, e.id]
|
||||
end
|
||||
end
|
||||
end
|
||||
def order_cycle_hub_enterprise_options
|
||||
validated_enterprise_options order_cycle_hub_enterprises, confirmed: true, shipping_and_payment_methods: true
|
||||
end
|
||||
|
||||
def order_cycle_status_class(order_cycle)
|
||||
@@ -68,8 +63,12 @@ module OrderCyclesHelper
|
||||
OrderCycle.active.with_distributor(@distributor).present?
|
||||
end
|
||||
|
||||
def order_cycles_simple_view
|
||||
@order_cycles_simple_view ||= !OpenFoodNetwork::Permissions.new(spree_current_user).can_manage_complex_order_cycles?
|
||||
def order_cycles_simple_index
|
||||
@order_cycles_simple_index ||= !OpenFoodNetwork::Permissions.new(spree_current_user).can_manage_complex_order_cycles?
|
||||
end
|
||||
|
||||
def order_cycles_simple_form
|
||||
@order_cycles_simple_form ||= @order_cycle.coordinator.sells == 'own'
|
||||
end
|
||||
|
||||
def order_cycles_enabled?
|
||||
@@ -80,4 +79,28 @@ module OrderCyclesHelper
|
||||
order_cycle.exchanges.to_enterprises(current_distributor).outgoing.first.pickup_time
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validated_enterprise_options(enterprises, options={})
|
||||
enterprises.map do |e|
|
||||
disabled_message = nil
|
||||
if options[:shipping_and_payment_methods] && (e.shipping_methods.empty? || e.payment_methods.available.empty?)
|
||||
if e.shipping_methods.empty? && e.payment_methods.available.empty?
|
||||
disabled_message = 'no shipping or payment methods'
|
||||
elsif e.shipping_methods.empty?
|
||||
disabled_message = 'no shipping methods'
|
||||
elsif e.payment_methods.available.empty?
|
||||
disabled_message = 'no payment methods'
|
||||
end
|
||||
elsif options[:confirmed] && !e.confirmed?
|
||||
disabled_message = 'unconfirmed'
|
||||
end
|
||||
|
||||
if disabled_message
|
||||
["#{e.name} (#{disabled_message})", e.id, {disabled: true}]
|
||||
else
|
||||
[e.name, e.id]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
9
app/helpers/spree/base_helper_decorator.rb
Normal file
9
app/helpers/spree/base_helper_decorator.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
module Spree
|
||||
module BaseHelper
|
||||
# human readable list of variant options
|
||||
# Override: Do not show out of stock text
|
||||
def variant_options(v, options={})
|
||||
v.options_text
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,3 +1,5 @@
|
||||
require 'spree/money_decorator'
|
||||
|
||||
module Spree
|
||||
module ReportsHelper
|
||||
def report_order_cycle_options(order_cycles)
|
||||
@@ -7,5 +9,17 @@ module Spree
|
||||
[ "#{oc.name} (#{orders_open_at} - #{orders_close_at})".html_safe, oc.id ]
|
||||
end
|
||||
end
|
||||
|
||||
def report_payment_method_options(orders)
|
||||
orders.map { |o| o.payments.first.payment_method.andand.name }.uniq
|
||||
end
|
||||
|
||||
def report_shipping_method_options(orders)
|
||||
orders.map { |o| o.shipping_method.andand.name }.uniq
|
||||
end
|
||||
|
||||
def currency_symbol
|
||||
Spree::Money.currency_symbol
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
7
app/models/customer.rb
Normal file
7
app/models/customer.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
class Customer < ActiveRecord::Base
|
||||
belongs_to :enterprise
|
||||
|
||||
validates :code, presence: true, uniqueness: {scope: :enterprise_id}
|
||||
validates :email, presence: true
|
||||
validates :enterprise_id, presence: true
|
||||
end
|
||||
@@ -56,20 +56,25 @@ class Enterprise < ActiveRecord::Base
|
||||
validates :address, presence: true, associated: true
|
||||
validates :email, presence: true
|
||||
validates_presence_of :owner
|
||||
validates :permalink, uniqueness: true, presence: true
|
||||
validate :shopfront_taxons
|
||||
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_save :confirmation_check, if: lambda { email_changed? }
|
||||
|
||||
before_validation :initialize_permalink, if: lambda { permalink.nil? }
|
||||
before_validation :ensure_owner_is_manager, if: lambda { owner_id_changed? && !owner_id.nil? }
|
||||
before_validation :set_unused_address_fields
|
||||
after_validation :geocode_address
|
||||
|
||||
after_create :relate_to_owners_enterprises
|
||||
# TODO: Later versions of devise have a dedicated after_confirmation callback, so use that
|
||||
after_update :welcome_after_confirm, if: lambda { confirmation_token_changed? && confirmation_token.nil? }
|
||||
after_create :send_welcome_email, if: lambda { email_is_known? }
|
||||
|
||||
after_rollback :restore_permalink
|
||||
|
||||
scope :by_name, order('name')
|
||||
scope :visible, where(:visible => true)
|
||||
scope :confirmed, where('confirmed_at IS NOT NULL')
|
||||
@@ -93,6 +98,7 @@ class Enterprise < ActiveRecord::Base
|
||||
}
|
||||
scope :is_primary_producer, where(:is_primary_producer => true)
|
||||
scope :is_distributor, where('sells != ?', 'none')
|
||||
scope :is_hub, where(sells: 'any')
|
||||
scope :supplying_variant_in, lambda { |variants| joins(:supplied_products => :variants_including_master).where('spree_variants.id IN (?)', variants).select('DISTINCT enterprises.*') }
|
||||
scope :with_supplied_active_products_on_hand, lambda {
|
||||
joins(:supplied_products)
|
||||
@@ -199,7 +205,7 @@ class Enterprise < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def to_param
|
||||
"#{id}-#{name.parameterize}"
|
||||
permalink
|
||||
end
|
||||
|
||||
def relatives
|
||||
@@ -247,6 +253,10 @@ class Enterprise < ActiveRecord::Base
|
||||
self.sells != "none"
|
||||
end
|
||||
|
||||
def is_hub
|
||||
self.sells == 'any'
|
||||
end
|
||||
|
||||
# Simplify enterprise categories for frontend logic and icons, and maybe other things.
|
||||
def category
|
||||
# Make this crazy logic human readable so we can argue about it sanely.
|
||||
@@ -290,6 +300,22 @@ class Enterprise < ActiveRecord::Base
|
||||
shipping_methods.any? && payment_methods.available.any?
|
||||
end
|
||||
|
||||
def self.find_available_permalink(test_permalink)
|
||||
test_permalink = test_permalink.parameterize
|
||||
test_permalink = "my-enterprise" if test_permalink.blank?
|
||||
existing = Enterprise.select(:permalink).order(:permalink).where("permalink LIKE ?", "#{test_permalink}%").map(&:permalink)
|
||||
if existing.empty?
|
||||
test_permalink
|
||||
else
|
||||
used_indices = existing.map do |p|
|
||||
p.slice!(/^#{test_permalink}/)
|
||||
p.match(/^\d+$/).to_s.to_i
|
||||
end.select{ |p| p }
|
||||
options = (1..existing.length).to_a - used_indices
|
||||
test_permalink + options.first.to_s
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def devise_mailer
|
||||
@@ -330,7 +356,7 @@ class Enterprise < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def geocode_address
|
||||
address.geocode if address.changed?
|
||||
address.geocode if address.andand.changed?
|
||||
end
|
||||
|
||||
def ensure_owner_is_manager
|
||||
@@ -343,9 +369,49 @@ class Enterprise < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def relate_to_owners_enterprises
|
||||
# When a new producer is created, it grants permissions to all pre-existing hubs
|
||||
# When a new hub is created,
|
||||
# - it grants permissions to all pre-existing hubs
|
||||
# - all producers grant permission to it
|
||||
|
||||
enterprises = owner.owned_enterprises.where('enterprises.id != ?', self)
|
||||
|
||||
# We grant permissions to all pre-existing hubs
|
||||
enterprises.is_hub.each do |enterprise|
|
||||
EnterpriseRelationship.create!(parent: self,
|
||||
child: enterprise,
|
||||
permissions_list: [:add_to_order_cycle,
|
||||
:manage_products,
|
||||
:edit_profile,
|
||||
:create_variant_overrides])
|
||||
end
|
||||
|
||||
# All pre-existing producers grant permission to new hubs
|
||||
if is_hub
|
||||
enterprises.is_primary_producer.each do |enterprise|
|
||||
EnterpriseRelationship.create!(parent: enterprise,
|
||||
child: self,
|
||||
permissions_list: [:add_to_order_cycle,
|
||||
:manage_products,
|
||||
:edit_profile,
|
||||
:create_variant_overrides])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def shopfront_taxons
|
||||
unless preferred_shopfront_taxon_order =~ /\A((\d+,)*\d+)?\z/
|
||||
errors.add(:shopfront_category_ordering, "must contain a list of taxons.")
|
||||
end
|
||||
end
|
||||
|
||||
def restore_permalink
|
||||
# If the permalink has errors, reset it to it's original value, so we can update the form
|
||||
self.permalink = permalink_was if permalink_changed? && errors[:permalink].present?
|
||||
end
|
||||
|
||||
def initialize_permalink
|
||||
self.permalink = Enterprise.find_available_permalink(name)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
class EnterpriseFee < ActiveRecord::Base
|
||||
belongs_to :enterprise
|
||||
belongs_to :tax_category, class_name: 'Spree::TaxCategory', foreign_key: 'tax_category_id'
|
||||
has_and_belongs_to_many :order_cycles, join_table: 'coordinator_fees'
|
||||
has_many :exchange_fees, dependent: :destroy
|
||||
has_many :exchanges, through: :exchange_fees
|
||||
@@ -8,7 +9,7 @@ class EnterpriseFee < ActiveRecord::Base
|
||||
|
||||
calculated_adjustments
|
||||
|
||||
attr_accessible :enterprise_id, :fee_type, :name, :calculator_type
|
||||
attr_accessible :enterprise_id, :fee_type, :name, :tax_category_id, :calculator_type
|
||||
|
||||
FEE_TYPES = %w(packing transport admin sales fundraising)
|
||||
PER_ORDER_CALCULATORS = ['Spree::Calculator::FlatRate', 'Spree::Calculator::FlexiRate']
|
||||
|
||||
@@ -1,13 +1,28 @@
|
||||
require 'open_food_network/locking'
|
||||
|
||||
class EnterpriseGroup < ActiveRecord::Base
|
||||
acts_as_list
|
||||
|
||||
has_and_belongs_to_many :enterprises
|
||||
belongs_to :owner, class_name: 'Spree::User', foreign_key: :owner_id, inverse_of: :owned_groups
|
||||
belongs_to :address, :class_name => 'Spree::Address'
|
||||
accepts_nested_attributes_for :address
|
||||
validates :address, presence: true, associated: true
|
||||
before_validation :set_undefined_address_fields
|
||||
before_validation :set_unused_address_fields
|
||||
after_find :unset_undefined_address_fields
|
||||
after_save :unset_undefined_address_fields
|
||||
|
||||
validates :name, presence: true
|
||||
validates :description, presence: true
|
||||
|
||||
attr_accessible :name, :description, :long_description, :on_front_page, :enterprise_ids
|
||||
attr_accessible :owner_id
|
||||
attr_accessible :logo, :promo_image
|
||||
attr_accessible :address_attributes
|
||||
attr_accessible :email, :website, :facebook, :instagram, :linkedin, :twitter
|
||||
|
||||
delegate :phone, :address1, :address2, :city, :zipcode, :state, :country, :to => :address
|
||||
|
||||
has_attached_file :logo,
|
||||
styles: {medium: "100x100"},
|
||||
@@ -28,4 +43,32 @@ class EnterpriseGroup < ActiveRecord::Base
|
||||
|
||||
scope :by_position, order('position ASC')
|
||||
scope :on_front_page, where(on_front_page: true)
|
||||
scope :managed_by, lambda { |user|
|
||||
if user.has_spree_role?('admin')
|
||||
scoped
|
||||
else
|
||||
where('owner_id = ?', user.id)
|
||||
end
|
||||
}
|
||||
|
||||
def set_unused_address_fields
|
||||
address.firstname = address.lastname = 'unused' if address.present?
|
||||
end
|
||||
|
||||
def set_undefined_address_fields
|
||||
return unless address.present?
|
||||
address.phone.present? || address.phone = 'undefined'
|
||||
address.address1.present? || address.address1 = 'undefined'
|
||||
address.city.present? || address.city = 'undefined'
|
||||
address.zipcode.present? || address.zipcode = 'undefined'
|
||||
end
|
||||
|
||||
def unset_undefined_address_fields
|
||||
return unless address.present?
|
||||
address.phone.sub!(/^undefined$/, '')
|
||||
address.address1.sub!(/^undefined$/, '')
|
||||
address.city.sub!(/^undefined$/, '')
|
||||
address.zipcode.sub!(/^undefined$/, '')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -15,6 +15,7 @@ class EnterpriseRelationship < ActiveRecord::Base
|
||||
}
|
||||
|
||||
scope :permitting, ->(enterprises) { where('child_id IN (?)', enterprises) }
|
||||
scope :permitted_by, ->(enterprises) { where('parent_id IN (?)', enterprises) }
|
||||
|
||||
scope :with_permission, ->(permission) {
|
||||
joins(:permissions).
|
||||
|
||||
@@ -6,6 +6,7 @@ class AbilityDecorator
|
||||
def initialize(user)
|
||||
add_base_abilities user if is_new_user? user
|
||||
add_enterprise_management_abilities user if can_manage_enterprises? user
|
||||
add_group_management_abilities user if can_manage_groups? user
|
||||
add_product_management_abilities user if can_manage_products? user
|
||||
add_order_management_abilities user if can_manage_orders? user
|
||||
add_relationship_management_abilities user if can_manage_relationships? user
|
||||
@@ -21,6 +22,11 @@ class AbilityDecorator
|
||||
user.enterprises.present?
|
||||
end
|
||||
|
||||
# Users can manage a group if they have one.
|
||||
def can_manage_groups?(user)
|
||||
user.owned_groups.present?
|
||||
end
|
||||
|
||||
# Users can manage products if they have an enterprise that is not a profile.
|
||||
def can_manage_products?(user)
|
||||
can_manage_enterprises?(user) &&
|
||||
@@ -41,6 +47,14 @@ class AbilityDecorator
|
||||
can [:create], Enterprise
|
||||
end
|
||||
|
||||
def add_group_management_abilities(user)
|
||||
can [:admin, :index], :overview
|
||||
can [:admin, :index], EnterpriseGroup
|
||||
can [:read, :edit, :update], EnterpriseGroup do |group|
|
||||
user.owned_groups.include? group
|
||||
end
|
||||
end
|
||||
|
||||
def add_enterprise_management_abilities(user)
|
||||
# Spree performs authorize! on (:create, nil) when creating a new order from admin, and also (:search, nil)
|
||||
# when searching for variants to add to the order
|
||||
@@ -52,6 +66,9 @@ class AbilityDecorator
|
||||
|
||||
can [:admin, :index, :create], Enterprise
|
||||
can [:read, :edit, :update, :bulk_update, :set_sells, :resend_confirmation], Enterprise do |enterprise|
|
||||
OpenFoodNetwork::Permissions.new(user).editable_enterprises.include? enterprise
|
||||
end
|
||||
can [:manage_payment_methods, :manage_shipping_methods, :manage_enterprise_fees], Enterprise do |enterprise|
|
||||
user.enterprises.include? enterprise
|
||||
end
|
||||
|
||||
@@ -60,6 +77,8 @@ class AbilityDecorator
|
||||
can [:admin, :read, :edit, :bulk_update, :destroy], EnterpriseFee do |enterprise_fee|
|
||||
user.enterprises.include? enterprise_fee.enterprise
|
||||
end
|
||||
|
||||
can [:admin, :known_users], :search
|
||||
end
|
||||
|
||||
def add_product_management_abilities(user)
|
||||
@@ -75,9 +94,15 @@ class AbilityDecorator
|
||||
end
|
||||
|
||||
can [:admin, :index, :read, :update, :bulk_update], VariantOverride do |vo|
|
||||
OpenFoodNetwork::Permissions.new(user).
|
||||
hub_auth = OpenFoodNetwork::Permissions.new(user).
|
||||
order_cycle_enterprises.is_distributor.
|
||||
include? vo.hub
|
||||
|
||||
producer_auth = OpenFoodNetwork::Permissions.new(user).
|
||||
variant_override_producers.
|
||||
include? vo.variant.product.supplier
|
||||
|
||||
hub_auth && producer_auth
|
||||
end
|
||||
|
||||
can [:admin, :index, :read, :create, :edit, :update_positions, :destroy], Spree::ProductProperty
|
||||
@@ -128,7 +153,7 @@ class AbilityDecorator
|
||||
end
|
||||
|
||||
# Reports page
|
||||
can [:admin, :index, :customers, :group_buys, :bulk_coop, :payments, :orders_and_distributors, :orders_and_fulfillment, :products_and_inventory], :report
|
||||
can [:admin, :index, :customers, :group_buys, :bulk_coop, :sales_tax, :payments, :orders_and_distributors, :orders_and_fulfillment, :products_and_inventory, :order_cycle_management], :report
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -3,5 +3,17 @@ module Spree
|
||||
has_one :metadata, class_name: 'AdjustmentMetadata', dependent: :destroy
|
||||
|
||||
scope :enterprise_fee, where(originator_type: 'EnterpriseFee')
|
||||
scope :included_tax, where(originator_type: 'Spree::TaxRate', adjustable_type: 'Spree::LineItem')
|
||||
|
||||
attr_accessible :included_tax
|
||||
|
||||
def set_included_tax!(rate)
|
||||
tax = amount - (amount / (1 + rate))
|
||||
set_absolute_included_tax! tax
|
||||
end
|
||||
|
||||
def set_absolute_included_tax!(tax)
|
||||
update_attributes! included_tax: tax.round(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
10
app/models/spree/app_configuration_decorator.rb
Normal file
10
app/models/spree/app_configuration_decorator.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
Spree::AppConfiguration.class_eval do
|
||||
# This file decorates the existing preferences file defined by Spree.
|
||||
# It allows us to add our own global configuration variables, which
|
||||
# we can allow to be modified in the UI by adding appropriate form
|
||||
# elements to existing or new configuration pages.
|
||||
|
||||
# Tax Preferences
|
||||
preference :products_require_tax_category, :boolean, default: false
|
||||
preference :shipping_tax_rate, :decimal, default: 0
|
||||
end
|
||||
15
app/models/spree/inventory_unit_decorator.rb
Normal file
15
app/models/spree/inventory_unit_decorator.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
module Spree
|
||||
InventoryUnit.class_eval do
|
||||
def self.assign_opening_inventory(order)
|
||||
return [] unless order.completed?
|
||||
|
||||
#increase inventory to meet initial requirements
|
||||
order.line_items.each do |line_item|
|
||||
# Scope variant to hub so that stock levels may be subtracted from VariantOverride.
|
||||
line_item.variant.scope_to_hub order.distributor
|
||||
|
||||
increase(order, line_item.variant, line_item.quantity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -26,7 +26,7 @@ Spree::LineItem.class_eval do
|
||||
def price_with_adjustments
|
||||
# EnterpriseFee#create_locked_adjustment applies adjustments on line items to their parent order,
|
||||
# so line_item.adjustments returns an empty array
|
||||
price + order.adjustments.where(source_id: id).sum(&:amount) / quantity
|
||||
(price + order.adjustments.where(source_id: id).sum(&:amount) / quantity).round(2)
|
||||
end
|
||||
|
||||
def single_display_amount_with_adjustments
|
||||
@@ -34,9 +34,9 @@ Spree::LineItem.class_eval do
|
||||
end
|
||||
|
||||
def amount_with_adjustments
|
||||
# EnterpriseFee#create_locked_adjustment applies adjustments on line items to their parent order,
|
||||
# so line_item.adjustments returns an empty array
|
||||
amount + order.adjustments.where(source_id: id).sum(&:amount)
|
||||
# We calculate from price_with_adjustments here rather than building our own value because
|
||||
# rounding errors can produce discrepencies of $0.01.
|
||||
price_with_adjustments * quantity
|
||||
end
|
||||
|
||||
def display_amount_with_adjustments
|
||||
|
||||
7
app/models/spree/money_decorator.rb
Normal file
7
app/models/spree/money_decorator.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
Spree::Money.class_eval do
|
||||
|
||||
# return the currency symbol (on it's own) for the current default currency
|
||||
def self.currency_symbol
|
||||
Money.new(0, Spree::Config[:currency]).symbol
|
||||
end
|
||||
end
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user