Clean up master.
[working/Evergreen.git] / reports / report-add-data-source.xml
1 <?xml version="1.0" encoding="utf-8"?>
2 <chapter version="5.0" xml:id="add-data-source" xml:lang="EN"
3          xmlns="http://docbook.org/ns/docbook"
4          xmlns:xlink="http://www.w3.org/1999/xlink"
5          xmlns:xi="http://www.w3.org/2001/XInclude"
6          xmlns:ns5="http://www.w3.org/1998/Math/MathML"
7          xmlns:ns4="http://www.w3.org/2000/svg"
8          xmlns:ns3="http://www.w3.org/1999/xhtml"
9          xmlns:ns="http://docbook.org/ns/docbook">
10   <info>
11     <title>Adding Data Sources to Reporter</title>
12   </info>
13
14   <para>You can further customize your Evergreen reporting environment by
15   adding additional data sources.</para>
16
17   <para>The Evergreen reporter module does not build and execute SQL queries
18   directly, but instead uses a data abstraction layer called Fieldmapper to
19   mediate queries on the Evergreen database. Fieldmapper is also used by other
20   core Evergreen DAO services, including cstore and permacrud. The
21   configuration file fm_IDL.xml contains the mapping between Fieldmapper class
22   definitions and the database. The fm_IDL.xml file is located in the
23   /openils/conf directory.</para>
24
25   <para>There are 3 basic steps to adding a new data source. Each step will be
26   discussed in more detail in the</para>
27
28   <orderedlist>
29     <listitem>
30       <para>Create a PostgreSQL query, view, or table that will provide the
31       data for your data source.</para>
32     </listitem>
33
34     <listitem>
35       <para>Add a new class to fm_IDL.xml for your data source.</para>
36     </listitem>
37
38     <listitem>
39       <para>Restart the affected services to see the new data source in
40       Reporter.</para>
41     </listitem>
42   </orderedlist>
43
44   <para>There are two possbile sources for new data sources:</para>
45
46   <itemizedlist>
47     <listitem>
48       <para>An SQL query built directly into the class definition in
49       fm_IDL.xml. You can use this method if you are only going to access this
50       data source through the Evergreen reporter and/or cstore code that you
51       write.</para>
52     </listitem>
53
54     <listitem>
55       <para>A new table or view in the Evergreen PostgresSQL database on which
56       a class definition in fm_IDL.xml. You can use this method if you want to
57       be able to access this data source through directly through SQL or using
58       other reporting tool.</para>
59     </listitem>
60   </itemizedlist>
61
62   <section>
63     <title>Create a PostgreSQL query, view, or table that will provide the
64     data for your data source</title>
65
66     <para>You need to decide whether you will create your data source as a
67     query, a view, or a table.</para>
68
69     <itemizedlist>
70       <listitem>
71         <para>Create a <emphasis>query</emphasis> if you are planning to
72         access this data source only through the Evergreen reporter and/or
73         cstore code that you write. You will use this query to create an IDL
74         only view.</para>
75       </listitem>
76
77       <listitem>
78         <para>Create a <emphasis>view</emphasis> if you are planning to access
79         this data source through other methods in addition to the Evergreen
80         reporter, or if you may need to do performance tuning to optimize your
81         query.</para>
82       </listitem>
83
84       <listitem>
85         <para>You may also need to use an additional
86         <emphasis>table</emphasis> as part of your data source if you have
87         additional data that's not included in the base Evergreen, or if you
88         need to use a table to store the results of a query for performance
89         reasons.</para>
90       </listitem>
91     </itemizedlist>
92
93     <para>To develop and test queries, views, and tables, you will need</para>
94
95     <itemizedlist>
96       <listitem>
97         <para>Access to the Evergree PostgreSQL database at the command line.
98         This is normally the psql application. For introductory information,
99         please see <xref linkend="intro_to_sql" />. You can access the
100         Postgres documentation at the <link
101         xlink:href="http://www.postgresql.org/docs/">Official Postgres
102         documentation</link> for more information about PostgreSQL.</para>
103       </listitem>
104
105       <listitem>
106         <para>Knowledge of the Evergreen database structure for the data that
107         you want to access. You can find this information by looking at the
108         Evergreen schema - see <xref linkend="databaseschema" /> and <xref
109         linkend="data_models_and_access" /></para>
110       </listitem>
111     </itemizedlist>
112
113     <para>If the views that you are creating are purely local in usage are are
114     intended for contribution to the core Evergreen code, create the Views and
115     Tables in the extend_reporter schema. This schema is intended to be used
116     for local customizations and will not be modified during upgrades to the
117     Evergreen system.</para>
118
119     <para>You should make that you have an appropriate version control pocess
120     for the SQL used to create you data sources.</para>
121
122     <para>Here's an example of a view created to incorporate some locally
123     defined user statistical categories.<programlisting>create view extend_reporter.patronstats as
124 select u.id, 
125 grp.name as "ptype",
126 rl.stat_cat_entry as "reg_lib",
127 gr.stat_cat_entry as "gender",
128 ag.stat_cat_entry as "age_group",
129 EXTRACT(YEAR FROM age(u.dob)) as "age",
130 hl.id as "home_lib",
131 u.create_date,
132 u.expire_date,
133 ms_balance_owed
134 from actor.usr u
135 join permission.grp_tree grp on (u.profile = grp.id and (grp.parent = 2 or grp.name = 'patron')) 
136 join actor.org_unit hl on (u.home_ou = hl.id)
137 left join money.open_usr_summary ms on (ms.usr = u.id) 
138 left join actor.stat_cat_entry_usr_map rl on (u.id = rl.target_usr and rl.stat_cat = 4) 
139 left join actor.stat_cat_entry_usr_map bt on (u.id = bt.target_usr and bt.stat_cat = 3) 
140 left join actor.stat_cat_entry_usr_map gr on (u.id = gr.target_usr and gr.stat_cat = 2) 
141 left join actor.stat_cat_entry_usr_map gr on (u.id = gr.target_usr and gr.stat_cat = 2) 
142 left join actor.stat_cat_entry_usr_map ag on (u.id = ag.target_usr and ag.stat_cat = 1) 
143 where u.active = 't' and u.deleted &lt;&gt; 't';
144 </programlisting></para>
145   </section>
146
147   <section>
148     <title>Add a new class to fm_IDL.xml for your data source</title>
149
150     <para>Once you have your data source, the next step is to add that data
151     source as a new class in fm_IDL.xml. </para>
152
153     <para>You will need to add the following attributes for the class
154     definition</para>
155
156     <itemizedlist>
157       <listitem>
158         <para><emphasis>id.</emphasis> You should follow a consistent naming
159         convention for your class names that won't create conflicts in the
160         future with any standard classes added in future upgrades. Evergreen
161         normally names each class with the first letter of each word in the
162         schema and table names. You may want to add a local prefix or suffix
163         to your local class names.</para>
164       </listitem>
165
166       <listitem>
167         <para><emphasis>controller=”open-ils.cstore”</emphasis></para>
168       </listitem>
169
170       <listitem>
171         <para><emphasis>oils_obj:fieldmapper</emphasis>=”extend_reporter::long_name_of_view”</para>
172       </listitem>
173
174       <listitem>
175         <para><emphasis>oils_persist.readonly</emphasis>=”true”</para>
176       </listitem>
177
178       <listitem>
179         <para><emphasis>reporter:core</emphasis>=”true” (if you want this to
180         show up as a “core” reporting source)</para>
181       </listitem>
182
183       <listitem>
184         <para><emphasis>reporter</emphasis>:label. This is the name that will
185         appear on the data source list in the Evergreen reporter.</para>
186       </listitem>
187
188       <listitem>
189         <para><emphasis>oils_persist:source_definition</emphasis>. If this is
190         an IDL-only view, add the SQL query here. You don't need this
191         attribute if your class is based on a PostgreSQL view or table.</para>
192       </listitem>
193
194       <listitem>
195         <para><emphasis>oils_persist:tablename=</emphasis>"schemaname.viewname
196         or tablename" If this class is based on a PostgreSQL view or table,
197         add the table name here. You don't need this attribute is your class
198         is an IDL-only view.</para>
199       </listitem>
200     </itemizedlist>
201
202     <para>For each column in the view or query output, add
203     <emphasis>field</emphasis> element and set the following attributes. The
204     fields should be wrapped with &lt;field&gt; &lt;/field&gt; </para>
205
206     <itemizedlist>
207       <listitem>
208         <para>reporter:label. This is the name that appears in the Evergreen
209         reporter.</para>
210       </listitem>
211
212       <listitem>
213         <para>name. This should match the column name in the view or query
214         output.</para>
215       </listitem>
216
217       <listitem>
218         <para>reporter:datatype (which can be id, bool, money, org_unit, int,
219         number, interval, float, text, timestamp, or link)</para>
220       </listitem>
221     </itemizedlist>
222
223     <para>For each linking field, add a <emphasis>link</emphasis> element with
224     the following attributes. The elements should be wrapped with &lt;link&gt;
225     &lt;/link&gt;</para>
226
227     <itemizedlist>
228       <listitem>
229         <para>field (should match field.name)</para>
230       </listitem>
231
232       <listitem>
233         <para>reltype (“has_a”, “might_have”, or “has_many”)</para>
234       </listitem>
235
236       <listitem>
237         <para>map (“”)</para>
238       </listitem>
239
240       <listitem>
241         <para>key (name of the linking field in the foreign table)</para>
242       </listitem>
243
244       <listitem>
245         <para>class (ID of the IDL class of the table that is to be linked
246         to)</para>
247       </listitem>
248     </itemizedlist>
249
250     <para>The following example is a class definition for the example view
251     that was created in the previous section.</para>
252
253     <para><programlisting>&lt;class id="erpstats" controller="open-ils.reporter-store" oils_obj:fieldmapper="extend_reporter::patronstats" oils_persist:tablename="extend_reporter.patronstats" oils_persist:readonly="true" reporter:label="Patron Statistics" reporter:core="true"&gt;
254   &lt;fields oils_persist:primary="id"&gt;
255   &lt;field reporter:label="Patron ID" name="id" reporter:datatype="link" /&gt;
256   &lt;field reporter:label="Patron Type" name="ptype" reporter:datatype="text" /&gt;
257   &lt;field reporter:label="Reg Lib" name="reg_lib" reporter:datatype="text" /&gt;
258   &lt;field reporter:label="Boro/Twp" name="boro_twp" reporter:datatype="text" /&gt;
259   &lt;field reporter:label="Gender" name="gender" reporter:datatype="text" /&gt;
260   &lt;field reporter:label="Age Group" name="age_group" reporter:datatype="text" /&gt;
261   &lt;field reporter:label="Age" name="age" reporter:datatype="int" /&gt;
262   &lt;field reporter:label="Home Lib ID" name="home_lib_id" reporter:datatype="link" /&gt;
263   &lt;field reporter:label="Home Lib Code" name="home_lib_code" reporter:datatype="text" /&gt;
264   &lt;field reporter:label="Home Lib" name="home_lib" reporter:datatype="text" /&gt;
265   &lt;field reporter:label="Create Date" name="create_date" reporter:datatype="timestamp" /&gt;
266   &lt;field reporter:label="Expire Date" name="expire_date" reporter:datatype="timestamp" /&gt;
267   &lt;field reporter:label="Balance Owed" name="balance_owed" reporter:datatype="money" /&gt;
268 &lt;/fields&gt;
269 &lt;links&gt;
270   &lt;link field="id" reltype="has_a" key="id" map="" class="au"/&gt;
271   &lt;link field="home_lib_id" reltype="has_a" key="id" map="" class="aou"/&gt;
272 &lt;/links&gt;
273 &lt;/class&gt;</programlisting><caution>
274         <para>fm_IDL.xml is used by other core Evergreen DAO services,
275         including cstore and permacrud. So changes to this file can affect the
276         entire Evergreen application, not just reporter. After making changes
277         fm_IDL.xml, it is a good idea to ensure that it is valid XML by using
278         a utility such as xmllint – a syntax error can render much of
279         Evergreen nonfunctional. Set up a good change control system for any
280         changes to fm_IDL.xml. You will need to keep a separate copy of you
281         local class definitions so that you can reapply the changes to
282         fm_IDL.xml after Evergreen upgrades.</para>
283       </caution></para>
284   </section>
285
286   <section>
287     <title>Restart the affected services to see the new data source in the
288     reporter</title>
289
290     <para>The following steps are needed to for Evergreen to recognize the
291     changes to fm_IDL.xml</para>
292
293     <orderedlist>
294       <listitem>
295         <para>Copy the updated fm_IDL.xml Update /openils/conf/fm_IDL.xml to
296         /openils/var/web/reports/fm_IDL.xml<programlisting>cp /openils/conf/fm_IDL.xml /openils/var/web/reports/fm_IDL.xml</programlisting></para>
297       </listitem>
298
299       <listitem>
300         <para>Run Autogen to to update the Javascript versions of the
301         fieldmapper definitions.</para>
302
303         <programlisting>/openils/bin/autogen.sh</programlisting>
304       </listitem>
305
306       <listitem>
307         <para>Restart C services<programlisting>osrf_ctl.sh -l -a restart_c</programlisting></para>
308       </listitem>
309
310       <listitem>
311         <para>Restart the Evergreen reporter. You may need to modify this
312         command depending on your system configuration and pid
313         path<programlisting>opensrf-perl.pl -l -action restart -service open-ils.reporter -config /openils/conf/opensrf_core.xml -pid-dir /openils/var/run</programlisting></para>
314       </listitem>
315
316       <listitem>
317         <para>Restart the Evergreen application or use Admin, For Developers,
318         Clear Cache</para>
319       </listitem>
320     </orderedlist>
321   </section>
322 </chapter>