Merge remote branch 'kc/new/enh/bug_5869' into kcmaster

This commit is contained in:
Chris Cormack 2011-03-17 14:37:00 +13:00
commit c78387b7d0
4 changed files with 935 additions and 1 deletions

View file

@ -9,7 +9,8 @@
<li><a href="/cgi-bin/koha/reports/borrowers_stats.pl">Patrons</a></li>
<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/serials_stats.pl">Serials</a></li>
<li><a href="/cgi-bin/koha/reports/reserves_stats.pl">Holds</a></li>
</ul>

View 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">Holds</a></li>
</ul></div>
<div class="yui-u"><h2>Top Lists</h2>

View file

@ -0,0 +1,549 @@
<!-- TMPL_INCLUDE NAME="doc-head-open.inc" -->
<title>Koha &rsaquo; Reports &rsaquo; Holds 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">Holds statistics</a> &rsaquo; Results <!-- TMPL_ELSE -->&rsaquo; Holds 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>Holds 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>Holds statistics</legend><table>
<thead>
<tr>
<th>Title</th>
<th>Row</th>
<th>Column</th>
<th>Filter</th>
</tr>
</thead>
<tbody>
<tr >
<td>Hold 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>Hold 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 holds</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" -->

383
reports/reserves_stats.pl Executable file
View file

@ -0,0 +1,383 @@
#!/usr/bin/perl
# Copyright 2010 Biblibre
#
# 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.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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;