Compare commits

..

40 Commits

Author SHA1 Message Date
Rohan Mitchell
9d3afe80c6 split_products_by_distributor was not written with pre-pagination by searcher in mind, resulting in silently dropped products. Disable pagination at searcher. 2012-08-03 18:47:33 +10:00
Rohan Mitchell
28e75d6467 Fix add to cart JS for compatibility with group buy 2012-08-03 18:32:19 +10:00
Rohan Mitchell
b0fa05df0c Remove assets from git 2012-08-03 18:31:28 +10:00
Rohan Mitchell
f3ffba378a Add a product with variants to the cart with max quantity for a group buy 2012-08-03 18:05:45 +10:00
Rohan Mitchell
2d89640271 Instrument orders controller to debug populate_variant_attributes 2012-08-03 14:11:59 +10:00
Rohan Mitchell
e6ee6b5164 Itemwise shipping calculator returns 0 instead of nil when there are no items 2012-08-03 08:44:53 +10:00
Rohan Mitchell
768a170bb8 Fix with_products_on_hand query for server db compatibility 2012-08-03 08:21:45 +10:00
Rohan Mitchell
8834268970 Fix error on no shipping method defined 2012-08-02 17:45:22 +10:00
Rohan Mitchell
fe61b4aab1 Display shipping fee at all steps of the checkout process, not just after delivery method is chosen 2012-08-02 16:24:08 +10:00
Rohan Mitchell
a6c2490597 Enable auto-capture for spree_paypal_express 2012-08-02 15:45:31 +10:00
Rohan Mitchell
9110dc6414 Fix form local var naming for admin shared address form 2012-08-02 15:33:39 +10:00
Rohan Mitchell
77be0dd6eb Adding a product with a max quantity less than quantity results in max_quantity==quantity 2012-08-02 15:26:13 +10:00
Rohan Mitchell
40544eb27b Adding a product to cart that is not a group buy does not show max quantity field 2012-08-02 15:16:44 +10:00
Rohan Mitchell
306cb5b089 Add max quantity to order and distributor report 2012-08-02 15:07:34 +10:00
Rohan Mitchell
c46613877c Add max quantity field to add to cart form, add end-to-end test for max_quantity 2012-08-02 14:45:55 +10:00
Rohan Mitchell
2db2fbcade Change set_variant_attribute to set_variant_attributes, implement it on Order 2012-08-02 14:45:27 +10:00
Rohan Mitchell
ea05f05576 When adding a group buy product to the cart, set the max quantity on the order 2012-08-02 14:29:05 +10:00
Rohan Mitchell
361a87f580 Add group buy option to new/edit product in admin 2012-08-02 13:42:47 +10:00
Rohan Mitchell
330c62716c Add fields for group buy feature 2012-08-02 13:15:17 +10:00
Rohan Mitchell
63bf25293d Only show distributors in sidebar that have products in stock 2012-08-02 11:49:10 +10:00
Rohan Mitchell
93867682bb Only show distributors in sidebar that have products 2012-08-02 11:33:36 +10:00
Rohan Mitchell
7d5c158021 Install Bugsnag 2012-08-02 10:32:33 +10:00
Rohan Mitchell
06c6422591 Fix by-weight calculator to take line item quantity into account 2012-07-23 18:49:03 +10:00
Rohan Mitchell
5e04032797 Explicitly specify Spree 1.1.1, fix test regression in OrdersController 2012-07-23 18:48:30 +10:00
Andrew Spinks
f716176361 specify ruby version in Gemfile as per heroku requirement: https://devcenter.heroku.com/articles/ruby-versions 2012-07-20 20:40:55 +10:00
Andrew Spinks
2826f62497 Add extra details to the order report. 2012-07-20 20:25:53 +10:00
Andrew Spinks
7172fe0c87 added extra fields to order report. 2012-07-20 00:07:41 +10:00
Andrew Spinks
7e9a84087e cleaning up order report 2012-07-19 22:48:42 +10:00
Andrew Spinks
58e9cd3eeb fix distributor name in report 2012-07-15 21:00:10 +10:00
Andrew Spinks
54559c4a5f first cut at orders report. 2012-07-15 20:48:10 +10:00
Andrew Spinks
8f5b5e7ae4 allow shipping instructions to be provided. 2012-07-11 23:33:03 +10:00
Andrew Spinks
759ceae23f add distributor name to confirmation email 2012-07-11 23:20:59 +10:00
Andrew Spinks
32b37a1390 add padding to the second address line. 2012-07-11 22:45:57 +10:00
Andrew Spinks
0e43fcfaa1 adjust address formatting in confirmation email. 2012-07-11 22:25:42 +10:00
Andrew Spinks
6a27f8da32 update formatting of confirmation email. 2012-07-11 22:15:46 +10:00
Andrew Spinks
c24543c237 Add delivery details to confirmation email. 2012-07-11 22:07:18 +10:00
Andrew Spinks
44314ccb99 copied original spree confirmation mail 2012-07-11 21:35:07 +10:00
Andrew Spinks
9ad42a3966 adding precompiled assets 2012-07-11 20:46:20 +10:00
Andrew Spinks
d34e6570fc trying to get asset precompilation to work on deploy 2012-07-11 20:39:49 +10:00
Andrew Spinks
b5b35491cc allow asset precompile to work on new heroku instance 2012-07-07 10:17:33 +10:00
39 changed files with 492 additions and 80 deletions

29
.gitignore vendored
View File

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

16
Gemfile
View File

@@ -1,9 +1,10 @@
source 'http://rubygems.org'
ruby "1.9.3"
gem 'rails', '3.2.3'
gem 'pg'
gem 'spree'
gem 'spree', '1.1.1'
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'
@@ -14,6 +15,7 @@ gem 'spree_last_address', :git => 'git://github.com/dancinglightning/spree-last-
gem 'simple_form', :git => 'git://github.com/RohanM/simple_form.git'
gem 'unicorn'
gem 'bugsnag'
gem 'spree_heroku', :git => 'git://github.com/joneslee85/spree-heroku.git'
gem 'haml'
gem 'aws-s3'
@@ -33,17 +35,6 @@ end
gem 'jquery-rails'
# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'
# Use unicorn as the web server
# gem 'unicorn'
# Deploy with Capistrano
# gem 'capistrano'
# To use debugger
# gem 'ruby-debug19', :require => 'ruby-debug'
group :test, :development do
# Pretty printed test output
@@ -56,5 +47,6 @@ group :test, :development do
gem 'database_cleaner', '0.7.1', :require => false
gem 'spork', '~> 1.0rc'
gem 'pry'
gem 'awesome_print'
end

View File

@@ -82,6 +82,7 @@ GEM
andand (1.3.3)
ansi (1.4.2)
arel (3.0.2)
awesome_print (1.0.2)
aws-s3 (0.6.3)
builder
mime-types
@@ -94,6 +95,9 @@ GEM
bcrypt-ruby (3.0.1)
braintree (2.16.0)
builder (>= 2.0.0)
bugsnag (1.1.2)
httparty (~> 0.8.3)
multi_json (~> 1.3.4)
builder (3.0.0)
cancan (1.6.7)
capybara (1.1.2)
@@ -322,7 +326,9 @@ PLATFORMS
DEPENDENCIES
andand
awesome_print
aws-s3
bugsnag
capybara
coffee-rails (~> 3.2.1)
database_cleaner (= 0.7.1)
@@ -338,7 +344,7 @@ DEPENDENCIES
shoulda-matchers
simple_form!
spork (~> 1.0rc)
spree
spree (= 1.1.1)
spree_heroku!
spree_i18n!
spree_last_address!

View File

@@ -9,7 +9,7 @@ $(document).ready(function() {
$("#quantity").change();
// Product page with master price only
$(".add-to-cart input.title:not(#quantity)").change(products_update_price_without_variant).change();
$(".add-to-cart input.title:not(#quantity):not(#max_quantity)").change(products_update_price_without_variant).change();
});

View File

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

View File

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

View File

@@ -1,5 +1,6 @@
Spree::OrdersController.class_eval do
before_filter :populate_order_distributor, :only => :populate
after_filter :populate_variant_attributes, :only => :populate
def populate_order_distributor
@distributor = params.key?(:distributor_id) ? Spree::Distributor.find(params[:distributor_id]) : nil
@@ -14,6 +15,22 @@ Spree::OrdersController.class_eval do
end
end
def populate_variant_attributes
if params.key? :variant_attributes
params[:variant_attributes].each do |variant_id, attributes|
@order.set_variant_attributes(Spree::Variant.find(variant_id), attributes)
end
end
if params.key? :quantity
params[:products].each do |product_id, variant_id|
max_quantity = params[:max_quantity].to_i
@order.set_variant_attributes(Spree::Variant.find(variant_id), {:max_quantity => max_quantity})
end
end
end
private
def populate_valid? distributor
# -- Distributor must be specified

View File

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

View File

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

View File

@@ -13,6 +13,7 @@ module Spree
validates_associated :pickup_address
scope :by_name, order('name')
scope :with_products_on_hand, joins(:products).where('spree_products.count_on_hand > 0').select('distinct(distributors.*)')
after_initialize :initialize_country
before_validation :set_unused_address_fields

View File

@@ -1,4 +1,6 @@
Spree::LineItem.class_eval do
attr_accessible :max_quantity
def shipping_method
self.product.shipping_method_for_distributor(self.order.distributor)
end

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,6 +11,9 @@
- else
%p Quantity
= number_field_tag (@product.has_variants? ? :quantity : "variants[#{@product.master.id}]"), 1, :class => 'title', :in => 1..@product.on_hand
- if @product.group_buy
%p Max quantity
= number_field_tag (@product.has_variants? ? :max_quantity : "variant_attributes[#{@product.master.id}][max_quantity]"), 1, :class => 'title', :in => 1..@product.on_hand
- order = current_order(false)
- if order.nil? || order.can_change_distributor?
%p Distributor

View File

@@ -64,5 +64,7 @@ module Openfoodweb
# Version of your assets, change this if you want to expire all your assets
config.assets.version = '1.0'
config.assets.initialize_on_precompile = true
end
end

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20120702020402) do
ActiveRecord::Schema.define(:version => 20120802031147) do
create_table "distributors", :force => true do |t|
t.string "name"
@@ -180,10 +180,11 @@ ActiveRecord::Schema.define(:version => 20120702020402) do
create_table "spree_line_items", :force => true do |t|
t.integer "order_id"
t.integer "variant_id"
t.integer "quantity", :null => false
t.decimal "price", :precision => 8, :scale => 2, :null => false
t.integer "quantity", :null => false
t.decimal "price", :precision => 8, :scale => 2, :null => false
t.datetime "created_at"
t.datetime "updated_at"
t.integer "max_quantity"
end
add_index "spree_line_items", ["order_id"], :name => "index_line_items_on_order_id"
@@ -366,6 +367,7 @@ ActiveRecord::Schema.define(:version => 20120702020402) do
t.datetime "updated_at"
t.integer "count_on_hand", :default => 0, :null => false
t.integer "supplier_id"
t.boolean "group_buy"
end
add_index "spree_products", ["available_on"], :name => "index_products_on_available_on"

View File

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

View File

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

View File

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

View File

@@ -40,6 +40,7 @@ end
FactoryGirl.modify do
factory :simple_product do
supplier { Spree::Supplier.first || FactoryGirl.create(:supplier) }
on_hand 3
# before(:create) do |product, evaluator|
# product.product_distributions = [FactoryGirl.create(:product_distribution, :product => product)]

View File

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

View File

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

View File

@@ -5,12 +5,12 @@ describe OpenFoodWeb::Calculator::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)
line_item_1 = double(:line_item, :variant => variant_1, :quantity => 1)
line_item_2 = double(:line_item, :variant => variant_2, :quantity => 3)
order = double(:order, :line_items => [line_item_1, line_item_2])
subject.set_preference(:per_kg, 10)
subject.compute(order).should == 300
subject.compute(order).should == (10*1 + 20*3) * 10
end
end

View File

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

View File

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

View File

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

View File

@@ -13,6 +13,7 @@ feature %q{
d1 = create(:distributor)
d2 = create(:distributor)
p = create(:product, :distributors => [d1])
create(:product, :distributors => [d2])
# When I choose a distributor
visit spree.root_path
@@ -104,4 +105,74 @@ feature %q{
page.should have_selector 'h4 a', :text => p2.name
end
end
scenario "adding a product to the cart for a group buy" do
# Given a group buy product and a distributor
d = create(:distributor)
p = create(:product, :distributors => [d], :group_buy => true)
# When I add the item to my cart
visit spree.product_path p
fill_in "variants_#{p.master.id}", :with => 2
fill_in "variant_attributes_#{p.master.id}_max_quantity", :with => 3
click_button 'Add To Cart'
# Then the item should be in my cart with correct quantities
order = Spree::Order.last
li = order.line_items.first
li.product.should == p
li.quantity.should == 2
li.max_quantity.should == 3
end
scenario "adding a product with variants to the cart for a group buy" do
# Given a group buy product with variants and a distributor
d = create(:distributor)
p = create(:product, :distributors => [d], :group_buy => true)
create(:variant, :product => p)
# When I add the item to my cart
visit spree.product_path p
fill_in "quantity", :with => 2
fill_in "max_quantity", :with => 3
click_button 'Add To Cart'
# Then the item should be in my cart with correct quantities
order = Spree::Order.last
li = order.line_items.first
li.product.should == p
li.quantity.should == 2
li.max_quantity.should == 3
end
scenario "adding a product to cart that is not a group buy does not show max quantity field" do
# Given a group buy product and a distributor
d = create(:distributor)
p = create(:product, :distributors => [d], :group_buy => false)
# When I view the add to cart form, there should not be a max quantity field
visit spree.product_path p
page.should_not have_selector "#variant_attributes_#{p.master.id}_max_quantity"
end
scenario "adding a product with a max quantity less than quantity results in max_quantity==quantity" do
# Given a group buy product and a distributor
d = create(:distributor)
p = create(:product, :distributors => [d], :group_buy => true)
# When I add the item to my cart
visit spree.product_path p
fill_in "variants_#{p.master.id}", :with => 2
fill_in "variant_attributes_#{p.master.id}_max_quantity", :with => 1
click_button 'Add To Cart'
# Then the item should be in my cart with correct quantities
order = Spree::Order.last
li = order.line_items.first
li.product.should == p
li.quantity.should == 2
li.max_quantity.should == 2
end
end

View File

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