xbrlware-ce 1.0.4 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Rakefile.rb +4 -4
- data/Readme.txt +6 -1
- data/ReleaseNotes.txt +22 -5
- data/doc/classes/Edgar/HTMLFeedDownloader.html +8 -8
- data/doc/classes/Edgar/RSSFeedDownloader.html +15 -15
- data/doc/classes/Xbrlware.html +22 -0
- data/doc/classes/Xbrlware/Context.html +104 -74
- data/doc/classes/Xbrlware/Context/Period.html +305 -0
- data/doc/classes/Xbrlware/Entity.html +75 -51
- data/doc/classes/Xbrlware/Identifier.html +17 -17
- data/doc/classes/Xbrlware/Instance.html +165 -137
- data/doc/classes/Xbrlware/Item.html +19 -19
- data/doc/classes/Xbrlware/Linkbase/CalculationLinkbase/Calculation.html +1 -1
- data/doc/classes/Xbrlware/Linkbase/DefinitionLinkbase/Definition.html +2 -2
- data/doc/classes/Xbrlware/Linkbase/Linkbase/Link.html +9 -3
- data/doc/classes/Xbrlware/Linkbase/Linkbase/Link/Arc.html +4 -4
- data/doc/classes/Xbrlware/Linkbase/PresentationLinkbase/Presentation.html +1 -1
- data/doc/classes/Xbrlware/Report.html +352 -0
- data/doc/classes/Xbrlware/Taxonomy.html +48 -48
- data/doc/classes/Xbrlware/TaxonomyDefintion.html +15 -15
- data/doc/classes/Xbrlware/Unit.html +6 -6
- data/doc/classes/Xbrlware/Unit/Divide.html +6 -6
- data/doc/created.rid +1 -1
- data/doc/files/Readme_txt.html +9 -1
- data/doc/files/lib/xbrlware/context_rb.html +1 -1
- data/doc/files/lib/xbrlware/date_util_rb.html +1 -1
- data/doc/files/lib/xbrlware/instance_rb.html +1 -1
- data/doc/files/lib/xbrlware/linkbase/calculation_linkbase_rb.html +1 -1
- data/doc/files/lib/xbrlware/linkbase/definition_linkbase_rb.html +1 -1
- data/doc/files/lib/xbrlware/linkbase/linkbase_rb.html +1 -1
- data/doc/files/lib/xbrlware/linkbase/presentation_linkbase_rb.html +1 -1
- data/doc/files/lib/xbrlware/meta_util_rb.html +1 -1
- data/doc/files/lib/xbrlware/report_rb.html +101 -0
- data/doc/files/lib/xbrlware/taxonomy_rb.html +1 -1
- data/doc/files/lib/xbrlware/version_rb.html +129 -0
- data/doc/fr_class_index.html +2 -0
- data/doc/fr_file_index.html +2 -0
- data/doc/fr_method_index.html +75 -62
- data/example/case_study/buy_strategy.rb +1 -1
- data/example/case_study/c_sell_strategy.rb +1 -1
- data/lib/xbrlware/context.rb +77 -34
- data/lib/xbrlware/date_util.rb +16 -6
- data/lib/xbrlware/instance.rb +35 -28
- data/lib/xbrlware/linkbase/calculation_linkbase.rb +1 -1
- data/lib/xbrlware/linkbase/definition_linkbase.rb +2 -2
- data/lib/xbrlware/linkbase/linkbase.rb +3 -2
- data/lib/xbrlware/linkbase/presentation_linkbase.rb +1 -1
- data/lib/xbrlware/meta_util.rb +5 -0
- data/lib/xbrlware/report.rb +277 -0
- data/lib/xbrlware/taxonomy.rb +13 -10
- data/lib/xbrlware/version.rb +22 -0
- data/test/lib/xbrlware/47_context_test.rb +13 -4
- data/test/lib/xbrlware/date_util_test.rb +10 -2
- data/test/lib/xbrlware/instance_test.rb +19 -0
- data/test/lib/xbrlware/meta_util_test.rb +21 -1
- metadata +10 -4
@@ -21,7 +21,7 @@ end
|
|
21
21
|
|
22
22
|
curr_asset, prev_asset=0, 0
|
23
23
|
|
24
|
-
if
|
24
|
+
if assets[0].context.period.value > assets[1].context.period.value
|
25
25
|
curr_asset=assets[0].value.to_f
|
26
26
|
prev_asset=assets[1].value.to_f
|
27
27
|
else
|
@@ -14,7 +14,7 @@ end
|
|
14
14
|
|
15
15
|
curr_netincome, prev_netincome=0, 0
|
16
16
|
|
17
|
-
if
|
17
|
+
if net_incomes[0].context.period.value["end_date"] > net_incomes[1].context.period.value["end_date"]
|
18
18
|
curr_netincome=net_incomes[0].value.to_f
|
19
19
|
prev_netincome=net_incomes[1].value.to_f
|
20
20
|
else
|
data/lib/xbrlware/context.rb
CHANGED
@@ -21,29 +21,66 @@ module Xbrlware
|
|
21
21
|
# This class represents each context in the XBRL instance file.
|
22
22
|
# Look at {delaing with instance page on xbrlware wiki}[http://code.google.com/p/xbrlware/wiki/InstanceTaxonomy] for more details.
|
23
23
|
class Context
|
24
|
-
attr_reader :id
|
24
|
+
attr_reader :id, :entity, :period, :scenario
|
25
25
|
PERIOD_FOREVER = -1
|
26
|
-
|
26
|
+
|
27
|
+
class Period
|
28
|
+
attr_reader :value
|
29
|
+
|
30
|
+
def initialize(value)
|
31
|
+
@value = value
|
32
|
+
end
|
33
|
+
|
34
|
+
def to_s
|
35
|
+
@value.to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
def eql?(o)
|
39
|
+
o.is_a?(Period) && @value == o.value
|
40
|
+
end
|
41
|
+
|
42
|
+
def hash
|
43
|
+
@value.hash
|
44
|
+
end
|
45
|
+
|
46
|
+
def is_instant?
|
47
|
+
@value.is_a?(Date)
|
48
|
+
end
|
49
|
+
|
50
|
+
def is_duration?
|
51
|
+
@value.is_a?(Hash)
|
52
|
+
end
|
53
|
+
|
54
|
+
def is_forever?
|
55
|
+
@value.is_a?(Fixnum)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def initialize(id, entity, period, scenario=nil)
|
27
60
|
@id = id
|
28
61
|
@entity = entity
|
29
|
-
@period = period
|
62
|
+
@period = Period.new(period)
|
30
63
|
@scenario=scenario
|
31
64
|
end
|
32
|
-
|
65
|
+
|
66
|
+
def has_scenario?
|
67
|
+
(not @scenario.nil?)
|
68
|
+
end
|
69
|
+
|
33
70
|
def to_s
|
34
|
-
"Id [" + id + "], Entity { " + @entity.to_s + " }, period ["+period.to_s+"]"+ (", scenario ["+scenario+"]" unless scenario.nil?).to_s
|
71
|
+
"Id [" + id + "], Entity { " + @entity.to_s + " }, period ["+period.to_s+"]"+ (", scenario ["+scenario+"]" unless scenario.nil?).to_s
|
35
72
|
end
|
36
|
-
|
73
|
+
|
37
74
|
def eql?(o)
|
38
75
|
o.is_a?(Context) && @id == o.id
|
39
76
|
end
|
40
|
-
|
77
|
+
|
41
78
|
def hash
|
42
79
|
@id.hash
|
43
80
|
end
|
44
|
-
|
81
|
+
|
45
82
|
def has_explicit_dimensions?(dimensions=[])
|
46
|
-
return @entity.has_explicit_dimensions?(dimensions) unless @entity.nil?
|
83
|
+
return @entity.has_explicit_dimensions?(dimensions) unless @entity.nil?
|
47
84
|
false
|
48
85
|
end
|
49
86
|
|
@@ -54,10 +91,10 @@ module Xbrlware
|
|
54
91
|
end
|
55
92
|
|
56
93
|
alias_method :dimensions, :explicit_dimensions
|
57
|
-
|
94
|
+
|
58
95
|
def explicit_domains(dimensions=[])
|
59
96
|
return @entity.explicit_domains(dimensions)
|
60
|
-
end
|
97
|
+
end
|
61
98
|
|
62
99
|
alias_method :domains, :explicit_domains
|
63
100
|
|
@@ -66,37 +103,42 @@ module Xbrlware
|
|
66
103
|
end
|
67
104
|
|
68
105
|
alias_method :dimensions_domains, :explicit_dimensions_domains
|
69
|
-
|
106
|
+
|
70
107
|
end
|
71
|
-
|
108
|
+
|
72
109
|
class Entity
|
73
|
-
attr_reader :identifier
|
74
|
-
|
110
|
+
attr_reader :identifier, :segment
|
111
|
+
|
112
|
+
def initialize(identifier, segment=nil)
|
75
113
|
@identifier = identifier
|
76
114
|
@segment = segment
|
77
115
|
end
|
78
|
-
|
116
|
+
|
117
|
+
def has_segment?
|
118
|
+
(not @segment.nil?)
|
119
|
+
end
|
120
|
+
|
79
121
|
def to_s
|
80
122
|
"Identifier { " + @identifier.to_s + " } " + (", segment [" + segment.to_s + "]" unless segment.nil?).to_s
|
81
123
|
end
|
82
|
-
|
124
|
+
|
83
125
|
def has_explicit_dimensions?(dimensions=[])
|
84
126
|
dimensions_set=Set.new
|
85
127
|
dimensions_set.merge(dimensions)
|
86
128
|
unless @segment.nil? || @segment["explicitMember"].nil?
|
87
|
-
|
88
|
-
return true if dimensions.size==0
|
89
|
-
|
129
|
+
|
130
|
+
return true if dimensions.size==0
|
131
|
+
|
90
132
|
dim = Set.new
|
91
133
|
@segment["explicitMember"].each do |member|
|
92
134
|
dim << member["dimension"]
|
93
135
|
end
|
94
|
-
return dim.superset?(dimensions_set)
|
136
|
+
return dim.superset?(dimensions_set)
|
95
137
|
end
|
96
|
-
|
138
|
+
|
97
139
|
return false
|
98
140
|
end
|
99
|
-
|
141
|
+
|
100
142
|
def explicit_dimensions
|
101
143
|
dim = Set.new
|
102
144
|
unless @segment.nil? || @segment["explicitMember"].nil?
|
@@ -106,7 +148,7 @@ module Xbrlware
|
|
106
148
|
end
|
107
149
|
return dim.to_a
|
108
150
|
end
|
109
|
-
|
151
|
+
|
110
152
|
def explicit_domains(dimensions=[])
|
111
153
|
dom = Set.new
|
112
154
|
if has_explicit_dimensions?(dimensions)
|
@@ -116,33 +158,34 @@ module Xbrlware
|
|
116
158
|
next unless dim==member["dimension"]
|
117
159
|
dom << member["content"]
|
118
160
|
end
|
119
|
-
end
|
161
|
+
end
|
120
162
|
end
|
121
163
|
return dom.to_a
|
122
164
|
end
|
123
|
-
|
165
|
+
|
124
166
|
def explicit_dimensions_domains
|
125
167
|
dim_dom={}
|
126
168
|
if has_explicit_dimensions?
|
127
169
|
@segment["explicitMember"].each do |member|
|
128
170
|
dim_dom[member["dimension"]]=[] if dim_dom[member["dimension"]].nil?
|
129
171
|
dim_dom[member["dimension"]] << member["content"]
|
130
|
-
end
|
172
|
+
end
|
131
173
|
end
|
132
174
|
return dim_dom
|
133
175
|
end
|
134
|
-
|
176
|
+
|
135
177
|
end
|
136
|
-
|
137
|
-
class Identifier
|
138
|
-
attr_reader :value
|
139
|
-
|
178
|
+
|
179
|
+
class Identifier
|
180
|
+
attr_reader :value, :scheme
|
181
|
+
|
182
|
+
def initialize(scheme, value)
|
140
183
|
@scheme = scheme
|
141
184
|
@value = value
|
142
185
|
end
|
143
|
-
|
186
|
+
|
144
187
|
def to_s
|
145
|
-
"schema [" + @scheme.to_s + "], value [" + @value.to_s + "]"
|
188
|
+
"schema [" + @scheme.to_s + "], value [" + @value.to_s + "]"
|
146
189
|
end
|
147
190
|
end
|
148
191
|
end
|
data/lib/xbrlware/date_util.rb
CHANGED
@@ -21,15 +21,25 @@ module Xbrlware
|
|
21
21
|
module DateUtil # :nodoc:
|
22
22
|
def self.stringify_date (date)
|
23
23
|
return "" if date.nil?
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
24
|
+
begin
|
25
|
+
_date=Date.parse(date) if date.is_a?(String)
|
26
|
+
_date=date if date.is_a?(Date)
|
27
|
+
m=Date::ABBR_MONTHNAMES[_date.month]
|
28
|
+
m + " " + _date.day.to_s + ", " + _date.year.to_s
|
29
|
+
rescue Exception => e
|
30
|
+
""
|
31
|
+
end
|
28
32
|
end
|
29
33
|
|
30
34
|
def self.months_between(date1=Date.today, date2=Date.today)
|
31
|
-
|
32
|
-
|
35
|
+
begin
|
36
|
+
date1=Date.parse(date1) if date1.is_a?(String)
|
37
|
+
date2=Date.parse(date2) if date2.is_a?(String)
|
38
|
+
(date1 > date2) ? (recent_date, past_date = date1, date2) : (recent_date, past_date = date2, date1)
|
39
|
+
(recent_date.year - past_date.year) * 12 + (recent_date.month - past_date.month) + 1
|
40
|
+
rescue Exception => e
|
41
|
+
0
|
42
|
+
end
|
33
43
|
end
|
34
44
|
end
|
35
45
|
end
|
data/lib/xbrlware/instance.rb
CHANGED
@@ -58,6 +58,7 @@ module Xbrlware
|
|
58
58
|
end
|
59
59
|
|
60
60
|
@taxonomy=Xbrlware::Taxonomy.new(taxonomy_filepath, self)
|
61
|
+
@entity_details=Hash.new("UNKNOWN")
|
61
62
|
end
|
62
63
|
|
63
64
|
# Returns raw content of instance file in the form of Hash
|
@@ -190,9 +191,9 @@ module Xbrlware
|
|
190
191
|
# Returns -1 if period is forever
|
191
192
|
def period(period_content)
|
192
193
|
if period_content["startDate"] && period_content["endDate"]
|
193
|
-
return {"start_date" => period_content["startDate"][0]["content"], "end_date" => period_content["endDate"][0]["content"]}
|
194
|
+
return {"start_date" => Date.parse(period_content["startDate"][0]["content"]), "end_date" => Date.parse(period_content["endDate"][0]["content"])}
|
194
195
|
elsif period_content["instant"]
|
195
|
-
return period_content["instant"][0]["content"]
|
196
|
+
return Date.parse(period_content["instant"][0]["content"])
|
196
197
|
elsif period_content["forever"]
|
197
198
|
return Context::PERIOD_FOREVER
|
198
199
|
end
|
@@ -279,7 +280,7 @@ module Xbrlware
|
|
279
280
|
all_items.each do |name, item_content|
|
280
281
|
_name=name.upcase
|
281
282
|
next if _name=="CONTEXT" || _name=="UNIT"
|
282
|
-
items_hash[name.upcase] = item(name)
|
283
|
+
items_hash[name.upcase] = item(name)
|
283
284
|
end
|
284
285
|
items_hash
|
285
286
|
end
|
@@ -348,34 +349,40 @@ module Xbrlware
|
|
348
349
|
@item_footnote_map
|
349
350
|
end
|
350
351
|
|
352
|
+
def entity_details=(value)
|
353
|
+
@entity_details.merge!(value) if value.is_a?(Hash)
|
354
|
+
end
|
351
355
|
|
352
356
|
def entity_details
|
353
|
-
@entity_details={}
|
354
357
|
if @entity_details.size==0
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
358
|
+
begin
|
359
|
+
# Specific to US filing
|
360
|
+
e_name=item("EntityRegistrantName")[0]
|
361
|
+
e_ci_key=item("EntityCentralIndexKey")[0]
|
362
|
+
e_doc_type=item("DocumentType")[0]
|
363
|
+
e_doc_end_type=item("DocumentPeriodEndDate")[0]
|
364
|
+
|
365
|
+
fedate=item("CurrentFiscalYearEndDate")
|
366
|
+
e_fiscal_end_date=fedate[0] unless fedate.nil?
|
367
|
+
|
368
|
+
shares_outstanding = item("EntityCommonStockSharesOutstanding")
|
369
|
+
e_common_shares_outstanding=shares_outstanding[0] unless shares_outstanding.nil?
|
370
|
+
|
371
|
+
@entity_details["name"]=e_name.value unless e_name.nil?
|
372
|
+
@entity_details["ci_key"]=e_ci_key.value unless e_ci_key.nil?
|
373
|
+
@entity_details["doc_type"]=e_doc_type.value unless e_doc_type.nil?
|
374
|
+
@entity_details["doc_end_date"]=e_doc_end_type.value unless e_doc_end_type.nil?
|
375
|
+
@entity_details["fiscal_end_date"]=e_fiscal_end_date.value unless e_fiscal_end_date.nil?
|
376
|
+
@entity_details["common_shares_outstanding"]=e_common_shares_outstanding.value unless e_common_shares_outstanding.nil?
|
377
|
+
|
378
|
+
file_name=File.basename(@file_name)
|
379
|
+
symbol=file_name.split("-")[0]
|
380
|
+
symbol.upcase!
|
381
|
+
|
382
|
+
@entity_details["symbol"]=symbol unless symbol.nil?
|
383
|
+
rescue Exception => e
|
384
|
+
@entity_details
|
385
|
+
end
|
379
386
|
end
|
380
387
|
@entity_details
|
381
388
|
end
|
@@ -116,7 +116,7 @@ module Xbrlware
|
|
116
116
|
attr_reader :contexts, :entity_details
|
117
117
|
|
118
118
|
def initialize(entity_details, title, role, href=nil, arcs=nil, contexts=nil)
|
119
|
-
super(title, role, href, arcs)
|
119
|
+
super("Calculation", title, role, href, arcs)
|
120
120
|
@contexts=contexts
|
121
121
|
@entity_details=entity_details
|
122
122
|
end
|
@@ -151,7 +151,7 @@ module Xbrlware
|
|
151
151
|
attr_reader :primary_items
|
152
152
|
|
153
153
|
def initialize(title, role, href=nil, primary_items=nil)
|
154
|
-
super(title, role, href, primary_items)
|
154
|
+
super("Definition", title, role, href, primary_items)
|
155
155
|
@primary_items=primary_items
|
156
156
|
end
|
157
157
|
|
@@ -164,7 +164,7 @@ module Xbrlware
|
|
164
164
|
dimension.domains.each do |domain|
|
165
165
|
domains << domain.href.sub("_", ":")
|
166
166
|
end
|
167
|
-
dim_dom_map[dimension.href.sub("_", ":")]=domains
|
167
|
+
dim_dom_map[dimension.href.sub("_", ":")]=domains if domains.size > 0
|
168
168
|
end
|
169
169
|
end
|
170
170
|
end unless @primary_items.nil?
|
@@ -95,9 +95,10 @@ module Xbrlware
|
|
95
95
|
|
96
96
|
class Link
|
97
97
|
|
98
|
-
attr_reader :title, :role, :href, :arcs
|
98
|
+
attr_reader :link_type, :title, :role, :href, :arcs
|
99
99
|
|
100
|
-
def initialize(title, role, href, arcs=nil)
|
100
|
+
def initialize(link_type, title, role, href, arcs=nil)
|
101
|
+
@link_type=link_type
|
101
102
|
@role = role
|
102
103
|
@href = href
|
103
104
|
|
@@ -133,7 +133,7 @@ module Xbrlware
|
|
133
133
|
attr_reader :contexts, :definition, :instance, :timelines, :dimensions, :entity_details
|
134
134
|
|
135
135
|
def initialize(entity_details, title, role, href=nil, contexts=nil, arcs=nil, definition=nil, instance=nil, dimensions=[])
|
136
|
-
super(title, role, href, arcs)
|
136
|
+
super("Presentation", title, role, href, arcs)
|
137
137
|
@entity_details=entity_details
|
138
138
|
@contexts=contexts
|
139
139
|
@definition=definition
|
data/lib/xbrlware/meta_util.rb
CHANGED
@@ -0,0 +1,277 @@
|
|
1
|
+
module Xbrlware
|
2
|
+
|
3
|
+
#This class defines methods to generate HTML reports from XBRL documents.
|
4
|
+
class Report
|
5
|
+
|
6
|
+
PREF={}
|
7
|
+
|
8
|
+
def initialize(entity_details={}, pref={})
|
9
|
+
PREF.merge!(pref)
|
10
|
+
PREF["ITEM_FORMAT"]=lambda{|val| (BigDecimal(val)/1000000).round(4).to_s("F")} if PREF["ITEM_FORMAT"].nil?
|
11
|
+
PREF["ITEM_FORMAT_DESC"]=" in millions " if PREF["ITEM_FORMAT_DESC"].nil?
|
12
|
+
PREF["ITEM_FORMAT_EXCLUDE"] = ["EntityRegistrantName", "EntityCentralIndexKey", "DocumentType", "DocumentPeriodEndDate", "CurrentFiscalYearEndDate", "EntityCommonStockSharesOutstanding"] if PREF["ITEM_EXCLUDE"].nil?
|
13
|
+
@entity_details=entity_details
|
14
|
+
end
|
15
|
+
|
16
|
+
@@html_template = %{
|
17
|
+
<html>
|
18
|
+
<head>
|
19
|
+
<% if defined? reports_map && (not reports_map.nil?) %>
|
20
|
+
<title>
|
21
|
+
<%=reports_map["entity_details"]["symbol"].to_s + " :: " + reports_map["entity_details"]["doc_type"].to_s + " :: " + DateUtil.stringify_date(reports_map["entity_details"]["doc_end_date"]) + " :: Presentation & Calculation Reports"%>
|
22
|
+
</title>
|
23
|
+
<meta name="title" content="<%=reports_map["entity_details"]["symbol"].to_s + " :: " + reports_map["entity_details"]["doc_type"].to_s + " :: " + DateUtil.stringify_date(reports_map["entity_details"]["doc_end_date"]) + " :: Presentation & Calculation Reports"%>" />
|
24
|
+
<meta name="description" content="<%=reports_map["entity_details"]["name"].to_s + " ( " + reports_map["entity_details"]["symbol"].to_s + " ) :: " + reports_map["entity_details"]["doc_type"].to_s + " :: " + DateUtil.stringify_date(reports_map["entity_details"]["doc_end_date"]) + " :: Presentation & Calculation Reports" %>" />
|
25
|
+
<link rel="image_src" href="/static/<%=reports_map["entity_details"]["ci_key"].to_s + ".png"%>" / >
|
26
|
+
<% end %>
|
27
|
+
<meta name="Author" content="xbrlware (bitstat technologies)"/>
|
28
|
+
<style>
|
29
|
+
table, td {
|
30
|
+
border-color: #000000;
|
31
|
+
border-style: solid;
|
32
|
+
}
|
33
|
+
|
34
|
+
table {
|
35
|
+
border-width: 0 0 1px 1px;
|
36
|
+
border-spacing: 0;
|
37
|
+
border-collapse: collapse;
|
38
|
+
}
|
39
|
+
|
40
|
+
tr {
|
41
|
+
background-color: #FFC;
|
42
|
+
}
|
43
|
+
|
44
|
+
.tr_white_bg {
|
45
|
+
background-color: #FFFFFF;
|
46
|
+
}
|
47
|
+
|
48
|
+
td {
|
49
|
+
margin: 0;
|
50
|
+
padding: 4px;
|
51
|
+
border-width: 1px 1px 0 0;
|
52
|
+
|
53
|
+
font-family: 'Times New Roman','Times serif';
|
54
|
+
font-size: 10pt;
|
55
|
+
}
|
56
|
+
</style>
|
57
|
+
</head>
|
58
|
+
<body>
|
59
|
+
<table border="1">
|
60
|
+
<tr class="tr_white_bg">
|
61
|
+
<td><b>Entity</b></td>
|
62
|
+
<td><b>Presentation Reports</b></td>
|
63
|
+
<td><b>Calculation Reports</b></td>
|
64
|
+
</tr>
|
65
|
+
<% count=0 %>
|
66
|
+
<% @ins_report_map.each do |ins, reports_map| %>
|
67
|
+
<% if count % 2 == 0%>
|
68
|
+
<tr>
|
69
|
+
<% else %>
|
70
|
+
<tr class="tr_white_bg">
|
71
|
+
<% end %>
|
72
|
+
<% count=count+1 %>
|
73
|
+
<td>
|
74
|
+
<%=reports_map["entity_details"]["name"]%> (<%=reports_map["entity_details"]["symbol"]%>)
|
75
|
+
<br><%=reports_map["entity_details"]["doc_type"] + " : " + DateUtil.stringify_date(reports_map["entity_details"]["doc_end_date"])%>
|
76
|
+
</td>
|
77
|
+
<td valign="top">
|
78
|
+
<%=create_report_html(reports_map["pre"])%>
|
79
|
+
</td>
|
80
|
+
<td valign="top">
|
81
|
+
<%=create_report_html(reports_map["cal"])%>
|
82
|
+
</td>
|
83
|
+
</tr>
|
84
|
+
<% end %>
|
85
|
+
</table>
|
86
|
+
</body>
|
87
|
+
</html>
|
88
|
+
} # :nodoc:
|
89
|
+
|
90
|
+
private
|
91
|
+
def create_report_html(reports) # :nodoc:
|
92
|
+
return "" if reports.nil?
|
93
|
+
html_snipet=StringIO.new
|
94
|
+
reports.each do |title, report_files|
|
95
|
+
next if report_files.size==0
|
96
|
+
html_snipet << title << " "
|
97
|
+
report_files.each do |report_file|
|
98
|
+
html_snipet << "<a href='" << report_file << "'>"
|
99
|
+
html_snipet << File.extname(report_file).sub(".", "") << "</a> | "
|
100
|
+
end
|
101
|
+
html_snipet << "</br>"
|
102
|
+
end
|
103
|
+
html_snipet.string
|
104
|
+
end
|
105
|
+
|
106
|
+
public
|
107
|
+
# Takes path to folder that contains xbrl documents of entities. If the folder contains xbrl documents of single entity
|
108
|
+
# then HTML reports are generated for that entity. If there is need to generate reports for multiple entities then
|
109
|
+
# 1. Create root folder
|
110
|
+
# 2. Create subfolder for each entity inside root folder
|
111
|
+
# 3. The sub folders contains xbrl documents of the entity
|
112
|
+
# 4. File names of xbrl documents has to be in the following convention (if files are not in the convention mentioned below, you have to use gen_for method to generate reports)
|
113
|
+
# calculation linkbase document must end with _cal.xml
|
114
|
+
# definition linkbase document must end with _def.xml
|
115
|
+
# presentation linkbase document must end with _pre.xml
|
116
|
+
# label linkbase document must end with _lab.xml
|
117
|
+
# taxonomy file must end with .xsd
|
118
|
+
# instance document must end with .xml
|
119
|
+
# calling "gen" with root folder, will create reports for all entities under root folder
|
120
|
+
# detailed reports are stored under "reports" folder of the entity. If the "reports" doesn't exist, it
|
121
|
+
# will be created. Consolidated report of all generated reports is stored under root folder with name "edgar_report_index.html"
|
122
|
+
def gen(path_to_data_folder=".", report_for="pre|cal", report_type="html|xls|xml|json", verbose_flag="q")
|
123
|
+
@ins_report_map={}
|
124
|
+
files=xbrl_files(path_to_data_folder)
|
125
|
+
$LOG.info " Filtering xbrl files from folder [" + path_to_data_folder + "] done"
|
126
|
+
files.each do |file_map|
|
127
|
+
begin
|
128
|
+
@ins_report_map[file_map["ins"]]=gen_for(file_map, report_for, report_type, verbose_flag)
|
129
|
+
$LOG.info "Report generation for ["+file_map["ins"]+"] completed."
|
130
|
+
rescue Exception => e:
|
131
|
+
$LOG.fatal e.to_s
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
erb = ERB.new(@@html_template)
|
136
|
+
index_content=erb.result(get_binding)
|
137
|
+
File.open("master_report_index.html", 'w') {|f| f.write(index_content) }
|
138
|
+
|
139
|
+
rescue Exception => e:
|
140
|
+
$LOG.fatal e.to_s
|
141
|
+
end
|
142
|
+
|
143
|
+
private
|
144
|
+
def get_binding
|
145
|
+
binding
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
def xbrl_files(folder_path)
|
150
|
+
files=[]
|
151
|
+
presentation_files=Dir[folder_path+File::Separator+"**"+File::Separator+"*pre.xml"]
|
152
|
+
presentation_files.each do |pre_file|
|
153
|
+
files << Xbrlware::file_grep(File.dirname(pre_file))
|
154
|
+
end
|
155
|
+
files
|
156
|
+
end
|
157
|
+
|
158
|
+
private
|
159
|
+
def reports_content (link, report_type, verbose_flag)
|
160
|
+
reports_content={}
|
161
|
+
|
162
|
+
reports_content["html"]=link.to_html(verbose_flag) if report_type =~ /html|HTML/
|
163
|
+
reports_content["xls"]=link.to_xls if report_type =~ /xls|XLS/
|
164
|
+
reports_content["xml"]=link.to_xml if report_type =~ /xml|XML/
|
165
|
+
reports_content["json"]=link.to_json if report_type =~ /json|JSON/
|
166
|
+
reports_content["hash"]=link.to_hash if report_type =~ /hash|HASH/
|
167
|
+
|
168
|
+
return reports_content
|
169
|
+
end
|
170
|
+
|
171
|
+
private
|
172
|
+
def write_reports (links, report_dir, report_type, verbose_flag)
|
173
|
+
reports=HashUtil::OHash.new
|
174
|
+
links.each do |link|
|
175
|
+
reports_content=reports_content(link, report_type, verbose_flag)
|
176
|
+
report_name=link.title.gsub(/[^a-zA-Z0-9]/, "_")
|
177
|
+
report_files=[]
|
178
|
+
reports_content.each do |rtype, rcontent|
|
179
|
+
next if rcontent.nil?
|
180
|
+
extension = "." + rtype
|
181
|
+
report_dir = report_dir +File::Separator unless report_dir.end_with?(File::Separator)
|
182
|
+
report_file = report_dir+report_name+extension
|
183
|
+
File.open(report_file, 'w') {|f| f.write(rcontent) }
|
184
|
+
report_files << report_file
|
185
|
+
end
|
186
|
+
reports[link.title] = report_files
|
187
|
+
end
|
188
|
+
return reports
|
189
|
+
end
|
190
|
+
|
191
|
+
public
|
192
|
+
# Generates HTML reports from given Hash that contains files for instance, taxonomy, calculation, presentation, label, definition.
|
193
|
+
# Example of populating hash,
|
194
|
+
# files={}
|
195
|
+
# files["ins"] = "<instnace_file_path>"
|
196
|
+
# files["tax"] = "<taxonomy_file_path>"
|
197
|
+
# files["cal"] = "<calculation_linkbase_file_path>"
|
198
|
+
# files["pre"] = "<presentation_linkbase_file_path>"
|
199
|
+
# files["lab"] = "<label_linkbase_file_path>"
|
200
|
+
# files["def"] = "<definition_linkbase_file_path>"
|
201
|
+
# Generated HTML reports will be stored under "reports" folder of current dir. If the "reports" doesn't exist, it
|
202
|
+
# will be created. If "cal" is passed as null, calculation linkbase path from taxonomy will be used. Same for other
|
203
|
+
# linkbases too (ie, "pre", "lab" and "def".)
|
204
|
+
def gen_for (file_map, report_for="pre|cal", report_type="html|xls|xml|json", verbose_flag="q", report_dir=nil, meta_gen=true)
|
205
|
+
ins_file=file_map["ins"]
|
206
|
+
tax_file=file_map["tax"]
|
207
|
+
cal_file=file_map["cal"]
|
208
|
+
pre_file=file_map["pre"]
|
209
|
+
lab_file=file_map["lab"]
|
210
|
+
def_file=file_map["def"]
|
211
|
+
|
212
|
+
reports_map={}
|
213
|
+
|
214
|
+
instance=nil
|
215
|
+
m=Benchmark.measure do
|
216
|
+
instance = Instance.new(ins_file, tax_file)
|
217
|
+
taxonomy=instance.taxonomy
|
218
|
+
taxonomy.init_all_lb(cal_file, pre_file, lab_file, def_file)
|
219
|
+
end
|
220
|
+
bm(" Initializing xbrl took", m)
|
221
|
+
|
222
|
+
instance.entity_details=@entity_details
|
223
|
+
reports_map["entity_details"]=instance.entity_details
|
224
|
+
reports_map["instance"]=instance
|
225
|
+
|
226
|
+
report_dir = (File.expand_path(File.dirname(ins_file)) + File::Separator + "report" + File::Separator) if report_dir.nil?
|
227
|
+
File.makedirs(report_dir) unless File.directory?(report_dir)
|
228
|
+
|
229
|
+
if report_for =~ /pre/ && (not instance.taxonomy.prelb.nil?)
|
230
|
+
links=instance.taxonomy.prelb.presentation
|
231
|
+
pre_dir = report_dir + "pre"
|
232
|
+
File.makedirs(pre_dir) unless File.directory?(pre_dir)
|
233
|
+
reports_map["pre"]=write_reports(links, pre_dir, report_type, verbose_flag)
|
234
|
+
end
|
235
|
+
|
236
|
+
if report_for =~ /cal/ && (not instance.taxonomy.callb.nil?)
|
237
|
+
links=instance.taxonomy.callb.calculation
|
238
|
+
cal_dir = report_dir + "cal"
|
239
|
+
File.makedirs(cal_dir) unless File.directory?(cal_dir)
|
240
|
+
reports_map["cal"]=write_reports(links, cal_dir, report_type, verbose_flag)
|
241
|
+
end
|
242
|
+
|
243
|
+
_tmp = @ins_report_map
|
244
|
+
|
245
|
+
erb = ERB.new(@@html_template)
|
246
|
+
index_content=erb.result(lambda do
|
247
|
+
@ins_report_map={}
|
248
|
+
@ins_report_map[file_map["ins"]]=reports_map
|
249
|
+
lambda {}
|
250
|
+
end.call)
|
251
|
+
|
252
|
+
@ins_report_map = _tmp
|
253
|
+
|
254
|
+
# str_ci_key=reports_map["entity_details"]["ci_key"]
|
255
|
+
# str_doc_end_date=reports_map["entity_details"]["doc_end_date"]
|
256
|
+
# str_doc_end_date="" if str_doc_end_date.nil?
|
257
|
+
# str_doc_end_date.gsub!("-", "")
|
258
|
+
# report_index_file = report_dir + str_ci_key+"_"+str_doc_end_date+"_report.html"
|
259
|
+
|
260
|
+
report_index_file = report_dir + "report_index.html"
|
261
|
+
File.open( report_index_file, 'w') {|f| f.write(index_content) }
|
262
|
+
|
263
|
+
reports_map["report_index_file"]=report_index_file
|
264
|
+
|
265
|
+
if meta_gen
|
266
|
+
meta_file_name = report_dir + "meta.json"
|
267
|
+
meta_gen_content = reports_map.reject {|k, v| k=="instance"}.to_json.to_s
|
268
|
+
File.open( meta_file_name, 'w') {|f| f.write(meta_gen_content) }
|
269
|
+
reports_map["report_meta_file"]=meta_file_name
|
270
|
+
end
|
271
|
+
|
272
|
+
reports_map
|
273
|
+
rescue Exception => e
|
274
|
+
raise " Report generation failed for instance " + ins_file + "\n #{e.to_s + "\n" + e.backtrace.join("\n ")}"
|
275
|
+
end
|
276
|
+
end
|
277
|
+
end
|