Compare commits

...

27 Commits
0.2.0 ... 0.2.2

Author SHA1 Message Date
Rohan Mitchell
9fbcd8c01b Display CMS pages with Spree's layout 2012-10-12 10:21:21 +11:00
Rohan Mitchell
927970d1a9 Viewing another products listing page does not display home page content 2012-10-12 09:39:49 +11:00
Rohan Mitchell
3dd3d8030f Display CMS pages in menu 2012-10-11 17:00:34 +11:00
Rohan Mitchell
cab61ddb7c CMS content on home page 2012-10-11 16:21:33 +11:00
Rohan Mitchell
015b7f88b0 Add tests for CMS admin security 2012-10-11 13:17:05 +11:00
Rohan Mitchell
28fc16ac66 Create links between Spree and CMS admin sections 2012-10-11 12:50:59 +11:00
Rohan Mitchell
e1d4ee318c Fix issues with elRTE - sprites and functionality now work for link and image functions 2012-10-11 12:00:30 +11:00
Rohan Mitchell
48497266da Precompile CMS assets 2012-10-11 11:06:52 +11:00
Rohan Mitchell
fe5fd76415 Further syntax fixes for GroupBuyReport 2012-10-11 10:53:33 +11:00
Rohan Mitchell
c05911fa10 Fix spree_creditcards table renamed in Spree 1.2 upgrade, remove old pending test 2012-10-11 10:50:37 +11:00
Rohan Mitchell
a686a820d9 Add distributor show page, redirect here after selecting distributor 2012-10-11 10:50:36 +11:00
Rohan Mitchell
3889545f2b Convert suppliers page to HAML 2012-10-11 10:50:36 +11:00
Rohan Mitchell
7432cb416e Andand all the html_safes 2012-10-11 10:50:36 +11:00
Rohan Mitchell
0b830a7845 Suppliers and distributors long description editable with WYSIWYG editor from CMS and displayed as HTML 2012-10-11 10:50:36 +11:00
Rohan Mitchell
58e5724f81 Display supplier details on supplier page 2012-10-11 10:50:36 +11:00
Rohan Mitchell
c07a33d88c Edit long description field in admin for suppliers and distributors 2012-10-11 10:50:36 +11:00
Rohan Mitchell
d080aa49d5 Add long description field to distributors and suppliers 2012-10-11 10:50:36 +11:00
Rohan Mitchell
a31c5bbe46 Authorise CMS via Spree login 2012-10-11 10:50:36 +11:00
Rohan Mitchell
b35fb618f3 Add base install of Comfortable Mexican Sofa 2012-10-11 10:50:36 +11:00
Rob H
8c7ed6f4ef Merge branch 'group-buy-report' 2012-10-10 15:47:02 +11:00
Rob H
1709083d8f Merge branch 'master' of github.com:andrewspinks/openfoodweb 2012-10-10 15:45:42 +11:00
Rob H
5803da9c55 Syntax fixes for group buy report classes and tests 2012-10-10 15:13:15 +11:00
Rohan Mitchell
0ad6045363 Fix struct superclass mismatch error 2012-10-10 14:02:44 +11:00
Rob H
9737f21bb8 WIP: Write body of group buy report 2012-10-10 13:46:51 +11:00
Rob H
d7a5a87aef create group buy report, display header 2012-10-03 11:49:21 +10:00
Rob H
3b8c41840f Merge branch 'master' of github.com:andrewspinks/openfoodweb
Conflicts:
	app/models/spree/line_item_decorator.rb
	db/migrate/20120919013335_add_shipping_method_to_line_items.rb
2012-10-03 10:27:19 +10:00
Rob H
fe3743af16 Replace shipping method lookup with relation 2012-09-19 12:06:43 +10:00
57 changed files with 957 additions and 52 deletions

View File

@@ -9,6 +9,7 @@ gem 'spree_i18n', :git => 'git://github.com/spree/spree_i18n.git'
gem 'spree_paypal_express', :git => 'git://github.com/spree/spree_paypal_express.git', :branch => '1-1-stable'
gem 'spree_last_address', :git => 'git://github.com/dancinglightning/spree-last-address.git'
gem 'comfortable_mexican_sofa'
# Fix bug in simple_form preventing collection_check_boxes usage within form_for block
# When merged, revert to upstream gem

View File

@@ -102,6 +102,7 @@ GEM
rack-cache (~> 1.2)
rack-test (~> 0.6.1)
sprockets (~> 2.1.3)
active_link_to (1.0.0)
active_utils (1.0.5)
activesupport (>= 2.3.11)
i18n
@@ -167,6 +168,10 @@ GEM
execjs
coffee-script-source (1.3.3)
columnize (0.3.6)
comfortable_mexican_sofa (1.6.24)
active_link_to (~> 1.0.0)
paperclip (>= 2.3.0)
rails (>= 3.0.0)
database_cleaner (0.7.1)
debugger (1.1.4)
columnize (>= 0.3.1)
@@ -351,6 +356,7 @@ DEPENDENCIES
bugsnag
capybara
coffee-rails (~> 3.2.1)
comfortable_mexican_sofa
database_cleaner (= 0.7.1)
factory_girl_rails
faker

View File

@@ -4,4 +4,11 @@
#header h1 {
left: 275px;
}
}
/* Fix conflict between Spree and elRTE's styles */
.el-rte .toolbar {
float: none;
margin-bottom: 0;
}

View File

@@ -128,6 +128,13 @@ ul.product-listing {
}
/* Supplier and distributor description */
.supplier-description, .distributor-description {
margin-bottom: 2em;
}
/* Highlight local products in distributor-split product listings */
#products-local ul {
margin-bottom: 1em;

View File

@@ -1,9 +1,15 @@
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :load_data_for_menu
before_filter :load_data_for_sidebar
private
def load_data_for_menu
@cms_site = Cms::Site.where(:identifier => 'open-food-web').first
end
def load_data_for_sidebar
@suppliers = Spree::Supplier.all
@distributors = Spree::Distributor.with_active_products_on_hand.by_name

View File

@@ -1,9 +1,11 @@
require 'csv'
require 'open_food_web/order_and_distributor_report'
require 'open_food_web/group_buy_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"}})
Spree::Admin::ReportsController::AVAILABLE_REPORTS.merge!({:group_buys => {:name => "Group Buys", :description => "Orders by supplier and variant"}})
def orders_and_distributors
params[:q] = {} unless params[:q]
@@ -23,7 +25,7 @@ Spree::Admin::ReportsController.class_eval do
orders = @search.result
@report = OpenFoodWeb::OrderAndDistributorReport.new orders
if(!params[:csv])
unless params[:csv]
render :html => @report
else
csv_string = CSV.generate do |csv|
@@ -34,4 +36,35 @@ Spree::Admin::ReportsController.class_eval do
end
end
def group_buys
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
@distributors = Spree::Distributor.all
@report = OpenFoodWeb::GroupBuyReport.new orders
unless params[:csv]
render :html => @report
else
csv_string = CSV.generate do |csv|
csv << @report.header
@report.table.each { |row| csv << row }
end
send_data csv_string, :filename => "group_buy.csv"
end
end
end

View File

@@ -1,12 +1,15 @@
module Spree
class DistributorsController < BaseController
helper 'spree/products'
def show
options = {:distributor_id => params[:id]}
options.merge(params.reject { |k,v| k == :id })
@distributor = Distributor.find params[:id]
@searcher = Config.searcher_class.new(options)
@products = @searcher.retrieve_products
render :template => 'spree/products/index'
end
def select
@@ -19,7 +22,7 @@ module Spree
order.save!
end
redirect_to root_path
redirect_to distributor
end
def deselect

View File

@@ -1,6 +1,6 @@
Spree::OrdersController.class_eval do
before_filter :populate_order_distributor, :only => :populate
after_filter :populate_variant_attributes, :only => :populate
before_filter :populate_order_distributor, :only => :populate
after_filter :populate_variant_attributes, :only => :populate
def populate_order_distributor
@distributor = params[:distributor_id].present? ? Spree::Distributor.find(params[:distributor_id]) : nil

View File

@@ -6,9 +6,10 @@ module Spree
options = {:supplier_id => params[:id]}
options.merge(params.reject { |k,v| k == :id })
@supplier = Supplier.find params[:id]
@searcher = Config.searcher_class.new(options)
@products = @searcher.retrieve_products
render :template => 'spree/products/index'
end
end
end

View File

@@ -1,2 +1,7 @@
module ApplicationHelper
def home_page_cms_content
if controller.controller_name == 'home' && controller.action_name == 'index'
cms_page_content(:content, Cms::Page.find_by_full_path('/'))
end
end
end

View File

@@ -5,7 +5,6 @@ Spree::LineItem.class_eval do
before_create :set_itemwise_shipping_method
def itemwise_shipping_cost
order = OpenStruct.new :line_items => [self]
shipping_method.compute_amount(order)

View File

@@ -0,0 +1,4 @@
Deface::Override.new(:virtual_path => "spree/layouts/admin",
:name => "cms_admin_tab",
:insert_bottom => "[data-hook='admin_tabs'], #admin_tabs[data-hook]",
:text => "<li><%= link_to('CMS Admin', main_app.cms_admin_path) %></li>")

View File

@@ -0,0 +1 @@
%li= link_to 'Spree Admin', spree.admin_path

View File

@@ -1,14 +1 @@
<!DOCTYPE html>
<html>
<head>
<title>Openfoodweb</title>
<%= stylesheet_link_tag "application" %>
<%= javascript_include_tag "application" %>
<%= csrf_meta_tags %>
</head>
<body>
<%= yield %>
</body>
</html>
<%= render :file => 'spree/layouts/spree_application' %>

View File

@@ -0,0 +1,17 @@
-# Include all stylesheets except reset (which overrides Spree styles)
-# See cms/app/views/layouts/cms_admin/_head.html.erb
= stylesheet_link_tag 'comfortable_mexican_sofa/structure',
'comfortable_mexican_sofa/typography',
'comfortable_mexican_sofa/form',
'comfortable_mexican_sofa/content',
'comfortable_mexican_sofa/files',
'comfortable_mexican_sofa/elrte',
'comfortable_mexican_sofa/codemirror',
'comfortable_mexican_sofa/jquery_ui',
'comfortable_mexican_sofa/dialogs',
'comfortable_mexican_sofa/widgets'
= javascript_include_tag('comfortable_mexican_sofa/application')
%meta{:name => "cms-admin-path", :content => ComfortableMexicanSofa.config.admin_route_prefix}
%meta{:name => "cms-locale", :content => I18n.locale}

View File

@@ -1,3 +1,6 @@
- content_for :head do
= render 'shared/cms_elrte_head'
%table{"data-hook" => "distributors"}
%tr{"data-hook" => "name"}
%td Name:
@@ -5,6 +8,9 @@
%tr{"data-hook" => "description"}
%td Description:
%td= f.text_field :description
%tr{'data-hook' => "long_description"}
%td Extended Description:
%td= f.text_area :long_description, :class => 'rich_text'
%tr{"data-hook" => "contact"}
%td Contact:
%td= f.text_field :contact

View File

@@ -6,6 +6,9 @@
%tr
%th Description:
%td= @distributor.description
%tr
%th Extended Description:
%td= @distributor.long_description.andand.html_safe
%tr
%th Contact person:
%td= @distributor.contact

View File

@@ -0,0 +1,37 @@
= form_for @search, :url => spree.group_buys_admin_reports_path do |f|
= label_tag nil, t(:date_range)
%br
.date-range-filter
%div{"class" => "left sub-field"}
= f.text_field :created_at_gt, :class => 'datepicker'
%br
= label_tag nil, t(:start), :class => 'sub'
%div{"class" => "right sub-field"}
= f.text_field :created_at_lt, :class => 'datepicker'
%br
= label_tag nil, t(:stop)
%br
= label_tag nil, "Distributor: "
= f.collection_select(:distributor_id_eq, @distributors, :id, :name)
%br
%br
= 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,3 +1,6 @@
- content_for :head do
= render 'shared/cms_elrte_head'
%table{'data-hook' => "suppliers"}
%tr{'data-hook' => "name"}
%td Name:
@@ -5,6 +8,9 @@
%tr{'data-hook' => "description"}
%td Description:
%td= f.text_field :description
%tr{'data-hook' => "long_description"}
%td Extended Description:
%td= f.text_area :long_description, :class => 'rich_text'
= f.fields_for :address do |address_form|
= render 'spree/admin/shared/address_form', :f => address_form
%tr{'data-hook' => "email"}

View File

@@ -6,6 +6,9 @@
%tr
%th Description:
%td= @supplier.description
%tr
%th Extended Description:
%td= @supplier.long_description.andand.html_safe
%tr
%th Address:
%td= render 'spree/shared/address', :address => @supplier.address

View File

@@ -0,0 +1,7 @@
%h2= @distributor.name
.distributor-description= @distributor.long_description.andand.html_safe
%h3 Available Now
= render :template => 'spree/products/index'

View File

@@ -12,7 +12,7 @@
- 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
= link_to distributor.name, distributor
- else
%span.inactive= distributor.name
- if current_distributor && order.can_change_distributor?

View File

@@ -1,3 +1,5 @@
= home_page_cms_content
- if @products
#products= render 'spree/shared/products', :products => @products, :taxon => @taxon
- else

View File

@@ -1,6 +1,10 @@
%li#home-link{'data-hook' => ''}
= link_to t(:home), root_path
- if @cms_site
- @cms_site.pages.root.children.published.each do |page|
%li= link_to page.label, page.full_path
%li#link-to-cart{'data-hook' => ''}
= link_to_cart

View File

@@ -0,0 +1,7 @@
%h2= @supplier.name
.supplier-description= @supplier.long_description.andand.html_safe
%h3 Available Now
= render :template => 'spree/products/index'

View File

@@ -66,6 +66,6 @@ module Openfoodweb
config.assets.version = '1.0'
config.assets.initialize_on_precompile = false
config.assets.precompile += ['store/all.css', 'store/all.js', 'admin/all.css', 'admin/*.js', 'admin/**/*.js']
config.assets.precompile += ['store/all.css', 'store/all.js', 'admin/all.css', 'admin/*.js', 'admin/**/*.js', 'comfortable_mexican_sofa/*']
end
end

View File

@@ -0,0 +1,127 @@
# encoding: utf-8
ComfortableMexicanSofa.configure do |config|
# Title of the admin area
# config.cms_title = 'ComfortableMexicanSofa CMS Engine'
# Module responsible for authentication. You can replace it with your own.
# It simply needs to have #authenticate method. See http_auth.rb for reference.
config.admin_auth = 'CmsSpreeAuth'
# Module responsible for public authentication. Similar to the above. You also
# will have access to @cms_site, @cms_layout, @cms_page so you can use them in
# your logic. Default module doesn't do anything.
# config.public_auth = 'ComfortableMexicanSofa::DummyAuth'
# Default url to access admin area is http://yourhost/cms-admin/
# You can change 'cms-admin' to 'admin', for example. To disable admin area
# entirely set this to '' or nil
# config.admin_route_prefix = 'cms-admin'
# When arriving at /cms-admin you may chose to redirect to arbirtary path,
# for example '/cms-admin/users'
# config.admin_route_redirect = ''
# Normally we include default routes from https://github.com/comfy/comfortable-mexican-sofa/blob/master/config/routes.rb
# If you want to include the routes manually set this to false
# config.use_default_routes = true
# /sitemap.xml that is used by search engines for indexing. It's enabled by
# default, but you may turn it off.
# config.enable_sitemap = true
# File uploads use Paperclip and can support filesystem or s3 uploads. Override
# the upload method and appropriate settings based on Paperclip. For S3 see:
# http://rdoc.info/gems/paperclip/2.3.8/Paperclip/Storage/S3, and for
# filesystem see: http://rdoc.info/gems/paperclip/2.3.8/Paperclip/Storage/Filesystem
# config.upload_file_options = {:url => '/system/:class/:id/:attachment/:style/:filename'}
# Sofa allows you to setup entire site from files. Database is updated with each
# request (if necessary). Please note that database entries are destroyed if there's
# no corresponding file. Fixtures are disabled by default.
# config.enable_fixtures = false
# Path where fixtures can be located.
# config.fixtures_path = File.expand_path('db/cms_fixtures', Rails.root)
# Importing fixtures into Database
# To load fixtures into the database just run this rake task:
# local: $ rake comfortable_mexican_sofa:fixtures:import FROM=example.local TO=localhost
# Heroku: $ heroku run rake comfortable_mexican_sofa:fixtures:import FROM=example.local TO=yourapp.herokuapp.com
# From indicates folder the fixtures are in and to is the Site hostname you have defined in the database.
# Exporting fixtures into Files
# If you need to dump database contents into fixture files run:
# local: $ rake comfortable_mexican_sofa:fixtures:export FROM=localhost TO=example.local
# Heroku: $ heroku run rake comfortable_mexican_sofa:fixtures:export FROM=yourapp.herokuapp.com TO=example.local
# This will create example.local folder and dump all content from example.com Site.
# Content for Layouts, Pages and Snippets has a revision history. You can revert
# a previous version using this system. You can control how many revisions per
# object you want to keep. Set it to 0 if you wish to turn this feature off.
# config.revisions_limit = 25
# Locale definitions. If you want to define your own locale merge
# {:locale => 'Locale Title'} with this.
# config.locales = {:en => 'English', :es => 'Español'}
# Admin interface will respect the locale of the site being managed. However you can
# force it to English by setting this to `:en`
# config.admin_locale = nil
# If you want to keep your CMS tables in a location other than the default database
# add a database_config. For example, setting it to 'cms' will look for a cms_#{Rails.env}
# definition in your database.yml file
# config.database_config = nil
# A class that is included as a sweeper to admin base controller if it's set
# config.admin_cache_sweeper = nil
# By default you cannot have irb code inside your layouts/pages/snippets.
# Generally this is to prevent putting something like this:
# <% User.delete_all %> but if you really want to allow it...
# config.allow_irb = false
# Whitelist of all helper methods that can be used via {{cms:helper}} tag. By default
# all helpers are allowed except `eval`, `send`, `call` and few others. Empty array
# will prevent rendering of all helpers.
# config.allowed_helpers = nil
# Whitelist of partials paths that can be used via {{cms:partial}} tag. All partials
# are accessible by default. Empty array will prevent rendering of all partials.
# config.allowed_partials = nil
# Site aliases, if you want to have aliases for your site. Good for harmonizing
# production env with dev/testing envs.
# e.g. config.site_aliases = {'host.com' => 'host.inv', 'host_a.com' => ['host.lvh.me', 'host.dev']}
# Default is nil (not used)
# config.hostname_aliases = nil
end
module CmsSpreeAuth
def authenticate
unless current_user && current_user.has_role?('admin')
redirect_to spree.login_path
end
end
end
# Default credentials for ComfortableMexicanSofa::HttpAuth
# YOU REALLY WANT TO CHANGE THIS BEFORE PUTTING YOUR SITE LIVE
ComfortableMexicanSofa::HttpAuth.username = 'username'
ComfortableMexicanSofa::HttpAuth.password = 'password'
# If you need to inject some html in cms admin views you can define what partial
# should be rendered into the following areas:
# ComfortableMexicanSofa::ViewHooks.add(:navigation, '/layouts/admin/navigation')
# ComfortableMexicanSofa::ViewHooks.add(:html_head, '/layouts/admin/html_head')
# ComfortableMexicanSofa::ViewHooks.add(:page_form, '/layouts/admin/page_form')
ComfortableMexicanSofa::ViewHooks.add(:navigation, 'layouts/cms_nav_spree')
# Provide some Spree helpers to the CMS controller so it can render Spree's layout
ComfortableMexicanSofa::CmsContentController.class_eval do
helper 'spree/base'
include Spree::Core::ControllerHelpers
include Spree::Core::Engine.routes.url_helpers
end

View File

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

View File

@@ -0,0 +1 @@
label: Default Fixture Layout

View File

@@ -0,0 +1,5 @@
<html>
<body>
{{ cms:page:content }}
</body>
</html>

View File

@@ -0,0 +1 @@
body{color: red}

View File

@@ -0,0 +1 @@
// default js

View File

@@ -0,0 +1,2 @@
label: Default Fixture Nested Layout
position: 42

View File

@@ -0,0 +1,2 @@
<div class='left'> {{ cms:page:left }} </div>
<div class='right'> {{ cms:page:right }} </div>

View File

@@ -0,0 +1 @@
div{float:left}

View File

@@ -0,0 +1 @@
// nested js

View File

@@ -0,0 +1,2 @@
label: Home Fixture Page
layout: default

View File

@@ -0,0 +1,3 @@
label: Child Fixture Page
layout: nested
position: 42

View File

@@ -0,0 +1 @@
Child Page Left Fixture Content

View File

@@ -0,0 +1 @@
Child Page Right Fixture Content

View File

@@ -0,0 +1,2 @@
Home Page Fixture Contént
{{ cms:snippet:default }}

View File

@@ -0,0 +1 @@
label: Default Fixture Snippet

View File

@@ -0,0 +1 @@
Fixture Content for Default Snippet

View File

@@ -0,0 +1,137 @@
class CreateCms < ActiveRecord::Migration
def self.up
text_limit = case ActiveRecord::Base.connection.adapter_name
when 'PostgreSQL'
{ }
else
{ :limit => 16777215 }
end
# -- Sites --------------------------------------------------------------
create_table :cms_sites do |t|
t.string :label, :null => false
t.string :identifier, :null => false
t.string :hostname, :null => false
t.string :path
t.string :locale, :null => false, :default => 'en'
t.boolean :is_mirrored, :null => false, :default => false
end
add_index :cms_sites, :hostname
add_index :cms_sites, :is_mirrored
# -- Layouts ------------------------------------------------------------
create_table :cms_layouts do |t|
t.integer :site_id, :null => false
t.integer :parent_id
t.string :app_layout
t.string :label, :null => false
t.string :identifier, :null => false
t.text :content, text_limit
t.text :css, text_limit
t.text :js, text_limit
t.integer :position, :null => false, :default => 0
t.boolean :is_shared, :null => false, :default => false
t.timestamps
end
add_index :cms_layouts, [:parent_id, :position]
add_index :cms_layouts, [:site_id, :identifier], :unique => true
# -- Pages --------------------------------------------------------------
create_table :cms_pages do |t|
t.integer :site_id, :null => false
t.integer :layout_id
t.integer :parent_id
t.integer :target_page_id
t.string :label, :null => false
t.string :slug
t.string :full_path, :null => false
t.text :content, text_limit
t.integer :position, :null => false, :default => 0
t.integer :children_count, :null => false, :default => 0
t.boolean :is_published, :null => false, :default => true
t.boolean :is_shared, :null => false, :default => false
t.timestamps
end
add_index :cms_pages, [:site_id, :full_path]
add_index :cms_pages, [:parent_id, :position]
# -- Page Blocks --------------------------------------------------------
create_table :cms_blocks do |t|
t.integer :page_id, :null => false
t.string :identifier, :null => false
t.text :content
t.timestamps
end
add_index :cms_blocks, [:page_id, :identifier]
# -- Snippets -----------------------------------------------------------
create_table :cms_snippets do |t|
t.integer :site_id, :null => false
t.string :label, :null => false
t.string :identifier, :null => false
t.text :content, text_limit
t.integer :position, :null => false, :default => 0
t.boolean :is_shared, :null => false, :default => false
t.timestamps
end
add_index :cms_snippets, [:site_id, :identifier], :unique => true
add_index :cms_snippets, [:site_id, :position]
# -- Files --------------------------------------------------------------
create_table :cms_files do |t|
t.integer :site_id, :null => false
t.integer :block_id
t.string :label, :null => false
t.string :file_file_name, :null => false
t.string :file_content_type, :null => false
t.integer :file_file_size, :null => false
t.string :description, :limit => 2048
t.integer :position, :null => false, :default => 0
t.timestamps
end
add_index :cms_files, [:site_id, :label]
add_index :cms_files, [:site_id, :file_file_name]
add_index :cms_files, [:site_id, :position]
add_index :cms_files, [:site_id, :block_id]
# -- Revisions -----------------------------------------------------------
create_table :cms_revisions, :force => true do |t|
t.string :record_type, :null => false
t.integer :record_id, :null => false
t.text :data, text_limit
t.datetime :created_at
end
add_index :cms_revisions, [:record_type, :record_id, :created_at]
# -- Categories ---------------------------------------------------------
create_table :cms_categories, :force => true do |t|
t.integer :site_id, :null => false
t.string :label, :null => false
t.string :categorized_type, :null => false
end
add_index :cms_categories, [:site_id, :categorized_type, :label], :unique => true
create_table :cms_categorizations, :force => true do |t|
t.integer :category_id, :null => false
t.string :categorized_type, :null => false
t.integer :categorized_id, :null => false
end
add_index :cms_categorizations, [:category_id, :categorized_type, :categorized_id], :unique => true,
:name => 'index_cms_categorizations_on_cat_id_and_catd_type_and_catd_id'
end
def self.down
drop_table :cms_sites
drop_table :cms_layouts
drop_table :cms_pages
drop_table :cms_snippets
drop_table :cms_blocks
drop_table :cms_files
drop_table :cms_revisions
drop_table :cms_categories
drop_table :cms_categorizations
end
end

View File

@@ -0,0 +1,6 @@
class AddLongDescriptionToDistributorsAndSuppliers < ActiveRecord::Migration
def change
add_column :distributors, :long_description, :text
add_column :suppliers, :long_description, :text
end
end

View File

@@ -11,7 +11,124 @@
#
# It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20121005015852) do
ActiveRecord::Schema.define(:version => 20121010004400) do
create_table "cms_blocks", :force => true do |t|
t.integer "page_id", :null => false
t.string "identifier", :null => false
t.text "content"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "cms_blocks", ["page_id", "identifier"], :name => "index_cms_blocks_on_page_id_and_identifier"
create_table "cms_categories", :force => true do |t|
t.integer "site_id", :null => false
t.string "label", :null => false
t.string "categorized_type", :null => false
end
add_index "cms_categories", ["site_id", "categorized_type", "label"], :name => "index_cms_categories_on_site_id_and_categorized_type_and_label", :unique => true
create_table "cms_categorizations", :force => true do |t|
t.integer "category_id", :null => false
t.string "categorized_type", :null => false
t.integer "categorized_id", :null => false
end
add_index "cms_categorizations", ["category_id", "categorized_type", "categorized_id"], :name => "index_cms_categorizations_on_cat_id_and_catd_type_and_catd_id", :unique => true
create_table "cms_files", :force => true do |t|
t.integer "site_id", :null => false
t.integer "block_id"
t.string "label", :null => false
t.string "file_file_name", :null => false
t.string "file_content_type", :null => false
t.integer "file_file_size", :null => false
t.string "description", :limit => 2048
t.integer "position", :default => 0, :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "cms_files", ["site_id", "block_id"], :name => "index_cms_files_on_site_id_and_block_id"
add_index "cms_files", ["site_id", "file_file_name"], :name => "index_cms_files_on_site_id_and_file_file_name"
add_index "cms_files", ["site_id", "label"], :name => "index_cms_files_on_site_id_and_label"
add_index "cms_files", ["site_id", "position"], :name => "index_cms_files_on_site_id_and_position"
create_table "cms_layouts", :force => true do |t|
t.integer "site_id", :null => false
t.integer "parent_id"
t.string "app_layout"
t.string "label", :null => false
t.string "identifier", :null => false
t.text "content"
t.text "css"
t.text "js"
t.integer "position", :default => 0, :null => false
t.boolean "is_shared", :default => false, :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "cms_layouts", ["parent_id", "position"], :name => "index_cms_layouts_on_parent_id_and_position"
add_index "cms_layouts", ["site_id", "identifier"], :name => "index_cms_layouts_on_site_id_and_identifier", :unique => true
create_table "cms_pages", :force => true do |t|
t.integer "site_id", :null => false
t.integer "layout_id"
t.integer "parent_id"
t.integer "target_page_id"
t.string "label", :null => false
t.string "slug"
t.string "full_path", :null => false
t.text "content"
t.integer "position", :default => 0, :null => false
t.integer "children_count", :default => 0, :null => false
t.boolean "is_published", :default => true, :null => false
t.boolean "is_shared", :default => false, :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "cms_pages", ["parent_id", "position"], :name => "index_cms_pages_on_parent_id_and_position"
add_index "cms_pages", ["site_id", "full_path"], :name => "index_cms_pages_on_site_id_and_full_path"
create_table "cms_revisions", :force => true do |t|
t.string "record_type", :null => false
t.integer "record_id", :null => false
t.text "data"
t.datetime "created_at"
end
add_index "cms_revisions", ["record_type", "record_id", "created_at"], :name => "index_cms_revisions_on_record_type_and_record_id_and_created_at"
create_table "cms_sites", :force => true do |t|
t.string "label", :null => false
t.string "identifier", :null => false
t.string "hostname", :null => false
t.string "path"
t.string "locale", :default => "en", :null => false
t.boolean "is_mirrored", :default => false, :null => false
end
add_index "cms_sites", ["hostname"], :name => "index_cms_sites_on_hostname"
add_index "cms_sites", ["is_mirrored"], :name => "index_cms_sites_on_is_mirrored"
create_table "cms_snippets", :force => true do |t|
t.integer "site_id", :null => false
t.string "label", :null => false
t.string "identifier", :null => false
t.text "content"
t.integer "position", :default => 0, :null => false
t.boolean "is_shared", :default => false, :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
add_index "cms_snippets", ["site_id", "identifier"], :name => "index_cms_snippets_on_site_id_and_identifier", :unique => true
add_index "cms_snippets", ["site_id", "position"], :name => "index_cms_snippets_on_site_id_and_position"
create_table "distributors", :force => true do |t|
t.string "name"
@@ -27,6 +144,7 @@ ActiveRecord::Schema.define(:version => 20121005015852) do
t.datetime "updated_at"
t.integer "pickup_address_id"
t.string "next_collection_at"
t.text "long_description"
end
create_table "product_distributions", :force => true do |t|
@@ -133,7 +251,7 @@ ActiveRecord::Schema.define(:version => 20121005015852) do
t.integer "numcode"
end
create_table "spree_credit_cards", :force => true do |t|
create_table "spree_creditcards", :force => true do |t|
t.string "month"
t.string "year"
t.string "cc_type"
@@ -663,6 +781,7 @@ ActiveRecord::Schema.define(:version => 20121005015852) do
t.datetime "created_at"
t.datetime "updated_at"
t.integer "address_id"
t.text "long_description"
end
end

View File

@@ -0,0 +1,57 @@
module OpenFoodWeb
GroupBuyVariantRow = Struct.new(:variant, :sum_quantities, :sum_max_quantities) do
def to_row
[variant.product.supplier.name, variant.product.name, "UNITSIZE", variant.options_text, variant.weight, sum_quantities, sum_max_quantities]
end
end
GroupBuyProductRow = Struct.new(:product, :sum_quantities, :sum_max_quantities) do
def to_row
[product.supplier.name, product.name, "UNITSIZE", "TOTAL", "", sum_quantities, sum_max_quantities]
end
end
class GroupBuyReport
def initialize orders
@orders = orders
end
def header
["Supplier", "Product", "Unit Size", "Variant", "Weight", "Total Ordered", "Total Max"]
end
def variants_and_quantities
variants_and_quantities = []
line_items = @orders.map { |o| o.line_items }.flatten
supplier_groups = line_items.group_by { |li| li.variant.product.supplier }
supplier_groups.each do |supplier, line_items_by_supplier|
product_groups = line_items_by_supplier.group_by { |li| li.variant.product }
product_groups.each do |product, line_items_by_product|
# Cycle thorugh variant of a product
variant_groups = line_items_by_product.group_by { |li| li.variant }
variant_groups.each do |variant, line_items_by_variant|
sum_quantities = line_items_by_variant.sum { |li| li.quantity }
sum_max_quantities = line_items_by_variant.sum { |li| li.max_quantity || 0 }
variants_and_quantities << GroupBuyVariantRow.new(variant, sum_quantities, sum_max_quantities)
end
# Sum quantities for each product (Total line)
sum_quantities = line_items_by_product.sum { |li| li.variant.weight * li.quantity }
sum_max_quantities = line_items_by_product.sum { |li| li.variant.weight * (li.max_quantity || 0) }
variants_and_quantities << GroupBuyProductRow.new(product, sum_quantities, sum_max_quantities)
end
end
variants_and_quantities
end
def table
table = []
variants_and_quantities.each do |vr|
table << vr.to_row
end
table
end
end
end

View File

@@ -5,6 +5,7 @@ FactoryGirl.define do
factory :supplier, :class => Spree::Supplier do
sequence(:name) { |n| "Supplier #{n}" }
description 'supplier'
long_description '<p>Hello, world!</p><p>This is a paragraph.</p>'
email 'supplier@example.com'
address { Spree::Address.first || FactoryGirl.create(:address) }
end
@@ -14,6 +15,7 @@ FactoryGirl.define do
contact 'Mr Turing'
phone '1000100100'
description 'The creator'
long_description '<p>Hello, world!</p><p>This is a paragraph.</p>'
email 'alan@somewhere.com'
url 'http://example.com'
pickup_times "Whenever you're free"
@@ -74,3 +76,39 @@ FactoryGirl.modify do
country { Spree::Country.find_by_name 'Australia' || Spree::Country.first }
end
end
# -- CMS
FactoryGirl.define do
factory :cms_site, :class => Cms::Site do
identifier 'open-food-web'
label 'Open Food Web'
hostname 'localhost'
end
factory :cms_layout, :class => Cms::Layout do
site { Cms::Site.first || create(:cms_site) }
label 'layout'
identifier 'layout'
content '{{ cms:page:content:text }}'
end
factory :cms_page, :class => Cms::Page do
site { Cms::Site.first || create(:cms_site) }
label 'page'
sequence(:slug) { |n| "page-#{n}" }
layout { Cms::Layout.first || create(:cms_layout) }
# Pass content through to block, where it is stored
after(:create) do |cms_page, evaluator|
cms_page.blocks.first.update_attribute(:content, evaluator.content)
cms_page.save! # set_cached_content
end
end
factory :cms_block, :class => Cms::Block do
page { Cms::Page.first || create(:cms_page) }
identifier 'block'
content 'hello, block'
end
end

View File

@@ -0,0 +1,97 @@
require 'spec_helper'
module OpenFoodWeb
describe GroupBuyReport do
before(:each) do
@orders = []
bill_address = create(:address)
distributor_address = create(:address, :address1 => "distributor address", :city => 'The Shire', :zipcode => "1234")
distributor = create(:distributor, :pickup_address => distributor_address)
@supplier1 = create(:supplier)
@variant1 = create(:variant)
@variant1.product.supplier = @supplier1
@variant1.product.save!
shipping_method = create(:shipping_method)
product_distribution = create(:product_distribution, :product => @variant1.product, :distributor => distributor, :shipping_method => create(:shipping_method))
shipping_instructions = "pick up on thursday please!"
order1 = create(:order, :distributor => distributor, :bill_address => bill_address, :special_instructions => shipping_instructions)
line_item11 = create(:line_item, :variant => @variant1, :order => order1)
order1.line_items << line_item11
@orders << order1
order2 = create(:order, :distributor => distributor, :bill_address => bill_address, :special_instructions => shipping_instructions)
line_item21 = create(:line_item, :variant => @variant1, :order => order2)
order2.line_items << line_item21
@variant2 = create(:variant)
@variant2.product.supplier = @supplier1
@variant2.product.save!
product_distribution = create(:product_distribution, :product => @variant2.product, :distributor => distributor, :shipping_method => create(:shipping_method))
line_item22 = create(:line_item, :variant => @variant2, :order => order2)
order2.line_items << line_item22
@orders << order2
@supplier2 = create(:supplier)
@variant3 = create(:variant)
@variant3.product.supplier = @supplier2
@variant3.product.save!
product_distribution = create(:product_distribution, :product => @variant3.product, :distributor => distributor, :shipping_method => create(:shipping_method))
order3 = create(:order, :distributor => distributor, :bill_address => bill_address, :special_instructions => shipping_instructions)
line_item31 = create(:line_item, :variant => @variant3, :order => order3)
order3.line_items << line_item31
@orders << order3
end
it "should return a header row describing the report" do
subject = GroupBuyReport.new [@order1]
header = subject.header
header.should == ["Supplier", "Product", "Unit Size", "Variant", "Weight", "Total Ordered", "Total Max"]
end
it "should provide the required variant and quantity information in a table" do
subject = GroupBuyReport.new @orders
table = subject.table
line_items = @orders.map{ |o| o.line_items }.flatten.select{ |li| li.product.supplier == @supplier1 && li.variant == @variant1 }
sum_quantities = line_items.map { |li| li.quantity }.sum
sum_max_quantities = line_items.map { |li| li.max_quantity || 0 }.sum
table[0].should == [@variant1.product.supplier.name,@variant1.product.name,"UNITSIZE",@variant1.options_text,@variant1.weight,sum_quantities,sum_max_quantities]
end
it "should return a table wherein each rows contains the same number of columns as the heading" do
subject = GroupBuyReport.new @orders
table = subject.table
columns = subject.header.length
table.each do |r|
r.length.should == columns
end
end
it "should split and group line items from multiple suppliers and of multiple variants" do
subject = GroupBuyReport.new @orders
table_row_objects = subject.variants_and_quantities
variant_rows = table_row_objects.select{ |r| r.class == OpenFoodWeb::GroupBuyVariantRow }
product_rows = table_row_objects.select{ |r| r.class == OpenFoodWeb::GroupBuyProductRow }
supplier_groups = variant_rows.group_by { |r| r.variant.product.supplier }
variant_groups = variant_rows.group_by{ |r| r.variant }
product_groups = product_rows.group_by{ |r| r.product }
supplier_groups.length.should == 2
variant_groups.length.should == 3
product_groups.length.should == 3
end
end
end

View File

@@ -43,9 +43,6 @@ module OpenFoodWeb
@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

@@ -0,0 +1,34 @@
require 'spec_helper'
feature %q{
In order to provide content to users of the site
As an administrator
I want to access the CMS admin site
} do
include AuthenticationWorkflow
include WebHelper
scenario "admin can access CMS admin and return to Spree admin" do
login_to_admin_section
click_link 'CMS Admin'
page.should have_content "ComfortableMexicanSofa"
click_link 'Spree Admin'
page.should have_selector 'h1', :text => 'Administration'
end
scenario "anonymous user can't access CMS admin" do
visit cms_admin_path
page.should_not have_content "ComfortableMexicanSofa"
page.should have_content "Login"
end
scenario "non-admin user can't access CMS admin" do
login_to_consumer_section
visit cms_admin_path
page.should_not have_content "ComfortableMexicanSofa"
page.should have_content "Open Food Web"
end
end

View File

@@ -8,6 +8,25 @@ feature %q{
include WebHelper
scenario "listing distributors" do
d = create(:distributor)
login_to_admin_section
click_link 'Distributors'
page.should have_content d.name
end
scenario "viewing a distributor" do
d = create(:distributor)
login_to_admin_section
click_link 'Distributors'
click_link d.name
page.should have_content d.name
end
scenario "creating a new distributor" do
login_to_admin_section
@@ -16,6 +35,7 @@ feature %q{
fill_in 'distributor_name', :with => 'Eaterprises'
fill_in 'distributor_description', :with => 'Connecting farmers and eaters'
fill_in 'distributor_long_description', :with => 'Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro.'
fill_in 'distributor_contact', :with => 'Kirsten or Ren'
fill_in 'distributor_phone', :with => '0413 897 321'

View File

@@ -10,29 +10,47 @@ feature %q{
background do
end
context "setting up suppliers" do
scenario "creating a new supplier" do
login_to_admin_section
scenario "listing suppliers" do
s = create(:supplier)
click_link 'Suppliers'
click_link 'New Supplier'
login_to_admin_section
click_link 'Suppliers'
fill_in 'supplier_name', :with => 'David Arnold'
fill_in 'supplier_description', :with => 'A farmer with a difference'
page.should have_content s.name
end
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')
scenario "viewing a supplier" do
s = create(:supplier)
fill_in 'supplier_email', :with => 'david@here.com'
fill_in 'supplier_website', :with => 'http://somewhere.com'
fill_in 'supplier_twitter', :with => 'davida'
login_to_admin_section
click_link 'Suppliers'
click_link s.name
click_button 'Create'
page.should have_content s.name
end
flash_message.should == 'Supplier "David Arnold" has been successfully created!'
end
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_description', :with => 'A farmer with a difference'
fill_in 'supplier_long_description', :with => 'Zombie ipsum reversus ab viral inferno, nam rick grimes malum cerebro.'
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!'
end
end

View File

@@ -0,0 +1,51 @@
require 'spec_helper'
feature %q{
In order to learn about food
As a user of the site
I want to see static content pages
} do
include AuthenticationWorkflow
include WebHelper
scenario "viewing the home page" do
# Given a CMS home page
create(:cms_page, content: 'Home page content')
# When I visit the home page
visit spree.root_path
# Then I should see my content
page.should have_content 'Home page content'
end
scenario "viewing another products listing page does not display home page content" do
# Given a CMS home page
create(:cms_page, content: 'Home page content')
# When I visit a products listing page
visit spree.products_path
# Then I should not see the home page content
page.should_not have_content 'Home page content'
end
scenario "viewing the menu of CMS pages" do
# Given some CMS pages
home_page = create(:cms_page, content: 'Home')
create(:cms_page, parent: home_page, label: 'One')
create(:cms_page, parent: home_page, label: 'Two')
create(:cms_page, parent: home_page, label: 'Three')
# When I visit the home page
visit spree.root_path
# Then I should see a menu with these pages
page.should have_selector 'ul#main-nav-bar li', :text => 'One'
page.should have_selector 'ul#main-nav-bar li', :text => 'Two'
page.should have_selector 'ul#main-nav-bar li', :text => 'Three'
end
end

View File

@@ -26,19 +26,36 @@ feature %q{
page.should_not have_selector 'a', :text => d3.name
end
context "when a distributor is selected" do
it "displays the distributor's name" do
it "displays the distributor's details" do
# Given a distributor with a product
d = create(:distributor, :name => 'Melb Uni Co-op')
d = create(:distributor, :name => 'Melb Uni Co-op', :description => '<p>Hello, world!</p>')
create(:product, :distributors => [d])
# When I select the distributor
visit spree.root_path
click_link d.name
# Then I should see the name of the distributor that I've selected
page.should have_selector 'h2', :text => 'Melb Uni Co-op'
# And I should see the distributor's long description
page.should have_selector 'div.distributor-description', :text => 'Hello, world!'
end
it "displays the distributor's name on the home page" do
# Given a distributor with a product
d = create(:distributor, :name => 'Melb Uni Co-op', :description => '<p>Hello, world!</p>')
create(:product, :distributors => [d])
# When I select the distributor
visit spree.root_path
click_link d.name
visit spree.root_path
# Then I should see the name of the distributor that I've selected
page.should have_content 'You are shopping at Melb Uni Co-op'
page.should_not have_selector 'div.distributor-description'
end
it "splits the product listing by local/remote distributor" do
@@ -54,6 +71,7 @@ feature %q{
# When I select the first distributor
visit spree.root_path
click_link d1.name
visit spree.root_path
# 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

View File

@@ -23,14 +23,18 @@ feature %q{
scenario "viewing products provided by a supplier" do
# Given a supplier with a product
s = create(:supplier, :name => 'Murrnong')
s = create(:supplier, :name => 'Murrnong', :long_description => "<p>Hello, world!</p>")
p = create(:product, :supplier => s)
# When I select the supplier
visit spree.root_path
click_link s.name
# Then I should see the product
# Then I should see the supplier details
page.should have_selector 'h2', :text => s.name
page.should have_selector 'div.supplier-description', :text => 'Hello, world!'
# And I should see the product
page.should have_content p.name
end
end

View File

@@ -17,6 +17,9 @@ module AuthenticationWorkflow
end
def login_to_consumer_section
# The first user is given the admin role by Spree, so create a dummy user if this is the first
create(:user) if Spree::User.admin.empty?
user_role = Spree::Role.create(:name => 'user')
user = Spree::User.create({
:email => 'someone@ofw.org',