prawn_report 1.9.18

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/app/controllers/ac_filter_defs_controller.rb +17 -0
  3. data/app/controllers/custom_generate_report_controller.rb +18 -0
  4. data/app/controllers/generate_report_controller.rb +24 -0
  5. data/app/controllers/report_templates_controller.rb +40 -0
  6. data/app/models/ac_filter.rb +15 -0
  7. data/app/models/ac_filter_def.rb +38 -0
  8. data/app/models/ac_filter_option.rb +5 -0
  9. data/app/models/report_template.rb +22 -0
  10. data/lib/ac_filters_utils.rb +187 -0
  11. data/lib/active_record_helpers.rb +218 -0
  12. data/lib/bands/band.rb +23 -0
  13. data/lib/bands/footer_band.rb +7 -0
  14. data/lib/bands/header_band.rb +9 -0
  15. data/lib/bands/summary_band.rb +7 -0
  16. data/lib/custom_report_controller.rb +48 -0
  17. data/lib/generators/prawn_report/install/install_generator.rb +16 -0
  18. data/lib/generators/prawn_report/install/templates/20120108210141_create_prawn_report_catalogs.rb +14 -0
  19. data/lib/generators/prawn_report/install/templates/20120124012653_add_filter_defs.rb +35 -0
  20. data/lib/generators/prawn_report/install/templates/20120209231821_add_filters_to_reports.rb +13 -0
  21. data/lib/generators/prawn_report/install/templates/20120222021437_add_order_to_filter_def.rb +9 -0
  22. data/lib/generators/prawn_report/install/templates/20120222025632_add_select_sql.rb +9 -0
  23. data/lib/generators/prawn_report/install/templates/20120222030526_create_ac_filter_joins.rb +12 -0
  24. data/lib/generators/prawn_report/install/templates/20120222122507_add_serialization_params_to_report.rb +9 -0
  25. data/lib/generators/prawn_report/install/templates/20120222134101_create_ac_filter_includes.rb +12 -0
  26. data/lib/generators/prawn_report/install/templates/20120222150029_change_includes_and_joins_to_hash.rb +21 -0
  27. data/lib/generators/prawn_report/install/templates/20120229134810_add_group_to_filter_def.rb +9 -0
  28. data/lib/generators/prawn_report/install/templates/20120229194434_add_system_criteria_to_ac_filter.rb +9 -0
  29. data/lib/generators/prawn_report/install/templates/20120301063031_change_select_sql.rb +11 -0
  30. data/lib/generators/prawn_report/install/templates/20120303104431_change_filled_criteria_unfilled_criteria.rb +15 -0
  31. data/lib/generators/prawn_report/install/templates/20120316162712_add_filled_criteria_to_options.rb +9 -0
  32. data/lib/generators/prawn_report/install/templates/20120323124446_add_fields_to_filter.rb +17 -0
  33. data/lib/generators/prawn_report/install/templates/20130122101313_add_sql_query_to_ac_filter_def.rb +5 -0
  34. data/lib/generators/prawn_report/install/templates/20131107172133_add_excluir_to_report_template.rb +9 -0
  35. data/lib/prawn_report.rb +21 -0
  36. data/lib/prawn_report/engine.rb +9 -0
  37. data/lib/prawn_report/version.rb +3 -0
  38. data/lib/prawn_report_seeds.rb +46 -0
  39. data/lib/report.rb +190 -0
  40. data/lib/report_helpers.rb +82 -0
  41. data/lib/report_info.rb +27 -0
  42. data/repo/bands/footers/footer_001.rb +20 -0
  43. data/repo/bands/headers/header_001.rb +61 -0
  44. data/repo/bands/headers/header_002.rb +31 -0
  45. data/repo/reports/column_group.rb +58 -0
  46. data/repo/reports/listing.rb +144 -0
  47. data/repo/reports/simple_listing.rb +130 -0
  48. metadata +93 -0
@@ -0,0 +1,190 @@
1
+ #coding: utf-8
2
+
3
+ require 'prawn'
4
+
5
+ require File.expand_path(File.dirname(__FILE__) + "/report_helpers")
6
+ require File.expand_path(File.dirname(__FILE__) + "/report_info")
7
+
8
+ # This is the module for all classes in the prawn_report gem
9
+ module PrawnReport
10
+ unless defined? DEFAULT_REPORT_PARAMS
11
+ DEFAULT_REPORT_PARAMS = {:page_size => 'A4', :margin => [20, 20, 20, 20],
12
+ :page_layout => :portrait}
13
+
14
+ LABEL_SIZE = 6
15
+ TEXT_SIZE = 10
16
+
17
+ SECTION_SPACING = LABEL_SIZE + 4
18
+
19
+ LINE_WIDTH = 0.3
20
+
21
+ DEFAULT_FONT = 'Times-Roman'
22
+
23
+ TEXT_BOX_RADIUS = 2
24
+ TEXT_BOX_HEIGTH = 20
25
+ end
26
+
27
+ # Report is the base class for all reports, it encapsulates all logic for rendering
28
+ # report parts.
29
+ class Report
30
+ attr_reader :pdf, :data, :max_width, :max_height, :totals, :group_totals
31
+ attr_accessor :header_class, :header_other_pages_class, :x, :report_params,
32
+ :running_totals
33
+
34
+ def initialize(report_params)
35
+ @report_params = DEFAULT_REPORT_PARAMS.merge(report_params || {})
36
+ @running_totals = @report_params.delete(:running_totals) || []
37
+ @num_pages = 1
38
+
39
+ @pdf = Prawn::Document.new(@report_params)
40
+
41
+ @pdf.font(DEFAULT_FONT)
42
+ @pdf.line_width = LINE_WIDTH
43
+
44
+ if @report_params[:page_size].is_a?(String)
45
+ if @report_params[:page_layout] == :portrait
46
+ w, h = *Prawn::Document::PageGeometry::SIZES[@report_params[:page_size]]
47
+ else
48
+ h, w = *Prawn::Document::PageGeometry::SIZES[@report_params[:page_size]]
49
+ end
50
+ else
51
+ w, h = @report_params[:page_size]
52
+ end
53
+ @x = 0
54
+ @y = @max_height = h - (@report_params[:margin][0] + @report_params[:margin][2])
55
+ @max_width = w - (@report_params[:margin][1] + @report_params[:margin][3])
56
+
57
+ @footer_size = 0
58
+ @pdf.move_cursor_to(max_height - @report_params[:margin][2])
59
+
60
+ @header_class = @header_other_pages_class = @summary_band_class = @footer_class = nil
61
+ @totals = {}
62
+ @group_totals = {}
63
+
64
+ initialize_running_totals
65
+ end
66
+
67
+ def params
68
+ @report_params
69
+ end
70
+
71
+ def draw(data)
72
+ @data = data
73
+
74
+ draw_header_first_page
75
+ draw_internal
76
+ draw_summary
77
+ draw_footer
78
+
79
+ second_pass
80
+
81
+ @pdf.close_and_stroke
82
+ @pdf.render
83
+ end
84
+
85
+ def new_page(print_titles = true)
86
+ draw_footer
87
+
88
+ @num_pages += 1
89
+ @pdf.start_new_page
90
+ @x = 0
91
+ @pdf.move_down(@report_params[:margin][0])
92
+
93
+ draw_header_other_pages
94
+ end
95
+
96
+ def fill_color(color)
97
+ @pdf.fill_color color
98
+ @pdf.fill_rectangle [x,y], max_width, 15
99
+ @pdf.fill_color '000000'
100
+ end
101
+
102
+ protected
103
+
104
+ def draw_header_first_page
105
+ draw_header(@header_class)
106
+ end
107
+
108
+ def draw_header_other_pages
109
+ draw_header(@header_other_pages_class || @header_class)
110
+ end
111
+
112
+ def draw_header(klass)
113
+ if klass
114
+ header = klass.new(self)
115
+ header.draw
116
+ @pdf.y = @max_height - header.height
117
+ @x = 0
118
+ end
119
+ end
120
+
121
+ def draw_footer
122
+ if @footer_class
123
+ footer = @footer_class.new(self)
124
+ @pdf.move_cursor_to(@footer_class.height)
125
+ footer.draw
126
+ end
127
+ end
128
+
129
+ def draw_summary
130
+ if @summary_class
131
+ summary = @summary_class.new(self)
132
+ summary.draw
133
+ end
134
+ end
135
+
136
+ def draw_group_summary
137
+ if @report_params[:group] && @report_params[:group][:summary_class]
138
+ summary = @report_params[:group][:summary_class].new(self)
139
+ summary.draw
140
+ end
141
+ end
142
+
143
+ def draw_group_header
144
+ if @report_params[:group][:header_class]
145
+ header = @report_params[:group][:header_class].new(self)
146
+ header.draw
147
+ end
148
+ end
149
+
150
+ def second_pass
151
+
152
+ end
153
+
154
+ def run_totals(data_row)
155
+ @running_totals.each do |rt|
156
+ vl = get_raw_field_value(data_row, rt)
157
+ vl = (vl.is_a? (String) ? vl.to_f : vl)
158
+ @totals[rt] = (@totals[rt] || 0) + (vl == '' ? 0 : vl)
159
+ @group_totals[rt] = (@group_totals[rt] || 0) + (vl == '' ? 0 : vl)
160
+ end
161
+ end
162
+
163
+ def initialize_running_totals
164
+ @running_totals.each do |rt|
165
+ @totals[rt] = 0
166
+ @group_totals[rt] = 0
167
+ end
168
+ end
169
+
170
+ def reset_group_totals
171
+ @running_totals.each do |rt|
172
+ @group_totals[rt] = 0
173
+ end
174
+ end
175
+
176
+ def reset_totals
177
+ @running_totals.each do |rt|
178
+ @totals[rt] = 0
179
+ end
180
+ end
181
+
182
+ def get_raw_field_value(row, column_name)
183
+ c = row
184
+ column_name.split('.').each {|n| c = c[n] if c}
185
+ c.nil? ? '' : c
186
+ end
187
+
188
+ end
189
+ end
190
+
@@ -0,0 +1,82 @@
1
+ # coding: utf-8
2
+
3
+ module PrawnReport
4
+ class Report
5
+
6
+ def box(width, height, options = {})
7
+ @pdf.rounded_rectangle([0, y], width, height, TEXT_BOX_RADIUS)
8
+ end
9
+
10
+ def text_box_with_box(label, text, width, height = nil, options = {})
11
+ @pdf.rounded_rectangle([@x, y], width, height || TEXT_BOX_HEIGTH, TEXT_BOX_RADIUS)
12
+ @pdf.text_box(label, :size => LABEL_SIZE, :at => [@x + 2, y - 2], :width => width - 2,
13
+ :height => LABEL_SIZE, :valign => :top)
14
+ h_text = height.nil? ? TEXT_SIZE : height - LABEL_SIZE - 4
15
+ @pdf.text_box(text || '', { :size => TEXT_SIZE, :at => [@x + 2, y - LABEL_SIZE - 4],
16
+ :width => width - 2, :height => h_text, :valign => :top }.merge(options))
17
+ @x += width
18
+ end
19
+
20
+ def text(text, width, options = {})
21
+ font_size = options[:font_size] || TEXT_SIZE
22
+ @pdf.text_box(text, :size => font_size, :style => options[:style], :at => [@x, y - 4],
23
+ :width => width, :height => font_size,
24
+ :valign => (options[:valign] || :top),
25
+ :align => (options[:align] || :left)
26
+ )
27
+ @x = @x + width
28
+ end
29
+
30
+ def horizontal_line(x_ini = 0, x_end = @max_width)
31
+ @pdf.stroke do
32
+ @pdf.horizontal_line(x_ini, x_end, :at => y)
33
+ end
34
+ end
35
+
36
+ def y
37
+ @pdf.y
38
+ end
39
+
40
+ def y=(y)
41
+ @pdf.y = y
42
+ end
43
+
44
+ def space(width)
45
+ @x += width
46
+ end
47
+
48
+ def line_break(size = TEXT_SIZE)
49
+ @x = 0
50
+ @pdf.move_down(@pdf.height_of('A', :size => size) + 2)
51
+ end
52
+
53
+ def format(value, formatter, options = {})
54
+ if !value.nil? && value != ''
55
+ if (formatter == :currency)
56
+ if value < 0
57
+ '-'+((value.to_i*-1).to_s.reverse.gsub(/...(?=.)/,'\&.').reverse) + ',' + ('%02d' % ((value.abs * 100).round % 100))
58
+ else
59
+ (value.to_i.to_s.reverse.gsub(/...(?=.)/,'\&.').reverse) + ',' + ('%02d' % ((value * 100).round % 100))
60
+ end
61
+ elsif (formatter == :date)
62
+ value.to_time.strftime('%d/%m/%Y')
63
+ elsif (formatter == :timezone_date)
64
+ tz = Time.zone.parse(value)
65
+ tz.nil? ? '' : tz.strftime('%d/%m/%Y')
66
+ elsif (formatter == :function)
67
+ send(options[:formatter_function].to_s, value)
68
+ else
69
+ value.to_s
70
+ end
71
+ else
72
+ ''
73
+ end
74
+ end
75
+
76
+ def draw_graph(g, params)
77
+ data = StringIO.new(g.to_blob)
78
+ @pdf.image(data, params)
79
+ end
80
+
81
+ end
82
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+
3
+ require 'date'
4
+
5
+ module PrawnReport
6
+ class Report
7
+
8
+ attr_accessor :force_today_as
9
+
10
+ def fits?(h)
11
+ (y - footer_size - h - @report_params[:margin][2]) >= 0
12
+ end
13
+
14
+ def header_size
15
+ @header ? @header_class.height : 0
16
+ end
17
+
18
+ def footer_size
19
+ @footer_class ? @footer_class.height : 0
20
+ end
21
+
22
+ def today
23
+ @force_today_as ? @force_today_as : Date.today
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,20 @@
1
+ #coding: utf-8
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + "/../../../lib/bands/footer_band")
4
+
5
+ module PrawnReport
6
+
7
+ class Footer001 < FooterBand
8
+
9
+ def internal_draw
10
+ report.horizontal_line
11
+ report.x = 0
12
+ end
13
+
14
+ def self.height
15
+ 10
16
+ end
17
+
18
+ end
19
+
20
+ end
@@ -0,0 +1,61 @@
1
+ #coding: utf-8
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + "/../../../lib/bands/header_band")
4
+
5
+ module PrawnReport
6
+
7
+ #This header renders:
8
+ #
9
+ #* Company name based on a property at the root of data named +company_name+ left aligned
10
+ # font size 16.
11
+ #* Data de emissão dated today right aligned font size 12
12
+ #* Report name based on a parameter named +report_name+ setted in the report
13
+ #* A list of filters read from *report.params[:filters]*. Each filter is printed in one
14
+ # line. *params[:filters]* must be an array of arrays where the inner arrays must be
15
+ # tuples of two elements, the first one being the title and second one being the value of the
16
+ # filter. If value is present the title is concatenated with ':'
17
+ class Header001 < HeaderBand
18
+
19
+ def initialize(report, params = {})
20
+ super(report, params)
21
+ @filter_size = 0
22
+ end
23
+
24
+ def internal_draw
25
+ report.text(report.data['company_name'], 300, :style => :bold, :font_size => 16)
26
+ txt_emissao = 'Data de emissão: ' + report.today.strftime('%d/%m/%Y')
27
+ length = report.pdf.width_of(txt_emissao, :size => 12)
28
+ report.x = report.max_width - length
29
+ report.text(txt_emissao, length, :font_size => 12,
30
+ :valign => :bottom, :align => :right)
31
+ report.line_break(16)
32
+ report.text(report.params[:report_name], report.max_width, :font_size => 13,
33
+ :align => :center)
34
+ report.line_break(13)
35
+ draw_filters if report.params[:filters]
36
+ report.horizontal_line
37
+ end
38
+
39
+ def draw_filters
40
+ report.params[:filters].each do |param|
41
+ title = param[0]
42
+ if param[1].to_s != ''
43
+ title = title + ':'
44
+ end
45
+ report.text(title, 2 + report.pdf.width_of(title, :size => 10), :font_size => 10)
46
+ report.text(param[1], 2 + report.pdf.width_of(param[1], :size => 10), :font_size => 10)
47
+ report.x = 0
48
+ size = report.pdf.height_of(param[1], :size => 10)
49
+ size = 10 if size < 10
50
+ report.pdf.move_down(size + 2)
51
+ @filter_size += size + 2
52
+ end
53
+ end
54
+
55
+ def height
56
+ 45 + @filter_size
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,31 @@
1
+ #coding: utf-8
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + "/../../../lib/bands/header_band")
4
+
5
+ module PrawnReport
6
+ #This is a minimalist header intended to render the company name and report name in additional
7
+ #pages of a report.
8
+ #
9
+ #This header renders:
10
+ #
11
+ #* Company name based on a property at the root of data named +company_name+ left aligned
12
+ # font size 12.
13
+ #* Report name based on a parameter named +report_name+ setted in the report
14
+ class Header002 < HeaderBand
15
+
16
+ def internal_draw
17
+ report.x = 0
18
+ report.text(report.data['company_name'], 300, :font_size => 12)
19
+ report.x = 0
20
+ report.text(report.params[:report_name], report.max_width, :font_size => 12, :align => :right)
21
+ report.line_break(12)
22
+ report.horizontal_line
23
+ end
24
+
25
+ def height
26
+ 20
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,58 @@
1
+ module PrawnReport
2
+ class NoGroupingFieldProvided < Exception; end
3
+ class NoGroupingValueFieldProvided < Exception; end
4
+ class NoGroupingContextFieldProvided < Exception; end
5
+
6
+ class ColumnGroup < Listing
7
+ attr_accessor :grouping_field
8
+ attr_accessor :grouping_context_field
9
+ attr_accessor :grouping_value_field
10
+
11
+ def new_page(print_titles = true)
12
+ draw_column_titles if print_titles
13
+ end
14
+
15
+ def before_draw_lines
16
+ super
17
+ draw_column_titles
18
+ end
19
+
20
+ def initialize(report_params = {})
21
+ super(report_params)
22
+ raise NoGroupingFieldProvided unless report_params[:grouping_field]
23
+ raise NoGroupingValueFieldProvided unless report_params[:grouping_value_field]
24
+ raise NoGroupingContextFieldProvided unless report_params[:grouping_context_field]
25
+ @grouping_field = report_params[:grouping_field]
26
+ @grouping_value_field = report_params[:grouping_value_field]
27
+ @grouping_context_field = report_params[:grouping_context_field]
28
+ end
29
+
30
+ def draw(data)
31
+ data = traverse_data(data)
32
+ super(data)
33
+ end
34
+
35
+ protected
36
+
37
+ def traverse_data(data)
38
+ new_data = []
39
+ last_value = nil
40
+ new_row = nil
41
+ old_data = data[@detail_name]
42
+ old_data.each do |row|
43
+ if row[@grouping_field] != last_value then
44
+ new_data << new_row unless new_row.nil?
45
+ last_value = row[@grouping_field]
46
+ new_row = {}
47
+ row.each_pair {|k,v| new_row[k] = v}
48
+ end
49
+ new_row[@grouping_context_field.to_s + '_' + row[@grouping_context_field].to_s] = row[@grouping_value_field]
50
+ end
51
+ new_data << new_row unless new_row.nil?
52
+ data[@detail_name]=new_data
53
+ data
54
+ end
55
+
56
+
57
+ end
58
+ end