mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-24 20:36:49 +00:00
Compare commits
64 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f581fce43 | ||
|
|
8156da509e | ||
|
|
718e54f933 | ||
|
|
cb56e9f658 | ||
|
|
9afa566be5 | ||
|
|
86847d99da | ||
|
|
258559f9d0 | ||
|
|
af05448dd8 | ||
|
|
e74f9054ae | ||
|
|
82dd485e01 | ||
|
|
1d5e4d22e7 | ||
|
|
28d2292de0 | ||
|
|
73e601315b | ||
|
|
a0c1d1d255 | ||
|
|
411ba107ce | ||
|
|
4f1e4fc223 | ||
|
|
eae05ea59c | ||
|
|
c09d4c98c8 | ||
|
|
474c049f0d | ||
|
|
1d3b7de5c6 | ||
|
|
3f08c2a9b0 | ||
|
|
5930363fa2 | ||
|
|
5f9b823b9c | ||
|
|
d859999bdc | ||
|
|
c5270d6fa1 | ||
|
|
340259eb2a | ||
|
|
09f5bb8eed | ||
|
|
e0e566e625 | ||
|
|
4b9c0f01e2 | ||
|
|
ba3c02346d | ||
|
|
f75b9bb176 | ||
|
|
cb6ac2064d | ||
|
|
3ad575cb5f | ||
|
|
34b694666c | ||
|
|
0662e8f676 | ||
|
|
f3d52825ae | ||
|
|
9258d47e55 | ||
|
|
a48a100bcc | ||
|
|
32dca81467 | ||
|
|
6cd9bff29f | ||
|
|
a7df5a2f1e | ||
|
|
f4108921ed | ||
|
|
178f581452 | ||
|
|
98bcc9ce71 | ||
|
|
df831a9128 | ||
|
|
4481ca83f9 | ||
|
|
24ad4f53fc | ||
|
|
a41c5d4735 | ||
|
|
7b92fcb614 | ||
|
|
d3c80e99fc | ||
|
|
056733a426 | ||
|
|
3219006423 | ||
|
|
fc5795173e | ||
|
|
99d6f0baa9 | ||
|
|
b5082009ce | ||
|
|
4faed954e6 | ||
|
|
b2f5e23fa4 | ||
|
|
a91722a593 | ||
|
|
9be5dc41b9 | ||
|
|
34f95ffb4a | ||
|
|
ebb624bdc3 | ||
|
|
32050bbba4 | ||
|
|
5411685c83 | ||
|
|
5e6c4de34b |
6
Gemfile
6
Gemfile
@@ -5,9 +5,9 @@ gem 'rails', '3.2.3'
|
||||
gem 'pg'
|
||||
gem 'spree'
|
||||
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_last_address', :git => 'git://github.com/dancinglightning/spree-last-address.git'
|
||||
|
||||
gem 'spree_usa_epay'
|
||||
gem 'spree_skrill'
|
||||
|
||||
# Fix bug in simple_form preventing collection_check_boxes usage within form_for block
|
||||
# When merged, revert to upstream gem
|
||||
@@ -50,7 +50,7 @@ group :test, :development do
|
||||
gem 'turn', '~> 0.8.3', :require => false
|
||||
gem 'rspec-rails'
|
||||
gem 'shoulda-matchers'
|
||||
gem 'factory_girl_rails'
|
||||
gem 'factory_girl_rails', :require => false
|
||||
gem 'faker'
|
||||
gem 'capybara'
|
||||
gem 'database_cleaner', '0.7.1', :require => false
|
||||
|
||||
42
Gemfile.lock
42
Gemfile.lock
@@ -6,6 +6,13 @@ GIT
|
||||
actionpack (~> 3.0)
|
||||
activemodel (~> 3.0)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/dancinglightning/spree-last-address.git
|
||||
revision: f5ed71a5482fbc16da559737903bb46fe032c150
|
||||
specs:
|
||||
spree_last_address (1.1.0)
|
||||
spree_core (>= 1.1)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/joneslee85/spree-heroku.git
|
||||
revision: 63f0cfa47089cae50365e226ec7dd1eccde0ac05
|
||||
@@ -22,6 +29,13 @@ GIT
|
||||
i18n (~> 0.5)
|
||||
spree (~> 1.1)
|
||||
|
||||
GIT
|
||||
remote: git://github.com/spree/spree_paypal_express.git
|
||||
revision: d48f4649506e876b88244dcb4e5a86250e4ef8f0
|
||||
specs:
|
||||
spree_paypal_express (1.1.0)
|
||||
spree_core (>= 1.0.0)
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
@@ -65,9 +79,6 @@ GEM
|
||||
multi_json (~> 1.0)
|
||||
acts_as_list (0.1.4)
|
||||
addressable (2.2.8)
|
||||
akami (1.1.0)
|
||||
gyoku (>= 0.4.0)
|
||||
nokogiri (>= 1.5.2)
|
||||
andand (1.3.3)
|
||||
ansi (1.4.2)
|
||||
arel (3.0.2)
|
||||
@@ -125,16 +136,12 @@ GEM
|
||||
i18n (~> 0.4)
|
||||
ffaker (1.12.1)
|
||||
ffi (1.0.11)
|
||||
gyoku (0.4.5)
|
||||
builder (>= 2.1.2)
|
||||
haml (3.1.6)
|
||||
highline (1.6.11)
|
||||
hike (1.2.1)
|
||||
httparty (0.8.3)
|
||||
multi_json (~> 1.0)
|
||||
multi_xml
|
||||
httpi (1.0.0)
|
||||
rack
|
||||
i18n (0.6.0)
|
||||
journey (1.0.4)
|
||||
jquery-rails (2.0.2)
|
||||
@@ -163,7 +170,6 @@ GEM
|
||||
activerecord (>= 3.0.0)
|
||||
railties (>= 3.0.0)
|
||||
nokogiri (1.5.3)
|
||||
nori (1.1.0)
|
||||
orm_adapter (0.0.7)
|
||||
paperclip (2.7.0)
|
||||
activerecord (>= 2.3.0)
|
||||
@@ -230,14 +236,6 @@ GEM
|
||||
railties (~> 3.2.0)
|
||||
sass (>= 3.1.10)
|
||||
tilt (~> 1.3)
|
||||
savon (0.9.14)
|
||||
akami (~> 1.1)
|
||||
builder (>= 2.1.2)
|
||||
gyoku (>= 0.4.0)
|
||||
httpi (~> 1.0)
|
||||
nokogiri (>= 1.4.0)
|
||||
nori (~> 1.1)
|
||||
wasabi (~> 2.2)
|
||||
selenium-webdriver (2.22.2)
|
||||
childprocess (>= 0.2.5)
|
||||
ffi (~> 1.0)
|
||||
@@ -289,11 +287,6 @@ GEM
|
||||
spree_core (= 1.1.1)
|
||||
spree_sample (1.1.1)
|
||||
spree_core (= 1.1.1)
|
||||
spree_skrill (1.0.2)
|
||||
spree_core (>= 1.0.0)
|
||||
spree_usa_epay (1.0.2)
|
||||
savon
|
||||
spree_core (>= 1.0.0)
|
||||
sprockets (2.1.3)
|
||||
hike (~> 1.2)
|
||||
rack (~> 1.0)
|
||||
@@ -320,9 +313,6 @@ GEM
|
||||
uuidtools (2.1.2)
|
||||
warden (1.1.1)
|
||||
rack (>= 1.0)
|
||||
wasabi (2.4.0)
|
||||
httpi (~> 1.0)
|
||||
nokogiri (>= 1.4.0)
|
||||
xml-simple (1.1.1)
|
||||
xpath (0.1.4)
|
||||
nokogiri (~> 1.3)
|
||||
@@ -351,8 +341,8 @@ DEPENDENCIES
|
||||
spree
|
||||
spree_heroku!
|
||||
spree_i18n!
|
||||
spree_skrill
|
||||
spree_usa_epay
|
||||
spree_last_address!
|
||||
spree_paypal_express!
|
||||
therubyracer
|
||||
turn (~> 0.8.3)
|
||||
uglifier (>= 1.0.3)
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
// the compiled file.
|
||||
//
|
||||
|
||||
//= require 'jquery'
|
||||
//= require store/spree_core
|
||||
//= require store/spree_auth
|
||||
//= require store/spree_promo
|
||||
|
||||
38
app/assets/javascripts/store/products.js
Normal file
38
app/assets/javascripts/store/products.js
Normal file
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Update the price on the product details page in real time when the variant or the quantity are changed.
|
||||
**/
|
||||
|
||||
$(document).ready(function() {
|
||||
// Product page with variant choice
|
||||
$("#product-variants input[type='radio']").change(products_update_price_with_variant);
|
||||
$("#quantity").change(products_update_price_with_variant);
|
||||
$("#quantity").change();
|
||||
|
||||
// Product page with master price only
|
||||
$(".add-to-cart input.title:not(#quantity)").change(products_update_price_without_variant).change();
|
||||
});
|
||||
|
||||
|
||||
function products_update_price_with_variant() {
|
||||
var variant_price = $("#product-variants input[type='radio']:checked").parent().find("span.price").html();
|
||||
variant_price = variant_price.substr(2, variant_price.length-3);
|
||||
|
||||
var quantity = $("#quantity").val();
|
||||
|
||||
$("#product-price span.price").html("$"+(parseFloat(variant_price) * parseInt(quantity)).toFixed(2));
|
||||
}
|
||||
|
||||
|
||||
function products_update_price_without_variant() {
|
||||
var master_price = $("#product-price span.price").data('master-price');
|
||||
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);
|
||||
$("#product-price span.price").data('master-price', master_price);
|
||||
}
|
||||
|
||||
var quantity = $(this).val();
|
||||
|
||||
$("#product-price span.price").html("$"+(parseFloat(master_price)*parseInt(quantity)).toFixed(2));
|
||||
}
|
||||
@@ -6,6 +6,11 @@ nav #main-nav-bar {
|
||||
&#current-distributor {
|
||||
float: right;
|
||||
margin-right: 24px;
|
||||
|
||||
a {
|
||||
font-size: 12px;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,12 +33,18 @@ nav#filters {
|
||||
margin-bottom: 20px;
|
||||
list-style: disc outside;
|
||||
|
||||
li a {
|
||||
font-size: $main_navigation_font_size;
|
||||
li {
|
||||
a {
|
||||
font-size: $main_navigation_font_size;
|
||||
}
|
||||
span.inactive {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Style the product source on the product details page in the
|
||||
* same manner as the product properties table above it.
|
||||
*/
|
||||
@@ -43,3 +54,124 @@ nav#filters {
|
||||
#product-properties td, #product-source td {
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
|
||||
/* Apply Spree's ul#products style to ul.product-listing. When viewing products
|
||||
* split by distributor, a separate product listing is displayed for local and
|
||||
* remote products, so the #products id is removed to avoid its duplication.
|
||||
*/
|
||||
ul.product-listing {
|
||||
&:after {
|
||||
content: " ";
|
||||
display: block;
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
line-height: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
margin-bottom: 20px;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
|
||||
&.info {
|
||||
height: 35px;
|
||||
margin-top: 5px;
|
||||
font-size: $product_list_name_font_size;
|
||||
color: $product_link_text_color;
|
||||
border-bottom: 1px solid lighten($body_text_color, 60);
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.product-image {
|
||||
border: 1px solid lighten($body_text_color, 60);
|
||||
padding: 5px;
|
||||
min-height: 110px;
|
||||
background-color: $product_background_color;
|
||||
|
||||
&:hover {
|
||||
border-color: $link_text_color;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.price {
|
||||
color: $link_text_color;
|
||||
font-size: $product_list_price_font_size;
|
||||
padding-top: 5px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Highlight local products in distributor-split product listings */
|
||||
#products-local ul {
|
||||
margin-bottom: 1em;
|
||||
padding: 10px;
|
||||
border-radius: 10px;
|
||||
background-color: #def;
|
||||
}
|
||||
|
||||
|
||||
/* Add to cart form on product details page */
|
||||
#cart-form {
|
||||
.error-distributor {
|
||||
font-size: 120%;
|
||||
font-weight: bold;
|
||||
color: #f00;
|
||||
|
||||
a {
|
||||
color: #f00;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.distributor-fixed {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* View cart form */
|
||||
#subtotal {
|
||||
width: 100%;
|
||||
}
|
||||
.links {
|
||||
float: right;
|
||||
text-align: right;
|
||||
}
|
||||
#empty-cart {
|
||||
float: left;
|
||||
|
||||
p {
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Delivery fees table on checkout page */
|
||||
#delivery-fees {
|
||||
clear: both;
|
||||
padding-top: 6em;
|
||||
|
||||
table#delivery {
|
||||
width: 100%;
|
||||
|
||||
tbody {
|
||||
tr {
|
||||
td.item-shipping-cost, td.item-shipping-method {
|
||||
text-align: center;
|
||||
}
|
||||
td.item-shipping-cost {
|
||||
@extend span.price;
|
||||
@extend span.price.selling;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +1,30 @@
|
||||
module Spree
|
||||
module Admin
|
||||
class DistributorsController < ResourceController
|
||||
before_filter :load_data, :except => [:index]
|
||||
before_filter :load_distributor_set, :only => :index
|
||||
before_filter :load_countries, :except => :index
|
||||
|
||||
def bulk_update
|
||||
@distributor_set = DistributorSet.new(params[:distributor_set])
|
||||
if @distributor_set.save
|
||||
redirect_to admin_distributors_path, :notice => 'Distributor collection times updated.'
|
||||
else
|
||||
render :index
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def load_data
|
||||
@countries = Country.order(:name)
|
||||
def load_distributor_set
|
||||
@distributor_set = Spree::DistributorSet.new :distributors => collection
|
||||
end
|
||||
|
||||
def load_countries
|
||||
@countries = Country.order(:name)
|
||||
end
|
||||
|
||||
def collection
|
||||
super.order(:name)
|
||||
super.order(:name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,12 +5,12 @@ module Spree
|
||||
|
||||
private
|
||||
def load_data
|
||||
@countries = Country.order(:name)
|
||||
@countries = Country.order(:name)
|
||||
end
|
||||
|
||||
def collection
|
||||
super.order(:name)
|
||||
super.order(:name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -13,10 +13,24 @@ module Spree
|
||||
distributor = Distributor.find params[:id]
|
||||
|
||||
order = current_order(true)
|
||||
order.distributor = distributor
|
||||
order.save!
|
||||
|
||||
redirect_back_or_default(root_path)
|
||||
if order.can_change_distributor?
|
||||
order.distributor = distributor
|
||||
order.save!
|
||||
end
|
||||
|
||||
redirect_to root_path
|
||||
end
|
||||
|
||||
def deselect
|
||||
order = current_order(true)
|
||||
|
||||
if order.can_change_distributor?
|
||||
order.distributor = nil
|
||||
order.save!
|
||||
end
|
||||
|
||||
redirect_to root_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
10
app/controllers/spree/home_controller_decorator.rb
Normal file
10
app/controllers/spree/home_controller_decorator.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
require 'open_food_web/split_products_by_distributor'
|
||||
|
||||
Spree::HomeController.class_eval do
|
||||
include Spree::DistributorsHelper
|
||||
include OpenFoodWeb::SplitProductsByDistributor
|
||||
|
||||
respond_override :index => { :html => { :success => lambda {
|
||||
@products, @products_local, @products_remote = split_products_by_distributor @products, current_distributor
|
||||
} } }
|
||||
end
|
||||
41
app/controllers/spree/orders_controller_decorator.rb
Normal file
41
app/controllers/spree/orders_controller_decorator.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
Spree::OrdersController.class_eval do
|
||||
before_filter :populate_order_distributor, :only => :populate
|
||||
|
||||
def populate_order_distributor
|
||||
@distributor = params.key?(:distributor_id) ? Spree::Distributor.find(params[:distributor_id]) : nil
|
||||
|
||||
if populate_valid? @distributor
|
||||
order = current_order(true)
|
||||
order.distributor = @distributor
|
||||
order.save!
|
||||
|
||||
else
|
||||
redirect_to cart_path
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def populate_valid? distributor
|
||||
# -- Distributor must be specified
|
||||
return false if distributor.nil?
|
||||
|
||||
# -- All products must be available under that distributor
|
||||
params[:products].each do |product_id, variant_id|
|
||||
product = Spree::Product.find product_id
|
||||
return false unless product.distributors.include? distributor
|
||||
end if params[:products]
|
||||
|
||||
params[:variants].each do |variant_id, quantity|
|
||||
variant = Spree::Variant.find variant_id
|
||||
return false unless variant.product.distributors.include? distributor
|
||||
end if params[:variants]
|
||||
|
||||
# -- If products in cart, distributor can't be changed
|
||||
order = current_order(false)
|
||||
if !order.nil? && !order.can_change_distributor? && order.distributor != distributor
|
||||
return false
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
end
|
||||
11
app/controllers/spree/products_controller_decorator.rb
Normal file
11
app/controllers/spree/products_controller_decorator.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
require 'open_food_web/split_products_by_distributor'
|
||||
|
||||
Spree::ProductsController.class_eval do
|
||||
include Spree::DistributorsHelper
|
||||
include OpenFoodWeb::SplitProductsByDistributor
|
||||
|
||||
respond_override :index => { :html => { :success => lambda {
|
||||
@products, @products_local, @products_remote = split_products_by_distributor @products, current_distributor
|
||||
} } }
|
||||
|
||||
end
|
||||
10
app/controllers/spree/taxons_controller_decorator.rb
Normal file
10
app/controllers/spree/taxons_controller_decorator.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
require 'open_food_web/split_products_by_distributor'
|
||||
|
||||
Spree::TaxonsController.class_eval do
|
||||
include Spree::DistributorsHelper
|
||||
include OpenFoodWeb::SplitProductsByDistributor
|
||||
|
||||
respond_override :show => { :html => { :success => lambda {
|
||||
@products, @products_local, @products_remote = split_products_by_distributor @products, current_distributor
|
||||
} } }
|
||||
end
|
||||
8
app/helpers/spree/products_helper_decorator.rb
Normal file
8
app/helpers/spree/products_helper_decorator.rb
Normal file
@@ -0,0 +1,8 @@
|
||||
module Spree
|
||||
ProductsHelper.class_eval do
|
||||
# Return the price of the variant
|
||||
def variant_price_diff(variant)
|
||||
"(#{number_to_currency variant.price})"
|
||||
end
|
||||
end
|
||||
end
|
||||
13
app/models/open_food_web/calculator/itemwise.rb
Normal file
13
app/models/open_food_web/calculator/itemwise.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
module OpenFoodWeb
|
||||
class Calculator::Itemwise < Spree::Calculator
|
||||
|
||||
def self.description
|
||||
"Itemwise Shipping"
|
||||
end
|
||||
|
||||
def compute(object)
|
||||
# Given an order, sum the shipping on each individual item
|
||||
object.line_items.map { |li| li.itemwise_shipping_cost }.inject(:+)
|
||||
end
|
||||
end
|
||||
end
|
||||
15
app/models/open_food_web/calculator/weight.rb
Normal file
15
app/models/open_food_web/calculator/weight.rb
Normal file
@@ -0,0 +1,15 @@
|
||||
module OpenFoodWeb
|
||||
class Calculator::Weight < Spree::Calculator
|
||||
preference :per_kg, :decimal, :default => 0.0
|
||||
attr_accessible :preferred_per_kg
|
||||
|
||||
def self.description
|
||||
"Weight (per kg)"
|
||||
end
|
||||
|
||||
def compute(object)
|
||||
total_weight = object.line_items.inject(0) { |sum, li| sum+li.variant.weight }
|
||||
total_weight * self.preferred_per_kg
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,17 +1,29 @@
|
||||
module Spree
|
||||
class Distributor < ActiveRecord::Base
|
||||
self.table_name = 'distributors'
|
||||
belongs_to :country
|
||||
belongs_to :state
|
||||
has_and_belongs_to_many :products
|
||||
belongs_to :pickup_address, :foreign_key => 'pickup_address_id', :class_name => 'Spree::Address'
|
||||
has_many :orders
|
||||
|
||||
validates :name, :pickup_address, :country_id, :state_id, :city, :post_code, :presence => true
|
||||
has_many :product_distributions, :dependent => :destroy
|
||||
has_many :products, :through => :product_distributions
|
||||
|
||||
accepts_nested_attributes_for :pickup_address
|
||||
|
||||
validates_presence_of :name, :pickup_address
|
||||
validates_associated :pickup_address
|
||||
|
||||
scope :by_name, order('name')
|
||||
|
||||
after_initialize :initialize_country
|
||||
before_validation :set_unused_address_fields
|
||||
|
||||
def initialize_country
|
||||
self.country = Spree::Country.find_by_id(Spree::Config[:default_country_id])
|
||||
self.pickup_address ||= Address.new
|
||||
self.pickup_address.country = Country.find_by_id(Spree::Config[:default_country_id]) if self.pickup_address.new_record?
|
||||
end
|
||||
|
||||
def set_unused_address_fields
|
||||
pickup_address.firstname = pickup_address.lastname = pickup_address.phone = 'unused' if pickup_address.present?
|
||||
end
|
||||
|
||||
def to_param
|
||||
|
||||
36
app/models/spree/distributor_set.rb
Normal file
36
app/models/spree/distributor_set.rb
Normal file
@@ -0,0 +1,36 @@
|
||||
# Tableless model to handle updating multiple distributors at once from a
|
||||
# single form. Used to update next_collection_at field for all distributors in
|
||||
# admin backend.
|
||||
module Spree
|
||||
class DistributorSet
|
||||
include ActiveModel::Conversion
|
||||
extend ActiveModel::Naming
|
||||
|
||||
attr_accessor :distributors
|
||||
|
||||
def initialize(attributes={})
|
||||
@distributors = Spree::Distributor.all
|
||||
|
||||
attributes.each do |name, value|
|
||||
send("#{name}=", value)
|
||||
end
|
||||
end
|
||||
|
||||
def distributors_attributes=(attributes)
|
||||
attributes.each do |k, attributes|
|
||||
# attributes == {:id => 123, :next_collection_at => '...'}
|
||||
d = @distributors.detect { |d| d.id.to_s == attributes[:id].to_s }
|
||||
d.assign_attributes(attributes.except(:id))
|
||||
end
|
||||
end
|
||||
|
||||
def save
|
||||
distributors.all?(&:save)
|
||||
end
|
||||
|
||||
def persisted?
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
10
app/models/spree/line_item_decorator.rb
Normal file
10
app/models/spree/line_item_decorator.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
Spree::LineItem.class_eval do
|
||||
def shipping_method
|
||||
self.product.shipping_method_for_distributor(self.order.distributor)
|
||||
end
|
||||
|
||||
def itemwise_shipping_cost
|
||||
order = OpenStruct.new :line_items => [self]
|
||||
shipping_method.compute_amount(order)
|
||||
end
|
||||
end
|
||||
@@ -1,20 +1,34 @@
|
||||
Spree::Order.class_eval do
|
||||
belongs_to :distributor
|
||||
|
||||
# before_validation :shipping_address_from_distributor
|
||||
def can_change_distributor?
|
||||
# Distributor may not be changed once an item has been added to the cart/order
|
||||
line_items.empty?
|
||||
end
|
||||
|
||||
def distributor=(distributor)
|
||||
raise "You cannot change the distributor of an order with products" unless distributor == self.distributor || can_change_distributor?
|
||||
super(distributor)
|
||||
end
|
||||
|
||||
def can_add_product_to_cart?(product)
|
||||
can_change_distributor? || product.distributors.include?(distributor)
|
||||
end
|
||||
|
||||
|
||||
|
||||
before_validation :shipping_address_from_distributor
|
||||
|
||||
private
|
||||
# def shipping_address_from_distributor
|
||||
# if distributor
|
||||
# ship_address.firstname = bill_address.firstname
|
||||
# ship_address.lastname = bill_address.lastname
|
||||
# ship_address.phone = bill_address.phone
|
||||
def shipping_address_from_distributor
|
||||
if distributor
|
||||
self.ship_address = distributor.pickup_address.clone
|
||||
|
||||
# ship_address.address1 = distributor.pickup_address
|
||||
# ship_address.city = distributor.city
|
||||
# ship_address.zipcode = distributor.post_code
|
||||
# ship_address.state = distributor.state
|
||||
# ship_address.country_id = distributor.country_id
|
||||
# end
|
||||
# end
|
||||
if bill_address
|
||||
self.ship_address.firstname = bill_address.firstname
|
||||
self.ship_address.lastname = bill_address.lastname
|
||||
self.ship_address.phone = bill_address.phone
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,11 +1,32 @@
|
||||
Spree::Product.class_eval do
|
||||
belongs_to :supplier
|
||||
has_and_belongs_to_many :distributors
|
||||
|
||||
attr_accessible :supplier_id, :distributor_ids
|
||||
has_many :product_distributions, :dependent => :destroy
|
||||
has_many :distributors, :through => :product_distributions
|
||||
|
||||
validates_presence_of :supplier, :distributors
|
||||
accepts_nested_attributes_for :product_distributions, :allow_destroy => true
|
||||
|
||||
attr_accessible :supplier_id, :distributor_ids, :product_distributions_attributes
|
||||
|
||||
validates_presence_of :supplier
|
||||
|
||||
scope :in_supplier, lambda { |supplier| where(:supplier_id => supplier) }
|
||||
scope :in_distributor, lambda { |distributor| joins(:distributors).where('distributors.id = ?', (distributor.respond_to?(:id) ? distributor.id : distributor.to_i)) }
|
||||
scope :in_distributor, lambda { |distributor| joins(:product_distributions).where('product_distributions.distributor_id = ?', (distributor.respond_to?(:id) ? distributor.id : distributor.to_i)) }
|
||||
|
||||
|
||||
def shipping_method_for_distributor(distributor)
|
||||
distribution = self.product_distributions.find_by_distributor_id(distributor)
|
||||
raise ArgumentError, "This product is not available through that distributor" unless distribution
|
||||
distribution.shipping_method
|
||||
end
|
||||
|
||||
|
||||
# Build a product distribution for each distributor
|
||||
def build_product_distributions
|
||||
Spree::Distributor.all.each do |distributor|
|
||||
unless self.product_distributions.find_by_distributor_id distributor.id
|
||||
self.product_distributions.build(:distributor => distributor)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
13
app/models/spree/product_distribution.rb
Normal file
13
app/models/spree/product_distribution.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
module Spree
|
||||
class ProductDistribution < ActiveRecord::Base
|
||||
self.table_name = 'product_distributions'
|
||||
|
||||
belongs_to :product
|
||||
belongs_to :distributor
|
||||
belongs_to :shipping_method
|
||||
|
||||
validates_presence_of :product_id, :on => :update
|
||||
validates_presence_of :distributor_id, :shipping_method_id
|
||||
validates_uniqueness_of :product_id, :scope => :distributor_id
|
||||
end
|
||||
end
|
||||
@@ -2,15 +2,23 @@ module Spree
|
||||
class Supplier < ActiveRecord::Base
|
||||
self.table_name = 'suppliers'
|
||||
has_many :products
|
||||
belongs_to :country
|
||||
belongs_to :state
|
||||
belongs_to :address
|
||||
|
||||
validates :name, :address, :country_id, :state_id, :city, :postcode, :presence => true
|
||||
accepts_nested_attributes_for :address
|
||||
|
||||
validates_presence_of :name, :address
|
||||
validates_associated :address
|
||||
|
||||
after_initialize :initialize_country
|
||||
before_validation :set_unused_address_fields
|
||||
|
||||
def initialize_country
|
||||
self.country = Spree::Country.find_by_id(Spree::Config[:default_country_id])
|
||||
self.address ||= Address.new
|
||||
self.address.country = Country.find_by_id(Spree::Config[:default_country_id]) if self.address.new_record?
|
||||
end
|
||||
|
||||
def set_unused_address_fields
|
||||
address.firstname = address.lastname = address.phone = 'unused' if address.present?
|
||||
end
|
||||
|
||||
def to_param
|
||||
|
||||
4
app/overrides/add_distributor_fees_to_cart_form.rb
Normal file
4
app/overrides/add_distributor_fees_to_cart_form.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
Deface::Override.new(:virtual_path => "spree/orders/edit",
|
||||
:insert_after => "#empty-cart",
|
||||
:partial => "spree/orders/distributor_fees",
|
||||
:name => "cart_distributor_fees")
|
||||
4
app/overrides/add_distributor_to_add_to_cart_form.rb
Normal file
4
app/overrides/add_distributor_to_add_to_cart_form.rb
Normal file
@@ -0,0 +1,4 @@
|
||||
Deface::Override.new(:virtual_path => "spree/products/_cart_form",
|
||||
:replace => "[data-hook='product_price'] .add-to-cart",
|
||||
:partial => "spree/products/add_to_cart",
|
||||
:name => "product_add_to_cart")
|
||||
@@ -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/distributors",
|
||||
:name => "distributors")
|
||||
:insert_bottom => "[data-hook='admin_product_form_additional_fields']",
|
||||
:partial => "spree/admin/products/distributors",
|
||||
:name => "distributors")
|
||||
|
||||
Deface::Override.new(:virtual_path => "spree/admin/products/new",
|
||||
:insert_bottom => ".left",
|
||||
:partial => "spree/admin/products/distributors",
|
||||
:name => "distributors")
|
||||
:insert_bottom => ".left",
|
||||
:partial => "spree/admin/products/distributors",
|
||||
:name => "distributors")
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
Deface::Override.new(:virtual_path => "spree/shared/_order_details",
|
||||
:replace => "div.payment-info",
|
||||
:partial => "spree/shared/order_details_payment_info",
|
||||
:name => "order_details_payment_info")
|
||||
10
app/overrides/rearrange_cart_form.rb
Normal file
10
app/overrides/rearrange_cart_form.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
# Remove column layout from cart form items so we can style it with CSS
|
||||
Deface::Override.new(:virtual_path => "spree/orders/edit",
|
||||
:replace => "[data-hook='inside_cart_form']",
|
||||
:partial => "spree/orders/inside_cart_form",
|
||||
:name => "inside_cart_form")
|
||||
|
||||
Deface::Override.new(:virtual_path => "spree/orders/edit",
|
||||
:replace => "#empty-cart[data-hook]",
|
||||
:partial => "spree/orders/empty_cart_form",
|
||||
:name => "empty_cart_form")
|
||||
@@ -1,5 +1,4 @@
|
||||
Deface::Override.new(:virtual_path => "spree/checkout/_address",
|
||||
:replace => "[data-hook='shipping_fieldset_wrapper']",
|
||||
:partial => "spree/checkout/distributor",
|
||||
:name => "drop_off_point")
|
||||
|
||||
:name => "delivery_address")
|
||||
|
||||
19
app/overrides/split_products_by_distributor.rb
Normal file
19
app/overrides/split_products_by_distributor.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
Deface::Override.new(:virtual_path => "spree/home/index",
|
||||
:replace => "[data-hook='homepage_products']",
|
||||
:partial => "spree/shared/products_by_distributor",
|
||||
:name => "products_home")
|
||||
|
||||
Deface::Override.new(:virtual_path => "spree/products/index",
|
||||
:replace => "[data-hook='homepage_products']",
|
||||
:partial => "spree/shared/products_by_distributor",
|
||||
:name => "products_products")
|
||||
|
||||
Deface::Override.new(:virtual_path => "spree/products/index",
|
||||
:replace => "[data-hook='search_results']",
|
||||
:partial => "spree/shared/products_by_distributor",
|
||||
:name => "products_search")
|
||||
|
||||
Deface::Override.new(:virtual_path => "spree/taxons/show",
|
||||
:replace => "[data-hook='taxon_products']",
|
||||
:partial => "spree/shared/products_by_distributor",
|
||||
:name => "products_taxon")
|
||||
@@ -1,67 +0,0 @@
|
||||
<table data-hook="distributors">
|
||||
<tr data-hook="name">
|
||||
<td>Name:</td>
|
||||
<td><%= f.text_field :name %></td>
|
||||
</tr>
|
||||
|
||||
<tr data-hook="description">
|
||||
<td>Description:</td>
|
||||
<td><%= f.text_field :description %></td>
|
||||
</tr>
|
||||
|
||||
<tr data-hook="contact">
|
||||
<td>Contact:</td>
|
||||
<td><%= f.text_field :contact %></td>
|
||||
</tr>
|
||||
|
||||
<tr data-hook="phone">
|
||||
<td>Phone:</td>
|
||||
<td><%= f.text_field :phone %></td>
|
||||
</tr>
|
||||
|
||||
<tr data-hook="email">
|
||||
<td>Email:</td>
|
||||
<td><%= f.text_field :email %></td>
|
||||
</tr>
|
||||
|
||||
<tr data-hook="pickup_address">
|
||||
<td>Address: </td>
|
||||
<td><%= f.text_field :pickup_address %></td>
|
||||
</tr>
|
||||
<tr data-hook="pickup_city">
|
||||
<td>City:</td>
|
||||
<td><%= f.text_field :city %></td>
|
||||
</tr>
|
||||
<tr data-hook="pickup_post_code">
|
||||
<td>Post code:</td>
|
||||
<td><%= f.text_field :post_code %></td>
|
||||
</tr>
|
||||
<tr data-hook="pickup_country">
|
||||
<td>Country: </td>
|
||||
<td><%= f.collection_select(:country_id, @countries, :id, :name, :include_blank => true) %></td>
|
||||
</tr>
|
||||
<tr data-hook="pickup_state">
|
||||
<td>State: </td>
|
||||
<td><%= f.collection_select(:state_id, @distributor.country.states, :id, :name, :include_blank => true) %></td>
|
||||
</tr>
|
||||
|
||||
<tr data-hook="pickup_times">
|
||||
<td>Pickup times:</td>
|
||||
<td><%= f.text_field :pickup_times %></td>
|
||||
</tr>
|
||||
|
||||
<tr data-hook="url">
|
||||
<td>URL:</td>
|
||||
<td><%= f.text_field :url %></td>
|
||||
</tr>
|
||||
|
||||
<tr data-hook="abn">
|
||||
<td>ABN:</td>
|
||||
<td><%= f.text_field :abn %></td>
|
||||
</tr>
|
||||
|
||||
<tr data-hook="acn">
|
||||
<td>ACN:</td>
|
||||
<td><%= f.text_field :acn %></td>
|
||||
</tr>
|
||||
</table>
|
||||
36
app/views/spree/admin/distributors/_form.html.haml
Normal file
36
app/views/spree/admin/distributors/_form.html.haml
Normal file
@@ -0,0 +1,36 @@
|
||||
%table{"data-hook" => "distributors"}
|
||||
%tr{"data-hook" => "name"}
|
||||
%td Name:
|
||||
%td= f.text_field :name
|
||||
%tr{"data-hook" => "description"}
|
||||
%td Description:
|
||||
%td= f.text_field :description
|
||||
%tr{"data-hook" => "contact"}
|
||||
%td Contact:
|
||||
%td= f.text_field :contact
|
||||
%tr{"data-hook" => "phone"}
|
||||
%td Phone:
|
||||
%td= f.text_field :phone
|
||||
%tr{"data-hook" => "email"}
|
||||
%td Email:
|
||||
%td= f.text_field :email
|
||||
%tr{"data-hook" => "url"}
|
||||
%td URL:
|
||||
%td= f.text_field :url
|
||||
%tr{"data-hook" => "abn"}
|
||||
%td ABN:
|
||||
%td= f.text_field :abn
|
||||
%tr{"data-hook" => "acn"}
|
||||
%td ACN:
|
||||
%td= f.text_field :acn
|
||||
%fieldset
|
||||
%legend Pickup details
|
||||
%table{"data-hook" => "distributors_pickup_details"}
|
||||
%tr{"data-hook" => "next_collection_at"}
|
||||
%td Next collection date/time:
|
||||
%td= f.text_field :next_collection_at
|
||||
%tr{"data-hook" => "pickup_times"}
|
||||
%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
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
<div class="toolbar" data-hook="toolbar">
|
||||
<ul class="actions">
|
||||
<li>
|
||||
@@ -8,30 +7,34 @@
|
||||
<br class="clear" />
|
||||
</div>
|
||||
|
||||
<table class="index" id='listing_distributors'>
|
||||
<thead>
|
||||
<tr data-hook="distributors_header">
|
||||
<th>Name</th>
|
||||
<th>
|
||||
Description
|
||||
</th>
|
||||
<th>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @distributors.each do |distributor| %>
|
||||
<tr >
|
||||
<td><%= link_to distributor.name, spree.admin_distributor_path(distributor) %></td>
|
||||
<td><%=distributor.description %></td>
|
||||
<td data-hook="admin_users_index_row_actions">
|
||||
<%= link_to_edit distributor, :class => 'edit' %>
|
||||
<%= link_to_delete distributor %>
|
||||
</td>
|
||||
<%= form_for @distributor_set, :url => bulk_update_admin_distributors_path do |f| %>
|
||||
<table class="index" id="listing_distributors">
|
||||
<thead>
|
||||
<tr data-hook="distributors_header">
|
||||
<th>Name</th>
|
||||
<th>Next Collection Date/Time</th>
|
||||
<th>Description</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% if @distributors.empty? %>
|
||||
<tr><td colspan="2"><%= t(:none) %></td></tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody>
|
||||
<%= f.fields_for :distributors do |distributor_form| %>
|
||||
<% distributor = distributor_form.object %>
|
||||
<tr>
|
||||
<td><%= link_to distributor.name, spree.admin_distributor_path(distributor) %></td>
|
||||
<td><%= distributor_form.text_field :next_collection_at %></td>
|
||||
<td><%= distributor.description %></td>
|
||||
<td data-hook="admin_users_index_row_actions">
|
||||
<%= link_to_edit distributor, :class => 'edit' %>
|
||||
<%= link_to_delete distributor %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% if @distributors.empty? %>
|
||||
<tr><td colspan="4"><%= t(:none) %></td></tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= f.submit 'Update' %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
<h1>Distributor</h1>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<td>
|
||||
<%= @distributor.name %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<td>
|
||||
<%= @distributor.description %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Contact person</th>
|
||||
<td>
|
||||
<%= @distributor.contact %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Phone number</th>
|
||||
<td>
|
||||
<%= @distributor.phone %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<th>Email</th>
|
||||
<td>
|
||||
<%= @distributor.email %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<th>Pickup address</th>
|
||||
<td>
|
||||
<%= @distributor.pickup_address %>
|
||||
</td>
|
||||
</tr>
|
||||
<th>Pickup city</th>
|
||||
<td>
|
||||
<%= @distributor.city %>
|
||||
</td>
|
||||
</tr>
|
||||
<th>Pickup post code</th>
|
||||
<td>
|
||||
<%= @distributor.post_code %>
|
||||
</td>
|
||||
</tr>
|
||||
<th>Pickup country</th>
|
||||
<td>
|
||||
<%= @distributor.country.name if @distributor.country %>
|
||||
</td>
|
||||
</tr>
|
||||
<th>Pickup state</th>
|
||||
<td>
|
||||
<%= @distributor.state.name if @distributor.state %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<th>Pickup times</th>
|
||||
<td>
|
||||
<%= @distributor.pickup_times %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<th>ABN</th>
|
||||
<td>
|
||||
<%= @distributor.abn %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<th>ACN</th>
|
||||
<td>
|
||||
<%= @distributor.acn %>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<th>URL</th>
|
||||
<td>
|
||||
<%= @distributor.url %>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p>
|
||||
<%= link_to :Edit, spree.edit_admin_distributor_path(@distributor), :class => 'edit_distributor' %> <%= t(:or) %>
|
||||
<%= link_to t(:back), spree.admin_distributors_path %>
|
||||
</p>
|
||||
39
app/views/spree/admin/distributors/show.html.haml
Normal file
39
app/views/spree/admin/distributors/show.html.haml
Normal file
@@ -0,0 +1,39 @@
|
||||
%h1 Distributor
|
||||
%table
|
||||
%tr
|
||||
%th Name:
|
||||
%td= @distributor.name
|
||||
%tr
|
||||
%th Description:
|
||||
%td= @distributor.description
|
||||
%tr
|
||||
%th Contact person:
|
||||
%td= @distributor.contact
|
||||
%tr
|
||||
%th Phone number:
|
||||
%td= @distributor.phone
|
||||
%tr
|
||||
%th Email:
|
||||
%td= @distributor.email
|
||||
%tr
|
||||
%th Pickup address:
|
||||
%td= render 'spree/shared/address', :address => @distributor.pickup_address
|
||||
%tr
|
||||
%th Next collection date/time:
|
||||
%td= @distributor.next_collection_at
|
||||
%tr
|
||||
%th Regular pickup times:
|
||||
%td= @distributor.pickup_times
|
||||
%tr
|
||||
%th ABN:
|
||||
%td= @distributor.abn
|
||||
%tr
|
||||
%th ACN:
|
||||
%td= @distributor.acn
|
||||
%tr
|
||||
%th URL:
|
||||
%td= @distributor.url
|
||||
%p
|
||||
= link_to :Edit, spree.edit_admin_distributor_path(@distributor), :class => 'edit_distributor'
|
||||
= t(:or)
|
||||
= link_to t(:back), spree.admin_distributors_path
|
||||
@@ -1,5 +1,14 @@
|
||||
= f.field_container :distributors do
|
||||
= f.label :distributors
|
||||
%br
|
||||
= f.collection_check_boxes(:distributor_ids, Spree::Distributor.all, :id, :name)
|
||||
= f.error_message_on :distributors
|
||||
%h2 Distributors
|
||||
= f.field_container :product_distributions do
|
||||
- f.object.build_product_distributions
|
||||
%table
|
||||
= f.fields_for :product_distributions do |pd_form|
|
||||
%tr
|
||||
%td
|
||||
= hidden_field_tag "#{pd_form.object_name}[_destroy]", 1, :id => nil
|
||||
= check_box_tag "#{pd_form.object_name}[_destroy]", 0, !pd_form.object.new_record?
|
||||
%td
|
||||
= label_tag "#{pd_form.object_name}[_destroy]", pd_form.object.distributor.name
|
||||
= pd_form.hidden_field :distributor_id
|
||||
%td
|
||||
= pd_form.collection_select :shipping_method_id, Spree::ShippingMethod.all, :id, :name
|
||||
|
||||
18
app/views/spree/admin/shared/_address_form.html.haml
Normal file
18
app/views/spree/admin/shared/_address_form.html.haml
Normal file
@@ -0,0 +1,18 @@
|
||||
%tr{"data-hook" => "address1"}
|
||||
%td Address:
|
||||
%td= form.text_field :address1
|
||||
%tr{"data-hook" => "address2"}
|
||||
%td Address (cont.):
|
||||
%td= form.text_field :address2
|
||||
%tr{"data-hook" => "city"}
|
||||
%td City:
|
||||
%td= form.text_field :city
|
||||
%tr{"data-hook" => "zipcode"}
|
||||
%td Postcode:
|
||||
%td= form.text_field :zipcode
|
||||
%tr{"data-hook" => "country"}
|
||||
%td Country:
|
||||
%td= form.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)
|
||||
@@ -5,21 +5,8 @@
|
||||
%tr{'data-hook' => "description"}
|
||||
%td Description:
|
||||
%td= f.text_field :description
|
||||
%tr{'data-hook' => "address"}
|
||||
%td Address:
|
||||
%td= f.text_field :address
|
||||
%tr{'data-hook' => "city"}
|
||||
%td City:
|
||||
%td= f.text_field :city
|
||||
%tr{'data-hook' => "post_code"}
|
||||
%td Post Code:
|
||||
%td= f.text_field :postcode
|
||||
%tr{'data-hook' => "country"}
|
||||
%td Country:
|
||||
%td= f.collection_select(:country_id, @countries, :id, :name, :include_blank => true)
|
||||
%tr{'data-hook' => "state"}
|
||||
%td State:
|
||||
%td= f.collection_select(:state_id, @supplier.country.states, :id, :name, :include_blank => true)
|
||||
= f.fields_for :address do |address_form|
|
||||
= render 'spree/admin/shared/address_form', :form => address_form
|
||||
%tr{'data-hook' => "email"}
|
||||
%td Email:
|
||||
%td= f.text_field :email
|
||||
@@ -28,4 +15,4 @@
|
||||
%td= f.text_field :website
|
||||
%tr{'data-hook' => "twitter"}
|
||||
%td Twitter:
|
||||
%td= f.text_field :twitter
|
||||
%td= f.text_field :twitter
|
||||
|
||||
@@ -1,34 +1,22 @@
|
||||
%h1 Supplier
|
||||
%table
|
||||
%tr
|
||||
%th Name
|
||||
%th Name:
|
||||
%td= @supplier.name
|
||||
%tr
|
||||
%th Description
|
||||
%th Description:
|
||||
%td= @supplier.description
|
||||
%tr
|
||||
%th Address
|
||||
%td= @supplier.address
|
||||
%th Address:
|
||||
%td= render 'spree/shared/address', :address => @supplier.address
|
||||
%tr
|
||||
%th City:
|
||||
%td= @supplier.city
|
||||
%tr
|
||||
%th Post Code:
|
||||
%td= @supplier.postcode
|
||||
%tr
|
||||
%th Country:
|
||||
%td= @supplier.country.name if @supplier.country
|
||||
%tr
|
||||
%th State:
|
||||
%td= @supplier.state.name if @supplier.state
|
||||
%tr
|
||||
%th Email
|
||||
%th Email:
|
||||
%td= @supplier.email
|
||||
%tr
|
||||
%th Website
|
||||
%th Website:
|
||||
%td= @supplier.website
|
||||
%tr
|
||||
%th Twitter
|
||||
%th Twitter:
|
||||
%td= @supplier.twitter
|
||||
%p
|
||||
= link_to :Edit, spree.edit_admin_supplier_path(@supplier), :class => 'edit_supplier'
|
||||
|
||||
@@ -1,5 +1,27 @@
|
||||
.columns.omega.six
|
||||
%fieldset{:id => 'shipping'}
|
||||
%legend Collection Point
|
||||
=form.collection_select("distributor_id", Spree::Distributor.all, :id, :name, {}, {:class => 'required'})
|
||||
%fieldset#shipping
|
||||
%legend Distributor
|
||||
%h2= @order.distributor.name
|
||||
%p
|
||||
%strong Address:
|
||||
%br/
|
||||
= render 'spree/shared/address', :address => @order.distributor.pickup_address
|
||||
%p
|
||||
%strong Next collection time:
|
||||
%br/
|
||||
= @order.distributor.next_collection_at
|
||||
%p
|
||||
%strong Regular collection times:
|
||||
%br/
|
||||
= @order.distributor.pickup_times
|
||||
%p
|
||||
%strong Contact:
|
||||
%br/
|
||||
= @order.distributor.contact
|
||||
%br/
|
||||
= "Phone: #{@order.distributor.phone}"
|
||||
%br/
|
||||
= "Email: #{@order.distributor.email}"
|
||||
%p= @order.distributor.description
|
||||
%p= link_to @order.distributor.url, @order.distributor.url if @order.distributor.url
|
||||
|
||||
|
||||
17
app/views/spree/orders/_distributor_fees.html.haml
Normal file
17
app/views/spree/orders/_distributor_fees.html.haml
Normal file
@@ -0,0 +1,17 @@
|
||||
#delivery-fees
|
||||
%h2 Delivery Fees
|
||||
|
||||
%table#delivery
|
||||
%thead
|
||||
%tr
|
||||
%th Item
|
||||
%th Shipping Method
|
||||
%th Delivery Fee
|
||||
%tbody
|
||||
- @order.line_items.each do |line_item|
|
||||
- tr_class = cycle('', 'alt')
|
||||
%tr{:class => tr_class}
|
||||
%td
|
||||
%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
|
||||
6
app/views/spree/orders/_empty_cart_form.html.haml
Normal file
6
app/views/spree/orders/_empty_cart_form.html.haml
Normal file
@@ -0,0 +1,6 @@
|
||||
#empty-cart{'data-hook' => ""}
|
||||
= form_tag empty_cart_path, :method => :put do
|
||||
%p#clear_cart_link{'data-hook' => ""}
|
||||
= link_to t(:continue_shopping), products_path, :class => 'continue button'
|
||||
= t(:or)
|
||||
= submit_tag t(:empty_cart), :class => 'button'
|
||||
14
app/views/spree/orders/_inside_cart_form.html.haml
Normal file
14
app/views/spree/orders/_inside_cart_form.html.haml
Normal file
@@ -0,0 +1,14 @@
|
||||
%div{'data-hook' => "inside_cart_form"}
|
||||
%div{'data-hook' => "cart_items"}
|
||||
= render :partial => 'form', :locals => { :order_form => order_form }
|
||||
|
||||
#subtotal{'data-hook' => ""}
|
||||
%h5
|
||||
= t(:subtotal)
|
||||
\:
|
||||
%span.order-total= order_subtotal(@order)
|
||||
|
||||
.links{'data-hook' => "cart_buttons"}
|
||||
= button_tag :class => 'primary', :id => 'update-button' do
|
||||
= t(:update)
|
||||
= link_to t(:checkout), checkout_path, :class => 'button checkout primary', :id => 'checkout-link'
|
||||
24
app/views/spree/products/_add_to_cart.html.haml
Normal file
24
app/views/spree/products/_add_to_cart.html.haml
Normal file
@@ -0,0 +1,24 @@
|
||||
.add-to-cart
|
||||
- if !@product.has_stock? && !Spree::Config[:allow_backorders]
|
||||
= content_tag('strong', t(:out_of_stock))
|
||||
|
||||
- elsif current_order(false) && !current_order(false).can_add_product_to_cart?(@product)
|
||||
.error-distributor
|
||||
Please complete your order at
|
||||
= link_to current_distributor.name, root_path
|
||||
before shopping with another distributor.
|
||||
|
||||
- else
|
||||
%p Quantity
|
||||
= number_field_tag (@product.has_variants? ? :quantity : "variants[#{@product.master.id}]"), 1, :class => 'title', :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)
|
||||
- else
|
||||
= hidden_field_tag "distributor_id", order.distributor.id
|
||||
.distributor-fixed= "Your distributor for this order is #{order.distributor.name}"
|
||||
%br/
|
||||
= button_tag :class => 'large primary', :id => 'add-to-cart-button', :type => :submit do
|
||||
= t(:add_to_cart)
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
%td
|
||||
%strong Supplier
|
||||
%td= @product.supplier.name
|
||||
%br/
|
||||
%table#product-source.table-display{:width => "100%"}
|
||||
%tbody
|
||||
- @product.distributors.each do |distributor|
|
||||
%tr.even
|
||||
%td
|
||||
|
||||
@@ -6,5 +6,14 @@
|
||||
|
||||
%h6.filter_name Shop by Distributor
|
||||
%ul.filter_choices
|
||||
- order = current_order(false)
|
||||
- @distributors.each do |distributor|
|
||||
%li.nowrap= link_to distributor.name, select_distributor_path(distributor)
|
||||
%li.nowrap
|
||||
- if order.nil? || order.can_change_distributor?
|
||||
= link_to distributor.name, select_distributor_path(distributor)
|
||||
- elsif order.distributor == distributor
|
||||
= link_to distributor.name, root_path
|
||||
- else
|
||||
%span.inactive= distributor.name
|
||||
- if current_distributor && order.can_change_distributor?
|
||||
= button_to 'Browse All Distributors', deselect_distributors_path, :method => :get
|
||||
|
||||
4
app/views/spree/shared/_address.html.haml
Normal file
4
app/views/spree/shared/_address.html.haml
Normal file
@@ -0,0 +1,4 @@
|
||||
= address.address1
|
||||
= ", #{address.address2}" unless address.address2.blank?
|
||||
%br/
|
||||
= [address.city, address.state_text, address.zipcode, address.country.name].compact.join ', '
|
||||
@@ -1,19 +0,0 @@
|
||||
<% filters = @taxon ? @taxon.applicable_filters : [] %>
|
||||
<% unless filters.empty? %>
|
||||
<nav id="filters">
|
||||
<% params[:search] ||= {} %>
|
||||
<% filters.each do |filter| %>
|
||||
<% labels = filter[:labels] || filter[:conds].map {|m,c| [m,m]} %>
|
||||
<% next if labels.empty? %>
|
||||
<h6 class="filter_name">Shop by <%= filter[:name] %></h6>
|
||||
<ul class="filter_choices">
|
||||
<% labels.each do |nm,val| %>
|
||||
<li class="nowrap">
|
||||
<% active = params[:search][filter[:scope]] && params[:search][filter[:scope]].include?(val.to_s) %>
|
||||
<%= link_to nm, "?search[#{filter[:scope].to_s}][]=#{CGI.escape(val)}" %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
<% end %>
|
||||
</nav>
|
||||
<% end %>
|
||||
15
app/views/spree/shared/_filters.html.haml
Normal file
15
app/views/spree/shared/_filters.html.haml
Normal file
@@ -0,0 +1,15 @@
|
||||
- filters = @taxon ? @taxon.applicable_filters : []
|
||||
- unless filters.empty?
|
||||
%nav#filters
|
||||
- params[:search] ||= {}
|
||||
- filters.each do |filter|
|
||||
- labels = filter[:labels] || filter[:conds].map {|m,c| [m,m]}
|
||||
- next if labels.empty?
|
||||
|
||||
%h6.filter_name= "Shop by #{filter[:name]}"
|
||||
|
||||
%ul.filter_choices
|
||||
- labels.each do |nm,val|
|
||||
%li.nowrap
|
||||
- active = params[:search][filter[:scope]] && params[:search][filter[:scope]].include?(val.to_s)
|
||||
= link_to nm, "?search[#{filter[:scope].to_s}][]=#{CGI.escape(val)}"
|
||||
@@ -0,0 +1,2 @@
|
||||
- if order.payment_method.type == "Spree::PaymentMethod::Check"
|
||||
= simple_format order.payment_method.description
|
||||
23
app/views/spree/shared/_products.html.haml
Normal file
23
app/views/spree/shared/_products.html.haml
Normal file
@@ -0,0 +1,23 @@
|
||||
- paginated_products = @searcher.retrieve_products if params.key?(:keywords)
|
||||
- paginated_products ||= products
|
||||
|
||||
- if products.empty?
|
||||
= t(:no_products_found)
|
||||
- elsif params.key?(:keywords)
|
||||
%h6.search-results-title= t(:search_results, :keywords => h(params[:keywords]))
|
||||
|
||||
- if products.any?
|
||||
%ul.inline.product-listing{"data-hook" => ""}
|
||||
- reset_cycle('default')
|
||||
- products.each do |product|
|
||||
- if Spree::Config[:show_zero_stock_products] || product.has_stock?
|
||||
%li{:class => "columns three #{cycle("alpha", "secondary", "", "omega secondary")}", "data-hook" => "products_list_item", :id => "product_#{product.id}", :itemscope => "", :itemtype => "http://schema.org/Product"}
|
||||
.product-image
|
||||
= link_to small_image(product, :itemprop => "image"), product, :itemprop => 'url'
|
||||
= link_to truncate(product.name, :length => 50), product, :class => 'info', :itemprop => "name", :title => product.name
|
||||
%span.price.selling{:itemprop => "price"}= number_to_currency product.price
|
||||
|
||||
- if paginated_products.respond_to?(:num_pages)
|
||||
- params.delete(:search)
|
||||
- params.delete(:taxon)
|
||||
= paginate paginated_products
|
||||
@@ -0,0 +1,9 @@
|
||||
- if @products
|
||||
#products= render 'spree/shared/products', :products => @products, :taxon => @taxon
|
||||
- else
|
||||
#products-local
|
||||
%h2= "Products at #{current_distributor.name}"
|
||||
= render 'spree/shared/products', :products => @products_local, :taxon => @taxon
|
||||
#products-remote
|
||||
%h2 Products found elsewhere
|
||||
= render 'spree/shared/products', :products => @products_remote, :taxon => @taxon
|
||||
@@ -6,4 +6,5 @@
|
||||
|
||||
- if current_distributor
|
||||
%li#current-distributor{'data-hook' => ''}
|
||||
= "You are shopping at #{current_distributor.name}"
|
||||
You are shopping at
|
||||
= link_to current_distributor.name, root_path
|
||||
|
||||
@@ -24,6 +24,13 @@ module Openfoodweb
|
||||
end
|
||||
end
|
||||
|
||||
# Register Spree calculators
|
||||
initializer "spree.register.calculators" do |app|
|
||||
app.config.spree.calculators.shipping_methods << OpenFoodWeb::Calculator::Itemwise
|
||||
app.config.spree.calculators.shipping_methods << OpenFoodWeb::Calculator::Weight
|
||||
end
|
||||
|
||||
|
||||
# Settings in config/environments/* take precedence over those specified here.
|
||||
# Application configuration should go into files in config/initializers
|
||||
# -- all .rb files in that directory are automatically loaded.
|
||||
|
||||
@@ -16,7 +16,7 @@ Spree.config do |config|
|
||||
# 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.default_country_id = 12 # This should be Australia, see: spree/core/db/default/spree/countries.yml
|
||||
|
||||
config.searcher_class = OpenFoodWeb::Searcher
|
||||
end
|
||||
|
||||
@@ -8,10 +8,13 @@ Spree::Core::Engine.routes.prepend do
|
||||
resources :suppliers
|
||||
resources :distributors do
|
||||
get :select, :on => :member
|
||||
get :deselect, :on => :collection
|
||||
end
|
||||
|
||||
namespace :admin do
|
||||
resources :distributors
|
||||
resources :distributors do
|
||||
post :bulk_update, :on => :collection, :as => :bulk_update
|
||||
end
|
||||
resources :suppliers
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
class ExtractDistributorAndSupplierAddressToSpreeAddress < ActiveRecord::Migration
|
||||
def up
|
||||
# -- Distributors
|
||||
add_column :distributors, :pickup_address_id, :integer
|
||||
Spree::Distributor.reset_column_information
|
||||
|
||||
Spree::Distributor.all.each do |distributor|
|
||||
pickup_address = Spree::Address.create!(:firstname => 'unused',
|
||||
:lastname => 'unused',
|
||||
:phone => 'unused',
|
||||
:address1 => distributor[:pickup_address],
|
||||
:city => distributor.city,
|
||||
:zipcode => distributor.post_code,
|
||||
:state_id => distributor.state_id,
|
||||
:country_id => distributor.country_id)
|
||||
distributor.pickup_address = pickup_address
|
||||
distributor.save!
|
||||
end
|
||||
|
||||
%w(pickup_address city post_code state_id country_id).each do |column|
|
||||
remove_column :distributors, column
|
||||
end
|
||||
|
||||
|
||||
# -- Suppliers
|
||||
add_column :suppliers, :address_id, :integer
|
||||
Spree::Supplier.reset_column_information
|
||||
|
||||
Spree::Supplier.all.each do |supplier|
|
||||
address = Spree::Address.create!(:firstname => 'unused',
|
||||
:lastname => 'unused',
|
||||
:phone => 'unused',
|
||||
:address1 => supplier[:address],
|
||||
:city => supplier.city,
|
||||
:zipcode => supplier.postcode,
|
||||
:state_id => supplier.state_id,
|
||||
:country_id => supplier.country_id)
|
||||
supplier.address = address
|
||||
supplier.save!
|
||||
end
|
||||
|
||||
%w(address city postcode state_id country_id).each do |column|
|
||||
remove_column :suppliers, column
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
# -- Distributors
|
||||
add_column :distributors, :pickup_address, :string
|
||||
add_column :distributors, :city, :string
|
||||
add_column :distributors, :post_code, :string
|
||||
add_column :distributors, :state_id, :integer
|
||||
add_column :distributors, :country_id, :integer
|
||||
Spree::Distributor.reset_column_information
|
||||
|
||||
Spree::Distributor.all.each do |distributor|
|
||||
distributor[:pickup_address] = distributor.pickup_address.address1
|
||||
distributor.city = distributor.pickup_address.city
|
||||
distributor.post_code = distributor.pickup_address.zipcode
|
||||
distributor.state_id = distributor.pickup_address.state_id
|
||||
distributor.country_id = distributor.pickup_address.country_id
|
||||
distributor.save!
|
||||
end
|
||||
|
||||
remove_column :distributors, :pickup_address_id
|
||||
|
||||
|
||||
# -- Suppliers
|
||||
add_column :suppliers, :address, :string
|
||||
add_column :suppliers, :city, :string
|
||||
add_column :suppliers, :postcode, :string
|
||||
add_column :suppliers, :state_id, :integer
|
||||
add_column :suppliers, :country_id, :integer
|
||||
Spree::Supplier.reset_column_information
|
||||
|
||||
Spree::Supplier.all.each do |supplier|
|
||||
supplier[:address] = supplier.address.address1
|
||||
supplier.city = supplier.address.city
|
||||
supplier.post_code = supplier.address.zipcode
|
||||
supplier.state_id = supplier.address.state_id
|
||||
supplier.country_id = supplier.address.country_id
|
||||
supplier.save!
|
||||
end
|
||||
|
||||
remove_column :suppliers, :address_id
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,24 @@
|
||||
class RenameDistributorsProductsToProductDistributions < ActiveRecord::Migration
|
||||
def up
|
||||
# Convert m2m join table into explicit join model, and add a shipping method relation and timestamps
|
||||
rename_table :distributors_products, :product_distributions
|
||||
add_column :product_distributions, :id, :primary_key
|
||||
change_table :product_distributions do |t|
|
||||
t.references :shipping_method
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
# Set default shipping method on all product distributions
|
||||
sm = Spree::ShippingMethod.first
|
||||
Spree::ProductDistribution.update_all(:shipping_method_id => sm.id) if sm
|
||||
end
|
||||
|
||||
def down
|
||||
change_table :product_distributions do |t|
|
||||
t.remove :id
|
||||
t.remove :shipping_method_id
|
||||
t.remove :created_at, :updated_at
|
||||
end
|
||||
rename_table :product_distributions, :distributors_products
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
# This migration comes from spree (originally 20120507232704)
|
||||
class IncreaseScaleOfTaxRateAmount < ActiveRecord::Migration
|
||||
def up
|
||||
change_column :spree_tax_rates, :amount, :decimal, { :scale => 5, :precision => 8 }
|
||||
end
|
||||
|
||||
def down
|
||||
change_column :spree_tax_rates, :amount, :decimal, { :scale => 4, :precision => 8 }
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,6 @@
|
||||
# This migration comes from spree_auth (originally 20120203010234)
|
||||
class AddResetPasswordSentAtToSpreeUsers < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :spree_users, :reset_password_sent_at, :datetime
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,6 @@
|
||||
# This migration comes from spree_api (originally 20120411123334)
|
||||
class ResizeApiKeyField < ActiveRecord::Migration
|
||||
def change
|
||||
change_column :spree_users, :api_key, :string, :limit => 48
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
# This migration comes from spree_paypal_express (originally 20100224133156)
|
||||
class CreatePaypalAccounts < ActiveRecord::Migration
|
||||
def self.up
|
||||
create_table :paypal_accounts do |t|
|
||||
t.string :email
|
||||
t.string :payer_id
|
||||
t.string :payer_country
|
||||
t.string :payer_status
|
||||
end
|
||||
end
|
||||
|
||||
def self.down
|
||||
drop_table :paypal_accounts
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,6 @@
|
||||
# This migration comes from spree_paypal_express (originally 20120117182027)
|
||||
class NamespacePaypalAccounts < ActiveRecord::Migration
|
||||
def change
|
||||
rename_table :paypal_accounts, :spree_paypal_accounts
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
class AddNextCollectionAtToDistributors < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :distributors, :next_collection_at, :string
|
||||
end
|
||||
end
|
||||
40
db/schema.rb
40
db/schema.rb
@@ -11,14 +11,13 @@
|
||||
#
|
||||
# It's strongly recommended to check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 20120621064227) do
|
||||
ActiveRecord::Schema.define(:version => 20120702020402) do
|
||||
|
||||
create_table "distributors", :force => true do |t|
|
||||
t.string "name"
|
||||
t.string "contact"
|
||||
t.string "phone"
|
||||
t.string "email"
|
||||
t.string "pickup_address"
|
||||
t.string "pickup_times"
|
||||
t.string "url"
|
||||
t.string "abn"
|
||||
@@ -26,15 +25,16 @@ ActiveRecord::Schema.define(:version => 20120621064227) do
|
||||
t.string "description"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "city"
|
||||
t.string "post_code"
|
||||
t.integer "country_id"
|
||||
t.integer "state_id"
|
||||
t.integer "pickup_address_id"
|
||||
t.string "next_collection_at"
|
||||
end
|
||||
|
||||
create_table "distributors_products", :id => false, :force => true do |t|
|
||||
t.integer "product_id"
|
||||
t.integer "distributor_id"
|
||||
create_table "product_distributions", :force => true do |t|
|
||||
t.integer "product_id"
|
||||
t.integer "distributor_id"
|
||||
t.integer "shipping_method_id"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
create_table "spree_activators", :force => true do |t|
|
||||
@@ -283,6 +283,13 @@ ActiveRecord::Schema.define(:version => 20120621064227) do
|
||||
t.string "avs_response"
|
||||
end
|
||||
|
||||
create_table "spree_paypal_accounts", :force => true do |t|
|
||||
t.string "email"
|
||||
t.string "payer_id"
|
||||
t.string "payer_country"
|
||||
t.string "payer_status"
|
||||
end
|
||||
|
||||
create_table "spree_pending_promotions", :force => true do |t|
|
||||
t.integer "user_id"
|
||||
t.integer "promotion_id"
|
||||
@@ -525,7 +532,7 @@ ActiveRecord::Schema.define(:version => 20120621064227) do
|
||||
end
|
||||
|
||||
create_table "spree_tax_rates", :force => true do |t|
|
||||
t.decimal "amount", :precision => 8, :scale => 4
|
||||
t.decimal "amount", :precision => 8, :scale => 5
|
||||
t.integer "zone_id"
|
||||
t.integer "tax_category_id"
|
||||
t.datetime "created_at"
|
||||
@@ -586,8 +593,8 @@ ActiveRecord::Schema.define(:version => 20120621064227) do
|
||||
t.string "persistence_token"
|
||||
t.string "reset_password_token"
|
||||
t.string "perishable_token"
|
||||
t.integer "sign_in_count", :default => 0, :null => false
|
||||
t.integer "failed_attempts", :default => 0, :null => false
|
||||
t.integer "sign_in_count", :default => 0, :null => false
|
||||
t.integer "failed_attempts", :default => 0, :null => false
|
||||
t.datetime "last_request_at"
|
||||
t.datetime "current_sign_in_at"
|
||||
t.datetime "last_sign_in_at"
|
||||
@@ -602,7 +609,8 @@ ActiveRecord::Schema.define(:version => 20120621064227) do
|
||||
t.string "unlock_token"
|
||||
t.datetime "locked_at"
|
||||
t.datetime "remember_created_at"
|
||||
t.string "api_key", :limit => 40
|
||||
t.string "api_key", :limit => 48
|
||||
t.datetime "reset_password_sent_at"
|
||||
end
|
||||
|
||||
add_index "spree_users", ["persistence_token"], :name => "index_users_on_persistence_token"
|
||||
@@ -648,11 +656,7 @@ ActiveRecord::Schema.define(:version => 20120621064227) do
|
||||
t.string "website"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.string "address"
|
||||
t.string "city"
|
||||
t.string "postcode"
|
||||
t.integer "state_id"
|
||||
t.integer "country_id"
|
||||
t.integer "address_id"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
13
db/seeds.rb
13
db/seeds.rb
@@ -1,7 +1,7 @@
|
||||
# This file should contain all the record creation needed to seed the database with its default values.
|
||||
# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
|
||||
|
||||
require File.expand_path('../../spec/support/factories', __FILE__)
|
||||
require File.expand_path('../../spec/factories', __FILE__)
|
||||
|
||||
|
||||
# -- Spree
|
||||
@@ -36,6 +36,17 @@ unless Spree::State.find_by_name 'Victoria'
|
||||
end
|
||||
|
||||
|
||||
# -- Shipping / payment information
|
||||
unless Spree::Zone.find_by_name 'Australia'
|
||||
puts "[db:seed] Seeding shipping / payment information"
|
||||
zone = FactoryGirl.create(:zone, :name => 'Australia', :zone_members => [])
|
||||
country = Spree::Country.find_by_name('Australia')
|
||||
Spree::ZoneMember.create(:zone => zone, :zoneable => country)
|
||||
FactoryGirl.create(:shipping_method, :zone => zone)
|
||||
FactoryGirl.create(:payment_method, :environment => 'development')
|
||||
end
|
||||
|
||||
|
||||
# -- Taxonomies
|
||||
unless Spree::Taxonomy.find_by_name 'Products'
|
||||
puts "[db:seed] Seeding taxonomies"
|
||||
|
||||
19
lib/open_food_web/split_products_by_distributor.rb
Normal file
19
lib/open_food_web/split_products_by_distributor.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
module OpenFoodWeb
|
||||
module SplitProductsByDistributor
|
||||
|
||||
# If a distributor is provided, split the list of products into local (at that
|
||||
# distributor) and remote (at another distributor). If a distributor is not
|
||||
# provided, perform no split.
|
||||
def split_products_by_distributor(products, distributor)
|
||||
products_local = products_remote = nil
|
||||
|
||||
if distributor
|
||||
products_local = products.select { |p| p.distributors.include? distributor }
|
||||
products_remote = products.reject { |p| p.distributors.include? distributor }
|
||||
products = nil
|
||||
end
|
||||
|
||||
[products, products_local, products_remote]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -4,13 +4,69 @@ require 'spree/core/current_order'
|
||||
describe Spree::DistributorsController do
|
||||
include Spree::Core::CurrentOrder
|
||||
|
||||
before do
|
||||
stub!(:before_save_new_order)
|
||||
stub!(:after_save_new_order)
|
||||
end
|
||||
|
||||
|
||||
it "selects distributors" do
|
||||
d = create(:distributor)
|
||||
|
||||
spree_get :select, :id => d.id
|
||||
response.should be_redirect
|
||||
|
||||
order = current_order(false)
|
||||
order.distributor.should == d
|
||||
end
|
||||
|
||||
it "deselects distributors" do
|
||||
d = create(:distributor)
|
||||
order = current_order(true)
|
||||
order.distributor = d
|
||||
order.save!
|
||||
|
||||
spree_get :deselect
|
||||
response.should be_redirect
|
||||
|
||||
order.reload
|
||||
order.distributor.should be_nil
|
||||
end
|
||||
|
||||
context "when a product has been added to the cart" do
|
||||
it "does not allow selecting another distributor" do
|
||||
# Given some distributors and an order with a product
|
||||
d1 = create(:distributor)
|
||||
d2 = create(:distributor)
|
||||
p = create(:product, :distributors => [d1])
|
||||
o = current_order(true)
|
||||
o.distributor = d1
|
||||
o.add_variant(p.master, 1)
|
||||
o.save!
|
||||
|
||||
# When I attempt to select a distributor
|
||||
spree_get :select, :id => d2.id
|
||||
|
||||
# Then my distributor should remain unchanged
|
||||
o.reload
|
||||
o.distributor.should == d1
|
||||
end
|
||||
|
||||
it "does not allow deselecting distributors" do
|
||||
# Given a distributor and an order with a product
|
||||
d = create(:distributor)
|
||||
p = create(:product, :distributors => [d])
|
||||
o = current_order(true)
|
||||
o.distributor = d
|
||||
o.add_variant(p.master, 1)
|
||||
o.save!
|
||||
|
||||
# When I attempt to deselect the distributor
|
||||
spree_get :deselect
|
||||
|
||||
# Then my distributor should remain unchanged
|
||||
o.reload
|
||||
o.distributor.should == d
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
28
spec/controllers/home_controller_spec.rb
Normal file
28
spec/controllers/home_controller_spec.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Spree::HomeController do
|
||||
it "loads products" do
|
||||
product = create(:product)
|
||||
spree_get :index
|
||||
assigns(:products).should == [product]
|
||||
assigns(:products_local).should be_nil
|
||||
assigns(:products_remote).should be_nil
|
||||
end
|
||||
|
||||
it "splits products by local/remote distributor when distributor is selected" do
|
||||
# Given two distributors with a product under each
|
||||
d1 = create(:distributor)
|
||||
d2 = create(:distributor)
|
||||
p1 = create(:product, :distributors => [d1])
|
||||
p2 = create(:product, :distributors => [d2])
|
||||
|
||||
# And the first distributor is selected
|
||||
controller.stub(:current_distributor).and_return(d1)
|
||||
|
||||
# When I fetch the home page, the products should be split by local/remote distributor
|
||||
spree_get :index
|
||||
assigns(:products).should be_nil
|
||||
assigns(:products_local).should == [p1]
|
||||
assigns(:products_remote).should == [p2]
|
||||
end
|
||||
end
|
||||
112
spec/controllers/orders_controller_spec.rb
Normal file
112
spec/controllers/orders_controller_spec.rb
Normal file
@@ -0,0 +1,112 @@
|
||||
require 'spec_helper'
|
||||
require 'spree/core/current_order'
|
||||
|
||||
describe Spree::OrdersController do
|
||||
include Spree::Core::CurrentOrder
|
||||
|
||||
def current_user
|
||||
controller.current_user
|
||||
end
|
||||
|
||||
|
||||
context "adding the first product to the cart" do
|
||||
it "does not add the product if the user does not specify a distributor" do
|
||||
create(:distributor)
|
||||
p = create(:product)
|
||||
|
||||
expect do
|
||||
spree_put :populate, :variants => {p.id => 1}
|
||||
end.to change(Spree::LineItem, :count).by(0)
|
||||
end
|
||||
|
||||
it "does not add the product if the user specifies a distributor that the product is not available at" do
|
||||
distributor_product = create(:distributor)
|
||||
distributor_no_product = create(:distributor)
|
||||
p = create(:product, :distributors => [distributor_product])
|
||||
|
||||
expect do
|
||||
spree_put :populate, :variants => {p.id => 1}, :distributor_id => distributor_no_product.id
|
||||
end.to change(Spree::LineItem, :count).by(0)
|
||||
end
|
||||
|
||||
it "adds the product and sets the distributor even if the order has a different distributor set" do
|
||||
distributor_product = create(:distributor)
|
||||
distributor_no_product = create(:distributor)
|
||||
p = create(:product, :distributors => [distributor_product])
|
||||
|
||||
order = current_order(true)
|
||||
order.distributor = distributor_no_product
|
||||
order.save!
|
||||
|
||||
expect do
|
||||
spree_put :populate, :variants => {p.id => 1}, :distributor_id => distributor_product.id
|
||||
end.to change(Spree::LineItem, :count).by(1)
|
||||
|
||||
order.reload.distributor.should == distributor_product
|
||||
end
|
||||
|
||||
it "sets the order's distributor" do
|
||||
# Given a product in a distributor
|
||||
d = create(:distributor)
|
||||
p = create(:product, :distributors => [d])
|
||||
|
||||
# When we add the product to our cart
|
||||
spree_put :populate, :variants => {p.id => 1}, :distributor_id => d.id
|
||||
|
||||
# Then our order should have its distributor set to the chosen distributor
|
||||
current_order(false).distributor.should == d
|
||||
end
|
||||
end
|
||||
|
||||
context "adding a subsequent product to the cart" do
|
||||
before(:each) do
|
||||
# Given a product and a distributor
|
||||
@distributor = create(:distributor)
|
||||
@product = create(:product, :distributors => [@distributor])
|
||||
|
||||
# And the product is in the cart
|
||||
spree_put :populate, :variants => {@product.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
|
||||
|
||||
it "does not add the product if the product is not available at the order's distributor" do
|
||||
# Given a product at another distributor
|
||||
d2 = create(:distributor)
|
||||
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
|
||||
|
||||
# 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
|
||||
|
||||
it "does not add the product if the product is not available at the given distributor" do
|
||||
# Given a product at another distributor
|
||||
d2 = create(:distributor)
|
||||
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
|
||||
|
||||
# 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
|
||||
|
||||
it "does not add the product if the chosen distributor is different from the order's distributor" do
|
||||
# Given a product that's available at the chosen distributor and another distributor
|
||||
d2 = create(:distributor)
|
||||
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
|
||||
|
||||
# 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
|
||||
end
|
||||
53
spec/factories.rb
Normal file
53
spec/factories.rb
Normal file
@@ -0,0 +1,53 @@
|
||||
require 'faker'
|
||||
require 'spree/core/testing_support/factories'
|
||||
|
||||
FactoryGirl.define do
|
||||
factory :supplier, :class => Spree::Supplier do
|
||||
sequence(:name) { |n| "Supplier #{n}" }
|
||||
description 'supplier'
|
||||
email 'supplier@example.com'
|
||||
address { Spree::Address.first || FactoryGirl.create(:address) }
|
||||
end
|
||||
|
||||
factory :distributor, :class => Spree::Distributor do
|
||||
sequence(:name) { |n| "Distributor #{n}" }
|
||||
contact 'Mr Turing'
|
||||
phone '1000100100'
|
||||
description 'The creator'
|
||||
email 'alan@somewhere.com'
|
||||
url 'http://example.com'
|
||||
pickup_times "Whenever you're free"
|
||||
next_collection_at 'Thursday 10am'
|
||||
pickup_address { Spree::Address.first || FactoryGirl.create(:address) }
|
||||
end
|
||||
|
||||
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) }
|
||||
end
|
||||
|
||||
factory :itemwise_shipping_method, :parent => :shipping_method do
|
||||
name 'Delivery'
|
||||
calculator { FactoryGirl.build(:itemwise_calculator) }
|
||||
end
|
||||
|
||||
factory :itemwise_calculator, :class => OpenFoodWeb::Calculator::Itemwise do
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
FactoryGirl.modify do
|
||||
factory :simple_product do
|
||||
supplier { Spree::Supplier.first || FactoryGirl.create(:supplier) }
|
||||
|
||||
# before(:create) do |product, evaluator|
|
||||
# product.product_distributions = [FactoryGirl.create(:product_distribution, :product => product)]
|
||||
# end
|
||||
end
|
||||
|
||||
factory :address do
|
||||
state { Spree::State.find_by_name 'Victoria' }
|
||||
country { Spree::Country.find_by_name 'Australia' || Spree::Country.first }
|
||||
end
|
||||
end
|
||||
35
spec/helpers/products_helper_spec.rb
Normal file
35
spec/helpers/products_helper_spec.rb
Normal file
@@ -0,0 +1,35 @@
|
||||
require 'spec_helper'
|
||||
|
||||
module Spree
|
||||
describe ProductsHelper do
|
||||
subject do
|
||||
obj = Object.new
|
||||
obj.extend(ProductsHelper)
|
||||
obj.extend(ActionView::Helpers::NumberHelper)
|
||||
end
|
||||
|
||||
|
||||
it "displays variant price differences as absolute, not relative values" do
|
||||
variant = make_variant_stub(10.00, 10.00)
|
||||
subject.variant_price_diff(variant).should == "($10.00)"
|
||||
|
||||
variant = make_variant_stub(10.00, 15.55)
|
||||
subject.variant_price_diff(variant).should == "($15.55)"
|
||||
|
||||
variant = make_variant_stub(10.00, 5.55)
|
||||
subject.variant_price_diff(variant).should == "($5.55)"
|
||||
end
|
||||
|
||||
private
|
||||
def make_variant_stub(product_price, variant_price)
|
||||
product = stub(:product)
|
||||
product.stub(:price).and_return(product_price)
|
||||
|
||||
variant = stub(:variant)
|
||||
variant.stub(:product).and_return(product)
|
||||
variant.stub(:price).and_return(variant_price)
|
||||
|
||||
variant
|
||||
end
|
||||
end
|
||||
end
|
||||
30
spec/lib/open_food_web/split_products_by_distributor_spec.rb
Normal file
30
spec/lib/open_food_web/split_products_by_distributor_spec.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe OpenFoodWeb::SplitProductsByDistributor do
|
||||
let(:products_splitter) { Class.new { include OpenFoodWeb::SplitProductsByDistributor } }
|
||||
let(:subject) { products_splitter.new }
|
||||
|
||||
|
||||
it "does nothing when no distributor is selected" do
|
||||
orig_products = (1..3).map { |i| build(:product) }
|
||||
|
||||
products, products_local, products_remote = subject.split_products_by_distributor orig_products, nil
|
||||
|
||||
products.should == orig_products
|
||||
products_local.should be_nil
|
||||
products_remote.should be_nil
|
||||
end
|
||||
|
||||
it "splits products when a distributor is selected" do
|
||||
d1 = build(:distributor)
|
||||
d2 = build(:distributor)
|
||||
orig_products = [build(:product, :distributors => [d1]),
|
||||
build(:product, :distributors => [d2])]
|
||||
|
||||
products, products_local, products_remote = subject.split_products_by_distributor orig_products, d1
|
||||
|
||||
products.should be_nil
|
||||
products_local.should == [orig_products[0]]
|
||||
products_remote.should == [orig_products[1]]
|
||||
end
|
||||
end
|
||||
13
spec/models/calculator/itemwise_spec.rb
Normal file
13
spec/models/calculator/itemwise_spec.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe OpenFoodWeb::Calculator::Itemwise do
|
||||
it "computes the shipping cost for each line item in an order" do
|
||||
line_item = double(:line_item)
|
||||
line_item.should_receive(:itemwise_shipping_cost).exactly(3).times.and_return(10)
|
||||
|
||||
order = double(:order)
|
||||
order.stub(:line_items).and_return([line_item]*3)
|
||||
|
||||
subject.compute(order).should == 30
|
||||
end
|
||||
end
|
||||
16
spec/models/calculator/weight_spec.rb
Normal file
16
spec/models/calculator/weight_spec.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
require 'spec_helper'
|
||||
|
||||
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)
|
||||
|
||||
line_item_1 = double(:line_item, :variant => variant_1)
|
||||
line_item_2 = double(:line_item, :variant => variant_2)
|
||||
|
||||
order = double(:order, :line_items => [line_item_1, line_item_2])
|
||||
|
||||
subject.set_preference(:per_kg, 10)
|
||||
subject.compute(order).should == 300
|
||||
end
|
||||
end
|
||||
@@ -1,9 +1,21 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Spree::Distributor do
|
||||
module Spree
|
||||
describe Distributor do
|
||||
|
||||
it "should default the country to the default spree country" do
|
||||
describe "associations" do
|
||||
it { should belong_to(:pickup_address) }
|
||||
it { should have_many(:product_distributions) }
|
||||
it { should have_many(:orders) }
|
||||
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) }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
21
spec/models/line_item_spec.rb
Normal file
21
spec/models/line_item_spec.rb
Normal file
@@ -0,0 +1,21 @@
|
||||
require 'spec_helper'
|
||||
|
||||
module Spree
|
||||
describe LineItem do
|
||||
it "computes shipping cost for its product" do
|
||||
# Create a shipping method with flat rate of 10
|
||||
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(:order).and_return(order)
|
||||
|
||||
subject.itemwise_shipping_cost.should == 10
|
||||
end
|
||||
end
|
||||
end
|
||||
49
spec/models/order_spec.rb
Normal file
49
spec/models/order_spec.rb
Normal file
@@ -0,0 +1,49 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Spree::Order do
|
||||
it "reveals permission for changing distributor" do
|
||||
p = build(:product)
|
||||
|
||||
subject.can_change_distributor?.should be_true
|
||||
subject.add_variant(p.master, 1)
|
||||
subject.can_change_distributor?.should be_false
|
||||
end
|
||||
|
||||
it "raises an exception if distributor is changed without permission" do
|
||||
d = build(:distributor)
|
||||
p = build(:product, :distributors => [d])
|
||||
subject.distributor = d
|
||||
subject.add_variant(p.master, 1)
|
||||
subject.can_change_distributor?.should be_false
|
||||
|
||||
expect do
|
||||
subject.distributor = nil
|
||||
end.to raise_error "You cannot change the distributor of an order with products"
|
||||
end
|
||||
|
||||
it "reveals permission for adding products to the cart" do
|
||||
d1 = create(:distributor)
|
||||
d2 = create(:distributor)
|
||||
|
||||
p_first = create(:product, :distributors => [d1])
|
||||
p_subsequent_same_dist = create(:product, :distributors => [d1])
|
||||
p_subsequent_other_dist = create(:product, :distributors => [d2])
|
||||
|
||||
# We need to set distributor, since order.add_variant does not, and
|
||||
# we also need to save the order so that line items can be added to
|
||||
# the association.
|
||||
subject.distributor = d1
|
||||
subject.save!
|
||||
|
||||
# The first product in the cart can be added
|
||||
subject.can_add_product_to_cart?(p_first).should be_true
|
||||
subject.add_variant(p_first.master, 1)
|
||||
|
||||
# A subsequent product can be added if the distributor matches
|
||||
subject.can_add_product_to_cart?(p_subsequent_same_dist).should be_true
|
||||
subject.add_variant(p_subsequent_same_dist.master, 1)
|
||||
|
||||
# And cannot be added if it does not match
|
||||
subject.can_add_product_to_cart?(p_subsequent_other_dist).should be_false
|
||||
end
|
||||
end
|
||||
23
spec/models/product_distribution_spec.rb
Normal file
23
spec/models/product_distribution_spec.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Spree::ProductDistribution do
|
||||
it "is unique for scope [product, distributor]" do
|
||||
pd1 = create(:product_distribution)
|
||||
pd1.should be_valid
|
||||
|
||||
new_product = create(:product)
|
||||
new_distributor = create(:distributor)
|
||||
|
||||
pd2 = build(:product_distribution, :product => pd1.product, :distributor => pd1.distributor)
|
||||
pd2.should_not be_valid
|
||||
|
||||
pd2 = build(:product_distribution, :product => pd1.product, :distributor => new_distributor)
|
||||
pd2.should be_valid
|
||||
|
||||
pd2 = build(:product_distribution, :product => new_product, :distributor => pd1.distributor)
|
||||
pd2.should be_valid
|
||||
|
||||
pd2 = build(:product_distribution, :product => new_product, :distributor => new_distributor)
|
||||
pd2.should be_valid
|
||||
end
|
||||
end
|
||||
@@ -4,25 +4,36 @@ describe Spree::Product do
|
||||
|
||||
describe "associations" do
|
||||
it { should belong_to(:supplier) }
|
||||
it { should have_and_belong_to_many(:distributors) }
|
||||
it { should have_many(:product_distributions) }
|
||||
end
|
||||
|
||||
describe "validations" do
|
||||
it "is valid when created from factory" do
|
||||
build(:product).should be_valid
|
||||
create(:product).should be_valid
|
||||
end
|
||||
|
||||
it "requires a supplier" do
|
||||
product = build(:product)
|
||||
product = create(:product)
|
||||
product.supplier = nil
|
||||
product.should_not be_valid
|
||||
end
|
||||
|
||||
it "requires at least one distributor" do
|
||||
product = build(:product)
|
||||
product.distributors.clear
|
||||
product.should_not be_valid
|
||||
end
|
||||
end
|
||||
|
||||
context "finders" do
|
||||
it "finds the shipping method for a particular distributor" do
|
||||
shipping_method = create(:shipping_method)
|
||||
distributor = create(:distributor)
|
||||
product = create(:product)
|
||||
product_distribution = create(:product_distribution, :product => product, :distributor => distributor, :shipping_method => shipping_method)
|
||||
product.shipping_method_for_distributor(distributor).should == shipping_method
|
||||
end
|
||||
|
||||
it "raises an error if distributor is not found" do
|
||||
distributor = create(:distributor)
|
||||
product = create(:product)
|
||||
expect do
|
||||
product.shipping_method_for_distributor(distributor)
|
||||
end.to raise_error "This product is not available through that distributor"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,26 +1,21 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe Spree::Supplier do
|
||||
module Spree
|
||||
describe Supplier do
|
||||
|
||||
describe "associations" do
|
||||
it { should have_many(:products) }
|
||||
it { should belong_to(:address) }
|
||||
end
|
||||
|
||||
it "should default country to system country" do
|
||||
supplier = Supplier.new
|
||||
supplier.address.country.should == Country.find_by_id(Config[:default_country_id])
|
||||
end
|
||||
|
||||
describe "validations" do
|
||||
it { should validate_presence_of(:name) }
|
||||
end
|
||||
|
||||
describe "associations" do
|
||||
it { should have_many(:products) }
|
||||
end
|
||||
|
||||
it "should have an address"
|
||||
|
||||
it "should default country to system country" do
|
||||
supplier = Spree::Supplier.new
|
||||
|
||||
supplier.country.should == Spree::Country.find_by_id(Spree::Config[:default_country_id])
|
||||
end
|
||||
|
||||
describe 'validations' do
|
||||
it{ should validate_presence_of(:name) }
|
||||
it{ should validate_presence_of(:address) }
|
||||
it{ should validate_presence_of(:country_id) }
|
||||
it{ should validate_presence_of(:state_id) }
|
||||
it{ should validate_presence_of(:city) }
|
||||
it{ should validate_presence_of(:postcode) }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -7,34 +7,54 @@ feature %q{
|
||||
include AuthenticationWorkflow
|
||||
include WebHelper
|
||||
|
||||
background do
|
||||
|
||||
scenario "creating a new distributor" do
|
||||
login_to_admin_section
|
||||
|
||||
click_link 'Distributors'
|
||||
click_link 'New Distributor'
|
||||
|
||||
fill_in 'distributor_name', :with => 'Eaterprises'
|
||||
fill_in 'distributor_description', :with => 'Connecting farmers and eaters'
|
||||
fill_in 'distributor_contact', :with => 'Kirsten or Ren'
|
||||
fill_in 'distributor_phone', :with => '0413 897 321'
|
||||
|
||||
fill_in 'distributor_pickup_address_attributes_address1', :with => '35 Ballantyne St'
|
||||
fill_in 'distributor_pickup_address_attributes_city', :with => 'Thornbury'
|
||||
fill_in 'distributor_pickup_address_attributes_zipcode', :with => '3072'
|
||||
select('Australia', :from => 'distributor_pickup_address_attributes_country_id')
|
||||
select('Victoria', :from => 'distributor_pickup_address_attributes_state_id')
|
||||
|
||||
fill_in 'distributor_next_collection_at', :with => 'Thursday, 22nd Feb, 6 - 9 PM'
|
||||
fill_in 'distributor_pickup_times', :with => 'Thursday, 22nd Feb, 6 - 9 PM. Friday, 23nd Feb, 6 - 9 PM'
|
||||
fill_in 'distributor_email', :with => 'info@eaterprises.com.au'
|
||||
fill_in 'distributor_url', :with => 'http://eaterprises.com.au'
|
||||
fill_in 'distributor_abn', :with => '09812309823'
|
||||
fill_in 'distributor_acn', :with => ''
|
||||
|
||||
click_button 'Create'
|
||||
|
||||
flash_message.should == 'Distributor "Eaterprises" has been successfully created!'
|
||||
end
|
||||
|
||||
context "Given I am setting up distributors" do
|
||||
scenario "I should be able to create a new distributor" do
|
||||
login_to_admin_section
|
||||
|
||||
click_link 'Distributors'
|
||||
click_link 'New Distributor'
|
||||
scenario "updating many distributor next collection times at once" do
|
||||
# Given three distributors
|
||||
3.times { create(:distributor) }
|
||||
|
||||
fill_in 'distributor_name', :with => 'Eaterprises'
|
||||
fill_in 'distributor_description', :with => 'Connecting farmers and eaters'
|
||||
fill_in 'distributor_contact', :with => 'Kirsten or Ren'
|
||||
fill_in 'distributor_phone', :with => '0413 897 321'
|
||||
fill_in 'distributor_pickup_address', :with => '35 Ballantyne St'
|
||||
fill_in 'distributor_city', :with => 'Thornbury'
|
||||
fill_in 'distributor_post_code', :with => '3072'
|
||||
select('Australia', :from => 'distributor_country_id')
|
||||
select('Victoria', :from => 'distributor_state_id')
|
||||
fill_in 'distributor_pickup_times', :with => 'Thursday, 22nd Feb, 6 - 9 PM. Friday, 23nd Feb, 6 - 9 PM'
|
||||
fill_in 'distributor_email', :with => 'info@eaterprises.com.au'
|
||||
fill_in 'distributor_url', :with => 'http://eaterprises.com.au'
|
||||
fill_in 'distributor_abn', :with => '09812309823'
|
||||
fill_in 'distributor_acn', :with => ''
|
||||
# When I go to the distributors page
|
||||
login_to_admin_section
|
||||
click_link 'Distributors'
|
||||
|
||||
click_button 'Create'
|
||||
# And I fill in some new collection times and save them
|
||||
fill_in 'distributor_set_distributors_attributes_0_next_collection_at', :with => 'One'
|
||||
fill_in 'distributor_set_distributors_attributes_1_next_collection_at', :with => 'Two'
|
||||
fill_in 'distributor_set_distributors_attributes_2_next_collection_at', :with => 'Three'
|
||||
click_button 'Update'
|
||||
|
||||
flash_message.should == 'Distributor "Eaterprises" has been successfully created!'
|
||||
end
|
||||
# Then my times should have been saved
|
||||
flash_message.should == 'Distributor collection times updated.'
|
||||
Spree::Distributor.all.map { |d| d.next_collection_at }.should == %w(One Two Three)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -10,10 +10,11 @@ feature %q{
|
||||
background do
|
||||
@supplier = create(:supplier, :name => 'New supplier')
|
||||
@distributors = (1..3).map { create(:distributor) }
|
||||
@shipping_method = create(:shipping_method, :name => 'My shipping method')
|
||||
end
|
||||
|
||||
context "creating a product" do
|
||||
scenario "I should be able to assign a supplier to the product" do
|
||||
scenario "assigning a supplier and distributors to the product" do
|
||||
login_to_admin_section
|
||||
|
||||
click_link 'Products'
|
||||
@@ -22,8 +23,11 @@ feature %q{
|
||||
fill_in 'product_name', :with => 'A new product !!!'
|
||||
fill_in 'product_price', :with => '19.99'
|
||||
select 'New supplier', :from => 'product_supplier_id'
|
||||
|
||||
check @distributors[0].name
|
||||
select 'My shipping method', :from => 'product_product_distributions_attributes_0_shipping_method_id'
|
||||
check @distributors[2].name
|
||||
select 'My shipping method', :from => 'product_product_distributions_attributes_2_shipping_method_id'
|
||||
|
||||
click_button 'Create'
|
||||
|
||||
@@ -31,8 +35,7 @@ feature %q{
|
||||
product = Spree::Product.find_by_name('A new product !!!')
|
||||
product.supplier.should == @supplier
|
||||
product.distributors.should == [@distributors[0], @distributors[2]]
|
||||
product.product_distributions.map { |pd| pd.shipping_method }.should == [@shipping_method, @shipping_method]
|
||||
end
|
||||
end
|
||||
|
||||
context "Given I am cloning a Product"
|
||||
end
|
||||
|
||||
@@ -10,27 +10,29 @@ feature %q{
|
||||
background do
|
||||
end
|
||||
|
||||
context "Given I am setting up suppliers" do
|
||||
scenario "I should be able to create a new supplier" do
|
||||
context "setting up suppliers" do
|
||||
scenario "creating a new supplier" do
|
||||
login_to_admin_section
|
||||
|
||||
click_link 'Suppliers'
|
||||
click_link 'New Supplier'
|
||||
|
||||
fill_in 'supplier_name', :with => 'David arnold'
|
||||
fill_in 'supplier_name', :with => 'David Arnold'
|
||||
fill_in 'supplier_description', :with => 'A farmer with a difference'
|
||||
fill_in 'supplier_address', :with => '35 Byron Ave'
|
||||
fill_in 'supplier_city', :with => 'Ararat'
|
||||
fill_in 'supplier_postcode', :with => '1112'
|
||||
select('Australia', :from => 'supplier_country_id')
|
||||
select('Victoria', :from => 'supplier_state_id')
|
||||
|
||||
fill_in 'supplier_address_attributes_address1', :with => '35 Byron Ave'
|
||||
fill_in 'supplier_address_attributes_city', :with => 'Ararat'
|
||||
fill_in 'supplier_address_attributes_zipcode', :with => '1112'
|
||||
select('Australia', :from => 'supplier_address_attributes_country_id')
|
||||
select('Victoria', :from => 'supplier_address_attributes_state_id')
|
||||
|
||||
fill_in 'supplier_email', :with => 'david@here.com'
|
||||
fill_in 'supplier_website', :with => 'http://somewhere.com'
|
||||
fill_in 'supplier_twitter', :with => 'davida'
|
||||
|
||||
click_button 'Create'
|
||||
|
||||
flash_message.should == 'Supplier "David arnold" has been successfully created!'
|
||||
flash_message.should == 'Supplier "David Arnold" has been successfully created!'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
107
spec/requests/consumer/add_to_cart_spec.rb
Normal file
107
spec/requests/consumer/add_to_cart_spec.rb
Normal file
@@ -0,0 +1,107 @@
|
||||
require 'spec_helper'
|
||||
|
||||
feature %q{
|
||||
As a consumer
|
||||
I want to choose a distributor when adding products to my cart
|
||||
So that I can avoid making an order from many different distributors
|
||||
} do
|
||||
include AuthenticationWorkflow
|
||||
include WebHelper
|
||||
|
||||
scenario "adding the first product to the cart" do
|
||||
# Given a product and some distributors
|
||||
d1 = create(:distributor)
|
||||
d2 = create(:distributor)
|
||||
p = create(:product, :distributors => [d1])
|
||||
|
||||
# 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
|
||||
visit spree.product_path p
|
||||
select d1.name, :from => 'distributor_id'
|
||||
click_button 'Add To Cart'
|
||||
|
||||
# Then the item should be in my cart
|
||||
order = Spree::Order.last
|
||||
order.line_items.first.product.should == p
|
||||
|
||||
# And my order should have its distributor set to the chosen distributor
|
||||
order.distributor.should == d1
|
||||
end
|
||||
|
||||
it "does not allow the user to change distributor after a product has been added to the cart" do
|
||||
# Given a product and some distributors
|
||||
d1 = create(:distributor)
|
||||
d2 = create(:distributor)
|
||||
p = create(:product, :distributors => [d1])
|
||||
|
||||
# When I add a product to my cart (which sets my distributor)
|
||||
visit spree.product_path p
|
||||
click_button 'Add To Cart'
|
||||
page.should have_content "You are shopping at #{d1.name}"
|
||||
|
||||
# Then I should not be able to change distributor
|
||||
visit spree.root_path
|
||||
page.should_not have_selector "a[href*='select']", :text => d1.name
|
||||
page.should_not have_selector "a[href*='select']", :text => d2.name
|
||||
page.should_not have_selector "a", :text => 'Leave distributor'
|
||||
end
|
||||
|
||||
context "adding a subsequent product to the cart" do
|
||||
it "does not allow the user to choose a distributor" do
|
||||
# Given a product under a distributor
|
||||
d = create(:distributor)
|
||||
p = create(:product, :distributors => [d])
|
||||
|
||||
# And a product in my cart
|
||||
visit spree.product_path p
|
||||
click_button 'Add To Cart'
|
||||
|
||||
# When I go to add it again, I should not have a choice of distributor
|
||||
visit spree.product_path p
|
||||
page.should_not have_selector 'select#distributor_id'
|
||||
page.should have_selector '.distributor-fixed', :text => "Your distributor for this order is #{d.name}"
|
||||
end
|
||||
|
||||
it "does not allow the user to add a product from another distributor" do
|
||||
# Given two products, each at a different distributor
|
||||
d1 = create(:distributor)
|
||||
d2 = create(:distributor)
|
||||
p1 = create(:product, :distributors => [d1])
|
||||
p2 = create(:product, :distributors => [d2])
|
||||
|
||||
# When I add one of them to my cart
|
||||
visit spree.product_path p1
|
||||
click_button 'Add To Cart'
|
||||
|
||||
# And I attempt to add the other
|
||||
visit spree.product_path p2
|
||||
|
||||
# Then I should not be allowed to add the product
|
||||
page.should_not have_selector "button#add-to-cart-button"
|
||||
page.should have_content "Please complete your order at #{d1.name} before shopping with another distributor."
|
||||
end
|
||||
|
||||
it "adds products with valid distributors" do
|
||||
# Given two products, each at the same distributor
|
||||
d = create(:distributor)
|
||||
p1 = create(:product, :distributors => [d])
|
||||
p2 = create(:product, :distributors => [d])
|
||||
|
||||
# When I add the first to my cart
|
||||
visit spree.product_path p1
|
||||
click_button 'Add To Cart'
|
||||
|
||||
# And I add the second
|
||||
visit spree.product_path p2
|
||||
click_button 'Add To Cart'
|
||||
|
||||
# Then both should be in my cart
|
||||
visit spree.cart_path
|
||||
page.should have_selector 'h4 a', :text => p1.name
|
||||
page.should have_selector 'h4 a', :text => p2.name
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -9,62 +9,119 @@ feature %q{
|
||||
include WebHelper
|
||||
|
||||
background do
|
||||
@distributor1 = create(:distributor, :name => 'Eaterprises')
|
||||
@distributor2 = create(:distributor, :name => 'Edible garden',
|
||||
:pickup_address => '12 Bungee Rd',
|
||||
:city => 'Carion',
|
||||
:pickup_times => 'Tuesday, 4 PM')
|
||||
@product = create(:product, :name => 'Fuji apples')
|
||||
@distributor = create(:distributor, :name => 'Edible garden',
|
||||
:pickup_address => create(:address,
|
||||
:address1 => '12 Bungee Rd',
|
||||
:city => 'Carion',
|
||||
:zipcode => 3056,
|
||||
:state => Spree::State.find_by_name('Victoria'),
|
||||
:country => Spree::Country.find_by_name('Australia')),
|
||||
:pickup_times => 'Tuesday, 4 PM')
|
||||
|
||||
@shipping_method_1 = create(:shipping_method, :name => 'Shipping Method One')
|
||||
@shipping_method_1.calculator.set_preference :amount, 1
|
||||
@shipping_method_1.calculator.save!
|
||||
|
||||
@shipping_method_2 = create(:shipping_method, :name => 'Shipping Method Two')
|
||||
@shipping_method_2.calculator.set_preference :amount, 2
|
||||
@shipping_method_2.calculator.save!
|
||||
|
||||
@product_1 = create(:product, :name => 'Fuji apples')
|
||||
@product_1.product_distributions.create(:distributor => @distributor, :shipping_method => @shipping_method_1)
|
||||
|
||||
@product_2 = create(:product, :name => 'Garlic')
|
||||
@product_2.product_distributions.create(:distributor => @distributor, :shipping_method => @shipping_method_2)
|
||||
|
||||
@zone = create(:zone)
|
||||
create(:zone_member, zone: @zone, zoneable: Spree::Country.find_by_name('Australia'))
|
||||
create(:shipping_method, zone: @zone)
|
||||
create(:payment_method)
|
||||
c = Spree::Country.find_by_name('Australia')
|
||||
Spree::ZoneMember.create(:zoneable => c, :zone => @zone)
|
||||
create(:itemwise_shipping_method, zone: @zone)
|
||||
create(:payment_method, :description => 'Cheque payment method')
|
||||
end
|
||||
|
||||
context "Given I am buying a product", :js => true do
|
||||
scenario "I should be able choose a distributor to pick up from", :skip => true do
|
||||
login_to_consumer_section
|
||||
|
||||
click_link 'Fuji apples'
|
||||
click_button 'Add To Cart'
|
||||
click_link 'Checkout'
|
||||
scenario "viewing delivery fees" do
|
||||
# Given I am logged in
|
||||
login_to_consumer_section
|
||||
|
||||
fill_in_fields('order_bill_address_attributes_firstname' => 'Joe',
|
||||
'order_bill_address_attributes_lastname' => 'Luck',
|
||||
'order_bill_address_attributes_address1' => '19 Sycamore Lane',
|
||||
'order_bill_address_attributes_city' => 'Horse Hill',
|
||||
'order_bill_address_attributes_zipcode' => '3213',
|
||||
'order_bill_address_attributes_phone' => '12999911111')
|
||||
# When I add some apples and some garlic to my cart
|
||||
click_link 'Fuji apples'
|
||||
click_button 'Add To Cart'
|
||||
click_link 'Continue shopping'
|
||||
|
||||
click_link 'Garlic'
|
||||
click_button 'Add To Cart'
|
||||
|
||||
# Then I should see a breakdown of my delivery fees:
|
||||
# Item | Shipping Method | Delivery Fee
|
||||
# Garlic | Shipping Method Two | $2.00
|
||||
# Fuji apples | Shipping Method One | $1.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']
|
||||
end
|
||||
|
||||
|
||||
select('Australia', :from => 'order_bill_address_attributes_country_id')
|
||||
select('Victoria', :from => 'order_bill_address_attributes_state_id')
|
||||
scenario "buying a product", :js => true do
|
||||
login_to_consumer_section
|
||||
|
||||
select('Edible garden', :from => 'order_distributor_id')
|
||||
click_link 'Fuji apples'
|
||||
click_button 'Add To Cart'
|
||||
click_link 'Continue shopping'
|
||||
|
||||
# within('.distributor-details') do
|
||||
# page.should have_content('12 Bungee Rd')
|
||||
# page.should have_content('Carion')
|
||||
# page.should have_content('Tuesday, 4 PM')
|
||||
# end
|
||||
click_link 'Garlic'
|
||||
click_button 'Add To Cart'
|
||||
click_link 'Checkout'
|
||||
|
||||
click_button 'Save and Continue'
|
||||
#display delivery details?
|
||||
# -- Checkout: Address
|
||||
fill_in_fields('order_bill_address_attributes_firstname' => 'Joe',
|
||||
'order_bill_address_attributes_lastname' => 'Luck',
|
||||
'order_bill_address_attributes_address1' => '19 Sycamore Lane',
|
||||
'order_bill_address_attributes_city' => 'Horse Hill',
|
||||
'order_bill_address_attributes_zipcode' => '3213',
|
||||
'order_bill_address_attributes_phone' => '12999911111')
|
||||
|
||||
click_button 'Save and Continue'
|
||||
fill_in 'card_number', :with => '4111111111111111'
|
||||
select('1', :from => 'payment_source_1_month')
|
||||
select("#{DateTime.now.year + 1}", :from => 'payment_source_1_year')
|
||||
fill_in 'card_code', :with => '234'
|
||||
select('Australia', :from => 'order_bill_address_attributes_country_id')
|
||||
select('Victoria', :from => 'order_bill_address_attributes_state_id')
|
||||
|
||||
click_button 'Save and Continue'
|
||||
# Distributor details should be displayed
|
||||
within('fieldset#shipping') do
|
||||
[@distributor.name,
|
||||
@distributor.pickup_address.address1,
|
||||
@distributor.pickup_address.city,
|
||||
@distributor.pickup_address.zipcode,
|
||||
@distributor.pickup_address.state_text,
|
||||
@distributor.pickup_address.country.name,
|
||||
@distributor.pickup_times,
|
||||
@distributor.next_collection_at,
|
||||
@distributor.contact,
|
||||
@distributor.phone,
|
||||
@distributor.email,
|
||||
@distributor.description,
|
||||
@distributor.url].each do |value|
|
||||
|
||||
page.should have_content('Your order has been processed successfully')
|
||||
# page.should have_content('Your order will be available on:')
|
||||
# page.should have_content('On Tuesday, 4 PM')
|
||||
# page.should have_content('12 Bungee Rd, Carion')
|
||||
page.should have_content value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
click_button 'Save and Continue'
|
||||
|
||||
# -- Checkout: Delivery
|
||||
page.should have_selector 'label', :text => "Delivery $3.00"
|
||||
click_button 'Save and Continue'
|
||||
|
||||
# -- Checkout: Payment
|
||||
click_button 'Save and Continue'
|
||||
|
||||
# -- Checkout: Order complete
|
||||
page.should have_content('Your order has been processed successfully')
|
||||
page.should have_content('Cheque payment method')
|
||||
|
||||
|
||||
# page.should have_content('Your order will be available on:')
|
||||
# page.should have_content('On Tuesday, 4 PM')
|
||||
# page.should have_content('12 Bungee Rd, Carion')
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,12 +8,10 @@ feature %q{
|
||||
include AuthenticationWorkflow
|
||||
include WebHelper
|
||||
|
||||
background do
|
||||
scenario "viewing a list of distributors" do
|
||||
# Given some distributors
|
||||
3.times { create(:distributor) }
|
||||
end
|
||||
|
||||
scenario "viewing a list of distributors" do
|
||||
# When I go to the home page
|
||||
visit spree.root_path
|
||||
|
||||
@@ -34,36 +32,96 @@ feature %q{
|
||||
click_link d.name
|
||||
|
||||
# Then I should see the name of the distributor that I've selected
|
||||
page.should have_selector '#current-distributor', :text => 'You are shopping at Melb Uni Co-op'
|
||||
page.should have_content 'You are shopping at Melb Uni Co-op'
|
||||
end
|
||||
|
||||
it "splits the product listing by local/remote distributor"
|
||||
it "splits the product listing by local/remote distributor" do
|
||||
# Given two distributors, with a product under each, and each product under a taxon
|
||||
taxonomy = Spree::Taxonomy.find_by_name('Products') || create(:taxonomy, :name => 'Products')
|
||||
taxonomy_root = taxonomy.root
|
||||
taxon = create(:taxon, :name => 'Taxon one', :parent_id => taxonomy_root.id)
|
||||
d1 = create(:distributor)
|
||||
d2 = create(:distributor)
|
||||
p1 = create(:product, :distributors => [d1], :taxons => [taxon])
|
||||
p2 = create(:product, :distributors => [d2], :taxons => [taxon])
|
||||
|
||||
it "allows the user to leave the distributor"
|
||||
# When I select the first distributor
|
||||
visit spree.root_path
|
||||
click_link d1.name
|
||||
|
||||
context "viewing a product" do
|
||||
it "provides a choice of distributor when adding to cart" # Test product at remote distributor
|
||||
it "displays the local distributor as the default choice when available for the current product"
|
||||
# Then I should see products split by local/remote distributor
|
||||
# on the home page, the products page, the search results page and the taxon page
|
||||
[spree.root_path,
|
||||
spree.products_path,
|
||||
spree.products_path(:keywords => 'Product'),
|
||||
spree.nested_taxons_path(taxon.permalink)
|
||||
].each do |path|
|
||||
|
||||
visit path
|
||||
page.should_not have_selector '#products'
|
||||
page.should have_selector '#products-local', :text => p1.name
|
||||
page.should have_selector '#products-remote', :text => p2.name
|
||||
end
|
||||
end
|
||||
|
||||
it "allows the user to leave the distributor" do
|
||||
# Given a distributor
|
||||
d = create(:distributor, :name => 'Melb Uni Co-op')
|
||||
|
||||
# When I select the distributor and then leave it
|
||||
visit spree.root_path
|
||||
click_link d.name
|
||||
click_button 'Browse All Distributors'
|
||||
|
||||
# Then I should have left the distributor
|
||||
page.should_not have_selector '#current-distributor', :text => 'You are shopping at Melb Uni Co-op'
|
||||
end
|
||||
|
||||
context "viewing a product, it provides a choice of distributor when adding to cart" do
|
||||
it "works when no distributor is chosen" do
|
||||
# Given a distributor and a product under it
|
||||
distributor = create(:distributor)
|
||||
product = create(:product, :distributors => [distributor])
|
||||
|
||||
# When we view the product
|
||||
visit spree.product_path(product)
|
||||
|
||||
# Then we should see a choice of distributor, with no default
|
||||
page.should have_selector "select#distributor_id option", :text => distributor.name
|
||||
page.should_not have_selector "select#distributor_id option[selected='selected']"
|
||||
end
|
||||
|
||||
it "displays the local distributor as the default choice when available for the current product" do
|
||||
# Given a distributor and a product under it
|
||||
distributor = create(:distributor)
|
||||
product = create(:product, :distributors => [distributor])
|
||||
|
||||
# When we select the distributor and view the product
|
||||
visit spree.root_path
|
||||
click_link distributor.name
|
||||
visit spree.product_path(product)
|
||||
|
||||
# Then we should see our distributor as the default option when adding the item to our cart
|
||||
page.should have_selector "select#distributor_id option[value='#{distributor.id}'][selected='selected']"
|
||||
end
|
||||
|
||||
it "works when viewing a product from a remote distributor" do
|
||||
# Given two distributors and a product under one
|
||||
distributor_product = create(:distributor)
|
||||
distributor_no_product = create(:distributor)
|
||||
product = create(:product, :distributors => [distributor_product])
|
||||
|
||||
# When we select the distributor without the product and then view the product
|
||||
visit spree.root_path
|
||||
click_link distributor_no_product.name
|
||||
visit spree.product_path(product)
|
||||
|
||||
# Then we should see a choice of distributor,
|
||||
# with no default and no option for the distributor that the product does not belong to
|
||||
page.should have_selector "select#distributor_id option", :text => distributor_product.name
|
||||
page.should_not have_selector "select#distributor_id option", :text => distributor_no_product.name
|
||||
page.should_not have_selector "select#distributor_id option[selected='selected']"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
# scenario "browsing products by distributor" do
|
||||
# # Given a product at each of two distributors
|
||||
# d1 = create(:distributor)
|
||||
# d2 = create(:distributor)
|
||||
# p1 = create(:product, :distributors => [d1])
|
||||
# p2 = create(:product, :distributors => [d2])
|
||||
|
||||
# # When I go to the home page, I should see both products
|
||||
# visit spree.root_path
|
||||
# page.should have_content p1.name
|
||||
# page.should have_content p2.name
|
||||
|
||||
# # When I filter by one distributor, I should see only the product from that distributor
|
||||
# click_link d1.name
|
||||
# page.should have_content p1.name
|
||||
# page.should_not have_content p2.name
|
||||
# end
|
||||
end
|
||||
|
||||
@@ -51,7 +51,7 @@ feature %q{
|
||||
# When I visit the home page and select my distributor
|
||||
visit spree.root_path
|
||||
click_link my_distributor.name
|
||||
page.should have_selector '#current-distributor', :text => 'You are shopping at My Distributor'
|
||||
page.should have_content 'You are shopping at My Distributor'
|
||||
|
||||
# Then I should see distributor-scoped product counts next to the taxons
|
||||
page.should have_selector 'nav#taxonomies li', :text => 'Taxon one (0)'
|
||||
|
||||
@@ -3,15 +3,15 @@ require 'spork'
|
||||
#uncomment the following line to use spork with the debugger
|
||||
#require 'spork/ext/ruby-debug'
|
||||
|
||||
ENV["RAILS_ENV"] ||= 'test'
|
||||
require File.expand_path("../../config/environment", __FILE__)
|
||||
require 'rspec/rails'
|
||||
require 'rspec/autorun'
|
||||
require 'capybara'
|
||||
require 'database_cleaner'
|
||||
|
||||
|
||||
Spork.prefork do
|
||||
ENV["RAILS_ENV"] ||= 'test'
|
||||
require File.expand_path("../../config/environment", __FILE__)
|
||||
require 'rspec/rails'
|
||||
require 'rspec/autorun'
|
||||
require 'capybara'
|
||||
require 'database_cleaner'
|
||||
|
||||
# Requires supporting ruby files with custom matchers and macros, etc,
|
||||
# in spec/support/ and its subdirectories.
|
||||
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
|
||||
@@ -48,11 +48,12 @@ Spork.prefork do
|
||||
#
|
||||
config.filter_run_excluding :skip => true
|
||||
|
||||
config.before(:suite) do
|
||||
DatabaseCleaner.strategy = :transaction
|
||||
end
|
||||
|
||||
config.before(:each) do
|
||||
if example.metadata[:js]
|
||||
DatabaseCleaner.strategy = :truncation, { :except => ['spree_countries', 'spree_states'] }
|
||||
else
|
||||
DatabaseCleaner.strategy = :transaction
|
||||
end
|
||||
DatabaseCleaner.start
|
||||
end
|
||||
|
||||
@@ -63,11 +64,18 @@ Spork.prefork do
|
||||
config.include Spree::UrlHelpers
|
||||
config.include Spree::Core::TestingSupport::ControllerRequests, :type => :controller
|
||||
config.include Devise::TestHelpers, :type => :controller
|
||||
config.include FactoryGirl::Syntax::Methods
|
||||
end
|
||||
end
|
||||
|
||||
Spork.each_run do
|
||||
# Dir["#{File.dirname(__FILE__)}/../app/**/*.rb"].each {|f| load f}
|
||||
# Rails.application.reload_routes!
|
||||
Dir["#{File.dirname(__FILE__)}/../app/**/*.rb"].each {|f| load f}
|
||||
Dir["#{File.dirname(__FILE__)}/../lib/**/*.rb"].each {|f| load f}
|
||||
|
||||
Rails.application.reload_routes!
|
||||
|
||||
require 'factory_girl_rails'
|
||||
|
||||
RSpec.configure do |config|
|
||||
config.include FactoryGirl::Syntax::Methods
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
require 'faker'
|
||||
require 'spree/core/testing_support/factories'
|
||||
|
||||
FactoryGirl.define do
|
||||
factory :supplier, :class => Spree::Supplier do
|
||||
sequence(:name) { |n| "Supplier #{n}" }
|
||||
description 'supplier'
|
||||
email 'supplier@example.com'
|
||||
address '4 McDougal Rd'
|
||||
city 'Austinvale'
|
||||
postcode '2312'
|
||||
state { Spree::State.find_by_name('Victoria') }
|
||||
country { Spree::Country.find_by_name('Australia') }
|
||||
end
|
||||
|
||||
factory :distributor, :class => Spree::Distributor do
|
||||
sequence(:name) { |n| "Distributor #{n}" }
|
||||
contact "Mr Turing"
|
||||
phone "1000100100"
|
||||
description 'The creator'
|
||||
email 'alan@somewhere.com'
|
||||
pickup_address 'Wilmslow'
|
||||
pickup_times "Whenever you're free"
|
||||
city 'Cheshire'
|
||||
post_code '2312'
|
||||
state { Spree::State.find_by_name('Victoria') }
|
||||
country { Spree::Country.find_by_name('Australia') }
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
FactoryGirl.modify do
|
||||
factory :simple_product do
|
||||
supplier { Spree::Supplier.first || FactoryGirl.create(:supplier) }
|
||||
distributors { [Spree::Distributor.first || FactoryGirl.create(:distributor)] }
|
||||
end
|
||||
end
|
||||
10
spec/support/spree/init.rb
Normal file
10
spec/support/spree/init.rb
Normal file
@@ -0,0 +1,10 @@
|
||||
# Initialise shipping method when created without one, like this:
|
||||
# create(:product, :distributors => [...])
|
||||
# In this case, we don't care what the shipping method is, but we need one for validations to pass.
|
||||
Spree::ProductDistribution.class_eval do
|
||||
before_validation :init_shipping_method
|
||||
|
||||
def init_shipping_method
|
||||
self.shipping_method ||= Spree::ShippingMethod.first || FactoryGirl.create(:shipping_method)
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user