juno-report 0.1.2 → 0.1.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.
- checksums.yaml +4 -4
- metadata +5 -41
- data/.gitignore +0 -20
- data/.idea/.name +0 -1
- data/.idea/.rakeTasks +0 -7
- data/.idea/encodings.xml +0 -5
- data/.idea/juno-report.iml +0 -31
- data/.idea/misc.xml +0 -5
- data/.idea/modules.xml +0 -9
- data/.idea/scopes/scope_settings.xml +0 -5
- data/.idea/vcs.xml +0 -7
- data/.idea/workspace.xml +0 -281
- data/.rspec +0 -2
- data/Gemfile +0 -4
- data/Gemfile.lock +0 -52
- data/LICENSE.txt +0 -22
- data/README.md +0 -197
- data/Rakefile +0 -7
- data/juno-report.gemspec +0 -24
- data/lib/juno-report/pdf/behaviors.rb +0 -18
- data/lib/juno-report/pdf.rb +0 -246
- data/lib/juno-report/report_object.rb +0 -9
- data/lib/juno-report/version.rb +0 -3
- data/lib/juno-report.rb +0 -32
- data/report.pdf +0 -153
- data/samples/example.rb +0 -21
- data/samples/report.pdf +0 -972
- data/samples/report.yml +0 -30
- data/spec/data/data1.rb +0 -9
- data/spec/data/rule1.yml +0 -10
- data/spec/default_spec.rb +0 -13
- data/spec/rules_spec.rb +0 -13
- data/spec/spec_helper.rb +0 -11
data/README.md
DELETED
@@ -1,197 +0,0 @@
|
|
1
|
-
# Juno Report
|
2
|
-
|
3
|
-
Cry with Report Generation? Nevermore!
|
4
|
-
|
5
|
-
## Installation
|
6
|
-
|
7
|
-
Add this line to your application's Gemfile:
|
8
|
-
|
9
|
-
gem 'juno-report'
|
10
|
-
|
11
|
-
And then execute:
|
12
|
-
|
13
|
-
$ bundle
|
14
|
-
|
15
|
-
Or install it yourself as:
|
16
|
-
|
17
|
-
$ gem install juno-report
|
18
|
-
|
19
|
-
## Usage
|
20
|
-
|
21
|
-
The generating reports is based on a YAML file with all rules, with the fields and their settings, divided by sections.
|
22
|
-
|
23
|
-
### Body section
|
24
|
-
|
25
|
-
Represents the records which will be iterated to report generating
|
26
|
-
|
27
|
-
```yaml
|
28
|
-
# example.yml
|
29
|
-
body:
|
30
|
-
settings: {posY: 40, height: 25}
|
31
|
-
fields:
|
32
|
-
test_field1: [10]
|
33
|
-
test_field2: [220]
|
34
|
-
test_field3: [430, {column: "Named Test Field 3"}]
|
35
|
-
footer:
|
36
|
-
label_total: [10, {value: "Total"}]
|
37
|
-
totalizer: [220, {behavior: count}]
|
38
|
-
test_field3: [430, {behavior: sum}]
|
39
|
-
```
|
40
|
-
The [body] section ***must*** have three rules:
|
41
|
-
|
42
|
-
* `settings`: Defines some configurations for body, like their height and ypos.
|
43
|
-
* `fields`: Describes each field of record to be iterated.
|
44
|
-
* `footer`: Drawn at the end of all printed records and calculates fields according behavior parameter.
|
45
|
-
|
46
|
-
Each of these rules receives a array, where the first position is an integer representing the field horizontal position and
|
47
|
-
the second position is a hash with some configurations.
|
48
|
-
|
49
|
-
|
50
|
-
##### Settings
|
51
|
-
|
52
|
-
* `height`: Set the of each row at report [Integer].
|
53
|
-
* `posY`: Relative vertical position of last row at report [Integer].
|
54
|
-
* `groups`: Describes which groups will be printed (More bellow) [Array].
|
55
|
-
|
56
|
-
##### Fields
|
57
|
-
|
58
|
-
* `size`: Font size of the field [Integer].
|
59
|
-
* `align`: Defines the text alignment for each value [left|center|right].
|
60
|
-
* `font`: Supports all font type provided by Prawn gem (See more in http://rubydoc.info/gems/prawn/Prawn/Font/AFM).
|
61
|
-
* `style`: Stylistic variations of a font [bold|italic].
|
62
|
-
* `value`: Fixed text to be printed [string].
|
63
|
-
* `column`: The header are "humanized" automatically, but you can set other value manually [string].
|
64
|
-
|
65
|
-
##### Footer
|
66
|
-
|
67
|
-
* `behavior`: Specify a function to be performed, sending as parameter the fieldname value [string].
|
68
|
-
* `label`: Preppends a text to fieldname value specified [string].
|
69
|
-
* `value`: Fixed text to be printed (fieldname value will be ignored) [string].
|
70
|
-
|
71
|
-
With theses configurations already is possible generate a basic report, without groups feature.
|
72
|
-
For this we need call the generate method on JunoReport module:
|
73
|
-
|
74
|
-
```ruby
|
75
|
-
# test.rb
|
76
|
-
require 'juno-report'
|
77
|
-
|
78
|
-
data = [
|
79
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 50},
|
80
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 7},
|
81
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 10},
|
82
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 5},
|
83
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 2},
|
84
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 4},
|
85
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 2", :test_field3 => 24}
|
86
|
-
]
|
87
|
-
|
88
|
-
JunoReport::generate(data, :report => 'example')
|
89
|
-
```
|
90
|
-
|
91
|
-
The first parameter must be a set of hash or objects which represent the report data. And the second parameter is a hash
|
92
|
-
with the report settings, that can be:
|
93
|
-
|
94
|
-
* `report`: The source of all rules. Must be a YAML file [string].
|
95
|
-
* `type`: Specify if the report will be writed on the disc or returned to the caller such a stream [:file|:stream]
|
96
|
-
* `filename`: Defines the report name which will be writed on disc. If not specified, the default name is "report.pdf" [string].
|
97
|
-
|
98
|
-
### Page section
|
99
|
-
|
100
|
-
You may want to print a title every time that a page is created. You simply insert a [page] section.
|
101
|
-
|
102
|
-
```yaml
|
103
|
-
# example.yml
|
104
|
-
page:
|
105
|
-
fields:
|
106
|
-
title1: [260, {size: 24, align: center, value: "Test Report"}]
|
107
|
-
subtitle1: [260, {size: 20, posY: 20, align: center, value: "Generated by Juno Report"}]
|
108
|
-
body:
|
109
|
-
settings: {posY: 40, height: 25}
|
110
|
-
fields:
|
111
|
-
test_field1: [10]
|
112
|
-
test_field2: [220]
|
113
|
-
test_field3: [430, {column: "Named Test Field 3"}]
|
114
|
-
footer:
|
115
|
-
label_total: [10, {value: "Total"}]
|
116
|
-
totalizer: [220, {behavior: count}]
|
117
|
-
test_field3: [430, {behavior: sum}]
|
118
|
-
```
|
119
|
-
|
120
|
-
### Groups section
|
121
|
-
|
122
|
-
For each item in groups parameter at body section you should create a section with same name.
|
123
|
-
This section represents the header configurations to every time that the group is printed and behaves like [body] section.
|
124
|
-
|
125
|
-
```yaml
|
126
|
-
# example.yml
|
127
|
-
page:
|
128
|
-
fields:
|
129
|
-
title1: [260, {size: 24, align: center, value: "Test Report"}]
|
130
|
-
subtitle1: [260, {size: 20, posY: 20, align: center, value: "Generated by Juno Report"}]
|
131
|
-
body:
|
132
|
-
settings: {posY: 40, height: 30, groups: [group_field1, group_field2]}
|
133
|
-
fields:
|
134
|
-
test_field1: [10]
|
135
|
-
test_field2: [220]
|
136
|
-
test_field3: [420, {column: "Named Test Field 3"}]
|
137
|
-
footer:
|
138
|
-
label_total: [10, {value: "Total"}]
|
139
|
-
totalizer1: [220, {behavior: count}]
|
140
|
-
test_field3: [420, {behavior: sum}]
|
141
|
-
group_field1:
|
142
|
-
settings: {posY: 30, height: 10}
|
143
|
-
fields:
|
144
|
-
group_field1: [10, size: 25]
|
145
|
-
footer:
|
146
|
-
group_field1: [10, {label: "Total "}]
|
147
|
-
totalizer1: [220, {behavior: count}]
|
148
|
-
test_field3: [420, {behavior: sum}]
|
149
|
-
group_field2:
|
150
|
-
settings: {posY: 30, height: 25}
|
151
|
-
fields:
|
152
|
-
group_field2: [10, size: 17]
|
153
|
-
footer:
|
154
|
-
group_field2: [10, {label: "Total "}]
|
155
|
-
totalizer1: [220, {behavior: count}]
|
156
|
-
test_field3: [420, {behavior: sum}]
|
157
|
-
```
|
158
|
-
|
159
|
-
Every time that a "group field" value changes, the group will be printed.
|
160
|
-
|
161
|
-
```ruby
|
162
|
-
# test.rb
|
163
|
-
require 'juno-report'
|
164
|
-
|
165
|
-
data = [
|
166
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 1", :test_field3 => 50, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 1'},
|
167
|
-
{:test_field1 => 'Test Value 2', :test_field2 => "Test Value 2", :test_field3 => 16, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 1'},
|
168
|
-
{:test_field1 => 'Test Value 5', :test_field2 => "Test Value 3", :test_field3 => 7, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 1'},
|
169
|
-
{:test_field1 => 'Test Value 3', :test_field2 => "Test Value 9", :test_field3 => 10, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 2'},
|
170
|
-
{:test_field1 => 'Test Value 3', :test_field2 => "Test Value 2", :test_field3 => 4, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 2'},
|
171
|
-
{:test_field1 => 'Test Value 9', :test_field2 => "Test Value 4", :test_field3 => 10, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 2'},
|
172
|
-
{:test_field1 => 'Test Value 7', :test_field2 => "Test Value 5", :test_field3 => 5, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 3'},
|
173
|
-
{:test_field1 => 'Test Value 3', :test_field2 => "Test Value 5", :test_field3 => 2, :group_field1 => 'Group 1', :group_field2 => 'Subgroup 3'},
|
174
|
-
{:test_field1 => 'Test Value 3', :test_field2 => "Test Value 2", :test_field3 => 27, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 1'},
|
175
|
-
{:test_field1 => 'Test Value 3', :test_field2 => "Test Value 5", :test_field3 => 2, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 1'},
|
176
|
-
{:test_field1 => 'Test Value 0', :test_field2 => "Test Value 4", :test_field3 => 13, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 1'},
|
177
|
-
{:test_field1 => 'Test Value 4', :test_field2 => "Test Value 7", :test_field3 => 7, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 1'},
|
178
|
-
{:test_field1 => 'Test Value 1', :test_field2 => "Test Value 3", :test_field3 => 28, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 1'},
|
179
|
-
{:test_field1 => 'Test Value 4', :test_field2 => "Test Value 5", :test_field3 => 4, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 2'},
|
180
|
-
{:test_field1 => 'Test Value 5', :test_field2 => "Test Value 6", :test_field3 => 24, :group_field1 => 'Group 2', :group_field2 => 'Subgroup 2'}
|
181
|
-
]
|
182
|
-
|
183
|
-
JunoReport::generate(data, :report => 'example', :filename => 'juno-report.pdf')
|
184
|
-
```
|
185
|
-
|
186
|
-
## Contributors
|
187
|
-
|
188
|
-
2. Edson Júnior (http://github.com/ebfjunior)
|
189
|
-
|
190
|
-
## Contributing
|
191
|
-
|
192
|
-
1. Fork it
|
193
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
194
|
-
3. Commit your changes (`git commit -am 'Added some feature'`)
|
195
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
196
|
-
5. Create new Pull Request
|
197
|
-
|
data/Rakefile
DELETED
data/juno-report.gemspec
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
# -*- encoding: utf-8 -*-
|
2
|
-
$:.push File.expand_path("../lib", __FILE__)
|
3
|
-
require 'juno-report/version'
|
4
|
-
|
5
|
-
Gem::Specification.new do |gem|
|
6
|
-
gem.name = "juno-report"
|
7
|
-
gem.version = JunoReport::VERSION
|
8
|
-
gem.platform = Gem::Platform::RUBY
|
9
|
-
gem.authors = ["Edson Júnior"]
|
10
|
-
gem.email = ["ejunior.batista@gmail.com"]
|
11
|
-
gem.description = "A simple, but efficient, report genarator yaml based"
|
12
|
-
gem.summary = "Juno Reports generates reports with the minimum configuration and effort"
|
13
|
-
gem.homepage = "http://github.com/ebfjunior/juno-report"
|
14
|
-
|
15
|
-
gem.files = `git ls-files`.split("\n")
|
16
|
-
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
17
|
-
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
-
gem.require_paths = ["lib"]
|
19
|
-
|
20
|
-
gem.add_dependency "prawml"
|
21
|
-
|
22
|
-
gem.add_development_dependency 'rake'
|
23
|
-
gem.add_development_dependency 'rspec'
|
24
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module JunoReport
|
2
|
-
module Pdf
|
3
|
-
module Behaviors
|
4
|
-
def self.sum old_value, new_value
|
5
|
-
value = (old_value.to_f + new_value.to_f).to_s
|
6
|
-
(/^[0-9]+(?=\.)/.match value).nil? ? value : value[/^[0-9]+(?=\.)/]
|
7
|
-
end
|
8
|
-
|
9
|
-
def self.substract old_value, new_value
|
10
|
-
old_value.to_f - new_value.to_f
|
11
|
-
end
|
12
|
-
|
13
|
-
def self.count old_value, new_value = nil
|
14
|
-
old_value.to_i + 1
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
data/lib/juno-report/pdf.rb
DELETED
@@ -1,246 +0,0 @@
|
|
1
|
-
module JunoReport
|
2
|
-
module Pdf
|
3
|
-
|
4
|
-
#Responsible for generate a report, based on rules passed as parameter in Juno::Report::generate.
|
5
|
-
#Juno Reports has support groups, just by especifying them at the rules file.
|
6
|
-
#Receives a collection as parameter, which should be a Array of records of the report.
|
7
|
-
def generate(collection)
|
8
|
-
@defaults = {
|
9
|
-
:style => :normal,
|
10
|
-
:size => 12,
|
11
|
-
:align => :left,
|
12
|
-
:format => false,
|
13
|
-
:font => 'Times-Roman',
|
14
|
-
:type => :text,
|
15
|
-
:color => '000000',
|
16
|
-
:fixed => false
|
17
|
-
}
|
18
|
-
|
19
|
-
get_sections
|
20
|
-
set_pos_y
|
21
|
-
|
22
|
-
@defaults.merge!(@sections[:defaults]) unless @sections[:defaults].nil?
|
23
|
-
|
24
|
-
collection = [collection] unless collection.is_a?(Array) or collection.is_a?(ActiveRecord::Relation)
|
25
|
-
print_section :page unless @sections[:page].nil?
|
26
|
-
set_pos_y (@sections[:body][:settings][:posY] || 0)
|
27
|
-
@current_groups = {}
|
28
|
-
@footers = {}
|
29
|
-
@count = 0
|
30
|
-
|
31
|
-
unless @sections[:groups].empty?
|
32
|
-
reset_groups_values
|
33
|
-
else
|
34
|
-
draw_columns
|
35
|
-
end
|
36
|
-
|
37
|
-
initialize_footer_values
|
38
|
-
can_print_footer = false
|
39
|
-
|
40
|
-
collection.each do |record|
|
41
|
-
@record = record.is_a?(Hash) ? ReportObject.new(record) : record #Convert the hash on a Object to futurely extend a module
|
42
|
-
|
43
|
-
headers_to_print, headers_height = calculate_header
|
44
|
-
|
45
|
-
unless headers_to_print.empty?
|
46
|
-
@count = 0
|
47
|
-
draw_footer headers_to_print, @sections[:groups] if can_print_footer
|
48
|
-
if @posY - headers_height < 2*@sections[:body][:settings][:height]
|
49
|
-
new_page
|
50
|
-
else
|
51
|
-
headers_to_print.each { |group| print_section group, @record, true }
|
52
|
-
draw_columns
|
53
|
-
end
|
54
|
-
end
|
55
|
-
can_print_footer = true
|
56
|
-
|
57
|
-
update_footer_values
|
58
|
-
print_section :body, @record
|
59
|
-
@count += 1
|
60
|
-
end
|
61
|
-
|
62
|
-
draw_footer(@sections[:body][:settings][:groups].collect {|group| group.to_sym}, @sections[:groups]) if has_groups?
|
63
|
-
draw_footer [:body], @sections
|
64
|
-
|
65
|
-
@pdf
|
66
|
-
end
|
67
|
-
|
68
|
-
protected
|
69
|
-
|
70
|
-
#Creates a new page, restarting the vertical position of the pointer.
|
71
|
-
#Print the whole header for the current groups and the columns of the report.
|
72
|
-
def new_page
|
73
|
-
@pdf.start_new_page
|
74
|
-
set_pos_y
|
75
|
-
print_section :page unless @sections[:page].nil?
|
76
|
-
set_pos_y (@sections[:body][:settings][:posY] || 0)
|
77
|
-
@current_groups.each do |field, value|
|
78
|
-
print_section field.to_sym, @record, true
|
79
|
-
end
|
80
|
-
draw_columns
|
81
|
-
end
|
82
|
-
|
83
|
-
#Generic function to print a section like :body, :page or the group sections.
|
84
|
-
def print_section(section_name, values = nil, group = false)
|
85
|
-
section = !group ? @sections[section_name] : @sections[:groups][section_name]
|
86
|
-
set_pos_y(section[:settings][:posY] || 0) unless section_name.eql?(:body) || section[:settings].nil?
|
87
|
-
new_page if @posY < 30
|
88
|
-
|
89
|
-
if section_name.eql? :body and @count % 2 != 0
|
90
|
-
@pdf.fill_color "F7F7F7"
|
91
|
-
width = @options[:page_layout] == :portrait ? 530 : 770
|
92
|
-
@pdf.fill_rectangle [0, @posY+(section[:settings][:height]/2)], width, section[:settings][:height]
|
93
|
-
end
|
94
|
-
|
95
|
-
section[:fields].each do |field, settings|
|
96
|
-
symbolize! settings[1] unless settings[1].nil?
|
97
|
-
set_pos_y settings[1][:posY] unless settings[1].nil? || settings[1][:posY].nil?
|
98
|
-
settings = [settings[0], @posY, (@defaults.merge (settings[1] || { }))]
|
99
|
-
settings[2][:style] = settings[2][:style].to_sym
|
100
|
-
set_options settings[2]
|
101
|
-
|
102
|
-
value = settings[2][:value].nil? ? (values.respond_to?(field) ? values.send(field) : "") : settings[2][:value]
|
103
|
-
string_cut = settings[2][:cut].nil? ? value : value[0..settings[2][:cut]]
|
104
|
-
draw_text string_cut, settings
|
105
|
-
end
|
106
|
-
set_pos_y (section[:settings][:height]) unless section[:settings].nil? || section[:settings][:height].nil?
|
107
|
-
end
|
108
|
-
|
109
|
-
#Print a horizontal line with the whole width of the page.
|
110
|
-
def draw_line(y)
|
111
|
-
width = @options[:page_layout] == :portrait ? 530 : 770
|
112
|
-
@pdf.stroke { @pdf.horizontal_line 0, width, :at => y }
|
113
|
-
end
|
114
|
-
|
115
|
-
#Update the pointer vertical position to the specified value or 'zero' if the parameter is nil.
|
116
|
-
#Obs: Prawn pointer is decrescent, in other words, the left-top corner position is (0, 750). For
|
117
|
-
#semantic purposes, we set the same corner as (0, 0).
|
118
|
-
def set_pos_y(posY = nil)
|
119
|
-
height = @options[:page_layout] == :portrait ? 750 : 520
|
120
|
-
@posY = height if @posY.nil?
|
121
|
-
@posY = posY.nil? ? height : @posY - posY
|
122
|
-
end
|
123
|
-
|
124
|
-
#Convert to symbol all hash keys, recursively.
|
125
|
-
def symbolize! hash
|
126
|
-
hash.symbolize_keys!
|
127
|
-
hash.values.select{|v| v.is_a? Hash}.each{|h| symbolize!(h)}
|
128
|
-
end
|
129
|
-
|
130
|
-
#Convert the structure of the rules to facilitate the generating proccess.
|
131
|
-
def get_sections
|
132
|
-
symbolize! @rules
|
133
|
-
raise "[body] section on YAML file is needed to generate the report." if @rules[:body].nil?
|
134
|
-
@sections = {:page => @rules[:page], :body => @rules[:body], :defaults => @rules[:defaults], :groups => {}}
|
135
|
-
@sections[:body][:settings][:groups].each { |group| @sections[:groups][group.to_sym] = @rules[group.to_sym] } if has_groups?
|
136
|
-
end
|
137
|
-
|
138
|
-
#@current_groups storages the value for all groups. When a value is changed, the header is printed.
|
139
|
-
#This function set nil value for every item in @current_groups if the parameter is not passed. Otherwise,
|
140
|
-
#only the forward groups will be cleaned to avoid conflict problems with others groups.
|
141
|
-
def reset_groups_values current_group = nil
|
142
|
-
groups = @sections[:body][:settings][:groups]
|
143
|
-
groups.each_with_index do |group, idx|
|
144
|
-
@current_groups[group] = nil if current_group.nil? || groups.index(current_group.to_s) <= idx
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
|
149
|
-
#Calculates the headers which must be printed before print the current record.
|
150
|
-
#The function also returns the current header height to create a new page if the
|
151
|
-
#page remaining space is smaller than (header + a record height)
|
152
|
-
def calculate_header
|
153
|
-
headers = []
|
154
|
-
height = 0
|
155
|
-
@current_groups.each do |field, value|
|
156
|
-
if @record.send(field) != value
|
157
|
-
reset_groups_values field
|
158
|
-
|
159
|
-
headers << field.to_sym
|
160
|
-
height += @sections[:groups][field.to_sym][:settings][:height] + @sections[:groups][field.to_sym][:settings][:posY]
|
161
|
-
|
162
|
-
@current_groups[field] = @record.send(field)
|
163
|
-
end
|
164
|
-
end unless @current_groups.empty?
|
165
|
-
[headers, height]
|
166
|
-
end
|
167
|
-
|
168
|
-
#Create a structure to calculate the footer values for all groups. Appends the footer body to total values too.
|
169
|
-
def initialize_footer_values
|
170
|
-
@sections[:body][:settings][:groups].each do |group|
|
171
|
-
current_footer = {}
|
172
|
-
@sections[:groups][group.to_sym][:footer].each { |field, settings| current_footer[field] = nil } unless @sections[:groups][group.to_sym][:footer].nil?
|
173
|
-
@footers[group.to_sym] = current_footer unless current_footer.empty?
|
174
|
-
end if has_groups?
|
175
|
-
raise "The report must have at least a footer on body section" if @sections[:body][:footer].nil?
|
176
|
-
current_footer = {}
|
177
|
-
@sections[:body][:footer].each { |field, settings| current_footer[field] = nil }
|
178
|
-
@footers[:body] = current_footer unless current_footer.empty?
|
179
|
-
end
|
180
|
-
|
181
|
-
#Call the function that calculates the footer values for all groups and the total body footer, with
|
182
|
-
#different source for each
|
183
|
-
def update_footer_values
|
184
|
-
@sections[:body][:settings][:groups].reverse_each do |group|
|
185
|
-
calculate_footer_values group, @sections[:groups][group.to_sym][:footer]
|
186
|
-
end if has_groups?
|
187
|
-
calculate_footer_values :body, @sections[:body][:footer]
|
188
|
-
end
|
189
|
-
|
190
|
-
#Returns the values to the group passed as parameter. If :behavior setting is used, so a
|
191
|
-
#function in [lib/pdf/behaviors.rb] calculates the value of current field, else the report
|
192
|
-
#method is called
|
193
|
-
def calculate_footer_values group, source
|
194
|
-
@footers[group.to_sym].each do |field, value|
|
195
|
-
footer_rule = source[field]
|
196
|
-
symbolize! footer_rule[1]
|
197
|
-
unless footer_rule[1][:behavior].nil?
|
198
|
-
@footers[group.to_sym][field] = JunoReport::Pdf::Behaviors.send footer_rule[1][:behavior].to_sym, value, (@record.respond_to?(field) ? @record.send(field) : nil)
|
199
|
-
else
|
200
|
-
@footers[group.to_sym][field] = footer_rule[1][:value] || (footer_rule[1][:label].to_s + @record.send(field))
|
201
|
-
end unless @footers[group.to_sym].nil? || footer_rule[1].nil?
|
202
|
-
end
|
203
|
-
end
|
204
|
-
|
205
|
-
#Print the footers according to the groups and source specified
|
206
|
-
def draw_footer footers_to_print, source
|
207
|
-
footers_to_print.reverse_each do |group|
|
208
|
-
draw_line(@posY + @sections[:body][:settings][:height]/2)
|
209
|
-
source[group][:footer].each do |field, settings|
|
210
|
-
settings = [settings[0], @posY, (@defaults.merge (settings[1] || { }).symbolize_keys!)]
|
211
|
-
settings[2][:style] = settings[2][:style].to_sym
|
212
|
-
set_options settings[2]
|
213
|
-
draw_text @footers[group][field], settings
|
214
|
-
end
|
215
|
-
draw_line(@posY - @sections[:body][:settings][:height]/4)
|
216
|
-
set_pos_y @sections[:body][:settings][:height]
|
217
|
-
|
218
|
-
reset_footer group
|
219
|
-
end
|
220
|
-
end
|
221
|
-
|
222
|
-
#Resets the footer to next groups
|
223
|
-
def reset_footer(group); @footers[group].each { |field, value| @footers[group][field] = nil }; end
|
224
|
-
|
225
|
-
#Based on the Key names of the :body section at the rules, the function draw columns with
|
226
|
-
#baselines on the top and bottom of the header.
|
227
|
-
def draw_columns
|
228
|
-
@sections[:body][:fields].each do |field, settings|
|
229
|
-
settings = [settings[0], @posY, (@defaults.merge (settings[1] || { }).symbolize_keys!)]
|
230
|
-
settings[2][:style] = settings[2][:style].to_sym
|
231
|
-
set_options settings[2]
|
232
|
-
draw_line(@posY + @sections[:body][:settings][:height]/2)
|
233
|
-
field = settings[2][:column] || field.to_s.split('_').inject('') do |str, part|
|
234
|
-
str << part.camelize << " "
|
235
|
-
end
|
236
|
-
draw_text field, settings
|
237
|
-
end
|
238
|
-
draw_line(@posY - @sections[:body][:settings][:height]/2)
|
239
|
-
set_pos_y @sections[:body][:settings][:height]
|
240
|
-
end
|
241
|
-
|
242
|
-
def has_groups?
|
243
|
-
!@sections[:body][:settings][:groups].nil?
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
@@ -1,9 +0,0 @@
|
|
1
|
-
class ReportObject
|
2
|
-
def initialize(hash)
|
3
|
-
hash.each do |k,v|
|
4
|
-
self.instance_variable_set("@#{k}", v)
|
5
|
-
self.class.send(:define_method, k, proc{self.instance_variable_get("@#{k}")})
|
6
|
-
self.class.send(:define_method, "#{k}=", proc{|v| self.instance_variable_set("@#{k}", v)})
|
7
|
-
end
|
8
|
-
end
|
9
|
-
end
|
data/lib/juno-report/version.rb
DELETED
data/lib/juno-report.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
require "juno-report/version"
|
2
|
-
require "juno-report/pdf"
|
3
|
-
require "juno-report/pdf/behaviors"
|
4
|
-
require "prawml"
|
5
|
-
|
6
|
-
module JunoReport
|
7
|
-
autoload :ReportObject, 'juno-report/report_object'
|
8
|
-
|
9
|
-
def self.generate(collection, options)
|
10
|
-
rules = (File.open "#{options[:report]}.yml").read
|
11
|
-
|
12
|
-
defaults = {
|
13
|
-
:page_layout => :portrait
|
14
|
-
}
|
15
|
-
|
16
|
-
pdf = Prawml::PDF.new rules, defaults.merge(options)
|
17
|
-
|
18
|
-
pdf.extend JunoReport::Pdf
|
19
|
-
report = pdf.generate(collection)
|
20
|
-
|
21
|
-
options[:type] ||= :file
|
22
|
-
|
23
|
-
if options[:type].eql? :file
|
24
|
-
report.render_file (options[:filename] || "report.pdf")
|
25
|
-
elsif options[:type].eql? :stream
|
26
|
-
return report.render
|
27
|
-
else
|
28
|
-
raise "Type options must be :file or :stream."
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
end
|
data/report.pdf
DELETED
@@ -1,153 +0,0 @@
|
|
1
|
-
%PDF-1.3
|
2
|
-
%����
|
3
|
-
1 0 obj
|
4
|
-
<< /Creator <feff0050007200610077006e>
|
5
|
-
/Producer <feff0050007200610077006e>
|
6
|
-
>>
|
7
|
-
endobj
|
8
|
-
2 0 obj
|
9
|
-
<< /Type /Catalog
|
10
|
-
/Pages 3 0 R
|
11
|
-
>>
|
12
|
-
endobj
|
13
|
-
3 0 obj
|
14
|
-
<< /Type /Pages
|
15
|
-
/Count 1
|
16
|
-
/Kids [5 0 R]
|
17
|
-
>>
|
18
|
-
endobj
|
19
|
-
4 0 obj
|
20
|
-
<< /Length 926
|
21
|
-
>>
|
22
|
-
stream
|
23
|
-
q
|
24
|
-
/DeviceRGB cs
|
25
|
-
0.000 0.000 0.000 scn
|
26
|
-
36.000 758.000 m
|
27
|
-
566.000 758.000 l
|
28
|
-
S
|
29
|
-
|
30
|
-
BT
|
31
|
-
46 746.0 Td
|
32
|
-
/F1.0 12 Tf
|
33
|
-
[<54> 70 <657374204669656c643120>] TJ
|
34
|
-
ET
|
35
|
-
|
36
|
-
0.000 0.000 0.000 scn
|
37
|
-
36.000 758.000 m
|
38
|
-
566.000 758.000 l
|
39
|
-
S
|
40
|
-
|
41
|
-
BT
|
42
|
-
256 746.0 Td
|
43
|
-
/F1.0 12 Tf
|
44
|
-
[<54> 70 <657374204669656c643220>] TJ
|
45
|
-
ET
|
46
|
-
|
47
|
-
0.000 0.000 0.000 scn
|
48
|
-
36.000 758.000 m
|
49
|
-
566.000 758.000 l
|
50
|
-
S
|
51
|
-
|
52
|
-
BT
|
53
|
-
466 746.0 Td
|
54
|
-
/F1.0 12 Tf
|
55
|
-
[<4e616d65642054> 70 <657374204669656c642033>] TJ
|
56
|
-
ET
|
57
|
-
|
58
|
-
36.000 734.000 m
|
59
|
-
566.000 734.000 l
|
60
|
-
S
|
61
|
-
0.000 0.000 0.000 scn
|
62
|
-
|
63
|
-
BT
|
64
|
-
46 721.0 Td
|
65
|
-
/F1.0 12 Tf
|
66
|
-
[<>] TJ
|
67
|
-
ET
|
68
|
-
|
69
|
-
0.000 0.000 0.000 scn
|
70
|
-
|
71
|
-
BT
|
72
|
-
256 721.0 Td
|
73
|
-
/F1.0 12 Tf
|
74
|
-
[<>] TJ
|
75
|
-
ET
|
76
|
-
|
77
|
-
0.000 0.000 0.000 scn
|
78
|
-
|
79
|
-
BT
|
80
|
-
466 721.0 Td
|
81
|
-
/F1.0 12 Tf
|
82
|
-
[<>] TJ
|
83
|
-
ET
|
84
|
-
|
85
|
-
36.000 708.000 m
|
86
|
-
566.000 708.000 l
|
87
|
-
S
|
88
|
-
0.000 0.000 0.000 scn
|
89
|
-
|
90
|
-
BT
|
91
|
-
46 696.0 Td
|
92
|
-
/F1.0 12 Tf
|
93
|
-
[<54> 80 <6f74616c>] TJ
|
94
|
-
ET
|
95
|
-
|
96
|
-
0.000 0.000 0.000 scn
|
97
|
-
|
98
|
-
BT
|
99
|
-
256 696.0 Td
|
100
|
-
/F1.0 12 Tf
|
101
|
-
[<31>] TJ
|
102
|
-
ET
|
103
|
-
|
104
|
-
0.000 0.000 0.000 scn
|
105
|
-
|
106
|
-
BT
|
107
|
-
466 696.0 Td
|
108
|
-
/F1.0 12 Tf
|
109
|
-
[<30>] TJ
|
110
|
-
ET
|
111
|
-
|
112
|
-
36.000 690.000 m
|
113
|
-
566.000 690.000 l
|
114
|
-
S
|
115
|
-
Q
|
116
|
-
|
117
|
-
endstream
|
118
|
-
endobj
|
119
|
-
5 0 obj
|
120
|
-
<< /Type /Page
|
121
|
-
/Parent 3 0 R
|
122
|
-
/MediaBox [0 0 595.28 841.89]
|
123
|
-
/Contents 4 0 R
|
124
|
-
/Resources << /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
|
125
|
-
/Font << /F1.0 6 0 R
|
126
|
-
>>
|
127
|
-
>>
|
128
|
-
>>
|
129
|
-
endobj
|
130
|
-
6 0 obj
|
131
|
-
<< /Type /Font
|
132
|
-
/Subtype /Type1
|
133
|
-
/BaseFont /Times-Roman
|
134
|
-
/Encoding /WinAnsiEncoding
|
135
|
-
>>
|
136
|
-
endobj
|
137
|
-
xref
|
138
|
-
0 7
|
139
|
-
0000000000 65535 f
|
140
|
-
0000000015 00000 n
|
141
|
-
0000000109 00000 n
|
142
|
-
0000000158 00000 n
|
143
|
-
0000000215 00000 n
|
144
|
-
0000001192 00000 n
|
145
|
-
0000001372 00000 n
|
146
|
-
trailer
|
147
|
-
<< /Size 7
|
148
|
-
/Root 2 0 R
|
149
|
-
/Info 1 0 R
|
150
|
-
>>
|
151
|
-
startxref
|
152
|
-
1471
|
153
|
-
%%EOF
|