Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

business hour exceptions. refactored business hours to use actual dat…

…etimes. admin pages for business hours and business hour exceptions. security against mass-assignment in models. rake tasks to load some dev data
  • Loading branch information...
commit 85790130414c2fe6d042ec04811ebdc9b33481a2 1 parent 736a066
@jamezilla authored
Showing with 615 additions and 78 deletions.
  1. +9 −0 app/admin/business_hour_exceptions.rb
  2. +79 −0 app/admin/business_hours.rb
  3. +8 −0 app/admin/locations.rb
  4. +0 −4 app/assets/javascripts/active_admin.js.coffee
  5. +3 −0  app/assets/javascripts/business_hour_exceptions.js.coffee
  6. +3 −2 app/assets/javascripts/reservations.js.coffee
  7. +0 −3  app/assets/stylesheets/active_admin.css.scss
  8. +3 −0  app/assets/stylesheets/business_hour_exceptions.css.scss
  9. +2 −0  app/controllers/business_hour_exceptions_controller.rb
  10. +23 −13 app/controllers/reservations_controller.rb
  11. +2 −0  app/helpers/business_hour_exceptions_helper.rb
  12. +3 −0  app/inputs/date_picker_input.rb
  13. +3 −0  app/inputs/formtastic_time_picker_input.rb
  14. +2 −0  app/inputs/simpleform_time_picker_input.rb
  15. +0 −3  app/inputs/time_picker_input.rb
  16. +3 −0  app/models/asset_tag.rb
  17. +2 −0  app/models/brand.rb
  18. +2 −0  app/models/budget.rb
  19. +53 −15 app/models/business_hour.rb
  20. +25 −0 app/models/business_hour_exception.rb
  21. +2 −0  app/models/category.rb
  22. +12 −0 app/models/kit.rb
  23. +81 −2 app/models/location.rb
  24. +5 −2 app/models/model.rb
  25. +41 −3 app/models/reservation.rb
  26. +12 −0 app/views/business_hour_exceptions/_form.html.erb
  27. +6 −0 app/views/business_hour_exceptions/edit.html.erb
  28. +25 −0 app/views/business_hour_exceptions/index.html.erb
  29. +5 −0 app/views/business_hour_exceptions/new.html.erb
  30. +15 −0 app/views/business_hour_exceptions/show.html.erb
  31. +1 −1  app/views/business_hours/_form.html.erb
  32. +16 −0 app/views/layouts/application.html.erb
  33. +1 −0  app/views/models/index.html.erb
  34. +2 −2 app/views/reservations/_form.html.erb
  35. +20 −15 app/views/reservations/show.html.erb
  36. +2 −1  config/application.rb
  37. +7 −4 config/routes.rb
  38. +2 −3 db/migrate/20120307071639_create_business_hours.rb
  39. +11 −0 db/migrate/20120312235755_create_business_hour_exceptions.rb
  40. +12 −4 db/schema.rb
  41. BIN  doc/checkout.graffle
  42. +43 −1 lib/tasks/legacy_migration.rake
  43. +9 −0 test/fixtures/business_hour_exceptions.yml
  44. +49 −0 test/functional/business_hour_exceptions_controller_test.rb
  45. +7 −0 test/unit/business_hour_exception_test.rb
  46. +4 −0 test/unit/helpers/business_hour_exceptions_helper_test.rb
View
9 app/admin/business_hour_exceptions.rb
@@ -0,0 +1,9 @@
+ActiveAdmin.register BusinessHourException do
+
+ index do
+ column :location
+ column :date_closed
+ column :updated_at
+ end
+
+end
View
79 app/admin/business_hours.rb
@@ -0,0 +1,79 @@
+ActiveAdmin.register BusinessHour do
+
+ filter :location
+
+ form do |f|
+ f.inputs "Details" do
+ f.input :location
+ f.input :day, :as => :select, :collection => BusinessHour.days_for_select
+ f.input :open_at, :as => :time
+ f.input :closed_at, :as => :time
+ end
+ f.buttons
+ end
+
+ index do
+ column :location
+ column "Hours" do |h|
+ h.to_s
+ end
+ default_actions
+ end
+
+ show do |bh|
+ attributes_table do
+ row :hours do
+ bh.to_s
+ end
+ end
+ active_admin_comments
+ end
+
+
+ controller do
+
+ before_filter :munge_params, :only => [:create, :update]
+
+ def new
+ utc_offset = (Time.now.utc_offset / 60 / 60).to_s
+ open = DateTime.commercial(1969, 1, 1, 9, 0, 0, utc_offset)
+ close = DateTime.commercial(1969, 1, 1, 17, 0, 0, utc_offset)
+ @business_hour = BusinessHour.new(:open_at => open, :closed_at => close)
+ end
+
+
+ protected
+
+ def munge_params
+
+
+ # delete the junk in formtastic's weird ass format
+ params['business_hour'].delete('open_at(1i)')
+ params['business_hour'].delete('open_at(2i)')
+ params['business_hour'].delete('open_at(3i)')
+ params['business_hour'].delete('closed_at(1i)')
+ params['business_hour'].delete('closed_at(2i)')
+ params['business_hour'].delete('closed_at(3i)')
+
+ # reconstruct the times in OUR weird ass format
+ utc_offset = (Time.now.utc_offset / 60 / 60).to_s
+
+ day = params['business_hour'].delete('day')
+ day = Date::DAYS_INTO_WEEK[day.to_sym] + 1
+
+ open_hour = params['business_hour'].delete('open_at(4i)').to_i
+ open_minute = params['business_hour'].delete('open_at(5i)').to_i
+
+ closed_hour = params['business_hour'].delete('closed_at(4i)').to_i
+ closed_minute = params['business_hour'].delete('closed_at(5i)').to_i
+
+ logger.debug "---- open #{ day.inspect } #{ open_hour.inspect} #{ open_minute.inspect}"
+ logger.debug "---- closed #{ day.inspect } #{ closed_hour.inspect} #{ closed_minute.inspect}"
+
+ params['business_hour']['open_at'] = DateTime.commercial(1969, 1, day, open_hour, open_minute, 0, utc_offset)
+ params['business_hour']['closed_at'] = DateTime.commercial(1969, 1, day, closed_hour, closed_minute, 0, utc_offset)
+ end
+
+ end
+
+end
View
8 app/admin/locations.rb
@@ -0,0 +1,8 @@
+ActiveAdmin.register Location do
+
+ index do
+ column :name
+ default_actions
+ end
+
+end
View
4 app/assets/javascripts/active_admin.js.coffee
@@ -1,5 +1 @@
//= require active_admin/base
-//= require jquery.calendrical
-
-jQuery ->
- $('.timepicker').calendricalTime()
View
3  app/assets/javascripts/business_hour_exceptions.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
View
5 app/assets/javascripts/reservations.js.coffee
@@ -1,6 +1,7 @@
jQuery ->
- $(".datepicker").datepicker(
- altFormat: "yyyy-mm-dd",
+ $("input.date_picker").datepicker(
+ altFormat: "yy-mm-dd",
+ dateFormat: "yy-mm-dd",
minDate: "-0d",
# TODO: parameterize this range
maxDate: "+90d",
View
3  app/assets/stylesheets/active_admin.css.scss
@@ -2,6 +2,3 @@
@import "active_admin/mixins";
@import "active_admin/base";
-// To customize the Active Admin interfaces, add your
-// styles here:
-@import "calendrical"
View
3  app/assets/stylesheets/business_hour_exceptions.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the BusinessHourExceptions controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
View
2  app/controllers/business_hour_exceptions_controller.rb
@@ -0,0 +1,2 @@
+class BusinessHourExceptionsController < InheritedResources::Base
+end
View
36 app/controllers/reservations_controller.rb
@@ -1,4 +1,5 @@
class ReservationsController < ApplicationController
+
# GET /reservations
# GET /reservations.json
def index
@@ -24,14 +25,26 @@ def show
# GET /reservations/new
# GET /reservations/new.json
def new
- if params[:user_id].present? && params[:kit_id].present?
- @reservation = User.find(params[:user_id]).reservations.build(:kit_id =>params[:kit_id])
+ @user = (params[:user_id]) ? User.find(params[:user_id]) : current_user
+
+ if params[:kit_id].present?
+ # we have a specific kit to check out
+ @reservation = @user.reservations.build(:kit_id => params[:kit_id])
+
+ # gather the available checkout days for the kit
+ gon.days_open = @reservation.kit.location.open_days
+
+ # do we have a general model to check out?
+ elsif params[:model_id].present?
+ @reservation = @user.reservations.build
+ @model = Model.find(params[:model_id])
+# @reservation = Model.find(params[:model_id].)
+
else
- flash[:error] = "No kit was specified, start by finding something to check out"
- redirect_to root
+ flash[:error] = "Start by finding something to check out!"
+ redirect_to models_path and return
end
- set_open_days
respond_to do |format|
format.html # new.html.erb
@@ -42,7 +55,9 @@ def new
# GET /reservations/1/edit
def edit
@reservation = Reservation.find(params[:id])
- set_open_days
+
+ gon.days_open = @reservation.kit.location.open_days
+
end
# POST /reservations
@@ -55,7 +70,8 @@ def create
format.html { redirect_to @reservation, notice: 'Reservation was successfully created.' }
format.json { render json: @reservation, status: :created, location: @reservation }
else
- set_open_days
+ logger.debug "----" + @reservation.errors.inspect
+ # FIXME: set_open_days
format.html { render action: "new" }
format.json { render json: @reservation.errors, status: :unprocessable_entity }
@@ -92,10 +108,4 @@ def destroy
end
end
- protected
-
- def set_open_days
- gon.days_open = @reservation.kit.location.open_days
- end
-
end
View
2  app/helpers/business_hour_exceptions_helper.rb
@@ -0,0 +1,2 @@
+module BusinessHourExceptionsHelper
+end
View
3  app/inputs/date_picker_input.rb
@@ -0,0 +1,3 @@
+class DatePickerInput < SimpleForm::Inputs::StringInput
+
+end
View
3  app/inputs/formtastic_time_picker_input.rb
@@ -0,0 +1,3 @@
+class FormtasticTimePickerInput < Formtastic::Inputs::StringInput
+
+end
View
2  app/inputs/simpleform_time_picker_input.rb
@@ -0,0 +1,2 @@
+class SimpleformTimePickerInput < SimpleForm::Inputs::StringInput
+
View
3  app/inputs/time_picker_input.rb
@@ -1,3 +0,0 @@
-class TimePickerInput < SimpleForm::Inputs::StringInput
-
-end
View
3  app/models/asset_tag.rb
@@ -1,3 +1,6 @@
class AssetTag < ActiveRecord::Base
belongs_to :part
+
+ attr_accessible :uid, :part_id
+
end
View
2  app/models/brand.rb
@@ -1,6 +1,8 @@
class Brand < ActiveRecord::Base
has_many :models
+ attr_accessible :name
+
default_scope order("brands.name ASC")
def self.tombstoned
View
2  app/models/budget.rb
@@ -12,6 +12,8 @@ class Budget < ActiveRecord::Base
before_validation :strip_fields
+ attr_accessible :name, :number, :date_start, :date_end
+
def self.options_map
order("date_start DESC, number ASC").all.map { |b| [b.to_s, b.id] }
end
View
68 app/models/business_hour.rb
@@ -9,9 +9,8 @@ class BusinessHour < ActiveRecord::Base
# :message => "should happen once per year"
# }
- validates :day, :presence => true
- validates :open, :presence => true
- validates :close, :presence => true
+ validates :open_at, :presence => true
+ validates :closed_at, :presence => true
validate :validate_hours_in_order
@@ -25,16 +24,9 @@ class BusinessHour < ActiveRecord::Base
# end
# end
- def validate_hours_in_order
- unless hours_in_order?
- errors.add(:open, "must come before close")
- errors.add(:close, "must come after open")
- end
- end
-
- def hours_in_order?
- Time.parse(open) < Time.parse(close)
- end
+ attr_accessible :location_id, :open_at, :closed_at
+
+ default_scope joins(:location).order("locations.name ASC, business_hours.open_at ASC")
def self.days_for_select
IceCube::TimeUtil::DAYS.collect {|k,v| [k.to_s.titleize, k] }
@@ -59,12 +51,58 @@ def self.times_for_select
times.flatten!
end
+ def validate_hours_in_order
+ unless hours_in_order?
+ errors.add(:open_at, "must come before close")
+ errors.add(:closed_at, "must come after open")
+ end
+ end
+
+ def hours_in_order?
+ open_at < closed_at
+ end
+
+ def day
+ open_at.try(:strftime, '%A')
+ end
+
+ def day_sym
+ day.downcase.to_sym
+ end
+
+ def open_hour
+ open_at.strftime('%k').to_i
+ end
+
+ def open_minute
+ open_at.strftime('%M').to_i
+ end
+
+ def open_at_to_s
+ open_at.try(:strftime, '%l:%M%P').try(:strip)
+ end
+
+ def closed_at_to_s
+ closed_at.try(:strftime, '%l:%M%P').try(:strip)
+ end
+
+ def closed_hour
+ closed_at.strftime('%k').to_i
+ end
+
+ def closed_minute
+ closed_at.strftime('%M').to_i
+ end
+
+ def to_s
+ "#{ day } #{ open_at_to_s }-#{ closed_at_to_s }"
+ end
+
def open_occurrences(days_out = 90)
schedule = IceCube::Schedule.new
- schedule.add_recurrence_rule IceCube::Rule.weekly.day(self.day.to_sym)
+ schedule.add_recurrence_rule IceCube::Rule.weekly.day(day_sym)
open_days = schedule.occurrences_between(Time.now, (Time.now + days_out.days)).collect { |d| [d.month, d.day]}
return open_days
end
-
end
View
25 app/models/business_hour_exception.rb
@@ -0,0 +1,25 @@
+class BusinessHourException < ActiveRecord::Base
+ belongs_to :location
+
+ validates :location_id, :presence => true
+ validates :date_closed, :presence => true
+
+ default_scope order("location_id ASC, date_closed ASC")
+
+ def day
+ date_closed.strftime('%e')
+ end
+
+ def day_sym
+ day.downcase.to_sym
+ end
+
+ def month
+ date_closed.strftime('%-m')
+ end
+
+ def to_a
+ [month.to_i, day.to_i]
+ end
+
+end
View
2  app/models/category.rb
@@ -3,4 +3,6 @@ class Category < ActiveRecord::Base
default_scope order("categories.name ASC")
+ attr_accessible :name, :description
+
end
View
12 app/models/kit.rb
@@ -1,4 +1,5 @@
class Kit < ActiveRecord::Base
+
belongs_to :location
has_many :parts
has_many :models, :through => :parts
@@ -12,12 +13,23 @@ class Kit < ActiveRecord::Base
default_scope order("kits.name ASC")
+ attr_accessible :name, :location_id, :tombstoned, :checkoutable
+
def should_have_at_least_one_part
if parts.count < 1
errors[:base] << "Kit should have at least one part"
end
end
+ def days_reservable(days_out = 90)
+ checkout_hours = location.open_days(days_out)
+
+ end
+
+ def days_reserved(days_out = 90)
+
+ end
+
def to_s
name
end
View
83 app/models/location.rb
@@ -1,6 +1,8 @@
class Location < ActiveRecord::Base
+
has_many :kits
has_many :business_hours
+ has_many :business_hour_exceptions
validates :name, :uniqueness => true
@@ -8,14 +10,91 @@ class Location < ActiveRecord::Base
# TODO: enforce some referential integrity so you can't delete a location and orphan all its kits
- def open_on?(date)
+ # returns the last closing time for the given date
+ def closes_at(date)
+ # return nothing if we're closed on this day
+ if !business_hour_exceptions.where("date_closed = ?", date.to_date).empty?
+ return nil
+ end
+
+ # figure out our target day of the week
+ day_offset = date.days_to_week_start
+
+ hours_on_day = Array.new
+ business_hours.each do |bh|
+ if bh.closed_at.days_to_week_start == day_offset
+ hours_on_day << bh
+ end
+ end
+
+ return nil if hours_on_day.empty?
+
+ # sort them
+ hours_on_day.sort_by! { |x| x.closed_at }
+
+ # construct a new datetime with the right hours on the day of inquiry
+ # FIXME: I'm sure this calculation of base_datetime is buggy in some time zone
+ base_datetime = (date.to_datetime + 1.day).in_time_zone.at_beginning_of_day
+ hour_offset = hours_on_day.first.closed_hour.hours
+ minute_offset = hours_on_day.first.closed_minute.minutes
+
+ return base_datetime + hour_offset + minute_offset
+ end
+
+ # returns an array of [month, day] pairs for each
+ # business_hour_exception at this location
+ def exception_days(days_out = 90)
+ dates = business_hour_exceptions.where("date_closed > ? AND date_closed < ?", Time.now.to_date, Time.now.to_date + days_out.days)
+ dates.collect { |d| d.to_a }
+ end
+
+ # returns the first opening time for the given date
+ def opens_at(date)
+ # return nothing if we're closed on this day
+ if !business_hour_exceptions.where("date_closed = ?", date.to_date).empty?
+ return nil
+ end
+
+ # figure out our target day of the week
+ day_offset = date.days_to_week_start
+
+ hours_on_day = Array.new
+ business_hours.each do |bh|
+ if bh.open_at.days_to_week_start == day_offset
+ hours_on_day << bh
+ end
+ end
+
+ return nil if hours_on_day.empty?
+
+ # sort them
+ hours_on_day.sort_by! { |x| x.open_at }
+
+ # construct a new datetime with the right hours on the day of inquiry
+ # FIXME: I'm sure this calculation of base_datetime is buggy in some time zone
+ base_datetime = (date.to_datetime + 1.day).in_time_zone.at_beginning_of_day
+ hour_offset = hours_on_day.first.open_hour.hours
+ minute_offset = hours_on_day.first.open_minute.minutes
+ return base_datetime + hour_offset + minute_offset
+ end
+
+ def closed_on?(date)
+ return !open_on?(date)
+ end
+
+ def open_on?(date)
+ return opens_at(date) ? true : false
end
def open_days(days_out = 90)
days = []
business_hours.each { |x| days.concat(x.open_occurrences(days_out)) }
- return days
+ return days - exception_days
+ end
+
+ def to_s
+ name
end
end
View
7 app/models/model.rb
@@ -5,7 +5,7 @@ class Model < ActiveRecord::Base
has_many :kits, :through => :parts
has_and_belongs_to_many :categories
- default_scope eager_load(:brand).order("brands.name ASC, models.name ASC")
+ default_scope eager_load(:brand, :kits).order("brands.name ASC, models.name ASC")
def self.tombstoned
joins(:parts => :kit).where("kits.tombstoned = ?", true).uniq
@@ -19,7 +19,10 @@ def self.checkoutable
joins(:parts => :kit ).where("kits.tombstoned = ? AND kits.checkoutable = ?", false, true).uniq
end
- # TODO: implement self.reservable
+ # TODO: implement this
+ def self.reservable(from_date, to_date)
+
+ end
def self.brand(brand_id)
joins(:brand).where('brands.id = ?', brand_id.to_i)
View
44 app/models/reservation.rb
@@ -6,8 +6,46 @@ class Reservation < ActiveRecord::Base
belongs_to :out_assistant, :class_name => "User"
belongs_to :in_assistant, :class_name => "User"
- validates :kit_id, :presence => true
- validates :start_at, :presence => true
- validates :end_at, :presence => true
+ validates :client_id, :presence => true
+ validates :kit_id, :presence => true
+ validates :start_at, :presence => true
+ validates :end_at, :presence => true
+
+ attr_accessible :client_id, :kit_id, :start_at, :end_at
+
+ before_validation :adjust_start_at
+ before_validation :adjust_end_at
+
+ def adjust_start_at
+ set_to_location_open_at!
+ end
+
+ def adjust_end_at
+ set_to_location_close_at!
+ end
+
+ # TODO: deal with UTC parsing problems
+ def set_to_location_open_at!
+ # get the first opening time on the day
+ opens_at = kit.location.opens_at(self.start_at)
+
+ # figure out what the opening time's offset is from midnight
+ offset = opens_at.seconds_since_midnight
+
+ # set start_at to the same offset
+ self.start_at = self.start_at.beginning_of_day + offset
+ end
+
+ def set_to_location_close_at!
+ # get the last closing time on the day
+ closes_at = kit.location.closes_at(self.end_at)
+
+ # figure out what the closing time's offset is from midnight
+ offset = closes_at.seconds_since_midnight
+
+ # set end_at to the same offset
+ self.end_at = self.end_at.beginning_of_day + offset
+ end
+
end
View
12 app/views/business_hour_exceptions/_form.html.erb
@@ -0,0 +1,12 @@
+<%= simple_form_for(@business_hour_exception) do |f| %>
+ <%= f.error_notification %>
+
+ <div class="form-inputs">
+ <%= f.association :location %>
+ <%= f.input :date_closed %>
+ </div>
+
+ <div class="form-actions">
+ <%= f.button :submit %>
+ </div>
+<% end %>
View
6 app/views/business_hour_exceptions/edit.html.erb
@@ -0,0 +1,6 @@
+<h1>Editing business_hour_exception</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Show', @business_hour_exception %> |
+<%= link_to 'Back', business_hour_exceptions_path %>
View
25 app/views/business_hour_exceptions/index.html.erb
@@ -0,0 +1,25 @@
+<h1>Listing business_hour_exceptions</h1>
+
+<table>
+ <tr>
+ <th>Location</th>
+ <th>Date closed</th>
+ <th></th>
+ <th></th>
+ <th></th>
+ </tr>
+
+<% @business_hour_exceptions.each do |business_hour_exception| %>
+ <tr>
+ <td><%= business_hour_exception.location %></td>
+ <td><%= business_hour_exception.date_closed %></td>
+ <td><%= link_to 'Show', business_hour_exception %></td>
+ <td><%= link_to 'Edit', edit_business_hour_exception_path(business_hour_exception) %></td>
+ <td><%= link_to 'Destroy', business_hour_exception, confirm: 'Are you sure?', method: :delete %></td>
+ </tr>
+<% end %>
+</table>
+
+<br />
+
+<%= link_to 'New Business hour exception', new_business_hour_exception_path %>
View
5 app/views/business_hour_exceptions/new.html.erb
@@ -0,0 +1,5 @@
+<h1>New business_hour_exception</h1>
+
+<%= render 'form' %>
+
+<%= link_to 'Back', business_hour_exceptions_path %>
View
15 app/views/business_hour_exceptions/show.html.erb
@@ -0,0 +1,15 @@
+<p id="notice"><%= notice %></p>
+
+<p>
+ <b>Location:</b>
+ <%= @business_hour_exception.location %>
+</p>
+
+<p>
+ <b>Date closed:</b>
+ <%= @business_hour_exception.date_closed %>
+</p>
+
+
+<%= link_to 'Edit', edit_business_hour_exception_path(@business_hour_exception) %> |
+<%= link_to 'Back', business_hour_exceptions_path %>
View
2  app/views/business_hours/_form.html.erb
@@ -6,7 +6,7 @@
<% BusinessHour.days.each do |k, v| %>
<div class="form-inputs">
<%= f.input :day %>
- <%= f.input :open, :as => :sf_time_picker %>
+ <%= f.input :open, :as => :simpleform_time_picker %>
<%= f.input :close %>
</div>
View
16 app/views/layouts/application.html.erb
@@ -67,6 +67,22 @@
</div>
<div class="container-fluid">
+
+ <!-- <header class="jumbotron subhead" id="overview"> -->
+ <!-- <h1>Scaffolding</h1> -->
+ <!-- <p class="lead">Bootstrap is built on a responsive 12-column grid. We've also included fixed- and fluid-width layouts based on that system.</p> -->
+ <!-- <div class="subnav subnav-fixed"> -->
+ <!-- <ul class="nav nav-pills"> -->
+ <!-- <li class="active"><a href="#global">Global styles</a></li> -->
+ <!-- <li class=""><a href="#gridSystem">Grid system</a></li> -->
+ <!-- <li class=""><a href="#fluidGridSystem">Fluid grid system</a></li> -->
+ <!-- <li class=""><a href="#gridCustomization">Customizing</a></li> -->
+ <!-- <li class=""><a href="#layouts">Layouts</a></li> -->
+ <!-- <li class=""><a href="#responsive">Responsive design</a></li> -->
+ <!-- </ul> -->
+ <!-- </div> -->
+ <!-- </header> -->
+
<% flash.each do |name, msg| %>
<div class="alert alert-<%= name == :notice ? "success" : "error" %>">
<a class="close" data-dismiss="alert">×</a>
View
1  app/views/models/index.html.erb
@@ -19,6 +19,7 @@
<td><%= model.description %></td>
<td><%= model.parts.count %></td>
<td>
+ <%#= link_to 'Reserve', new_reservation_path(:model_id => model), :class => 'btn btn-mini' if model.checkoutable? %>
<%= link_to 'Reserve', '#', :class => 'btn btn-mini' if model.checkoutable? %>
</td>
</tr>
View
4 app/views/reservations/_form.html.erb
@@ -6,8 +6,8 @@
<%= f.association :client, :disabled => true %>
<%= f.association :kit, :as => :hidden %>
<%= f.association :kit, :disabled => true %>
- <%= f.input :start_at, :as => :string, :input_html => { :class => 'datepicker' } %>
- <%= f.input :end_at, :as => :string, :input_html => { :class => 'datepicker' } %>
+ <%= f.input :start_at, :as => :date_picker, :input_html => { :value => f.object.new_record? ? nil : localize(f.object.start_at, :format => "%Y-%m-%d") } %>
+ <%= f.input :end_at, :as => :date_picker, :input_html => { :value => f.object.new_record? ? nil : localize(f.object.end_at, :format => "%Y-%m-%d") } %>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
View
35 app/views/reservations/show.html.erb
@@ -1,38 +1,43 @@
<h1>Reservation</h1>
<p>
+ <b>Client</b><br>
+ <%= @reservation.client.username %>
+</p>
+
+<p>
+ <b>Check Out Location</b><br>
+ <%= @reservation.kit.location %>
+</p>
+
+<p>
<b>Kit</b><br>
- <%= @reservation.kit_id %>
+ <%= @reservation.kit %>
</p>
<p>
- <b>Start at</b><br>
+ <b>Check Out Day</b><br>
<%= @reservation.start_at %>
</p>
<p>
- <b>End at</b><br>
+ <b>Check In Day</b><br>
<%= @reservation.end_at %>
</p>
<p>
- <b>Out at</b><br>
- <%= @reservation.out_at %>
+ <b>Checked Out At</b><br>
+ <%= @reservation.out_at ||= 'Not checked out yet' %>
</p>
<p>
- <b>In at</b><br>
- <%= @reservation.in_at %>
+ <b>Checked In At</b><br>
+ <%= @reservation.in_at ||= 'Not checked in yet' %>
</p>
<p>
<b>Late</b><br>
- <%= @reservation.late %>
-</p>
-
-<p>
- <b>Client</b><br>
- <%= @reservation.client_id %>
+ <%= @reservation.late ||= false.to_s %>
</p>
<p>
@@ -41,12 +46,12 @@
</p>
<p>
- <b>Out assistant</b><br>
+ <b>Checked Out By</b><br>
<%= @reservation.out_assistant_id %>
</p>
<p>
- <b>In assistant</b><br>
+ <b>Checked In By</b><br>
<%= @reservation.in_assistant_id %>
</p>
View
3  config/application.rb
@@ -27,7 +27,8 @@ class Application < Rails::Application
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
- # config.time_zone = 'Central Time (US & Canada)'
+ # -- NOTE: this will use the local computer's time zone
+ config.time_zone = ActiveSupport::TimeZone[Time.now.utc_offset]
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
View
11 config/routes.rb
@@ -1,5 +1,7 @@
Checkout::Application.routes.draw do
+ resources :business_hour_exceptions
+
root :to => 'models#index'
# devise_for :users, ActiveAdmin::Devise.config
@@ -23,9 +25,7 @@
resources :asset_tags
resources :brands do
- resources :models do
- resources :parts
- end
+ resources :models
end
resources :categories do
resources :models
@@ -34,7 +34,10 @@
resources :reservations, :only => [:index]
end
resources :locations
- resources :models
+ resources :models do
+ resources :parts
+ resources :reservations
+ end
resources :parts
resources :reservations
resource :users do
View
5 db/migrate/20120307071639_create_business_hours.rb
@@ -2,9 +2,8 @@ class CreateBusinessHours < ActiveRecord::Migration
def change
create_table :business_hours do |t|
t.references :location, :null => false
- t.string :day, :null => false
- t.string :open
- t.string :close
+ t.datetime :open_at, :null => false
+ t.datetime :closed_at, :null => false
t.timestamps
end
View
11 db/migrate/20120312235755_create_business_hour_exceptions.rb
@@ -0,0 +1,11 @@
+class CreateBusinessHourExceptions < ActiveRecord::Migration
+ def change
+ create_table :business_hour_exceptions do |t|
+ t.references :location, :null => false
+ t.date :date_closed, :null => false
+
+ t.timestamps
+ end
+ add_index :business_hour_exceptions, :location_id
+ end
+end
View
16 db/schema.rb
@@ -11,7 +11,7 @@
#
# It's strongly recommended to check this file into your version control system.
-ActiveRecord::Schema.define(:version => 20120307155717) do
+ActiveRecord::Schema.define(:version => 20120312235755) do
create_table "active_admin_comments", :force => true do |t|
t.string "resource_id", :null => false
@@ -52,11 +52,19 @@
t.datetime "updated_at", :null => false
end
+ create_table "business_hour_exceptions", :force => true do |t|
+ t.integer "location_id", :null => false
+ t.date "date_closed", :null => false
+ t.datetime "created_at", :null => false
+ t.datetime "updated_at", :null => false
+ end
+
+ add_index "business_hour_exceptions", ["location_id"], :name => "index_business_hour_exceptions_on_location_id"
+
create_table "business_hours", :force => true do |t|
t.integer "location_id", :null => false
- t.string "day", :null => false
- t.string "open"
- t.string "close"
+ t.datetime "open_at", :null => false
+ t.datetime "closed_at", :null => false
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
View
BIN  doc/checkout.graffle
Binary file not shown
View
44 lib/tasks/legacy_migration.rake
@@ -256,5 +256,47 @@ namespace :db do
task :rebuild => ["db:drop", "db:create", "db:migrate"]
desc "drop, create, migrate, dbx2"
- task :repop => ["db:rebuild", "dbx2"]
+ task :repop => ["db:rebuild", "dbx2", "db:seed_dev"]
+
+ desc "loads some fake data, helpful for development"
+ task :seed_dev => :environment do
+
+ User.create!(:username => 'admin', :email => 'admin@example.com', :password => 'password', :password_confirmation => 'password')
+
+ utc_offset = (Time.now.utc_offset / 60 / 60).to_s
+
+ Location.all.each_with_index do |l,idx|
+ if idx % 2 == 0
+ # M, W, F
+ [1, 3, 5].each do |day|
+ # 9:00am
+ open = DateTime.commercial(1969, 1, day, 9, 0, 0, utc_offset)
+ # 5:00pm
+ close = DateTime.commercial(1969, 1, day, 17, 0, 0, utc_offset)
+ l.business_hours << BusinessHour.new(:open_at => open, :closed_at => close)
+ end
+ else
+ # T, Th
+ [2, 4].each do |day|
+ # 11:00am
+ open = DateTime.commercial(1969, 1, day, 11, 0, 0, utc_offset)
+ # 3:00pm
+ close = DateTime.commercial(1969, 1, day, 15, 0, 0, utc_offset)
+ l.business_hours << BusinessHour.new(:open_at => open, :closed_at => close)
+ end
+ end
+ l.save
+ end
+
+ BusinessHour.all.each do |x|
+ open_days = x.open_occurrences
+ open_days.each_with_index do |y, idx|
+ if idx % 5 == 0
+ BusinessHourException.create!(:location => x.location, :date_closed => Date.new(Time.now.year, y.first, y.last))
+ end
+ end
+ end
+
+ end
+
end
View
9 test/fixtures/business_hour_exceptions.yml
@@ -0,0 +1,9 @@
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html
+
+one:
+ location:
+ date_closed: 2012-03-12
+
+two:
+ location:
+ date_closed: 2012-03-12
View
49 test/functional/business_hour_exceptions_controller_test.rb
@@ -0,0 +1,49 @@
+require 'test_helper'
+
+class BusinessHourExceptionsControllerTest < ActionController::TestCase
+ setup do
+ @business_hour_exception = business_hour_exceptions(:one)
+ end
+
+ test "should get index" do
+ get :index
+ assert_response :success
+ assert_not_nil assigns(:business_hour_exceptions)
+ end
+
+ test "should get new" do
+ get :new
+ assert_response :success
+ end
+
+ test "should create business_hour_exception" do
+ assert_difference('BusinessHourException.count') do
+ post :create, business_hour_exception: @business_hour_exception.attributes
+ end
+
+ assert_redirected_to business_hour_exception_path(assigns(:business_hour_exception))
+ end
+
+ test "should show business_hour_exception" do
+ get :show, id: @business_hour_exception
+ assert_response :success
+ end
+
+ test "should get edit" do
+ get :edit, id: @business_hour_exception
+ assert_response :success
+ end
+
+ test "should update business_hour_exception" do
+ put :update, id: @business_hour_exception, business_hour_exception: @business_hour_exception.attributes
+ assert_redirected_to business_hour_exception_path(assigns(:business_hour_exception))
+ end
+
+ test "should destroy business_hour_exception" do
+ assert_difference('BusinessHourException.count', -1) do
+ delete :destroy, id: @business_hour_exception
+ end
+
+ assert_redirected_to business_hour_exceptions_path
+ end
+end
View
7 test/unit/business_hour_exception_test.rb
@@ -0,0 +1,7 @@
+require 'test_helper'
+
+class BusinessHourExceptionTest < ActiveSupport::TestCase
+ # test "the truth" do
+ # assert true
+ # end
+end
View
4 test/unit/helpers/business_hour_exceptions_helper_test.rb
@@ -0,0 +1,4 @@
+require 'test_helper'
+
+class BusinessHourExceptionsHelperTest < ActionView::TestCase
+end
Please sign in to comment.
Something went wrong with that request. Please try again.