artisan-core 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/artisan/activity/activity_interactor.rb +18 -0
- data/lib/artisan/activity/activity_presenter.rb +35 -0
- data/lib/artisan/activity/formatters/diff_changes.rb +41 -0
- data/lib/artisan/activity/formatters/name.rb +22 -0
- data/lib/artisan/activity/formatters/source.rb +16 -0
- data/lib/artisan/activity/formatters/temporal.rb +20 -0
- data/lib/artisan/activity/iteration_auditor.rb +44 -0
- data/lib/artisan/activity/project_auditor.rb +28 -0
- data/lib/artisan/activity/story_auditor.rb +42 -0
- data/lib/artisan/callbacks.rb +27 -0
- data/lib/artisan/crud_strategy.rb +23 -0
- data/lib/artisan/event_mailer.rb +22 -0
- data/lib/artisan/inviter.rb +36 -0
- data/lib/artisan/iterations/iteration_point_calculator.rb +28 -0
- data/lib/artisan/iterations/iteration_presenter.rb +20 -0
- data/lib/artisan/iterations/iteration_workflow_interactor.rb +60 -0
- data/lib/artisan/iterations/iteration_workflow_presenter.rb +11 -0
- data/lib/artisan/iterations/iterations.rb +47 -0
- data/lib/artisan/iterations/iterations_interactor.rb +48 -0
- data/lib/artisan/iterations/move_to_backlog.rb +28 -0
- data/lib/artisan/iterations/story_tags.rb +15 -0
- data/lib/artisan/member.rb +52 -0
- data/lib/artisan/no_op_callbacks.rb +6 -0
- data/lib/artisan/projects/api_key_generator.rb +26 -0
- data/lib/artisan/projects/archive_interactor.rb +29 -0
- data/lib/artisan/projects/completed_stories_presenter.rb +20 -0
- data/lib/artisan/projects/iteration_numberer.rb +15 -0
- data/lib/artisan/projects/project_creator.rb +51 -0
- data/lib/artisan/projects/projects_interactor.rb +58 -0
- data/lib/artisan/projects/projects_presenter.rb +46 -0
- data/lib/artisan/projects/story_point_summer.rb +16 -0
- data/lib/artisan/reports/average_stat_per_iteration_data.rb +55 -0
- data/lib/artisan/reports/burn_up_chart.rb +46 -0
- data/lib/artisan/reports/high_charts_data_retriever.rb +77 -0
- data/lib/artisan/reports/high_charts_interactor.rb +31 -0
- data/lib/artisan/reports/percentage_of_commitments_met_data.rb +47 -0
- data/lib/artisan/reports/signoff/pdf.rb +161 -0
- data/lib/artisan/reports/signoff/report.rb +120 -0
- data/lib/artisan/reports/velocity_report.rb +43 -0
- data/lib/artisan/repository.rb +51 -0
- data/lib/artisan/stories/pert_calculator.rb +62 -0
- data/lib/artisan/stories/stories_interactor.rb +78 -0
- data/lib/artisan/stories/story_collection.rb +66 -0
- data/lib/artisan/stories/story_exporter.rb +45 -0
- data/lib/artisan/stories/story_numberer.rb +15 -0
- data/lib/artisan/stories/story_presenter.rb +23 -0
- data/lib/artisan/stories/story_sorter.rb +37 -0
- data/lib/artisan/story_board.rb +45 -0
- data/lib/artisan/story_column_changer.rb +71 -0
- data/lib/artisan/story_exporter.rb +14 -0
- data/lib/artisan/team.rb +50 -0
- data/spec/crud_strategy_spec.rb +100 -0
- data/spec/event_mailer_spec.rb +86 -0
- data/spec/inviter_spec.rb +58 -0
- data/spec/member_spec.rb +58 -0
- data/spec/repository_spec.rb +32 -0
- data/spec/story_board_spec.rb +36 -0
- data/spec/story_collection_spec.rb +61 -0
- data/spec/story_column_changer_spec.rb +222 -0
- data/spec/story_exporter_spec.rb +25 -0
- data/spec/story_sorter_spec.rb +67 -0
- data/spec/team_spec.rb +107 -0
- metadata +128 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'artisan/repository'
|
2
|
+
require 'artisan/stories/story_collection'
|
3
|
+
|
4
|
+
module Artisan
|
5
|
+
module Projects
|
6
|
+
class ProjectsPresenter
|
7
|
+
|
8
|
+
def initialize(user)
|
9
|
+
@user = user
|
10
|
+
end
|
11
|
+
|
12
|
+
#TODO - PWP - optimize this method to use sql to create the returns rather than ruby
|
13
|
+
def archived
|
14
|
+
read_attributes_to_hash(@user.projects.archived)
|
15
|
+
end
|
16
|
+
|
17
|
+
#TODO - PWP - optimize this method to use sql to create the returns rather than ruby
|
18
|
+
def current
|
19
|
+
read_attributes_to_hash(@user.projects.unarchived)
|
20
|
+
end
|
21
|
+
|
22
|
+
def active_stories_by_project
|
23
|
+
active_stories.group_by(&:project)
|
24
|
+
end
|
25
|
+
|
26
|
+
def active_points
|
27
|
+
Stories::StoryCollection.new(active_stories).estimated_points
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
#TODO - PWP - optimize this method to use sql to create the returns rather than ruby
|
33
|
+
def active_stories
|
34
|
+
Repository.user.active_stories_for(@user).reject { |story| story.project.archived? }
|
35
|
+
end
|
36
|
+
|
37
|
+
def read_attributes_to_hash(scoped_projects)
|
38
|
+
projects = []
|
39
|
+
scoped_projects.each do |project|
|
40
|
+
projects << {:updated_at => project.updated_at, :name => project.name, :id => project.id}
|
41
|
+
end
|
42
|
+
return projects
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "artisan/stories/pert_calculator"
|
2
|
+
module Artisan
|
3
|
+
module Projects
|
4
|
+
class StoryPointSummer
|
5
|
+
|
6
|
+
def initialize(stories)
|
7
|
+
@stories = stories
|
8
|
+
end
|
9
|
+
|
10
|
+
def sum
|
11
|
+
total = @stories.inject(0){ |total, story| total + story.estimate }
|
12
|
+
return total.round(2)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "artisan/iterations/iterations"
|
2
|
+
|
3
|
+
module Artisan
|
4
|
+
module Reports
|
5
|
+
class AverageStatPerIterationData
|
6
|
+
def initialize(project)
|
7
|
+
@project = project
|
8
|
+
end
|
9
|
+
|
10
|
+
def average_of(stat)
|
11
|
+
average(stat)
|
12
|
+
end
|
13
|
+
|
14
|
+
def average_standard_deviation
|
15
|
+
average(:standard_deviation)
|
16
|
+
end
|
17
|
+
|
18
|
+
def average_story_size
|
19
|
+
average(:estimate)
|
20
|
+
end
|
21
|
+
|
22
|
+
def current_iteration?(iteration)
|
23
|
+
Iterations::Iterations.new(@project).current == iteration
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def average(stat_type)
|
29
|
+
@project.iterations.inject([]) do |average_story_size, iteration|
|
30
|
+
average_story_size << accumulate_average_standard_deviation_for(iteration, stat_type).round(2) unless current_iteration?(iteration)
|
31
|
+
average_story_size
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
NONE = 0
|
36
|
+
|
37
|
+
def accumulate_average_standard_deviation_for(iteration, stat_type)
|
38
|
+
if number_of_stories_in(iteration) == NONE
|
39
|
+
NONE
|
40
|
+
else
|
41
|
+
total_standard_deviation_in(iteration, stat_type) / number_of_stories_in(iteration)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def total_standard_deviation_in(iteration, stat_type)
|
46
|
+
iteration.stories.inject(0.0) {| sum, story| sum + story.send(stat_type)}
|
47
|
+
end
|
48
|
+
|
49
|
+
def number_of_stories_in(iteration)
|
50
|
+
iteration.stories.count
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Artisan
|
2
|
+
module Reports
|
3
|
+
|
4
|
+
class BurnUpChart
|
5
|
+
attr_accessor :project
|
6
|
+
def initialize(project)
|
7
|
+
@project = project
|
8
|
+
end
|
9
|
+
|
10
|
+
def project_size date
|
11
|
+
sum_of_stories_by project_query(date)
|
12
|
+
end
|
13
|
+
|
14
|
+
def completed_size date
|
15
|
+
sum_of_stories_by completed_query(date)
|
16
|
+
end
|
17
|
+
|
18
|
+
def project_data
|
19
|
+
accumulate_by(:project_size)
|
20
|
+
end
|
21
|
+
|
22
|
+
def completed_data
|
23
|
+
accumulate_by(:completed_size)
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def accumulate_by(method)
|
29
|
+
Iterations::Iterations.new(@project).by_start_date.inject([]) {|acc, iteration| acc << send(method, iteration.start_date)}
|
30
|
+
end
|
31
|
+
|
32
|
+
def project_query(date)
|
33
|
+
["created_at <= ?", date]
|
34
|
+
end
|
35
|
+
|
36
|
+
def completed_query(date)
|
37
|
+
["created_at <= ? AND complete = ? ", date, true]
|
38
|
+
end
|
39
|
+
|
40
|
+
def sum_of_stories_by conditions
|
41
|
+
stories = @project.stories.find(:all, :conditions => conditions)
|
42
|
+
return stories.inject(0) {|acc, story| acc + story.estimate.to_f}
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Artisan
|
2
|
+
module Reports
|
3
|
+
module HighChartsDataRetriever
|
4
|
+
def self.build_burn_up_chart(project)
|
5
|
+
chart_data = Artisan::Reports::BurnUpChart.new(project)
|
6
|
+
|
7
|
+
LazyHighCharts::HighChart.new do |f|
|
8
|
+
f.chart(:defaultSeriesType => 'line', :backgroundColor => nil, :margin => [0,0,0,0])
|
9
|
+
f.yAxis(:gridLineWidth => nil, :labels => 'none')
|
10
|
+
f.xAxis(:gridLineWidth => nil, :labels => false, :lineColor => 'transparent', :tickLength => nil)
|
11
|
+
f.tooltip(:shadow => false, :backgroundColor => 'rgba(0,0,0,0.7)', :borderWidth => 0, :style => { :color => '#ffffff', :padding => [7,7,7,7], :fontSize => 13 }, :crosshairs => { :color => '#999', :dashStyle => 'solid'})
|
12
|
+
f.title(:text => nil)
|
13
|
+
f.options[:legend][:enabled] = false
|
14
|
+
f.plotOptions(:line => { :lineWidth=> 1, :shadow => false, :marker => { :symbol => 'circle', :radius => 2, :states => { :hover => { :enabled => true, :fillColor => '#000000'} } } })
|
15
|
+
|
16
|
+
f.series(:data => chart_data.project_data.slice(0, chart_data.project_data.length-1), :color => '#b8be43')
|
17
|
+
f.series(:data => chart_data.completed_data.slice(0, chart_data.project_data.length-1), :color => '#800000')
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.build_average_story_size_per_iteration_chart(project)
|
22
|
+
return build_iteration_chart(project, :estimate, '#2B65EC')
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.build_average_standard_deviation_per_iteration_chart(project)
|
26
|
+
return build_iteration_chart(project, :standard_deviation, '#F87217')
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.build_iteration_chart(project, stat, color)
|
30
|
+
chart_data = Artisan::Reports::AverageStatPerIterationData.new(project)
|
31
|
+
|
32
|
+
return LazyHighCharts::HighChart.new do |f|
|
33
|
+
f.chart(:defaultSeriesType => 'line', :backgroundColor => nil, :margin => [0,0,0,0])
|
34
|
+
f.yAxis(:gridLineWidth => nil, :labels => 'none')
|
35
|
+
f.xAxis(:gridLineWidth => nil, :labels => false, :lineColor => 'transparent', :tickLength => nil)
|
36
|
+
f.tooltip(:shadow => false, :backgroundColor => 'rgba(0,0,0,0.7)', :borderWidth => 0, :style => { :color => '#ffffff', :padding => [7,7,7,7], :fontSize => 13 }, :crosshairs => { :color => '#999', :dashStyle => 'solid'})
|
37
|
+
f.title(:text => nil)
|
38
|
+
f.options[:legend][:enabled] = false
|
39
|
+
f.plotOptions(:line => { :lineWidth=> 1, :shadow => false, :marker => { :symbol => 'circle', :radius => 2, :states => { :hover => { :enabled => true, :fillColor => '#000000'} } } })
|
40
|
+
|
41
|
+
f.series(:data => chart_data.average_of(stat), :color => color)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.build_percentage_of_commitments_met_chart(project)
|
46
|
+
chart_data = Artisan::Reports::PercentageOfCommitmentsMetData.new(project)
|
47
|
+
|
48
|
+
LazyHighCharts::HighChart.new do |f|
|
49
|
+
f.options[:chart][:backgroundColor] = 'transparent'
|
50
|
+
f.options[:chart][:defaultSeriesType] = 'pie'
|
51
|
+
f.series(:data=>[{y: go_no_higher_than_100(chart_data.percentage_of_commitments_met), color: 'green'}, {y: go_no_lower_than_0(chart_data.percentage_of_commitments_not_met), color: '#CCC'}], :innerSize => '65%')
|
52
|
+
f.tooltip(:enabled => false)
|
53
|
+
f.title(:text => '')
|
54
|
+
f.plotOptions(:series => {:stacking => true, :shadow => false, :dataLabels => { :enabled => false }})
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.percentage_of_commitments_met(project)
|
59
|
+
chart_data = Artisan::Reports::PercentageOfCommitmentsMetData.new(project)
|
60
|
+
chart_data.percentage_of_commitments_met.to_i
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.go_no_higher_than_100(number)
|
64
|
+
return 0 if number.nil?
|
65
|
+
number > 100 ? 100 : number
|
66
|
+
end
|
67
|
+
|
68
|
+
def self.go_no_lower_than_0(number)
|
69
|
+
return 0 if number.nil?
|
70
|
+
number < 0 ? 0 : number
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Artisan
|
2
|
+
module Reports
|
3
|
+
class HighChartsInteractor
|
4
|
+
attr_reader :project
|
5
|
+
|
6
|
+
def initialize(project)
|
7
|
+
@project = project
|
8
|
+
end
|
9
|
+
|
10
|
+
def burn_up_chart
|
11
|
+
Artisan::Reports::HighChartsDataRetriever.build_burn_up_chart(@project)
|
12
|
+
end
|
13
|
+
|
14
|
+
def average_story_size_per_iteration_chart
|
15
|
+
Artisan::Reports::HighChartsDataRetriever.build_average_story_size_per_iteration_chart(@project)
|
16
|
+
end
|
17
|
+
|
18
|
+
def average_standard_deviation_per_iteration_chart
|
19
|
+
Artisan::Reports::HighChartsDataRetriever.build_average_standard_deviation_per_iteration_chart(@project)
|
20
|
+
end
|
21
|
+
|
22
|
+
def percentage_of_commitments_met_chart
|
23
|
+
Artisan::Reports::HighChartsDataRetriever.build_percentage_of_commitments_met_chart(@project)
|
24
|
+
end
|
25
|
+
|
26
|
+
def percentage_of_commitments_met
|
27
|
+
Artisan::Reports::HighChartsDataRetriever.percentage_of_commitments_met(@project)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "artisan/iterations/iterations"
|
2
|
+
|
3
|
+
module Artisan
|
4
|
+
module Reports
|
5
|
+
class PercentageOfCommitmentsMetData
|
6
|
+
def initialize(project)
|
7
|
+
@project = project
|
8
|
+
end
|
9
|
+
|
10
|
+
def percentages_of_commitments_met
|
11
|
+
@project.iterations.reverse.inject([]) do |percentages_of_commitments_met, iteration|
|
12
|
+
percentages_of_commitments_met << accumulate_percentage_of_commitments_met_for(iteration) unless current_iteration?(iteration)
|
13
|
+
percentages_of_commitments_met
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def percentage_of_commitments_met
|
18
|
+
unless percentages_of_commitments_met.compact.count == 0
|
19
|
+
((percentages_of_commitments_met.compact.inject(0, :+) / percentages_of_commitments_met.compact.count) * 100).round
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def percentage_of_commitments_not_met
|
24
|
+
100 - percentage_of_commitments_met unless percentage_of_commitments_met.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
def current_iteration?(iteration)
|
28
|
+
Iterations::Iterations.new(@project.id).current == iteration
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def accumulate_percentage_of_commitments_met_for(iteration)
|
34
|
+
if iteration.committed_points == 0 || iteration.committed_points.nil?
|
35
|
+
nil
|
36
|
+
else
|
37
|
+
total_billed_points_for(iteration) / iteration.committed_points
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def total_billed_points_for(iteration)
|
42
|
+
stories = iteration.stories.select { |story| story.complete? && !story.nonbillable? && story.estimate }
|
43
|
+
stories.inject(0.0) {|sum, story| sum + story.estimate}
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'prawn'
|
2
|
+
require 'reports_helper'
|
3
|
+
|
4
|
+
module Signoff
|
5
|
+
class Pdf
|
6
|
+
def initialize(report)
|
7
|
+
@report = report
|
8
|
+
end
|
9
|
+
|
10
|
+
def render
|
11
|
+
to_document.render
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_document
|
15
|
+
@document = Prawn::Document.new
|
16
|
+
fonts
|
17
|
+
header
|
18
|
+
project_title
|
19
|
+
iteration_information
|
20
|
+
tables
|
21
|
+
committed_total
|
22
|
+
signature_box
|
23
|
+
@document
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def fonts
|
29
|
+
types_dir = Rails.root.join('public', 'types')
|
30
|
+
|
31
|
+
@document.font_families.update("ArvoRegular" => {
|
32
|
+
:normal => types_dir.join("Arvo-Regular-webfont.ttf").to_s,
|
33
|
+
:bold => types_dir.join("Arvo-Bold.ttf").to_s
|
34
|
+
})
|
35
|
+
@document.font_families.update("FrescoPlus" => {
|
36
|
+
:normal => types_dir.join("FrescoPlus-Normal.ttf").to_s,
|
37
|
+
:italic => types_dir.join("FrescoPlus-NormalItalic.ttf").to_s,
|
38
|
+
:bold => types_dir.join("FrescoPlus-Bold.ttf").to_s
|
39
|
+
})
|
40
|
+
@document.font_families.update("FrescoSansPlus" => {
|
41
|
+
:normal => types_dir.join("FrescoSansPlus-Normal.ttf").to_s,
|
42
|
+
:bold => types_dir.join("FrescoSansPlus-Bold.ttf").to_s
|
43
|
+
})
|
44
|
+
end
|
45
|
+
|
46
|
+
def header
|
47
|
+
header_height_1 = 88
|
48
|
+
|
49
|
+
@document.repeat :all do
|
50
|
+
@document.bounding_box( [0, 720], height: header_height_1, width: 540/2) do
|
51
|
+
@document.image Rails.root.join('public', 'images', 'sign_off_8th_light_black.jpg').to_s, :height => 50 , :width => 93.75, :at => [30, 76]
|
52
|
+
end
|
53
|
+
|
54
|
+
@document.bounding_box([(540/2)-30, 710], width: 540/2, height: header_height_1) do
|
55
|
+
@document.text "<font name='FrescoSansPlus' size='14'><b><color rgb='32a5f5'>8th</color> Light, Inc.</b></font>",
|
56
|
+
{
|
57
|
+
align: :right,
|
58
|
+
inline_format: true,
|
59
|
+
kerning: true,
|
60
|
+
leading: 12
|
61
|
+
}
|
62
|
+
|
63
|
+
@document.text "<font name='FrescoPlus' size='11'>" +
|
64
|
+
"1232 American Way" +
|
65
|
+
"\nLibertyville, IL 60048" +
|
66
|
+
"\n<i>tel</i> 877-407-4154" +
|
67
|
+
"\n<i>fax</i> 847-573-1748" +
|
68
|
+
"</font>",
|
69
|
+
{
|
70
|
+
align: :right,
|
71
|
+
inline_format: true,
|
72
|
+
kerning: true,
|
73
|
+
leading: 2
|
74
|
+
}
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def project_title
|
80
|
+
@document.fill_color = "3A66A7"
|
81
|
+
@document.font_size = 20
|
82
|
+
@document.text "Feature Set for #{@report.project_name}"
|
83
|
+
end
|
84
|
+
|
85
|
+
def iteration_information
|
86
|
+
@document.move_down @document.font.height
|
87
|
+
@document.font_size = 13
|
88
|
+
@document.fill_color = "000000"
|
89
|
+
@document.formatted_text [
|
90
|
+
{ :text => " #{@report.iteration_name} ", :styles => [:bold] },
|
91
|
+
{ :text => " from "},
|
92
|
+
{ :text => " #{@report.start_date.strftime("%m/%d/%Y")} ", :styles => [:bold] },
|
93
|
+
{ :text => " to "},
|
94
|
+
{ :text => " #{@report.finish_date.strftime("%m/%d/%Y")} ", :styles => [:bold] } ]
|
95
|
+
@document.move_down @document.font.height
|
96
|
+
@document.formatted_text [
|
97
|
+
{ :text => "Team Members: ", :styles => [:bold] },
|
98
|
+
{ :text => "#{@report.team_member_names}"} ]
|
99
|
+
@document.move_down @document.font.height
|
100
|
+
end
|
101
|
+
|
102
|
+
def tables
|
103
|
+
@report.tables.each do |table|
|
104
|
+
adjusted_table_data = @report.table_data[table.downcase]
|
105
|
+
@document.text table
|
106
|
+
@document.transparent(0.8) do
|
107
|
+
@document.table([@report.column_titles], :row_colors => ['bbbbbb'],
|
108
|
+
:column_widths => [60, 280, 100],
|
109
|
+
:cell_style => {:align => :center, :font_style => :bold} )
|
110
|
+
end
|
111
|
+
while !adjusted_table_data.empty? do
|
112
|
+
current_table = adjusted_table_data.slice!(0...1)
|
113
|
+
if start_new_page?(@document.cursor, 50)
|
114
|
+
@document.start_new_page
|
115
|
+
@document.move_down 120
|
116
|
+
@document.transparent(0.8) do
|
117
|
+
@document.table([@report.column_titles], :row_colors => ['bbbbbb'],
|
118
|
+
:column_widths => [60, 280, 100],
|
119
|
+
:cell_style => {:align => :center, :font_style => :bold} )
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
@document.table(current_table,
|
124
|
+
:column_widths => @report.column_widths,
|
125
|
+
:cell_style => {:align => :center}) do |table|
|
126
|
+
table.columns(1).align = :left
|
127
|
+
if adjusted_table_data.empty?
|
128
|
+
table.rows(table.row_length-1).style(:background_color => 'bbbbbb', :font_style => :bold)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
@document.move_down @document.font.height*2 if @document.cursor < 580
|
133
|
+
|
134
|
+
if start_new_page?(@document.cursor, 100)
|
135
|
+
@document.start_new_page
|
136
|
+
@document.move_down 120
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
def committed_total
|
142
|
+
@document.formatted_text [
|
143
|
+
{ :text => "Completed Points / Committed Points: ", :styles => [:bold] },
|
144
|
+
{ :text => "#{@report.total_billed_points} / #{@report.committed_points_at_completion} "} ]
|
145
|
+
end
|
146
|
+
|
147
|
+
def signature_box
|
148
|
+
@document.font "Helvetica"
|
149
|
+
@document.font_size = 10
|
150
|
+
@document.draw_text "__________________________________________", :at => [0, @document.font.height*4.5+5]
|
151
|
+
@document.draw_text "Print Name", :at => [0, @document.font.height*3.5+5]
|
152
|
+
@document.draw_text "__________________________________________ ________________________", :at => [0, @document.font.height+5]
|
153
|
+
@document.draw_text "Signature", :at => [0, 5]
|
154
|
+
@document.draw_text "Date", :at => [265, 5]
|
155
|
+
end
|
156
|
+
|
157
|
+
def start_new_page?(cursor, height)
|
158
|
+
cursor < height
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|