[Koha-patches] [PATCH 31/54] Adding a reserve report

paul.poulain at biblibre.com paul.poulain at biblibre.com
Thu Dec 16 11:54:25 CET 2010


From: Paul Poulain <paul.poulain at biblibre.com>

---
 .../prog/en/modules/reports/reports-home.tmpl      |    1 +
 .../prog/en/modules/reports/reserves_stats.tmpl    |  549 ++++++++++++++++++++
 reports/reserves_stats.pl                          |  382 ++++++++++++++
 3 files changed, 932 insertions(+), 0 deletions(-)
 create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/reports/reserves_stats.tmpl
 create mode 100755 reports/reserves_stats.pl

diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reports-home.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reports-home.tmpl
index b2d8487..7c6efae 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reports-home.tmpl
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reports-home.tmpl
@@ -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
index 0000000..2b78133
--- /dev/null
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/reserves_stats.tmpl
@@ -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
index 0000000..93f2818
--- /dev/null
+++ b/reports/reserves_stats.pl
@@ -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 ", at sqlwhere) if (@sqlwhere);
+	$strcalc .= " AND (".join(" OR ", at 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, at sqlorparams);
+	$dbcalc->execute(@sqlparams, at 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;
-- 
1.7.1



More information about the Koha-patches mailing list