bookyt_projects 0.18.2 → 0.18.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,6 @@ class Activity < ActiveRecord::Base
2
2
  # Associations
3
3
  belongs_to :project
4
4
  belongs_to :person
5
- belongs_to :work_day
6
5
  validates :project, :presence => true, :allow_blank => false
7
6
  validates :person, :presence => true, :allow_blank => false
8
7
 
@@ -14,8 +13,6 @@ class Activity < ActiveRecord::Base
14
13
 
15
14
  validates_date :date, :allow_nil => false, :allow_blank => false
16
15
 
17
- before_save :create_work_day
18
-
19
16
  def duration=(value)
20
17
  if value.match(/:/)
21
18
  hours, minutes = value.split(':')
@@ -29,12 +26,12 @@ class Activity < ActiveRecord::Base
29
26
  "%s: %0.2fh" % [project.name, duration]
30
27
  end
31
28
 
32
- private
33
-
34
- def create_work_day
35
- work_day = WorkDay.where(:person_id => person_id, :date => date).first
36
- work_day ||= WorkDay.create(:person_id => person_id, :date => date)
29
+ # Work day
30
+ belongs_to :work_day, :autosave => true
31
+ before_save :update_work_day
37
32
 
38
- self.work_day = work_day
33
+ private
34
+ def update_work_day
35
+ WorkDay.create_or_update_upto(self.person, date)
39
36
  end
40
37
  end
@@ -4,6 +4,7 @@ module BookytProjects
4
4
 
5
5
  included do
6
6
  has_many :activities, :foreign_key => :person_id
7
+ has_many :work_days, :foreign_key => :person_id
7
8
  end
8
9
 
9
10
  module InstanceMethods
@@ -1,27 +1,42 @@
1
1
  class WorkDay < ActiveRecord::Base
2
-
2
+ # Associations
3
3
  belongs_to :person
4
+ validates :person, :presence => true
5
+
4
6
  has_many :activities
5
7
 
6
- before_create :current_daily_workload
8
+ # Order
9
+ default_scope order(:date)
7
10
 
8
- def current_daily_workload
9
- unless person && person.employments.current && person.employments.current.daily_workload
10
- self.daily_workload = 0.0
11
- else
12
- self.daily_workload = person.employments.current(self.date).daily_workload
13
- end
11
+ # Calculations
12
+ default_scope select('work_days.*, hours_worked - hours_due AS overtime')
13
+
14
+ def self.create_or_update(person, date)
15
+ work_day = person.work_days.where(:date => date).first
16
+ work_day ||= person.work_days.build(:date => date)
17
+
18
+ work_day.update_hours
19
+
20
+ work_day.save
21
+ end
22
+
23
+ def update_hours
24
+ self.hours_due = calculate_hours_due
25
+ self.hours_worked = calculate_hours_worked
14
26
  end
15
27
 
16
- def self.create_for_current_employment(employee)
17
- if employee.employments.current
18
- workdays = WorkDay.where(:person_id => employee.id)
19
- start_date = workdays.last.date unless workdays.empty?
20
- start_date ||= employee.employments.current.duration_from
28
+ def self.create_or_update_upto(person, end_date)
29
+ # Guard
30
+ if latest_work_day = person.work_days.last
31
+ start_date = latest_work_day.date
32
+ else
33
+ start_date = end_date
34
+ end
21
35
 
22
- (start_date..Date.today).each do |date|
23
- WorkDay.create(:person => employee, :date => date)
24
- end if workdays.last && (workdays.last.date < start_date)
36
+ (start_date..end_date).each do |date|
37
+ transaction do
38
+ self.create_or_update(person, date)
39
+ end
25
40
  end
26
41
  end
27
42
 
@@ -33,35 +48,34 @@ class WorkDay < ActiveRecord::Base
33
48
  # params:
34
49
  # :employee: Employee to build WorkDay instances for
35
50
  # :range: Date range giving first and last day
36
- def self.for_range(employee, range)
51
+ def self.build_or_update(employee, date)
37
52
  self.create_for_current_employment(employee)
38
-
39
- range.inject([]) do |out, day|
53
+ range.collect do |day|
40
54
  work_day = WorkDay.where(:person_id => employee.id, :date => day).first
41
55
  work_day ||= WorkDay.create(:person => employee, :date => day)
42
- out << work_day
43
-
44
- out
45
56
  end
46
57
  end
47
58
 
48
- # Get WorkDay instances for a month
59
+ # Get employment
49
60
  #
50
- # params:
51
- # :employee: Employee to build WorkDay instances for
52
- # :date_in_month: Any day in the requested month. Uses today by default.
53
- def self.for_month(employee, date_in_month = nil)
54
- # Assume today if no date given
55
- date_in_month ||= Date.today
56
-
57
- start_date = date_in_month.beginning_of_month
58
- end_date = date_in_month.end_of_month
61
+ # Lookup the employment for this day.
62
+ def employment
63
+ person.employments.current(self.date)
64
+ end
59
65
 
60
- self.for_range(employee, start_date..end_date)
66
+ # Get daily workload
67
+ #
68
+ # Lookup daily workload for person. Returns 0.0 if no
69
+ # employment is specified.
70
+ def daily_workload
71
+ employment.try(:daily_workload) || 0.0
61
72
  end
62
73
 
63
74
  # Working hours for this day
64
- def hours_due
75
+ #
76
+ # Saturday and sunday are off, uses daily workload for
77
+ # all other days.
78
+ def calculate_hours_due
65
79
  case date.wday
66
80
  when 6, 0
67
81
  # Saturday and sunday are off
@@ -76,18 +90,12 @@ class WorkDay < ActiveRecord::Base
76
90
  #
77
91
  # Calculates hours worked by summing up duration of all logged
78
92
  # activities.
79
- def hours_worked
80
- activities.where(:date => date).to_a.sum(&:duration)
81
- end
82
-
83
- # Overtime
84
- #
85
- # Simply substract hours_due from hours_worked.
86
- def overtime
87
- hours_worked - hours_due
93
+ def calculate_hours_worked
94
+ activities.where(:date => date).sum('duration')
88
95
  end
89
96
 
97
+ # Calculate accumulated overtime
90
98
  def overall_overtime
91
- WorkDay.where(:person_id => person.id).where('date <= ?', date).to_a.sum(&:overtime)
99
+ WorkDay.where('date <= ?', date).sum('hours_worked - hours_due')
92
100
  end
93
101
  end
@@ -5,9 +5,9 @@
5
5
  %th.number= t_attr :overtime, Activity
6
6
  %th.number= t_attr :overall_overtime, Activity
7
7
 
8
- - overall_overtime = 0
9
- - WorkDay.for_month(@employee).each do |day|
10
- - overall_overtime += day.overtime
8
+ - WorkDay.create_or_update_upto(@employee, Date.today.end_of_month)
9
+ - range = Date.today.beginning_of_month..Date.today.end_of_month
10
+ - @employee.work_days.where(:date => range).each do |day|
11
11
  - tr_params = {:class => work_day_classes(day)}
12
12
  - tr_params.merge!(:rel => 'popover', 'data-content' => h(render 'timesheets/activities_popover', :activities => day.activities), 'data-original-title' => 'Aktivitäten', 'data-html' => 'true') unless day.activities.empty?
13
13
  %tr{tr_params}
@@ -0,0 +1,5 @@
1
+ class AddHoursDueToActivities < ActiveRecord::Migration
2
+ def change
3
+ add_column :activities, :hours_due, :decimal, :precision => 10, :scale => 2
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ class ChangeMaterializedColumnsInWorkDays < ActiveRecord::Migration
2
+ def up
3
+ add_column :work_days, :hours_due, :decimal, :precision => 10, :scale => 2
4
+ add_column :work_days, :hours_worked, :decimal, :precision => 10, :scale => 2
5
+
6
+ remove_column :work_days, :daily_workload
7
+ end
8
+ end
@@ -1,3 +1,3 @@
1
1
  module BookytPos
2
- VERSION = '0.18.2'
2
+ VERSION = '0.18.3'
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bookyt_projects
3
3
  version: !ruby/object:Gem::Version
4
- hash: 83
4
+ hash: 81
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 18
9
- - 2
10
- version: 0.18.2
9
+ - 3
10
+ version: 0.18.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Roman Simecek (CyT)
@@ -145,6 +145,8 @@ files:
145
145
  - db/migrate/20120118131814_create_work_days.rb
146
146
  - db/migrate/20120118140839_add_activities_to_work_day.rb
147
147
  - db/migrate/20120119081136_add_indices_to_activities.rb
148
+ - db/migrate/20120119102801_add_hours_due_to_activities.rb
149
+ - db/migrate/20120119111230_change_materialized_columns_in_work_days.rb
148
150
  - lib/bookyt_projects.rb
149
151
  - lib/bookyt_projects/navigation.rb
150
152
  - lib/bookyt_projects/railtie.rb