when end date is specified, data for the corresponding reporting period is now always included (:live_data may not be specified anymore in combination with :end_date) (closes #1) - reportable - Fork of reportable required by WarVox, from hdm/reportable.
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
       ---
 (DIR) commit 929610c2345e54b6f1740f0f2e545440d9c2d3a4
 (DIR) parent ca12152ec76255deacf609fed517a71f7901013b
 (HTM) Author: Marco Otte-Witte <marco.otte-witte@simplabs.com>
       Date:   Wed, 29 Apr 2009 18:32:17 +0200
       
       when end date is specified, data for the corresponding reporting period is now always included (:live_data may not be specified anymore in combination with :end_date) (closes #1)
       
       Diffstat:
         M lib/simplabs/reports_as_sparkline/… |       3 ++-
         M lib/simplabs/reports_as_sparkline/… |      10 +++++-----
         M lib/simplabs/reports_as_sparkline/… |      16 +++++++++++++++-
         M spec/classes/report_cache_spec.rb   |       2 +-
         M spec/classes/report_spec.rb         |      94 ++++++++++++++++++++++++++-----
         M spec/classes/reporting_period_spec… |      62 ++++++++++++++++++++++++++++---
       
       6 files changed, 159 insertions(+), 28 deletions(-)
       ---
 (DIR) diff --git a/lib/simplabs/reports_as_sparkline/report.rb b/lib/simplabs/reports_as_sparkline/report.rb
       @@ -108,7 +108,8 @@ module Simplabs #:nodoc:
                  raise ArgumentError.new('Options :live_data and :end_date may not both be specified!') if options[:live_data] && options[:end_date]
                  raise ArgumentError.new("Invalid grouping #{options[:grouping]}!") if options[:grouping] && ![:hour, :day, :week, :month].include?(options[:grouping])
                  raise ArgumentError.new("Invalid conditions: #{options[:conditions].inspect}!") if options[:conditions] && !options[:conditions].is_a?(Array) && !options[:conditions].is_a?(Hash)
       -          raise ArgumentError.new("Invalid end date: #{options[:end_date].inspect}; must be a DateTime!") if options[:end_date] && !options[:end_date].is_a?(DateTime)
       +          raise ArgumentError.new("Invalid end date: #{options[:end_date].inspect}; must be a DateTime!") if options[:end_date] && !options[:end_date].is_a?(DateTime) && !options[:end_date].is_a?(Time)
       +          raise ArgumentError.new('End date may not be in the future!') if options[:end_date] && options[:end_date] > DateTime.now
                end
        
            end
 (DIR) diff --git a/lib/simplabs/reports_as_sparkline/report_cache.rb b/lib/simplabs/reports_as_sparkline/report_cache.rb
       @@ -10,7 +10,7 @@ module Simplabs #:nodoc:
                raise ArgumentError.new('A block must be given') unless block_given?
                self.transaction do
                  cached_data = []
       -          first_reporting_period = ReportingPeriod.first(options[:grouping], options[:limit], options[:end_date])
       +          first_reporting_period = ReportingPeriod.first(options[:grouping], (options[:end_date] ? options[:limit] - 1 : options[:limit]), options[:end_date])
                  last_reporting_period = options[:end_date] ? ReportingPeriod.new(options[:grouping], options[:end_date]) : nil
        
                  if cache
       @@ -22,7 +22,7 @@ module Simplabs #:nodoc:
                  new_data = if !options[:live_data] && last_cached_reporting_period == ReportingPeriod.new(options[:grouping]).previous
                    []
                  else
       -            end_date = options[:live_data] ? nil : last_reporting_period && last_reporting_period.date_time
       +            end_date = options[:live_data] ? nil : (options[:end_date] ? last_reporting_period.last_date_time : nil)
                    yield((last_cached_reporting_period.next rescue first_reporting_period).date_time, end_date)
                  end
        
       @@ -35,9 +35,9 @@ module Simplabs #:nodoc:
                def self.prepare_result(new_data, cached_data, report, options, cache = true)
                  new_data = new_data.map { |data| [ReportingPeriod.from_db_string(options[:grouping], data[0]), data[1]] }
                  result = cached_data.map { |cached| [cached.reporting_period, cached.value] }
       -          last_reporting_period = ReportingPeriod.new(options[:grouping], options[:end_date])
       -          reporting_period = cached_data.empty? ? ReportingPeriod.first(options[:grouping], options[:limit], options[:end_date]) : ReportingPeriod.new(options[:grouping], cached_data.last.reporting_period).next
       -          while reporting_period < last_reporting_period
       +          last_reporting_period = ReportingPeriod.new(options[:grouping])
       +          reporting_period = cached_data.empty? ? ReportingPeriod.first(options[:grouping], (options[:end_date] ? options[:limit] - 1 : options[:limit]), options[:end_date]) : ReportingPeriod.new(options[:grouping], cached_data.last.reporting_period).next
       +          while reporting_period < (options[:end_date] ? ReportingPeriod.new(options[:grouping], options[:end_date]).next : last_reporting_period)
                    cached = build_cached_data(report, options[:grouping], options[:limit], reporting_period, find_value(new_data, reporting_period))
                    cached.save! if cache
                    result << [reporting_period.date_time, cached.value]
 (DIR) diff --git a/lib/simplabs/reports_as_sparkline/reporting_period.rb b/lib/simplabs/reports_as_sparkline/reporting_period.rb
       @@ -71,10 +71,24 @@ module Simplabs #:nodoc:
                raise ArgumentError.new("Can only compare instances of #{Simplabs::ReportsAsSparkline::ReportingPeriod.klass}")
              end
        
       +      def last_date_time #:nodoc:
       +        case @grouping.identifier
       +          when :hour
       +            DateTime.new(@date_time.year, @date_time.month, @date_time.day, @date_time.hour, 59, 59)
       +          when :day
       +            DateTime.new(@date_time.year, @date_time.month, @date_time.day, 23, 59, 59)
       +          when :week
       +            date_time = (@date_time - @date_time.wday.days) + 7.days
       +            Date.new(date_time.year, date_time.month, date_time.day)
       +          when :month
       +            Date.new(@date_time.year, @date_time.month, (Date.new(@date_time.year, 12, 31) << (12 - @date_time.month)).day)
       +        end
       +      end
       +
              private
        
                def parse_date_time(date_time)
       -          return case @grouping.identifier
       +          case @grouping.identifier
                    when :hour
                      DateTime.new(date_time.year, date_time.month, date_time.day, date_time.hour)
                    when :day
 (DIR) diff --git a/spec/classes/report_cache_spec.rb b/spec/classes/report_cache_spec.rb
       @@ -120,7 +120,7 @@ describe Simplabs::ReportsAsSparkline::ReportCache do
                  @report.options[:grouping].identifier.to_s,
                  @report.aggregation.to_s,
                  10,
       -          Simplabs::ReportsAsSparkline::ReportingPeriod.first(@report.options[:grouping], 10).date_time,
       +          Simplabs::ReportsAsSparkline::ReportingPeriod.first(@report.options[:grouping], 9).date_time,
                  Simplabs::ReportsAsSparkline::ReportingPeriod.new(@report.options[:grouping], end_date).date_time
                ],
                :limit => 10,
 (DIR) diff --git a/spec/classes/report_spec.rb b/spec/classes/report_spec.rb
       @@ -70,26 +70,53 @@ describe Simplabs::ReportsAsSparkline::Report do
        
            for grouping in [:hour, :day, :week, :month] do
        
       -      describe "for grouping #{grouping.to_s}" do
       +      describe "for grouping :#{grouping.to_s}" do
        
       -        [true, false].each do |live_data|
       +        before(:all) do
       +          User.create!(:login => 'test 1', :created_at => Time.now,                    :profile_visits => 2)
       +          User.create!(:login => 'test 2', :created_at => Time.now - 1.send(grouping), :profile_visits => 1)
       +          User.create!(:login => 'test 3', :created_at => Time.now - 3.send(grouping), :profile_visits => 2)
       +          User.create!(:login => 'test 4', :created_at => Time.now - 3.send(grouping), :profile_visits => 3)
       +        end
        
       -          describe "with :live_data = #{live_data}" do
       +        describe 'when :end_date is specified' do
       +
       +          describe 'the returned result' do
       +
       +            before do
       +              @end_date = DateTime.now - 1.send(grouping)
       +              @grouping = Simplabs::ReportsAsSparkline::Grouping.new(grouping)
       +              @report = Simplabs::ReportsAsSparkline::Report.new(User, :registrations,
       +                :grouping => grouping,
       +                :limit    => 10,
       +                :end_date => @end_date
       +              )
       +              @result = @report.run
       +            end
        
       -            before(:all) do
       -              User.create!(:login => 'test 1', :created_at => Time.now,                    :profile_visits => 2)
       -              User.create!(:login => 'test 2', :created_at => Time.now - 1.send(grouping), :profile_visits => 1)
       -              User.create!(:login => 'test 3', :created_at => Time.now - 3.send(grouping), :profile_visits => 2)
       -              User.create!(:login => 'test 4', :created_at => Time.now - 3.send(grouping), :profile_visits => 3)
       +            it "should start with the reporting period (end_date - limit.#{grouping.to_s})" do
       +              @result.first[0].should == Simplabs::ReportsAsSparkline::ReportingPeriod.new(@grouping, @end_date - 9.send(grouping)).date_time
                    end
        
       +            it "should end with the reporting period of the specified end date" do
       +              @result.last[0].should == Simplabs::ReportsAsSparkline::ReportingPeriod.new(@grouping, @end_date).date_time
       +            end
       +
       +          end
       +
       +        end
       +
       +        [true, false].each do |live_data|
       +
       +          describe "with :live_data = #{live_data}" do
       +
                    describe 'the returned result' do
        
                      before do
                        @grouping = Simplabs::ReportsAsSparkline::Grouping.new(grouping)
                        @report = Simplabs::ReportsAsSparkline::Report.new(User, :registrations,
       -                  :grouping => grouping,
       -                  :limit => 10,
       +                  :grouping  => grouping,
       +                  :limit     => 10,
                          :live_data => live_data
                        )
                        @result = @report.run
       @@ -228,7 +255,7 @@ describe Simplabs::ReportsAsSparkline::Report do
                      result[6][1].should  == 0.0
                    end
        
       -            it 'should return correct results when run twice with different limits' do
       +            it 'should return correct results when run twice in a row with a higher limit on the second run' do
                      @report = Simplabs::ReportsAsSparkline::Report.new(User, :registrations,
                        :aggregation => :count,
                        :grouping    => grouping,
       @@ -250,14 +277,49 @@ describe Simplabs::ReportsAsSparkline::Report do
                      result[6][1].should  == 0.0
                    end
        
       -          end
       +            unless live_data
       +
       +              it 'should return correct data for aggregation :count when :end_date is specified' do
       +                @report = Simplabs::ReportsAsSparkline::Report.new(User, :registrations,
       +                  :aggregation => :count,
       +                  :grouping    => grouping,
       +                  :limit       => 10,
       +                  :end_date    => Time.now - 3.send(grouping)
       +                )
       +                result = @report.run.to_a
       +
       +                result[9][1].should  == 2.0
       +                result[8][1].should  == 0.0
       +                result[7][1].should  == 0.0
       +                result[6][1].should  == 0.0
       +              end
       +
       +              it 'should return correct data for aggregation :sum when :end_date is specified' do
       +                @report = Simplabs::ReportsAsSparkline::Report.new(User, :registrations,
       +                  :aggregation  => :sum,
       +                  :grouping     => grouping,
       +                  :value_column => :profile_visits,
       +                  :limit        => 10,
       +                  :end_date     => Time.now - 3.send(grouping)
       +                )
       +                result = @report.run.to_a
       +
       +                result[9][1].should  == 5.0
       +                result[8][1].should  == 0.0
       +                result[7][1].should  == 0.0
       +                result[6][1].should  == 0.0
       +              end
       +
       +            end
        
       -          after(:all) do
       -            User.destroy_all
                  end
        
                end
        
       +        after(:all) do
       +          User.destroy_all
       +        end
       +
              end
        
            end
       @@ -425,6 +487,10 @@ describe Simplabs::ReportsAsSparkline::Report do
              lambda { @report.send(:ensure_valid_options, { :end_date => 'today' }) }.should raise_error(ArgumentError)
            end
        
       +    it 'should raise an error if an end date is specified that is in the future' do
       +      lambda { @report.send(:ensure_valid_options, { :end_date => (DateTime.now + 1.month) }) }.should raise_error(ArgumentError)
       +    end
       +
            it 'should raise an error if both an end date and :live_data = true are specified' do
              lambda { @report.send(:ensure_valid_options, { :end_date => DateTime.now, :live_data => true }) }.should raise_error(ArgumentError)
            end
 (DIR) diff --git a/spec/classes/reporting_period_spec.rb b/spec/classes/reporting_period_spec.rb
       @@ -28,24 +28,24 @@ describe Simplabs::ReportsAsSparkline::ReportingPeriod do
              end
        
              it 'should return the date of the monday of the week date_time is in when the specified date is a monday already' do
       -        date_time = DateTime.new(2008, 11, 24) #this is a monday already, should not change
       +        date_time = DateTime.new(2008, 11, 24)
                reporting_period = Simplabs::ReportsAsSparkline::ReportingPeriod.new(Simplabs::ReportsAsSparkline::Grouping.new(:week), date_time)
        
       -        reporting_period.date_time.should == Date.new(date_time.year, date_time.month, 24) # expect to get monday 24th again
       +        reporting_period.date_time.should == Date.new(date_time.year, date_time.month, 24)
              end
        
              it 'should return the date of the monday of the week date_time is in when the monday is in a different month than the specified date' do
       -        date_time = DateTime.new(2008, 11, 1) #this is a saturday
       +        date_time = DateTime.new(2008, 11, 1)
                reporting_period = Simplabs::ReportsAsSparkline::ReportingPeriod.new(Simplabs::ReportsAsSparkline::Grouping.new(:week), date_time)
        
       -        reporting_period.date_time.should == Date.new(2008, 10, 27) # expect to get the monday before the 1st, which is in october
       +        reporting_period.date_time.should == Date.new(2008, 10, 27)
              end
        
              it 'should return the date of the monday of the week date_time is in when the monday is in a different year than the specified date' do
       -        date_time = DateTime.new(2009, 1, 1) #this is a thursday
       +        date_time = DateTime.new(2009, 1, 1)
                reporting_period = Simplabs::ReportsAsSparkline::ReportingPeriod.new(Simplabs::ReportsAsSparkline::Grouping.new(:week), date_time)
        
       -        reporting_period.date_time.should == Date.new(2008, 12, 29) # expect to get the monday before the 1st, which is in december 2008
       +        reporting_period.date_time.should == Date.new(2008, 12, 29)
              end
        
            end
       @@ -59,6 +59,56 @@ describe Simplabs::ReportsAsSparkline::ReportingPeriod do
        
          end
        
       +  describe '#last_date_time' do
       +
       +    it 'should return the date and time with minutes = seconds = 59 for grouping :hour' do
       +      date_time = DateTime.now
       +      reporting_period = Simplabs::ReportsAsSparkline::ReportingPeriod.new(Simplabs::ReportsAsSparkline::Grouping.new(:hour), date_time)
       +
       +      reporting_period.last_date_time.should == DateTime.new(date_time.year, date_time.month, date_time.day, date_time.hour, 59, 59)
       +    end
       +
       +    it 'should return the date part with hour = 23 and minute = seconds = 59 for grouping :day' do
       +      date_time = DateTime.now
       +      reporting_period = Simplabs::ReportsAsSparkline::ReportingPeriod.new(Simplabs::ReportsAsSparkline::Grouping.new(:day), date_time)
       +
       +      reporting_period.last_date_time.should == DateTime.new(date_time.year, date_time.month, date_time.day, 23, 59, 59)
       +    end
       +
       +    describe 'for grouping :week' do
       +
       +      it 'should return the date of the sunday of the week date_time is in for any day in that week' do
       +        date_time = DateTime.new(2008, 11, 27)
       +        reporting_period = Simplabs::ReportsAsSparkline::ReportingPeriod.new(Simplabs::ReportsAsSparkline::Grouping.new(:week), date_time)
       +
       +        reporting_period.last_date_time.should == Date.new(date_time.year, date_time.month, 30)
       +      end
       +
       +      it 'should return the date of the sunday of the week date_time is in when the sunday is in a different month than the specified date' do
       +        date_time = DateTime.new(2008, 10, 30)
       +        reporting_period = Simplabs::ReportsAsSparkline::ReportingPeriod.new(Simplabs::ReportsAsSparkline::Grouping.new(:week), date_time)
       +
       +        reporting_period.last_date_time.should == Date.new(2008, 11, 2)
       +      end
       +
       +      it 'should return the date of the sunday of the week date_time is in when the sunday is in a different year than the specified date' do
       +        date_time = DateTime.new(2008, 12, 29)
       +        reporting_period = Simplabs::ReportsAsSparkline::ReportingPeriod.new(Simplabs::ReportsAsSparkline::Grouping.new(:week), date_time)
       +
       +        reporting_period.last_date_time.should == Date.new(2009, 1, 4)
       +      end
       +
       +    end
       +
       +    it 'should return the date of the last day of the month for grouping :month' do
       +      date_time = DateTime.new(2009, 4, 29)
       +      reporting_period = Simplabs::ReportsAsSparkline::ReportingPeriod.new(Simplabs::ReportsAsSparkline::Grouping.new(:month), date_time)
       +
       +      reporting_period.last_date_time.should == Date.new(date_time.year, date_time.month, 30)
       +    end
       +
       +  end
       +
          describe '.from_db_string' do
        
            it 'should return a reporting period with the correct date and time and with minutes = seconds = 0 for grouping :hour' do