Compare commits

...

84 Commits

Author SHA1 Message Date
Rohan Mitchell
2535e3965b When merging orders, set distributor when target order distributor is nil 2012-10-09 08:42:29 +11:00
Rohan Mitchell
568d948cbe Destroy incomplete orders if they can't be merged, prevents that order unexpectedly appearing in cart after checkout. Also ensure all orders have a shipping method. 2012-10-05 12:09:53 +10:00
Rohan Mitchell
6d9257d941 Do not delete shipping method referenced by a line item 2012-10-02 12:15:09 +10:00
Rohan Mitchell
7430fc9bdd Do not delete shipping method referenced by a product distribution 2012-10-02 11:58:18 +10:00
Rohan Mitchell
473b4e9adc Add positive case test 2012-10-02 11:54:18 +10:00
Rohan Mitchell
2aa450b072 Do not delete shipping method referenced by an order 2012-10-02 11:51:13 +10:00
Rohan Mitchell
3886ec39f7 Add web helper method to visit paths with delete method 2012-10-02 11:47:55 +10:00
Rohan Mitchell
afb8faa96f Update zeus config 2012-10-02 11:44:50 +10:00
Rohan Mitchell
27b7d59f46 BaseController does not attempt to merge incomplete and current orders when they have differing distributors 2012-10-02 09:44:51 +10:00
Rohan Mitchell
bc408d8b6e Add jquery and jquery_ujs includes to admin/all.js, as these have been removed from spree/admin/spree_core.js 2012-09-22 09:20:27 +10:00
Rohan Mitchell
a8758f1271 Fix OrdersHelper for upgraded spree 2012-09-21 16:36:50 +10:00
Rohan Mitchell
2bce9df25a Track 1-1-stable on spree git, fixes order quantity change bug 2012-09-21 15:55:51 +10:00
Rohan Mitchell
479c49752c Update spree_paypal_express, hopefully fixing 'Validation failed: State can't be blank' error 2012-09-21 15:32:19 +10:00
Rohan Mitchell
62d6067c1a Do not truncate cents for product price update on add to cart JS 2012-09-21 12:44:38 +10:00
Rohan Mitchell
a1b5102476 Fix checkout totals, also amend factories for valid test shipping method data 2012-09-21 12:35:01 +10:00
Rohan Mitchell
593f3887c8 Switch pry for pry-debugger 2012-09-21 12:29:06 +10:00
Rohan Mitchell
757456dd57 Set line item shipping method in callback so that Order#update shipping calcs run correctly 2012-09-20 10:45:50 +10:00
Rohan Mitchell
3894ce946d Fix error on supplier page, add test to cover 2012-09-19 15:46:56 +10:00
Rohan Mitchell
f1f9b5b2e8 Make order and distributor report resilient to orders without distributors 2012-09-19 15:19:30 +10:00
Rohan Mitchell
5402590d5f Add debug output on line item migration for lost data 2012-09-19 15:08:05 +10:00
Rohan Mitchell
eaca160367 Set line item shipping method when added to cart, update specs for changes to line item shipping method 2012-09-19 15:01:50 +10:00
Rohan Mitchell
85f18cfb12 Rob: Replace LineItem shipping_method method with relation 2012-09-19 14:27:28 +10:00
Rohan Mitchell
7492522066 Improve clarity of various totals (items, shipping, grand total) on checkout page 2012-09-14 15:35:22 +10:00
Rohan Mitchell
334f84637d Fix empty cart button alignment at checkout 2012-09-14 13:32:49 +10:00
Rohan Mitchell
3f15fc0b52 Set default admin orders view to sort with most recent orders first 2012-09-14 13:27:33 +10:00
Rohan Mitchell
a013854d2d Change logo to Eaterprises, update link colour to match 2012-09-14 11:25:36 +10:00
Rohan Mitchell
c883ab87b6 Add db backups and uploaded images to gitignore 2012-09-14 10:32:10 +10:00
Rohan Mitchell
0e313e5826 Add Zeus config 2012-09-14 10:23:22 +10:00
Rohan Mitchell
3794c00856 Upgrade Rails to 3.2.8 and Spree to 1.1.3 2012-09-14 10:20:52 +10:00
Rohan Mitchell
b87c59c051 Default to blank distributor on add to cart to require user to select one 2012-09-13 15:29:04 +10:00
Rohan Mitchell
356ae40c7b Display product descriptions as HTML in checkout 2012-09-13 13:05:12 +10:00
Rohan Mitchell
8394c47064 Add admin js includes 2012-09-13 12:27:20 +10:00
Rohan Mitchell
a84f6f08eb Compile all admin javascripts, fixes admin/images/new.js not found error 2012-09-13 12:20:35 +10:00
Rohan Mitchell
3a391d1e76 Give undefined payment method tolerance to orders and distributors report 2012-08-08 15:30:25 +10:00
Rohan Mitchell
9dd94eaf57 Weight shipping calculator treats variants without weight defined as zero weight 2012-08-08 15:29:47 +10:00
Rohan Mitchell
9f013f0e37 When loading distributors for sidebar, only show those that have active products on hand 2012-08-04 17:51:08 +10:00
Rohan Mitchell
f0ec3080e4 Remove instrumentation 2012-08-04 17:50:30 +10:00
Rohan Mitchell
245de4fe1a Add instrumentation to debug products not appearing on distributor view 2012-08-04 16:52:18 +10:00
Rohan Mitchell
9d33ef460c Max quantity field doesn't affect JS price calcs on products without variants 2012-08-04 16:51:43 +10:00
Rohan Mitchell
e0b8b8b4d4 Force precompile admin css and js 2012-08-04 10:27:15 +10:00
Rohan Mitchell
529de72f75 Force precompilation of store/all.css and store/all.js 2012-08-04 10:23:00 +10:00
Rohan Mitchell
b4f867924b Do not connect to db during asset precompile, fix heroku deploy to cedar 2012-08-04 10:12:06 +10:00
Rohan Mitchell
9d3afe80c6 split_products_by_distributor was not written with pre-pagination by searcher in mind, resulting in silently dropped products. Disable pagination at searcher. 2012-08-03 18:47:33 +10:00
Rohan Mitchell
28e75d6467 Fix add to cart JS for compatibility with group buy 2012-08-03 18:32:19 +10:00
Rohan Mitchell
b0fa05df0c Remove assets from git 2012-08-03 18:31:28 +10:00
Rohan Mitchell
f3ffba378a Add a product with variants to the cart with max quantity for a group buy 2012-08-03 18:05:45 +10:00
Rohan Mitchell
2d89640271 Instrument orders controller to debug populate_variant_attributes 2012-08-03 14:11:59 +10:00
Rohan Mitchell
e6ee6b5164 Itemwise shipping calculator returns 0 instead of nil when there are no items 2012-08-03 08:44:53 +10:00
Rohan Mitchell
768a170bb8 Fix with_products_on_hand query for server db compatibility 2012-08-03 08:21:45 +10:00
Rohan Mitchell
8834268970 Fix error on no shipping method defined 2012-08-02 17:45:22 +10:00
Rohan Mitchell
fe61b4aab1 Display shipping fee at all steps of the checkout process, not just after delivery method is chosen 2012-08-02 16:24:08 +10:00
Rohan Mitchell
a6c2490597 Enable auto-capture for spree_paypal_express 2012-08-02 15:45:31 +10:00
Rohan Mitchell
9110dc6414 Fix form local var naming for admin shared address form 2012-08-02 15:33:39 +10:00
Rohan Mitchell
77be0dd6eb Adding a product with a max quantity less than quantity results in max_quantity==quantity 2012-08-02 15:26:13 +10:00
Rohan Mitchell
40544eb27b Adding a product to cart that is not a group buy does not show max quantity field 2012-08-02 15:16:44 +10:00
Rohan Mitchell
306cb5b089 Add max quantity to order and distributor report 2012-08-02 15:07:34 +10:00
Rohan Mitchell
c46613877c Add max quantity field to add to cart form, add end-to-end test for max_quantity 2012-08-02 14:45:55 +10:00
Rohan Mitchell
2db2fbcade Change set_variant_attribute to set_variant_attributes, implement it on Order 2012-08-02 14:45:27 +10:00
Rohan Mitchell
ea05f05576 When adding a group buy product to the cart, set the max quantity on the order 2012-08-02 14:29:05 +10:00
Rohan Mitchell
361a87f580 Add group buy option to new/edit product in admin 2012-08-02 13:42:47 +10:00
Rohan Mitchell
330c62716c Add fields for group buy feature 2012-08-02 13:15:17 +10:00
Rohan Mitchell
63bf25293d Only show distributors in sidebar that have products in stock 2012-08-02 11:49:10 +10:00
Rohan Mitchell
93867682bb Only show distributors in sidebar that have products 2012-08-02 11:33:36 +10:00
Rohan Mitchell
7d5c158021 Install Bugsnag 2012-08-02 10:32:33 +10:00
Rohan Mitchell
06c6422591 Fix by-weight calculator to take line item quantity into account 2012-07-23 18:49:03 +10:00
Rohan Mitchell
5e04032797 Explicitly specify Spree 1.1.1, fix test regression in OrdersController 2012-07-23 18:48:30 +10:00
Andrew Spinks
f716176361 specify ruby version in Gemfile as per heroku requirement: https://devcenter.heroku.com/articles/ruby-versions 2012-07-20 20:40:55 +10:00
Andrew Spinks
2826f62497 Add extra details to the order report. 2012-07-20 20:25:53 +10:00
Andrew Spinks
7172fe0c87 added extra fields to order report. 2012-07-20 00:07:41 +10:00
Andrew Spinks
7e9a84087e cleaning up order report 2012-07-19 22:48:42 +10:00
Andrew Spinks
58e9cd3eeb fix distributor name in report 2012-07-15 21:00:10 +10:00
Andrew Spinks
54559c4a5f first cut at orders report. 2012-07-15 20:48:10 +10:00
Andrew Spinks
8f5b5e7ae4 allow shipping instructions to be provided. 2012-07-11 23:33:03 +10:00
Andrew Spinks
759ceae23f add distributor name to confirmation email 2012-07-11 23:20:59 +10:00
Andrew Spinks
32b37a1390 add padding to the second address line. 2012-07-11 22:45:57 +10:00
Andrew Spinks
0e43fcfaa1 adjust address formatting in confirmation email. 2012-07-11 22:25:42 +10:00
Andrew Spinks
6a27f8da32 update formatting of confirmation email. 2012-07-11 22:15:46 +10:00
Andrew Spinks
c24543c237 Add delivery details to confirmation email. 2012-07-11 22:07:18 +10:00
Andrew Spinks
44314ccb99 copied original spree confirmation mail 2012-07-11 21:35:07 +10:00
Andrew Spinks
9ad42a3966 adding precompiled assets 2012-07-11 20:46:20 +10:00
Andrew Spinks
d34e6570fc trying to get asset precompilation to work on deploy 2012-07-11 20:39:49 +10:00
Andrew Spinks
b5b35491cc allow asset precompile to work on new heroku instance 2012-07-07 10:17:33 +10:00
Rohan Mitchell
1e471e5e22 Name all form-containing partials with _form, tweak admin new product form 2012-07-02 16:28:31 +10:00
Rohan Mitchell
aa027f6e29 Display subtotal for delivery fees 2012-07-02 16:13:55 +10:00
74 changed files with 1186 additions and 221 deletions

31
.gitignore vendored
View File

@@ -10,48 +10,21 @@ log/*.log.lck
log/*.log.*
tmp/
.idea/*
solr/data/
solr/pids/
\#*
.#*
*~
*.~lock.*
.emacs.desktop
.DS_Store
.emacs.desktop.lock*
coverage
merged_coverage
upstream_coverage
true/
reports
*.tmproj
*tags
dump.rdb
bin/
spec/javascripts/generated/*
db/development_structure.sql
db/test_structure.sql
db/staging_structure.sql
db/production_structure.sql
db/bootstrap/*.sql
db/bootstrap/*.dump
db/bootstrap/*.bak
db/bootstrap/*.pgz
db/bootstrap/image_fixtures/*
db/bootstrap/image_fixtures/properties/*
db/backup
public/system
public/stylesheets
public/images
vendor/bundle
config/database.Tom-Meiers-MacBook-Pro.local.yml
public/spree
config/abr.yml
vendor/ruby
ey-cloud-recipes/db/bootstrap/*.dump
ey-cloud-recipes/db/bootstrap/*.pgz
ey-cloud-recipes/db/bootstrap/image_fixtures/*
ey-cloud-recipes/.idea/*
chromedriver.log
financial_reports/*.csv
NERD_tree*
spec/reference_images/*
public/search

23
Gemfile
View File

@@ -1,11 +1,12 @@
source 'http://rubygems.org'
ruby "1.9.3"
gem 'rails', '3.2.3'
gem 'rails', '3.2.8'
gem 'pg'
gem 'spree'
gem 'spree', :git => 'git://github.com/spree/spree.git', :branch => '1-1-stable'
gem 'spree_i18n', :git => 'git://github.com/spree/spree_i18n.git'
gem 'spree_paypal_express', :git => 'git://github.com/spree/spree_paypal_express.git'
gem 'spree_paypal_express', :git => 'git://github.com/spree/spree_paypal_express.git', :branch => '1-1-stable'
gem 'spree_last_address', :git => 'git://github.com/dancinglightning/spree-last-address.git'
@@ -14,10 +15,12 @@ gem 'spree_last_address', :git => 'git://github.com/dancinglightning/spree-last-
gem 'simple_form', :git => 'git://github.com/RohanM/simple_form.git'
gem 'unicorn'
gem 'bugsnag'
gem 'spree_heroku', :git => 'git://github.com/joneslee85/spree-heroku.git'
gem 'haml'
gem 'aws-s3'
gem 'andand'
gem 'truncate_html'
# Gems used only for assets and not required
# in production environments by default.
@@ -33,17 +36,6 @@ end
gem 'jquery-rails'
# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'
# Use unicorn as the web server
# gem 'unicorn'
# Deploy with Capistrano
# gem 'capistrano'
# To use debugger
# gem 'ruby-debug19', :require => 'ruby-debug'
group :test, :development do
# Pretty printed test output
@@ -55,6 +47,7 @@ group :test, :development do
gem 'capybara'
gem 'database_cleaner', '0.7.1', :require => false
gem 'spork', '~> 1.0rc'
gem 'pry'
gem 'pry-debugger'
gem 'awesome_print'
end

View File

@@ -21,6 +21,54 @@ GIT
aws-sdk (~> 1.3.4)
spree_core (>= 0.70.0)
GIT
remote: git://github.com/spree/spree.git
revision: d66ffac9088d0d5d0b0d146f305044ce619f0464
branch: 1-1-stable
specs:
spree (1.1.3)
spree_api (= 1.1.3)
spree_auth (= 1.1.3)
spree_cmd (= 1.1.3)
spree_core (= 1.1.3)
spree_dash (= 1.1.3)
spree_promo (= 1.1.3)
spree_sample (= 1.1.3)
spree_api (1.1.3)
rabl (= 0.6.5)
spree_auth (= 1.1.3)
spree_core (= 1.1.3)
spree_auth (1.1.3)
cancan (= 1.6.7)
devise (~> 2.0.0)
spree_core (= 1.1.3)
spree_cmd (1.1.3)
thor (>= 0.14.6)
spree_core (1.1.3)
activemerchant (= 1.28.0)
acts_as_list (= 0.1.4)
aws-sdk (~> 1.3.4)
deface (>= 0.9.0)
ffaker (~> 1.12.0)
highline (= 1.6.11)
jquery-rails (~> 2.0)
kaminari (= 0.13.0)
nested_set (= 1.7.0)
paperclip (~> 2.7)
rails (~> 3.2.8)
ransack (~> 0.6.0)
state_machine (= 1.1.2)
stringex (~> 1.3.2)
spree_dash (1.1.3)
httparty (~> 0.8.1)
spree_auth (= 1.1.3)
spree_core (= 1.1.3)
spree_promo (1.1.3)
spree_auth (= 1.1.3)
spree_core (= 1.1.3)
spree_sample (1.1.3)
spree_core (= 1.1.3)
GIT
remote: git://github.com/spree/spree_i18n.git
revision: a96bee02340e008e60549295a4f09e047fd2e628
@@ -31,50 +79,52 @@ GIT
GIT
remote: git://github.com/spree/spree_paypal_express.git
revision: d48f4649506e876b88244dcb4e5a86250e4ef8f0
revision: 2c61f1700ef853e3d4f39739793dc3308422e94b
branch: 1-1-stable
specs:
spree_paypal_express (1.1.0)
spree_auth (>= 1.0.0)
spree_core (>= 1.0.0)
GEM
remote: http://rubygems.org/
specs:
actionmailer (3.2.3)
actionpack (= 3.2.3)
actionmailer (3.2.8)
actionpack (= 3.2.8)
mail (~> 2.4.4)
actionpack (3.2.3)
activemodel (= 3.2.3)
activesupport (= 3.2.3)
actionpack (3.2.8)
activemodel (= 3.2.8)
activesupport (= 3.2.8)
builder (~> 3.0.0)
erubis (~> 2.7.0)
journey (~> 1.0.1)
journey (~> 1.0.4)
rack (~> 1.4.0)
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.1.2)
active_utils (1.0.3)
sprockets (~> 2.1.3)
active_utils (1.0.5)
activesupport (>= 2.3.11)
i18n
activemerchant (1.20.4)
activemerchant (1.28.0)
active_utils (>= 1.0.2)
activesupport (>= 2.3.11)
braintree (>= 2.0.0)
builder (>= 2.0.0)
i18n
json (>= 1.5.1)
money (<= 3.7.1)
activemodel (3.2.3)
activesupport (= 3.2.3)
money
nokogiri
activemodel (3.2.8)
activesupport (= 3.2.8)
builder (~> 3.0.0)
activerecord (3.2.3)
activemodel (= 3.2.3)
activesupport (= 3.2.3)
activerecord (3.2.8)
activemodel (= 3.2.8)
activesupport (= 3.2.8)
arel (~> 3.0.2)
tzinfo (~> 0.3.29)
activeresource (3.2.3)
activemodel (= 3.2.3)
activesupport (= 3.2.3)
activesupport (3.2.3)
activeresource (3.2.8)
activemodel (= 3.2.8)
activesupport (= 3.2.8)
activesupport (3.2.8)
i18n (~> 0.6)
multi_json (~> 1.0)
acts_as_list (0.1.4)
@@ -82,6 +132,7 @@ GEM
andand (1.3.3)
ansi (1.4.2)
arel (3.0.2)
awesome_print (1.0.2)
aws-s3 (0.6.3)
builder
mime-types
@@ -92,9 +143,10 @@ GEM
nokogiri (>= 1.4.4)
uuidtools (~> 2.1)
bcrypt-ruby (3.0.1)
braintree (2.16.0)
builder (>= 2.0.0)
builder (3.0.0)
bugsnag (1.1.2)
httparty (~> 0.8.3)
multi_json (~> 1.3.4)
builder (3.0.3)
cancan (1.6.7)
capybara (1.1.2)
mime-types (>= 1.16)
@@ -105,8 +157,8 @@ GEM
xpath (~> 0.1.4)
childprocess (0.3.2)
ffi (~> 1.0.6)
cocaine (0.2.1)
coderay (1.0.6)
cocaine (0.3.0)
coderay (1.0.7)
coffee-rails (3.2.2)
coffee-script (>= 2.2.0)
railties (~> 3.2.0)
@@ -114,7 +166,15 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.3.3)
columnize (0.3.6)
database_cleaner (0.7.1)
debugger (1.1.4)
columnize (>= 0.3.1)
debugger-linecache (~> 1.1.1)
debugger-ruby_core_source (~> 1.1.3)
debugger-linecache (1.1.2)
debugger-ruby_core_source (>= 1.1.1)
debugger-ruby_core_source (1.1.3)
deface (0.9.1)
nokogiri (~> 1.5.0)
rails (~> 3.1)
@@ -142,12 +202,12 @@ GEM
httparty (0.8.3)
multi_json (~> 1.0)
multi_xml
i18n (0.6.0)
i18n (0.6.1)
journey (1.0.4)
jquery-rails (2.0.2)
railties (>= 3.2.0, < 5.0)
jquery-rails (2.1.2)
railties (>= 3.1.0, < 5.0)
thor (~> 0.14)
json (1.7.3)
json (1.7.5)
kaminari (0.13.0)
actionpack (>= 3.0.0)
activesupport (>= 3.0.0)
@@ -160,16 +220,17 @@ GEM
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
method_source (0.7.1)
mime-types (1.18)
money (3.7.1)
method_source (0.8)
mime-types (1.19)
money (5.0.0)
i18n (~> 0.4)
json
multi_json (1.3.6)
multi_xml (0.5.1)
nested_set (1.7.0)
activerecord (>= 3.0.0)
railties (>= 3.0.0)
nokogiri (1.5.3)
nokogiri (1.5.5)
orm_adapter (0.0.7)
paperclip (2.7.0)
activerecord (>= 2.3.0)
@@ -180,10 +241,13 @@ GEM
polyamorous (0.5.0)
activerecord (~> 3.0)
polyglot (0.3.3)
pry (0.9.9.6)
pry (0.9.10)
coderay (~> 1.0.5)
method_source (~> 0.7.1)
slop (>= 2.4.4, < 3)
method_source (~> 0.8)
slop (~> 3.3.1)
pry-debugger (0.2.0)
debugger (~> 1.1.3)
pry (~> 0.9.9)
rabl (0.6.5)
activesupport (>= 2.3.14)
multi_json (~> 1.0)
@@ -194,21 +258,21 @@ GEM
rack
rack-test (0.6.1)
rack (>= 1.0)
rails (3.2.3)
actionmailer (= 3.2.3)
actionpack (= 3.2.3)
activerecord (= 3.2.3)
activeresource (= 3.2.3)
activesupport (= 3.2.3)
rails (3.2.8)
actionmailer (= 3.2.8)
actionpack (= 3.2.8)
activerecord (= 3.2.8)
activeresource (= 3.2.8)
activesupport (= 3.2.8)
bundler (~> 1.0)
railties (= 3.2.3)
railties (3.2.3)
actionpack (= 3.2.3)
activesupport (= 3.2.3)
railties (= 3.2.8)
railties (3.2.8)
actionpack (= 3.2.8)
activesupport (= 3.2.8)
rack-ssl (~> 1.3.2)
rake (>= 0.8.7)
rdoc (~> 3.4)
thor (~> 0.14.6)
thor (>= 0.14.6, < 2.0)
raindrops (0.9.0)
rake (0.9.2.2)
ransack (0.6.0)
@@ -244,49 +308,8 @@ GEM
rubyzip
shoulda-matchers (1.1.0)
activesupport (>= 3.0.0)
slop (2.4.4)
slop (3.3.3)
spork (1.0.0rc3)
spree (1.1.1)
spree_api (= 1.1.1)
spree_auth (= 1.1.1)
spree_cmd (= 1.1.1)
spree_core (= 1.1.1)
spree_dash (= 1.1.1)
spree_promo (= 1.1.1)
spree_sample (= 1.1.1)
spree_api (1.1.1)
rabl (= 0.6.5)
spree_auth (= 1.1.1)
spree_core (= 1.1.1)
spree_auth (1.1.1)
cancan (= 1.6.7)
devise (~> 2.0.0)
spree_core (= 1.1.1)
spree_cmd (1.1.1)
spree_core (1.1.1)
activemerchant (= 1.20.4)
acts_as_list (= 0.1.4)
aws-sdk (~> 1.3.4)
deface (>= 0.8.0)
ffaker (~> 1.12.0)
highline (= 1.6.11)
jquery-rails (~> 2.0.0)
kaminari (>= 0.13.0)
nested_set (= 1.7.0)
paperclip (~> 2.7)
rails (>= 3.2.2, <= 3.2.3)
ransack (~> 0.6.0)
state_machine (= 1.1.2)
stringex (~> 1.3.2)
spree_dash (1.1.1)
httparty (~> 0.8.1)
spree_auth (= 1.1.1)
spree_core (= 1.1.1)
spree_promo (1.1.1)
spree_auth (= 1.1.1)
spree_core (= 1.1.1)
spree_sample (1.1.1)
spree_core (= 1.1.1)
sprockets (2.1.3)
hike (~> 1.2)
rack (~> 1.0)
@@ -295,11 +318,12 @@ GEM
stringex (1.3.3)
therubyracer (0.10.1)
libv8 (~> 3.3.10)
thor (0.14.6)
thor (0.16.0)
tilt (1.3.3)
treetop (1.4.10)
polyglot
polyglot (>= 0.3.1)
truncate_html (0.5.5)
turn (0.8.3)
ansi
tzinfo (0.3.33)
@@ -310,7 +334,7 @@ GEM
kgio (~> 2.6)
rack
raindrops (~> 0.7)
uuidtools (2.1.2)
uuidtools (2.1.3)
warden (1.1.1)
rack (>= 1.0)
xml-simple (1.1.1)
@@ -322,7 +346,9 @@ PLATFORMS
DEPENDENCIES
andand
awesome_print
aws-s3
bugsnag
capybara
coffee-rails (~> 3.2.1)
database_cleaner (= 0.7.1)
@@ -331,19 +357,20 @@ DEPENDENCIES
haml
jquery-rails
pg
pry
rails (= 3.2.3)
pry-debugger
rails (= 3.2.8)
rspec-rails
sass-rails (~> 3.2.3)
shoulda-matchers
simple_form!
spork (~> 1.0rc)
spree
spree!
spree_heroku!
spree_i18n!
spree_last_address!
spree_paypal_express!
therubyracer
truncate_html
turn (~> 0.8.3)
uglifier (>= 1.0.3)
unicorn

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

BIN
app/assets/images/logo.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

BIN
app/assets/images/store/cart.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 479 B

View File

@@ -5,6 +5,8 @@
// the compiled file.
//
//= require jquery
//= require jquery_ujs
//= require admin/spree_core
//= require admin/spree_auth
//= require admin/spree_promo

View File

@@ -9,7 +9,7 @@ $(document).ready(function() {
$("#quantity").change();
// Product page with master price only
$(".add-to-cart input.title:not(#quantity)").change(products_update_price_without_variant).change();
$(".add-to-cart input.title:not(#quantity):not(.max_quantity)").change(products_update_price_without_variant).change();
});
@@ -28,7 +28,7 @@ function products_update_price_without_variant() {
if(master_price == null) {
// Store off the master price
master_price = $("#product-price span.price").html();
master_price = master_price.substr(1, master_price.length-2);
master_price = master_price.substring(1);
$("#product-price span.price").data('master-price', master_price);
}

View File

@@ -0,0 +1,7 @@
#header #logo {
top: 10px;
}
#header h1 {
left: 275px;
}

View File

@@ -1,5 +1,23 @@
@import "screen";
a:hover {
color: lighten($link_text_color, 20) !important;
}
table {
tbody, tfoot {
tr {
&.alt, &.odd {
background-color: lighten($link_text_color, 75) !important;
}
}
}
}
#header #logo {
padding-top: 10px;
}
/* Style current distributor in main nav bar */
nav #main-nav-bar {
li {
@@ -147,6 +165,7 @@ ul.product-listing {
}
#empty-cart {
float: left;
margin-top: 15px !important;
p {
padding: 0;
@@ -174,4 +193,15 @@ ul.product-listing {
}
}
}
.subtotal {
width: 100%;
text-align: right;
text-transform: uppercase;
margin-top: 15px;
span.order-total {
@extend span.price;
}
}
}

View File

@@ -0,0 +1,58 @@
/*--------------------------------------*/
/* Colors
/*--------------------------------------*/
$c_green: #8dba53; /* Spree green */
$c_red: #e45353; /* Error red */
$layout_background_color: #FFFFFF;
$title_text_color: #404042;
$body_text_color: #404042;
$link_text_color: #006066;
$product_background_color: #FFFFFF;
$product_title_text_color: #404042;
$product_body_text_color: #404042;
$product_link_text_color: #BBBBBB;
/*--------------------------------------*/
/* Fonts import from remote
/*--------------------------------------*/
@import url(//fonts.googleapis.com/css?family=Ubuntu:400,700,400italic,700italic|&subset=latin,cyrillic,greek,greek-ext,latin-ext,cyrillic-ext);
/*--------------------------------------*/
/* Font families
/*--------------------------------------*/
$ff_base: 'Ubuntu', sans-serif;
/*--------------------------------------
| Font sizes
|--------------------------------------
|- Navigation
| */
$header_navigation_font_size: 14px;
$horizontal_navigation_font_size: 16px;
$main_navigation_header_font_size: 14px;
$main_navigation_font_size: 12px;
/*|------------------------------------
|- Product Listing
| */
$product_list_name_font_size: 12px;
$product_list_price_font_size: 16px;
$product_list_header_font_size: 20px;
$product_list_search_font_size: 14px;
/*|------------------------------------
|- Product Details
| */
$product_detail_name_font_size: 24px;
$product_detail_description_font_size: 12px;
$product_detail_price_font_size: 20px;
$product_detail_title_font_size: 14px;
/*|------------------------------------
|- Basic
| */
$heading_font_size: 24px;
$sub_heading_font_size: 14px;
$button_font_size: 12px;
$input_box_font_size: 13px;
$base_font_size: 12px;
$button_border_color: rgba(0, 138, 189, .75);

View File

@@ -6,7 +6,7 @@ class ApplicationController < ActionController::Base
private
def load_data_for_sidebar
@suppliers = Spree::Supplier.all
@distributors = Spree::Distributor.all
@distributors = Spree::Distributor.with_active_products_on_hand.by_name
end
end

View File

@@ -0,0 +1,37 @@
require 'csv'
require 'open_food_web/order_and_distributor_report'
Spree::Admin::ReportsController.class_eval do
Spree::Admin::ReportsController::AVAILABLE_REPORTS.merge!({:orders_and_distributors => {:name => "Orders And Distributors", :description => "Orders with distributor details"}})
def orders_and_distributors
params[:q] = {} unless params[:q]
if params[:q][:created_at_gt].blank?
params[:q][:created_at_gt] = Time.zone.now.beginning_of_month
else
params[:q][:created_at_gt] = Time.zone.parse(params[:q][:created_at_gt]).beginning_of_day rescue Time.zone.now.beginning_of_month
end
if params[:q] && !params[:q][:created_at_lt].blank?
params[:q][:created_at_lt] = Time.zone.parse(params[:q][:created_at_lt]).end_of_day rescue ""
end
params[:q][:meta_sort] ||= "created_at.desc"
@search = Spree::Order.complete.search(params[:q])
orders = @search.result
@report = OpenFoodWeb::OrderAndDistributorReport.new orders
if(!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 => "orders_and_distributors.csv"
end
end
end

View File

@@ -0,0 +1,28 @@
module Spree
module Admin
ShippingMethodsController.class_eval do
before_filter :do_not_destroy_referenced_shipping_methods, :only => :destroy
def do_not_destroy_referenced_shipping_methods
order = Order.where(:shipping_method_id => @object).first
if order
flash[:error] = "That shipping method cannot be deleted as it is referenced by an order: #{order.number}."
redirect_to collection_url and return
end
product_distribution = ProductDistribution.where(:shipping_method_id => @object).first
if product_distribution
p = product_distribution.product
flash[:error] = "That shipping method cannot be deleted as it is referenced by a product distribution: #{p.id} - #{p.name}."
redirect_to collection_url and return
end
line_item = LineItem.where(:shipping_method_id => @object).first
if line_item
flash[:error] = "That shipping method cannot be deleted as it is referenced by a line item in order: #{line_item.order.number}."
redirect_to collection_url and return
end
end
end
end
end

View File

@@ -0,0 +1,25 @@
module Spree
BaseController.class_eval do
# Override definition in spree/auth/app/controllers/spree/base_controller_decorator.rb
# Do not attempt to merge incomplete and current orders when they have differing distributors
# Instead, destroy the incomplete orders, otherwise they are restored after checkout, causing much confusion
def set_current_order
if current_user
if current_user.respond_to?(:last_incomplete_order)
last_incomplete_order = current_user.last_incomplete_order
if session[:order_id].nil? && last_incomplete_order
session[:order_id] = last_incomplete_order.id
elsif current_order && last_incomplete_order && current_order != last_incomplete_order
if current_order.distributor.nil? || current_order.distributor == last_incomplete_order.distributor
current_order.set_distributor! last_incomplete_order.distributor if current_order.distributor.nil?
current_order.merge!(last_incomplete_order)
else
last_incomplete_order.destroy
end
end
end
end
end
end
end

View File

@@ -1,20 +1,38 @@
Spree::OrdersController.class_eval do
before_filter :populate_order_distributor, :only => :populate
before_filter :populate_order_distributor, :only => :populate
after_filter :populate_variant_attributes, :only => :populate
def populate_order_distributor
@distributor = params.key?(:distributor_id) ? Spree::Distributor.find(params[:distributor_id]) : nil
@distributor = params[:distributor_id].present? ? Spree::Distributor.find(params[:distributor_id]) : nil
if populate_valid? @distributor
order = current_order(true)
order.distributor = @distributor
order.save!
order.set_distributor! @distributor
else
redirect_to cart_path
flash[:error] = "Please choose a distributor for this order." if @distributor.nil?
redirect_populate_to_first_product
end
end
def populate_variant_attributes
if params.key? :variant_attributes
params[:variant_attributes].each do |variant_id, attributes|
@order.set_variant_attributes(Spree::Variant.find(variant_id), attributes)
end
end
if params.key? :quantity
params[:products].each do |product_id, variant_id|
max_quantity = params[:max_quantity].to_i
@order.set_variant_attributes(Spree::Variant.find(variant_id), {:max_quantity => max_quantity})
end
end
end
private
def populate_valid? distributor
# -- Distributor must be specified
return false if distributor.nil?
@@ -38,4 +56,14 @@ Spree::OrdersController.class_eval do
true
end
def redirect_populate_to_first_product
product = if params[:products].present?
Spree::Product.find(params[:products].keys.first)
else
Spree::Variant.find(params[:variants].keys.first).product
end
redirect_to product
end
end

View File

@@ -1,5 +1,7 @@
module Spree
class SuppliersController < BaseController
helper 'spree/products'
def show
options = {:supplier_id => params[:id]}
options.merge(params.reject { |k,v| k == :id })

View File

@@ -0,0 +1,9 @@
module Spree
module OrdersHelper
def order_delivery_fee_subtotal(order, options={})
options.reverse_merge! :format_as_currency => true
amount = order.line_items.map { |li| li.itemwise_shipping_cost }.sum
options.delete(:format_as_currency) ? number_to_currency(amount) : amount
end
end
end

View File

@@ -7,7 +7,7 @@ module OpenFoodWeb
def compute(object)
# Given an order, sum the shipping on each individual item
object.line_items.map { |li| li.itemwise_shipping_cost }.inject(:+)
object.line_items.map { |li| li.itemwise_shipping_cost }.inject(:+) || 0
end
end
end

View File

@@ -8,7 +8,7 @@ module OpenFoodWeb
end
def compute(object)
total_weight = object.line_items.inject(0) { |sum, li| sum+li.variant.weight }
total_weight = object.line_items.inject(0) { |sum, li| sum + ((li.variant.andand.weight || 0) * li.quantity) }
total_weight * self.preferred_per_kg
end
end

View File

@@ -13,6 +13,7 @@ module Spree
validates_associated :pickup_address
scope :by_name, order('name')
scope :with_active_products_on_hand, lambda { joins(:products).where('spree_products.deleted_at IS NULL AND spree_products.available_on <= ? AND spree_products.count_on_hand > 0', Time.now).select('distinct(distributors.*)') }
after_initialize :initialize_country
before_validation :set_unused_address_fields

View File

@@ -1,10 +1,20 @@
Spree::LineItem.class_eval do
def shipping_method
self.product.shipping_method_for_distributor(self.order.distributor)
end
belongs_to :shipping_method
attr_accessible :max_quantity
before_create :set_itemwise_shipping_method
def itemwise_shipping_cost
order = OpenStruct.new :line_items => [self]
shipping_method.compute_amount(order)
end
private
def set_itemwise_shipping_method
self.shipping_method = self.product.shipping_method_for_distributor(self.order.distributor)
end
end

View File

@@ -1,6 +1,9 @@
Spree::Order.class_eval do
belongs_to :distributor
before_validation :shipping_address_from_distributor
after_create :set_default_shipping_method
def can_change_distributor?
# Distributor may not be changed once an item has been added to the cart/order
line_items.empty?
@@ -11,15 +14,47 @@ Spree::Order.class_eval do
super(distributor)
end
def set_distributor!(distributor)
self.distributor = distributor
save!
end
def can_add_product_to_cart?(product)
can_change_distributor? || product.distributors.include?(distributor)
end
def set_variant_attributes(variant, attributes)
line_item = contains?(variant)
if attributes.key?(:max_quantity) && attributes[:max_quantity].to_i < line_item.quantity
attributes[:max_quantity] = line_item.quantity
end
line_item.assign_attributes(attributes)
line_item.save!
end
before_validation :shipping_address_from_distributor
private
# On creation of the order (when the first item is added to the user's cart), set the
# shipping method to the first one available and create a shipment.
# order.create_shipment! creates an adjustment for the shipping cost on the order,
# which means that the customer can see their shipping cost at every step of the
# checkout process, not just after the delivery step.
# This is based on the assumption that there's only one shipping method visible to the user,
# which is a method using the itemwise shipping calculator.
def set_default_shipping_method
self.shipping_method = Spree::ShippingMethod.where("display_on != 'back_end'").first
if self.shipping_method
self.save!
self.create_shipment!
else
raise 'No default shipping method found'
end
end
def shipping_address_from_distributor
if distributor
self.ship_address = distributor.pickup_address.clone

View File

@@ -6,7 +6,7 @@ Spree::Product.class_eval do
accepts_nested_attributes_for :product_distributions, :allow_destroy => true
attr_accessible :supplier_id, :distributor_ids, :product_distributions_attributes
attr_accessible :supplier_id, :distributor_ids, :product_distributions_attributes, :group_buy
validates_presence_of :supplier

View File

@@ -1,9 +1,9 @@
Deface::Override.new(:virtual_path => "spree/admin/products/_form",
:insert_bottom => "[data-hook='admin_product_form_additional_fields']",
:partial => "spree/admin/products/distributors",
:insert_bottom => "[data-hook='admin_product_form_additional_fields']",
:partial => "spree/admin/products/distributors_form",
:name => "distributors")
Deface::Override.new(:virtual_path => "spree/admin/products/new",
:insert_bottom => ".left",
:partial => "spree/admin/products/distributors",
:insert_after => "[data-hook='new_product_attrs']",
:partial => "spree/admin/products/distributors_form",
:name => "distributors")

View File

@@ -0,0 +1,9 @@
Deface::Override.new(:virtual_path => "spree/admin/products/_form",
:insert_top => "[data-hook='admin_product_form_right']",
:partial => "spree/admin/products/group_buy_form",
:name => "group buy")
Deface::Override.new(:virtual_path => "spree/admin/products/new",
:insert_bottom => ".right",
:partial => "spree/admin/products/group_buy_form",
:name => "group buy")

View File

@@ -1,9 +1,9 @@
Deface::Override.new(:virtual_path => "spree/admin/products/_form",
:insert_top => "[data-hook='admin_product_form_right']",
:partial => "spree/admin/products/supplier",
:name => "supplier")
Deface::Override.new(:virtual_path => "spree/admin/products/_form",
:insert_top => "[data-hook='admin_product_form_right']",
:partial => "spree/admin/products/supplier_form",
:name => "supplier")
Deface::Override.new(:virtual_path => "spree/admin/products/new",
:insert_bottom => ".left",
:partial => "spree/admin/products/supplier",
:name => "supplier")
:insert_bottom => ".right",
:partial => "spree/admin/products/supplier_form",
:name => "supplier")

View File

@@ -0,0 +1,4 @@
Deface::Override.new(:virtual_path => "spree/orders/_line_item",
:replace => "[data-hook='cart_item_description']",
:partial => "spree/orders/cart_item_description",
:name => "cart_item_description")

View File

@@ -33,4 +33,4 @@
%td Regular pickup times:
%td= f.text_field :pickup_times
= f.fields_for :pickup_address do |pickup_address_form|
= render 'spree/admin/shared/address_form', :form => pickup_address_form
= render 'spree/admin/shared/address_form', :f => pickup_address_form

View File

@@ -0,0 +1,7 @@
= f.field_container :group_buy do
= f.label :group_buy, 'Group buy?'
%br
= f.radio_button :group_buy, '1', :checked => f.object.group_buy
= f.label :group_buy_1, 'Yes'
= f.radio_button :group_buy, '0', :checked => !f.object.group_buy
= f.label :group_buy_0, 'No'

View File

@@ -0,0 +1,32 @@
= form_for @search, :url => spree.orders_and_distributors_admin_reports_path do |s|
= label_tag nil, t(:date_range)
%br
.date-range-filter
%div{"class" => "left sub-field"}
= s.text_field :created_at_gt, :class => 'datepicker'
%br
= label_tag nil, t(:start), :class => 'sub'
%div{"class" => "right sub-field"}
= s.text_field :created_at_lt, :class => 'datepicker'
%br
= label_tag nil, t(:stop)
= check_box_tag :csv
= label_tag :csv, "Download as csv"
%br
= button t(:search)
%br
%br
%table#listing_orders.index
%thead
%tr{'data-hook' => "orders_header"}
- @report.header.each do |heading|
%th=heading
%tbody
- @report.table.each do |row|
%tr
- row.each do |column|
%td= column
- if @report.table.empty?
%tr
%td{:colspan => "2"}= t(:none)

View File

@@ -1,18 +1,18 @@
%tr{"data-hook" => "address1"}
%td Address:
%td= form.text_field :address1
%td= f.text_field :address1
%tr{"data-hook" => "address2"}
%td Address (cont.):
%td= form.text_field :address2
%td= f.text_field :address2
%tr{"data-hook" => "city"}
%td City:
%td= form.text_field :city
%td= f.text_field :city
%tr{"data-hook" => "zipcode"}
%td Postcode:
%td= form.text_field :zipcode
%td= f.text_field :zipcode
%tr{"data-hook" => "country"}
%td Country:
%td= form.collection_select(:country_id, available_countries, :id, :name)
%td= f.collection_select(:country_id, available_countries, :id, :name)
%tr{"data-hook" => "state"}
%td State:
%td= form.collection_select(:state_id, form.object.country.states, :id, :name)
%td= f.collection_select(:state_id, f.object.country.states, :id, :name)

View File

@@ -0,0 +1,6 @@
<%= tab :overview, :route => :admin %>
<%= tab :orders, :payments, :creditcard_payments, :shipments, :creditcards, :return_authorizations, {:url => admin_orders_path('q[s]' => 'completed_at desc')} %>
<%= tab :products , :option_types, :properties, :prototypes, :variants, :product_properties, :taxons %>
<%= tab :reports %>
<%= tab :configurations, :general_settings, :mail_methods, :tax_categories, :zones, :states, :payment_methods, :inventory_settings, :taxonomies, :shipping_methods, :trackers, :label => 'configuration' %>
<%= tab :users %>

View File

@@ -6,7 +6,7 @@
%td Description:
%td= f.text_field :description
= f.fields_for :address do |address_form|
= render 'spree/admin/shared/address_form', :form => address_form
= render 'spree/admin/shared/address_form', :f => address_form
%tr{'data-hook' => "email"}
%td Email:
%td= f.text_field :email

View File

@@ -0,0 +1,33 @@
Dear Customer,
Please review and retain the following order information for your records.
============================================================
Order Summary
============================================================
<% @order.line_items.each do |item| %>
<%= item.variant.sku %> <%= raw(item.variant.product.name) %> <%= raw(item.variant.options_text) -%> (<%=item.quantity%>) @ <%= number_to_currency item.price %> = <%= number_to_currency(item.price * item.quantity) %>
<% end %>
============================================================
Subtotal: <%= number_to_currency @order.item_total %>
<% @order.adjustments.each do |adjustment| %>
<%= raw(adjustment.label) %> <%= number_to_currency(adjustment.amount) %>
<% end %>
Order Total: <%= number_to_currency(@order.total) %>
============================================================
Delivery Details
============================================================
Address:
<%= @order.distributor.name %>
<% address = @order.distributor.pickup_address %>
<%= address.address1 %> <%= ",\n #{address.address2}" unless address.address2.blank? %>
<%= [address.city, address.state_text, address.zipcode, address.country.name].compact.join ', ' %>
Colection time:
<%= @order.distributor.next_collection_at %>
Contact:
<%= @order.distributor.contact %>
<%= "Phone: #{@order.distributor.phone}" %>
<%= "Email: #{@order.distributor.email}" %>
Thank you for your business.

View File

@@ -0,0 +1,8 @@
%td{'data-hook' => "cart_item_description"}
%h4= link_to variant.product.name, product_path(variant.product)
= variant.options_text
- if @order.insufficient_stock_lines.include? line_item
%span.out-of-stock
= variant.in_stock? ? t(:insufficient_stock, :on_hand => variant.on_hand) : t(:out_of_stock)
%br/
= truncate_html(variant.product.description, :length => 100, :omission => "...")

View File

@@ -15,3 +15,9 @@
%h4= link_to line_item.product.name, product_path(line_item.product)
%td.item-shipping-method= line_item.shipping_method.name
%td.item-shipping-cost= number_to_currency line_item.itemwise_shipping_cost
.subtotal{'data-hook' => 'delivery_fees_subtotal'}
%h5
Shipping total
\:
%span.order-total= order_delivery_fee_subtotal(@order)

View File

@@ -4,9 +4,17 @@
#subtotal{'data-hook' => ""}
%h5
= t(:subtotal)
Item total
\:
%span.order-total= order_subtotal(@order)
%span.order-total.item-total= number_to_currency @order.item_total
%h5
Shipping total
\:
%span.order-total.shipping-total= order_delivery_fee_subtotal(@order)
%h4
Total
\:
%span.order-total.grand-total= order_subtotal(@order)
.links{'data-hook' => "cart_buttons"}
= button_tag :class => 'primary', :id => 'update-button' do

View File

@@ -11,10 +11,13 @@
- else
%p Quantity
= number_field_tag (@product.has_variants? ? :quantity : "variants[#{@product.master.id}]"), 1, :class => 'title', :in => 1..@product.on_hand
- if @product.group_buy
%p Max quantity
= number_field_tag (@product.has_variants? ? :max_quantity : "variant_attributes[#{@product.master.id}][max_quantity]"), 1, :class => 'title max_quantity', :in => 1..@product.on_hand
- order = current_order(false)
- if order.nil? || order.can_change_distributor?
%p Distributor
= select_tag "distributor_id", options_from_collection_for_select(@product.distributors, "id", "name", current_distributor.andand.id)
= select_tag "distributor_id", options_from_collection_for_select([Spree::Distributor.new]+@product.distributors, "id", "name", current_distributor.andand.id)
- else
= hidden_field_tag "distributor_id", order.distributor.id
.distributor-fixed= "Your distributor for this order is #{order.distributor.name}"

View File

@@ -64,5 +64,8 @@ module Openfoodweb
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
config.assets.initialize_on_precompile = false
config.assets.precompile += ['store/all.css', 'store/all.js', 'admin/all.css', 'admin/*.js', 'admin/**/*.js']
end
end

View File

@@ -0,0 +1,3 @@
Bugsnag.configure do |config|
config.api_key = "937a200f492fad600b4cc29dddda5f71"
end

View File

@@ -12,11 +12,17 @@ require 'open_food_web/searcher'
Spree.config do |config|
config.site_name = "Open Food Web"
config.logo = 'logo.jpg'
config.admin_interface_logo = 'logo.jpg'
# config.shipping_instructions = true
config.shipping_instructions = true
config.checkout_zone = 'Australia'
config.address_requires_state = true
config.default_country_id = 12 # This should be Australia, see: spree/core/db/default/spree/countries.yml
config.searcher_class = OpenFoodWeb::Searcher
# -- spree_paypal_express
# Auto-capture payments. Without this option, payments must be manually captured in the paypal interface.
config.auto_capture = true
end

View File

@@ -17,4 +17,6 @@ Spree::Core::Engine.routes.prepend do
end
resources :suppliers
end
match '/admin/reports/orders_and_distributors' => 'admin/reports#orders_and_distributors', :as => "orders_and_distributors_admin_reports", :via => [:get, :post]
end

View File

@@ -0,0 +1,6 @@
class AddGroupBuyFields < ActiveRecord::Migration
def change
add_column :spree_products, :group_buy, :boolean
add_column :spree_line_items, :max_quantity, :integer
end
end

View File

@@ -0,0 +1,10 @@
# This migration comes from spree (originally 20120523061241)
class ConvertSalesTaxToDefaultTax < ActiveRecord::Migration
def up
execute "UPDATE spree_calculators SET type='Spree::Calculator::DefaultTax' WHERE type='Spree::Calculator::SalesTax'"
end
def down
execute "UPDATE spree_calculators SET type='Spree::Calculator::SalesTax' WHERE type='Spree::Calculator::DefaultTax'"
end
end

View File

@@ -0,0 +1,6 @@
# This migration comes from spree (originally 20120604030249)
class AddDeletedAtToSpreeShippingMethods < ActiveRecord::Migration
def change
add_column :spree_shipping_methods, :deleted_at, :datetime
end
end

View File

@@ -0,0 +1,11 @@
# This migration comes from spree (originally 20120605211305)
class MakeUsersEmailIndexUnique < ActiveRecord::Migration
def up
add_index "spree_users", ["email"], :name => "email_idx_unique", :unique => true
end
def down
remove_index "spree_users", :name => "email_idx_unique"
add_index "spree_users", ["email"], :name => "email_idx_unique"
end
end

View File

@@ -0,0 +1,15 @@
# This migration comes from spree (originally 20120712172620)
class AddCounterCacheToZoneMembers < ActiveRecord::Migration
def up
add_column :spree_zones, :zone_members_count, :integer, :default => 0
Spree::Zone.reset_column_information
Spree::Zone.find(:all).each do |zone|
Spree::Zone.update_counters zone.id, :zone_members_count => zone.zone_members.length
end
end
def down
remove_column :spree_zones, :zone_members_count
end
end

View File

@@ -0,0 +1,20 @@
class AddShippingMethodToLineItems < ActiveRecord::Migration
def up
add_column :spree_line_items, :shipping_method_id, :integer
Spree::LineItem.all.each do |li|
begin
shipping_method = li.product.shipping_method_for_distributor(li.order.distributor)
rescue ArgumentError
shipping_method = Spree::ShippingMethod.find_by_name 'Producer Delivery'
say "Line item #{li.id} does not have a valid shipping method, setting to '#{shipping_method.name}'"
end
Spree::LineItem.update_all("shipping_method_id = #{shipping_method.id}", "id = #{li.id}")
end
end
def down
remove_column :spree_line_items, :shipping_method_id
end
end

View File

@@ -0,0 +1,10 @@
class PopulateOrderDefaultShippingMethod < ActiveRecord::Migration
def up
Spree::Order.where(shipping_method_id: nil).each do |order|
order.send(:set_default_shipping_method)
end
end
def down
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20120702020402) do
ActiveRecord::Schema.define(:version => 20121005015852) do
create_table "distributors", :force => true do |t|
t.string "name"
@@ -133,7 +133,7 @@ ActiveRecord::Schema.define(:version => 20120702020402) do
t.integer "numcode"
end
create_table "spree_creditcards", :force => true do |t|
create_table "spree_credit_cards", :force => true do |t|
t.string "month"
t.string "year"
t.string "cc_type"
@@ -144,8 +144,8 @@ ActiveRecord::Schema.define(:version => 20120702020402) do
t.string "start_year"
t.string "issue_number"
t.integer "address_id"
t.datetime "created_at"
t.datetime "updated_at"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
t.string "gateway_customer_profile_id"
t.string "gateway_payment_profile_id"
end
@@ -180,10 +180,12 @@ ActiveRecord::Schema.define(:version => 20120702020402) do
create_table "spree_line_items", :force => true do |t|
t.integer "order_id"
t.integer "variant_id"
t.integer "quantity", :null => false
t.decimal "price", :precision => 8, :scale => 2, :null => false
t.integer "quantity", :null => false
t.decimal "price", :precision => 8, :scale => 2, :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.integer "max_quantity"
t.integer "shipping_method_id"
end
add_index "spree_line_items", ["order_id"], :name => "index_line_items_on_order_id"
@@ -366,6 +368,7 @@ ActiveRecord::Schema.define(:version => 20120702020402) do
t.datetime "updated_at"
t.integer "count_on_hand", :default => 0, :null => false
t.integer "supplier_id"
t.boolean "group_buy"
end
add_index "spree_products", ["available_on"], :name => "index_products_on_available_on"
@@ -492,6 +495,7 @@ ActiveRecord::Schema.define(:version => 20120702020402) do
t.boolean "match_none"
t.boolean "match_all"
t.boolean "match_one"
t.datetime "deleted_at"
end
create_table "spree_skrill_transactions", :force => true do |t|
@@ -613,6 +617,7 @@ ActiveRecord::Schema.define(:version => 20120702020402) do
t.datetime "reset_password_sent_at"
end
add_index "spree_users", ["email"], :name => "email_idx_unique", :unique => true
add_index "spree_users", ["persistence_token"], :name => "index_users_on_persistence_token"
create_table "spree_variants", :force => true do |t|
@@ -645,7 +650,8 @@ ActiveRecord::Schema.define(:version => 20120702020402) do
t.string "description"
t.datetime "created_at"
t.datetime "updated_at"
t.boolean "default_tax", :default => false
t.boolean "default_tax", :default => false
t.integer "zone_members_count", :default => 0
end
create_table "suppliers", :force => true do |t|

View File

@@ -0,0 +1,31 @@
module OpenFoodWeb
class OrderAndDistributorReport
def initialize orders
@orders = orders
end
def header
["Order date", "Order Id",
"Customer Name","Customer Email", "Customer Phone", "Customer City",
"SKU", "Item name", "Variant", "Quantity", "Max Quantity", "Cost", "Shipping cost",
"Payment method",
"Distributor", "Distributor address", "Distributor city", "Distributor postcode", "Shipping instructions"]
end
def table
order_and_distributor_details = []
@orders.each do |order|
order.line_items.each do |line_item|
order_and_distributor_details << [order.created_at, order.id,
order.bill_address.full_name, order.email, order.bill_address.phone, order.bill_address.city,
line_item.product.sku, line_item.product.name, line_item.variant.options_text, line_item.quantity, line_item.max_quantity, line_item.price * line_item.quantity, line_item.itemwise_shipping_cost,
order.payments.first.payment_method.andand.name,
order.distributor.andand.name, order.distributor.pickup_address.address1, order.distributor.pickup_address.city, order.distributor.pickup_address.zipcode, order.special_instructions ]
end
end
order_and_distributor_details
end
end
end

View File

@@ -3,6 +3,14 @@ require 'spree/core/search/base'
module OpenFoodWeb
class Searcher < Spree::Core::Search::Base
# Do not perform pagination
def retrieve_products
@products_scope = get_base_scope
curr_page = page || 1
@products = @products_scope.includes([:master])
end
def get_base_scope
base_scope = super

View File

@@ -4,9 +4,11 @@ require 'spree/core/current_order'
describe Spree::DistributorsController do
include Spree::Core::CurrentOrder
before do
before :each do
stub!(:before_save_new_order)
stub!(:after_save_new_order)
create(:itemwise_shipping_method)
end
@@ -40,9 +42,10 @@ describe Spree::DistributorsController do
d2 = create(:distributor)
p = create(:product, :distributors => [d1])
o = current_order(true)
o.distributor = d1
o.add_variant(p.master, 1)
o.save!
o.add_variant(p.master, 1)
# When I attempt to select a distributor
spree_get :select, :id => d2.id
@@ -58,8 +61,8 @@ describe Spree::DistributorsController do
p = create(:product, :distributors => [d])
o = current_order(true)
o.distributor = d
o.add_variant(p.master, 1)
o.save!
o.add_variant(p.master, 1)
# When I attempt to deselect the distributor
spree_get :deselect

View File

@@ -25,4 +25,39 @@ describe Spree::HomeController do
assigns(:products_local).should == [p1]
assigns(:products_remote).should == [p2]
end
context "BaseController: merging incomplete orders" do
it "does not attempt to merge incomplete and current orders when they have differing distributors" do
incomplete_order = double(:order, distributor: 1)
current_order = double(:order, distributor: 2)
user = double(:user, last_incomplete_order: incomplete_order)
controller.stub(:current_user).and_return(user)
controller.stub(:current_order).and_return(current_order)
incomplete_order.should_receive(:destroy)
incomplete_order.should_receive(:merge!).never
current_order.should_receive(:merge!).never
session[:order_id] = 123
spree_get :index
end
it "sets the distributor when the target order has no distributor" do
incomplete_order = double(:order, distributor: 1)
current_order = double(:order, distributor: nil)
user = double(:user, last_incomplete_order: incomplete_order)
controller.stub(:current_user).and_return(user)
controller.stub(:current_order).and_return(current_order)
current_order.should_receive(:set_distributor!).with(1)
current_order.should_receive(:merge!)
session[:order_id] = 123
spree_get :index
end
end
end

View File

@@ -15,7 +15,7 @@ describe Spree::OrdersController do
p = create(:product)
expect do
spree_put :populate, :variants => {p.id => 1}
spree_post :populate, :variants => {p.master.id => 1}
end.to change(Spree::LineItem, :count).by(0)
end
@@ -25,7 +25,7 @@ describe Spree::OrdersController do
p = create(:product, :distributors => [distributor_product])
expect do
spree_put :populate, :variants => {p.id => 1}, :distributor_id => distributor_no_product.id
spree_post :populate, :variants => {p.master.id => 1}, :distributor_id => distributor_no_product.id
end.to change(Spree::LineItem, :count).by(0)
end
@@ -39,7 +39,7 @@ describe Spree::OrdersController do
order.save!
expect do
spree_put :populate, :variants => {p.id => 1}, :distributor_id => distributor_product.id
spree_post :populate, :variants => {p.master.id => 1}, :distributor_id => distributor_product.id
end.to change(Spree::LineItem, :count).by(1)
order.reload.distributor.should == distributor_product
@@ -51,7 +51,7 @@ describe Spree::OrdersController do
p = create(:product, :distributors => [d])
# When we add the product to our cart
spree_put :populate, :variants => {p.id => 1}, :distributor_id => d.id
spree_post :populate, :variants => {p.master.id => 1}, :distributor_id => d.id
# Then our order should have its distributor set to the chosen distributor
current_order(false).distributor.should == d
@@ -65,7 +65,7 @@ describe Spree::OrdersController do
@product = create(:product, :distributors => [@distributor])
# And the product is in the cart
spree_put :populate, :variants => {@product.id => 1}, :distributor_id => @distributor.id
spree_post :populate, :variants => {@product.master.id => 1}, :distributor_id => @distributor.id
current_order(false).line_items.reload.map { |li| li.product }.should == [@product]
current_order(false).distributor.reload.should == @distributor
end
@@ -76,7 +76,7 @@ describe Spree::OrdersController do
p2 = create(:product, :distributors => [d2])
# When I attempt to add the product to the cart
spree_put :populate, :variants => {p2.id => 1}, :distributor_id => d2.id
spree_post :populate, :variants => {p2.master.id => 1}, :distributor_id => d2.id
# Then the product should not be added to the cart
current_order(false).line_items.reload.map { |li| li.product }.should == [@product]
@@ -89,7 +89,7 @@ describe Spree::OrdersController do
p2 = create(:product, :distributors => [d2])
# When I attempt to add the product to the cart with a fake distributor_id
spree_put :populate, :variants => {p2.id => 1}, :distributor_id => @distributor.id
spree_post :populate, :variants => {p2.master.id => 1}, :distributor_id => @distributor.id
# Then the product should not be added to the cart
current_order(false).line_items.reload.map { |li| li.product }.should == [@product]
@@ -102,11 +102,26 @@ describe Spree::OrdersController do
p2 = create(:product, :distributors => [@distributor, d2])
# When I attempt to add the product to the cart with the alternate distributor
spree_put :populate, :variants => {p2.id => 1}, :distributor_id => d2
spree_post :populate, :variants => {p2.master.id => 1}, :distributor_id => d2
# Then the product should not be added to the cart
current_order(false).line_items.reload.map { |li| li.product }.should == [@product]
current_order(false).distributor.reload.should == @distributor
end
end
context "adding a group buy product to the cart" do
it "sets a variant attribute for the max quantity" do
distributor_product = create(:distributor)
p = create(:product, :distributors => [distributor_product], :group_buy => true)
order = current_order(true)
order.should_receive(:set_variant_attributes).with(p.master, {'max_quantity' => '3'})
controller.stub(:current_order).and_return(order)
expect do
spree_post :populate, :variants => {p.master.id => 1}, :variant_attributes => {p.master.id => {:max_quantity => 3}}, :distributor_id => distributor_product.id
end.to change(Spree::LineItem, :count).by(1)
end
end
end

View File

@@ -24,7 +24,7 @@ FactoryGirl.define do
factory :product_distribution, :class => Spree::ProductDistribution do
product { |pd| Spree::Product.first || FactoryGirl.create(:product) }
distributor { |pd| Spree::Distributor.first || FactoryGirl.create(:distributor) }
shipping_method { |pd| Spree::ShippingMethod.first || FactoryGirl.create(:shipping_method) }
shipping_method { |pd| Spree::ShippingMethod.where("name != 'Delivery'").first || FactoryGirl.create(:shipping_method) }
end
factory :itemwise_shipping_method, :parent => :shipping_method do
@@ -39,11 +39,34 @@ end
FactoryGirl.modify do
factory :simple_product do
# Fix product factory name sequence with Kernel.rand so it is not interpreted as a Spree::Product method
# Pull request: https://github.com/spree/spree/pull/1964
# When this fix has been merged into a version of Spree that we're using, this line can be removed.
sequence(:name) { |n| "Product ##{n} - #{Kernel.rand(9999)}" }
supplier { Spree::Supplier.first || FactoryGirl.create(:supplier) }
on_hand 3
# before(:create) do |product, evaluator|
# product.product_distributions = [FactoryGirl.create(:product_distribution, :product => product)]
# end
# Do not create products distributed via the 'Delivery' shipping method
after(:create) do |product, evaluator|
pd = product.product_distributions.first
if pd.andand.shipping_method.andand.name == 'Delivery'
pd.shipping_method = Spree::ShippingMethod.where("name != 'Delivery'").first || FactoryGirl.create(:shipping_method)
pd.save!
end
end
end
factory :line_item do
shipping_method { |li| li.product.shipping_method_for_distributor(li.order.distributor) }
end
factory :shipping_method do
display_on ''
end
factory :address do

View File

@@ -0,0 +1,51 @@
require 'spec_helper'
module OpenFoodWeb
describe OrderAndDistributorReport do
describe "orders and distributors report" do
before(:each) do
@bill_address = create(:address)
@distributor_address = create(:address, :address1 => "distributor address", :city => 'The Shire', :zipcode => "1234")
@distributor = create(:distributor, :pickup_address => @distributor_address)
product = create(:product)
product_distribution = create(:product_distribution, :product => product, :distributor => @distributor, :shipping_method => create(:shipping_method))
@shipping_instructions = "pick up on thursday please!"
@order = create(:order, :distributor => @distributor, :bill_address => @bill_address, :special_instructions => @shipping_instructions)
@payment_method = create(:payment_method)
payment = create(:payment, :payment_method => @payment_method, :order => @order )
@order.payments << payment
@line_item = create(:line_item, :product => product, :order => @order)
@order.line_items << @line_item
end
it "should return a header row describing the report" do
subject = OrderAndDistributorReport.new [@order]
header = subject.header
header.should == ["Order date", "Order Id",
"Customer Name","Customer Email", "Customer Phone", "Customer City",
"SKU", "Item name", "Variant", "Quantity", "Max Quantity", "Cost", "Shipping cost",
"Payment method",
"Distributor", "Distributor address", "Distributor city", "Distributor postcode", "Shipping instructions"]
end
it "should denormalise order and distributor details for display as csv" do
subject = OrderAndDistributorReport.new [@order]
table = subject.table
table[0].should == [@order.created_at, @order.id,
@bill_address.full_name, @order.email, @bill_address.phone, @bill_address.city,
@line_item.product.sku, @line_item.product.name, @line_item.variant.options_text, @line_item.quantity, @line_item.max_quantity, @line_item.price * @line_item.quantity, @line_item.itemwise_shipping_cost,
@payment_method.name,
@distributor.name, @distributor.pickup_address.address1, @distributor.pickup_address.city, @distributor.pickup_address.zipcode, @shipping_instructions ]
end
it "should include breakdown an order into each line item"
end
end
end

View File

@@ -10,4 +10,11 @@ describe OpenFoodWeb::Calculator::Itemwise do
subject.compute(order).should == 30
end
it "returns zero for an order with no items" do
order = double(:order)
order.stub(:line_items).and_return([])
subject.compute(order).should == 0
end
end

View File

@@ -4,13 +4,15 @@ describe OpenFoodWeb::Calculator::Weight do
it "computes shipping cost for an order by total weight" do
variant_1 = double(:variant, :weight => 10)
variant_2 = double(:variant, :weight => 20)
variant_3 = double(:variant, :weight => nil)
line_item_1 = double(:line_item, :variant => variant_1)
line_item_2 = double(:line_item, :variant => variant_2)
line_item_1 = double(:line_item, :variant => variant_1, :quantity => 1)
line_item_2 = double(:line_item, :variant => variant_2, :quantity => 3)
line_item_3 = double(:line_item, :variant => variant_3, :quantity => 5)
order = double(:order, :line_items => [line_item_1, line_item_2])
order = double(:order, :line_items => [line_item_1, line_item_2, line_item_3])
subject.set_preference(:per_kg, 10)
subject.compute(order).should == 300
subject.compute(order).should == (10*1 + 20*3) * 10
end
end

View File

@@ -9,13 +9,28 @@ module Spree
it { should have_many(:orders) }
end
describe "validations" do
it { should validate_presence_of(:name) }
end
it "should default country to system country" do
distributor = Distributor.new
distributor.pickup_address.country.should == Country.find_by_id(Config[:default_country_id])
end
describe "validations" do
it { should validate_presence_of(:name) }
describe "scopes" do
it "returns distributors with products in stock" do
d1 = create(:distributor)
d2 = create(:distributor)
d3 = create(:distributor)
d4 = create(:distributor)
create(:product, :distributors => [d1, d2], :on_hand => 5)
create(:product, :distributors => [d1], :on_hand => 5)
create(:product, :distributors => [d3], :on_hand => 0)
Distributor.with_active_products_on_hand.sort.should == [d1, d2]
end
end
end
end

View File

@@ -7,12 +7,9 @@ module Spree
shipping_method = create(:shipping_method)
shipping_method.calculator.set_preference :amount, 10
product = double(:product)
product.should_receive(:shipping_method_for_distributor).and_return(shipping_method)
order = double(:order, :distributor => nil)
subject.stub(:product).and_return(product)
subject.stub(:shipping_method).and_return(shipping_method)
subject.stub(:order).and_return(order)
subject.itemwise_shipping_cost.should == 10

View File

@@ -1,8 +1,25 @@
require 'spec_helper'
describe Spree::Order do
it "initialises a default shipping method after creation" do
shipping_method_back_end = create(:shipping_method, :display_on => :back_end)
shipping_method_both = create(:shipping_method, :display_on => :both)
subject.shipping_method.should be_nil
subject.adjustments.should be_empty
subject.save!
subject.shipping_method.should == shipping_method_both
subject.adjustments.where(:label => "Shipping").should be_present
end
it "reveals permission for changing distributor" do
p = build(:product)
d = create(:distributor)
p = create(:product, :distributors => [d])
subject.distributor = d
subject.save!
subject.can_change_distributor?.should be_true
subject.add_variant(p.master, 1)
@@ -10,9 +27,11 @@ describe Spree::Order do
end
it "raises an exception if distributor is changed without permission" do
d = build(:distributor)
p = build(:product, :distributors => [d])
d = create(:distributor)
p = create(:product, :distributors => [d])
subject.distributor = d
subject.save!
subject.add_variant(p.master, 1)
subject.can_change_distributor?.should be_false
@@ -46,4 +65,18 @@ describe Spree::Order do
# And cannot be added if it does not match
subject.can_add_product_to_cart?(p_subsequent_other_dist).should be_false
end
it "sets attributes on line items for variants" do
d = create(:distributor)
p = create(:product, :distributors => [d])
subject.distributor = d
subject.save!
subject.add_variant(p.master, 1)
subject.set_variant_attributes(p.master, {'max_quantity' => '3'})
li = Spree::LineItem.last
li.max_quantity.should == 3
end
end

View File

@@ -36,6 +36,26 @@ feature %q{
product.supplier.should == @supplier
product.distributors.should == [@distributors[0], @distributors[2]]
product.product_distributions.map { |pd| pd.shipping_method }.should == [@shipping_method, @shipping_method]
product.group_buy.should be_false
end
scenario "making a group buy product" do
login_to_admin_section
click_link 'Products'
click_link 'New Product'
fill_in 'product_name', :with => 'A new product !!!'
fill_in 'product_price', :with => '19.99'
select 'New supplier', :from => 'product_supplier_id'
choose 'product_group_buy_1'
click_button 'Create'
flash_message.should == 'Product "A new product !!!" has been successfully created!'
product = Spree::Product.find_by_name('A new product !!!')
product.group_buy.should be_true
end
end
end

View File

@@ -0,0 +1,58 @@
require 'spec_helper'
feature 'shipping methods' do
include AuthenticationWorkflow
include WebHelper
before :each do
login_to_admin_section
@sm = create(:shipping_method)
end
scenario "deleting a shipping method" do
visit_delete spree.admin_shipping_method_path(@sm)
page.should have_content "Shipping method \"#{@sm.name}\" has been successfully removed!"
Spree::ShippingMethod.where(:id => @sm.id).should be_empty
end
scenario "deleting a shipping method referenced by an order" do
o = create(:order, shipping_method: @sm)
visit_delete spree.admin_shipping_method_path(@sm)
page.should have_content "That shipping method cannot be deleted as it is referenced by an order: #{o.number}."
Spree::ShippingMethod.find(@sm.id).should_not be_nil
end
scenario "deleting a shipping method referenced by a product distribution" do
p = create(:product)
d = create(:distributor)
create(:product_distribution, product: p, distributor: d, shipping_method: @sm)
visit_delete spree.admin_shipping_method_path(@sm)
page.should have_content "That shipping method cannot be deleted as it is referenced by a product distribution: #{p.id} - #{p.name}."
Spree::ShippingMethod.find(@sm.id).should_not be_nil
end
scenario "deleting a shipping method referenced by a line item" do
sm2 = create(:shipping_method)
d = create(:distributor)
p = create(:product)
create(:product_distribution, product: p, distributor: d, shipping_method: sm2)
o = create(:order, distributor: d)
o.shipping_method = sm2
o.save!
li = create(:line_item, order: o, product: p)
li.shipping_method = @sm
li.save!
visit_delete spree.admin_shipping_method_path(@sm)
page.should have_content "That shipping method cannot be deleted as it is referenced by a line item in order: #{o.number}."
Spree::ShippingMethod.find(@sm.id).should_not be_nil
end
end

View File

@@ -8,24 +8,58 @@ feature %q{
include AuthenticationWorkflow
include WebHelper
scenario "adding the first product to the cart" do
scenario "adding a product to the cart with no distributor chosen" do
# Given a product and some distributors
d1 = create(:distributor)
d2 = create(:distributor)
p = create(:product, :distributors => [d1])
create(:product, :distributors => [d2])
# When I add an item to my cart without choosing a distributor
visit spree.product_path p
click_button 'Add To Cart'
# Then I should see an error message
page.should have_content "Please choose a distributor for this order."
# And the product should not have been added to my cart
Spree::Order.last.should be_nil
end
scenario "adding the first product to the cart" do
create(:itemwise_shipping_method)
# Given a product, some distributors and a defined shipping cost
d1 = create(:distributor)
d2 = create(:distributor)
create(:product, :distributors => [d2])
p = create(:product, :price => 12.34)
create(:product_distribution, :product => p, :distributor => d1, :shipping_method => create(:shipping_method))
# ... with a flat rate shipping method of cost $1.23
sm = p.product_distributions.first.shipping_method
sm.calculator.preferred_amount = 1.23
sm.calculator.save!
# When I choose a distributor
visit spree.root_path
click_link d2.name
# When I add an item to my cart from a different distributor
# And I add an item to my cart from a different distributor
visit spree.product_path p
select d1.name, :from => 'distributor_id'
click_button 'Add To Cart'
# Then the item should be in my cart
# Then the correct totals should be displayed
page.should have_selector 'span.item-total', :text => '$12.34'
page.should have_selector 'span.shipping-total', :text => '$1.23'
page.should have_selector 'span.grand-total', :text => '$13.57'
# And the item should be in my cart, with shipping method set for the line item
order = Spree::Order.last
order.line_items.first.product.should == p
line_item = order.line_items.first
line_item.product.should == p
line_item.shipping_method.should == p.product_distributions.first.shipping_method
# And my order should have its distributor set to the chosen distributor
order.distributor.should == d1
@@ -39,6 +73,7 @@ feature %q{
# When I add a product to my cart (which sets my distributor)
visit spree.product_path p
select d1.name, :from => 'distributor_id'
click_button 'Add To Cart'
page.should have_content "You are shopping at #{d1.name}"
@@ -57,6 +92,7 @@ feature %q{
# And a product in my cart
visit spree.product_path p
select d.name, :from => 'distributor_id'
click_button 'Add To Cart'
# When I go to add it again, I should not have a choice of distributor
@@ -74,6 +110,7 @@ feature %q{
# When I add one of them to my cart
visit spree.product_path p1
select d1.name, :from => 'distributor_id'
click_button 'Add To Cart'
# And I attempt to add the other
@@ -92,6 +129,7 @@ feature %q{
# When I add the first to my cart
visit spree.product_path p1
select d.name, :from => 'distributor_id'
click_button 'Add To Cart'
# And I add the second
@@ -104,4 +142,78 @@ feature %q{
page.should have_selector 'h4 a', :text => p2.name
end
end
context "group buys" do
scenario "adding a product to the cart for a group buy" do
# Given a group buy product and a distributor
d = create(:distributor)
p = create(:product, :distributors => [d], :group_buy => true)
# When I add the item to my cart
visit spree.product_path p
select d.name, :from => 'distributor_id'
fill_in "variants_#{p.master.id}", :with => 2
fill_in "variant_attributes_#{p.master.id}_max_quantity", :with => 3
click_button 'Add To Cart'
# Then the item should be in my cart with correct quantities
order = Spree::Order.last
li = order.line_items.first
li.product.should == p
li.quantity.should == 2
li.max_quantity.should == 3
end
scenario "adding a product with variants to the cart for a group buy" do
# Given a group buy product with variants and a distributor
d = create(:distributor)
p = create(:product, :distributors => [d], :group_buy => true)
create(:variant, :product => p)
# When I add the item to my cart
visit spree.product_path p
select d.name, :from => 'distributor_id'
fill_in "quantity", :with => 2
fill_in "max_quantity", :with => 3
click_button 'Add To Cart'
# Then the item should be in my cart with correct quantities
order = Spree::Order.last
li = order.line_items.first
li.product.should == p
li.quantity.should == 2
li.max_quantity.should == 3
end
scenario "adding a product to cart that is not a group buy does not show max quantity field" do
# Given a group buy product and a distributor
d = create(:distributor)
p = create(:product, :distributors => [d], :group_buy => false)
# When I view the add to cart form, there should not be a max quantity field
visit spree.product_path p
page.should_not have_selector "#variant_attributes_#{p.master.id}_max_quantity"
end
scenario "adding a product with a max quantity less than quantity results in max_quantity==quantity" do
# Given a group buy product and a distributor
d = create(:distributor)
p = create(:product, :distributors => [d], :group_buy => true)
# When I add the item to my cart
visit spree.product_path p
select d.name, :from => 'distributor_id'
fill_in "variants_#{p.master.id}", :with => 2
fill_in "variant_attributes_#{p.master.id}_max_quantity", :with => 1
click_button 'Add To Cart'
# Then the item should be in my cart with correct quantities
order = Spree::Order.last
li = order.line_items.first
li.product.should == p
li.quantity.should == 2
li.max_quantity.should == 2
end
end
end

View File

@@ -46,6 +46,7 @@ feature %q{
# When I add some apples and some garlic to my cart
click_link 'Fuji apples'
select @distributor.name, :from => 'distributor_id'
click_button 'Add To Cart'
click_link 'Continue shopping'
@@ -56,11 +57,14 @@ feature %q{
# Item | Shipping Method | Delivery Fee
# Garlic | Shipping Method Two | $2.00
# Fuji apples | Shipping Method One | $1.00
#
# Subtotal: $3.00
table = page.find 'table#delivery'
rows = table.all('tr')
rows[0].all('th').map { |cell| cell.text.strip }.should == ['Item', 'Shipping Method', 'Delivery Fee']
rows[1].all('td').map { |cell| cell.text.strip }.should == ['Fuji apples', 'Shipping Method One', '$1.00']
rows[2].all('td').map { |cell| cell.text.strip }.should == ['Garlic', 'Shipping Method Two', '$2.00']
page.should have_selector '#delivery-fees span.order-total', :text => '$3.00'
end
@@ -68,6 +72,7 @@ feature %q{
login_to_consumer_section
click_link 'Fuji apples'
select @distributor.name, :from => 'distributor_id'
click_button 'Add To Cart'
click_link 'Continue shopping'

View File

@@ -10,22 +10,28 @@ feature %q{
scenario "viewing a list of distributors" do
# Given some distributors
3.times { create(:distributor) }
d1 = create(:distributor)
d2 = create(:distributor)
d3 = create(:distributor)
# And some of those distributors have a product
create(:product, :distributors => [d1, d2])
# When I go to the home page
visit spree.root_path
# Then I should see a list containing all distributors
Spree::Distributor.all.each do |distributor|
page.should have_selector 'a', :text => distributor.name
end
# Then I should see a list containing the distributors that have products
page.should have_selector 'a', :text => d1.name
page.should have_selector 'a', :text => d2.name
page.should_not have_selector 'a', :text => d3.name
end
context "when a distributor is selected" do
it "displays the distributor's name" do
# Given a distributor
# Given a distributor with a product
d = create(:distributor, :name => 'Melb Uni Co-op')
create(:product, :distributors => [d])
# When I select the distributor
visit spree.root_path
@@ -65,8 +71,9 @@ feature %q{
end
it "allows the user to leave the distributor" do
# Given a distributor
# Given a distributor with a product
d = create(:distributor, :name => 'Melb Uni Co-op')
create(:product, :distributors => [d])
# When I select the distributor and then leave it
visit spree.root_path
@@ -106,10 +113,11 @@ feature %q{
end
it "works when viewing a product from a remote distributor" do
# Given two distributors and a product under one
# Given two distributors and our product under one
distributor_product = create(:distributor)
distributor_no_product = create(:distributor)
product = create(:product, :distributors => [distributor_product])
create(:product, :distributors => [distributor_no_product])
# When we select the distributor without the product and then view the product
visit spree.root_path

View File

@@ -0,0 +1,36 @@
require 'spec_helper'
feature %q{
As a consumer
I want to see a list of products from a supplier
So that I can connect with them (and maybe buy stuff too)
} do
include AuthenticationWorkflow
include WebHelper
scenario "viewing a list of suppliers" do
# Given some suppliers
s1 = create(:supplier)
s2 = create(:supplier)
s3 = create(:supplier)
# When I go to the home page
visit spree.root_path
# Then I should see a list containing all the suppliers
[s1, s2, s3].each { |s| page.should have_selector 'a', :text => s.name }
end
scenario "viewing products provided by a supplier" do
# Given a supplier with a product
s = create(:supplier, :name => 'Murrnong')
p = create(:product, :supplier => s)
# When I select the supplier
visit spree.root_path
click_link s.name
# Then I should see the product
page.should have_content p.name
end
end

View File

@@ -76,6 +76,11 @@ module WebHelper
page.find(:xpath, "//div[@class=\"ui-dialog-buttonset\"]//span[contains(text(),\"#{button_content}\")]").click
end
def visit_delete(url)
response = Capybara.current_session.driver.delete url
click_link 'redirected' if response.status == 302
end
def trigger_manual_event(field_selector, event = 'change')
page.execute_script("$('#{field_selector}').trigger('#{event}');")
end

22
zeus.json Normal file
View File

@@ -0,0 +1,22 @@
{
"command": "ruby -rubygems -rzeus/rails -eZeus.go",
"plan": {
"boot": {
"default_bundle": {
"development_environment": {
"prerake": {"rake": []},
"runner": ["r"],
"console": ["c"],
"server": ["s"],
"generate": ["g"],
"dbconsole": []
},
"test_environment": {
"cucumber_environment": {"cucumber": []},
"test_helper": {"test": ["rspec", "testrb"]}
}
}
}
}
}