Bug 5869 : Adding a reserve report
authorPaul Poulain <paul.poulain@biblibre.com>
Tue, 15 Mar 2011 17:00:17 +0000 (13:00 -0400)
committerChris Cormack <chrisc@catalyst.net.nz>
Thu, 17 Mar 2011 01:33:08 +0000 (14:33 +1300)
Signed-off-by: Nicole C. Engard <nengard@bywatersolutions.com>
Signed-off-by: Chris Cormack <chrisc@catalyst.net.nz>
koha-tmpl/intranet-tmpl/prog/en/modules/reports/reports-home.tmpl
koha-tmpl/intranet-tmpl/prog/en/modules/reports/reserves_stats.tmpl [new file with mode: 0644]
reports/reserves_stats.pl [new file with mode: 0755]

index b2d8487..7c6efae 100644 (file)
@@ -34,6 +34,7 @@
                <li><a href="/cgi-bin/koha/reports/catalogue_stats.pl">Catalog</a></li>
                <li><a href="/cgi-bin/koha/reports/issues_stats.pl">Circulation</a></li>
                <li><a href="/cgi-bin/koha/reports/serials_stats.pl">Serials</a></li>
+               <li><a href="/cgi-bin/koha/reports/reserves_stats.pl">Reserves</a></li>
        </ul></div>
 
        <div class="yui-u"><h2>Top Lists</h2>
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reserves_stats.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reserves_stats.tmpl
new file mode 100644 (file)
index 0000000..2b78133
--- /dev/null
@@ -0,0 +1,549 @@
+<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
+<title>Koha &rsaquo; Reports &rsaquo; Checkout statistics <!-- TMPL_IF NAME="do_it" -->&rsaquo; Results<!-- /TMPL_IF --></title>
+<!-- TMPL_INCLUDE NAME="doc-head-close.inc" -->
+<!-- TMPL_INCLUDE NAME="calendar.inc" -->
+<style type="text/css">
+       .sql {display:none;}
+</style>
+</head>
+<body>
+<!-- TMPL_INCLUDE NAME="header.inc" -->
+<!-- TMPL_INCLUDE NAME="cat-search.inc" -->
+
+<div id="breadcrumbs"><a href="/cgi-bin/koha/mainpage.pl">Home</a> &rsaquo; <a href="/cgi-bin/koha/reports/reports-home.pl">Reports</a> <!-- TMPL_IF NAME="do_it" -->&rsaquo; <a href="/cgi-bin/koha/reports/reserves_stats.pl">Reserves statistics</a> &rsaquo; Results <!-- TMPL_ELSE -->&rsaquo; Reserves statistics<!-- /TMPL_IF --></div>
+
+<div id="doc3" class="yui-t2">
+
+   <div id="bd">
+       <div id="yui-main">
+       <div class="yui-b">
+
+<!-- TMPL_IF NAME="do_it" -->
+    <!-- TMPL_IF NAME="mainloop" -->
+        <h1>Reserves statistics</h1>
+        <!-- TMPL_IF NAME="loopfilter" -->
+            <p>Filtered on</p>
+            <ul>
+            <!-- TMPL_LOOP NAME="loopfilter" -->
+                <!-- TMPL_IF NAME="err" --><li class="error">Error:
+                               <!-- TMPL_ELSIF NAME="sql" --><li class="sql">
+                               <!-- TMPL_ELSE --><li>
+                               <!--/TMPL_IF -->
+                                       <!-- TMPL_VAR NAME="crit"--> <!-- TMPL_VAR NAME="filter"-->
+                               </li>
+            <!-- /TMPL_LOOP -->
+            </ul>
+        <!-- /TMPL_IF -->
+               
+    <!-- TMPL_LOOP NAME="mainloop" -->
+        
+        <table> 
+            <tr>
+                <th><!-- TMPL_VAR name="line" --> / <!-- TMPL_VAR name="column" --></th>
+                <!-- TMPL_LOOP NAME="loopcol" -->
+                    <th><!-- TMPL_VAR ESCAPE="HTML" NAME="coltitle_display" --></th>
+                <!-- /TMPL_LOOP -->
+                <th>TOTAL</th>
+                </tr>
+                <!-- TMPL_LOOP NAME="looprow" -->
+                    <tr<!-- TMPL_UNLESS NAME="__odd__" --> class="highlight"<!-- /TMPL_UNLESS -->>
+                        <td><!-- TMPL_VAR ESCAPE="HTML" NAME="rowtitle_display" DEFAULT="UNKNOWN VALUE" --></td>
+                    <!-- TMPL_LOOP NAME="loopcell" -->
+                                               <td align="center">
+                                               <!--TMPL_IF Name="url_complement"--><a href="reserves_stats.pl?output=<!--TMPL_VAR Name=output-->&amp;<!--TMPL_VAR Name="url_complement"-->"><!-- TMPL_VAR NAME="value" DEFAULT="&nbsp;" --></a><!--TMPL_ELSE--><!-- TMPL_VAR NAME="value" DEFAULT="&nbsp;" --><!--/TMPL_IF-->
+                                               </td>
+                    <!-- /TMPL_LOOP -->
+                                               <td align="center"><!-- TMPL_VAR NAME="totalrow" --></td>
+                    </tr>
+                <!-- /TMPL_LOOP -->
+            <tr>
+                <th>TOTAL</th>
+                <!-- TMPL_LOOP NAME="loopfooter" -->
+                <th><!-- TMPL_VAR NAME="totalcol" --></th>
+                <!-- /TMPL_LOOP -->
+                <th><!-- TMPL_VAR NAME="total" --></th>
+            </tr>
+        </table>
+    <!-- /TMPL_LOOP -->
+    <!-- /TMPL_IF -->
+<!-- TMPL_ELSE -->
+
+    <form method="post" action="/cgi-bin/koha/reports/reserves_stats.pl">
+    <fieldset class="rows">
+       <legend>Reserve statistics</legend><table>
+        <thead>
+            <tr>
+                <th>Title</th>
+                <th>Row</th>
+                <th>Column</th>
+                <th>Filter</th>
+            </tr>
+        </thead>
+        <tbody>
+               <tr >
+                <td>Reserve status </td>
+                <td><input type="radio" name="Line" value="reservestatus" /></td>
+                <td><input type="radio" name="Column" value="reservestatus" checked="checked" /></td>
+                <td>
+                               <input type="checkbox" name="filter_reservestatus_or_1" value="1">Asked</input>
+                               <input type="checkbox" name="filter_reservestatus_or_2" value="2"> Processing</input>
+                               <input type="checkbox" name="filter_reservestatus_or_3" value="3">Waiting</input>
+                               <input type="checkbox" name="filter_reservestatus_or_4" value="4">Satisfied</input>
+                               <input type="checkbox" name="filter_reservestatus_or_5" value="5">cancelled</input>
+                               </td>
+             </tr>
+             <tr class="highlight">
+                <td>reserve date</td>
+                <td><input type="radio" name="Line" value="reservedate" /></td>
+                <td><input type="radio" name="Column" value="reservedate" /></td>
+                <td><label for="reservedate_begin">From</label> <input type="text"  size="10" id="filter_reservedate_begin" name="filter_reservedate_begin" />
+                    <img src="<!-- TMPL_VAR Name="themelang" -->/lib/calendar/cal.gif" alt="Show Calendar" border="0" id="openreservedateFrom" style="cursor: pointer;" />
+                   <script type="text/javascript">
+                                  //<![CDATA[ 
+                                  function validate1(date) {
+                        var day = date.getDate();
+                        var month = date.getMonth() + 1;
+                        var year = date.getFullYear();
+                        var weekDay = date.getDay();
+                        var dayMonth = month + '-' + day;
+                        var dateString = year + '-' + month + '-' + day;
+                        var dateTo = document.getElementById('filter_reservedate_end').value.split("-");
+                        var limitDate = new Date(dateTo[0], (dateTo[1] - 1), dateTo[2]);
+                        if (date > limitDate) {
+                             return true;
+                        } else {
+                             return false;
+                        }
+                    }
+                    Calendar.setup({
+                            inputField : "filter_reservedate_begin",
+                            ifFormat : "<!-- TMPL_VAR NAME="DHTMLcalendar_dateformat" -->",
+                            button : "openreservedateFrom",
+                            disableFunc : validate1,
+                            dateStatusFunc : validate1
+                    });
+                                       //]]>
+                                       </script>
+                    <label for="filter_reservedate_end">To</label> <input size="10" id="filter_reservedate_end" name="filter_reservedate_end" value="" type="text" />
+                    <img src="<!-- TMPL_VAR Name="themelang" -->/lib/calendar/cal.gif" alt="Show Calendar" id="openreservedateTo" style="cursor: pointer;" border="0" />
+                    <script type="text/javascript">
+                                       //<![CDATA[  
+                                       function validate2(date) {
+                         var day = date.getDate();
+                         var month = date.getMonth() + 1;
+                         var year = date.getFullYear();
+                         var weekDay = date.getDay();
+                         var dayMonth = month + '-' + day;
+                         var dateString = year + '-' + month + '-' + day;
+                         var dateFrom = document.getElementById('filter_reservedate_begin').value.split("-");
+                         var limitDate = new Date(dateFrom[0], (dateFrom[1] - 1), dateFrom[2]);
+                         if (limitDate > date) {
+                              return true;
+                         } else {
+                              return false;
+                         }
+                     }
+                     Calendar.setup({
+                             inputField : "filter_reservedate_end",
+                             ifFormat : "<!-- TMPL_VAR NAME="DHTMLcalendar_dateformat" -->",
+                             button : "openreservedateTo",
+                             disableFunc : validate2,
+                             dateStatusFunc : validate2
+                     });
+                                       //]]>
+                                       </script>
+                    </td>
+                </tr>
+            <tr>
+                <td>notification date</td>
+                <td><input type="radio" name="Line" value="notificationdate" /></td>
+                <td><input type="radio" name="Column" value="notificationdate" /></td>
+                <td><label for="filter_notificationdate_begin">From</label> <input type="text"  size="10" id="filter_notificationdate_begin" name="filter_notificationdate_begin" />
+                    <img src="<!-- TMPL_VAR Name="themelang" -->/lib/calendar/cal.gif" alt="Show Calendar" border="0" id="opennotificationdateFrom" style="cursor: pointer;" />
+                   <script type="text/javascript">
+                                  //<![CDATA[ 
+                                  function validate1(date) {
+                        var day = date.getDate();
+                        var month = date.getMonth() + 1;
+                        var year = date.getFullYear();
+                        var weekDay = date.getDay();
+                        var dayMonth = month + '-' + day;
+                        var dateString = year + '-' + month + '-' + day;
+                        var dateTo = document.getElementById('filter_notificationdate_end').value.split("-");
+                        var limitDate = new Date(dateTo[0], (dateTo[1] - 1), dateTo[2]);
+                        if (date > limitDate) {
+                             return true;
+                        } else {
+                             return false;
+                        }
+                    }
+                    Calendar.setup({
+                            inputField : "filter_notificationdate_begin",
+                            ifFormat : "<!-- TMPL_VAR NAME="DHTMLcalendar_dateformat" -->",
+                            button : "opennotificationdateFrom",
+                            disableFunc : validate1,
+                            dateStatusFunc : validate1
+                    });
+                                       //]]>
+                                       </script>
+                    <label for="filter_notificationdate_end">To</label> <input  size="10" id="filter_notificationdate_end" name="filter_notificationdate_end" value="" type="text" />
+                    <img src="<!-- TMPL_VAR Name="themelang" -->/lib/calendar/cal.gif" alt="Show Calendar" id="opennotificationdateTo" style="cursor: pointer;" border="0" />
+                    <script type="text/javascript">
+                                       //<![CDATA[  
+                                       function validate2(date) {
+                         var day = date.getDate();
+                         var month = date.getMonth() + 1;
+                         var year = date.getFullYear();
+                         var weekDay = date.getDay();
+                         var dayMonth = month + '-' + day;
+                         var dateString = year + '-' + month + '-' + day;
+                         var dateFrom = document.getElementById('filter_notificationdate_begin').value.split("-");
+                         var limitDate = new Date(dateFrom[0], (dateFrom[1] - 1), dateFrom[2]);
+                         if (limitDate > date) {
+                              return true;
+                         } else {
+                              return false;
+                         }
+                     }
+                     Calendar.setup({
+                             inputField : "filter_notificationdate_end",
+                             ifFormat : "<!-- TMPL_VAR NAME="DHTMLcalendar_dateformat" -->",
+                             button : "opennotificationdateTo",
+                             disableFunc : validate2,
+                             dateStatusFunc : validate2
+                     });
+                                       //]]>
+                                       </script>
+                    </td>
+             </tr>
+            <tr>
+                <td>Reminder date</td>
+                <td><input type="radio" name="Line" value="reminderdate" /></td>
+                <td><input type="radio" name="Column" value="reminderdate" /></td>
+                <td><label for="filter_reminderdate_begin">From</label> <input type="text"  size="10" id="filter_reminderdate_begin" name="Filter" />
+                    <img src="<!-- TMPL_VAR Name="themelang" -->/lib/calendar/cal.gif" alt="Show Calendar" border="0" id="openreminderdateFrom" style="cursor: pointer;" />
+                   <script type="text/javascript">
+                                  //<![CDATA[ 
+                                  function validate1(date) {
+                        var day = date.getDate();
+                        var month = date.getMonth() + 1;
+                        var year = date.getFullYear();
+                        var weekDay = date.getDay();
+                        var dayMonth = month + '-' + day;
+                        var dateString = year + '-' + month + '-' + day;
+                        var dateTo = document.getElementById('filter_reminderdate_end').value.split("-");
+                        var limitDate = new Date(dateTo[0], (dateTo[1] - 1), dateTo[2]);
+                        if (date > limitDate) {
+                             return true;
+                        } else {
+                             return false;
+                        }
+                    }
+                    Calendar.setup({
+                            inputField : "filter_reminderdate_begin",
+                            ifFormat : "<!-- TMPL_VAR NAME="DHTMLcalendar_dateformat" -->",
+                            button : "openreminderdateFrom",
+                            disableFunc : validate1,
+                            dateStatusFunc : validate1
+                    });
+                                       //]]>
+                                       </script>
+                    <label for="filter_reminderdate_end">To</label> <input size="10" id="filter_reminderdate_end" name="filter_reminderdate_end" value="" type="text" />
+                    <img src="<!-- TMPL_VAR Name="themelang" -->/lib/calendar/cal.gif" alt="Show Calendar" id="openreminderdateTo" style="cursor: pointer;" border="0" />
+                    <script type="text/javascript">
+                                       //<![CDATA[  
+                                       function validate2(date) {
+                         var day = date.getDate();
+                         var month = date.getMonth() + 1;
+                         var year = date.getFullYear();
+                         var weekDay = date.getDay();
+                         var dayMonth = month + '-' + day;
+                         var dateString = year + '-' + month + '-' + day;
+                         var dateFrom = document.getElementById('filter_reminderdate_begin').value.split("-");
+                         var limitDate = new Date(dateFrom[0], (dateFrom[1] - 1), dateFrom[2]);
+                         if (limitDate > date) {
+                              return true;
+                         } else {
+                              return false;
+                         }
+                     }
+                     Calendar.setup({
+                             inputField : "filter_reminderdate_end",
+                             ifFormat : "<!-- TMPL_VAR NAME="DHTMLcalendar_dateformat" -->",
+                             button : "openreminderdateTo",
+                             disableFunc : validate2,
+                             dateStatusFunc : validate2
+                     });
+                                       //]]>
+                                       </script>
+                    </td>
+             </tr>
+            <tr>
+                <td>Waiting date</td>
+                <td><input type="radio" name="Line" value="waitingdate" /></td>
+                <td><input type="radio" name="Column" value="waitingdate" /></td>
+                <td><label for="filter_waitingdate_begin">From</label> <input type="text"  size="10" id="filter_waitingdate_begin" name="filter_waitingdate_begin" />
+                    <img src="<!-- TMPL_VAR Name="themelang" -->/lib/calendar/cal.gif" alt="Show Calendar" border="0" id="openwaitingdateFrom" style="cursor: pointer;" />
+                   <script type="text/javascript">
+                                  //<![CDATA[ 
+                                  function validate1(date) {
+                        var day = date.getDate();
+                        var month = date.getMonth() + 1;
+                        var year = date.getFullYear();
+                        var weekDay = date.getDay();
+                        var dayMonth = month + '-' + day;
+                        var dateString = year + '-' + month + '-' + day;
+                        var dateTo = document.getElementById('filter_waitingdate_end').value.split("-");
+                        var limitDate = new Date(dateTo[0], (dateTo[1] - 1), dateTo[2]);
+                        if (date > limitDate) {
+                             return true;
+                        } else {
+                             return false;
+                        }
+                    }
+                    Calendar.setup({
+                            inputField : "filter_waitingdate_begin",
+                            ifFormat : "<!-- TMPL_VAR NAME="DHTMLcalendar_dateformat" -->",
+                            button : "openwaitingdateFrom",
+                            disableFunc : validate1,
+                            dateStatusFunc : validate1
+                    });
+                                       //]]>
+                                       </script>
+                    <label for="filter_waitingdate_end">To</label> <input  size="10" id="filter_waitingdate_end" name="filter_waitingdate_end" value="" type="text" />
+                    <img src="<!-- TMPL_VAR Name="themelang" -->/lib/calendar/cal.gif" alt="Show Calendar" id="openwaitingdateTo" style="cursor: pointer;" border="0" />
+                    <script type="text/javascript">
+                                       //<![CDATA[  
+                                       function validate2(date) {
+                         var day = date.getDate();
+                         var month = date.getMonth() + 1;
+                         var year = date.getFullYear();
+                         var weekDay = date.getDay();
+                         var dayMonth = month + '-' + day;
+                         var dateString = year + '-' + month + '-' + day;
+                         var dateFrom = document.getElementById('filter_waitingdate_begin').value.split("-");
+                         var limitDate = new Date(dateFrom[0], (dateFrom[1] - 1), dateFrom[2]);
+                         if (limitDate > date) {
+                              return true;
+                         } else {
+                              return false;
+                         }
+                     }
+                     Calendar.setup({
+                             inputField : "filter_waitingdate_end",
+                             ifFormat : "<!-- TMPL_VAR NAME="DHTMLcalendar_dateformat" -->",
+                             button : "openwaitingdateTo",
+                             disableFunc : validate2,
+                             dateStatusFunc : validate2
+                     });
+                                       //]]>
+                                       </script>
+                    </td>
+             </tr>
+                        <tr>
+                <td>cancellation date</td>
+                <td><input type="radio" name="Line" value="cancellationdate" /></td>
+                <td><input type="radio" name="Column" value="cancellationdate" /></td>
+                <td><label for="filter_cancellationdate_begin">From</label> <input type="text"  size="10" id="filter_cancellationdate_begin" name="filter_cancellationdate_begin" />
+                    <img src="<!-- TMPL_VAR Name="themelang" -->/lib/calendar/cal.gif" alt="Show Calendar" border="0" id="opencancellationdateFrom" style="cursor: pointer;" />
+                   <script type="text/javascript">
+                                  //<![CDATA[ 
+                                  function validate1(date) {
+                        var day = date.getDate();
+                        var month = date.getMonth() + 1;
+                        var year = date.getFullYear();
+                        var weekDay = date.getDay();
+                        var dayMonth = month + '-' + day;
+                        var dateString = year + '-' + month + '-' + day;
+                        var dateTo = document.getElementById('filter_cancellationdate_end').value.split("-");
+                        var limitDate = new Date(dateTo[0], (dateTo[1] - 1), dateTo[2]);
+                        if (date > limitDate) {
+                             return true;
+                        } else {
+                             return false;
+                        }
+                    }
+                    Calendar.setup({
+                            inputField : "filter_cancellationdate_begin",
+                            ifFormat : "<!-- TMPL_VAR NAME="DHTMLcalendar_dateformat" -->",
+                            button : "opencancellationdateFrom",
+                            disableFunc : validate1,
+                            dateStatusFunc : validate1
+                    });
+                                       //]]>
+                                       </script>
+                    <label for="filter_cancellationdate_end">To</label> <input  size="10" id="filter_cancellationdate_end" name="filter_cancellationdate_end" value="" type="text" />
+                    <img src="<!-- TMPL_VAR Name="themelang" -->/lib/calendar/cal.gif" alt="Show Calendar" id="opencancellationdateTo" style="cursor: pointer;" border="0" />
+                    <script type="text/javascript">
+                                       //<![CDATA[  
+                                       function validate2(date) {
+                         var day = date.getDate();
+                         var month = date.getMonth() + 1;
+                         var year = date.getFullYear();
+                         var weekDay = date.getDay();
+                         var dayMonth = month + '-' + day;
+                         var dateString = year + '-' + month + '-' + day;
+                         var dateFrom = document.getElementById('filter_cancellationdate_begin').value.split("-");
+                         var limitDate = new Date(dateFrom[0], (dateFrom[1] - 1), dateFrom[2]);
+                         if (limitDate > date) {
+                              return true;
+                         } else {
+                              return false;
+                         }
+                     }
+                     Calendar.setup({
+                             inputField : "filter_cancellationdate_end",
+                             ifFormat : "<!-- TMPL_VAR NAME="DHTMLcalendar_dateformat" -->",
+                             button : "opencancellationdateTo",
+                             disableFunc : validate2,
+                             dateStatusFunc : validate2
+                     });
+                                       //]]>
+                                       </script>
+                    </td>
+             </tr>
+        <tr>
+            <td>Patron Category</td>
+            <td><input type="radio" name="Line" value="borrowers.categorycode" /></td>
+            <td><input type="radio" name="Column" value="borrowers.categorycode" /></td>
+           <td><select name="filter_categorycode" id="borcat">
+               <option value=""> </option>
+               <!-- TMPL_LOOP NAME="categoryloop" -->
+                 <!-- TMPL_IF NAME="selected" --><option value="<!-- TMPL_VAR NAME="categorycode" -->" selected="selected"><!-- TMPL_VAR NAME="description" --></option><!-- TMPL_ELSE --><option value="<!-- TMPL_VAR NAME="categorycode" -->"><!-- TMPL_VAR NAME="description" --></option><!-- /TMPL_IF -->
+               <!-- /TMPL_LOOP -->
+               </select>
+             </td> 
+        </tr>
+        <tr class="highlight">
+            <td>Item Type</td>
+            <td><input type="radio" name="Line" value="items.itype" /></td>
+            <td><input type="radio" name="Column" value="items.itype" /></td>
+           <td><select name="filter_items.itype" id="itype">
+               <option value=""> </option>
+               <!-- TMPL_LOOP NAME="itypeloop" -->
+                 <!-- TMPL_IF NAME="selected" --><option value="<!-- TMPL_VAR NAME="code" -->" selected="selected"><!-- TMPL_VAR NAME="description" --></option><!-- TMPL_ELSE --><option value="<!-- TMPL_VAR NAME="code" -->"><!-- TMPL_VAR NAME="description" --></option><!-- /TMPL_IF -->
+               <!-- /TMPL_LOOP -->
+               </select>
+             </td> 
+        </tr>
+        <tr>
+            <td>Pickup Library</td>
+            <td><input type="radio" name="Line" value="reserves.branchcode" checked="checked" /></td>
+            <td><input type="radio" name="Column" value="reserves.branchcode" /></td>
+            <td><select name="filter_reserves.branchcode" id="resbranchcode">
+               <option value=""> </option>
+               <!-- TMPL_LOOP NAME="branchloop" -->
+<!-- TMPL_IF NAME="selected" --><option value="<!-- TMPL_VAR NAME="value" -->" selected="selected"><!-- TMPL_VAR NAME="branchname" --></option><!-- TMPL_ELSE --><option value="<!-- TMPL_VAR NAME="value" -->"><!-- TMPL_VAR NAME="branchname" --></option><!-- /TMPL_IF -->
+                               <!-- /TMPL_LOOP -->
+               </select>
+             </td> 
+        </tr>
+        <tr class="highlight">
+            <td>Holding Library</td>
+            <td><input type="radio" name="Line" value="holdingbranch" /></td>
+            <td><input type="radio" name="Column" value="holdingbranch" /></td>
+            <td><select name="filter_holdingbranch" id="holdingbranch">
+               <option value=""> </option>
+               <!-- TMPL_LOOP NAME="branchloop" -->
+<!-- TMPL_IF NAME="selected" --><option value="<!-- TMPL_VAR NAME="value" -->" selected="selected"><!-- TMPL_VAR NAME="branchname" --></option><!-- TMPL_ELSE --><option value="<!-- TMPL_VAR NAME="value" -->"><!-- TMPL_VAR NAME="branchname" --></option><!-- /TMPL_IF -->
+                               <!-- /TMPL_LOOP -->
+               </select>
+             </td> 
+        </tr>
+        <tr>
+            <td>Home Library</td>
+            <td><input type="radio" name="Line" value="homebranch" /></td>
+            <td><input type="radio" name="Column" value="homebranch" /></td>
+            <td><select name="filter_homebranch" id="homebranch">
+               <option value=""> </option>
+               <!-- TMPL_LOOP NAME="branchloop" -->
+<!-- TMPL_IF NAME="selected" --><option value="<!-- TMPL_VAR NAME="value" -->" selected="selected"><!-- TMPL_VAR NAME="branchname" --></option><!-- TMPL_ELSE --><option value="<!-- TMPL_VAR NAME="value" -->"><!-- TMPL_VAR NAME="branchname" --></option><!-- /TMPL_IF -->
+                               <!-- /TMPL_LOOP -->
+               </select>
+             </td> 
+        </tr>
+        <tr class="highlight">
+            <td>Collection</td>
+            <td><input type="radio" name="Line"   value="items.ccode" /></td>
+            <td><input type="radio" name="Column" value="items.ccode" /></td>
+            <td><select name="filter_items.ccode" id="ccode">
+                <option value=""> </option>
+                <!-- TMPL_LOOP NAME="ccodeloop" -->
+                                       <!-- TMPL_IF NAME="selected" --> <option value="<!-- TMPL_VAR NAME="code" -->" selected="selected"><!-- TMPL_VAR NAME="description" --></option><!-- TMPL_ELSE --><option value="<!-- TMPL_VAR NAME="code" -->"><!-- TMPL_VAR NAME="description" --></option><!-- /TMPL_IF -->
+                <!-- /TMPL_LOOP -->
+                </select>
+            </td>
+        </tr>
+        <tr>
+            <td>Shelving Location</td>
+            <td><input type="radio" name="Line" value="items.location" /></td>
+            <td><input type="radio" name="Column" value="items.location" /></td>
+            <td><select name="filter_items.location" id="location">
+                <option value=""> </option>
+                <!-- TMPL_LOOP NAME="locationloop" -->
+                                       <!-- TMPL_IF NAME="selected" --><option value="<!-- TMPL_VAR NAME="code" -->" selected="selected"><!-- TMPL_VAR NAME="description" --></option><!-- TMPL_ELSE --><option value="<!-- TMPL_VAR NAME="code" -->"><!-- TMPL_VAR NAME="description" --></option><!-- /TMPL_IF -->
+                               <!-- /TMPL_LOOP -->
+               </select>
+            </td> 
+        </tr>
+        <tr class="highlight">
+            <td>Item Call Number</td>
+            <td></td>
+            <td></td>
+            <td>From <input type="text" name="filter_itemcallnumber" size="10" /> (inclusive) to <input type="text" name="fiter_itemcallnumber" size="10" /> (exclusive) </td>
+        </tr>
+        <!-- TMPL_IF Name="hassort1" -->
+        <tr><td>Patron sort1</td>
+                       <td><input type="radio" name="Line" value="borrowers.sort1" /></td>
+                       <td><input type="radio" name="Column" value="borrowers.sort1" /></td>
+                       <td><select name="filter_borrowers.sort1" id="sort1">
+               <option value=""> </option>
+               <!-- TMPL_LOOP NAME="Bsort1" -->
+                          <!-- TMPL_IF NAME="selected" --><option value="<!-- TMPL_VAR NAME="authorised_value" -->" selected="selected"><!-- TMPL_VAR NAME="lib" --></option><!-- TMPL_ELSE --><option value="<!-- TMPL_VAR NAME="authorised_value" -->" ><!-- TMPL_VAR NAME="lib" --></option><!-- /TMPL_IF -->
+               <!-- /TMPL_LOOP -->
+               </select>
+            </td> 
+        </tr>
+        <!-- /TMPL_IF -->
+        <!-- TMPL_IF Name="hassort2" -->
+        <tr class="highlight"><td>Patron sort2</td>
+            <td><input type="radio" name="Line" value="borrowers.sort2" /></td>
+            <td><input type="radio" name="Column" value="borrowers.sort2" /></td>
+               <td><select name="filter_borrowers.sort2" id="sort2">
+               <option value=""> </option>
+               <!-- TMPL_LOOP NAME="Bsort2" -->
+                          <!-- TMPL_IF NAME="selected" --><option value="<!-- TMPL_VAR NAME="authorised_value" -->" selected="selected"><!-- TMPL_VAR NAME="lib" --></option><!-- TMPL_ELSE --><option value="<!-- TMPL_VAR NAME="authorised_value" -->" ><!-- TMPL_VAR NAME="lib" --></option><!-- /TMPL_IF -->
+               <!-- /TMPL_LOOP -->
+               </select>
+            </td> 
+        </tr>
+        <!-- /TMPL_IF -->
+        </tbody>
+    </table><br /></fieldset>
+
+<fieldset class="rows"><legend>Cell value </legend><ol><li><label for="cellvalue1">Count reserves</label> <input type="radio" name="Cellvalue" value="1" id="cellvalue1" checked="checked" /> </li>
+            <li><label for="cellvalue2">Count unique borrowers</label> <input type="radio" name="Cellvalue" value="2" id="cellvalue2" /> </li><li><label for="cellvalue3">Count unique items</label> <input type="radio" name="Cellvalue" id="cellvalue3" value="3" /> </li><li><label for="cellvalue4">Count unique biblios</label> <input type="radio" name="Cellvalue" id="cellvalue4" value="4" /> </li></ol></fieldset>
+                       
+       <fieldset class="rows">
+       <legend>Output</legend>
+<ol><li><label for="outputscreen">To screen into the browser: </label><input type="radio" checked="checked" name="output" id="outputscreen" value="screen" /> </li>
+<li><label for="outputfile">To a file:</label> <input type="radio" name="output" value="file" id="outputfile" /> <label class="inline" for="basename">Named: </label><input type="text" name="basename" id="basename" value="Export" /> <label class="inline" for="MIME">Into an application  
+               </label><!-- TMPL_VAR NAME="CGIextChoice" -->
+               <!-- TMPL_VAR NAME="CGIsepChoice" --></li></ol>
+       </fieldset>
+
+       <fieldset class="action">
+       <input type="submit" value="Submit" />
+       <input type="hidden" name="report_name" value="<!--TMPL_VAR NAME="report_name" -->" />
+       <input type="hidden" name="do_it" value="1" />
+       </fieldset>
+       </form>
+<!-- /TMPL_IF -->
+
+</div>
+</div>
+<div class="yui-b">
+<!-- TMPL_INCLUDE NAME="reports-menu.inc" -->
+</div>
+</div>
+<!-- TMPL_INCLUDE NAME="intranet-bottom.inc" -->
diff --git a/reports/reserves_stats.pl b/reports/reserves_stats.pl
new file mode 100755 (executable)
index 0000000..93f2818
--- /dev/null
@@ -0,0 +1,382 @@
+#!/usr/bin/perl
+
+
+# Copyright 2000-2002 Katipo Communications
+#
+# This file is part of Koha.
+#
+# Koha is free software; you can redistribute it and/or modify it under the
+# terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at your option) any later
+# version.
+#
+# Koha is distributed in the hope that it will be useful, but WITHOUT ANY
+# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+# A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# Koha; if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+# Suite 330, Boston, MA  02111-1307 USA
+
+use strict;
+
+use CGI;
+
+use C4::Auth;
+use C4::Debug;
+use C4::Context;
+use C4::Branch; # GetBranches
+use C4::Koha;
+use C4::Output;
+use C4::Reports;
+use C4::Members;
+use C4::Dates qw/format_date format_date_in_iso/;
+use C4::Category;
+use List::MoreUtils qw/any/;
+use YAML;
+
+=head1 NAME
+
+plugin that shows circulation stats
+
+=head1 DESCRIPTION
+
+=over 2
+
+=cut
+
+# my $debug = 1;       # override for now.
+my $input = new CGI;
+my $fullreportname = "reports/reserves_stats.tmpl";
+my $do_it    = $input->param('do_it');
+my $line     = $input->param("Line");
+my $column   = $input->param("Column");
+my $podsp    = $input->param("DisplayBy");
+my $type     = $input->param("PeriodTypeSel");
+my $daysel   = $input->param("PeriodDaySel");
+my $monthsel = $input->param("PeriodMonthSel");
+my $calc     = $input->param("Cellvalue");
+my $output   = $input->param("output");
+my $basename = $input->param("basename");
+my $mime     = $input->param("MIME");
+my $hash_params = $input->Vars;
+my $filter_hashref;
+foreach my $filter (grep {$_ =~/^filter/} keys %$hash_params){
+       my $filterstring=$filter;
+       $filterstring=~s/^filter_//g;
+       $$filter_hashref{$filterstring}=$$hash_params{$filter} if (defined $$hash_params{$filter} && $$hash_params{$filter} ne "");
+}
+my ($template, $borrowernumber, $cookie) = get_template_and_user({
+       template_name => $fullreportname,
+       query => $input,
+       type => "intranet",
+       authnotrequired => 0,
+       flagsrequired => {reports => '*'},
+       debug => 0,
+});
+our $sep     = $input->param("sep");
+$sep = "\t" if ($sep eq 'tabulation');
+$template->param(do_it => $do_it,
+       DHTMLcalendar_dateformat => C4::Dates->DHTMLcalendar(),
+);
+
+my $itemtypes = GetItemTypes();
+my $categoryloop = GetBorrowercategoryList;
+
+my $ccodes    = GetKohaAuthorisedValues("items.ccode");
+my $locations = GetKohaAuthorisedValues("items.location");
+my $authvalue = GetKohaAuthorisedValues("items.authvalue");
+
+my $Bsort1 = GetAuthorisedValues("Bsort1");
+my $Bsort2 = GetAuthorisedValues("Bsort2");
+my ($hassort1,$hassort2);
+$hassort1=1 if $Bsort1;
+$hassort2=1 if $Bsort2;
+
+
+if ($do_it) {
+# Displaying results
+       my $results = calculate($line, $column,  $calc, $filter_hashref);
+       if ($output eq "screen"){
+# Printing results to screen
+               $template->param(mainloop => $results);
+               output_html_with_http_headers $input, $cookie, $template->output;
+       } else {
+# Printing to a csv file
+        print $input->header(-type => 'application/vnd.sun.xml.calc',
+                            -encoding    => 'utf-8',
+                            -attachment=>"$basename.csv",
+                            -filename=>"$basename.csv" );
+               my $cols  = @$results[0]->{loopcol};
+               my $lines = @$results[0]->{looprow};
+# header top-right
+               print @$results[0]->{line} ."/". @$results[0]->{column} .$sep;
+# Other header
+               foreach my $col ( @$cols ) {
+                       print $col->{coltitle}.$sep;
+               }
+               print "Total\n";
+# Table
+               foreach my $line ( @$lines ) {
+                       my $x = $line->{loopcell};
+                       print $line->{rowtitle}.$sep;
+                       print map {$_->{value}.$sep} @$x;
+                       print $line->{totalrow}, "\n";
+               }
+# footer
+        print "TOTAL";
+        $cols = @$results[0]->{loopfooter};
+               print map {$sep.$_->{totalcol}} @$cols;
+        print $sep.@$results[0]->{total};
+       }
+       exit(1); # exit either way after $do_it
+}
+
+my $dbh = C4::Context->dbh;
+my @values;
+my %labels;
+my %select;
+
+# create itemtype arrayref for <select>.
+my @itemtypeloop;
+for my $itype ( sort {$itemtypes->{$a}->{description} cmp $itemtypes->{$b}->{description}} keys(%$itemtypes)) {
+       push @itemtypeloop, { code => $itype , description => $itemtypes->{$itype}->{description} } ;
+}
+
+    # location list
+my @locations;
+foreach (sort keys %$locations) {
+       push @locations, { code => $_, description => "$_ - " . $locations->{$_} };
+}
+    
+my @ccodes;
+foreach (sort {$ccodes->{$a} cmp $ccodes->{$b}} keys %$ccodes) {
+       push @ccodes, { code => $_, description => $ccodes->{$_} };
+}
+
+# various
+my @mime = (C4::Context->preference("MIME"));
+
+my $CGIextChoice=CGI::scrolling_list(
+       -name     => 'MIME',
+       -id       => 'MIME',
+       -values   => \@mime,
+       -size     => 1,
+       -multiple => 0 );
+    
+my $CGIsepChoice=GetDelimiterChoices;
+$template->param(
+       categoryloop => $categoryloop,
+       itemtypeloop => \@itemtypeloop,
+          ccodeloop => \@ccodes,
+         branchloop => GetBranchesLoop(C4::Context->userenv->{'branch'}),
+       hassort1=> $hassort1,
+       hassort2=> $hassort2,
+       Bsort1 => $Bsort1,
+       Bsort2 => $Bsort2,
+       CGIextChoice => $CGIextChoice,
+       CGIsepChoice => $CGIsepChoice,
+);
+output_html_with_http_headers $input, $cookie, $template->output;
+
+sub calculate {
+       my ($linefield, $colfield, $process, $filters_hashref) = @_;
+       my @loopfooter;
+       my @loopcol;
+       my @loopline;
+       my @looprow;
+       my %globalline;
+       my $grantotal =0;
+# extract parameters
+       my $dbh = C4::Context->dbh;
+
+# Filters
+# Checking filters
+#
+       my @loopfilter;
+       foreach my $filter (keys %$filters_hashref){
+               $$filters_hashref{$filter} =~s/\*/%/;
+               $$filters_hashref{$filter} = format_date_in_iso($$filters_hashref{$_}) if ($_=~/date/);
+       }
+       #display
+       @loopfilter= map{{ crit=>$_ ,filter=>($_=~/date/?
+                                                                                       format_date($$filters_hashref{$_})
+                                                                                       :$$filters_hashref{$_}
+                                                                                 )
+                                         }
+                                       } sort keys %$filters_hashref;
+
+
+
+
+       my $linesql=changeifreservestatus($linefield);
+       my $colsql=changeifreservestatus($colfield);
+       #Initialization of cell values.....
+
+       # preparing calculation
+    my $strcalc = "(SELECT $linesql line, $colsql col, ";
+        $strcalc .= ($process == 1) ? " COUNT(*)  calculation"                                 :
+                                       ($process == 2) ? "(COUNT(DISTINCT reserves.borrowernumber)) calculation"  :
+                               ($process == 3) ? "(COUNT(DISTINCT reserves.itemnumber)) calculation"      : 
+                               ($process == 4) ? "(COUNT(DISTINCT reserves.biblionumber)) calculation"    : '*';
+       $strcalc .= "
+        FROM reserves
+        LEFT JOIN borrowers USING (borrowernumber)
+       ";
+       $strcalc .= "LEFT JOIN biblio ON reserves.biblionumber=biblio.biblionumber "
+        if ($linefield =~ /^biblio\./ or $colfield =~ /^biblio\./ or any {$_=~/biblio/}keys %$filters_hashref);
+       $strcalc .= "LEFT JOIN items ON reserves.itemnumber=items.itemnumber "
+        if ($linefield =~ /^items\./ or $colfield =~ /^items\./ or any {$_=~/items/}keys %$filters_hashref);
+        
+       my @sqlparams;
+       my @sqlorparams;
+       my @sqlor;
+       my @sqlwhere;
+       ($debug) and print STDERR Dump($filters_hashref);
+       foreach my $filter (keys %$filters_hashref){
+               my $string;
+               my $stringfield=$filter;
+               $stringfield=~s/\_[a-z_]+$//;
+               warn $stringfield;
+               if ($filter=~/ /){
+                       $string=$stringfield;
+               }
+               elsif ($filter=~/_or/){
+                        push @sqlor, qq{( }.changeifreservestatus($filter)." = ? ) ";
+                        push @sqlorparams, $$filters_hashref{$filter};
+               }
+               elsif ($filter=~/_end$/){
+                       $string = " $stringfield <= ? ";
+               }
+               elsif ($filter=~/_begin$/){
+                       $string = " $stringfield >= ? ";
+               }
+               else {
+                       $string = " $stringfield LIKE ? ";
+               }
+               if ($string){
+                       push @sqlwhere, $string;
+                       push @sqlparams, $$filters_hashref{$filter};
+               }
+       }
+
+       $strcalc .= " WHERE ".join(" AND ",@sqlwhere) if (@sqlwhere);
+       $strcalc .= " AND (".join(" OR ",@sqlor).")" if (@sqlor);
+       $strcalc .= " GROUP BY line, col )";
+       my $strcalc_old=$strcalc;
+       $strcalc_old=~s/reserves/old_reserves/g;
+       $strcalc.=qq{ UNION $strcalc_old ORDER BY line, col};
+       ($debug) and print STDERR $strcalc;
+       my $dbcalc = $dbh->prepare($strcalc);
+       push @loopfilter, {crit=>'SQL =', sql=>1, filter=>$strcalc};
+       @sqlparams=(@sqlparams,@sqlorparams);
+       $dbcalc->execute(@sqlparams,@sqlparams);
+       my ($emptycol,$emptyrow); 
+       my $data = $dbcalc->fetchall_hashref([qw(line col)]);
+       my @loopline;
+       my %cols_hash;
+       foreach my $row (keys %$data){
+               push @loopline, $row;
+               foreach my $col (keys %{$$data{$row}}){
+                       $$data{$row}{totalrow}+=$$data{$row}{$col}{calculation};
+                       $grantotal+=$$data{$row}{$col}{calculation};
+                       $cols_hash{$col}=1 ;
+               }
+       }
+       my $urlbase="do_it=1&amp;".join("&amp;",map{"filter_$_=$$filters_hashref{$_}"} keys %$filters_hashref);
+       foreach my $row (sort @loopline) {
+               my @loopcell;
+               #@loopcol ensures the order for columns is common with column titles
+               # and the number matches the number of columns
+               foreach my $col (sort keys %cols_hash) {
+                       push @loopcell, {value =>( $$data{$row}{$col}{calculation} or ""),
+       #                                               url_complement=>($urlbase=~/&amp;$/?$urlbase."&amp;":$urlbase)."filter_$linefield=$row&amp;filter_$colfield=$col"
+                                                       }
+               }
+               push @looprow, {
+                       'rowtitle_display' => display_value($linefield,$row),
+                       'rowtitle' => $row,
+                       'loopcell' => \@loopcell,
+                       'totalrow' => $$data{$row}{totalrow}
+               };
+       }
+       for my $col ( sort keys %cols_hash ) {
+               my $total = 0;
+               foreach my $row (@loopline) {
+                       $total += $$data{$row}{$col}{calculation};
+                       $debug and warn "value added ".$$data{$row}{$col}{calculation}. "for line ".$row;
+               }
+               push @loopfooter, {'totalcol' => $total};
+               push @loopcol, {'coltitle' => $col,
+                                               coltitle_display=>display_value($colfield,$col)};
+       }
+
+       # the header of the table
+       $globalline{loopfilter}=\@loopfilter;
+       # the core of the table
+       $globalline{looprow} = \@looprow;
+       $globalline{loopcol} = \@loopcol;
+       #       # the foot (totals by borrower type)
+       $globalline{loopfooter} = \@loopfooter;
+       $globalline{total}  = $grantotal;
+       $globalline{line}   = $linefield;
+       $globalline{column} = $colfield;
+       return [(\%globalline)];
+}
+
+sub null_to_zzempty ($) {
+       my $string = shift;
+       defined($string)    or  return 'zzEMPTY';
+       ($string eq "NULL") and return 'zzEMPTY';
+       return $string;         # else return the valid value
+}
+sub display_value{
+       my ($crit,$value)=@_;
+       my $display_value =
+               ($crit =~ /ccode/   ) ? $ccodes->{$value}    :
+               ($crit =~ /location/) ? $locations->{$value} :
+               ($crit =~ /itemtype/) ? $itemtypes->{$value}->{description} :
+               ($crit =~ /branch/) ? GetBranchName($value):
+               ($crit =~ /reservestatus/) ? reservestatushuman($value):
+               $value; # default fallback
+       if ($crit =~ /(sort1|sort2)/) {
+               $display_value=GetAuthorisedValues("B$_",$value);
+       } elsif ($crit =~ /category/) {
+               my $element=any{$value eq $_->{categorycode}} @$categoryloop;
+               $display_value=$$element{description};
+       }
+       return $display_value;
+}
+sub reservestatushuman{
+       my ($val)=@_;
+       my %hashhuman=(
+       1=>"1- placed",
+       2=>"2- processed",
+       3=>"3- pending",
+       4=>"4- satisfied",
+       5=>"5- cancelled",
+       6=>"6- not a status"
+       );
+       $hashhuman{$val};
+}
+sub changeifreservestatus{
+       my ($val)=@_;
+       ($val=~/reservestatus/
+               ?$val=qq{ case 
+                                       when priority>0 then 1 
+                                       when priority=0 then
+                                               (case 
+                                                  when found='f' then 4
+                                                  when found='w' then 
+                                                  (case 
+                                                   when cancellationdate is null then 3
+                                                       else 5
+                                                       end )
+                                                  else 2 
+                                                end )
+                                   else 6 
+                                       end }
+               :$val);
+}
+1;