From oleonard at myacpl.org Tue Jul 2 15:39:09 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Tue, 2 Jul 2013 09:39:09 -0400 Subject: [Koha-patches] [PATCH] Bug 10522 - Javascript error on acquisition pages: YAHOO is not defined Message-ID: <1372772349-22700-1-git-send-email-oleonard@myacpl.org> acq.js includes an immediately invoked function expression, which means that it runs whether or not it is called. Because this function tries to reference the YAHOO object, it triggers an error on pages which don't include the main YAHOO assets. Only the basketgroups page uses this function and YAHOO assets. It's probably possible to make this a regular function, but I propose simply wrapping it in a check for the YAHOO object so that it only executes on pages where YAHOO exists--the basketgroups page. To test, apply the patch, clear your browser cache, and test on both the basketgroups page and at least one page which also includes acq.js (addorderiso2709.pl, neworderempty.pl, aqbudgets.pl, suggestion.pl, etc.) and confirm that the browser reports no JavaScript errors. --- koha-tmpl/intranet-tmpl/prog/en/js/acq.js | 280 ++++++++++++++--------------- 1 file changed, 140 insertions(+), 140 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/acq.js b/koha-tmpl/intranet-tmpl/prog/en/js/acq.js index 067cd08..b9039ea 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/js/acq.js +++ b/koha-tmpl/intranet-tmpl/prog/en/js/acq.js @@ -60,181 +60,181 @@ function isNum(v,maybenull) { //======================================================================= // Functions for drag-and-drop functionality +if( typeof(YAHOO) === "object"){ + (function() { -(function() { - -var Dom = YAHOO.util.Dom; -var Event = YAHOO.util.Event; -var DDM = YAHOO.util.DragDropMgr; - -DDApp = { - init: function() { - var uls = document.getElementsByTagName('ul'); - var i,j; - var ddtarget; - for (i=0; i this.lastY) { - this.goingUp = false; - } - this.lastY = y; - }, + if (y < this.lastY) { + this.goingUp = true; + } else if (y > this.lastY) { + this.goingUp = false; + } + this.lastY = y; + }, - onDragOver: function(e, id) { + onDragOver: function(e, id) { - var srcEl = this.getEl(); - var destEl = Dom.get(id); + var srcEl = this.getEl(); + var destEl = Dom.get(id); - // We are only concerned with list items, we ignore the dragover - // notifications for the list. - if (destEl.nodeName.toLowerCase() == "li") { - var orig_p = srcEl.parentNode; - var p = destEl.parentNode; + // We are only concerned with list items, we ignore the dragover + // notifications for the list. + if (destEl.nodeName.toLowerCase() == "li") { + var orig_p = srcEl.parentNode; + var p = destEl.parentNode; - if (this.goingUp) { - p.insertBefore(srcEl, destEl); // insert above - } else { - p.insertBefore(srcEl, destEl.nextSibling); // insert below - } + if (this.goingUp) { + p.insertBefore(srcEl, destEl); // insert above + } else { + p.insertBefore(srcEl, destEl.nextSibling); // insert below + } - DDM.refreshCache(); + DDM.refreshCache(); + } } - } -}); -})(); - + }); + })(); +} -- 1.7.9.5 From oleonard at myacpl.org Tue Jul 2 16:06:09 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Tue, 2 Jul 2013 10:06:09 -0400 Subject: [Koha-patches] [PATCH] Bug 10422 - Remove references to unused and non-existent wizard.css Message-ID: <1372773970-23118-1-git-send-email-oleonard@myacpl.org> doc-head-close.inc contains a reference to "wizard.css" which doesn't exist. The option to include it never evaluates as true, and that section can be removed from the template. To test, apply the patch and view any page in the staff client. Everything should be styled as before. A search of the Koha source should return no references to "wizard.css" or a "wizard" variable. --- .../prog/en/includes/doc-head-close.inc | 3 --- 1 file changed, 3 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc index ee7f3f2..ff4cca9 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/doc-head-close.inc @@ -20,9 +20,6 @@ [% IF ( login ) %] [% END %] -[% IF ( wizard ) %] - -[% END %] -- 1.7.9.5 From oleonard at myacpl.org Tue Jul 2 17:29:48 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Tue, 2 Jul 2013 11:29:48 -0400 Subject: [Koha-patches] [PATCH] Bug 2774 - Path to theme is hard-coded in many places Message-ID: <1372778988-27532-1-git-send-email-oleonard@myacpl.org> This patch corrects more places in Koha where the path to the "prog" theme is hard-coded in templates, CSS, and scripts. Staff client home page: Paths to the Koha logo background image and the module image sprite have been corrected. Inactive and hover states of the module links (circulation, patrons, etc) should look correct. addbiblio.pl: An tag is replaced with a text link and an additional CSS class. CSS uses an image-replacement technique to display the image as before. To test, open a blank or existing bibliographic record for editing. Confirm that the "tag editor" icon displays correctly in two cases: 1) tags linked to plugin editors and 2) tags linked to authorities. Both should look correct and work correctly. System preferences: The system preferences editor appends a "loading" image to system preference submit buttons when they are clicked. This patch changes ajax.js to insert a styled with a background-image instead. To test, open system preferences and modify any preference. Submit the change and confirm that the "loading" image appears correctly. Background jobs: Any place in Koha where a background job is used displays a progress bar. This patch corrects the path in CSS to the progress bar image. To test, perform an action which triggers the display of a progress bar. For instance, batch modification of items. Confirm that the progress bar image displays correctly. blue.css: I don't know if this is still used by anyone, but a couple of image paths in this CSS file have been corrected. --- cataloguing/addbiblio.pl | 6 +++--- koha-tmpl/intranet-tmpl/prog/en/css/blue.css | 6 +++--- koha-tmpl/intranet-tmpl/prog/en/css/mainpage.css | 4 ++-- .../intranet-tmpl/prog/en/css/preferences.css | 9 +++++++++ .../intranet-tmpl/prog/en/css/staff-global.css | 18 +++++++++++++----- koha-tmpl/intranet-tmpl/prog/en/js/ajax.js | 10 +++++----- 6 files changed, 35 insertions(+), 18 deletions(-) diff --git a/cataloguing/addbiblio.pl b/cataloguing/addbiblio.pl index d24972c..6592d1e 100755 --- a/cataloguing/addbiblio.pl +++ b/cataloguing/addbiblio.pl @@ -391,8 +391,8 @@ sub create_input { maxlength=\"".$subfield_data{maxlength}."\"". ($is_readonly ? "readonly=\"readonly\"" : ""). "\/> - {$tag}->{$subfield}->{authtypecode}."','biblio'); return false;\" tabindex=\"1\" title=\"Tag Editor\">\"Tag + {$tag}->{$subfield}->{authtypecode}."','biblio'); return false;\" tabindex=\"1\">Tag editor "; # it's a plugin field } @@ -421,7 +421,7 @@ sub create_input { size=\"67\" maxlength=\"".$subfield_data{maxlength}."\" onblur=\"Blur$function_name($index_tag); \" \/> - \"Tag + Tag editor $javascript"; } else { warn "Plugin Failed: $plugin"; diff --git a/koha-tmpl/intranet-tmpl/prog/en/css/blue.css b/koha-tmpl/intranet-tmpl/prog/en/css/blue.css index 4155b14..1f28d27 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/css/blue.css +++ b/koha-tmpl/intranet-tmpl/prog/en/css/blue.css @@ -39,7 +39,7 @@ h4 { h5 { font-size : 100%; font-weight : bold; - background: url( /intranet-tmpl/prog/img/css_header.png ); + background: url( ../../img/css_header.png ); background-repeat:repeat-x; color:white;} @@ -54,7 +54,7 @@ h6 { th { color:white; - background: url( /intranet-tmpl/prog/img/css_header.png ); + background: url( ../../img/css_header.png ); background-repeat:repeat-x; border-bottom : 1px solid #BCBCBC; border-left : 1px solid #BCBCBC; @@ -66,7 +66,7 @@ border: 1px solid #bbbbbb; } input[type=submit], input[type=button], input[type=reset] { - background: url( /intranet-tmpl/prog/img/css_header.png ); + background: url( ../../img/css_header.png ); color:white; border:1px inset; margin-top:10px; diff --git a/koha-tmpl/intranet-tmpl/prog/en/css/mainpage.css b/koha-tmpl/intranet-tmpl/prog/en/css/mainpage.css index 064668d..169f2a0 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/css/mainpage.css +++ b/koha-tmpl/intranet-tmpl/prog/en/css/mainpage.css @@ -13,7 +13,7 @@ #doc3 { /* Contains the news + both columns of links + pending box + userblock box */ - background-image:url('/intranet-tmpl/prog/img/background_koha_logo.png'); + background-image:url('../../img/background_koha_logo.png'); background-repeat:no-repeat; background-position:left top; padding-top: 12px; @@ -72,7 +72,7 @@ ul.biglinks-list li { ul.biglinks-list li a.icon_general { /* Class used for each module link */ - background-image:url('/intranet-tmpl/prog/img/staff-home-icons-sprite.png'); + background-image:url('../../img/staff-home-icons-sprite.png'); display: block; float: left; diff --git a/koha-tmpl/intranet-tmpl/prog/en/css/preferences.css b/koha-tmpl/intranet-tmpl/prog/en/css/preferences.css index c58e9a5..d9f8e16 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/css/preferences.css +++ b/koha-tmpl/intranet-tmpl/prog/en/css/preferences.css @@ -73,4 +73,13 @@ h3.collapsed { #toolbar.floating { box-shadow: 0 3px 2px 0 rgba(0, 0, 0, 0.5); border-radius: 0; +} + +.loading { + display: inline-block; + height : 16px; + width: 16px; + background: transparent url("../../img/spinner-small.gif") top left no-repeat; + padding : 0 4px; + vertical-align: middle; } \ No newline at end of file diff --git a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css index f5d5bc2..0fa93ab 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css +++ b/koha-tmpl/intranet-tmpl/prog/en/css/staff-global.css @@ -1859,10 +1859,6 @@ span.permissiondesc { font-weight: normal; } -img.spinner { - vertical-align: middle; - padding-right: 0.3em; -} ul.budget_hierarchy { margin-left: 0px; padding-left: 0px; @@ -2565,7 +2561,7 @@ fieldset.rows table.mceListBox { #jobpanel,#jobstatus,#jobfailed { display : none; } #jobstatus { margin:.4em; } -#jobprogress{ width:200px;height:10px;border:1px solid #666;background:url('/intranet-tmpl/prog/img/progress.png') -300px 0px no-repeat; } +#jobprogress{ width:200px;height:10px;border:1px solid #666;background:url('../../img/progress.png') -300px 0px no-repeat; } #selections { width : 100%; white-space : normal; } #selections span { margin:3px;padding:3px;background-color:#EBF3FF;-moz-border-radius:5px;border-radius:5px;white-space:nowrap;line-height:240%;font-size:75%; } #selections span.selected { background-color : #CCE0FC; } @@ -2582,3 +2578,15 @@ fieldset.rows table.mceListBox { -webkit-box-shadow: 0px 3px 2px 0px rgba(0, 0, 0, .5); box-shadow: 0px 3px 2px 0px rgba(0, 0, 0, .5); } + +.tag_editor { + background: transparent url("../../img/edit-tag.png") top left no-repeat; + display : block; + float : left; + width : 16px; + height: 16px; + margin : 4px; + text-indent: 100%; + white-space: nowrap; + overflow: hidden; +} \ No newline at end of file diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/ajax.js b/koha-tmpl/intranet-tmpl/prog/en/js/ajax.js index c9a45c0..a8a9241 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/js/ajax.js +++ b/koha-tmpl/intranet-tmpl/prog/en/js/ajax.js @@ -36,7 +36,7 @@ KOHA.AJAX = { $( selector ) .attr( 'disabled', 'disabled' ) .each( function () { - var $image = $( '' ); + var $spinner = $( '' ); var selector_type = this.localName; if (selector_type === undefined) selector_type = this.nodeName; // IE only switch ( selector_type.toLowerCase() ) { @@ -48,14 +48,14 @@ KOHA.AJAX = { $( this ) .data( 'original-text', $( this ).text ) .text( text ) - .before( $image ) + .before( $spinner ) .bind( 'click.disabled', function () { return false; } ); break; case 'button': $( this ) .data( 'original-text', $( this ).text() ) .text( text ) - .prepend( $image ); + .prepend( $spinner ); break; } } ); @@ -74,12 +74,12 @@ KOHA.AJAX = { $( this ) .text( $( this ).data( 'original-text' ) ) .unbind( 'click.disabled' ) - .prevAll( 'img.spinner' ).remove(); + .prevAll( 'span.loading' ).remove(); break; case 'button': $( this ) .text( $( this ).data( 'original-text' ) ) - .find( 'img.spinner' ).remove(); + .find( 'span.loading' ).remove(); break; } } ) -- 1.7.9.5 From oleonard at myacpl.org Wed Jul 3 16:37:03 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Wed, 3 Jul 2013 10:37:03 -0400 Subject: [Koha-patches] [PATCH] Bug 3134 - Ability to selelct multiple reports to delete at once Message-ID: <1372862224-30970-1-git-send-email-oleonard@myacpl.org> This patch adds the option to select multiple saved reports for deletion. To test you must have two or more saved reports to delete. Deletion should work properly when: - Selecting one report for deletion by checking the box. - Selecting more than one report for deletion by checking boxes. - Clicking the old "Delete" link Clicking the delete button should prompt you to confirm. Clicking cancel should cancel. Clicking the delete button when no boxes are checked should trigger an alert asking you to select reports for deletion. --- C4/Reports/Guided.pm | 14 ++++++------ .../en/modules/reports/guided_reports_start.tt | 23 +++++++++++++++++--- reports/guided_reports.pl | 11 ++++++++-- 3 files changed, 36 insertions(+), 12 deletions(-) diff --git a/C4/Reports/Guided.pm b/C4/Reports/Guided.pm index f0db7a3..9447c71 100644 --- a/C4/Reports/Guided.pm +++ b/C4/Reports/Guided.pm @@ -609,13 +609,13 @@ sub format_results { } sub delete_report { - my ($id) = @_; - my $dbh = C4::Context->dbh(); - my $query = "DELETE FROM saved_sql WHERE id = ?"; - my $sth = $dbh->prepare($query); - $sth->execute($id); -} - + my (@ids) = @_; + my $dbh = C4::Context->dbh; + my $query = 'DELETE FROM saved_sql WHERE id IN (' . join( ',', ('?') x @ids ) . ')'; + my $sth = $dbh->prepare($query); + $sth->execute(@ids); + $sth->finish; +} my $SAVED_REPORTS_BASE_QRY = < +
+ + @@ -297,6 +309,7 @@ canned reports and writing custom SQL reports.

[% FOREACH savedreport IN savedreports %] [% UNLESS ( loop.odd ) %][% ELSE %][% END %] + @@ -317,7 +330,7 @@ canned reports and writing custom SQL reports.

Show [% IF ( CAN_user_reports_create_reports ) %] Edit - Duplicate + Duplicate [% END %]
  ID Report name Type
[% savedreport.id %] [% savedreport.report_name %] [% savedreport.type %] @@ -331,6 +344,10 @@ canned reports and writing custom SQL reports.

[% END %]
+
+ +
+
[% ELSE %]
diff --git a/reports/guided_reports.pl b/reports/guided_reports.pl index 929feea..b9c49ad 100755 --- a/reports/guided_reports.pl +++ b/reports/guided_reports.pl @@ -108,11 +108,18 @@ elsif ( $phase eq 'Build new' ) { ); } +elsif ( $phase eq 'Delete Multiple') { + my @ids = $input->param('ids'); + delete_report( @ids ); + print $input->redirect("/cgi-bin/koha/reports/guided_reports.pl?phase=Use%20saved"); + exit; +} + elsif ( $phase eq 'Delete Saved') { # delete a report from the saved reports list - my $id = $input->param('reports'); - delete_report($id); + my $ids = $input->param('reports'); + delete_report($ids); print $input->redirect("/cgi-bin/koha/reports/guided_reports.pl?phase=Use%20saved"); exit; } -- 1.7.9.5 From oleonard at myacpl.org Wed Jul 3 18:41:16 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Wed, 3 Jul 2013 12:41:16 -0400 Subject: [Koha-patches] [PATCH] Bug 5766 - Add configuration for excluding articles from DataTables sorting Message-ID: <1372869676-2111-1-git-send-email-oleonard@myacpl.org> Client-side table sorting should exclude articles like "a," "an," and "the" when sorting by title. This patch adds a custom sorting plugin for use by DataTables and a configuration line to the DataTables string configuration file which can be translated for any language. As an example, this patch modifies the patron checkout history template to use the new sort on the title column. To test, apply the patch and clear your browser cache to ensure the revised JavaScript file is loaded. Sort the table by title. Titles should be sorted regardless of the presences of "a," "an", or "the" at the beginning of the title. --- .../prog/en/includes/datatables-strings.inc | 1 + koha-tmpl/intranet-tmpl/prog/en/js/datatables.js | 46 +++++++++++++++++++- .../prog/en/modules/members/readingrec.tt | 15 ++++++- 3 files changed, 60 insertions(+), 2 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/datatables-strings.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/datatables-strings.inc index 183f511..7e939fc 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/datatables-strings.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/datatables-strings.inc @@ -13,5 +13,6 @@ var MSG_DT_PROCESSING = _("Processing..."); var MSG_DT_SEARCH = _("Search:"); var MSG_DT_ZERO_RECORDS = _("No matching records found"); + var CONFIG_EXCLUDE_ARTICLES_FROM_SORT = _("a an the"); //]]> diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/datatables.js b/koha-tmpl/intranet-tmpl/prog/en/js/datatables.js index 703944e..fc24036 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/js/datatables.js +++ b/koha-tmpl/intranet-tmpl/prog/en/js/datatables.js @@ -493,4 +493,48 @@ jQuery.extend( jQuery.fn.dataTableExt.oSort, { "title-string-desc": function ( a, b ) { return ((a < b) ? 1 : ((a > b) ? -1 : 0)); } -} ); \ No newline at end of file +} ); + +(function() { + + /* Plugin to allow text sorting to ignore articles + * + * In DataTables config: + * "aoColumns": [ + * { "sType": "anti-the" }, + * ] + * Based on the plugin found here: + * http://datatables.net/plug-ins/sorting#anti_the + * Modified to exclude HTML tags from sorting + * Extended to accept a string of space-separated articles + * from a configuration file (in English, "a," "an," and "the") + */ + + if(CONFIG_EXCLUDE_ARTICLES_FROM_SORT){ + var articles = CONFIG_EXCLUDE_ARTICLES_FROM_SORT.split(" "); + var rpattern = ""; + for(i=0;i/g, "" ); + var y = x.trim(); + var z = y.replace(re, "").toLowerCase(); + return z; + }, + + "anti-the-asc": function ( a, b ) { + return ((a < b) ? -1 : ((a > b) ? 1 : 0)); + }, + + "anti-the-desc": function ( a, b ) { + return ((a < b) ? 1 : ((a > b) ? -1 : 0)); + } + }); + +}()); \ No newline at end of file diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/readingrec.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/readingrec.tt index 6084357..f488234 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/readingrec.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/readingrec.tt @@ -8,13 +8,26 @@
- [% UNLESS debarments %]

Patron is currently unrestricted.

[% END %] - - - - - - - - [% IF ( CAN_user_borrowers ) %] - - [% END %] - - - - - [% FOREACH d IN debarments %] + [% IF ( debarments.size < 1 ) %] +

Patron is currently unrestricted.

+ [% ELSE %] +
TypeCommentExpiration 
+ - - - - [% IF ( CAN_user_borrowers )%] - - [% END %] + + + + [% IF ( CAN_user_borrowers ) %] + + [% END %] - [% END %] - - - [% IF ( CAN_user_borrowers )%] - - - - - + + + [% FOREACH d IN debarments %] - - - - + + + + [% IF ( CAN_user_borrowers )%] + + [% END %] - - - [% END %] -
[% d.type %][% d.comment %][% IF d.expiration %] [% d.expiration | $KohaDates %] [% ELSE %] Indefinite [% END %] - - Remove - - TypeCommentExpiration 
MANUAL - - Clear Date - - - [% d.type %][% d.comment %][% IF d.expiration %] [% d.expiration | $KohaDates %] [% ELSE %] Indefinite [% END %] + + Remove + +
+ [% END %] + + + [% END %] +

Add manual restriction

+ [% IF ( CAN_user_borrowers )%] +
+ + +
+ Add manual restriction +
    +
  1. +
  2. + Clear date
  3. +
+
Cancel
+
+
+ [% END %]
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt index dd60dfc..749e1f8 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/members/memberentrygen.tt @@ -35,6 +35,23 @@ [% END %] $("#dateofbirth").datepicker({ maxDate: "-1D" }); $("#entryform").preventDoubleFormSubmit(); + + var mrform = $("#manual_restriction_form"); + var mrlink = $("#add_manual_restriction"); + mrform.hide(); + mrlink.on("click",function(e){ + $(this).hide(); + mrform.show(); + e.preventDefault(); + }); + $("#cancel_manual_restriction").on("click",function(e){ + $('#debarred_expiration').val(''); + $('#add_debarment').prop('checked', false); + $('#debarred_comment').val(''); + mrlink.show(); + mrform.hide(); + e.preventDefault(); + }); }); function clear_entry(node) { @@ -1296,50 +1313,51 @@ - +
Patron restrictions - [% UNLESS debarments %]

Patron is currently unrestricted.

[% END %] - - - - - - - - - - - - - [% FOREACH d IN debarments %] + [% IF ( debarments.size < 1 ) %] +

Patron is currently unrestricted.

+ [% ELSE %] +
TypeCommentExpirationRemove?
+ - - - - + + + + - [% END %] - + + + + [% FOREACH d IN debarments %] + + + + + + + [% END %] + +
[% d.type %][% d.comment %][% IF d.expiration %] [% d.expiration | $KohaDates %] [% ELSE %] Indefinite [% END %] - - TypeCommentExpirationRemove?
[% d.type %][% d.comment %][% IF d.expiration %] [% d.expiration | $KohaDates %] [% ELSE %] Indefinite [% END %] + +
+ [% END %] +

Add manual restriction

+
+ + Add manual restriction +
    +
  1. +
  2. + Clear date
  3. - - - - Add new - - - - - - Clear date - - Clear new restriction - - - +
+

+ Cancel +

+
[% END %] -- 1.7.9.5 From oleonard at myacpl.org Mon Jul 8 17:48:57 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Mon, 8 Jul 2013 11:48:57 -0400 Subject: [Koha-patches] [PATCH] Bug 10552 - Several preferences missing from OPAC login page Message-ID: <1373298537-14274-1-git-send-email-oleonard@myacpl.org> Several system preference variables are unavailable to the OPAC login template because they are not explicitly enabled for that page. Instead of adding them to Auth.pm using the old method this patch uses the new system preference check syntax using the Koha TT plugin. The following preferences are now checked using this syntax in masthead.inc: OpacAddMastheadLibraryPulldown UseCourseReserves reviewson OpacShowRecentComments In order for the call in masthead.inc to the new plugin to work on all OPAC pages "[% USE Koha %]" must be added to any template which includes it (most of them). Also in this patch: A change to Auth.pm to enable correct display of the LibraryName in the title of the OPAC login page. To test, turn on the above system preferences and confirm that the relevant links appear under the OPAC's main search bar on all pages including the login page. Confirm that the text specified in the LibraryName system preference is shown as the title of the login page. Confirm that course reserves and comments are displayed correctly on the biblio detail page. --- C4/Auth.pm | 12 +++++++----- koha-tmpl/opac-tmpl/ccsr/en/includes/masthead.inc | 12 ++++++------ koha-tmpl/opac-tmpl/prog/en/includes/masthead.inc | 8 ++++---- .../opac-tmpl/prog/en/modules/opac-ISBDdetail.tt | 1 + .../opac-tmpl/prog/en/modules/opac-MARCdetail.tt | 1 + .../opac-tmpl/prog/en/modules/opac-account.tt | 1 + .../opac-tmpl/prog/en/modules/opac-advsearch.tt | 1 + .../prog/en/modules/opac-alert-subscribe.tt | 1 + .../prog/en/modules/opac-auth-MARCdetail.tt | 1 + .../opac-tmpl/prog/en/modules/opac-auth-detail.tt | 1 + koha-tmpl/opac-tmpl/prog/en/modules/opac-auth.tt | 1 + .../prog/en/modules/opac-authorities-home.tt | 1 + .../en/modules/opac-authoritiessearchresultlist.tt | 1 + .../opac-tmpl/prog/en/modules/opac-browser.tt | 1 + .../prog/en/modules/opac-course-details.tt | 1 + .../prog/en/modules/opac-course-reserves.tt | 1 + koha-tmpl/opac-tmpl/prog/en/modules/opac-detail.tt | 9 +++++---- .../opac-tmpl/prog/en/modules/opac-downloadcart.tt | 1 + .../prog/en/modules/opac-downloadshelf.tt | 1 + .../prog/en/modules/opac-full-serial-issues.tt | 1 + .../opac-tmpl/prog/en/modules/opac-imageviewer.tt | 1 + koha-tmpl/opac-tmpl/prog/en/modules/opac-main.tt | 1 + .../modules/opac-memberentry-update-submitted.tt | 1 + .../opac-tmpl/prog/en/modules/opac-memberentry.tt | 1 + .../opac-tmpl/prog/en/modules/opac-messaging.tt | 1 + koha-tmpl/opac-tmpl/prog/en/modules/opac-passwd.tt | 1 + .../opac-tmpl/prog/en/modules/opac-privacy.tt | 1 + .../prog/en/modules/opac-readingrecord.tt | 2 +- .../en/modules/opac-registration-confirmation.tt | 1 + .../en/modules/opac-registration-email-sent.tt | 1 + .../prog/en/modules/opac-registration-invalid.tt | 1 + .../opac-tmpl/prog/en/modules/opac-reserve.tt | 1 + .../prog/en/modules/opac-results-grouped.tt | 1 + .../opac-tmpl/prog/en/modules/opac-results.tt | 1 + .../prog/en/modules/opac-search-history.tt | 1 + .../prog/en/modules/opac-serial-issues.tt | 1 + .../opac-tmpl/prog/en/modules/opac-shelves.tt | 2 +- .../opac-tmpl/prog/en/modules/opac-showreviews.tt | 2 +- .../opac-tmpl/prog/en/modules/opac-suggestions.tt | 1 + koha-tmpl/opac-tmpl/prog/en/modules/opac-tags.tt | 2 +- .../opac-tmpl/prog/en/modules/opac-tags_subject.tt | 1 + .../opac-tmpl/prog/en/modules/opac-topissues.tt | 1 + koha-tmpl/opac-tmpl/prog/en/modules/opac-user.tt | 2 +- 43 files changed, 61 insertions(+), 24 deletions(-) diff --git a/C4/Auth.pm b/C4/Auth.pm index 3c0b804..6070a92 100644 --- a/C4/Auth.pm +++ b/C4/Auth.pm @@ -328,7 +328,6 @@ sub get_template_and_user { noItemTypeImages => C4::Context->preference("noItemTypeImages"), marcflavour => C4::Context->preference("marcflavour"), persona => C4::Context->preference("persona"), - UseCourseReserves => C4::Context->preference("UseCourseReserves"), ); if ( $in->{'type'} eq "intranet" ) { $template->param( @@ -361,6 +360,7 @@ sub get_template_and_user { AllowMultipleCovers => C4::Context->preference('AllowMultipleCovers'), EnableBorrowerFiles => C4::Context->preference('EnableBorrowerFiles'), UseKohaPlugins => C4::Context->preference('UseKohaPlugins'), + UseCourseReserves => C4::Context->preference("UseCourseReserves"), ); } else { @@ -400,7 +400,6 @@ sub get_template_and_user { OpacHighlightedWords => C4::Context->preference("OpacHighlightedWords"), OPACItemHolds => C4::Context->preference("OPACItemHolds"), OPACShelfBrowser => "". C4::Context->preference("OPACShelfBrowser"), - OpacShowRecentComments => C4::Context->preference("OpacShowRecentComments"), OPACURLOpenInNewWindow => "" . C4::Context->preference("OPACURLOpenInNewWindow"), OPACUserCSS => "". C4::Context->preference("OPACUserCSS"), OPACMobileUserCSS => "". C4::Context->preference("OPACMobileUserCSS"), @@ -440,13 +439,11 @@ sub get_template_and_user { opacsmallimage => "" . C4::Context->preference("opacsmallimage"), opacuserjs => C4::Context->preference("opacuserjs"), opacuserlogin => "" . C4::Context->preference("opacuserlogin"), - reviewson => C4::Context->preference("reviewson"), ShowReviewer => C4::Context->preference("ShowReviewer"), ShowReviewerPhoto => C4::Context->preference("ShowReviewerPhoto"), suggestion => "" . C4::Context->preference("suggestion"), virtualshelves => "" . C4::Context->preference("virtualshelves"), OPACSerialIssueDisplayCount => C4::Context->preference("OPACSerialIssueDisplayCount"), - OpacAddMastheadLibraryPulldown => C4::Context->preference("OpacAddMastheadLibraryPulldown"), OPACXSLTDetailsDisplay => C4::Context->preference("OPACXSLTDetailsDisplay"), OPACXSLTResultsDisplay => C4::Context->preference("OPACXSLTResultsDisplay"), SyndeticsClientCode => C4::Context->preference("SyndeticsClientCode"), @@ -982,6 +979,10 @@ sub checkauth { push @inputs, { name => $name, value => $value }; } + my $LibraryNameTitle = C4::Context->preference("LibraryName"); + $LibraryNameTitle =~ s/<(?:\/?)(?:br|p)\s*(?:\/?)>/ /sgi; + $LibraryNameTitle =~ s/<(?:[^<>'"]|'(?:[^']*)'|"(?:[^"]*)")*>//sg; + my $template_name = ( $type eq 'opac' ) ? 'opac-auth.tmpl' : 'auth.tmpl'; my $template = C4::Templates::gettemplate($template_name, $type, $query ); $template->param( @@ -993,7 +994,8 @@ sub checkauth { casAuthentication => C4::Context->preference("casAuthentication"), suggestion => C4::Context->preference("suggestion"), virtualshelves => C4::Context->preference("virtualshelves"), - LibraryName => C4::Context->preference("LibraryName"), + LibraryName => "" . C4::Context->preference("LibraryName"), + LibraryNameTitle => "" . $LibraryNameTitle, opacuserlogin => C4::Context->preference("opacuserlogin"), OpacNav => C4::Context->preference("OpacNav"), OpacNavRight => C4::Context->preference("OpacNavRight"), diff --git a/koha-tmpl/opac-tmpl/ccsr/en/includes/masthead.inc b/koha-tmpl/opac-tmpl/ccsr/en/includes/masthead.inc index 4eb56c8..b85a427 100644 --- a/koha-tmpl/opac-tmpl/ccsr/en/includes/masthead.inc +++ b/koha-tmpl/opac-tmpl/ccsr/en/includes/masthead.inc @@ -29,7 +29,7 @@ [% IF ( OpacPublic ) %]
[% UNLESS ( advsearch ) %] -[% IF ( OpacAddMastheadLibraryPulldown ) %] +[% IF Koha.Preference( 'OpacAddMastheadLibraryPulldown' ) == 1 %] [% IF ( OpacShowFiltersPulldownMobile and not OpacShowLibrariesPulldownMobile ) or ( not OpacShowFiltersPulldownMobile and OpacShowLibrariesPulldownMobile ) %]
[% ELSE %] @@ -94,7 +94,7 @@ [% END %]
- [% IF ( OpacAddMastheadLibraryPulldown ) %] + [% IF Koha.Preference( 'OpacAddMastheadLibraryPulldown' ) == 1 %] [% IF ( OpacShowLibrariesPulldownMobile ) %]
[% ELSE %] @@ -142,7 +142,7 @@ [% ELSE %] - [% IF ( OpacAddMastheadLibraryPulldown ) %] + [% IF Koha.Preference( 'OpacAddMastheadLibraryPulldown' ) == 1 %] [% IF ( OpacShowFiltersPulldownMobile and not OpacShowLibrariesPulldownMobile ) or ( not OpacShowFiltersPulldownMobile and OpacShowLibrariesPulldownMobile ) %]
[% ELSE %] @@ -170,7 +170,7 @@
- [% IF ( OpacAddMastheadLibraryPulldown ) %] + [% IF Koha.Preference( 'OpacAddMastheadLibraryPulldown' ) == 1 %] [% IF ( OpacShowLibrariesPulldownMobile ) %]
[% ELSE %] @@ -192,10 +192,10 @@
Advanced search -[% IF ( UseCourseReserves ) %] | Course Reserves[% END %] +[% IF Koha.Preference( 'UseCourseReserves' ) == 1 %] | Course reserves[% END %] [% IF ( OpacBrowser ) %] | Browse by hierarchy[% END %] [% IF ( OpacAuthorities ) %] | Authority search[% END %] -[% IF ( opacuserlogin && reviewson && OpacShowRecentComments ) %] | Recent comments[% END %] +[% IF ( opacuserlogin && ( Koha.Preference( 'reviewson' ) == 1 ) && ( Koha.Preference( 'OpacShowRecentComments' ) == 1 ) ) %] | Recent comments[% END %] [% IF ( TagsEnabled ) %] | Tag cloud[% END %] [% IF ( OpacCloud ) %] | Subject cloud[% END %] [% IF ( OpacTopissue ) %] | Most popular[% END %] diff --git a/koha-tmpl/opac-tmpl/prog/en/includes/masthead.inc b/koha-tmpl/opac-tmpl/prog/en/includes/masthead.inc index 651e669..b915cb1 100644 --- a/koha-tmpl/opac-tmpl/prog/en/includes/masthead.inc +++ b/koha-tmpl/opac-tmpl/prog/en/includes/masthead.inc @@ -30,7 +30,7 @@
[% UNLESS ( advsearch ) %] @@ -84,7 +84,7 @@ [% ELSE %]
[% END %] - [% IF ( OpacAddMastheadLibraryPulldown ) %] + [% IF Koha.Preference( 'OpacAddMastheadLibraryPulldown' ) == 1 %] - + +
+ + +
-
+
-

Courses

-- 1.7.9.5 From oleonard at myacpl.org Wed Jul 10 18:40:14 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Wed, 10 Jul 2013 12:40:14 -0400 Subject: [Koha-patches] [PATCH] Bug 10558 [Follow-up] Convert records table in manage-marc-import.pl to ajax DataTable Message-ID: <1373474414-6193-1-git-send-email-oleonard@myacpl.org> This patch makes improvements to the default DataTables CSS and corrects a couple of errors in the original patch. CSS for the "full numbers" type pagination, used by this and the quotes editor, has been cleaned up and made more visually consistent with the brief pagination style. Also changed: - removed some hard-coded paths containing "http://staff.kohadev..." - Added a column header to the column showing record match details. This provides both information and a clearer target for clicking to resort - Expanding the default table pager controls for this page and the quotes editor (for consistency) --- koha-tmpl/intranet-tmpl/prog/en/css/datatables.css | 45 ++++++++++++-------- .../prog/en/modules/tools/manage-marc-import.tt | 9 ++-- .../intranet-tmpl/prog/en/modules/tools/quotes.tt | 1 + 3 files changed, 33 insertions(+), 22 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/css/datatables.css b/koha-tmpl/intranet-tmpl/prog/en/css/datatables.css index 92e1768..8e6b867 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/css/datatables.css +++ b/koha-tmpl/intranet-tmpl/prog/en/css/datatables.css @@ -58,12 +58,12 @@ div.dataTables_info { div.dataTables_length, div.dataTables_filter { border-left : 1px solid #FFF; + border-right : 1px solid #AAAAAA; } div.dataTables_filter { line-height : 1.9em; } div.dataTables_paginate { - background-color : #F4F4F4; padding : 0; } @@ -73,42 +73,49 @@ div.dataTables_paginate { border-left : 1px solid #FFF; display : block; float : left; - line-height:1.6em; - padding: .3em .7em; + line-height:1.9em; + padding : 0.4em 0.7em; cursor: pointer; } .paging_full_numbers a.paginate_button { + background-color : #FFF; + background-repeat: no-repeat; color : #0000CC; } .paging_full_numbers a.paginate_button.first { + background-color: transparent; background-image : url('../../img/first.png'); - background-repeat: no-repeat; - background-position : 1% center; - padding-left : 2em; + background-position : 3px center; + padding-left : 23px; } .paging_full_numbers a.paginate_button.previous { + background-color: transparent; background-image : url('../../img/prev.png'); - background-repeat: no-repeat; - background-position : 1% center; - padding-left : 2em; + background-position : 3px center; + padding-left : 23px; } .paging_full_numbers a.paginate_button.next { + background-color: transparent; background-image : url('../../img/next.png'); - background-repeat: no-repeat; - background-position : 96% center; - padding-right : 2em; + background-position : 93% center; + padding-right : 25px; } .paging_full_numbers a.paginate_button.last { + background-color: transparent; background-image : url('../../img/last.png'); - background-repeat: no-repeat; - background-position : 96% center; - border-right : 1px solid #686868; - padding-right : 2em; + background-position : 93% center; + border-right : 0; + padding-right : 25px; } div.bottom.pager .paging_full_numbers a.paginate_button.last { border-right-width : 0; } + +div.bottom.pager div:first-child { + border-left : 0; +} + .paging_full_numbers a.paginate_active { background-color : #FFFFEA; color : #000; @@ -203,8 +210,10 @@ div.dataTables_paginate.paging_four_button { .dataTables_processing { background-color: white; - border: 1px solid #DDDDDD; - color: #999999; + border: 1px solid #999; + -webkit-box-shadow: 2px 2px 3px 1px rgba(0, 0, 0, 0.2); + box-shadow: 2px 2px 3px 1px rgba(0, 0, 0, 0.2); + color: #333; font-size: 14px; height: 30px; left: 50%; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/manage-marc-import.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/manage-marc-import.tt index 57faa85..08d90b5 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/manage-marc-import.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/manage-marc-import.tt @@ -36,6 +36,7 @@ $(document).ready(function(){ "bServerSide": true, "sAjaxSource": 'batch_records_ajax.pl', "sPaginationType": "full_numbers", + "sDom": '<"top pager"iflp>rt<"bottom pager"flp><"clear">', "aoColumns": [ { "mDataProp": "import_record_id" }, { "mDataProp": "citation" }, @@ -64,13 +65,13 @@ $(document).ready(function(){ + aData['match_id'] + " (" + _("score") + "=" + aData['score'] - + '):' + '' + aData['match_citation'] + '' ); } $('td:eq(5)', nRow).html( - '' + aData['matched'] + '' ); }, @@ -372,8 +373,8 @@ Page - - + + diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/quotes.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/quotes.tt index 493c34b..6801001 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/quotes.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/quotes.tt @@ -22,6 +22,7 @@ "bProcessing" : true, "bPaginate" : true, "sPaginationType" : "full_numbers", + "sDom": '<"top pager"iflp>rt<"bottom pager"flp><"clear">', "sAjaxSource" : "/cgi-bin/koha/tools/quotes/quotes_ajax.pl", "aoColumns" : [ { "sWidth": "3%" }, -- 1.7.9.5 From srdjan at catalyst.net.nz Thu Jul 11 03:58:08 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Thu, 11 Jul 2013 13:58:08 +1200 Subject: [Koha-patches] [PATCH] [SIGNED-OFF] Bug 10515: The prototype for GetBranchCategory and GetBranchCategories is not consistent Message-ID: <1373507888-5615-1-git-send-email-srdjan@catalyst.net.nz> From: Jonathan Druart The prototype is not consistent, GetBranchCategory should return only 1 result and GetBranchCategories should not have a categorycode argument. This patch fixes that. Test plan: 1/ Try to add/remove/modify a library. 2/ Add some groups 3/ Add these groups to a library Signed-off-by: Srdjan --- C4/Branch.pm | 63 ++++++++-------------- admin/branches.pl | 47 +++++++--------- catalogue/search.pl | 2 +- .../prog/en/modules/admin/branches.tt | 2 +- opac/opac-search.pl | 2 +- 5 files changed, 44 insertions(+), 72 deletions(-) diff --git a/C4/Branch.pm b/C4/Branch.pm index 5770f7b..5783de9 100644 --- a/C4/Branch.pm +++ b/C4/Branch.pm @@ -248,7 +248,7 @@ sub ModBranch { } # sort out the categories.... my @checkedcats; - my $cats = GetBranchCategory(); + my $cats = GetBranchCategories(); foreach my $cat (@$cats) { my $code = $cat->{'categorycode'}; if ( $data->{$code} ) { @@ -294,87 +294,66 @@ sub ModBranch { $results = GetBranchCategory($categorycode); -C<$results> is an ref to an array. +C<$results> is an hashref =cut sub GetBranchCategory { - - # returns a reference to an array of hashes containing branches, my ($catcode) = @_; + return unless $catcode; + my $dbh = C4::Context->dbh; my $sth; - # print DEBUG "GetBranchCategory: entry: catcode=".cvs($catcode)."\n"; - if ($catcode) { - $sth = - $dbh->prepare( - "select * from branchcategories where categorycode = ?"); - $sth->execute($catcode); - } - else { - $sth = $dbh->prepare("Select * from branchcategories"); - $sth->execute(); - } - my @results; - while ( my $data = $sth->fetchrow_hashref ) { - push( @results, $data ); - } - $sth->finish; - - # print DEBUG "GetBranchCategory: exit: returning ".cvs(\@results)."\n"; - return \@results; + $sth = $dbh->prepare(q{ + SELECT * + FROM branchcategories + WHERE categorycode = ? + }); + $sth->execute( $catcode ); + return $sth->fetchrow_hashref; } =head2 GetBranchCategories - my $categories = GetBranchCategories($branchcode,$categorytype,$show_in_pulldown,$selected_in_pulldown); + my $categories = GetBranchCategories($categorytype,$show_in_pulldown,$selected_in_pulldown); Returns a list ref of anon hashrefs with keys eq columns of branchcategories table, -i.e. categorycode, categorydescription, categorytype, categoryname. -if $branchcode and/or $categorytype are passed, limit set to categories that -$branchcode is a member of , and to $categorytype. +i.e. categorydescription, categorytype, categoryname. =cut sub GetBranchCategories { - my ( $branchcode, $categorytype, $show_in_pulldown, $selected_in_pulldown ) = @_; + my ( $categorytype, $show_in_pulldown, $selected_in_pulldown ) = @_; my $dbh = C4::Context->dbh(); - my $query = "SELECT c.* FROM branchcategories c"; - my ( @where, @bind ); - - if( $branchcode ) { - $query .= ",branchrelations r, branches b "; - push @where, "c.categorycode = r.categorycode AND r.branchcode = ? "; - push @bind , $branchcode; - } + my $query = "SELECT * FROM branchcategories "; + my ( @where, @bind ); if ( $categorytype ) { - push @where, " c.categorytype = ? "; + push @where, " categorytype = ? "; push @bind, $categorytype; } if ( defined( $show_in_pulldown ) ) { - push( @where, " c.show_in_pulldown = ? " ); + push( @where, " show_in_pulldown = ? " ); push( @bind, $show_in_pulldown ); } $query .= " WHERE " . join(" AND ", @where) if(@where); - $query .= " ORDER BY categorytype,c.categorycode"; + $query .= " ORDER BY categorytype, categorycode"; my $sth=$dbh->prepare( $query); $sth->execute(@bind); my $branchcats = $sth->fetchall_arrayref({}); - $sth->finish(); if ( $selected_in_pulldown ) { foreach my $bc ( @$branchcats ) { - $bc->{'selected'} = 1 if ( $bc->{'categorycode'} eq $selected_in_pulldown ); + $bc->{selected} = 1 if $bc->{categorycode} eq $selected_in_pulldown; } } - return( $branchcats ); + return $branchcats; } =head2 GetCategoryTypes diff --git a/admin/branches.pl b/admin/branches.pl index 026d983..9e6b14a 100755 --- a/admin/branches.pl +++ b/admin/branches.pl @@ -234,14 +234,31 @@ sub editbranchform { my $data; my $oldprinter = ""; + + # make the checkboxes..... + my $catinfo = GetBranchCategories(); + if ($branchcode) { $data = GetBranchInfo($branchcode); $data = $data->[0]; + if ( exists $data->{categories} ) { + # Set the selected flag for the categories of this branch + $catinfo = [ + map { + my $catcode = $_->{categorycode}; + if ( grep {/$catcode/} @{$data->{categories}} ){ + $_->{selected} = 1; + } + $_; + } @{$catinfo} + ]; + } # get the old printer of the branch $oldprinter = $data->{'branchprinter'} || ''; _branch_to_template($data, $innertemplate); } + $innertemplate->param( categoryloop => $catinfo ); foreach my $thisprinter ( keys %$printers ) { push @printerloop, { @@ -252,29 +269,6 @@ sub editbranchform { } $innertemplate->param( printerloop => \@printerloop ); - # make the checkboxes..... - # - # We export a "categoryloop" array to the template, each element of which - # contains separate 'categoryname', 'categorycode', 'codedescription', and - # 'checked' fields. The $checked field is either empty or 1' - - my $catinfo = GetBranchCategory(); - my @categoryloop = (); - foreach my $cat (@$catinfo) { - my $checked; - my $tmp = quotemeta( $cat->{'categorycode'} ); - if ( grep { /^$tmp$/ } @{ $data->{'categories'} } ) { - $checked = 1; - } - push @categoryloop, { - categoryname => $cat->{'categoryname'}, - categorycode => $cat->{'categorycode'}, - categorytype => $cat->{'categorytype'}, - codedescription => $cat->{'codedescription'}, - checked => $checked, - }; - } - $innertemplate->param( categoryloop => \@categoryloop ); for my $obsolete ( 'categoryname', 'categorycode', 'codedescription' ) { $innertemplate->param( @@ -291,7 +285,6 @@ sub editcatform { my $data; if ($categorycode) { my $data = GetBranchCategory($categorycode); - $data = $data->[0]; $innertemplate->param( categorycode => $data->{'categorycode'}, categoryname => $data->{'categoryname'}, @@ -360,7 +353,7 @@ sub branchinfotable { my $no_categories_p = 1; my @categories; foreach my $cat ( @{ $branch->{'categories'} } ) { - my ($catinfo) = @{ GetBranchCategory($cat) }; + my $catinfo = GetBranchCategory($cat); push @categories, { 'categoryname' => $catinfo->{'categoryname'} }; $no_categories_p = 0; } @@ -375,8 +368,8 @@ sub branchinfotable { } my @branchcategories = (); for my $ctype ( GetCategoryTypes() ) { - my $catinfo = GetBranchCategories(undef,$ctype); - my @categories; + my $catinfo = GetBranchCategories($ctype); + my @categories; foreach my $cat (@$catinfo) { push @categories, { categoryname => $cat->{'categoryname'}, diff --git a/catalogue/search.pl b/catalogue/search.pl index d4e98b18..f8dab56 100755 --- a/catalogue/search.pl +++ b/catalogue/search.pl @@ -237,7 +237,7 @@ my @branch_loop = map { $branches->{$a}->{branchname} cmp $branches->{$b}->{branchname} } keys %$branches; -my $categories = GetBranchCategories(undef,'searchdomain'); +my $categories = GetBranchCategories('searchdomain'); $template->param(branchloop => \@branch_loop, searchdomainloop => $categories); diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branches.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branches.tt index 902f809..86fb8ce 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branches.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/branches.tt @@ -107,7 +107,7 @@ tinyMCE.init({
    [% FOREACH categoryloo IN categoryloop %]
  1. - [% IF ( categoryloo.checked ) %] + [% IF categoryloo.selected %] [% ELSE %] diff --git a/opac/opac-search.pl b/opac/opac-search.pl index dfe651e..880317a 100755 --- a/opac/opac-search.pl +++ b/opac/opac-search.pl @@ -193,7 +193,7 @@ if (C4::Context->preference('TagsEnabled')) { my $branches = GetBranches(); # used later in *getRecords, probably should be internalized by those functions after caching in C4::Branch is established $template->param( - searchdomainloop => GetBranchCategories(undef,'searchdomain'), + searchdomainloop => GetBranchCategories('searchdomain'), ); # load the language limits (for search) -- 1.8.1.2 From srdjan at catalyst.net.nz Thu Jul 11 05:19:03 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Thu, 11 Jul 2013 15:19:03 +1200 Subject: [Koha-patches] [PATCH] [SIGNED-OFF] Bug 10504: Remove the unused C4::Acq::ModOrderItem routine Message-ID: <1373512743-12589-1-git-send-email-srdjan@catalyst.net.nz> From: Jonathan Druart This routine has been introduced by commit 2d90fb22d43db986547bbaa945873d6dd78aab71. The only call has been removed by commit 9eba7dc594fc0d4698da5e791d5f6f8682b2712a. So now, this routine is useless. Signed-off-by: Srdjan --- C4/Acquisition.pm | 33 +-------------------------------- cataloguing/moveitem.pl | 2 +- 2 files changed, 2 insertions(+), 33 deletions(-) diff --git a/C4/Acquisition.pm b/C4/Acquisition.pm index b7ba2e1..1a210b5 100644 --- a/C4/Acquisition.pm +++ b/C4/Acquisition.pm @@ -59,7 +59,7 @@ BEGIN { &ModReceiveOrder &CancelReceipt &GetCancelledOrders &GetLastOrderNotReceivedFromSubscriptionid &GetLastOrderReceivedFromSubscriptionid - &NewOrderItem &ModOrderItem &ModItemOrder + &NewOrderItem &ModItemOrder &GetParcels &GetParcel &GetContracts &GetContract @@ -1225,37 +1225,6 @@ sub ModOrder { #------------------------------------------------------------# -=head3 ModOrderItem - - &ModOrderItem(\%hashref); - -Modifies the itemnumber in the aqorders_items table. The input hash needs three entities: - -=over - -=item - itemnumber: the old itemnumber -=item - ordernumber: the order this item is attached to -=item - newitemnumber: the new itemnumber we want to attach the line to - -=back - -=cut - -sub ModOrderItem { - my $orderiteminfo = shift; - if (! $orderiteminfo->{'ordernumber'} || ! $orderiteminfo->{'itemnumber'} || ! $orderiteminfo->{'newitemnumber'}){ - die "Ordernumber, itemnumber and newitemnumber is required"; - } - - my $dbh = C4::Context->dbh; - - my $query = "UPDATE aqorders_items set itemnumber=? where itemnumber=? and ordernumber=?"; - my @params = ($orderiteminfo->{'newitemnumber'}, $orderiteminfo->{'itemnumber'}, $orderiteminfo->{'ordernumber'}); - my $sth = $dbh->prepare($query); - $sth->execute(@params); - return 0; -} - =head3 ModItemOrder ModItemOrder($itemnumber, $ordernumber); diff --git a/cataloguing/moveitem.pl b/cataloguing/moveitem.pl index 24414cc..2622c36 100755 --- a/cataloguing/moveitem.pl +++ b/cataloguing/moveitem.pl @@ -30,7 +30,7 @@ use C4::Context; use C4::Koha; use C4::Branch; use C4::ClassSource; -use C4::Acquisition qw/GetOrderFromItemnumber ModOrder GetOrder ModOrderItem/; +use C4::Acquisition qw/GetOrderFromItemnumber ModOrder GetOrder/; use Date::Calc qw(Today); -- 1.8.1.2 From oleonard at myacpl.org Thu Jul 11 16:34:21 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Thu, 11 Jul 2013 10:34:21 -0400 Subject: [Koha-patches] [PATCH] Bug 10514 [Alternate] Add item link on acquisitions add item is too small Message-ID: <1373553262-9935-1-git-send-email-oleonard@myacpl.org> This alternate patch for Bug 10514 converts the "Add" and "Clear" links to the standard "submit/cancel" format inside a fieldset. This gives them a little more visual weight to solve the problem in a differnt way. Based on the changes made by Liz Rea and Jonathan Druart. Same test plan: create a basket add a record to it scroll down - the link to add item and cancel should both be more prominent now. Click "Add item" - it should add an item. --- koha-tmpl/intranet-tmpl/prog/en/js/additem.js | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/additem.js b/koha-tmpl/intranet-tmpl/prog/en/js/additem.js index 2c15b04..9dfaa1f 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/js/additem.js +++ b/koha-tmpl/intranet-tmpl/prog/en/js/additem.js @@ -1,5 +1,5 @@ function addItem( node, unique_item_fields ) { - var index = $(node).parent().attr('id'); + var index = $(node).closest("div").attr('id'); var current_qty = parseInt($("#quantity").val()); var max_qty; if($("#quantity_to_receive").length != 0){ @@ -12,7 +12,7 @@ function addItem( node, unique_item_fields ) { if ( current_qty < max_qty - 1 ) cloneItemBlock(index, unique_item_fields); addItemInList(index, unique_item_fields); - $("#" + index).find("a[name='buttonPlus']").text("Update"); + $("#" + index).find("input[name='buttonPlus']").val("Update"); $("#quantity").val(current_qty + 1).change(); } else if ( current_qty >= max_qty ) { alert(window.MSG_ADDITEM_JS_CANT_RECEIVE_MORE_ITEMS @@ -134,9 +134,12 @@ function cloneItemBlock(index, unique_item_fields) { $(this).val(random); }); /* Add buttons + and Clear */ - var buttonPlus = 'Add'; - var buttonClear = '' + (window.MSG_ADDITEM_JS_CLEAR || 'Clear') + ''; - $(clone).append(buttonPlus).append(buttonClear); + var buttonPlus = "
    "; + var buttonPlusText = _("Add item"); + buttonPlus += ''; + buttonPlus += '' + (window.MSG_ADDITEM_JS_CLEAR || 'Clear') + ''; + buttonPlus += "
    "; + $(clone).append(buttonPlus); /* Copy values from the original block (input) */ $(original).find("input[name='field_value']").each(function(){ var kohafield = $(this).siblings("input[name='kohafield']").val(); @@ -164,7 +167,7 @@ function cloneItemBlock(index, unique_item_fields) { } function clearItemBlock(node) { - var index = $(node).parent().attr('id'); + var index = $(node).closest("div").attr('id'); var block = $("#"+index); $(block).find("input[type='text']").each(function(){ $(this).val(""); -- 1.7.9.5 From christophe.croullebois at biblibre.com Thu Jul 11 17:41:18 2013 From: christophe.croullebois at biblibre.com (Christophe Croullebois) Date: Thu, 11 Jul 2013 17:41:18 +0200 Subject: [Koha-patches] =?utf-8?q?=5BPATCH_1/1=5D_Bug_10573=3A_French_tran?= =?utf-8?q?slation_for_printing_a_basketgroup?= Message-ID: <1373557278-12769-1-git-send-email-christophe.croullebois@biblibre.com> If you want to print a basketgroup with pdf format, it will be in english. The pdf is done with layout2pages.pm or layout3pages.pm which call layout2pages.pdf or layout3pages.pdf. This patch adds layout3pagesfr.pm in src/acqui/pdfformat/ which calls layout3pagesfr.pdf. And adds in basketgroup.pl the check for layout3pagesfr To use it you have to change the systempreferences to pdfformat::layout3pagesfr --- acqui/basketgroup.pl | 2 +- acqui/pdfformat/layout3pagesfr.pm | 439 ++++++++++++++++++++ .../intranet-tmpl/prog/pdf/layout3pagesfr.odt | Bin 0 -> 13284 bytes .../intranet-tmpl/prog/pdf/layout3pagesfr.pdf | Bin 0 -> 24394 bytes 4 files changed, 440 insertions(+), 1 deletion(-) create mode 100644 acqui/pdfformat/layout3pagesfr.pm create mode 100644 koha-tmpl/intranet-tmpl/prog/pdf/layout3pagesfr.odt create mode 100644 koha-tmpl/intranet-tmpl/prog/pdf/layout3pagesfr.pdf diff --git a/acqui/basketgroup.pl b/acqui/basketgroup.pl index 398980c..6fe4db2 100755 --- a/acqui/basketgroup.pl +++ b/acqui/basketgroup.pl @@ -189,7 +189,7 @@ sub printbasketgrouppdf{ my ($basketgroupid) = @_; my $pdfformat = C4::Context->preference("OrderPdfFormat"); - if ($pdfformat eq 'pdfformat::layout3pages' || $pdfformat eq 'pdfformat::layout2pages'){ + if ($pdfformat eq 'pdfformat::layout3pages' || $pdfformat eq 'pdfformat::layout2pages' || $pdfformat eq 'pdfformat::layout3pagesfr'){ eval { eval "require $pdfformat"; import $pdfformat; diff --git a/acqui/pdfformat/layout3pagesfr.pm b/acqui/pdfformat/layout3pagesfr.pm new file mode 100644 index 0000000..dc4a152 --- /dev/null +++ b/acqui/pdfformat/layout3pagesfr.pm @@ -0,0 +1,439 @@ +#!/usr/bin/perl + +#example script to print a basketgroup +#written 07/11/08 by john.soros at biblibre.com and paul.poulain at biblibre.com + +# Copyright 2008-2009 BibLibre SARL +# +# 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. + +#you can use any PDF::API2 module, all you need to do is return the stringifyed pdf object from the printpdf sub. +package pdfformat::layout3pagesfr; +use vars qw($VERSION @ISA @EXPORT); +use Number::Format qw(format_price); +use MIME::Base64; +use List::MoreUtils qw/uniq/; +use strict; +use warnings; +use utf8; + +use C4::Branch qw(GetBranchDetail GetBranchName); + +BEGIN { + use Exporter (); + our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS); + # set the version for version checking + $VERSION = 1.00; + @ISA = qw(Exporter); + @EXPORT = qw(printpdf); +} + + +#be careful, all the sizes (height, width, etc...) are in mm, not PostScript points (the default measurment of PDF::API2). +#The constants exported tranform that into PostScript points (/mm for milimeter, /in for inch, pt is postscript point, and as so is there only to show what is happening. +use constant mm => 25.4 / 72; +use constant in => 1 / 72; +use constant pt => 1; + +use PDF::API2; +#A4 paper specs +my ($height, $width) = (297, 210); +use PDF::Table; + +sub printorders { + my ($pdf, $basketgroup, $baskets, $orders) = @_; + + my $cur_format = C4::Context->preference("CurrencyFormat"); + my $num; + + if ( $cur_format eq 'FR' ) { + $num = new Number::Format( + 'decimal_fill' => '2', + 'decimal_point' => ',', + 'int_curr_symbol' => '', + 'mon_thousands_sep' => ' ', + 'thousands_sep' => ' ', + 'mon_decimal_point' => ',' + ); + } else { # US by default.. + $num = new Number::Format( + 'int_curr_symbol' => '', + 'mon_thousands_sep' => ',', + 'mon_decimal_point' => '.' + ); + } + + $pdf->mediabox($height/mm, $width/mm); + my $number = 3; + for my $basket (@$baskets){ + my $page = $pdf->page(); + + # print basket header (box) + my $box = $page->gfx; + $box->rectxy(($width - 10)/mm, ($height - 5)/mm, 10/mm, ($height - 25)/mm); + $box->stroke; +# $box->restore(); + + # create a text + my $text = $page->text; + # add basketgroup number + $text->font( $pdf->corefont("Times", -encoding => "utf8"), 6/mm ); + $text->translate(20/mm, ($height-15)/mm); + $text->text("Commande N?".$basketgroup->{'id'}.". Panier N? ".$basket->{basketno}.". ".$basket->{booksellernote}); + $text->translate(20/mm, ($height-20)/mm); + $text->font( $pdf->corefont("Times", -encoding => "utf8"), 4/mm ); + $text->text( ( $basket->{billingplace} ? "Facturation ? " . C4::Branch::GetBranchName( $basket->{billingplace} ) : "" ) + . ( $basket->{billingplace} and $basket->{deliveryplace} ? " et " : "" ) + . ( $basket->{deliveryplace} ? "livraison ? " . C4::Branch::GetBranchName( $basket->{deliveryplace}) : "" ) + ); + + my $pdftable = new PDF::Table(); + my $abaskets; + my $arrbasket; + my @keys = ('Document', 'Qte', 'Prix', 'Prix net', '% Remise', 'Remise', 'Taux TVA', 'Total HT', 'Total TTC'); + for my $bkey (@keys) { + push(@$arrbasket, $bkey); + } + push(@$abaskets, $arrbasket); + foreach my $line (@{$orders->{$basket->{basketno}}}) { + $arrbasket = undef; + push( @$arrbasket, + $line->{title} . " / " . $line->{author} . ( $line->{isbn} ? " ISBN : " . $line->{isbn} : '' ) . ( $line->{en} ? " EN : " . $line->{en} : '' ) . ", " . $line->{itemtype} . ( $line->{publishercode} ? ' published by '. $line->{publishercode} : ""), + $line->{quantity}, + $num->format_price($line->{rrpgste}), + $num->format_price($line->{rrpgsti}), + $num->format_price($line->{discount}).'%', + $num->format_price($line->{rrpgste} - $line->{ecostgste}), + $num->format_price($line->{gstrate} * 100).'%', + $num->format_price($line->{totalgste}), + $num->format_price($line->{totalgsti}), + ); + push(@$abaskets, $arrbasket); + } + + $pdftable->table($pdf, $page, $abaskets, + x => 10/mm, + w => ($width - 20)/mm, + start_y => 270/mm, + next_y => 285/mm, + start_h => 250/mm, + next_h => 250/mm, + padding => 5, + padding_right => 5, + background_color_odd => "lightgray", + font => $pdf->corefont("Times", -encoding => "utf8"), + font_size => 3/mm, + header_props => { + font => $pdf->corefont("Times", -encoding => "utf8"), + font_size => 9, + bg_color => 'gray', + repeat => 1, + }, + column_props => [ + { + min_w => 85/mm, # Minimum column width. + }, + { + justify => 'right', # One of left|right , + }, + { + justify => 'right', # One of left|right , + }, + { + justify => 'right', # One of left|right , + }, + { + justify => 'right', # One of left|right , + }, + { + justify => 'right', # One of left|right , + }, + { + justify => 'right', # One of left|right , + }, + { + justify => 'right', # One of left|right , + }, + { + justify => 'right', # One of left|right , + }, + ], + ); + } + $pdf->mediabox($width/mm, $height/mm); +} + +sub printbaskets { + my ($pdf, $basketgroup, $hbaskets, $bookseller, $GSTrate, $orders) = @_; + + # get library name + my $libraryname = C4::Context->preference("LibraryName"); + + my $cur_format = C4::Context->preference("CurrencyFormat"); + my $num; + + if ( $cur_format eq 'FR' ) { + $num = new Number::Format( + 'decimal_fill' => '2', + 'decimal_point' => ',', + 'int_curr_symbol' => '', + 'mon_thousands_sep' => ' ', + 'thousands_sep' => ' ', + 'mon_decimal_point' => ',' + ); + } else { # US by default.. + $num = new Number::Format( + 'int_curr_symbol' => '', + 'mon_thousands_sep' => ',', + 'mon_decimal_point' => '.' + ); + } + + $pdf->mediabox($width/mm, $height/mm); + my $page = $pdf->openpage(2); + # create a text + my $text = $page->text; + + # add basketgroup number + $text->font( $pdf->corefont("Times", -encoding => "utf8"), 6/mm ); + $text->translate(($width-40)/mm, ($height-53)/mm); + $text->text("".$basketgroup->{'id'}); + # print the libraryname in the header + $text->font( $pdf->corefont("Times", -encoding => "utf8"), 6/mm ); + $text->translate(30/mm, ($height-28.5)/mm); + $text->text($libraryname); + my $pdftable = new PDF::Table(); + my $abaskets; + my $arrbasket; + # header of the table + my @keys = ('Lot', 'Panier', 'Prix', 'Prix net', 'Taux TVA', 'TVA', 'Remise', 'Total HT', 'Total TTC'); + for my $bkey (@keys) { + push(@$arrbasket, $bkey); + } + my ($grandtotalrrpgsti, $grandtotalrrpgste, $grandtotalgsti, $grandtotalgste, $grandtotalgstvalue, $grandtotaldiscount); + # calculate each basket total + push(@$abaskets, $arrbasket); + for my $basket (@$hbaskets) { + my @gst; + $arrbasket = undef; + my ($totalrrpgste, $totalrrpgsti, $totalgste, $totalgsti, $totalgstvalue, $totaldiscount); + my $ords = $orders->{$basket->{basketno}}; + my $ordlength = @$ords; + foreach my $ord (@$ords) { + $totalgste += $ord->{totalgste}; + $totalgsti += $ord->{totalgsti}; + $totalgstvalue += $ord->{gstvalue}; + $totaldiscount += ($ord->{rrpgste} - $ord->{ecostgste} ) * $ord->{quantity}; + $totalrrpgste += $ord->{rrpgste} * $ord->{quantity}; + $totalrrpgsti += $ord->{rrpgsti} * $ord->{quantity}; + push @gst, $ord->{gstrate}; + } + @gst = uniq map { $_ * 100 } @gst; + $totalgsti = $num->round($totalgsti); + $totalgste = $num->round($totalgste); + $grandtotalrrpgste += $totalrrpgste; + $grandtotalrrpgsti += $totalrrpgsti; + $grandtotalgsti += $totalgsti; + $grandtotalgste += $totalgste; + $grandtotalgstvalue += $totalgstvalue; + $grandtotaldiscount += $totaldiscount; + my @gst_string = map{$num->format_price( $_ ) . '%'} @gst; + push(@$arrbasket, + $basket->{contractname}, + $basket->{basketname} . ' (No. ' . $basket->{basketno} . ')', + $num->format_price($totalrrpgste), + $num->format_price($totalrrpgsti), + "@gst_string", + $num->format_price($totalgstvalue), + $num->format_price($totaldiscount), + $num->format_price($totalgste), + $num->format_price($totalgsti) + ); + push(@$abaskets, $arrbasket); + } + # now, push total + undef $arrbasket; + push @$arrbasket,'','Total', $num->format_price($grandtotalrrpgste), $num->format_price($grandtotalrrpgsti), '', $num->format_price($grandtotalgstvalue), $num->format_price($grandtotaldiscount), $num->format_price($grandtotalgste), $num->format_price($grandtotalgsti); + push @$abaskets,$arrbasket; + # height is width and width is height in this function, as the pdf is in landscape mode for the Tables. + + $pdftable->table($pdf, $page, $abaskets, + x => 5/mm, + w => ($width - 10)/mm, + start_y => 230/mm, + next_y => 230/mm, + start_h => 230/mm, + next_h => 230/mm, + font => $pdf->corefont("Times", -encoding => "utf8"), + font_size => 3/mm, + padding => 5, + padding_right => 10, + background_color_odd => "lightgray", + header_props => { + bg_color => 'gray', + repeat => 1, + }, + column_props => [ + { + }, + { + }, + { + justify => 'right', + }, + { + justify => 'right', + }, + { + justify => 'right', + }, + { + justify => 'right', + }, + { + justify => 'right', + }, + ], + ); + $pdf->mediabox($height/mm, $width/mm); +} + +sub printhead { + my ($pdf, $basketgroup, $bookseller) = @_; + + # get library name + my $libraryname = C4::Context->preference("LibraryName"); + # get branch details + my $billingdetails = GetBranchDetail( $basketgroup->{billingplace} ); + my $deliverydetails = GetBranchDetail( $basketgroup->{deliveryplace} ); + my $freedeliveryplace = $basketgroup->{freedeliveryplace}; + # get the subject + my $subject; + + # open 1st page (with the header) + my $page = $pdf->openpage(1); + + # create a text + my $text = $page->text; + + # print the libraryname in the header + $text->font( $pdf->corefont("Times", -encoding => "utf8"), 6/mm ); + $text->translate(30/mm, ($height-28.5)/mm); + $text->text($libraryname); + + # print order info, on the default PDF + $text->font( $pdf->corefont("Times", -encoding => "utf8"), 8/mm ); + $text->translate(100/mm, ($height-5-48)/mm); + $text->text($basketgroup->{'id'}); + + # print the date + my $today = C4::Dates->today(); + $text->translate(130/mm, ($height-5-48)/mm); + $text->text($today); + + $text->font( $pdf->corefont("Times", -encoding => "utf8"), 4/mm ); + + # print billing infos + $text->translate(100/mm, ($height-86)/mm); + $text->text($libraryname); + $text->translate(100/mm, ($height-97)/mm); + $text->text($billingdetails->{branchname}); + $text->translate(100/mm, ($height-108.5)/mm); + $text->text($billingdetails->{branchphone}); + $text->translate(100/mm, ($height-115.5)/mm); + $text->text($billingdetails->{branchfax}); + $text->translate(100/mm, ($height-122.5)/mm); + $text->text($billingdetails->{branchaddress1}); + $text->translate(100/mm, ($height-127.5)/mm); + $text->text($billingdetails->{branchaddress2}); + $text->translate(100/mm, ($height-132.5)/mm); + $text->text($billingdetails->{branchaddress3}); + $text->translate(100/mm, ($height-137.5)/mm); + $text->text(join(' ', $billingdetails->{branchzip}, $billingdetails->{branchcity}, $billingdetails->{branchcountry})); + $text->translate(100/mm, ($height-147.5)/mm); + $text->text($billingdetails->{branchemail}); + + # print subject + $text->translate(100/mm, ($height-145.5)/mm); + $text->text($subject); + + # print bookseller infos + $text->translate(100/mm, ($height-180)/mm); + $text->text($bookseller->{name}); + $text->translate(100/mm, ($height-185)/mm); + $text->text($bookseller->{postal}); + $text->translate(100/mm, ($height-190)/mm); + $text->text($bookseller->{address1}); + $text->translate(100/mm, ($height-195)/mm); + $text->text($bookseller->{address2}); + $text->translate(100/mm, ($height-200)/mm); + $text->text($bookseller->{address3}); + + # print delivery infos + $text->font( $pdf->corefont("Times-Bold", -encoding => "utf8"), 4/mm ); + $text->translate(50/mm, ($height-237)/mm); + if ($freedeliveryplace) { + my $start = 242; + my @fdp = split('\n', $freedeliveryplace); + foreach (@fdp) { + $text->text($_); + $text->translate( 50 / mm, ( $height - $start ) / mm ); + $start += 5; + } + } else { + $text->text($deliverydetails->{branchaddress1}); + $text->translate(50/mm, ($height-242)/mm); + $text->text($deliverydetails->{branchaddress2}); + $text->translate(50/mm, ($height-247)/mm); + $text->text($deliverydetails->{branchaddress3}); + $text->translate(50/mm, ($height-252)/mm); + $text->text(join(' ', $deliverydetails->{branchzip}, $deliverydetails->{branchcity}, $deliverydetails->{branchcountry})); + } + $text->translate(50/mm, ($height-262)/mm); + $text->text($basketgroup->{deliverycomment}); +} + +sub printfooters { + my ($pdf) = @_; + for (my $i=1;$i <= $pdf->pages;$i++) { + my $page = $pdf->openpage($i); + my $text = $page->text; + $text->font( $pdf->corefont("Times", -encoding => "utf8"), 3/mm ); + $text->translate(10/mm, 10/mm); + $text->text("Page $i / ".$pdf->pages); + } +} + +sub printpdf { + my ($basketgroup, $bookseller, $baskets, $orders, $GST) = @_; + # open the default PDF that will be used for base (1st page already filled) + my $pdf_template = C4::Context->config('intrahtdocs') . '/' . C4::Context->preference('template') . '/pdf/layout3pagesfr.pdf'; + my $pdf = PDF::API2->open($pdf_template); + $pdf->pageLabel( 0, { + -style => 'roman', + } ); # start with roman numbering + # fill the 1st page (basketgroup information) + printhead($pdf, $basketgroup, $bookseller); + # fill the 2nd page (orders summary) + printbaskets($pdf, $basketgroup, $baskets, $bookseller, $GST, $orders); + # fill other pages (orders) + printorders($pdf, $basketgroup, $baskets, $orders); + # print something on each page (usually the footer, but you could also put a header + printfooters($pdf); + return $pdf->stringify; +} + +1; diff --git a/koha-tmpl/intranet-tmpl/prog/pdf/layout3pagesfr.odt b/koha-tmpl/intranet-tmpl/prog/pdf/layout3pagesfr.odt new file mode 100644 index 0000000000000000000000000000000000000000..041c011a100b6bcd2112a907a151dfc25475ae4e GIT binary patch literal 13284 zcmch8XIKt07IAohAcr4L^4X2EE&llIY-GkO9oM* zWC4LY=(4(gyL9Uc2%HmU3x=A)K#n$Gr~{`1*u_EpFJ#&~ z%HlMr0Knz(oeb;%7*pF z#9?M;5D-}Oss#>&DnMEU6bcvpQ6)j=Xb%Wu{U~v< zhCr<(=qwx at Y(=@aoSmIHo%uLn_U2qXA|fJO-)rgqXv!4yr<|>$z4dn~QxF%}8hqJp zI2R8m57(9KrH21isY}^kRf54_e>Qa4haX-1-W)GCH$T^p>#LT`?M+Rs|CIlw0|;3@ zE^{tZpaYP at 2?BP$O-K8O9e*)6FP-F-buZPB6#uS_IT#AI2Rgv)C6ys2_F%Q|=I7$$ z6rfjzKpkC-bc6+s1o>%ysWh^+hgpI_4qSW!+%`P)cO4=g zD!?PkbEVC9)DNK_D6lD_|4?%dkSoX<4432+_(SdA%Ks{C>WH`_h`vjzYw~a_@`{bUz9qHbC<~3lWd%cS)GZ<$b>ry(+c+Me+)63$zEC+XHPau7r8`|KMREk at o89JzP{I_M9^U?o_YbA(Kb9bYMez!|Z&G8J4&VAQzjN+zM^{ zb|OJFU`JqPkWw**&JwW&Z*X6ouaJu7k$8f3>vms({aDuBt?N3CEiZZt>}C2TE?%E5 zom9ZwMMJJ-`-&@qjMwyiG+bnp791Jb*2f=JX%=BI at xCIFHwh;p(R8`Cv7)=O`T1VE z^_i*C?L&vCc(y3b-QzZs9mvix5ou|y7H7=fm6uG?9g^t%X z%#km+>H&6KUOjP5)5fe%P3W~Bk69^fgB>4fN~%_2K71EZcCfN5+_l84xtEw86s;wy zv7z_EY)`@`=6=R5a0DG*|4HVBH`=HOkS|>Crh6X?esqmConMO!f9&nAckc%I7loZf zsviS)S9z5BZr^AoY(8qAq5 at A+_23ns#CB3HL}zORC{pU7?-LY!pz$Eh=;rbto{8Za z^V1TI%?ozNV%%l8ZB5t4*L+qNr%@KTvgGSjsUbeA@~uSkn;Y2<=4!EjdN~N%=htOG z8j2xQvY3-=|GM2;?46q2%)+?6_SFv{G*qm_INE#j5##;}bB)Z71zEW94&bKLw@&>>N1e{->%sjQB=#9N4nWzc5q2hveLWYC` z77OusuRHa*3QUlBDj!28O&piO-HH~-WWael5h-g`W67pqOC#sa=iGqyh$Y2dJ>Lvp zQH=LV%H(~|GS)N*8xw}{%h~2wCayC$SXhW(tM=(e39_EEq5w9L5IR>)Ks&Nh3|0IZ zHS-AM+Vm9067xy{{ha5$h zo`Cis+{J$R)#JB;&j}MKm}$t5r90Ci+O0 z>rA2tHk}3!>msMFd)nGpTJh#htOh-Ky6OFeJ}QBa+)s)xy=6e)6DjC?U^pw4*)Z#t z(w$154rKKl%%EG(`!nD4IRt|IUb1%rYQ~zL38%_8o|+L(UcW`%-<*dvqN6}gONr(D zK?uk*l3Cwc-i={%4b$s^TIk3%-#&QVgLYFRysu9Lf$;15a9=<|W_2r7JCXOnuqcI7 z9=>7bx7#Ddx?6%HhEftwnnRU~1dwz!> z!nz^w&A|ZffsmQZe!U(-(HSTcNis|y|BzB)D+7HU%i zew(a2V)I0DAoSD-7WFEthIIV5&pAhpyFEErNOX*M-4|ETb3H>pO at Ru_}nc>zwI#N zSoz77nssYC7H79_n$v8nLgjvux4BU(7VS96mABb=WET%enFF5N6qkIZMLx25jzMz_(4v!ag=#CrK6& zC^SBBOFJ*y4s|p1*#D|tRDE_*1R6h01A2T8o!Nc=M1!gyOAMXvjC|?Z2SvpUXB4a8 z5o1R4bu^jAtec$pBi7aNJgs5e?Mli2eBtS9E?dAbXHu{bgCbG zd5nF>p>n^#&?x at H$uu#WY$l3{E6QD at fnmNu0xy{=HNysj0mTUv&ks|kYyC)Sa<(qG zwOhgt9em^7WBFR!wAMF7BU4<%^FKaj;8)DaNu1gm-4117l7HXSA~SY;@^tTApR*oI zYLv`G%25krvXm4VRv+7rOp`FV#!?urNkDV|0BIl0gG{?P=)bFEX z2t7yub)f+OVGIDkKd*t+|-+aP74y(&ppK890)=xvlfAvR4BbH zXHlm$c*alV^k{$(T$-U6l5U-)RyMmyK1Moy>j3n){N|*cZpC}f+D~7^MnvY07s3Y2 z`^^d9jIyk(UzOfYZSS1R_NtzTdzG2d* zd&;|YII{~4J3V?-W>C{LlMD;Bh`LQ at IFN)-{&+QFOlRF?zIym`nZ)KhznfJvo(Icf3ZV);1;=kQZ4iN%Ge zI2&2B6Hf{&NVm^;0>0c-hN0i?ifVW73+9*3KG+|KqQ9X*+Una&$tc^+W=*;NVl<|P zyf^hWISN~K=0Wx2lh*ZqN48>I=(J^0_kP0 z!1paWPsKk)L2Wf(+kZUOfK?nJNm-+&OG^Cu7C%!{;?ew_3Hub#%EXJ3_=qvkP3(g* zEaeOibD(|NQ+Z!x0M`9Lj6GCY<#%}b<~|JX?Cj$y{i`fZDd#C-Gcz at FYGMxq-J87_ z*LzukuVWq3_yeG&o%z`Ij2!`JV*&>+6SH2_pBa3apHdEpfbO*S9G3amOPueiSkXAyHf}s*uJRu%SSllRt+;El7?36z^o%vO1*wELG$!!r=)6NUCW__%)8U&sdgPT}5cpL*ak*yuV^d=d5FRcJe4$tR*jC+MrwOzOZ? zULBjAp6_N-PWDM`m1lg6lusZZ%&YVbYmY(2F2 at _s{(@PCH8H0Hmv>nj%50%Nrd7A) zBB#B1lq9}Pp{wCGE^(B+Z4dY8D=;{Sed2T`Sz at D5aO9lmk%*{(IljAyH3)IWt9e}& z;Hc-v*3R=a>JMPX<4k&KD9k6643AhGl zu%c1VJun1O8bUp5FGuwDIGwymfcA_k^3J zYfX|Qyj4o+DX?y^-<%mj at +E1j^_=){otL*8&|9}Y!?rUvnfLkFcN)7?bLrt5ejHf1 z&xoIER=5gNK0cq8DAzW*7W#pvO_R*hQRuRU-NYmH1{a${eb1b#7c{<+#kHpSjT1-< ztrqO`XLLOz4+X at 7Dg)yBlGErYP(Et2>#-4r?&}1aqICPR6cBvt#U9Es9#eXY(uF=0 z1UGF55vKSEfP>|N)O67qo7F7VitQho+;=i$9+L=;wF_H<4pUFM~Sio z>9QD(NCwv at +tETHaj_f$a?HEVmNrg_rR>V)SlNN(_0n{M!S>f`m9L`?>~7k=c88HY zyQ>0g4JLAay&>A*Rz1!BWi^q>HOe!q#4g92LsiRCH at O#I=^Hz5>}j~F;#{k#$jkaW zH&8QI9eAZ(RrMC+W;h&lryUs6Or%^#wj7=~m7+Df&kfofg@)QM^c1wA&wL}FLcJzE zjx4BC9V8!#v8oY}d|p^T7Vay|8aRSc^ywi!wMCe|RX^)v)+)jauOw6f{?uQK^##*!_5kIu}_Yyt+XOM^*wHGC(g?+WN zulWiq7UIVBB=?||o-WR!jUUfUZJ=|hI(3JHw<}yrO9issMTMqs%QF!^WcX?<19OfE zh?%k32Grm=Kb=E|Pg*4!CN_xIxWmsD7B^0MtyXtu{Ml9)Ke+B}t&JX!9#8u3yKTqp zpCj!(b!`+k_GAdwJE0Zzy4Mi(QEk+#-uXo8a=9LE`%vtJ4gg#TT`kvFFA+l?C-soy z0sxl>8DhECv~aXBfdV1ca4v_dQ%+l`d4RgA0uB}h7D5C^Nl{h<@%J47fCRv}hB$MR zP6u-~od;JFP%r$yyfc427|=h3R)N#K?? zhWDII$tL!6np$^_NrRP9#MMoUuza95o4Z+4B5z>Jv7!cML{jrZ3d*aJN$_P`=ROWA z5}kN7qqRf#&j*;39-2XZ`t-TvQ=k8w>5A~8!DnK)m6G+_(@nk? z=Z%#8KA}(b1h$O+jfJijuNGyP2x9}8t9~E9(hCXe1n}?qp87tpP^YFdl9=s57A{T7 z4Fa~^%vU7f0J!~au}6!&G#u`ScMi$A-zL-ddx=Ylv`TRa86Dqtdusft#WAy%N6>36 z?B3jzVQt5t2FRgXRs(gN|A`#dOU+KXwYL`~BLa51@?6g*Ah1FX-M;i?6>{<$uHCI) z&&1dkiB5bw&xri9fE{nw&vzDc^wHs7(oh#XmuE8E`?rGnf^&q`$MzS at Gb6oOc}U4q z9qy+eXoY(2P*nKlbG}_Y7OYCL;hE&Ok9pUUuNpQS;F?wCS0y5qVLhG_teBJhe9_LK z=-&Fvh)e=inwA%54mn8dWGBXVhZxniz6qL42!;06m at MG+8!lP5Wa4grtNsGKz>y_{ zZ`XE+U3}dpL^e?0N18$N0HFToET>2lE5htzkaZ?xe4b+LaCSIX1nM)$fD1`PY|ZTL zM=+VO$59tnj_GbaKck@%?Mzqc3TQslu_bh=`&>5G%aH)<`CpDEvYB_tz+9Yy{_!QUyuC$TUN=_iXd}F!%`*;;cKVd z$NZMVOkxXkTKG)Z_#(+f at 6o;gRBDa7;!?NS{9EL;599qMEA+%Tm6*c zYj at tHX_**to50^q{g_GzqpuWlkA2h|DPd&e$^H zLxapS0Buni<7O;*i_~oWL*fjO)wDn-3!3$O zgKb)khY}s#khQaIVz#Zgm<-6w{2CTj<77-A}+-R|pwBk>)St;vOvRtom@~0Dp z8%NsIbT5O%gR8?zQcG02`SfGUGTNH>CK4#hPzPyQvYaNW2PWFsuIO9+7ZT zv>S+eo at MxXu@gw%`J{bbqjevh*ji_~;{LP7r*kKF2qqMEmLDiE^-{hPTuTz}8L_=h zG~sW^u{T9g at 9w(g5kd}4?sEOv1>Wpo167qT5S64Nr8hxAufp;*eL1#v94c*i~8WBk-xu=Q;)}o)2z|7 zLXU0xm7GI1#!|S at hSdA(RhA|gJ?5mgD290D!_kp>aJ{au#F^UN`Kssbr|A8YSrivX z=8KYs_2rCaW`m#- at cmp^vf%uDbU&q)B~9ErA=tT(yXyg|IUZ?WegEquqMf#y!o;N0 z8T}cc+pUr$#J2xI5cYk%;qaW+Jkx-^NK^z at wb_wZy*-;(z*%IRB z;ruj0A_-7KlH`<9uP2f<*zv0}+%Z}e1QQ(-B9qr6>Oh+ns$?hHZME3gL|hx!JuDVT zviwxpW(78L561K2zV+VbPBysHbSADofd2oIQ4V(szdg`8-s2sDD|8qp?YDVaoIU5z zTW`z at XkjLy-5Tx1keZ-- z52>jWrKK{I=X6gzD-48naRO(Nksh}I?QG7HPo#3;uNOY>YRywr5 zNV90P!eubwHL|YYRB&3O_c6{Ll#6uCKItv6hFSV`qO+`WMbcc5i`=UleA36#q>tv{|*M8YL=c>{e zKcvxW^IsQi4Rh+AUA94KBxNNNbpMVcu1kuKXbY7t0hlZmE}U8lG??|I-hIr zrm|*Vi?d&84>DeVwYx*#@E)9#WA%J at t^bYDera53gWcD`7q8yDn&|K(r&2f2A6n_i z3jFFH&3V|N=o9!g(@t%6IXTG0adK~KuV3yA at Z}pS^C#s0ny;N2Ki+_+Dd2xQ?s_>_ z=k at S3HRQCV14yHeq|lgOjeRQgE9;eq7-hQPQ7TH zqjAAxBr|9@&cNm3n3!GNB35aBpHN?NQCtA-_|Q at 3r7NM!wxJ;HOgN#?N&WbcG7TC% zmVYt&HLiQMx5~L0AhVvj1l&PO{&VuUNzzMK at dzQ8ljC7JHd}j)o!Q=bCg%Rt8*^hR z)OtJAW_r!_vHy4nUl%t+TKIJQ)Dv?Ss at lrTuf{_Iv*zrCoXSoc;R5$sgl(WI_JK%v z&!2 at hzGXicWXK_nX}>USzi&iU6<+0rN!>j8$JnE2%9*~JY12T z(`_4d|CZ3Q5TqD#?1pAAt6B1f-A)y1y1G_t=R8R5aTwmZ-_2G@!5Z)Ir~uE?@hqvq z;%;I*X at e&4Md+b6^-}1;qw3x)RjtH_`$4bnN9m_GIo%ZyK9R*qTb{Ik*SgLC#hA zF{w&UltZ9E+;pp509{ZE)1!N>>`RLzgUF|BW%l1Ux#KK2oT>|uV&|e%3Y?a}NP?Hv z4@*^UJ3kitu(mIp80$Qh|531lbG& zEh%A8x}q?>WF7l;=j7K%UIu6}d-0Q`HyAg`?9Qi`nQo|fF7Dk1YnPMZn}-2Y?wgyrti7on24QBi z7Aw7n!nhkUV*JKdNm=CPQ>>qYXU5$#C0&=N8K)`>3Js^I_AG;t^9rAJmW#G`i?$1K+sKY^i4RkT(lgj+15 zAx%_0)<^akrt;Kt<)CXPv&60mojGe8|dirpS4Tj8#>jldZex|WknqIT|bep4stts{sd=Csw7eSTtQ%v z>C$p%5^t*z9ys6`@|ESToO*;Q|4bB!GZ`4v3}XIAbOM~0%NAzqXp4x5apd}8 at xQ~- z{0;7VbOD^}F2unGXbb-r at ZUA+0E1cE0-<2*|0V7+?7H3Wh{h?u7D at jqN3M|=A} zKCmEvf1(ibfXlZsm+7CMsLMAwa0gdJbjy$E1eLI9LHxR-M`T!2lpNDF at dYy*hXZdc zyiri6%Eq5YGslO}W6^^rj}H=W$pyS(C_KE~^bx-?Vd0D2$KLBon>EQ{k443}b1L6& z`>ePV^yp9r#IDxV%qNF6yqun2J>8xSpkE-EZlz=8i?({R&jPkYi-5l?Zmvm*JeF5) z8)eKQe at IDXBim#z1X;3z^=LS?lEsV8FrStRh^^&BJgDG{fo2t2N1jaLqs-X8=l>q|9IX za+M0}`i6G)@8&$5=@h2cL=}E?E1d#A at uu+GS%0FNCI}d z at K(pD1J+a4N at uV*fqF9$1rK2eZp|B zi(56eXNsS?)B(w+1@}5x2c~I5n(Fm(8XZ9Bla?MHG3 at qFCfE z-jhI|D%_Adfw_`LXYrv9DM6wod|7T{+e<+8Dq5&ZeWM{W1BojXOR7UA{b`M##~PGw zd1q?Cg#q*?51W_?`~>;CQJdzPuAk1xZ$j8vuVJ%gcJ6TM^c23aR(Dy$6d(p&s|zB~ z8o&@`n#AsGXiTyQ%zZl@)P>$kn)vo^iP}52Oi|;~!$(-B*_E?IPi`n#`Ep7=)V&Qmm!Q}Y3}Ai5hldX0?}_vBOi*>Lm+RDIfR6ocuWf6k$In_fWg2R$dj z?YBNRyQ%0;V0m5r4lx!cKW at zfg%9R6EF{Q6%Vb)mF7z5mSpbgv%tnpGeA!<~?^NrP zOa*7~&qX<)%LMQvzhs7Uc;hyljanx|J~1!zMO1l1aolQT<5AW`+wNAx&Jl-rCAc!3 z*^7%ls0)u+rla8wTn&t*qMA<{lovHFe at WhwuP25n#DEg)DABDFb(J0mI-e-*pfLA%o z9*U>yOUiXUqX?hM%ruRPT`%zK*M5{G2Kpx%?>FEfRriLNQcTHLM4BGH11+p6=P-}f zXYB?n7o#&2rf2jpy{v1n at oR0pGbYV|j+IfSuK0PCQ#n1`EvQA2OHPVU8=u2Td3(pl zm*wj~^SMv-q?gRyHqG`XiwxU^`#Bl_ypo*WeE5?FK8hzw5|+4VuWO{ppT7bvo?y`c z=Z7tKAZ&}n_<8=8y7COfH*Ft#+Z?%pr=Vi>B)Ur(NTR#;T0y~KDq?*qVwn&*wYAhm zUJVgtx&y2Z$9M^~?lWoRuwEelkj5%f*L6Q6R`|=I2-560E>B#Xq?-%fgNd~>M*|K? zC1KdsDuc@?SdQ1~+?0boQ$OOL`JAIizLMl^n-ZtE&$IW!EZLnh z`)4mW at FG@8i$HS_wDs$`y(gk`&o{!H#&0{%TBXZSddU}3IetkinV~*=SpN*5V2ql) zwh?@BFT>TI&V|B9j!l@^@odjt#E7SUTE=QNkbf&Zg+%yTXh1x%09M4({#%b{UV+Ex>C6dBM@|_Q_un`lzUPx<(uK>OKblWz2iPqTQHdgN8aKo$u)G!&lASb_<wX5E|pSeN)eau3(g{&GF!#ok4?!zEC0Y`1GT|^$x^w7`3R2DC%yjKp!JH zwt%O``DjNoxjz~k at 0Gu^h8uyAx^sm81w7-vxp(B9$?zr at eMVLeE49)iK?r7jesj8b zhX8l8s^3^eCf+xEWrysJ!nbkr`Q$Wp=1- at GhJ3FsBK)PMcsp0y+ctL_ z=S7s$lNV*W{d0yBpgN37b)s7$8-8O=HwbZ=^q)Ku;U24-iesC5?^q}lY$!$FcoX3bAHZ7-*`-%fujm%@@F=sTgD1Vdx^sOkt z+co{U{Ou7%8GZ~wR59VBoccm at 6>8}p2~K*OzhQsdW|HxCj-P3f0N5d74vwA*xj?fs zK8Y|{Ny}@2(jMni%ibq7BJ}8?j;R~@6o==3!Tssn>vCrXC2W zR*}<`=1@|V=lXMVi-?oR*SrsHp~atBCB8A;HDIQdD*RY>4RZ)t`OAc~Pm|BBK$wx3 zrKDC=mv$-0bGr_RrX3&Q+(rN@@n+p&G?Mc+y=#+`- at 3Y$=1v-aV6x(E{Vd>MMg6*C zWPurjJv|leWICoeW3RkFZVoQv6Z$c!y at R;VmNS?-fd_9YcLc_OA|oB=(KDv2UASM> zF%K}7KOXAnF;{ID5e_)^QOw^`p~{IiZ`w7?G8HdYhx5CbhRZy`6IQq*@Z8*+(UjUO zJPFtO+RnskshzX`#u3UGLt9MRMz+Tt6N$3y_OI+W&^_MkQ*fgva4*#{yg2Kz^E@@p zi^n9E8SCEYohKtT83$_pT!u#ZEo at 9^fkUpNpu;Z&4Mdm~*V2K;lB{N=9bXS#}+{~h&vIQ&n93gYxK^z(Ap zbcMRww*49vbLsv3Os^1O^}j}g{*L_h1KnlR%+C~!Ao?YS<_dVVW&i#A-A|w#!Uq5J zHSdb$O7UNvu)iuEN%vPL?sw#`PRL)8^9bahqZ;9|T_LYD|EVbeaOp4nOcaR6=Jy@% zuP)19Z}3kX;=dPuy#Q$Z4bT5 at Vg8xyuS$je4cV_Q&41(qVeBK=IfjK4ZezvF(Lf-WcapQ()FAEtTr`>2Qry302ogn(QW L0DzwB^6LKp1SPX^ literal 0 HcmV?d00001 diff --git a/koha-tmpl/intranet-tmpl/prog/pdf/layout3pagesfr.pdf b/koha-tmpl/intranet-tmpl/prog/pdf/layout3pagesfr.pdf new file mode 100644 index 0000000000000000000000000000000000000000..07e70577ab6613ee1d9d67af409b03f0e8b3a40d GIT binary patch literal 24394 zcma&N1CSj%N6be=Q2MBIZ_( z#tyV1R{D;{LdJ%+M#elmPyj~HVyLCFyqdG;k6a95R zTnSsRIw`2liLcLb1w;=9P8l)+0*42$_^LnQ#?X6Buat$cFD3=nNk75Y at O8YIbhpBI zKVWN8bf>;HeCJPg2^%#sdm^4m;d2LHkC&?gPZbm-=gX*htspc{3sdseTMtk>V1Hdh z^}bC^aQ8TEPsdCRw7FSi3rWbk$>>5~Dp{61u)oUUnc>#B^6q_7 at p)QRT6WoKw1_-J zLDfeEI3eW3J)_FKJwz?$IYIyY1uP7tRv6;nxhK7_rj~gwHm#E7EoA4*;V)1agacCe z%)#x!=r+}%mYNTvY>TCLr=x*p$we}6s<)|G7GVx!1Y2c&SQw?zUB1w2*iHeLh|u#t)LI+M(782p}e9IEkD at WRegX7 zy*fI9QQ@#7J26D%40kpZ1v7-fza*V9F%L)?u|Wa{iUOU({UPVhI6KAT2t~AYKpjr zcU1;GQvYM--Xs3A5 at i<#ZlScOzDhZAI at W>BtKUB0Ie#pD`Ucw%6H#EH{lWy1j0YoiCaeePfUroj zbzGu_jU&x;nPh}S*I+E at nN0vsAA*w#@^w3qc>9Z5G|M?L zy5d*~OkqfwgEITYV^4=B^9$ygYR((Ot5?!y=f#`Nt1nx>*N+xkH?3N_qRtzo0rPC3 z?^AKTY|;?{=*Z2&%*jzx98aRer75EKCGE;t)c{RurM!eY-f0(~yQ;P2oPSh`fg zW~W%a1)e|QI}#uke+pO1P2;R_yX|CUZc z7{Y5LLmTTC+CJ~3;~{$j9dZORWsHcBlJtZ)9K&na`!B^r!9`zk0R8|an(BF;1BL9y zc*6jdo2AiFl_*#?a&!?8&5veKt7L5MPCB$TaO>pk{6PSKxSf3O!@0oK=gHd;GZbGh zd!;IpL1zh at UEyf7JIhvQz2AHvk}-|rWYpn#;eBF=((&i?qb@{&&yc+#rw_*sEvWTd z=3UL7z?S0iKkGe`0*1UZLl}JpTLhlXAAY z2cIgvq)p8Zkw2Mnc7)#qu1bPyxhq(Xb-s$}wS;~9g`YkneUcr7il%A zIX;n`7%UkcaTnm`r$s+<4bYJ8q-PYYnYUP=h&I-17Jf7k)Dk-wLbA$6k3yZVUx5hi z77le408$!wWP&89j)h!S9OrAhG)!~|SJ25F?5zD!MMi^oCQNWEkVTd`vWdk3++8Ab zfryxb;+plN!A*hy1j?JY5&kSo&`IFONYI85~@+ER*v!;HAJdG?l zN~$1z4o62JHbo{zuV*)0>!=VIkUhTbSv>jpnH`$-XL^|Hb?ozs#1yDCW0?1ZCw=%Ma04Yb zOP at HtBRQZ^*`=(ouLz^S{#LSsY`>@ECK)|@nm%Hwa}#tiHFn1 at gBp*9UGRyFS~-=e z15T1O`+=F4(3(bre*jFt1cbj-?du_cGt)a1(2GK)ytsxUKlr(zoFFl(^Exs^NYskOi at cHS3}GNhMGyKboP~k1SlKG4s?Z#j6#xh(JfCA z8 at XeUfPkRId9F?VmP|ngS}@Mdy=tw7k{S^;6!JCCy_+v6&Fp6z8Z_%{X(C$qY>YDN zlq&Q*W?h?gIs at 7~3_ at flxnC*NL=s7h!RJEuP%sajL9N+PcFCVnhNeRTi{^QQ`QFBr zr8a>)aJW13=cqo&RJtY z?bD{9p(s$va#X@|{(R7h^CDzs$nMXK3<8Q0)D`%N4&QE($eAX%A at bjD@%^{=Y(Lmo zf)Y@$KYJYwdd`D at +j(-%Fw>)5dee;QNpyuAF zK_jw>Z93YT=ob_ at 2g7biWk?c`F)r2{5N50wPUx;IHGoeuoGSl#SadVQ&CTsGEPYgd zb4XkS95SV=q7Rk)YHgw5XyN=^rg-qB2vW^#sdb^_qL`q0+VF#*IqQ`NafX*GfC+$R z9FrWwllZE3#F!>kthZB;R*7r*7)51!7#6|H%S!Zo&XCWQlaLX>daTDXk}gjz10EI3(nihp6KF^llv1t z2d^_Eld3nnQ?k_51P^9 zEP8*zn%UGOgJ^R-l~yI+3zylX#1nfRZ`u|T7b-gjh+=P at jbX=ID$S(GH+}%-a$)xU z14aWH%4zreCJ4w7W~T+ at 8f;Wr&XudT5uz5kHwK~`2Y-Zo1smV07Zd;cW50J1$nCcs z4d25|Y$r}{Vs;}0I2q-~I#4&fD?8tjX7GscUTionMEtzoqh9HmWMy<6 z$Vqt>PQ_Aq#|N<7F3cTIV3+}HZ`#H8BOs*MeUMo at p!t3o;~6bJo9jpw2s(OjPd_z1 zCOa}aj@UA~FOoHI}{Dr+G{2YMv;Q-lyH z>$lH%2<-3g6R4f9WY6FNos`c%;>q$$@RL8$_~+FYGKoAI#t2hYkZCrD%Qe}p4C+Cm z0vN&|M6C=Y=(`=SyC&YQPU}M=?iu)xy?%N08hc)~g_zJ<8=jp71bpV4>yF!5Jk8lu z&34t->{jQgb1p(#d{YCi=}h}fq{w`);w7*4ZuLP-ep%jR!I;FMAW&NvO{oB?(`GZK z_*q;vZvWw}z2K0Nz*H?1Gk| z7B-4Kl_VBT6T+nF9Y*R*SN(x5W7R5XNG?%r(QSy;7|X&bP#9QoNiB$!Ns*+a5;^tr zRxujZ)G`ILYX;56`Rvq7<7eb3Y~ah#)oAXex^h~AWT4ah2w{*+q(7$di%TI|K_N2+ z at x}D&C|&!SZ0?`x?zijEUsrv)Z$&%BJ}kX7x;CF{U|FMJev{-Ll-I=;RR0VCecb!Z(JsOjhh? z_^~m)OdMCdXJjsr*9L9(pZ#Dnb2@(iF=x!rSXf_pUw|o)4|9$)8yf!jU@$dI0;`~M zhOW~rE%8!>ALY*O%3BBrmA at JSv8gY=Q?ADH7m zB?wy;!a^03M!c7uv;BQ%4arNgODpz51G)Ws*BY at p-Y&HHPyA?%H_`4g at rQq)-^H&} z;4nFoLiIJOIEuC9wtM*F28PP*8J+FIE*{#r5MR5q2-1A05eWT8w89qR zJKu-W2kNjk>HhbV8M}@^OX5zcez$n85Ov6$1R60~$w{7EBF&^Xt}-o)SoGBU^*Im6 z`ahE2g!FK;ar}?IOyu;i63;X4Cvb^Sick)jGUvaH2PtB)fIoWVzR(Ag&V2a#@sqX8 z(}XUtR& z_I@&;W4dM)?O6EnlMNYd9rfO_eKDX{Ea-T8y&BHG2Ja<{*UU7t>nJUDaHNQwrmt;8 z^r+fBt10KjrSp^rGp at RIUI4gwh{(`KqoX4YG%gOuLbsL4=qCiHBc zZKR0Nd}~YVh6-G7*%NU;olecurXv_q$0j|VEwqZoW#FMv0Qx%C;_JmLeNTk!Mw;>(8l-gF_Ep$s>7Vfp zEa?PBnot=nH76OB&4@?U%~+nzUEk#_CraWFf|a{X6Py}-kcvJhIUXUNNnK!Vv#<_} z at Bt}|mZ>(uvy3(*gLI?OnwKj!tT$0>5&T3_*IMgRO z=!Q$zT(`Kd_m8FBlTqLmgFJ1sCdG8q#vfjJE*c20hKft(t|=7sErMuGmE zSLacZ!Q5!Y*FCD5{qRI?nx)G)l+Si3TEcBw^`wlVw0Au`O)@IV>=T7`|C}qG4H5MU z at f>Vf7!J}r at GsNa+8~t0h{g!j4=*MvdzgAeLMydLc_EQor!(63C`A^?n~)qJm@!xo zG%h%?ci-bz9NYzikkH$_28XK7KZSyi-9~-hSXXUt>f$J1`J<-PJ? ztxAU#QNX#h2+IsU`L-Qn#5UzlzDGOucvozVrS5+)BMI{y6>UUJE|oLTBE;gEPX~;rz&MLM+Sn zaA#q+tS_nO`!T-H)fCq%bwu<0O~tqdv-R+X8l-~4*7M13YGH5*`y(ia0~)lU^(@$! zQiDRUsKUVIDaTF3dWU)JIui|Qv&bpvaMn0TvfR++$@=r|1S()L3HWJ=&L!>Cs2gG_ zImUT{`n}_-{!Nl7#H!wgwesx)I$)mmpX5AF%FU&?aOSEJojB6-8Hxy zqcz>+D&|Wy6O+xxqpUf+H(z+*(96-4I^6Zmv1d>}wDWAa8RQjol+AmS+%rq4m*aig zBa1tJF+-M)D+yIOl!}q|3BCZ4z%1=V1rnS$VpgbB%o21w$y3h?fWIh_kijn&k{JcV zuu)JC*jXI~N##!*^z`~<_+*)?@ubx3L%giJMoWXl+ at QU*xH%0m_|nQjQRb482i5cc zK?<0y;3`)7Jw5Q`kLH?Yd#KJ_GLK(8)Qi!S>I*AMxG3T7M{qII$Szbclg<4B7AhQF zo}_P at dbC_Ts?X!d<_IimHk$KoRu`Jo0M>G+_eJk^+;{M$@extC-NWHeG+7*jtJmyD z37GmyZ{2~cFL;}U?WPPZH~Q|j>ipwdg(_LQEbB?ccEl0WeBbd!Z<%RopI3)R<9XfmPKQnn?d at YQ(2 z-{K`hXX0Ks@;kP0jN-UY_NzK&gyX|5SzyNXLi^K^NI_<*=NeKh84H0CME0j1*$AY@ zX$+tZ6f#kTXbu?eBJB#fl2p?0Jq=Ut#G65furQuY+uUMqKB1OyE{vP5fK){=JUw(P zu{Y!&HQK2#=PVS>9VGfpL%UTz*< z7_U2jm~+KyYfy{W+}NI6Yz=yjpERR;KlZ(}*xHVdE*u9zMbeV};5e+5rdjvW4KX`5 zC0 at TDe-k}%!>iQv&3-nX%z0MFZQwH0r+Vo8(|@Nn!CKE!5!GsSf9%DgNyi$>3PF$6 z2rj-@=umj;5Ni!h>M^ zouBh~+z2Yy9QEAtVuh-?BqH;i!+j01TK4^vw#`l_b75(7{T2b>oxwZuGUS){yRE_f zA}PEN0*;YK{%k|xh>>G3%|leJVN4K+SQZF|V0a4;FKNP`lr7zxL0 z9%)@$Tl%K#nrT&AOZtY;)GxlTGK{lnP|_39mQt0`vecE6r%SaQj}DKR zPA%!McCNe;>?FO3^p7wT{5F~*XOI)dWiTpU;2FE)3hI at PNT$9aNdbfgZpr9VJdCsD zHzIt^MrD=i>J*Gyqb9ZI8zvR&)+(p$AWY4zQ%B4gYy$()eo30=4Rix0`d%s>5Gn4p ziwWlhF&^F*uT>%JSA7Js4I#C-AK4J++ypV8Lqyplc?zG5d{eG8?xXg9*x^>wEZQaq zfHZL5>mXV at NVr@0Q7THPfcT*U8CFmAWv-M`>716|3KvGWuiaKu;7CN^ye9xdf}pY$ zq`UgLt=HOcJZG=r$BiLzz~YG(2fN&$6kH3A)Y_W)1>{iSXk1d%J0%AfNzC$nf>_dS z(QYPO6d1lpKw5WpxQBrb!b)y5Nirjk?M*Q7-QCVi+^B|!j9Yy_GVANJsJWS6C;etDIt7=|ZCs51rM>r0_ z;0$xzED!jDWV)}$HpA-!TCt&lbyst1 at Ho9Rs>h2tV~t}g^8 at odox5sqi)A#Vg^z1Y zguqd1+PSq>#U~|Os)9}}i=_hL0A&Zn5O}z#lih5=L85B zAehonD0k%`R-cqS439=MA)Znyiy1gIniXo1q_`_CXwC0F*pp5E<>Tb|Og0FscA?o! ziYKnUXX?hs~Z+3f5^z3rTPJQ67^Xx at D z{C4z}r48&&iT5*{0LE z8lg at bSz|Hhk at 4*RY)rd;HUzIML4ZhC1rLL`CAsC2G(&&H4P1mlixo^a=PJxvLL at eF z9x4-;(mfPs&Scw3QmJI7yoFB%y0j3d_&X_U5Ypa3gF>Zx_s0u0Gv at RJ8G`gJPJ9<{7aL)w5UV9qa!$JISNIoyV+b at uk2 zw*>2iZpRgKw*1zU&JfigZCmJhYOz-MHljqP?wtj?|7gp3L>RjOnEG{bRhcMjakzXc zx#Hgb@>W$HB_LsGf6NcUw1z?M1)n`?bR+3NLjkDW7I?Eq9kp|n-|;eZOxd>ythIM7 z)SnHZGu8c`=swmOEI at bx$RwN=CBY#4p`T`E^p&l at 2}AztEtbASS*FACk5Y0*_g$_j z^|<)_2P8DN?dfUWh}4Iy*-7`+VN43$=|w%&-i^UwrZ1E~G8;6d*XjK4J_y;Va-8R8 zR2PVY*lCM8w7065J-pg$>SEvHkU!Tio}FSPuS2aO*E+Myqu5jOTT#Czy9R<g>pQBSfbzx*vZ|$3_n=Aqu&*WNaX5G)-v! z6k!QW^o*LVvu~O-T7o)pL<|h;&Hx>@F=@DKc=w4@^aJ}46SV2Zr`hw)vBYc zdAxTmQOoLl-mzD@<#+Wac|LXI-Hdnmyq=i)INR=r`?JQENa=_c at 7?p2w5jr!G|1t$ zOWSa!dZ^N1O!srEr%u(I#FYX@#UojAq8!!j3s6k?DY(xk>p8O2WjYqG&sZ?)xOSyejH{^G*qDHvcZE(=bCx5xUYwz!Jt=;2{+-q0&JJD>WK6pj?pU2TY5S z_e-3k<=tkM^1vDa2m^ef5Btg&(>771xrhb|!!-?^N#+q5ixhPa9l5ivX{Md0#xtM~ zdr#7hz7$*u8*qLvbaq=`?og=S#kH7V@!6frc6&?yW_r6YO%pmFwYa`O>T^OG8%fAG z0&8|Su4|5hlVO?RUfM9eYTdhEI~IDJXH6Fap$OktYW(VX) zH$B#MgW>g&lH5E>AaptO&o!&Yx5~lsA)yHR*4ysSoOvzV>C7WjT zuy7QB!~IX0gU0O!!;#HPcJ at n`>lJ%h51G4-^uzh%ToCYC=L)6=}j)gK2_l&+O6@>|~z`#NnjZs2g&IT>- at dpiS?+ z{&Qlqd9-^J2f at U{)hD$SB$|(|*DPYe3_xe5Q;#vbeVfW?hTJM_8ERrACNf4ERP;DU za9Zl9p`a>BZ?4o%ScjZLfgRsX*hSVwJSE;fj!a$TDbr_W7KexfHW)D at lVBmbKI7gb z60f;lU;$`p35}^({G}Ti at s1%ni8WCS?aqD)C at +2Fqbb7v8C}w{P5zxQU4^P1YpjmT z_vBdEx6DaMo4|7lpN23}&vH8YNy(b10dD*Kfm9^y*YtEYeODQ?#Cr?Me%FSF8;M+l zQ+mR?rr3CPBbmc_GYxbfQr--uTF+MEet!|svd!TUrssdZd?EH_DB%L7IgF`#y(VWe zlhhJZ-M!l|5Fh?lywMiZ>Ma~{KZEMFxJ%{P8+Km>QF)LHww)bjYhcF{VEcQedo|=n z^Fb*^^amCGxT;IQJ_5k7+!dE-7{>m)Q_jv+Yn7Dp+6nc;MgqJn!L>8-aqm^}Sxy3~ zQV^4uy?z)2CYTGv#R at rL9?tN}^Ls6%CcC=*wRd`_Mkb3;_iIkpwxa#*IgqZ^mYFY64i)L`6%+Z7x^^^)Jbp{tbS(=321kCd?+`s#6xt zN|T7;$|HC9`ldCzHjIoW?lf$MVWz=JGe$$yCO?r>u{SXW6rIvnt>~M-JD_0K$_-kw zYugj7%mw}$ajgRi`u8-z%ao!A at 7q_~??U;PkprG5<}=Caqq;-9q)CsVnC at Tabx9vs zZgK0SD=uA`1Q(LL8X zZ1K;DnUy?|p4WWl^L*+OFZ1x<{VF%)D$UN~Lpi|uyAxRG-w2>k+U7$6TK+LDTP{aG zQ~4u(Q*OC;PWNIUVLcG^4K)4Tmjv%j+fI1JN0 at NNtQ8NRGI9OHZs!!lJR=g8J2qvz5}CMj#pGinumIm#G~co=2_uUL^`h- zR%6$iW)ttinqYhWVF&M483Dv~WG0}gYRR9cN>P29%Lnn|8e72mL+ zT|zw at eNeX_j3eCzi3mo&GEj{cI`C;%$OXy4kOuSPm?nMOqD%BqS7%J;=^(nF&&}1q zJRVEtYB4uMy<>x!N5d`WYEg~%qM0f~=pSf5o at F6<5`!6M2tI@`r-cX7ZfSU6Klc(}C5Ebd8qA;))>HlI+t0~e)88`jX#8fGGPW6!-z*JjSo&S4N z02}PNJn^yk0C=PDD-J~vqg*^^LNMbj$>Ql^fg!|5NDG`aR1Bn~q$FivQ~-!TqiwyI z8RjW1f`#)XV&WO3zNejmo#*xrUs!E(S+lpHw8#7#s=lkh2@=W3J2<$@bJR7mNQ?Hi z_vOt}-);BU?kqx{wVkJ{=H*GXUwYVAUz}f`eV*EjYZKo&FG8ESou|J+a$=&27LnXp z1n<%bFFN9+;rq?t!44aKh-hGRd^2KRldXfDk-`ZU2K*WtX7zTnb*qmY{}Wua>=W?q z$pL(%$H><0ZkXS$_u9J9Sihr6Oms|C at dz_}tF4^cGAlbf8$AaD6FYk|7xq?r!_J-FMYeUgU|L0 ze%ANkRuw1sJ896Ed at c^Mb03#TuKD)UZC~G}W3fjP!ZjY|6&~WR=qr at Bw|9sU5`MzO zj~aWLSIvOUrWr8|a*ZgFS#*w{;B1l21q4ix!!PJslJevq%0P_>u=&8QBJy|(sK5)L z#p^K=K;`@$JF;pE?gHen{Q&sv_r&Hz2kORh;m6)8 at FtK>+$JDrwY=*9OT^N5UuXEs z;A6Hm$X0nfO`nSIrWx;wIk+ke at Hd1~Yel+&nPybFj$CWlhdH8DvVLxAm%^ zpr`NS#0=z(!5>qI=)_5Tr1q^#-7mZ+r{6LXWsfV>c4SKpS)IVaWDwg{Di9FDLg;QkP+|B-IvM2o{J?Yrl zx8hYmySpN(szZ3L+rPLy)P3Fks4Xx*-;*Fs(VNazzP+7lLa?0GzT!hYdl at u>)qrI*bvf5ec*AY&Fqsw|apO=&G*4X(r+wUYwMwG}xAwvd;(Z$z zoji at 9I~#JSVJX<1NiNXrt`Az>z_|Vi`f`z5SH!P@$GZNjzc?zu>2#mt< z99-e2JL^SQKwz212%AM`#ARR*QHmN(!~wi;@i-TEQ6pRM)MT%(WXiSJ$n0<;`LVdC zusV_|xsb?-J|9gpqHnJ|y>mb3YRCc%%r#93uTCvwV1V!y^`L;Z0K?H19V8?qg5waf zfdUBxpsJ-V0_3t%S3z?JgTJAINJx+|TXX5c@?ciNWvIkTJl} z!Q9T#_Ahb&uPUQ&ZA>f3|L>rbGB+ at G(04SqwNW&7FgKwVu(dLR`bY0K1>iIN75+{a z5U_RCq^4(Mz^7)UW5lPYWBYfZW7Vb=cht8sH{`c5wKB%1gQDdJ7#iC+;lNL2FzriTU`E17|169kg8s11gF`|;{9!To>+9t(etjLxZ z>sYZ!Hj1$84>#rBL1d?)Oe`}X3>&EgihcJ5lHE9YG$ykk?ist}3nKbDHfE6CzK@;$ zE(~zeVH&L{GxoZoC^BezLB7gM9=pmL6|4F!YV@?cqFDWfZ0Zv=?eJLgbx~6a_g->B zvZ{;J;N!q&;uDn}|7qxnH}*yUsQy`}Qr9D5+SJY4U1i`C)fE28{8qY%cbvcSjXrC) zOum+z#*WX- z%!1Fz$cWEOM~BbE#E8%KpYlH&11szQob%83UvpSkSfKvt|NQ^r|D7y?;`lG{(}E*#Gz;U7xsUsga0PR|9wY>|CJbj=6x=7_V#c< zz?btuz$b>!r`J1-mqQP?`a)n;+xH6}Be0KFr#|aAm}RqPd49$|b`jgT(x_x}(Dd3DI_G>@v!*)l{UvrufqKdF%TM;_YZMjnQ;E z6YzJ8L)?GgBLk5p{6+rhVNg(@Nm%h8)OgMJXVSqS5n)hQRDwNh?9I9owudK(pY}b1 zVg+k;@6~#{(hgHp4BbS*+ICQ{o31F$!@)ID26`M4{T&EAVLZQR;u-t z8~SaHhZ7Uy-T8Q~QHlrgis(CVBboyPwAd)arc<ffAiTTsT^`}CUw;*z|b%pHdN7UG2P6ipQm5r0qlXo?(?VJIZq4#EvtpVwyXm%fod-l3SAM-9i#y|7l%~MuyiF{CNboM13i%4xXgy at J zWQ}}-db;!j=pwt;#HAv1d;?a3d~pOh>Xy0RLu5oqwna+54mT_k#KL7-C4>HIF=vt> z1`WSSbS>it0j`!FXuTmBg*No;BRftoN6_j+KT%>J+(W0-1*HuTMTd at zCcg5@j?9p5 zIE`m&;#Gzoi+~*^Y=LHgOp zl``ptBujxR^vU9n<%Pj@$RTAXC$X*+bc~ND?7-GBZ;arDek(ZI;xyo1C9OwgWg!Wu zK69kZ#9l7Cnu8WC6~joY-NAhLTr!p{-+SHcB6^FO8~S`b z=u#Jpa$!Wx;(WzA0Cd7Sv3zW?jIoha6iYy`d?B=ZmgdVBfolEX>{TH=PXEMQg7xZ3 za$}S2xdftZ1RF94%m=GjwnoaxT$dQqtKig6WZ*NPEO#!)y^v{gGft)WgiGzR_R!`I z86x7pAD-gLtkcx3>>cNl$A*&6HwzHe8mtwUmExbPabwf at M?wt7#x8ecIm^g at 6PUjZ z9>x_{qSn!@OqmJCT0HjFrYfQMYve9Z;q)q+rI7n6OXU=Xv!lVtnbn0mA=c)3rWYNV zz4?60q0+%if{fMj8oxzX7tVqDB1*28zACxFyAS5;af6|2QOWa_I^cfNm%$7g|n(FBjO9PF!h&`Y5k; zE4S36JB at A!*DHbz*QSwGI0XlBk<`AmIWx;8*rtLx)+ZtvE03;jmR8VwU#ebf#4iIM zkA7y^9u_%sC|dEIAa2sBS`pULVugqDh1Ud%#XR55T5xT;LEzhkk<@Og)4AxUX%vGs z`0Zr?=p>gGJ#V2?mUq!W(K#qCR^Dl#xVUrlP>?nEw-uYRp zPgXubb#`x%f}GM`L_l9A)PAy2>YkcBKd#3iyI#JZye2*VgP8!1iB_eQA%WU^d1_p` zx&H0Z;-&d$F=A>jQN?1NNjOc?Jox8t-7KMnpd^imh$`>)?4o3JDg(7yD{k2=1?2YR zkdykXcojG)@r?E}3}&I&cP*Fsy2?`67AK};aQsx}?D!j^%M#>|(c&s?TBukB?zvf~ zbiI0twH2>&ptW`#Wc?aFHGw*0aZ17}IT at _HzdYw^G?YLRb;>{Rm0Lc)h=S*7_UO)d zMHSfe5k!GTO6;HpW+5sQnL#;%UpA?J$-Qr^b2Fh_7V|`B<|4d|h*OQ_;)wGEg>ev- zrR+tC2P}x)!Xj_S_E(VWfMok+wKCZ~C(clLWh#$1+bn?A04tLk^qQ9vK|^hSkA-EP4DyG~(~F at C3HZux!`&@O>I--1>4CsqjQ3~I z(l*xCfG?jUO=Br5g^`q$8r1(onkSLQv;%Lt$MzWZ8l>p*;A_#n>iIm%C%2ipeP`gf z{rqL6yx(Oyd|0>Aj(siRG!HaWIu`Jm8s$(4m+=GhSqBF`xA?3@`Cl!DvO1F|zQFv)Nw(=Imv|QjeWxIyZ zG+LLAP`FSPy%pK;HHt1Z$#H}(Ey)n_0NS2pkSbJI`HcJt^?@sG_d(YlF-6V5`J+Ry z)Q8T|qLc&A{i9U;7#rKI$8?2^!`5qi0vovqz-BijoIeL|*dk)B;3yCP-6Kb15%iZ( zt|6m2b9TRI(o}9OY9(Zwpn34ga67g_W7rhw<03xnL%ZK_2bRV~xj$n3 at wX$^s8f3w zC$X0tO#tqT2tzk^JC=5A!yF?g_Ey2If$L{v^l14H3{K<8iI?!m?Zj_&5;P-EA#Z*X z2;)xO;Z26>_zWWjGDAwD_g&Jm-L2R*+j?NU_}kV<2qWw``+`X51B$dlF~2)J^{;(bxUdo*0u_-FnlGmc&ToQ-xLPs*ANL6WD=4Qg73wza)zX6txY at C<^HX_B*Sxt5K9a>?E(+qj12c z-tPvh>bm=jv|;D8 at 3Uf>osO7TS=p#UjvY~_3BO(Gs{fU1hrxYw{i at 3`Af_wJU9(CRKRyI ze5MT^BxVg#U{3CGS(YUksnyN;)5o*{pc^EzrxAy-myXU-n#(OoE$wxwRV?U%P^z8? zF$Fi>6lb2ccSbJb|XAs2Lp;mmC*!N}6Qtl at SW4T8k{Qz*uJ at nbwC>rm5=lDY=MByvoRF zNfX at dHkRgYQh$|Hb$Lp{V{x;P9B=VRS*YfEI0BhqT|VMjTF at Qqif^jyxm*iaE$TWl zAg?I27VYYkrg5;K|6Ytg8sESk>0XwKe)Y^=87Fj@%L1$W`!96E7N14(BnT}I6}2E$O=^hHuxE4(EKL*#$e0xS?5OQ?#_wStoKpj(&%+!z?-(&<2Dj4Arvjf zowRFSCz>VOo)(fZUm=4r(m{iClhMY1!(S70C*NbKYN>rF)My$3<|>r at Ph3!fR+M<49fai%$k$bJH4?TPN5XWUocd4?`CU zA8R*`F7m~EU&0k0NJqGSZ7se&t at _HuiF358xAIslE5BAl=ao+g+bb`qbeE9SJDce) zSkO0sk$dlqc3gKHe4*vg)S5`7B#9desV;_gMKf2z2z6>SB8{NWoFyrU{geleU{r9= zjos4ixT*UhAjP5#?T4s}!2b-SnvmkEv8TE)MLr*}vW&B*Q7*guKfRoFSX5oNz!5}3 zS_SD5BqfF!U68YQM!KZCr9}w=0YOr_yWyVk{rq0_d+)u^bN{&W zJZI*dwb$Nj at 4ePKGtbO#R@|nW321w0&l=yVIPuEW+Rc&sGNgmL(^f-Gu)@&)NrBpE zf{t9quIY61T1-TUTk6+lLP63=_x`VyM^<>*yKxJcdExo0Lf9_aSSIFmoS727Ma~%# z1>+XwU#(SNZs27S58oHv5W<^G<0)Bg>7p#hGst=)PH9A>TC^D+gq5hQ85j?LoCW++ zscJCmklmCzv5m$p^R`NX+`M{Lg?qhHWgb#j=;;p+HFLJY$WAtK=llvBsIlpp6cy9(1D z8DYE3OIq!pWFh$`=PCV6&DyV)I9;s?NB|i=Uz3Ta7Uor~*Mu0kuO^O`ONApUU8%R) z)ZCrF1SYy47vi6(6V+ugxK9RR?dpr~=zo_!HE~ahsBKvVKkywXRA$yrDY=-4F(acJ z#7Pj(M`Wg9CNY;a at 4Y@T-*eepGr9EKGc at t}NDz>@mFo;AQr{uCF-E+K!G29;U-)5G zJ()_+7=`Tmg(tZdIRWlEy@*E^{RaQYijk9>OV`*FDj+ at 36FD^`#g z4~|45C6#gEo$-XEAh!O(Mec+RInnm-LU|hjp3AK!R#xG)5`4^Mj`Lkk3^y at XP)cjY z!B at GKYlV&Fhy8ZTE$0|t8 at l7)q1HW^4&Jlt%(j6Rp09uIZ;H~XQ&o?){A5dEL+i_l z<5TRsIEs)8LZ?y=&yG8WZ@&X6EY14Hcd?3Dw_ at N%kYk#*XmWMd(djE?DF!Pn7}4dS zffRW)d39V$cM)04=x}o8(&?V1Dw+tCoHwCVDfCaH+|@MN7g?ArmK;$-;ENqSBC)xd zTGzhab{%sk>1SIRGxN=3rDynf>MwqxO=Z%Hnp36rl8)L}HGK2E=3K6&w$j+a^5N5w z0bQKHPLW8onOl1wu0cwSjJI}oANkYyru#lefDgzlQ)oq-mg>(Kp1G%W=yk*05RQ8q zt$M`Oo^V&KVDTE0!PTj3yEcp`eAuTwBK3XSt}@GcG`Y|~Ynz8YTRF7Lno&~V;B3+% z at u5PgBCcBdQ$$d-FKpt*Jyf`cpJwuAgP#%BV$et-R2-7qk$1yPb0^~|J{7rX2}VL*yvUFz9)@^)lVQVf)Zm`w~@L5}Yw1HAhkDu@>&?uM4y0 zXxCAE^@8q(lSc=T`nr<6=)Dn67$2X52 at Mmui(m*UC1iU9{pfUL*Gx^69n0=(+z6xj z+6~rF7lbuTs-K{>^Kiu^}k|l`Dw45Mv=BRGcR0 z8r=&8J&4e%UyH*FMsG&tY_y&h89nYaLJddymZiIzUOGO~xrN+3Zm(X`JTnb{R&3FK zi-nNifS*`)sCllQj_G~kh9Y~dzm&y%Tr8n5usED1W1 z9+ at 61EZye~-w{~)Hs*nu{OUgbL=;S|8FVppLv-3we6uFkJrm&dS`0VA%mmo&K5u+N z(aX^-ti551VUu|2AOo$rZneBJ*yW%- at B?+_YncKbrAm5^^pigR6!8ArpOzz)R2$Q4M>9@*KtLU3p*s71mFFS*bRED+_!@U**jZp8takJ{SWJ at y+I{KzlOpF-~vzkRm*%~&pdH>{rY*qErDdF{lnSrqN2iC zXt%YYt)b-G1=!WGj~CRYQ=NBi!l~XI;d$0}$+uCy$;ctFnC40g+lY)IAHa_#s~CC5 z{PfW~zVtbl5n&Xb42xkN^CWJBY$x9Qi>O;+Z=<#)9$Ge7-8X$n5 at vgsmzHa$?(ysR z5AoR}v$;`D20D*x3HK!GOIx~GmtLxL((6Tosf;MuNgYXEmP?2*4j~NN?{ZPW=wCu5 zHts)QBXjYslfNnDNo^`yKv+J+JVa_#u)a#?d{(tMFhe5u>})iKLF!9Sw}Ixf}?bo7* zS(bI|XEwr+lhSsD*K)M?^5S*kwlyN7C|<$6#Tb(G)`xwr*9Q0jU*3j1j`>^>8*7r) z8?72CmfQE(J$~@@#D}c1Ua16~MOPXdj1R%^aT80iQH(%n4BqWesP4>NMug2okOy^n zN374{ve^62SERX|raRyDYlLav*S}jQW2NZ$Y3?nY#j`jvaK*D#<|@%N^`Lr7OXq8} zmICwb#V6hr7dfey&MAWJjw-jgHr-9+i-ga;_1IZF*&SLVzLE*53M`*R7d^!d^@hRSgiju_**eC<@ zFYnHBCr`Z_TEUvi9WmG9HCW;iDUl1 at BTc{K^G2>~1-BdB1-<$@7V6lx+pO7LteUv@ zAz3wa4P$JQ825F)pUY at yvW;Pwe>8;Udh_m6UUMyii2T3TiYKnY^1) zbrv5>mRtv)DttQ0%lXr}hr;>$(HWfLOR^^4iIZ`X+Isz0b~^k*c*1Wk at j}jV5JwjK zVTvW$i2UfuHRoaBc-~Q-Ehjl%mpkjnQv_guEqk8-Z;m-5B-lu7eU<=fixR<@-S(+fUW zbuNL`SYJR4&Hdfn4CNa#&3mg at W$BC)=@Sy0)Tvo|#>p(USj;!;G74(1TapJ%xZfyG zJAH+L2%X at 6pmt+-_vTvlJH;Cb_q94L-5}*Ovc|n0CvW9zeK%$M+0JiWG9O{r^E)59 zsWj2+O0ISn-&L#hi;~}tI)y17p|KAP37_VJsLQ%ET9uL@{pp| zzpvWOu(AC3GS^d4uxKedvikGP1{2QO_~x2}f9e-QF+nu$+Zb`+1Ok>Q;klQ at tV<$h{KGoiJCU}u)On%;DcQG# z at TvJ*oSxjY#xN6PT*>kN40p*zGt0HQcFgZ>UyFHUd)|1Slkc}WJ&eJH3CYH<(BGI| zqp7=fYJ7Tdxb5FSi?RMwA7#v7s>CRIRN8 z7lX8QSpWwcnBx3+t=hx@C73R&2T31OWW?Qj-C0=2CT_FHP3Q>aH%s;Mu6gx$NWP?U~NwaF2S! z`3DTA^KKY(^9Fg&{2dzypLTYzH1ilA6xR+q at vo#3pczebJd6s8Ktnhek7-op$%M5N z?KEO>R6Q43ubHxIo0)-oCEYulpAWuE5OF_1XdwBlGmzm%z}bq~E#uJzT`q_KUo1sl0wJ9QLXLXW6nu^UIx>L$vc;RukT*_T2n*5SV~gY=@iyA at 3t&+ z#1V{-gL{M@{QTwmEyIh8ox$s7e$iL=`i#9~#=ed6b4U#`bNWaO>X=dBW>A`8(nSVc zVhhCOQe0Y~d<~j2L-_y>5w=808!6E~Qy>-EUwT!a-Z1FqGcxzIGkvoERPjUQKmj2a zT6J75+6=DQBfUUU4;%rkwD4=z6dT?MiVf6BOtSNg`C|XeiE*9^KU{yiA!!m_V at 3PpQgD#izyu(j82{luS*ANPg9?zNuI}Wbo$e9|q^t6e> zo`)b_?`&QVkqu*h at 2dFd{+O8?sY=&USj{yF3cpKbOBmxB>DKjOr6frdswb8X3}$Xg zQs94We}njvYmarRyb zwxqs?C<|Vdx~Qt1j6;S=6p?x^9b}l3H(fzfH at pHcW_oW2oOb z4DtzYvi(Bvf&I9bMtQxUX(lvctdHb1k_A%5&<@?q>sP>+~QW^tvn*%y5 zk1q>&5O?G~IWGuLj(P=-_Fnbt(vu6UpKYJu*Y4t%o`@ET+rQT~V&jAHJ$IKYf;C4# z2i(SX<;yEKbpxk1&Q+F^<@VX$MKtiA*zD?r)2C}qkC16jb!ac~Ck?TF41z8|GoUe0 z5>pdXwth1PFYpE0uHZAgx=-x&y7Ze+^1ey0fKbnyiOma_#K9DyRJ23#2757^48HP+ zY3H{eFT^aH&ekMDCd(z+sP%PGm8m&2HBXxYwyr)H>fX!1mlfc=Ab_3B?E8K{xmY at i z2 at dLiR5rRbHK94zhiB|)A)=j=pr!Y!RCc1VgLP1#;~R$9L{)r!b=B!)Rb-_S`uklW zv&Bhmv}$kiS*rOyd$Ntr$4&K=0_9P?ga%VHQv{POp5%mDm{3tr3r+WAkHMm!<{xn>iK7KCDlqn{w!2>#Gg{6v-mplTzT-_Itym zob0cI$0tpjre&Ikg^fN3s~l6L2#l2WY}xYXXpD`;4@*?h?a)eX(Vwb*t)?G|xUaDE z#abr^e7U!Yfln>*(#5*xgRD-E*|X@mz<>BQa1ydR<_X at G0YhOXWA

    uXo26~K9Qqom7DN5BiR3D1<;$)alrr<*m>DWe9E&VBs?S_B&f=SWdJTlzE8;1{Uy{*JFvE*#g(D>u?(OC?qk>PT zpEWGRTjmI8ElFpwzkJKX++c_(6SnO(_m>-E*pFu&WI7A$8^dz#ntFTWPCr7?E$KQM zm82lslfA^?6eh68OIK$wZ%qfUE|JD+pIPvw2PfiO5nuKQLd&+)>2-mHGNn8}_%*{G}GE1W at J_xhnwg1p)m4>3+wM1*x5nnHw%C4^HY6OWA>-|2qdxjmo-IWds|0@ zp|L%PsedTp at qLx}y33QEO`o zxB{^FmnX2<<>AIQ!iGphSL?44+0`{PK{k$7R)0N#fw5)uZA=+W5Udi4OuzaW@(V&M z?C4--i+Cs at E+GL10|5&LfJHD2IN=rrgCW564;j$*Q-*Bk<^>LM0bue#g>Qf#{@EP{ zr~!SD%`i^j73d3t0BS(k895pn|J36IhW;@Gp!-7~(BlM5aC86bKn at QD4nU5a0u(rh zhy$-&KTQIw76VF+Gm7y+z#LF8jDv%N6HtOa07DqSU+Khm3;*3Z(QO zeW6IS^EVlog9D&Qf0uDUAjo&B-}C?(u!28joX|h*azJ>1to%a{3i%Ja5D1v_&$$3H z?mz89AP{aKK7X4FAmRq%`41T{1jv{_Ww8I~3+3eabG^XIeqFBvLLWfE5y+zRO6IP{ zfGgP*ZEb;^LFNf?)0DC?u?78zY2<|%NDK5(LKMO+CN2Wyg>Z`ti}DC_itq?SxB#a^ zcsU?qTrdIb|6K){oMN_yqGra1miCU;Aa*feF}z|DqGF=Jmcqn1IYeO`qT&z{2#g0J d$|Wj}Ofh>0eT2i0kb^*hjKQX(6PK63{x1lfgiinf literal 0 HcmV?d00001 -- 1.7.9.5 From oleonard at myacpl.org Thu Jul 11 19:07:59 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Thu, 11 Jul 2013 13:07:59 -0400 Subject: [Koha-patches] [PATCH] Bug 7598 - Acquisitions JavaScript contains untranslatable English strings Message-ID: <1373562479-13121-1-git-send-email-oleonard@myacpl.org> English strings in acq.js cannot be processed by the translation script. This patch moves the strings to the templates to be set as JS variables for use by the script. To test: - On the uncertain prices page, enter an invalid price and click save. You should see a JavaScript alert pointing this out. - When adding a fund to an existing budget, enter an amount which exceeds the amount in the parent budget. You should see a JavaScript alert pointing this out. There is a similar function which has been corrected, checkBudgetParent(), but I don't know how to trigger it for testing. The closebasketgroup function has been updated but as far as I can tell it's not actually in use. --- koha-tmpl/intranet-tmpl/prog/en/js/acq.js | 20 ++++++++++---------- .../prog/en/modules/acqui/basketgroup.tt | 6 ++++++ .../prog/en/modules/acqui/uncertainprice.tt | 1 + .../prog/en/modules/admin/aqbudgets.tt | 7 +++++++ 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/acq.js b/koha-tmpl/intranet-tmpl/prog/en/js/acq.js index b9039ea..b1fdf58 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/js/acq.js +++ b/koha-tmpl/intranet-tmpl/prog/en/js/acq.js @@ -4,7 +4,7 @@ function uncheckbox(form, field) { var price = new Number(form.elements['price' + field].value); var tmpprice = ""; - var errmsg = _("ERROR: Price is not a valid number, please check the price and try again!") + var errmsg = MSG_INVALIDPRICE; if (isNaN(price)) { alert(errmsg); for(var i=0; i diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgets.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgets.tt index 7df04f3..44106ae 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgets.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgets.tt @@ -1,6 +1,13 @@ [% INCLUDE 'doc-head-open.inc' %] Koha › Administration › Funds[% IF ( add_form ) %] › [% IF ( budget_id ) %]Modify fund[% IF ( budget_name ) %] '[% budget_name %]'[% END %][% ELSE %]Add fund [% END %][% END %] [% INCLUDE 'doc-head-close.inc' %] + + [% IF ( add_form ) %] -- 1.7.9.5 From januszop at gmail.com Thu Jul 11 19:24:31 2013 From: januszop at gmail.com (Janusz Kaczmarek) Date: Thu, 11 Jul 2013 19:24:31 +0200 Subject: [Koha-patches] [PATCH] Bug 10578 - Escaping CGI breaks results sort feature (librarian's interface) Message-ID: <1373563471-13644-1-git-send-email-januszop@gmail.com> To test (in librarian's interface): 1. Have some biblio records to get a list when searching. 2. Make an advanced search with 'as phrase' modifier (title -- ti,phr: or author -- au,phr: , etc.) 3. Having the result list try to change the sort order. 4. You should get no results with a message like: "No results match your search for 'au%2Cphr: " etc. 5. Apply the patch 6. Repeat steps 2. & 3. 7. You should get the list sorted according to your choice. --- catalogue/search.pl | 5 +++++ 1 files changed, 5 insertions(+), 0 deletions(-) diff --git a/catalogue/search.pl b/catalogue/search.pl index d4e98b1..768a801 100755 --- a/catalogue/search.pl +++ b/catalogue/search.pl @@ -148,6 +148,7 @@ use C4::Languages qw(getAllLanguages); use C4::Koha; use C4::Members qw(GetMember); use C4::VirtualShelves; +use URI::Escape; use POSIX qw(ceil floor); use C4::Branch; # GetBranches @@ -392,10 +393,12 @@ unless (@servers) { # operators include boolean and proximity operators and are used # to evaluate multiple operands my @operators = $cgi->param('op'); + at operators = map { uri_unescape($_) } @operators; # indexes are query qualifiers, like 'title', 'author', etc. They # can be single or multiple parameters separated by comma: kw,right-Truncation my @indexes = $cgi->param('idx'); + at indexes = map { uri_unescape($_) } @indexes; # if a simple index (only one) display the index used in the top search box if ($indexes[0] && (!$indexes[1] || $params->{'scan'})) { @@ -407,9 +410,11 @@ if ($indexes[0] && (!$indexes[1] || $params->{'scan'})) { # an operand can be a single term, a phrase, or a complete ccl query my @operands = $cgi->param('q'); + at operands = map { uri_unescape($_) } @operands; # limits are use to limit to results to a pre-defined category such as branch or language my @limits = $cgi->param('limit'); + at limits = map { uri_unescape($_) } @limits; if($params->{'multibranchlimit'}) { my $multibranch = '('.join( " or ", map { "branch: $_ " } @{ GetBranchesInCategory( $params->{'multibranchlimit'} ) } ).')'; -- 1.7.2.5 From srdjan at catalyst.net.nz Tue Jul 16 02:09:07 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Tue, 16 Jul 2013 12:09:07 +1200 Subject: [Koha-patches] [PATCH] [SIGNED-OFF] Bug 10556: The delivery time is not inserted on adding a supplier. Message-ID: <1373933347-26719-1-git-send-email-srdjan@catalyst.net.nz> From: Jonathan Druart Test plan: Add/edit a supplier and check that the delivery time is set in DB. Note: This patch cleans the code (sql query) in order to see easily if a problem occurred. Signed-off-by: Srdjan --- C4/Bookseller.pm | 92 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/C4/Bookseller.pm b/C4/Bookseller.pm index c8389a3..10f4d80 100644 --- a/C4/Bookseller.pm +++ b/C4/Bookseller.pm @@ -175,32 +175,31 @@ sub AddBookseller { my $query = q| INSERT INTO aqbooksellers ( - name, address1, address2, address3, address4, - postal, phone, accountnumber, fax, url, - contact, - contpos, contphone, contfax, contaltphone, contemail, - contnotes, active, listprice, invoiceprice, gstreg, - listincgst,invoiceincgst, gstrate, discount, - notes + name, address1, address2, address3, address4, + postal, phone, accountnumber,fax, url, + contact, contpos, contphone, contfax, contaltphone, + contemail, contnotes, active, listprice, invoiceprice, + gstreg, listincgst, invoiceincgst,gstrate, discount, + notes, deliverytime ) - VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) | + VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) | ; my $sth = $dbh->prepare($query); $sth->execute( - $data->{'name'}, $data->{'address1'}, - $data->{'address2'}, $data->{'address3'}, - $data->{'address4'}, $data->{'postal'}, - $data->{'phone'}, $data->{'accountnumber'}, - $data->{'fax'}, - $data->{'url'}, $data->{'contact'}, - $data->{'contpos'}, $data->{'contphone'}, - $data->{'contfax'}, $data->{'contaltphone'}, - $data->{'contemail'}, $data->{'contnotes'}, - $data->{'active'}, $data->{'listprice'}, - $data->{'invoiceprice'}, $data->{'gstreg'}, - $data->{'listincgst'}, $data->{'invoiceincgst'}, - $data->{'gstrate'}, - $data->{'discount'}, $data->{'notes'} + $data->{name} ,$data->{address1}, + $data->{address2} ,$data->{address3}, + $data->{address4} ,$data->{postal}, + $data->{phone} ,$data->{accountnumber}, + $data->{fax}, + $data->{url} ,$data->{contact}, + $data->{contpos} ,$data->{contphone}, + $data->{contfax} ,$data->{contaltphone}, + $data->{contemail} ,$data->{contnotes}, + $data->{active} ,$data->{listprice}, + $data->{invoiceprice} ,$data->{gstreg}, + $data->{listincgst} ,$data->{invoiceincgst}, + $data->{gstrate} ,$data->{discount}, + $data->{notes} ,$data->{deliverytime}, ); # return the id of this new supplier @@ -227,32 +226,33 @@ C<&ModBookseller> with the result. sub ModBookseller { my ($data) = @_; my $dbh = C4::Context->dbh; - my $query = 'UPDATE aqbooksellers - SET name=?,address1=?,address2=?,address3=?,address4=?, - postal=?,phone=?,accountnumber=?,fax=?,url=?,contact=?,contpos=?, - contphone=?,contfax=?,contaltphone=?,contemail=?, - contnotes=?,active=?,listprice=?, invoiceprice=?, - gstreg=?,listincgst=?,invoiceincgst=?, - discount=?,notes=?,gstrate=?,deliverytime=? - WHERE id=?'; + my $query = q| + UPDATE aqbooksellers + SET name = ?, address1 = ?, address2 = ?, address3 = ?, address4 = ?, + postal = ?, phone = ?, accountnumber = ?, fax = ?, url = ?, + contact = ?, contpos = ?, contphone = ?, contfax = ?, contaltphone = ?, + contemail = ?, contnotes = ?, active = ?, listprice = ?, invoiceprice = ?, + gstreg = ?, listincgst = ?, invoiceincgst = ?, gstrate = ?, discount = ?, + notes = ?, deliverytime = ? + WHERE id=? + |; my $sth = $dbh->prepare($query); $sth->execute( - $data->{'name'}, $data->{'address1'}, - $data->{'address2'}, $data->{'address3'}, - $data->{'address4'}, $data->{'postal'}, - $data->{'phone'}, $data->{'accountnumber'}, - $data->{'fax'}, - $data->{'url'}, $data->{'contact'}, - $data->{'contpos'}, $data->{'contphone'}, - $data->{'contfax'}, $data->{'contaltphone'}, - $data->{'contemail'}, $data->{'contnotes'}, - $data->{'active'}, $data->{'listprice'}, - $data->{'invoiceprice'}, $data->{'gstreg'}, - $data->{'listincgst'}, $data->{'invoiceincgst'}, - $data->{'discount'}, $data->{'notes'}, - $data->{'gstrate'}, - $data->{deliverytime}, - $data->{'id'} + $data->{name} ,$data->{address1}, + $data->{address2} ,$data->{address3}, + $data->{address4} ,$data->{postal}, + $data->{phone} ,$data->{accountnumber}, + $data->{fax}, + $data->{url} ,$data->{contact}, + $data->{contpos} ,$data->{contphone}, + $data->{contfax} ,$data->{contaltphone}, + $data->{contemail} ,$data->{contnotes}, + $data->{active} ,$data->{listprice}, + $data->{invoiceprice} ,$data->{gstreg}, + $data->{listincgst} ,$data->{invoiceincgst}, + $data->{gstrate} ,$data->{discount}, + $data->{notes} ,$data->{deliverytime}, + $data->{id}, ); return; } -- 1.8.1.2 From srdjan at catalyst.net.nz Tue Jul 16 02:47:30 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Tue, 16 Jul 2013 12:47:30 +1200 Subject: [Koha-patches] [PATCH] Bug 10197: Add classes to patron info list Message-ID: <1373935650-30645-1-git-send-email-srdjan@catalyst.net.nz> From: "Nicole C. Engard" This patch adds classes to the patron info found on the top left of the circulation and patron related pages to allow for easy styling of the information displayed. To test: * Apply patch * View a patron detail page and view the source on the list to the left to see the styles * View a checkout screen and view the source on the list to the left with patron info to see the styles * You could also try to style things by customizing your CSS Signed-off-by: Srdjan --- koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc | 18 +++++++++--------- koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.tt | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc index 7101260..4632467 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/circ-menu.inc @@ -4,31 +4,31 @@ -

      +
        [% IF ( patronimages ) %] [% IF ( picture ) %]
      • [% firstname %] [% surname %] ([% cardnumber %])
      • [% ELSE %] -
      • [% firstname %] [% surname %] ([% cardnumber %])
      • +
      • [% firstname %] [% surname %] ([% cardnumber %])
      • [% END %] [% END %] [% IF ( address or address2 ) %] [% IF ( address ) %] -
      • [% address %]
      • +
      • [% address %]
      • [% END %] [% IF ( address2 ) %] -
      • [% address2 %]
      • +
      • [% address2 %]
      • [% END %] [% ELSE %]
      • No address stored.
      • [% END %] -
      • [% IF ( city ) %] +
      • [% IF ( city ) %] [% city %][% IF ( state ) %], [% state %][% END %] [% zipcode %][% IF ( country ) %], [% country %][% END %] [% ELSE %] No city stored. [% END %]
      • -
      • [% IF ( phone ) %] +
      • [% IF ( phone ) %] [% phone %] [% ELSE %] [% IF ( mobile ) %] @@ -53,12 +53,12 @@ [% IF ( ExtendedPatronAttributes ) %][% FOREACH extendedattribute IN extendedattributes %] [% IF ( extendedattribute.display_checkout ) %] [% IF ( extendedattribute.value ) %] -
      • [% extendedattribute.description %] : [% IF ( extendedattribute.value_description ) %][% extendedattribute.value_description %][% ELSE %][% extendedattribute.value %][% END %]
      • +
      • [% extendedattribute.description %] : [% IF ( extendedattribute.value_description ) %][% extendedattribute.value_description %][% ELSE %][% extendedattribute.value %][% END %]
      • [% END %] [% END %] [% END %][% END %] -
      • Category: [% categoryname %] ([% categorycode %])
      • -
      • Home library: [% IF ( branchname ) %][% branchname %][% ELSE %][% branch %][% END %]
      • +
      • Category: [% categoryname %] ([% categorycode %])
      • +
      • Home library: [% IF ( branchname ) %][% branchname %][% ELSE %][% branch %][% END %]
+ [% IF issue.returndate %] + [% issue.returndate | $KohaDates %] + [% ELSE %] + Checked Out + [% END %] + [% END %]
# Citation StatusMatch? Match typeMatch details Record
- [% IF issue.returndate %] - [% issue.returndate | $KohaDates %] - [% ELSE %] - Checked Out - [% END %] -
-- 1.8.1.2 From srdjan at catalyst.net.nz Wed Jul 17 05:59:32 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Wed, 17 Jul 2013 15:59:32 +1200 Subject: [Koha-patches] [PATCH] bug 10559: remove spurious "statement handle still active" warnings Message-ID: <1374033572-11093-1-git-send-email-srdjan@catalyst.net.nz> From: Galen Charlton Generating (e.g.) overdue notices can result in spurious warnings in the cronjob logs: $ ./misc/cronjobs/overdue_notices.pl -t -library CPL prepare_cached(SELECT * FROM issues WHERE itemnumber = ?) statement handle DBI::st=HASH(0x54a7828) still Active at C4/Letters.pm line 589 This patch removes the warning by making sure that the relevant statement handle is finished after fetching its first row of results. To test: [1] Set up an overdue loan such that running overdue_notices.pl will trigger the generation of a notice. [2] Run overdue_notices.pl -t and note the warning message. [3] Apply the patch. [4] Run overdue_notices.pl -t again and note that the warning message is no longer displayed. [5] Check the message_queue table and verify that the overdue notices generated in steps 2 and 4 have the same text. Signed-off-by: Galen Charlton Signed-off-by: Srdjan --- C4/Letters.pm | 1 + 1 file changed, 1 insertion(+) diff --git a/C4/Letters.pm b/C4/Letters.pm index d36c29f..37883c6 100644 --- a/C4/Letters.pm +++ b/C4/Letters.pm @@ -550,6 +550,7 @@ sub _substitute_tables { $sth->execute( $ref ? @$param : $param ); $values = $sth->fetchrow_hashref; + $sth->finish(); } _parseletter ( $letter, $table, $values ); -- 1.8.1.2 From srdjan at catalyst.net.nz Wed Jul 17 06:12:20 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Wed, 17 Jul 2013 16:12:20 +1200 Subject: [Koha-patches] [PATCH] Bug 10463 - Quote of the day feature not selecting random quotes Message-ID: <1374034340-12515-1-git-send-email-srdjan@catalyst.net.nz> From: Kyle M Hall When the Quote of the Day tool selects a new new quote, it updates the timestamp and does not take the timezone into account. Thus the time is set to +4 hours (e.g. 2013-06-11 13:33:48 when the time is 2013-06-11 09:33:48). It then repeats the same quote every day. To replicate: set Administration >> System preferences >> OPAC preferences >> Features >> QuoteOfTheDay to Enable In Home >> Tools >> Quote Editor, add several quotes. In the opac, refresh the home page. You should get a quote of the day at the top. mysql> select * from quotes; note the timestamp of the quote selected by the tool. It will not match the date on the machine. If you change the date to the previous date and refresh the opac, the tool wlill select another quote, which will not change unless forced. Test Plan: 1) Remove all your quotes and import a fresh set 2) Enable the quote of the day and view the opac 3) Look at your quotes table and note the timestamp is incorrect 4) Repeat steps 1 and 2 5) Look at your quotes table and note the timestamp is now correct Signed-off-by: Srdjan --- C4/Koha.pm | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/C4/Koha.pm b/C4/Koha.pm index 9976995..e40efc9 100644 --- a/C4/Koha.pm +++ b/C4/Koha.pm @@ -25,8 +25,8 @@ use strict; use C4::Context; use C4::Branch qw(GetBranchesCount); +use Koha::DateUtils qw(dt_from_string); use Memoize; -use DateTime; use DateTime::Format::MySQL; use autouse 'Data::Dumper' => qw(Dumper); @@ -1478,7 +1478,10 @@ sub GetDailyQuote { # update the timestamp for that quote $query = 'UPDATE quotes SET timestamp = ? WHERE id = ?'; $sth = C4::Context->dbh->prepare($query); - $sth->execute(DateTime::Format::MySQL->format_datetime(DateTime->now), $quote->{'id'}); + $sth->execute( + DateTime::Format::MySQL->format_datetime( dt_from_string() ), + $quote->{'id'} + ); } return $quote; } -- 1.8.1.2 From srdjan at catalyst.net.nz Thu Jul 18 01:41:25 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Thu, 18 Jul 2013 11:41:25 +1200 Subject: [Koha-patches] [PATCH] [SIGNED-OFF] bug 10503: fix various issues with use of Memoize::Memcached Message-ID: <1374104485-5364-1-git-send-email-srdjan@catalyst.net.nz> From: Galen Charlton Memoize::Memcached expects to be passed a hashref of connection parameters, which it in turn uses to initialize a Cache::Memcached object. However, commit 52afe06ddd started passing a Cache::Memcached object directly, not the required hashref. This happened to work by coincidence, but no longer works with recent versions of Memoize::Memcached packaged for Debian. This patch introduces a new C4::Context function, memcached_params(), that returns a hashref of connection parameters suitable for passing to the Cache::Memcached constructor. It also introduces a UNITCHECK block to C4::Context so that memcached_params() can be used during intialization of the module. This patch also corrects SQLHelper so that it no longer tries to use the deprecated (and removed) memcached_servers setting in koha-conf.xml; it now gets the memcached connection parameters from C4::Context->memcached_params(). To test: [1] This patch is most easily tested on Debian Wheezy, as version 0.03-2 of the libmemoize-memcached-perl package includes the fix for Debian bug 614868 that causes Koha's use of Memoize::Memcached to break. If you don't want to go so far as to install/upgrade to Wheezy, you can apply the following Debian patch to your copy of Memoize::Memcached to get the effect: http://patch-tracker.debian.org/patch/series/view/libmemoize-memcached-perl/0.03-2/universal.patch [2] Set up your Koha Apache configuration to point to a memcached server. [3] Restart memcached to start with a clear cache. [4] Do the following steps: - Create a new bib record. Note that it is sufficient to just open the editor; you don't need to save the bib. - Search for a patron record. [5] Use the memcdump command-line to get a list of keys in your memcached cache. You should *not* see keys that contain the strings GetMarcStructure, getTranslatedLanguages, or _get_columns. [6] Apply the patch, then go through step 4 again. [7] Use memcdump again. This time, you *should* see the keys mentioned in step 5. [8] Set the SessionStorage system preference to memcached. After logging in again, verify that your staff interface and OPAC sessions work without requiring that you log in for each and every page load. Signed-off-by: Galen Charlton Signed-off-by: Srdjan --- C4/Biblio.pm | 2 +- C4/Context.pm | 40 +++++++++++++++++++++++++++------------- C4/Languages.pm | 6 +++--- C4/SQLHelper.pm | 13 +++---------- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/C4/Biblio.pm b/C4/Biblio.pm index 7af8619..6f924bd 100644 --- a/C4/Biblio.pm +++ b/C4/Biblio.pm @@ -146,7 +146,7 @@ eval { import Memoize::Memcached qw(memoize_memcached); memoize_memcached( 'GetMarcStructure', - memcached => C4::Context->memcached); + memcached => C4::Context->memcached_params); } }; diff --git a/C4/Context.pm b/C4/Context.pm index 7709f7e..baffc5c 100644 --- a/C4/Context.pm +++ b/C4/Context.pm @@ -18,7 +18,7 @@ package C4::Context; use strict; use warnings; -use vars qw($VERSION $AUTOLOAD $context @context_stack $servers $memcached $ismemcached); +use vars qw($VERSION $AUTOLOAD $context @context_stack $memcached $ismemcached); BEGIN { if ($ENV{'HTTP_USER_AGENT'}) { @@ -79,23 +79,18 @@ BEGIN { } } # else there is no browser to send fatals to! + $VERSION = '3.07.00.049'; +} + +UNITCHECK { # Check if there are memcached servers set - $servers = $ENV{'MEMCACHED_SERVERS'}; - if ($servers) { + if ($ENV{'MEMCACHED_SERVERS'}) { # Load required libraries and create the memcached object require Cache::Memcached; - $memcached = Cache::Memcached->new({ - servers => [ $servers ], - debug => 0, - compress_threshold => 10_000, - expire_time => 600, - namespace => $ENV{'MEMCACHED_NAMESPACE'} || 'koha' - }); + $memcached = Cache::Memcached->new(memcached_params()); # Verify memcached available (set a variable and test the output) - $ismemcached = $memcached->set('ismemcached','1'); + $ismemcached = $memcached->set('ismemcached','1'); } - - $VERSION = '3.07.00.049'; } use DBI; @@ -293,6 +288,25 @@ sub memcached { } } +=head2 memcached_params + +Return a hashref containing the memcached parameters in a +form suitable for initializing a new C +object. Caller is responsible for verifying that connection +parameters work. + +=cut + +sub memcached_params { + return { + servers => [ $ENV{'MEMCACHED_SERVERS'} ], + namespace => $ENV{'MEMCACHED_NAMESPACE'} || 'koha', + debug => 0, + expire_time => 600, + compress_threshold => 10_000, + }; +} + # db_scheme2dbi # Translates the full text name of a database into de appropiate dbi name # diff --git a/C4/Languages.pm b/C4/Languages.pm index 3a5ee2a..ca683e4 100644 --- a/C4/Languages.pm +++ b/C4/Languages.pm @@ -30,9 +30,9 @@ eval { require Memoize::Memcached; import Memoize::Memcached qw(memoize_memcached); - memoize_memcached('getTranslatedLanguages', memcached => C4::Context->memcached); - memoize_memcached('getFrameworkLanguages' , memcached => C4::Context->memcached); - memoize_memcached('getAllLanguages', memcached => C4::Context->memcached); + memoize_memcached('getTranslatedLanguages', memcached => C4::Context->memcached_params); + memoize_memcached('getFrameworkLanguages' , memcached => C4::Context->memcached_params); + memoize_memcached('getAllLanguages', memcached => C4::Context->memcached_params); } }; diff --git a/C4/SQLHelper.pm b/C4/SQLHelper.pm index 21f5fa1..c107370 100644 --- a/C4/SQLHelper.pm +++ b/C4/SQLHelper.pm @@ -28,19 +28,12 @@ require Exporter; use vars qw($VERSION @ISA @EXPORT_OK %EXPORT_TAGS); eval { - my $servers = C4::Context->config('memcached_servers'); - if ($servers) { + if (C4::Context->ismemcached) { require Memoize::Memcached; import Memoize::Memcached qw(memoize_memcached); - my $memcached = { - servers => [$servers], - key_prefix => C4::Context->config('memcached_namespace') || 'koha', - expire_time => 600 - }; # cache for 10 mins - - memoize_memcached( '_get_columns', memcached => $memcached ); - memoize_memcached( 'GetPrimaryKeys', memcached => $memcached ); + memoize_memcached( '_get_columns', memcached => C4::Context->memcached_params() ); + memoize_memcached( 'GetPrimaryKeys', memcached => C4::Context->memcached_params() ); } }; -- 1.8.1.2 From srdjan at catalyst.net.nz Thu Jul 18 01:52:47 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Thu, 18 Jul 2013 11:52:47 +1200 Subject: [Koha-patches] [PATCH] [SIGNED-OFF] Bug 10441: Testing AddShare in VirtualShelves.t Message-ID: <1374105167-6710-1-git-send-email-srdjan@catalyst.net.nz> From: Marcel de Rooy Builds upon 10386 and 9032. Adds a unit test for routine AddShare. This patch also restores the inadvertently deleted DelShelf tests in bug 10499. Test plan: Run the test. All passed? Signed-off-by: Srdjan --- t/db_dependent/VirtualShelves.t | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/t/db_dependent/VirtualShelves.t b/t/db_dependent/VirtualShelves.t index 9f3f1b0..4a20619 100755 --- a/t/db_dependent/VirtualShelves.t +++ b/t/db_dependent/VirtualShelves.t @@ -5,7 +5,7 @@ # Larger modifications by Jonathan Druart and Marcel de Rooy use Modern::Perl; -use Test::More tests => 71; +use Test::More tests => 83; use MARC::Record; use C4::Biblio qw( AddBiblio DelBiblio ); @@ -177,6 +177,43 @@ for my $i(0..9){ } } +#----------------------- TEST AddShare ----------------------------------------# + +#first count the number of shares in the table; keep in mind that AddShare may +#delete some expired records while housekeeping +my $sql_sharecount="select count(*) from virtualshelfshares where DATEDIFF(sharedate, NOW())>0"; +my $cnt1=$dbh->selectrow_array($sql_sharecount); + +#try to add a share without shelfnumber: should fail +AddShare(0, 'abcdefghij'); +my $cnt2=$dbh->selectrow_array($sql_sharecount); +ok($cnt1 == $cnt2, "Did not add an invalid share record"); + +#add another share: should be okay +#AddShare assumes that you tested if category==private (so we could actually +#be doing something illegal here :) +my $n=$shelves[0]->{number}; +if($n<0) { + ok(1, 'Skip AddShare for shelf -1'); +} +else { + AddShare($n, 'abcdefghij'); + my $cnt3=$dbh->selectrow_array($sql_sharecount); + ok(1+$cnt2 == $cnt3, "Added one new share record with invitekey"); +} + +#----------------TEST DelShelf & DelFromShelf functions------------------------# + +for(my $i=0; $i<10;$i++){ + my $shelfnumber = $shelves[$i]->{number}; + if($shelfnumber<0) { + ok(1, 'Skip DelShelf for shelf -1'); + next; + } + my $status = DelShelf($shelfnumber); + ok(1 == $status, "deleted shelf $shelfnumber and its contents"); +} + #----------------------- SOME SUBS --------------------------------------------# sub randomname { -- 1.8.1.2 From srdjan at catalyst.net.nz Thu Jul 18 02:54:00 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Thu, 18 Jul 2013 12:54:00 +1200 Subject: [Koha-patches] [PATCH] Bug 10584 - Hide OPAC biblio details if all items are hidden Message-ID: <1374108840-12096-1-git-send-email-srdjan@catalyst.net.nz> From: Mark Tompsett If there are items for a given biblio number, and they are all hidden, then biblio needs to be hidden. If the biblio needs to be hidden, this is done by setting the biblionumber to 0, which triggers the same output as if the biblionumber does not exist. Signed-off-by: Srdjan --- opac/opac-detail.pl | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/opac/opac-detail.pl b/opac/opac-detail.pl index 9d0851f..612831a 100755 --- a/opac/opac-detail.pl +++ b/opac/opac-detail.pl @@ -70,9 +70,20 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( } ); -my $biblionumber = $query->param('biblionumber') || $query->param('bib'); +my $biblionumber = $query->param('biblionumber') || $query->param('bib') || 0; $biblionumber = int($biblionumber); +my @itemsmatchingbiblionumber = GetItemsInfo($biblionumber); +if (scalar @itemsmatchingbiblionumber >= 1) { + my @items2hide = GetHiddenItemnumbers(@itemsmatchingbiblionumber); + + if (scalar @items2hide == scalar @itemsmatchingbiblionumber ) { + # biblionumber=0 effectively hides the biblio record + # since there is no such biblionumber. + $biblionumber = 0; + } +} + my $record = GetMarcBiblio($biblionumber); if ( ! $record ) { print $query->redirect("/cgi-bin/koha/errors/404.pl"); # escape early -- 1.8.1.2 From srdjan at catalyst.net.nz Thu Jul 18 06:45:51 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Thu, 18 Jul 2013 16:45:51 +1200 Subject: [Koha-patches] [PATCH] [SIGNED-OFF] Bug 10578 - Escaping CGI breaks results sort feature (librarian's interface) Message-ID: <1374122751-31874-1-git-send-email-srdjan@catalyst.net.nz> From: Janusz Kaczmarek To test (in librarian's interface): 1. Have some biblio records to get a list when searching. 2. Make an advanced search with 'as phrase' modifier (title -- ti,phr: or author -- au,phr: , etc.) 3. Having the result list try to change the sort order. 4. You should get no results with a message like: "No results match your search for 'au%2Cphr: " etc. 5. Apply the patch 6. Repeat steps 2. & 3. 7. You should get the list sorted according to your choice. Signed-off-by: Srdjan --- catalogue/search.pl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/catalogue/search.pl b/catalogue/search.pl index f8dab56..e1154c3 100755 --- a/catalogue/search.pl +++ b/catalogue/search.pl @@ -148,6 +148,7 @@ use C4::Languages qw(getAllLanguages); use C4::Koha; use C4::Members qw(GetMember); use C4::VirtualShelves; +use URI::Escape; use POSIX qw(ceil floor); use C4::Branch; # GetBranches @@ -391,11 +392,11 @@ unless (@servers) { } # operators include boolean and proximity operators and are used # to evaluate multiple operands -my @operators = $cgi->param('op'); +my @operators = map uri_unescape($_), $cgi->param('op'); # indexes are query qualifiers, like 'title', 'author', etc. They # can be single or multiple parameters separated by comma: kw,right-Truncation -my @indexes = $cgi->param('idx'); +my @indexes = map uri_unescape($_), $cgi->param('idx'); # if a simple index (only one) display the index used in the top search box if ($indexes[0] && (!$indexes[1] || $params->{'scan'})) { @@ -404,12 +405,11 @@ if ($indexes[0] && (!$indexes[1] || $params->{'scan'})) { $template->param($idx => 1); } - # an operand can be a single term, a phrase, or a complete ccl query -my @operands = $cgi->param('q'); +my @operands = map uri_unescape($_), $cgi->param('q'); # limits are use to limit to results to a pre-defined category such as branch or language -my @limits = $cgi->param('limit'); +my @limits = map uri_unescape($_), $cgi->param('limit'); if($params->{'multibranchlimit'}) { my $multibranch = '('.join( " or ", map { "branch: $_ " } @{ GetBranchesInCategory( $params->{'multibranchlimit'} ) } ).')'; -- 1.8.1.2 From oleonard at myacpl.org Thu Jul 18 17:33:40 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Thu, 18 Jul 2013 11:33:40 -0400 Subject: [Koha-patches] [PATCH] Bug 7598 [Follow-up] Acquisitions JavaScript contains untranslatable English strings Message-ID: <1374161620-14222-1-git-send-email-oleonard@myacpl.org> This follow-up addresses QA comments and moves punctuation and line breaks out of the string to be translated. --- koha-tmpl/intranet-tmpl/prog/en/js/acq.js | 8 +------- .../prog/en/modules/admin/aqbudgets.tt | 5 +++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/js/acq.js b/koha-tmpl/intranet-tmpl/prog/en/js/acq.js index b1fdf58..9997768 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/js/acq.js +++ b/koha-tmpl/intranet-tmpl/prog/en/js/acq.js @@ -35,12 +35,6 @@ function isNull(f,noalert) { return true; } - - - - - - //Function returns false if v is not a number (if maybenull is 0, it also returns an error if the number is 0) function isNum(v,maybenull) { var n = new Number(v.value); @@ -822,7 +816,7 @@ if ( newBudgetParent ) { url += '&parent_id=' + newBudgetParent}; if (result == '1') { return MSG_BUDGET_PARENT_ALLOCATION; } else if (result == '2') { - return MSG_BUDGET_PARENT_ALLOCATION; + return MSG_BUDGET_PERIOD_ALLOCATION; } else { return false; } diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgets.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgets.tt index 44106ae..82a6647 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgets.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/aqbudgets.tt @@ -3,8 +3,9 @@ [% INCLUDE 'doc-head-close.inc' %] -- 1.7.9.5 From srdjan at catalyst.net.nz Fri Jul 19 03:56:34 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 19 Jul 2013 13:56:34 +1200 Subject: [Koha-patches] [PATCH] Bug 10508 : C4::Branch.pm needs unit tests. Message-ID: <1374198994-7750-1-git-send-email-srdjan@catalyst.net.nz> From: Kenza Zaki Unit tests are wrap in a transaction. NOTE: the field "issuing" isn't used in the database To test: prove t/db_dependent/Branch.t t/db_dependent/Branch.t .. ok All tests successful. Files=1, Tests=31, 0 wallclock secs ( 0.03 usr 0.00 sys + 0.13 cusr 0.00 csys = 0.16 CPU) Result: PASS Signed-off-by: Srdjan --- C4/Branch.pm | 10 -- t/db_dependent/Branch.t | 298 ++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 291 insertions(+), 17 deletions(-) diff --git a/C4/Branch.pm b/C4/Branch.pm index 8b76771..c1e3587 100644 --- a/C4/Branch.pm +++ b/C4/Branch.pm @@ -182,7 +182,6 @@ sub GetBranchName { $sth = $dbh->prepare("Select branchname from branches where branchcode=?"); $sth->execute($branchcode); my $branchname = $sth->fetchrow_array; - $sth->finish; return ($branchname); } @@ -278,7 +277,6 @@ sub ModBranch { "insert into branchrelations (branchcode, categorycode) values(?, ?)" ); $sth->execute( $branchcode, $cat ); - $sth->finish; } foreach my $cat (@removecats) { my $sth = @@ -286,7 +284,6 @@ sub ModBranch { "delete from branchrelations where branchcode=? and categorycode=?" ); $sth->execute( $branchcode, $cat ); - $sth->finish; } } @@ -422,7 +419,6 @@ sub GetBranchesInCategory { while (my $branch = $sth->fetchrow) { push @branches, $branch; } - $sth->finish(); return( \@branches ); } @@ -467,11 +463,9 @@ sub GetBranchInfo { while ( my ($cat) = $nsth->fetchrow_array ) { push( @cats, $cat ); } - $nsth->finish; $data->{'categories'} = \@cats; push( @results, $data ); } - $sth->finish; return \@results; } @@ -486,7 +480,6 @@ sub DelBranch { my $dbh = C4::Context->dbh; my $sth = $dbh->prepare("delete from branches where branchcode = ?"); $sth->execute($branchcode); - $sth->finish; } =head2 ModBranchCategoryInfo @@ -503,13 +496,11 @@ sub ModBranchCategoryInfo { # we are doing an insert my $sth = $dbh->prepare("INSERT INTO branchcategories (categorycode,categoryname,codedescription,categorytype,show_in_pulldown) VALUES (?,?,?,?,?)"); $sth->execute(uc( $data->{'categorycode'} ),$data->{'categoryname'}, $data->{'codedescription'},$data->{'categorytype'},$data->{'show_in_pulldown'} ); - $sth->finish(); } else { # modifying my $sth = $dbh->prepare("UPDATE branchcategories SET categoryname=?,codedescription=?,categorytype=?,show_in_pulldown=? WHERE categorycode=?"); $sth->execute($data->{'categoryname'}, $data->{'codedescription'},$data->{'categorytype'},$data->{'show_in_pulldown'},uc( $data->{'categorycode'} ) ); - $sth->finish(); } } @@ -546,7 +537,6 @@ sub DelBranchCategory { my $dbh = C4::Context->dbh; my $sth = $dbh->prepare("delete from branchcategories where categorycode = ?"); $sth->execute($categorycode); - $sth->finish; } =head2 CheckBranchCategorycode diff --git a/t/db_dependent/Branch.t b/t/db_dependent/Branch.t index cc19f21..4251816 100644 --- a/t/db_dependent/Branch.t +++ b/t/db_dependent/Branch.t @@ -21,7 +21,7 @@ use Modern::Perl; use C4::Context; use Data::Dumper; -use Test::More tests => 6; +use Test::More ;#tests => 6; use C4::Branch; @@ -30,6 +30,29 @@ BEGIN { use lib $FindBin::Bin; use_ok('C4::Branch'); } +can_ok( + 'C4::Branch', qw( + GetBranchCategory + GetBranchName + GetBranch + GetBranches + GetBranchesLoop + GetBranchDetail + get_branchinfos_of + ModBranch + CheckBranchCategorycode + GetBranchInfo + GetCategoryTypes + GetBranchCategories + GetBranchesInCategory + ModBranchCategoryInfo + DelBranch + DelBranchCategory + CheckCategoryUnique + mybranch + GetBranchesCount) +); + # Start transaction my $dbh = C4::Context->dbh; @@ -39,8 +62,127 @@ $dbh->{RaiseError} = 1; # clear the slate $dbh->do('DELETE FROM branchcategories'); -my @category_types = GetCategoryTypes(); -is_deeply(\@category_types, [ 'searchdomain', 'properties' ], 'received expected library category types'); +# Start test + +my $count = GetBranchesCount; +like( $count, '/^\d+$/', "the count is a number" ); + +#add 2 branches +my $b1 = { + add => 1, + branchcode => 'BRA', + branchname => 'BranchA', + branchaddress1 => 'adr1A', + branchaddress2 => 'adr2A', + branchaddress3 => 'adr3A', + branchzip => 'zipA', + branchcity => 'cityA', + branchstate => 'stateA', + branchcountry => 'countryA', + branchphone => 'phoneA', + branchfax => 'faxA', + branchemail => 'emailA', + branchurl => 'urlA', + branchip => 'ipA', + branchprinter => undef, + branchnotes => 'noteA', + opac_info => 'opacA' +}; +my $b2 = { + branchcode => 'BRB', + branchname => 'BranchB', + branchaddress1 => 'adr1B', + branchaddress2 => 'adr2B', + branchaddress3 => 'adr3B', + branchzip => 'zipB', + branchcity => 'cityB', + branchstate => 'stateB', + branchcountry => 'countryB', + branchphone => 'phoneB', + branchfax => 'faxB', + branchemail => 'emailB', + branchurl => 'urlB', + branchip => 'ipB', + branchprinter => undef, + branchnotes => 'noteB', + opac_info => 'opacB', +}; +ModBranch($b1); +is( ModBranch($b2), undef, 'the field add is missing' ); + +$b2->{add} = 1; +ModBranch($b2); +is( GetBranchesCount, $count + 2, "two branches added" ); + +#Test DelBranch + +is( DelBranch( $b2->{branchcode} ), 1, "One row affected" ); +is( GetBranchesCount, $count + 1, "branch BRB deleted" ); + +#Test GetBranchName +is( GetBranchName( $b1->{branchcode} ), + $b1->{branchname}, "GetBranchName returns the right name" ); + +#Test GetBranchDetail +my $branchdetail = GetBranchDetail( $b1->{branchcode} ); +$branchdetail->{add} = 1; +$b1->{issuing} = undef; # Not used in DB +is_deeply( $branchdetail, $b1, 'branchdetail is right' ); + +#Test Getbranches +my $branches = GetBranches; +is( scalar( keys %$branches ), + GetBranchesCount, "GetBranches returns the right number of branches" ); + +#Test ModBranch + +$b1 = { + branchcode => 'BRA', + branchname => 'BranchA modified', + branchaddress1 => 'adr1A modified', + branchaddress2 => 'adr2A modified', + branchaddress3 => 'adr3A modified', + branchzip => 'zipA modified', + branchcity => 'cityA modified', + branchstate => 'stateA modified', + branchcountry => 'countryA modified', + branchphone => 'phoneA modified', + branchfax => 'faxA modified', + branchemail => 'emailA modified', + branchurl => 'urlA modified', + branchip => 'ipA modified', + branchprinter => undef, + branchnotes => 'notesA modified', + opac_info => 'opacA modified' +}; + +ModBranch($b1); +is( GetBranchesCount, $count + 1, + "A branch has been modified, no new branch added" ); +$branchdetail = GetBranchDetail( $b1->{branchcode} ); +$b1->{issuing} = undef; +is_deeply( $branchdetail, $b1 ); + +#Test categories +my $categories = GetBranchCategories; +my $count_cat = scalar( keys $categories ); + +my $cat1 = { + add => 1, + categorycode => 'CAT1', + categoryname => 'catname1', + codedescription => 'catdesc1', + categorytype => 'cattype1', + show_in_pulldown => 1 +}; +my $cat2 = { + add => 1, + categorycode => 'CAT2', + categoryname => 'catname2', + categorytype => 'catype2', + codedescription => 'catdesc2', + show_in_pulldown => 1 +}; my %new_category = ( categorycode => 'LIBCATCODE', @@ -49,21 +191,163 @@ my %new_category = ( categorytype => 'searchdomain', show_in_pulldown => 1, ); + ModBranchCategoryInfo({ add => 1, %new_category, }); +ModBranchCategoryInfo($cat1); +ModBranchCategoryInfo($cat2); + +$categories = GetBranchCategories; +is( scalar( keys $categories ), $count_cat + 3, "Two categories added" ); +delete $cat1->{add}; +delete $cat2->{add}; +delete %new_category->{add}; +is_deeply($categories, [ $cat1,$cat2,\%new_category ], 'retrieve all expected library categories (bug 10515)'); + +#test GetBranchCategory +my $cat1detail = GetBranchCategory( $cat1->{categorycode} ); +delete $cat1->{add}; +is_deeply( $cat1detail, $cat1, 'CAT1 details are right' ); my $category = GetBranchCategory('LIBCATCODE'); is_deeply($category, \%new_category, 'fetched newly added library category'); +#Test DelBranchCategory +my $del = DelBranchCategory( $cat2->{categorycode} ); +is( $del, 1, 'One row affected' ); + +$categories = GetBranchCategories; +is( scalar( keys $categories ), $count_cat + 2, "Category CAT2 deleted" ); + +my $cat2detail = GetBranchCategory( $cat2->{categorycode} ); +is( $cat2detail, undef, 'CAT2 doesnt exist' ); + $category = GetBranchCategory(); is($category, undef, 'retrieve library category only if code is supplied (bug 10515)'); -my $categories = GetBranchCategories(); -is_deeply($categories, [ \%new_category ], 'retrieve all expected library categories (bug 10515)'); +#Test CheckBranchCategoryCode +my $check1 = CheckBranchCategorycode( $cat1->{categorycode} ); +my $check2 = CheckBranchCategorycode( $cat2->{categorycode} ); +like( $check1, '/^\d+$/', "CheckBranchCategorycode returns a number" ); + +$b2->{CAT1} = 1; +ModBranch($b2); +is( GetBranchesCount, $count + 2, 'BRB added' ); +is( + CheckBranchCategorycode( $cat1->{categorycode} ), + $check1 + 1, + 'BRB added to CAT1' +); + +#Test GetBranchInfo +my $b1info = GetBranchInfo( $b1->{branchcode} ); +$b1->{categories} = []; +is_deeply( @$b1info[0], $b1, 'BRA has no categories' ); + +my $b2info = GetBranchInfo( $b2->{branchcode} ); +my @cat = ( $cat1->{categorycode} ); +delete $b2->{add}; +delete $b2->{CAT1}; +$b2->{issuing} = undef; +$b2->{categories} = \@cat; +is_deeply( @$b2info[0], $b2, 'BRB has the category CAT1' ); + +ModBranchCategoryInfo({add => 1,%$cat2}); +$categories = GetBranchCategories; +is( scalar( keys $categories ), $count_cat + 3, "Two categories added" ); +$b2 = { + branchcode => 'BRB', + branchname => 'BranchB', + branchaddress1 => 'adr1B', + branchaddress2 => 'adr2B', + branchaddress3 => 'adr3B', + branchzip => 'zipB', + branchcity => 'cityB', + branchstate => 'stateB', + branchcountry => 'countryB', + branchphone => 'phoneB', + branchfax => 'faxB', + branchemail => 'emailB', + branchurl => 'urlB', + branchip => 'ipB', + branchprinter => undef, + branchnotes => 'noteB', + opac_info => 'opacB', + CAT1 => 1, + CAT2 => 1 +}; +ModBranch($b2); +$b2info = GetBranchInfo( $b2->{branchcode} ); +is( + CheckBranchCategorycode( $cat2->{categorycode} ), + $check2 + 1, + 'BRB added to CAT2' +); +push( @cat, $cat2->{categorycode} ); +delete $b2->{CAT1}; +delete $b2->{CAT2}; +$b2->{issuing} = undef; +$b2->{categories} = \@cat; +is_deeply( @$b2info[0], $b2, 'BRB has the category CAT1 and CAT2' ); + +#Test GetBranchesInCategory +my $brCat1 = GetBranchesInCategory( $cat1->{categorycode} ); +my @b = ( $b2->{branchcode} ); +is_deeply( $brCat1, \@b, 'CAT1 has branch BRB' ); + +my $b3 = { + add => 1, + branchcode => 'BRC', + branchname => 'BranchC', + branchaddress1 => 'adr1C', + branchaddress2 => 'adr2C', + branchaddress3 => 'adr3C', + branchzip => 'zipC', + branchcity => 'cityC', + branchstate => 'stateC', + branchcountry => 'countryC', + branchphone => 'phoneC', + branchfax => 'faxC', + branchemail => 'emailC', + branchurl => 'urlC', + branchip => 'ipC', + branchprinter => undef, + branchnotes => 'noteC', + opac_info => 'opacC', + CAT1 => 1, + CAT2 => 1 +}; +ModBranch($b3); +$brCat1 = GetBranchesInCategory( $cat1->{categorycode} ); +push( @b, $b3->{branchcode} ); +is_deeply( $brCat1, \@b, 'CAT1 has branch BRB and BRC' ); +is( + CheckBranchCategorycode( $cat1->{categorycode} ), + $check1 + 2, + 'BRC has been added to CAT1' +); + +#Test CheckCategoryUnique +is( CheckCategoryUnique('CAT2'), 0, 'CAT2 exists' ); +is( CheckCategoryUnique('CAT_NO_EXISTS'), 1, 'CAT_NO_EXISTS doesnt exist' ); + +#Test GetCategoryTypes +my @category_types = GetCategoryTypes(); +is_deeply(\@category_types, [ 'searchdomain', 'properties' ], 'received expected library category types'); $categories = GetBranchCategories(undef, undef, 'LIBCATCODE'); -is_deeply($categories, [ { %new_category, selected => 1 } ], 'retrieve expected, eselected library category (bug 10515)'); +is_deeply($categories, [ {%$cat1}, {%$cat2},{ %new_category, selected => 1 } ], 'retrieve expected, eselected library category (bug 10515)'); + +#TODO later: test mybranchine and onlymine +# Actually we cannot mock C4::Context->userenv in unit tests + +#Test GetBranchesLoop +my $loop = GetBranchesLoop; +is( scalar(@$loop), GetBranchesCount, 'There is the right number of branches' ); + +# End transaction +$dbh->rollback; -$dbh->rollback(); +done_testing; -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Jul 19 06:06:07 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 19 Jul 2013 16:06:07 +1200 Subject: [Koha-patches] [PATCH] Bug 10511 - Odd behavior for messaging preferences with Talking Tech enabled Message-ID: <1374206767-19332-1-git-send-email-srdjan@catalyst.net.nz> From: Kyle M Hall An error in the onclick for phone notices causes the "Do not notify" checkbox to be checked when the phone checkbox is checked. Also, checking "Do not notify" does not uncheck the phone checkbox. Test plan: 1) Enable TalkingTechItivaPhoneNotification 2) Browse to the new patron screen ( memberentry.pl ) 3) In the patron messaging preferences check the Phone checkbox 4) Not the "do not notify" checkbox is then checked 5) Uncheck the "do not notify" checkbox, and check the Email checkbox as well 6) Now check the "do not notify" checkbox, note the Phone checkbox remains checked 7) Apply this patch 8) Repeat steps 3-6, noting the odd behavior is no longer present Signed-off-by: Srdjan --- .../intranet-tmpl/prog/en/includes/messaging-preference-form.inc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/messaging-preference-form.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/messaging-preference-form.inc index ed6b067..367969d 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/messaging-preference-form.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/messaging-preference-form.inc @@ -7,6 +7,7 @@ newid = Number(rowid.replace("none","")) $("#sms"+newid).removeAttr("checked"); $("#email"+newid).removeAttr("checked"); + $("#phone"+newid).removeAttr("checked"); $("#digest"+newid).removeAttr("checked"); $("#rss"+newid).removeAttr("checked"); } @@ -99,12 +100,12 @@ + value="phone" checked="checked" onclick = "$('#none'+'[% messaging_preference.message_attribute_id %]').removeAttr('checked','');" /> [% ELSE %] + value="phone" onclick = "$('#none'+'[% messaging_preference.message_attribute_id %]').removeAttr('checked','');" /> [% END %] [% END %] [% END %] -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Jul 19 07:06:23 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 19 Jul 2013 17:06:23 +1200 Subject: [Koha-patches] [PATCH] Bug 10452 - AllowHoldsOnDamagedItems should control using damaged items to fulfill holds Message-ID: <1374210383-24450-1-git-send-email-srdjan@catalyst.net.nz> From: Kyle M Hall AllowHoldsOnDamagedItems will stop item-specific holds from being placed on damaged items, but does not stop Koha from using damaged items to fill holds. This seems like incorrect behavior. Test Plan: 1) Set 'AllowHoldsOnDamagedItems' to "Don't Allow" 2) Pick an item, set it to damaged 3) Place a bib-level hold on this item's record 4) Scan the item though the returns system 5) Koha will ask to use this item to fill the hold, click "ignore" 6) Apply this patch 7) Repeat step 4 8) Koha will not ask to use this item to fill the hold Signed-off-by: Srdjan --- C4/Reserves.pm | 26 ++++++++++++++-------- .../en/modules/admin/preferences/circulation.pref | 2 +- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/C4/Reserves.pm b/C4/Reserves.pm index 5ff12e4..b5336f7 100644 --- a/C4/Reserves.pm +++ b/C4/Reserves.pm @@ -421,13 +421,17 @@ sub CanItemBeReserved{ my $dbh = C4::Context->dbh; my $allowedreserves = 0; - my $controlbranch = C4::Context->preference('ReservesControlBranch'); - my $itype = C4::Context->preference('item-level_itypes') ? "itype" : "itemtype"; - # we retrieve borrowers and items informations # - my $item = GetItem($itemnumber); + my $item = GetItem($itemnumber); + + # If an item is damaged and we don't allow holds on damaged items, we can stop right here + return 0 if ( $item->{damaged} && !C4::Context->preference('AllowHoldsOnDamagedItems') ); + my $borrower = C4::Members::GetMember('borrowernumber'=>$borrowernumber); + my $controlbranch = C4::Context->preference('ReservesControlBranch'); + my $itype = C4::Context->preference('item-level_itypes') ? "itype" : "itemtype"; + # we retrieve user rights on this itemtype and branchcode my $sth = $dbh->prepare("SELECT categorycode, itemtype, branchcode, reservesallowed FROM issuingrules @@ -809,7 +813,8 @@ sub CheckReserves { items.biblioitemnumber, itemtypes.notforloan, items.notforloan AS itemnotforloan, - items.itemnumber + items.itemnumber, + items.damaged FROM items LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber LEFT JOIN itemtypes ON items.itype = itemtypes.itemtype @@ -821,7 +826,8 @@ sub CheckReserves { items.biblioitemnumber, itemtypes.notforloan, items.notforloan AS itemnotforloan, - items.itemnumber + items.itemnumber, + items.damaged FROM items LEFT JOIN biblioitems ON items.biblioitemnumber = biblioitems.biblioitemnumber LEFT JOIN itemtypes ON biblioitems.itemtype = itemtypes.itemtype @@ -837,13 +843,15 @@ sub CheckReserves { $sth->execute($barcode); } # note: we get the itemnumber because we might have started w/ just the barcode. Now we know for sure we have it. - my ( $biblio, $bibitem, $notforloan_per_itemtype, $notforloan_per_item, $itemnumber ) = $sth->fetchrow_array; + my ( $biblio, $bibitem, $notforloan_per_itemtype, $notforloan_per_item, $itemnumber, $damaged ) = $sth->fetchrow_array; + + return if ( $damaged && !C4::Context->preference('AllowHoldsOnDamagedItems') ); - return ( '' ) unless $itemnumber; # bail if we got nothing. + return unless $itemnumber; # bail if we got nothing. # if item is not for loan it cannot be reserved either..... # execpt where items.notforloan < 0 : This indicates the item is holdable. - return ( '' ) if ( $notforloan_per_item > 0 ) or $notforloan_per_itemtype; + return if ( $notforloan_per_item > 0 ) or $notforloan_per_itemtype; # Find this item in the reserves my @reserves = _Findgroupreserve( $bibitem, $biblio, $itemnumber ); diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref index c286ed1..a228efe 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref @@ -344,7 +344,7 @@ Circulation: choices: yes: Allow no: "Don't allow" - - hold requests to be placed on damaged items. + - hold requests to be placed on and filled by damaged items. - - pref: AllowOnShelfHolds choices: -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Jul 19 09:55:20 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 19 Jul 2013 19:55:20 +1200 Subject: [Koha-patches] [PATCH] Bug 10337: Unit tests is based on an existing database Message-ID: <1374220520-8066-1-git-send-email-srdjan@catalyst.net.nz> From: Jonathan Druart This patchs adds a new unit tests file which will launched before all others db_dependent tests. It will drop and recreate the database with sample data. Prerequisite: The database 'koha_ut' have to be created with CREATE DATABASE $dbname CHARACTER SET utf8 COLLATE utf8_bin http://bugs.koha-community.org/show_bug.cgi?id=10481 --- t/db_dependent/000-init_db.t | 113 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 t/db_dependent/000-init_db.t diff --git a/t/db_dependent/000-init_db.t b/t/db_dependent/000-init_db.t new file mode 100644 index 0000000..16d60f6 --- /dev/null +++ b/t/db_dependent/000-init_db.t @@ -0,0 +1,113 @@ +use Modern::Perl; +use Test::More tests => 34; + +use C4::Context; +use t::lib::Mocks; + +t::lib::Mocks::mock_config('database', 'koha_ut'); + + +my $koha_structure_file = C4::Context->config('intranetdir') . '/installer/data/mysql/kohastructure.sql'; +my $sample_files_optional = C4::Context->config('intranetdir') . '/installer/data/mysql/en/optional/*.sql'; +my $sample_files_mandatory = C4::Context->config('intranetdir') . '/installer/data/mysql/en/mandatory/*.sql'; +my $marc21_sample_files_mandatory = C4::Context->config('intranetdir') . '/installer/data/mysql/en/marcflavour/marc21/*/*.sql'; +my $unimarc_sample_files_mandatory = C4::Context->config('intranetdir') . '/installer/data/mysql/en/marcflavour/unimarc/mandatory/*.sql'; +my $sample_only_param_tables = C4::Context->config('intranetdir') . '/installer/data/mysql/sample_only_param_tables.sql'; +my $sysprefs = C4::Context->config('intranetdir') . '/installer/data/mysql/sysprefs.sql'; + +my $version = get_version(); + +our $dbh = C4::Context->dbh; +our $user = C4::Context->config('user'); +our $pass = C4::Context->config('pass'); +our $dbname = C4::Context->config("database"); + +# TODO All unit tests launch after this one should use the same database name +# instead of the dbname defined in the $KOHA_CONF file +# We have to mock C4::Context->config('database') with koha_ut everywhere +die q{The SQL database name should be 'koha_ut'} + if $dbname ne 'koha_ut'; + +recreate_db( $dbname ); +# Force C4::Context to recreate a new db handler +$dbh->disconnect; +$dbh = C4::Context->dbh; +initialize_data(); +update_database(); + + +# We can't insert unimarc AND marc21 files +#for my $f ( glob $unimarc_sample_files_mandatory ) { +# execute_sqlfile( $f, "inserting $f"); +#} + + +# FIXME This file crashes +#execute_sqlfile( $sample_only_param_tables, "inserting $sample_only_param_tables" ); + +sub recreate_db { + my $dbname = shift; + ok( $dbh->do(qq{ + DROP DATABASE $dbname + }), "drop database $dbname" ); + + is( $dbh->do(qq{ + CREATE DATABASE $dbname CHARACTER SET utf8 COLLATE utf8_bin + }), 1, "create database $dbname" ); +} + +sub initialize_data { + execute_sqlfile( $koha_structure_file, "inserting koha db structure" ); + + for my $f ( glob $sample_files_mandatory ) { + execute_sqlfile( $f, "inserting $f"); + } + + + for my $f ( glob $sample_files_optional ) { + execute_sqlfile( $f, "inserting $f"); + } + + for my $f ( glob $marc21_sample_files_mandatory ) { + execute_sqlfile( $f, "inserting $f"); + } + execute_sqlfile( $sysprefs, "inserting $sysprefs"); + + # set marcflavour (MARC21) + $dbh->do( q{ + INSERT INTO `systempreferences` (variable,value,explanation,options,type) + VALUES ('marcflavour','MARC21','Define global MARC flavor (MARC21 or UNIMARC) used for character encoding','MARC21|UNIMARC','Choice') + } ); + + # set version + $dbh->do( qq{ + INSERT INTO systempreferences(variable, value, options, explanation, type) + VALUES ('Version', '$version', NULL, 'The Koha database version. WARNING: Do not change this value manually, it is maintained by the webinstaller', NULL) + } ); +} + +sub execute_sqlfile { + my ( $filepath, $msg ) = @_; + is( system( qq{/usr/bin/mysql -u $user -p'$pass' -D $dbname < $filepath} ), 0, $msg ); +} + +sub get_version { + do C4::Context->config('intranetdir') . '/kohaversion.pl'; + my $version = kohaversion(); + $version =~ s/(\d)\.(\d{2})\.(\d{2})\.(\d{3})/$1.$2$3$4/; + return $version; +} + +sub update_database { + my $src_path = C4::Context->config('intranetdir'); + my $update_db_path = $src_path . '/installer/data/mysql/updatedatabase.pl'; + + my $file = `cat $update_db_path`; + $file =~ s/exit;//; + eval $file; + if ($@) { + fail("updatedatabase.pl process failed: $@"); + } else { + pass("updatedatabase.pl process succeeded."); + } +} -- 1.8.1.2 From oleonard at myacpl.org Fri Jul 19 15:11:19 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Fri, 19 Jul 2013 09:11:19 -0400 Subject: [Koha-patches] [PATCH] Bug 8821 - Receive shipment page should hide inactive funds like new order form Message-ID: <1374239479-20206-1-git-send-email-oleonard@myacpl.org> This patch adapts the fund-handling code from neworderempty.pl in order to limit the display of funds by default to active ones, with the option to check a box to display all funds. This patch also adds "(inactive)" to the display of funds on this and the neworderempty.tt template because it seemed like that was useful information. To test, make sure you have both active and inactive funds. Start the process of receiving a shipment. The "fund" option in the receive shipment form should show only active funds. Checking the "show all" checkbox should allow you to choose from both active and inactive funds. --- acqui/parcels.pl | 24 +++++++++++++++----- .../prog/en/modules/acqui/neworderempty.tt | 2 +- .../intranet-tmpl/prog/en/modules/acqui/parcels.tt | 23 ++++++++++++++++++- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/acqui/parcels.pl b/acqui/parcels.pl index 37a0023..c95d77b 100755 --- a/acqui/parcels.pl +++ b/acqui/parcels.pl @@ -179,13 +179,25 @@ if ($count_parcels) { $template->param( searchresults => $loopres, count => $count_parcels ); } -my $budgets = GetBudgets(); -my @budgets_loop; -foreach my $budget (@$budgets) { - next unless CanUserUseBudget($loggedinuser, $budget, $flags); - push @budgets_loop, $budget; +# build budget list +my $budget_loop = []; +my $budgets = GetBudgetHierarchy; +foreach my $r (@{$budgets}) { + next unless (CanUserUseBudget($loggedinuser, $r, $flags)); + if (!defined $r->{budget_amount} || $r->{budget_amount} == 0) { + next; + } + push @{$budget_loop}, { + b_id => $r->{budget_id}, + b_txt => $r->{budget_name}, + b_active => $r->{budget_period_active}, + }; } +@{$budget_loop} = + sort { uc( $a->{b_txt}) cmp uc( $b->{b_txt}) } @{$budget_loop}; + + $template->param( orderby => $order, filter => $code, @@ -196,7 +208,7 @@ $template->param( shipmentdate_today => C4::Dates->new()->output(), booksellerid => $booksellerid, GST => C4::Context->preference('gist'), - budgets => \@budgets_loop, + budgets => $budget_loop, ); output_html_with_http_headers $input, $cookie, $template->output; diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt index bbcd4e8..10b0399 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/neworderempty.tt @@ -426,7 +426,7 @@ $(document).ready(function() [% ELSE %] [% IF ( budget_loo.b_active ) %] - [% ELSE %] + [% ELSE %] [% END %] [% END %] [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/parcels.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/parcels.tt index 26e4af8..5e003f1 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/parcels.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/parcels.tt @@ -16,6 +16,20 @@ var parcelst = $("#parcelst").dataTable($.extend(true, {}, dataTablesDefaults, { "sPaginationType": "four_button" } ) ); + + //keep a copy of all budgets before removing the inactives + var budgetId = $("#shipmentcost_budgetid"); + var disabledBudgetsCopy = budgetId.html(); + $('.b_inactive').remove(); + + $('#showallfunds').click(function() { + if ($(this).is(":checked")) { + budgetId.html(disabledBudgetsCopy); //Puts back all the funds + } + else { + $('.b_inactive').remove(); + } + }); }); //]]> @@ -172,9 +186,16 @@ + + + -- 1.7.9.5 From oleonard at myacpl.org Fri Jul 19 16:04:36 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Fri, 19 Jul 2013 10:04:36 -0400 Subject: [Koha-patches] [PATCH] Bug 2969 - Report Name should be mandatory for saved reports Message-ID: <1374242676-21847-1-git-send-email-oleonard@myacpl.org> This patch re-implements the database changes from the original patch and adds an update for existing reports. It also reimplements the client-side validation using the new built-in validation plugin and adds coverage for SQL reports. I have also added the "required" attribute to the SQL report textarea since saving a report with no SQL triggers an error. To test: - Create a new guided report. Confirm that you cannot save your guided report without a report name. - Create or edit a saved SQL report. Confirm that you cannot save your report without a name or without SQL. - Confirm that the saved_sql table structure has been updated. --- installer/data/mysql/kohastructure.sql | 2 +- installer/data/mysql/updatedatabase.pl | 7 +++++++ .../en/modules/reports/guided_reports_start.tt | 14 +++++++------- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/installer/data/mysql/kohastructure.sql b/installer/data/mysql/kohastructure.sql index 8f9b30c..4ad79f2 100644 --- a/installer/data/mysql/kohastructure.sql +++ b/installer/data/mysql/kohastructure.sql @@ -1841,7 +1841,7 @@ CREATE TABLE saved_sql ( -- saved sql reports `last_modified` datetime default NULL, -- the date this report was last edited `savedsql` text, -- the SQL for this report `last_run` datetime default NULL, - `report_name` varchar(255) default NULL, -- the name of this report + `report_name` varchar(255) NOT NULL default '', -- the name of this report `type` varchar(255) default NULL, -- always 1 for tabular `notes` text, -- the notes or description given to this report `cache_expiry` int NOT NULL default 300, diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index fd8421e..6ead258 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -7050,6 +7050,13 @@ if ( CheckVersion($DBversion) ) { SetVersion($DBversion); } +$DBversion = "3.13.00.XXX"; +if ( CheckVersion($DBversion) ) { + $dbh->do("ALTER TABLE saved_sql CHANGE report_name report_name VARCHAR( 255 ) NOT NULL DEFAULT '' "); + print "Upgrade to $DBversion done, requiring that saved report name not be NULL. (Bug 2969: Report Name should be mandatory for saved reports)\n"; + SetVersion ($DBversion); +} + =head1 FUNCTIONS =head2 TableExists($table) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt index 8c34135..6bf0845 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/reports/guided_reports_start.tt @@ -636,7 +636,7 @@ canned reports and writing custom SQL reports.

[% END %] [% IF ( save ) %] -
+ @@ -645,7 +645,7 @@ canned reports and writing custom SQL reports.

Save your custom report
    -
  1. +
  2. Required
  3. [% PROCESS group_and_subgroup_selection %]
@@ -803,13 +803,13 @@ $(document).ready(function() { load_group_subgroups(); }); - +
Create report from SQL
    -
  1. - [% IF ( reportname ) %] - [% ELSE %][% END %] +
  2. + [% IF ( reportname ) %] + [% ELSE %][% END %] Required
  3. [% PROCESS group_and_subgroup_selection %] @@ -840,7 +840,7 @@ $(document).ready(function() {
    SQL:
    - + Required
    -- 1.7.9.5 From oleonard at myacpl.org Fri Jul 19 16:13:21 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Fri, 19 Jul 2013 10:13:21 -0400 Subject: [Koha-patches] [PATCH] Bug 10576 - Untranslatable strings in additem.js Message-ID: <1374243201-22244-1-git-send-email-oleonard@myacpl.org> There are a couple of untranslatable strings in additem.js. This patch moves the strings out of the script and into the include file which has been created for this purpose. To test, apply the patch and test the process for adding an item to an existing or new basket (with AcqCreateItem set to "when placing an order." The add item form should be correctly labeled "Add item." After adding an item, click to edit it again. The form should now be labeled "Update item." --- .../intranet-tmpl/prog/en/includes/additem.js.inc | 2 ++ koha-tmpl/intranet-tmpl/prog/en/js/additem.js | 5 ++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/additem.js.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/additem.js.inc index 5ab37f4..28d39e4 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/additem.js.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/additem.js.inc @@ -1,5 +1,7 @@ +[% INCLUDE 'doc-head-close.inc' %] + [% IF ( print_basket ) %] - - [% ELSE %][% INCLUDE 'doc-head-close.inc' %] + [% ELSE %] +[% INCLUDE 'datatables-strings.inc' %] @@ -175,7 +177,7 @@ $(document).ready(function() { [% IF ( subscription.numberpattern7 ) %] None of the above [% END %] - [% subscription.branchcode %] + [% Branches.GetName( subscription.branchcode ) %] [% subscription.callnumber %] [% subscription.notes %] [% UNLESS subscription.closed %] @@ -311,7 +313,7 @@ $(document).ready(function() { [% serial.notes %] - [% serial.branchcode %] + [% Branches.GetName( serial.branchcode ) %] [% IF ( routing ) %] -- 1.7.9.5 From oleonard at myacpl.org Fri Jul 19 21:49:28 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Fri, 19 Jul 2013 15:49:28 -0400 Subject: [Koha-patches] [PATCH] Bug 3134 - Ability to selelct multiple reports to delete at once Message-ID: <1374263369-26674-1-git-send-email-oleonard@myacpl.org> This patch adds the option to select multiple saved reports for deletion. To test you must have two or more saved reports to delete. Deletion should work properly when: - Selecting one report for deletion by checking the box. - Selecting more than one report for deletion by checking boxes. - Clicking the old "Delete" link Clicking the delete button should prompt you to confirm. Clicking cancel should cancel. Clicking the delete button when no boxes are checked should trigger an alert asking you to select reports for deletion. --- C4/Reports/Guided.pm | 14 ++++++------- .../en/modules/reports/guided_reports_start.tt | 21 +++++++++++++++++--- reports/guided_reports.pl | 11 ++++++++-- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/C4/Reports/Guided.pm b/C4/Reports/Guided.pm index f0db7a3..9447c71 100644 --- a/C4/Reports/Guided.pm +++ b/C4/Reports/Guided.pm @@ -609,13 +609,13 @@ sub format_results { } sub delete_report { - my ($id) = @_; - my $dbh = C4::Context->dbh(); - my $query = "DELETE FROM saved_sql WHERE id = ?"; - my $sth = $dbh->prepare($query); - $sth->execute($id); -} - + my (@ids) = @_; + my $dbh = C4::Context->dbh; + my $query = 'DELETE FROM saved_sql WHERE id IN (' . join( ',', ('?') x @ids ) . ')'; + my $sth = $dbh->prepare($query); + $sth->execute(@ids); + $sth->finish; +} my $SAVED_REPORTS_BASE_QRY = <
+ + @@ -297,7 +308,7 @@ canned reports and writing custom SQL reports.

[% FOREACH savedreport IN savedreports %] [% UNLESS ( loop.odd ) %][% ELSE %][% END %] - + @@ -317,7 +328,7 @@ canned reports and writing custom SQL reports.

Show [% IF ( CAN_user_reports_create_reports ) %] Edit - Duplicate + Duplicate [% END %]
[% savedreport.id %] [% savedreport.report_name %] [% savedreport.type %] [% savedreport.groupname %] @@ -331,6 +342,10 @@ canned reports and writing custom SQL reports.

[% END %]
+
+ +
+
[% ELSE %]
diff --git a/reports/guided_reports.pl b/reports/guided_reports.pl index 929feea..b9c49ad 100755 --- a/reports/guided_reports.pl +++ b/reports/guided_reports.pl @@ -108,11 +108,18 @@ elsif ( $phase eq 'Build new' ) { ); } +elsif ( $phase eq 'Delete Multiple') { + my @ids = $input->param('ids'); + delete_report( @ids ); + print $input->redirect("/cgi-bin/koha/reports/guided_reports.pl?phase=Use%20saved"); + exit; +} + elsif ( $phase eq 'Delete Saved') { # delete a report from the saved reports list - my $id = $input->param('reports'); - delete_report($id); + my $ids = $input->param('reports'); + delete_report($ids); print $input->redirect("/cgi-bin/koha/reports/guided_reports.pl?phase=Use%20saved"); exit; } -- 1.7.9.5 From oleonard at myacpl.org Fri Jul 19 22:14:18 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Fri, 19 Jul 2013 16:14:18 -0400 Subject: [Koha-patches] [PATCH] Bug 10516 - Improve titles, breadcrumbs, and confirmation messages for Z39.50 server adds and updates Message-ID: <1374264858-27406-1-git-send-email-oleonard@myacpl.org> The template for adding/editing Z39.50 servers shows the same title, breadcrumbs, etc. for add and edit operations. This patch creates separate text for each case. To test, try both adding and editing a Z39.50 server. The page title, breadcrumb, and heading should correctly reflect the operation you perform. --- admin/z3950servers.pl | 3 ++- .../prog/en/modules/admin/z3950servers.tt | 16 +++++++++++++--- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/admin/z3950servers.pl b/admin/z3950servers.pl index 92cc3e5..87711c1 100755 --- a/admin/z3950servers.pl +++ b/admin/z3950servers.pl @@ -104,12 +104,12 @@ if ($op eq 'add_form') { ################## ADD_VALIDATE ################################## # called by add_form, used to insert/modify data in DB } elsif ($op eq 'add_validate') { - $template->param(add_validate => 1); my $dbh=C4::Context->dbh; my $sth=$dbh->prepare("select * from z3950servers where name=?"); $sth->execute($input->param('searchfield')); my $checked = $input->param('checked') ? 1 : 0; if ($sth->rows) { + $template->param(confirm_update => 1); $sth=$dbh->prepare("update z3950servers set host=?, port=?, db=?, userid=?, password=?, name=?, checked=?, rank=?,syntax=?,encoding=?,timeout=? where name=?"); $sth->execute($input->param('host'), $input->param('port'), @@ -126,6 +126,7 @@ if ($op eq 'add_form') { ); } else { + $template->param(confirm_add => 1); $sth=$dbh->prepare( "INSERT INTO z3950servers " . "(host,port,db,userid,password,name,checked,rank,syntax,encoding,timeout) " . diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/z3950servers.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/z3950servers.tt index 18f92fc..fa61123 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/z3950servers.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/z3950servers.tt @@ -2,7 +2,8 @@ Koha › Administration › [% IF ( else ) %]Z39.50 servers[% END %] [% IF ( add_form ) %] Z39.50 servers › [% IF ( searchfield ) %]Modify Z39.50 server [% searchfield %][% ELSE %]New Z39.50 server[% END %][% END %] [% IF ( delete_confirm ) %]Z39.50 servers › Confirm deletion[% END %] -[% IF ( add_validate ) %]Z39.50 servers › Z39.50 server added[% END %] +[% IF ( confirm_add ) %] Z39.50 servers › Z39.50 server added[% END %] +[% IF ( confirm_update ) %] Z39.50 servers › Z39.50 server updated[% END %] [% IF ( delete_confirmed ) %]Z39.50 servers › Z39.50 server deleted[% END %] [% INCLUDE 'doc-head-close.inc' %] [% IF ( else ) %] @@ -94,7 +95,9 @@
@@ -244,13 +247,20 @@ [% END %] -[% IF ( add_validate ) %] +[% IF ( confirm_add ) %]

Z39.50 server added

[% END %] +[% IF ( confirm_update ) %] +

Z39.50 server updated

+
+ +
+[% END %] + [% IF ( delete_confirm ) %] [% reqsel %]

Confirm deletion of server [% searchfield %]

-- 1.7.9.5 From srdjan at catalyst.net.nz Wed Jul 24 05:12:37 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Wed, 24 Jul 2013 15:12:37 +1200 Subject: [Koha-patches] [PATCH] [SIGNED-OFF] C4::Branch.pm needs unit tests Message-ID: <1374635557-12489-1-git-send-email-srdjan@catalyst.net.nz> From: Kenza Zaki Unit tests are wrap in a transaction. To test: prove t/db_dependent/Branch.t t/db_dependent/Branch.t .. 1/36 Using a hash as a reference is deprecated at t/db_dependent/Branch.t line 207. t/db_dependent/Branch.t .. ok All tests successful. Files=1, Tests=36, 1 wallclock secs ( 0.02 usr 0.02 sys + 0.13 cusr 0.01 csys = 0.18 CPU) Result: PASS http://bugs.koha-community.org/show_bug.cgi?id=10508 Signed-off-by: Srdjan --- t/db_dependent/Branch.t | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/t/db_dependent/Branch.t b/t/db_dependent/Branch.t index 4251816..ffa2346 100644 --- a/t/db_dependent/Branch.t +++ b/t/db_dependent/Branch.t @@ -21,7 +21,7 @@ use Modern::Perl; use C4::Context; use Data::Dumper; -use Test::More ;#tests => 6; +use Test::More tests => 36; use C4::Branch; @@ -161,7 +161,7 @@ is( GetBranchesCount, $count + 1, "A branch has been modified, no new branch added" ); $branchdetail = GetBranchDetail( $b1->{branchcode} ); $b1->{issuing} = undef; -is_deeply( $branchdetail, $b1 ); +is_deeply( $branchdetail, $b1 , "GetBranchDetail gives the details of BRA"); #Test categories my $categories = GetBranchCategories; @@ -350,4 +350,3 @@ is( scalar(@$loop), GetBranchesCount, 'There is the right number of branches' ); # End transaction $dbh->rollback; -done_testing; -- 1.8.1.2 From srdjan at catalyst.net.nz Wed Jul 24 06:35:36 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Wed, 24 Jul 2013 16:35:36 +1200 Subject: [Koha-patches] [PATCH] Bug 7785 - MySQL-specific syntax in C4::Members columns() Message-ID: <1374640536-22202-1-git-send-email-srdjan@catalyst.net.nz> From: Mark Tompsett The initial thought was to remove this function. However, tools/import_borrowers.pl uses it. So rather than remove it to solve the problem, it was reworked to a more generic solution which runs faster. By accessing $sth->{NAME} directly, the driver becomes responsible for filling it correctly. This happens when a SELECT is done on the borrowers table. It does not even have to have data in the result set! The columns method could be more generic and used elsewhere too. Comparison between the old method and the STH method showed a significant time difference. The old method took 35 seconds for 40k iterations versus 19 seconds for the same amount of iterations with the STH method regardless of the size of the borrowers table. Signed-off-by: Srdjan --- C4/Members.pm | 48 ++++++++++++++++++++++++++++++++++++++-- t/db_dependent/Members_columns.t | 24 ++++++++++++++++++++ 2 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 t/db_dependent/Members_columns.t diff --git a/C4/Members.pm b/C4/Members.pm index 6d8d23a..f3dbebd 100644 --- a/C4/Members.pm +++ b/C4/Members.pm @@ -695,10 +695,54 @@ sub GetMemberIssuesAndFines { return ($overdue_count, $issue_count, $total_fines); } -sub columns(;$) { - return @{C4::Context->dbh->selectcol_arrayref("SHOW columns from borrowers")}; + +=head2 columns + + C4::Member->columns + +=head3 USAGE + + use C4::Member; + my @borrower_columns = C4::Member->columns; + +=head3 RETURNS + + The array of borrowers' table columns on success. + An empty array on failure. + +=head3 NOTES + + This runs significantly faster than the previous code while + being mostly SQL-agnostic. + +=cut + +sub columns { + + # Pure ANSI SQL goodness. + my $sql = 'SELECT * FROM borrowers WHERE 1=0;'; + + # Get the database handle. + my $dbh = C4::Context->dbh; + + # Run the SQL statement to load STH's readonly properties. + my $sth = $dbh->prepare($sql); + my $rv = $sth->execute(); + + # This only fails if the table doesn't exist. + # This will always be called AFTER an install or upgrade, + # so borrowers will exist! + my @data; + if ($sth->{NUM_OF_FIELDS}>0) { + @data = @{$sth->{NAME}}; + } + else { + @data = (); + } + return @data; } + =head2 ModMember my $success = ModMember(borrowernumber => $borrowernumber, diff --git a/t/db_dependent/Members_columns.t b/t/db_dependent/Members_columns.t new file mode 100644 index 0000000..7a70ce4 --- /dev/null +++ b/t/db_dependent/Members_columns.t @@ -0,0 +1,24 @@ +#!/usr/bin/perl +# +# This is to test C4/Members +# It requires a working Koha database with the sample data + +use Modern::Perl; + +use Test::More tests => 2; + +BEGIN { + use_ok('C4::Members'); +} + +my @borrowers_columns = C4::Members->columns; +ok( + $#borrowers_columns > 1, + 'C4::Member->column returned a reasonable number of columns (' + . ( $#borrowers_columns + 1 ) . ')' + ) + or diag( +'WARNING: Check that the borrowers table exists and has the correct fields defined.' + ); + +exit; -- 1.8.1.2 From srdjan at catalyst.net.nz Wed Jul 24 06:46:42 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Wed, 24 Jul 2013 16:46:42 +1200 Subject: [Koha-patches] [PATCH] Bug 10446 - System preference maxoutstanding is poorly named Message-ID: <1374641202-23961-1-git-send-email-srdjan@catalyst.net.nz> From: Kyle M Hall The system preference 'maxoutstanding' is defined as the maximum amount of fees owed by the patron before Koha should block placing holds, but the name does not describe its behavior very well. String changes only, no functional changes made. Test Plan: 1) Apply patch 2) Run updatedatabase.pl 3) Verify the new system preference FeesBlockHoldsAmount's value matches the previous value of maxoutstanding. 4) Set FeesBlockHoldsAmount to $10 5) Attempt to place an OPAC hold for a patron owing less than $10 This attempt should succeed. 6) Attempt to place an OPAC hold for a patron owing more than $10 This attempt should fail Signed-off-by: Srdjan --- C4/SIP/ILS/Patron.pm | 2 +- installer/data/mysql/sysprefs.sql | 2 +- installer/data/mysql/updatedatabase.pl | 7 +++++++ .../prog/en/modules/admin/preferences/circulation.pref | 2 +- opac/opac-reserve.pl | 6 +++--- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/C4/SIP/ILS/Patron.pm b/C4/SIP/ILS/Patron.pm index da4290b..21f06ce 100644 --- a/C4/SIP/ILS/Patron.pm +++ b/C4/SIP/ILS/Patron.pm @@ -329,7 +329,7 @@ sub excessive_fines { sub holds_blocked_by_excessive_fees { return ( $self->fee_amount - && $self->fee_amount > C4::Context->preference("maxoutstanding") ); + && $self->fee_amount > C4::Context->preference("FeesBlockHoldsAmount") ); } sub library_name { diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index e3c0f3d..97b1269 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -56,7 +56,7 @@ INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES -- INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('marcflavour','MARC21','Define global MARC flavor (MARC21 or UNIMARC) used for character encoding','MARC21|UNIMARC','Choice'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('MARCOrgCode','OSt','Define MARC Organization Code - http://www.loc.gov/marc/organizations/orgshome.html','','free'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('MaxFine',NULL,'Maximum fine a patron can have for all late returns at one moment. Single item caps are specified in the circulation rules matrix.','','Integer'); -INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('maxoutstanding',5,'maximum amount withstanding to be able make holds','','Integer'); +INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('FeesBlockHoldsAmount',5,'maximum amount withstanding to be able make holds','','Integer'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('maxreserves',50,'Define maximum number of holds a patron can place','','Integer'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('maxItemsInSearchResults',20,'Specify the maximum number of items to display for each result on a page of results',NULL,'free'); INSERT INTO `systempreferences` (variable,value,explanation,options,type) VALUES('memberofinstitution',0,'If ON, patrons can be linked to institutions',NULL,'YesNo'); diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index ebb195c..6da97ed 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -7058,6 +7058,13 @@ if ( CheckVersion($DBversion) ) { SetVersion($DBversion); } +$DBversion = "3.13.00.XXX"; +if ( CheckVersion($DBversion) ) { + $dbh->do("UPDATE systempreferences SET variable = 'FeesBlockHoldsAmount' WHERE variable = 'maxoutstanding'"); + print "Upgrade to $DBversion done (Bug 10446 - System preference maxoutstanding is poorly named)\n"; + SetVersion($DBversion); +} + =head1 FUNCTIONS =head2 TableExists($table) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref index c286ed1..53cf04f 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/circulation.pref @@ -241,7 +241,7 @@ Circulation: - a renewal notice according to patron checkout alert preferences. - - Prevent patrons from making holds on the OPAC if they owe more than - - pref: maxoutstanding + - pref: FeesBlockHoldsAmount class: currency - '[% local_currency %] in fines.' - diff --git a/opac/opac-reserve.pl b/opac/opac-reserve.pl index be72e84..26814db 100755 --- a/opac/opac-reserve.pl +++ b/opac/opac-reserve.pl @@ -285,9 +285,9 @@ if ( $query->param('place_reserve') ) { # # my $noreserves = 0; -my $maxoutstanding = C4::Context->preference("maxoutstanding"); -$template->param( noreserve => 1 ) unless $maxoutstanding; -if ( $borr->{'amountoutstanding'} && ($borr->{'amountoutstanding'} > $maxoutstanding) ) { +my $FeesBlockHoldsAmount = C4::Context->preference("FeesBlockHoldsAmount"); +$template->param( noreserve => 1 ) unless $FeesBlockHoldsAmount; +if ( $borr->{'amountoutstanding'} && ($borr->{'amountoutstanding'} > $FeesBlockHoldsAmount) ) { my $amount = sprintf "\$%.02f", $borr->{'amountoutstanding'}; $template->param( message => 1 ); $noreserves = 1; -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Jul 26 00:50:50 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 26 Jul 2013 10:50:50 +1200 Subject: [Koha-patches] [PATCH] C4::Bookseller.pm need unit tests Message-ID: <1374792650-3270-1-git-send-email-srdjan@catalyst.net.nz> From: Kenza Zaki The tests are wrap in a transaction. NOTE: some tests should pass but doesn't because of incoherences in the code. These tests are in comments and preceded by FIXME Test plan: prove t/db_dependent/Bookseller.t t/db_dependent/Bookseller.t .. 15/53 [Some warnings about uninitialised values] t/db_dependent/Bookseller.t .. ok All tests successful. Files=1, Tests=53, 1 wallclock secs ( 0.02 usr 0.00 sys + 0.46 cusr 0.03 csys = 0.51 CPU) Result: PASS http://bugs.koha-community.org/show_bug.cgi?id=10528 Signed-off-by: Srdjan --- t/db_dependent/Bookseller.t | 694 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 694 insertions(+) create mode 100644 t/db_dependent/Bookseller.t diff --git a/t/db_dependent/Bookseller.t b/t/db_dependent/Bookseller.t new file mode 100644 index 0000000..71307f1 --- /dev/null +++ b/t/db_dependent/Bookseller.t @@ -0,0 +1,694 @@ +#!/usr/bin/perl + +use Modern::Perl; + +use Test::More tests => 53; +use C4::Context; +use Koha::DateUtils; +use DateTime::Duration; +use C4::Acquisition; +use C4::Serials; +use C4::Budgets; +use C4::Biblio; + +BEGIN { + use_ok('C4::Bookseller'); +} + +can_ok( + + 'C4::Bookseller', qw( + AddBookseller + DelBookseller + GetBookSeller + GetBookSellerFromId + GetBooksellersWithLateOrders + ModBookseller ) +); + +#Start transaction +my $dbh = C4::Context->dbh; +$dbh->{RaiseError} = 1; +$dbh->{AutoCommit} = 0; + +#Start tests +$dbh->do(q|DELETE FROM aqorders|); +$dbh->do(q|DELETE FROM aqbasket|); +$dbh->do(q|DELETE FROM aqbooksellers|); +#Test AddBookseller +my $count = scalar( C4::Bookseller::GetBookSeller('') ); +my $sample_supplier1 = { + name => 'Name1', + address1 => 'address1_1', + address2 => 'address1-2', + address3 => 'address1_2', + address4 => 'address1_2', + postal => 'postal1', + phone => 'phone1', + accountnumber => 'accountnumber1', + fax => 'fax1', + url => 'url1', + contact => 'contact1', + contpos => 'contpos1', + contphone => 'contphone1', + contfax => 'contefax1', + contaltphone => 'contaltphone1', + contemail => 'contemail1', + contnotes => 'contnotes1', + active => 1, + gstreg => 1, + listincgst => 1, + invoiceincgst => 1, + gstrate => '1.0000', + discount => '1.0000', + notes => 'notes1', + deliverytime => undef +}; +my $sample_supplier2 = { + name => 'Name2', + address1 => 'address1_2', + address2 => 'address2-2', + address3 => 'address3_2', + address4 => 'address4_2', + postal => 'postal2', + phone => 'phone2', + accountnumber => 'accountnumber2', + fax => 'fax2', + url => 'url2', + contact => 'contact2', + contpos => 'contpos2', + contphone => 'contphone2', + contfax => 'contefax2', + contaltphone => 'contaltphone2', + contemail => 'contemail2', + contnotes => 'contnotes2', + active => 1, + gstreg => 1, + listincgst => 1, + invoiceincgst => 1, + gstrate => '2.0000', + discount => '2.0000', + notes => 'notes2', + deliverytime => 2, +}; + +my $id_supplier1 = C4::Bookseller::AddBookseller($sample_supplier1); +my $id_supplier2 = C4::Bookseller::AddBookseller($sample_supplier2); + +#my $id_bookseller3 = C4::Bookseller::AddBookseller();# NOTE : Doesn't work because the field name cannot be null + +like( $id_supplier1, '/^\d+$/', "AddBookseller for supplier1 return an id" ); +like( $id_supplier2, '/^\d+$/', "AddBookseller for supplier2 return an id" ); +is( scalar( C4::Bookseller::GetBookSeller('') ), + $count + 2, "Supplier1 and Supplier2 have been added" ); + +#Test DelBookseller +my $del = C4::Bookseller::DelBookseller($id_supplier1); +#FIXME: DelBookSeller always returns undef (if it works or not) +#is( $del, 1, "DelBookseller returns 1 - 1 supplier has been deleted " ); +is( C4::Bookseller::GetBookSellerFromId($id_supplier1), + undef, "Supplier1 has been deleted - id_supplier1 doesnt exist anymore" ); + +#Test GetBookSeller +my @bookseller2 = C4::Bookseller::GetBookSeller( $sample_supplier2->{name} ); +is( scalar(@bookseller2), 1, "Get only Supplier2" ); +$bookseller2[0] = field_filter( $bookseller2[0] ); +delete $bookseller2[0]->{basketcount}; + +$sample_supplier2->{id} = $id_supplier2; +is_deeply( $bookseller2[0], $sample_supplier2, + "GetBookSeller returns the right informations about $sample_supplier2" ); + +$id_supplier1 = C4::Bookseller::AddBookseller($sample_supplier1); +my @booksellers = C4::Bookseller::GetBookSeller('') + ; #NOTE :without params, it returns all the booksellers +for my $i ( 0 .. scalar(@booksellers) - 1 ) { + $booksellers[$i] = field_filter( $booksellers[$i] ); + delete $booksellers[$i]->{basketcount}; +} + +$sample_supplier1->{id} = $id_supplier1; +is( scalar(@booksellers), $count + 2, "Get Supplier1 and Supplier2" ); +my @tab = ( $sample_supplier1, $sample_supplier2 ); +is_deeply( \@booksellers, \@tab, + "Returns right fields of Supplier1 and Supplier2" ); + +#Test basketcount +my @bookseller1 = C4::Bookseller::GetBookSeller( $sample_supplier1->{name} ); +#FIXME : if there is 0 basket, GetBookSeller returns 1 as basketcount +#is( $bookseller1[0]->{basketcount}, 0, 'Supplier1 has 0 basket' ); +my $sample_basket1 = + C4::Acquisition::NewBasket( $id_supplier1, 'authorisedby1', 'basketname1' ); +my $sample_basket2 = + C4::Acquisition::NewBasket( $id_supplier1, 'authorisedby2', 'basketname2' ); + at bookseller1 = C4::Bookseller::GetBookSeller( $sample_supplier1->{name} ); +is( $bookseller1[0]->{basketcount}, 2, 'Supplier1 has 2 baskets' ); + +#Test GetBookSellerFromId +my $bookseller1fromid = C4::Bookseller::GetBookSellerFromId(); +is( $bookseller1fromid, undef, + "GetBookSellerFromId returns undef if no id given" ); +$bookseller1fromid = C4::Bookseller::GetBookSellerFromId($id_supplier1); +$bookseller1fromid = field_filter($bookseller1fromid); +delete $bookseller1fromid->{basketcount}; +delete $bookseller1fromid->{subscriptioncount}; +is_deeply( $bookseller1fromid, $sample_supplier1, + "Get Supplier1 (GetBookSellerFromId)" ); + +#Test basketcount +$bookseller1fromid = C4::Bookseller::GetBookSellerFromId($id_supplier1); +is( $bookseller1fromid->{basketcount}, 2, 'Supplier1 has 2 baskets' ); + +#Test subscriptioncount +my $dt_today = dt_from_string; +my $today = output_pref( $dt_today, 'iso', '24hr', 1 ); + +my $dt_today1 = dt_from_string; +my $dur5 = DateTime::Duration->new( days => -5 ); +$dt_today1->add_duration($dur5); +my $daysago5 = output_pref( $dt_today1, 'iso', '24hr', 1 ); + +my $budgetperiod = C4::Budgets::AddBudgetPeriod({ + budget_period_startdate => $daysago5, + budget_period_enddate => $today, + budget_description => "budget desc" +}); +my $id_budget = AddBudget({ + budget_code => "CODE", + budget_amount => "123.132", + budget_name => "Budgetname", + budget_notes => "This is a note", + budget_description => "BudgetDescription", + budget_active => 1, + budget_period_id => $budgetperiod +}); +my ($biblionumber, $biblioitemnumber) = AddBiblio(MARC::Record->new, ''); +$bookseller1fromid = C4::Bookseller::GetBookSellerFromId($id_supplier1); +is( $bookseller1fromid->{subscriptioncount}, + 0, 'Supplier1 has 0 subscription' ); +my $id_subscription1 = C4::Serials::NewSubscription( + undef, "", $id_supplier1, undef, + $id_budget, $biblionumber, '01-01-2013', undef, + undef, undef, undef, undef, + undef, undef, undef, undef, + undef, undef, undef, undef, + undef, undef, undef, undef, + undef, undef, undef, undef, + undef, undef, undef, 1, + "notes", undef, undef, undef, + undef, undef, undef, 0, + "intnotes", 0, undef, undef, + 0, undef, '31-12-2013', +); +my $id_subscription2 = C4::Serials::NewSubscription( + undef, "", $id_supplier1, undef, + $id_budget, $biblionumber, '01-01-2013', undef, + undef, undef, undef, undef, + undef, undef, undef, undef, + undef, undef, undef, undef, + undef, undef, undef, undef, + undef, undef, undef, undef, + undef, undef, undef, 1, + "notes", undef, undef, undef, + undef, undef, undef, 0, + "intnotes", 0, undef, undef, + 0, undef, '31-12-2013', +); +$bookseller1fromid = C4::Bookseller::GetBookSellerFromId($id_supplier1); +is( $bookseller1fromid->{subscriptioncount}, + 2, 'Supplier1 has 2 subscriptions' ); + +#Test ModBookseller +$sample_supplier2 = { + id => $id_supplier2, + name => 'Name2 modified', + address1 => 'address1_2 modified', + address2 => 'address2-2 modified', + address3 => 'address3_2 modified', + address4 => 'address4_2 modified', + postal => 'postal2 modified', + phone => 'phone2 modified', + accountnumber => 'accountnumber2 modified', + fax => 'fax2 modified', + url => 'url2 modified', + contact => 'contact2 modified', + contpos => 'contpos2 modified', + contphone => 'contphone2 modified', + contfax => 'contefax2 modified', + contaltphone => 'contaltphone2 modified', + contemail => 'contemail2 modified', + contnotes => 'contnotes2 modified', + active => 1, + gstreg => 1, + listincgst => 1, + invoiceincgst => 1, + gstrate => '2.0000 ', + discount => '2.0000', + notes => 'notes2 modified', + deliverytime => 2, +}; + +#FIXME : ModBookseller always returns undef, even if the id isn't given +#or doesn't exist +my $modif1 = C4::Bookseller::ModBookseller(); +is( $modif1, undef, + "ModBookseller returns undef if no params given - Nothing happened" ); +$modif1 = C4::Bookseller::ModBookseller($sample_supplier2); +#is( $modif1, 1, "ModBookseller modifies only the supplier2" ); +is( scalar( C4::Bookseller::GetBookSeller('') ), + $count + 2, "Supplier2 has been modified - Nothing added" ); + +$modif1 = C4::Bookseller::ModBookseller( + { + id => -1, + name => 'name3' + } +); +#is( $modif1, '0E0', +# "ModBookseller returns OEO if the id doesnt exist - Nothing modified" ); + +#Test GetBooksellersWithLateOrders +#Add 2 suppliers +my $sample_supplier3 = { + name => 'Name3', + address1 => 'address1_3', + address2 => 'address1-3', + address3 => 'address1_3', + address4 => 'address1_3', + postal => 'postal3', + phone => 'phone3', + accountnumber => 'accountnumber3', + fax => 'fax3', + url => 'url3', + contact => 'contact3', + contpos => 'contpos3', + contphone => 'contphone3', + contfax => 'contefax3', + contaltphone => 'contaltphone3', + contemail => 'contemail3', + contnotes => 'contnotes3', + active => 1, + gstreg => 1, + listincgst => 1, + invoiceincgst => 1, + gstrate => '3.0000', + discount => '3.0000', + notes => 'notes3', + deliverytime => 3 +}; +my $sample_supplier4 = { + name => 'Name4', + address1 => 'address1_4', + address2 => 'address1-4', + address3 => 'address1_4', + address4 => 'address1_4', + postal => 'postal4', + phone => 'phone4', + accountnumber => 'accountnumber4', + fax => 'fax4', + url => 'url4', + contact => 'contact4', + contpos => 'contpos4', + contphone => 'contphone4', + contfax => 'contefax4', + contaltphone => 'contaltphone4', + contemail => 'contemail4', + contnotes => 'contnotes4', + active => 1, + gstreg => 1, + listincgst => 1, + invoiceincgst => 1, + gstrate => '3.0000', + discount => '3.0000', + notes => 'notes3', +}; +my $id_supplier3 = C4::Bookseller::AddBookseller($sample_supplier3); +my $id_supplier4 = C4::Bookseller::AddBookseller($sample_supplier4); + +#Add 2 baskets +my $sample_basket3 = + C4::Acquisition::NewBasket( $id_supplier3, 'authorisedby3', 'basketname3', + 'basketnote3' ); +my $sample_basket4 = + C4::Acquisition::NewBasket( $id_supplier4, 'authorisedby4', 'basketname4', + 'basketnote4' ); + +#Modify the basket to add a close date +my $basket1info = { + basketno => $sample_basket1, + closedate => $today, + booksellerid => $id_supplier1 +}; + +my $basket2info = { + basketno => $sample_basket2, + closedate => $daysago5, + booksellerid => $id_supplier2 +}; + +my $dt_today2 = dt_from_string; +my $dur10 = DateTime::Duration->new( days => -10 ); +$dt_today2->add_duration($dur10); +my $daysago10 = output_pref( $dt_today2, 'iso', '24hr', 1 ); +my $basket3info = { + basketno => $sample_basket3, + closedate => $daysago10, +}; + +my $basket4info = { + basketno => $sample_basket4, + closedate => $today, +}; +ModBasket($basket1info); +ModBasket($basket2info); +ModBasket($basket3info); +ModBasket($basket4info); + +#Add 1 subscription +my $id_subscription3 = C4::Serials::NewSubscription( + undef, "", $id_supplier3, undef, + $id_budget, $biblionumber, '01-01-2013', undef, + undef, undef, undef, undef, + undef, undef, undef, undef, + undef, undef, undef, undef, + undef, undef, undef, undef, + undef, undef, undef, undef, + undef, undef, undef, 1, + "notes", undef, undef, undef, + undef, undef, undef, 0, + "intnotes", 0, undef, undef, + 0, undef, '31-12-2013', +); + +#Add 4 orders +my ( $ordernumber1, $ordernumber2, $ordernumber3, $ordernumber4 ); +my ( $basketno1, $basketno2, $basketno3, $basketno4 ); +( $basketno1, $ordernumber1 ) = C4::Acquisition::NewOrder( + { + basketno => $sample_basket1, + quantity => 24, + biblionumber => $biblionumber, + budget_id => $id_budget, + entrydate => '01-01-2013', + currency => 'EUR', + notes => "This is a note1", + gstrate => 0.0500, + orderstatus => 1, + subscriptionid => $id_subscription1, + quantityreceived => 2, + rrp => 10, + ecost => 10, + datereceived => '01-06-2013' + } +); +( $basketno2, $ordernumber2 ) = C4::Acquisition::NewOrder( + { + basketno => $sample_basket2, + quantity => 20, + biblionumber => $biblionumber, + budget_id => $id_budget, + entrydate => '01-01-2013', + currency => 'EUR', + notes => "This is a note2", + gstrate => 0.0500, + orderstatus => 1, + subscriptionid => $id_subscription2, + rrp => 10, + ecost => 10, + } +); +( $basketno3, $ordernumber3 ) = C4::Acquisition::NewOrder( + { + basketno => $sample_basket3, + quantity => 20, + biblionumber => $biblionumber, + budget_id => $id_budget, + entrydate => '02-02-2013', + currency => 'EUR', + notes => "This is a note3", + gstrate => 0.0500, + orderstatus => 2, + subscriptionid => $id_subscription3, + rrp => 11, + ecost => 11, + } +); +( $basketno4, $ordernumber4 ) = C4::Acquisition::NewOrder( + { + basketno => $sample_basket4, + quantity => 20, + biblionumber => $biblionumber, + budget_id => $id_budget, + entrydate => '02-02-2013', + currency => 'EUR', + notes => "This is a note3", + gstrate => 0.0500, + orderstatus => 2, + subscriptionid => $id_subscription3, + rrp => 11, + ecost => 11, + quantityreceived => 20 + } +); + +#Test cases: +# Sample datas : +# Supplier1: delivery -> undef Basket1 : closedate -> today +# Supplier2: delivery -> 2 Basket2 : closedate -> $daysago5 +# Supplier3: delivery -> 3 Basket3 : closedate -> $daysago10 +#Case 1 : Without parameters: +# quantityreceived < quantity AND rrp <> 0 AND ecost <> 0 AND quantity - COALESCE(quantityreceived,0) <> 0 AND closedate IS NOT NULL -LATE- +# datereceived !null AND rrp <> 0 AND ecost <> 0 AND quantity - COALESCE(quantityreceived,0) <> 0 AND closedate IS NOT NULL -LATE- +# datereceived !null AND rrp <> 0 AND ecost <> 0 AND quantity - COALESCE(quantityreceived,0) <> 0 AND closedate IS NOT NULL -LATE- +# quantityreceived = quantity -NOT LATE- +my %suppliers = C4::Bookseller::GetBooksellersWithLateOrders(); +ok( exists( $suppliers{$id_supplier1} ), "Supplier1 has late orders" ); +ok( exists( $suppliers{$id_supplier2} ), "Supplier2 has late orders" ); +ok( exists( $suppliers{$id_supplier3} ), "Supplier3 has late orders" ); +isnt( exists( $suppliers{$id_supplier4} ), 1, "Supplier4 hasnt late orders" ) + ; # Quantity = quantityreceived + +#Case 2: With $delay = 4 +# today + 0 > now-$delay -NOT LATE- +# (today-5) + 2 <= now() - $delay -NOT LATE- +# (today-10) + 3 <= now() - $delay -LATE- +# quantityreceived = quantity -NOT LATE- +%suppliers = C4::Bookseller::GetBooksellersWithLateOrders( 4, undef, undef ); +isnt( exists( $suppliers{$id_supplier1} ), + 1, "Supplier1 has late orders but today > now() - 4 days" ); +#FIXME: If only the field delay is given, it doen't consider the deliverytime +#isnt( exists( $suppliers{$id_supplier2} ), +# 1, "Supplier2 has late orders and $daysago5 <= now() - (4 days+2)" ); +ok( exists( $suppliers{$id_supplier3} ), + "Supplier3 has late orders and $daysago10 <= now() - (4 days+3)" ); +isnt( exists( $suppliers{$id_supplier4} ), 1, "Supplier4 hasnt late orders" ); + +#Case 3: With $delay = -1 +#FIXME: GetBooksellersWithLateOrders doesn't test if the delay is a positive value +#is( C4::Bookseller::GetBooksellersWithLateOrders( -1, undef, undef ), +# undef, "-1 is a wrong value for a delay" ); + +#Case 4: With $delay = 0 +# today == now-0 -LATE- (if no deliverytime or deliverytime == 0) +# today-5 <= now() - $delay+2 -LATE- +# today-10 <= now() - $delay+3 -LATE- +# quantityreceived = quantity -NOT LATE- +%suppliers = C4::Bookseller::GetBooksellersWithLateOrders( 0, undef, undef ); + +ok( exists( $suppliers{$id_supplier1} ), + "Supplier1 has late orders but $today == now() - 0 days" ) + ; +ok( exists( $suppliers{$id_supplier2} ), + "Supplier2 has late orders and $daysago5 <= now() - 2" ); +ok( exists( $suppliers{$id_supplier3} ), + "Supplier3 has late orders and $daysago10 <= now() - 3" ); +isnt( exists( $suppliers{$id_supplier4} ), 1, "Supplier4 hasnt late orders" ); + +#Case 5 : With $estimateddeliverydatefrom = today-4 +# today >= today-4 -NOT LATE- +# (today-5)+ 2 days >= today-4 -LATE- +# (today-10) + 3 days < today-4 -NOT LATE- +# quantityreceived = quantity -NOT LATE- +my $dt_today3 = dt_from_string; +my $dur4 = DateTime::Duration->new( days => -4 ); +$dt_today3->add_duration($dur4); +my $daysago4 = output_pref( $dt_today3, 'iso', '24hr', 1 ); +%suppliers = + C4::Bookseller::GetBooksellersWithLateOrders( undef, $daysago4, undef ); + +#FIXME: if the deliverytime is undef, it doesn't consider the supplier +#ok( exists( $suppliers{$id_supplier1} ), +# "Supplier1 has late orders and $today >= $daysago4 -deliverytime undef" ); +ok( exists( $suppliers{$id_supplier2} ), + "Supplier2 has late orders and $daysago5 + 2 days >= $daysago4 " ); +isnt( exists( $suppliers{$id_supplier3} ), + 1, "Supplier3 has late orders and $daysago10 + 5 days < $daysago4 " ); +isnt( exists( $suppliers{$id_supplier4} ), 1, "Supplier4 hasnt late orders" ); + +#Case 6: With $estimateddeliverydatefrom =today-10 and $estimateddeliverydateto = today - 5 +# $daysago10<$daysago5= $daysago5 -NOT LATE- +# $daysago5 + 2 days > $daysago5 -NOT LATE- +# $daysago10 + 3 <+ $daysago5 -LATE- +# quantityreceived = quantity -NOT LATE- +%suppliers = + C4::Bookseller::GetBooksellersWithLateOrders( undef, undef, $daysago5 ); +#FIXME: if only the estimateddeliverydatefrom is given, it doesn't consider the parameters, +#but it replaces it today's date +#isnt( exists( $suppliers{$id_supplier1} ), +# 1, +# "Supplier1 has late orders but $today >= $daysago5 - deliverytime undef" ); +#isnt( exists( $suppliers{$id_supplier2} ), +# 1, "Supplier2 has late orders but $daysago5 + 2 days > $daysago5 " ); +ok( exists( $suppliers{$id_supplier3} ), + "Supplier3 has late orders and $daysago10 + 3 <= $daysago5" ); +isnt( exists( $suppliers{$id_supplier4} ), 1, "Supplier4 hasnt late orders" ); + +#Test with $estimateddeliverydatefrom and $estimateddeliverydateto and $delay +#Case 8 :With $estimateddeliverydatefrom = 2013-07-05 and $estimateddeliverydateto = 2013-07-08 and $delay =5 +# $daysago4 $daysago10 + 3days < today and $daysago10 <= now()-3+3 days -NOT LATE- +# quantityreceived = quantity -NOT LATE- +%suppliers = + C4::Bookseller::GetBooksellersWithLateOrders( 3, $daysago4, $today ); +isnt( + exists( $suppliers{$id_supplier1} ), + 1, + "Supplier1 has late orders but $daysago4 $daysago10 + 3days < today and $daysago10 <= now()-3+3 days" +); +isnt( exists( $suppliers{$id_supplier4} ), 1, "Supplier4 hasnt late orders" ); + +#Case 9 :With $estimateddeliverydatefrom = $daysago5 and $delay = 3 +# $today < $daysago5 and $today > $today-5 -NOT LATE- +# $daysago5 + 2 days >= $daysago5 and $daysago5 < today - 3+2 -LATE- +# $daysago10 + 3 days < $daysago5 and $daysago10 < today -3+2-NOT LATE- +# quantityreceived = quantity -NOT LATE- +%suppliers = + C4::Bookseller::GetBooksellersWithLateOrders( 3, $daysago5, undef ); +isnt( exists( $suppliers{$id_supplier1} ), + 1, "$today < $daysago10 and $today > $today-3" ); +ok( + exists( $suppliers{$id_supplier2} ), +"Supplier2 has late orders and $daysago5 + 2 days >= $daysago5 and $daysago5 < today - 3+2" +); +isnt( + exists( $suppliers{$id_supplier3} ), + 1, +"Supplier2 has late orders but $daysago10 + 3 days < $daysago5 and $daysago10 < today -3+2 " +); +isnt( exists( $suppliers{$id_supplier4} ), 1, "Supplier4 hasnt late orders" ); + +#Test with $estimateddeliverydateto and $delay +#Case 10:With $estimateddeliverydateto = $daysago5 and $delay = 5 +# today > $daysago5 today > now() -5 -NOT LATE- +# $daysago5 + 2 days > $daysago5 and $daysago5 > now() - 2+5 days -NOT LATE- +# $daysago10 + 3 days <= $daysago5 and $daysago10 <= now() - 3+5 days -LATE- +# quantityreceived = quantity -NOT LATE- +%suppliers = + C4::Bookseller::GetBooksellersWithLateOrders( 5, undef, $daysago5 ); +isnt( exists( $suppliers{$id_supplier1} ), + 1, "Supplier2 has late orders but today > $daysago5 today > now() -5" ); +#FIXME: GetBookSellersWithLateOrders replace estimateddeliverydateto by +#today's date when no estimateddeliverydatefrom is give +#isnt( +# exists( $suppliers{$id_supplier2} ), +# 1, +#"Supplier2 has late orders but $daysago5 + 2 days > $daysago5 and $daysago5 > now() - 2+5 days" +#); +ok( + exists( $suppliers{$id_supplier3} ), +"Supplier2 has late orders and $daysago10 + 3 days <= $daysago5 and $daysago10 <= now() - 3+5 days " +); +isnt( exists( $suppliers{$id_supplier4} ), 1, "Supplier4 hasnt late orders" ); + +#Case 11: With $estimateddeliverydatefrom =today-10 and $estimateddeliverydateto = today - 10 +# $daysago10==$daysago10==$daysago10 -NOT LATE- +# $daysago10==$daysago10<$daysago5+2-NOT lATE- +# $daysago10==$daysago10 <$daysago10+3-LATE- +# quantityreceived = quantity -NOT LATE- + +#Basket1 closedate -> $daysago10 +$basket1info = { + basketno => $sample_basket1, + closedate => $daysago10, +}; +ModBasket($basket1info); +%suppliers = C4::Bookseller::GetBooksellersWithLateOrders( undef, $daysago10, + $daysago10 ); +#FIXME :GetBookSellers doesn't take care if the closedate is ==$estimateddeliverydateto +# ok( exists( $suppliers{$id_supplier1} ), +# "Supplier1 has late orders and $daysago10==$daysago10==$daysago10 " ) +# ; +isnt( exists( $suppliers{$id_supplier2} ), + 1, + "Supplier2 has late orders but $daysago10==$daysago10<$daysago5+2" ); +isnt( exists( $suppliers{$id_supplier3} ), + 1, + "Supplier3 has late orders but $daysago10==$daysago10 <$daysago10+3" ); +isnt( exists( $suppliers{$id_supplier4} ), 1, "Supplier4 hasnt late orders" ); + +#Case 12: closedate == $estimateddeliverydatefrom =today-10 +%suppliers = + C4::Bookseller::GetBooksellersWithLateOrders( undef, $daysago10, undef ); +#FIXME :GetBookSellers doesn't take care if the closedate is ==$estimateddeliverydateto +#ok( exists( $suppliers{$id_supplier1} ), +# "Supplier1 has late orders and $daysago10==$daysago10 " ); + +#Case 13: closedate == $estimateddeliverydateto =today-10 +%suppliers = + C4::Bookseller::GetBooksellersWithLateOrders( undef, undef, $daysago10 ); +ok( exists( $suppliers{$id_supplier1} ), + "Supplier1 has late orders and $daysago10==$daysago10 " ) + ; + +#End transaction +$dbh->rollback; + +#field_filter filters the useless fields or foreign keys +#NOTE: all the fields of aqbookseller arent considered +#returns a cleaned structure +sub field_filter { + my ($struct) = @_; + + for my $field ( + 'bookselleremail', 'booksellerfax', + 'booksellerurl', 'othersupplier', + 'currency', 'invoiceprice', + 'listprice' + ) + { + + if ( grep { /^$field$/ } keys %$struct ) { + delete $struct->{$field}; + } + } + return $struct; +} -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Jul 26 02:06:30 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 26 Jul 2013 12:06:30 +1200 Subject: [Koha-patches] [PATCH] Bug 10589 - Override OpacHiddenItems based on Patron Category Message-ID: <1374797190-12052-1-git-send-email-srdjan@catalyst.net.nz> From: Mark Tompsett Two system preferences, PatronSingleBranch and PatronEveryBranch, have been added to facilitate some granularity on the override. If the home branch of the item and the patron match and the catgegory code of the patron matches one of the pipe delimited values in the PatronSingleBranch patron category code, then an item which would normally be hidden will be visible. If the patron category matches one of the pipe delimited values in the PatronEveryBranch patron category, then every item hidden by OpacHiddenItems will be visible. Since the patron category codes used by default for these two system preferences are not added, OpacHiddenItems will continue function as expected until individual patrons and system preferences are configured. There is no need to provide this functionality to staff, as they have access to the staff client. Signed-off-by: Srdjan --- C4/Items.pm | 25 ++++++++++++++++++++-- installer/data/mysql/sysprefs.sql | 2 ++ installer/data/mysql/updatedatabase.pl | 16 ++++++++++++++ .../prog/en/modules/admin/preferences/opac.pref | 8 +++++++ 4 files changed, 49 insertions(+), 2 deletions(-) diff --git a/C4/Items.pm b/C4/Items.pm index 212a9d3..f7550dc 100644 --- a/C4/Items.pm +++ b/C4/Items.pm @@ -32,6 +32,7 @@ use C4::Log; use List::MoreUtils qw/any/; use Data::Dumper; # used as part of logging item record changes, not just for # debugging; so please don't remove this +use C4::Members qw/GetBorrowerCategorycode/; use vars qw($VERSION @ISA @EXPORT); @@ -1635,6 +1636,18 @@ sub GetHiddenItemnumbers { return (); } my $dbh = C4::Context->dbh; + my $borrowernumber = 0; + my $homebranch = q{}; + my $categorycode = q{}; + if (C4::Context->userenv) { + $borrowernumber = C4::Context->userenv->{'number'} || 0; + $homebranch = C4::Context->userenv->{'branch'} || q{}; + } + if ($borrowernumber) { + $categorycode = C4::Members::GetBorrowerCategorycode($borrowernumber) || q{}; + } + my @SingleBranchCodes = split /\|/,C4::Context->preference('PatronSingleBranch'); + my @EveryBranchCodes = split /\|/,C4::Context->preference('PatronEveryBranch'); # For each item foreach my $item (@items) { @@ -1654,8 +1667,16 @@ sub GetHiddenItemnumbers { # If the results matches the values in the yaml file if (any { $val eq $_ } @{$hidingrules->{$field}}) { - # We add the itemnumber to the list - push @resultitems, $item->{'itemnumber'}; + my $override = 0; + if ( ($homebranch eq $item->{'homebranch'} && + (any { /^$categorycode$/ } @SingleBranchCodes ) ) || + (any { /^$categorycode$/ } @EveryBranchCodes ) ) { + $override = 1; + } + if ($override==0) { + # We add the itemnumber to the hidden list + push @resultitems, $item->{'itemnumber'}; + } # If at least one rule matched for an item, no need to test the others last; diff --git a/installer/data/mysql/sysprefs.sql b/installer/data/mysql/sysprefs.sql index c8caee7..accb0b9 100644 --- a/installer/data/mysql/sysprefs.sql +++ b/installer/data/mysql/sysprefs.sql @@ -430,3 +430,5 @@ INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) V INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('CalculateFinesOnReturn','1','Switch to control if overdue fines are calculated on return or not', '', 'YesNo'); INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('AcqWarnOnDuplicateInvoice','0','Warn librarians when they try to create a duplicate invoice', '', 'YesNo'); INSERT IGNORE INTO systempreferences (variable,value,explanation,options,type) VALUES ('AllowTooManyOverride', '1', 'If on, allow staff to override and check out items when the patron has reached the maximum number of allowed checkouts', '', 'YesNo'); +INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('PatronEveryBranch','','Pipe delimited patron category codes which allow viewing hidden items for every branch','',''); +INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('PatronSingleBranch','',"Pipe delimited patron category codes which allow viewing hidden items for only the patron's home branch",'',''); diff --git a/installer/data/mysql/updatedatabase.pl b/installer/data/mysql/updatedatabase.pl index 74aeb3e..ab69e81 100755 --- a/installer/data/mysql/updatedatabase.pl +++ b/installer/data/mysql/updatedatabase.pl @@ -7067,6 +7067,22 @@ if ( CheckVersion($DBversion) ) { SetVersion($DBversion); } +$DBversion = "3.13.00.XXX"; +if ( CheckVersion($DBversion) ) { + $dbh->do( + q{ +INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('PatronEveryBranch','',"Pipe delimited patron category codes which allow viewing hidden items for every branch",'',''); +} + ); + $dbh->do( + q{ +INSERT INTO systempreferences (variable,value,explanation,options,type) VALUES ('PatronSingleBranch','',"Pipe delimited patron category codes which allow viewing hidden items for only the patron's home branch",'',''); +} + ); + print "Upgrade to $DBversion done (Bug filtering: Patron Category to override OPACHiddenItems)\n"; + SetVersion($DBversion); +} + =head1 FUNCTIONS =head2 TableExists($table) diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref index 90295ef..2f4c195 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref @@ -497,6 +497,14 @@ OPAC: class: code - Allows to define custom rules for hiding specific items at opac. See docs/opac/OpacHiddenItems.txt for more informations - + - pref: PatronSingleBranch + class: short + - Patrons matching one of these pipe delimited patron category codes override OpacHiddenItems for their home branch only. + - + - pref: PatronEveryBranch + class: short + - Patrons matching one of these pipe delimited patron category codes override OpacHiddenItems for every branch. + - - pref: OpacAllowPublicListCreation default: 1 choices: -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Jul 26 06:06:02 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 26 Jul 2013 16:06:02 +1200 Subject: [Koha-patches] [PATCH] Bug 10424 - Search received orders Message-ID: <1374811562-6318-1-git-send-email-srdjan@catalyst.net.nz> From: Amit Gupta Search against order numbers and pull up the related invoice to see when the item was received. This allows users to see details of received orders, including the details against which invoice the order is received. Test Plan: 1) Create a basket. 2) Create a orders under basket and close the basket. 3) Click on Receive shipment button and enter the invoice no and shipment date. 4) Click on Receive link to receive the items. 5) Click on Received orders link on the left hand side. 6) This allow user to search by orderline, basket, title, author, ISBN, vendor and date received. 7) Users will be able to see details of received orders. Sponsored-by: Staffordshire University/Halton Borough Council/PTFS Europe Signed-off-by: Srdjan --- C4/Acquisition.pm | 139 +++++++++++++++++++++ acqui/receivedorders.pl | 109 ++++++++++++++++ .../prog/en/includes/acquisitions-menu.inc | 1 + .../prog/en/modules/acqui/receivedorders.tt | 110 ++++++++++++++++ 4 files changed, 359 insertions(+) create mode 100755 acqui/receivedorders.pl create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/acqui/receivedorders.tt diff --git a/C4/Acquisition.pm b/C4/Acquisition.pm index 1a210b5..c8bc7d4 100644 --- a/C4/Acquisition.pm +++ b/C4/Acquisition.pm @@ -72,6 +72,7 @@ BEGIN { &CloseInvoice &ReopenInvoice &DelInvoice + &GetReceivedorder &GetItemnumbersFromOrder @@ -2061,6 +2062,144 @@ sub GetHistory { return \@order_loop, $total_qty, $total_price, $total_qtyreceived; } +=head3 GetReceivedorder + + $orderrec_loop = GetReceivedorder( %params ); + +Returns an arrayref of received orders + +params: + title + author + name + datereceivedfrom + datereceivedto + basket - search both basket name and number + ordernumber - search by ordernumber + +returns: + $order_loop is a reference to an array of hashrefs that each look like this: + { + 'author' => 'Twain, Mark', + 'basketno' => '1', + 'biblionumber' => '215', + 'datereceived' => 'MM/DD/YYYY' + 'name' => '', + 'ordernumber' => '1', + 'quantity' => 1, + 'quantityreceived' => undef, + 'title' => 'The Adventures of Huckleberry Finn' + } + +=cut + +sub GetReceivedorder { + croak "No search params" unless @_; + my %params = @_; + my $title = $params{title}; + my $author = $params{author}; + my $isbn = $params{isbn}; + my $ean = $params{ean}; + my $name = $params{name}; + my $datereceivedfrom = $params{datereceivedfrom}; + my $datereceivedto = $params{datereceivedto}; + my $basket = $params{basket}; + my $order = $params{ordernumber}; + + my $query =" + SELECT + biblio.title, + biblio.author, + biblioitems.isbn, + biblioitems.ean, + aqorders.basketno, + aqbasket.basketname, + aqbooksellers.name, + aqbasket.creationdate, + aqorders.datereceived, + aqorders.quantity, + aqorders.quantityreceived, + aqorders.ecost, + aqorders.ordernumber, + aqorders.invoiceid, + aqinvoices.invoicenumber, + aqbooksellers.id as id, + aqorders.biblionumber + FROM aqorders + LEFT JOIN aqbasket ON aqorders.basketno=aqbasket.basketno + LEFT JOIN aqbooksellers ON aqbasket.booksellerid=aqbooksellers.id + LEFT JOIN biblioitems ON biblioitems.biblionumber=aqorders.biblionumber + LEFT JOIN biblio ON biblio.biblionumber=aqorders.biblionumber + LEFT JOIN aqinvoices ON aqorders.invoiceid = aqinvoices.invoiceid"; + + $query .= " LEFT JOIN borrowers ON aqbasket.authorisedby=borrowers.borrowernumber" + if ( C4::Context->preference("IndependentBranches") ); + + $query .= " WHERE (aqorders.datereceived IS NOT NULL) "; + + my @query_params = (); + + if ( $title ) { + $query .= " AND biblio.title LIKE ? "; + $title =~ s/\s+/%/g; + push @query_params, "%$title%"; + } + + if ( $author ) { + $query .= " AND biblio.author LIKE ? "; + push @query_params, "%$author%"; + } + + if ( $isbn ) { + $query .= " AND biblioitems.isbn LIKE ? "; + push @query_params, "%$isbn%"; + } + if ( defined $ean and $ean ) { + $query .= " AND biblioitems.ean = ? "; + push @query_params, "$ean"; + } + if ( $name ) { + $query .= " AND aqbooksellers.name LIKE ? "; + push @query_params, "%$name%"; + } + if ( $datereceivedfrom ) { + $query .= " AND aqorders.datereceived >= ? "; + push @query_params, $datereceivedfrom; + } + + if ( $datereceivedto ) { + $query .= " AND aqorders.datereceived <= ? "; + push @query_params, $datereceivedto; + } + + if ($basket) { + if ($basket =~ m/^\d+$/) { + $query .= " AND aqorders.basketno = ? "; + push @query_params, $basket; + } else { + $query .= " AND aqbasket.basketname LIKE ? "; + push @query_params, "%$basket%"; + } + } + + if ($order =~ m/^\d+$/) { + $query .= " AND aqorders.ordernumber = ? "; + push @query_params, $order; + } + + if ( C4::Context->preference("IndependentBranches") ) { + my $userenv = C4::Context->userenv; + if ( $userenv && ($userenv->{flags} || 0) != 1 ) { + $query .= " AND (borrowers.branchcode = ? OR borrowers.branchcode ='' ) "; + push @query_params, $userenv->{branch}; + } + } + $query .= " ORDER BY id"; + + my $dbh = C4::Context->dbh; + return $dbh->selectall_arrayref( $query, { Slice => {} }, @query_params ); +} + =head2 GetRecentAcqui $results = GetRecentAcqui($days); diff --git a/acqui/receivedorders.pl b/acqui/receivedorders.pl new file mode 100755 index 0000000..c69c3cb --- /dev/null +++ b/acqui/receivedorders.pl @@ -0,0 +1,109 @@ +#!/usr/bin/perl + +# This file is part of Koha. +# +# Copyright 2013 Amit Gupta(amitddng135 at gmail.com) +# +# 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. + +=head1 NAME + +receivedorders.pl + +=head1 DESCRIPTION + +this script offer a interface to search among order. + +=head1 CGI PARAMETERS + +=over 4 + +=item title +if the script has to filter the results on title. + +=item author +if the script has to filter the results on author. + +=item name +if the script has to filter the results on supplier. + +=item datereceivedfrom +to filter on started date. + +=item datereceivedto +to filter on ended date. + +=back + +=cut + +use strict; +use warnings; +use CGI; +use C4::Auth; # get_template_and_user +use C4::Output; +use C4::Acquisition qw/GetReceivedorder/; +use C4::Dates; +use C4::Debug; + +my $input = new CGI(); +my $title = $input->param('title'); +my $ordernumber = $input->param('ordernumber'); +my $author = $input->param('author'); +my $isbn = $input->param('isbn'); +my $name = $input->param('name' ); +my $ean = $input->param('ean'); +my $basket = $input->param( 'basket' ); +my $do_search = $input->param('do_search') || 0; +my $from = C4::Dates->new($input->param('from')); +my $to = C4::Dates->new($input->param('to')); + +my ( $template, $loggedinuser, $cookie ) = get_template_and_user( + { + template_name => "acqui/receivedorders.tmpl", + query => $input, + type => "intranet", + authnotrequired => 0, + flagsrequired => { acquisition => '*' }, + debug => 1, + } +); + +my ( $from_iso, $to_iso, $d ); +if ( $d = $input->param('from') ) { + $from_iso = C4::Dates->new($d)->output('iso'); +} +if ( $d = $input->param('iso') ) { + $to_iso = C4::Dates->new($d)->output('iso'); +} + +my $orderrec_loop; + +if ($do_search) { + $orderrec_loop = GetReceivedorder( + title => $title, + author => $author, + isbn => $isbn, + ean => $ean, + name => $name, + datereceivedfrom => $from_iso, + datereceivedto => $to_iso, + basket => $basket, + ordernumber => $ordernumber, + ); +} + +$template->param( orderrec_loop => $orderrec_loop,); + +output_html_with_http_headers $input, $cookie, $template->output; diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc index 439118d..d37c4b6 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc @@ -2,6 +2,7 @@
  • Late orders
  • [% IF ( suggestion ) %]
  • Suggestions
  • [% ELSE %][% END %]
  • Invoices
  • +
  • Received orders
  • [% IF ( CAN_user_acquisition_budget_manage ) %]
  • Budgets
  • Funds
  • diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/receivedorders.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/receivedorders.tt new file mode 100644 index 0000000..185c6c1 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/receivedorders.tt @@ -0,0 +1,110 @@ +[% USE KohaDates %] +[% INCLUDE 'doc-head-open.inc' %] +Koha › Acquisitions › [% IF ( orderrec_loop ) %] Received orders › Search results[% ELSE %]Search received orders[% END %] + +[% INCLUDE 'doc-head-close.inc' %] +[% INCLUDE 'calendar.inc' %] + +[% INCLUDE 'datatables-strings.inc' %] + + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'acquisitions-search.inc' %] + + + +
    +
    +
    +
    + [% UNLESS ( orderrec_loop ) %]
    +
    + Search received orders +
      +
    1. +
    2. +
    3. +
    4. +
    5. + [% IF (UNIMARC) %] +
    6. + [% END %] +
    7. +
    8. + +
      [% INCLUDE 'date-format.inc' %]
      +
    9. +
    10. + +
      [% INCLUDE 'date-format.inc' %]
      +
    11. +
    +
    + +
    +
    + [% END %] + [% IF ( orderrec_loop ) %]

    Received orders search result

    +
    + + + + + + + + + + + + + + + + + [% FOREACH ordersrec_loo IN orderrec_loop %] + + + + + + + + + + + + + [% END %] + +
    BasketInvoice numberOrder numberSummaryVendorPlaced onReceived onQuantity orderedQuantity receivedUnit price
    [% ordersrec_loo.basketname %] ([% ordersrec_loo.basketno %]) + [% IF ordersrec_loo.invoicenumber %] + [% ordersrec_loo.invoicenumber %] + [% ELSE %] +   + [% END %] + [% ordersrec_loo.ordernumber %][% ordersrec_loo.title |html %] +
    [% ordersrec_loo.author %]
    [% ordersrec_loo.isbn %] +
    [% ordersrec_loo.name %][% ordersrec_loo.creationdate | $KohaDates %] + [% IF ordersrec_loo.datereceived %] + [% ordersrec_loo.datereceived | $KohaDates %] + [% END %] + [% ordersrec_loo.quantity %][% ordersrec_loo.quantityreceived %][% ordersrec_loo.ecost %]
    +
    + [% ELSE %] + [% END %] +
    +
    +
    +[% INCLUDE 'acquisitions-menu.inc' %] +
    +
    +[% INCLUDE 'intranet-bottom.inc' %] -- 1.8.1.2 From srdjan at catalyst.net.nz Fri Jul 26 06:13:39 2013 From: srdjan at catalyst.net.nz (Srdjan) Date: Fri, 26 Jul 2013 16:13:39 +1200 Subject: [Koha-patches] [PATCH] Bug 10393 - Receive shipment link in acquisitions main page Message-ID: <1374812019-7276-1-git-send-email-srdjan@catalyst.net.nz> From: Amit Gupta To add some shortcuts to acquisitions main screen e.g. RECEIVE SHIPMENT and the FILTER BOX Test plan: 1) Click on Receive shipment link on the left hand side. 2) It will give all the vendor list click on recieve shipment link to receive items. 3) For creating new basket click on "New Basket" link. Sponsored-by: Staffordshire University/Halton Borough Council/PTFS Europe Signed-off-by: Srdjan --- acqui/receiveshipment.pl | 57 +++++++++++++++++ .../prog/en/includes/acquisitions-menu.inc | 1 + .../prog/en/modules/acqui/receiveshipment.tt | 71 ++++++++++++++++++++++ 3 files changed, 129 insertions(+) create mode 100755 acqui/receiveshipment.pl create mode 100644 koha-tmpl/intranet-tmpl/prog/en/modules/acqui/receiveshipment.tt diff --git a/acqui/receiveshipment.pl b/acqui/receiveshipment.pl new file mode 100755 index 0000000..b24adf9 --- /dev/null +++ b/acqui/receiveshipment.pl @@ -0,0 +1,57 @@ +#!/usr/bin/perl + +# Copyright 2013 Amit Gupta(amitddng135 at gmail.com) +# 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. + +=head1 NAME + +receiveshipment.pl + +=head1 DESCRIPTION + +this script is the main page for acqui + +=cut + +use strict; +use warnings; +use CGI; +use C4::Auth; +use C4::Output; +use C4::Members; +use C4::Branch; +use C4::Debug; +use C4::Bookseller qw/ GetBookSeller /; + +my $input = CGI->new(); + +my ( $template, $loggedinuser, $cookie, $userflags ) = get_template_and_user( + { template_name => 'acqui/receiveshipment.tmpl', + query => $input, + type => 'intranet', + authnotrequired => 0, + flagsrequired => { acquisition => '*' }, + debug => 1, + } +); + +my $user = GetMember( 'borrowernumber' => $loggedinuser ); +my $branchname = GetBranchName($user->{branchcode}); + +my @suppliers = GetBookSeller(); +$template->param( supplier_loop => \@suppliers); + +output_html_with_http_headers $input, $cookie, $template->output; diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc index 439118d..9657466 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/acquisitions-menu.inc @@ -2,6 +2,7 @@
  • Late orders
  • [% IF ( suggestion ) %]
  • Suggestions
  • [% ELSE %][% END %]
  • Invoices
  • +
  • Receive shipment
  • [% IF ( CAN_user_acquisition_budget_manage ) %]
  • Budgets
  • Funds
  • diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/receiveshipment.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/receiveshipment.tt new file mode 100644 index 0000000..b1004a3 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/receiveshipment.tt @@ -0,0 +1,71 @@ +[% INCLUDE 'doc-head-open.inc' %] +Koha › Acquisitions › Receive shipment +[% INCLUDE 'doc-head-close.inc' %] + + +[% INCLUDE 'datatables-strings.inc' %] + + + + +[% INCLUDE 'header.inc' %] +[% INCLUDE 'acquisitions-search.inc' %] + + +
    +
    +
    +
    +
    +
    +[% IF (supplier_loop) %] +

    Receive shipment

    +
    + + + + + + + + + + +[% FOREACH suppliers IN supplier_loop %] + + + [% IF(suppliers.active == 1)%] + + [% ELSE %] + + [% END %] + + + +[% END %] + +
    VendorStatus  
    [% suppliers.name %]ActiveInactiveReceive shipmentNew basket
    +
    +[% END %] +
    +
    +
    +
    +
    +[% INCLUDE 'acquisitions-menu.inc' %] +
    +
    +[% INCLUDE 'intranet-bottom.inc' %] -- 1.8.1.2 From oleonard at myacpl.org Fri Jul 26 17:20:53 2013 From: oleonard at myacpl.org (Owen Leonard) Date: Fri, 26 Jul 2013 11:20:53 -0400 Subject: [Koha-patches] =?utf-8?q?=5BPATCH=5D_Bug_10649_-_Upgrade_DataTabl?= =?utf-8?q?es_and_move_scripts_out_of_theme_directory?= Message-ID: <1374852054-24445-1-git-send-email-oleonard@myacpl.org> This patch adds an upgraded copy of the DataTables plugin to the jQuery plugin directory outside the theme directories. Copies of the old DataTables plugin scripts have been left in the old location while templates are incrementally updated. To test, visit each affected page in Acquisitions and confirm that table sorting still words correctly: - Acquisitions home - Acquisitions -> Late orders - Acquisitions -> Order search - Acquisitions -> Ordered (from table of available funds) - Acquisitions -> Spent (from table of available funds) - Acquisitions -> Vendor search - Acquisitions -> Vendor detail - Acquisitions -> Vendor -> Basket - Acquisitions -> Vendor -> Basket -> Add order from existing record -> Add order from suggestion -> Add order from subscription -> Add order from external source -> Add order from staged file - Acquisitions -> Vendor -> Basket groups - Acquisitions -> Vendor -> Uncertain prices - Acquisitions -> Vendor -> Invoices - Acquisitions -> Vendor -> Invoices -> Invoice - Acquisitions -> Vendor -> Receive shipments - Acquisitions -> Vendor -> Receive shipments -> Receipt summary (click invoice number) Also test one or more pages which have not been modified to confirm that old DataTables assets are still in place and working (ex: Circulation, Quotes editor, Saved reports, etc.) --- .../lib/jquery/plugins/dataTables.fnReloadAjax.js | 50 ++ .../plugins/jquery.dataTables.columnFilter.js | 762 ++++++++++++++++++++ .../lib/jquery/plugins/jquery.dataTables.min.js | 155 ++++ .../intranet-tmpl/prog/en/includes/datatables.inc | 20 + .../prog/en/modules/acqui/acqui-home.tt | 4 +- .../prog/en/modules/acqui/addorderiso2709.tt | 4 +- .../intranet-tmpl/prog/en/modules/acqui/basket.tt | 5 +- .../prog/en/modules/acqui/basketgroup.tt | 3 +- .../prog/en/modules/acqui/booksellers.tt | 4 +- .../prog/en/modules/acqui/histsearch.tt | 4 +- .../intranet-tmpl/prog/en/modules/acqui/invoice.tt | 4 +- .../prog/en/modules/acqui/invoices.tt | 4 +- .../prog/en/modules/acqui/lateorders.tt | 5 +- .../prog/en/modules/acqui/neworderbiblio.tt | 4 +- .../prog/en/modules/acqui/newordersubscription.tt | 4 +- .../prog/en/modules/acqui/newordersuggestion.tt | 4 +- .../intranet-tmpl/prog/en/modules/acqui/ordered.tt | 4 +- .../intranet-tmpl/prog/en/modules/acqui/parcel.tt | 4 +- .../intranet-tmpl/prog/en/modules/acqui/parcels.tt | 4 +- .../intranet-tmpl/prog/en/modules/acqui/spent.tt | 4 +- .../prog/en/modules/acqui/supplier.tt | 4 +- .../prog/en/modules/acqui/uncertainprice.tt | 4 +- .../prog/en/modules/acqui/z3950_search.tt | 4 +- 23 files changed, 1006 insertions(+), 58 deletions(-) create mode 100644 koha-tmpl/intranet-tmpl/lib/jquery/plugins/dataTables.fnReloadAjax.js create mode 100644 koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.columnFilter.js create mode 100644 koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.min.js create mode 100644 koha-tmpl/intranet-tmpl/prog/en/includes/datatables.inc diff --git a/koha-tmpl/intranet-tmpl/lib/jquery/plugins/dataTables.fnReloadAjax.js b/koha-tmpl/intranet-tmpl/lib/jquery/plugins/dataTables.fnReloadAjax.js new file mode 100644 index 0000000..0eac52a --- /dev/null +++ b/koha-tmpl/intranet-tmpl/lib/jquery/plugins/dataTables.fnReloadAjax.js @@ -0,0 +1,50 @@ +$.fn.dataTableExt.oApi.fnReloadAjax = function ( oSettings, sNewSource, fnCallback, bStandingRedraw ) +{ + if ( typeof sNewSource != 'undefined' && sNewSource != null ) + { + oSettings.sAjaxSource = sNewSource; + } + this.oApi._fnProcessingDisplay( oSettings, true ); + var that = this; + var iStart = oSettings._iDisplayStart; + var aData = []; + + this.oApi._fnServerParams( oSettings, aData ); + + oSettings.fnServerData( oSettings.sAjaxSource, aData, function(json) { + /* Clear the old information from the table */ + that.oApi._fnClearTable( oSettings ); + + /* Got the data - add it to the table */ + var aData = (oSettings.sAjaxDataProp !== "") ? + that.oApi._fnGetObjectDataFn( oSettings.sAjaxDataProp )( json ) : json; + + for ( var i=0 ; i + ///Return values in the column + /// + ///DataTables settings + ///Id of the column + ///Return only distinct values + ///Return values only from the filtered rows + ///Ignore empty cells + + // check that we have a column id + if (typeof iColumn == "undefined") return new Array(); + + // by default we only wany unique data + if (typeof bUnique == "undefined") bUnique = true; + + // by default we do want to only look at filtered data + if (typeof bFiltered == "undefined") bFiltered = true; + + // by default we do not wany to include empty values + if (typeof bIgnoreEmpty == "undefined") bIgnoreEmpty = true; + + // list of rows which we're going to loop through + var aiRows; + + // use only filtered rows + if (bFiltered == true) aiRows = oSettings.aiDisplay; + // use all rows + else aiRows = oSettings.aiDisplayMaster; // all row numbers + + // set up data array + var asResultData = new Array(); + + for (var i = 0, c = aiRows.length; i < c; i++) { + var iRow = aiRows[i]; + var aData = oTable.fnGetData(iRow); + var sValue = aData[iColumn]; + + // ignore empty values? + if (bIgnoreEmpty == true && sValue.length == 0) continue; + + // ignore unique values? + else if (bUnique == true && jQuery.inArray(sValue, asResultData) > -1) continue; + + // else push the value onto the result data array + else asResultData.push(sValue); + } + + return asResultData.sort(); + } + + function _fnColumnIndex(iColumnIndex) { + if (properties.bUseColVis) + return iColumnIndex; + else + return oTable.fnSettings().oApi._fnVisibleToColumnIndex(oTable.fnSettings(), iColumnIndex); + //return iColumnIndex; + //return oTable.fnSettings().oApi._fnColumnIndexToVisible(oTable.fnSettings(), iColumnIndex); + } + + function fnCreateInput(oTable, regex, smart, bIsNumber, iFilterLength, iMaxLenght) { + var sCSSClass = "text_filter"; + if (bIsNumber) + sCSSClass = "number_filter"; + + label = label.replace(/(^\s*)|(\s*$)/g, ""); + var currentFilter = oTable.fnSettings().aoPreSearchCols[i].sSearch; + var search_init = 'search_init '; + var inputvalue = label; + if (currentFilter != '' && currentFilter != '^') { + if (bIsNumber && currentFilter.charAt(0) == '^') + inputvalue = currentFilter.substr(1); //ignore trailing ^ + else + inputvalue = currentFilter; + search_init = ''; + } + + var input = $(''); + if (iMaxLenght != undefined && iMaxLenght != -1) { + input.attr('maxlength', iMaxLenght); + } + th.html(input); + if (bIsNumber) + th.wrapInner(''); + else + th.wrapInner(''); + + asInitVals[i] = label; + var index = i; + + if (bIsNumber && !oTable.fnSettings().oFeatures.bServerSide) { + input.keyup(function () { + /* Filter on the column all numbers that starts with the entered value */ + oTable.fnFilter('^' + this.value, _fnColumnIndex(index), true, false); //Issue 37 + fnOnFiltered(); + }); + } else { + input.keyup(function () { + if (oTable.fnSettings().oFeatures.bServerSide && iFilterLength != 0) { + //If filter length is set in the server-side processing mode + //Check has the user entered at least iFilterLength new characters + + var currentFilter = oTable.fnSettings().aoPreSearchCols[index].sSearch; + var iLastFilterLength = $(this).data("dt-iLastFilterLength"); + if (typeof iLastFilterLength == "undefined") + iLastFilterLength = 0; + var iCurrentFilterLength = this.value.length; + if (Math.abs(iCurrentFilterLength - iLastFilterLength) < iFilterLength + //&& currentFilter.length == 0 //Why this? + ) { + //Cancel the filtering + return; + } + else { + //Remember the current filter length + $(this).data("dt-iLastFilterLength", iCurrentFilterLength); + } + } + /* Filter on the column (the index) of this element */ + oTable.fnFilter(this.value, _fnColumnIndex(index), regex, smart); //Issue 37 + fnOnFiltered(); + }); + } + + input.focus(function () { + if ($(this).hasClass("search_init")) { + $(this).removeClass("search_init"); + this.value = ""; + } + }); + input.blur(function () { + if (this.value == "") { + $(this).addClass("search_init"); + this.value = asInitVals[index]; + } + }); + } + + function fnCreateRangeInput(oTable) { + + //var currentFilter = oTable.fnSettings().aoPreSearchCols[i].sSearch; + th.html(_fnRangeLabelPart(0)); + var sFromId = oTable.attr("id") + '_range_from_' + i; + var from = $(''); + th.append(from); + th.append(_fnRangeLabelPart(1)); + var sToId = oTable.attr("id") + '_range_to_' + i; + var to = $(''); + th.append(to); + th.append(_fnRangeLabelPart(2)); + th.wrapInner(''); + var index = i; + aiCustomSearch_Indexes.push(i); + + + + //------------start range filtering function + + + /* Custom filtering function which will filter data in column four between two values + * Author: Allan Jardine, Modified by Jovan Popovic + */ + //$.fn.dataTableExt.afnFiltering.push( + oTable.dataTableExt.afnFiltering.push( + function (oSettings, aData, iDataIndex) { + if (oTable.attr("id") != oSettings.sTableId) + return true; + // Try to handle missing nodes more gracefully + if (document.getElementById(sFromId) == null) + return true; + var iMin = document.getElementById(sFromId).value * 1; + var iMax = document.getElementById(sToId).value * 1; + var iValue = aData[_fnColumnIndex(index)] == "-" ? 0 : aData[_fnColumnIndex(index)] * 1; + if (iMin == "" && iMax == "") { + return true; + } + else if (iMin == "" && iValue <= iMax) { + return true; + } + else if (iMin <= iValue && "" == iMax) { + return true; + } + else if (iMin <= iValue && iValue <= iMax) { + return true; + } + return false; + } + ); + //------------end range filtering function + + + + $('#' + sFromId + ',#' + sToId, th).keyup(function () { + + var iMin = document.getElementById(sFromId).value * 1; + var iMax = document.getElementById(sToId).value * 1; + if (iMin != 0 && iMax != 0 && iMin > iMax) + return; + + oTable.fnDraw(); + fnOnFiltered(); + }); + + + } + + + function fnCreateDateRangeInput(oTable) { + + var aoFragments = sRangeFormat.split(/[}{]/); + + th.html(""); + //th.html(_fnRangeLabelPart(0)); + var sFromId = oTable.attr("id") + '_range_from_' + i; + var from = $(''); + from.datepicker(); + //th.append(from); + //th.append(_fnRangeLabelPart(1)); + var sToId = oTable.attr("id") + '_range_to_' + i; + var to = $(''); + //th.append(to); + //th.append(_fnRangeLabelPart(2)); + + for (ti = 0; ti < aoFragments.length; ti++) { + + if (aoFragments[ti] == properties.sDateFromToken) { + th.append(from); + } else { + if (aoFragments[ti] == properties.sDateToToken) { + th.append(to); + } else { + th.append(aoFragments[ti]); + } + } + + + } + + + th.wrapInner(''); + to.datepicker(); + var index = i; + aiCustomSearch_Indexes.push(i); + + + //------------start date range filtering function + + //$.fn.dataTableExt.afnFiltering.push( + oTable.dataTableExt.afnFiltering.push( + function (oSettings, aData, iDataIndex) { + if (oTable.attr("id") != oSettings.sTableId) + return true; + + var dStartDate = from.datepicker("getDate"); + + var dEndDate = to.datepicker("getDate"); + + if (dStartDate == null && dEndDate == null) { + return true; + } + + var dCellDate = null; + try { + if (aData[_fnColumnIndex(index)] == null || aData[_fnColumnIndex(index)] == "") + return false; + dCellDate = $.datepicker.parseDate($.datepicker.regional[""].dateFormat, aData[_fnColumnIndex(index)]); + } catch (ex) { + return false; + } + if (dCellDate == null) + return false; + + + if (dStartDate == null && dCellDate <= dEndDate) { + return true; + } + else if (dStartDate <= dCellDate && dEndDate == null) { + return true; + } + else if (dStartDate <= dCellDate && dCellDate <= dEndDate) { + return true; + } + return false; + } + ); + //------------end date range filtering function + + $('#' + sFromId + ',#' + sToId, th).change(function () { + oTable.fnDraw(); + fnOnFiltered(); + }); + + + } + + function fnCreateColumnSelect(oTable, aData, iColumn, nTh, sLabel, bRegex, oSelected) { + if (aData == null) + aData = _fnGetColumnValues(oTable.fnSettings(), iColumn, true, false, true); + var index = iColumn; + var currentFilter = oTable.fnSettings().aoPreSearchCols[i].sSearch; + if (currentFilter == null || currentFilter == "")//Issue 81 + currentFilter = oSelected; + + var r = ''); + nTh.html(select); + nTh.wrapInner(''); + select.change(function () { + //var val = $(this).val(); + if ($(this).val() != "") { + $(this).removeClass("search_init"); + } else { + $(this).addClass("search_init"); + } + if (bRegex) + oTable.fnFilter($(this).val(), iColumn, bRegex); //Issue 41 + else + oTable.fnFilter(unescape($(this).val()), iColumn); //Issue 25 + fnOnFiltered(); + }); + if (currentFilter != null && currentFilter != "")//Issue 81 + oTable.fnFilter(unescape(currentFilter), iColumn); + } + + function fnCreateSelect(oTable, aData, bRegex, oSelected) { + var oSettings = oTable.fnSettings(); + if (aData == null && oSettings.sAjaxSource != "" && !oSettings.oFeatures.bServerSide) { + // Add a function to the draw callback, which will check for the Ajax data having + // been loaded. Use a closure for the individual column elements that are used to + // built the column filter, since 'i' and 'th' (etc) are locally "global". + oSettings.aoDrawCallback.push({ + "fn": (function (iColumn, nTh, sLabel) { + return function () { + // Only rebuild the select on the second draw - i.e. when the Ajax + // data has been loaded. + if (oSettings.iDraw == 2 && oSettings.sAjaxSource != null && oSettings.sAjaxSource != "" && !oSettings.oFeatures.bServerSide) { + return fnCreateColumnSelect(oTable, null, _fnColumnIndex(iColumn), nTh, sLabel, bRegex, oSelected); //Issue 37 + } + }; + })(i, th, label), + "sName": "column_filter_" + i + }); + } + // Regardless of the Ajax state, build the select on first pass + fnCreateColumnSelect(oTable, aData, _fnColumnIndex(i), th, label, bRegex, oSelected); //Issue 37 + + } + + function fnCreateCheckbox(oTable, aData) { + + if (aData == null) + aData = _fnGetColumnValues(oTable.fnSettings(), i, true, true, true); + var index = i; + + var r = '', j, iLen = aData.length; + + //clean the string + var localLabel = label.replace('%', 'Perc').replace("&", "AND").replace("$", "DOL").replace("?", "STERL").replace("@", "AT").replace(/\s/g, "_"); + localLabel = localLabel.replace(/[^a-zA-Z 0-9]+/g, ''); + //clean the string + + //button label override + var labelBtn = label; + if (properties.sFilterButtonText != null || properties.sFilterButtonText != undefined) { + labelBtn = properties.sFilterButtonText; + } + + var relativeDivWidthToggleSize = 10; + var numRow = 12; //numero di checkbox per colonna + var numCol = Math.floor(iLen / numRow); + if (iLen % numRow > 0) { + numCol = numCol + 1; + }; + + //count how many column should be generated and split the div size + var divWidth = 100 / numCol - 2; + + var divWidthToggle = relativeDivWidthToggleSize * numCol; + + if (numCol == 1) { + divWidth = 20; + } + + var divRowDef = '
    '; + var divClose = '
    '; + + var uniqueId = oTable.attr("id") + localLabel; + var buttonId = "chkBtnOpen" + uniqueId; + var checkToggleDiv = uniqueId + "-flt-toggle"; + r += ''; //filter button witch open dialog + r += '
    '; //dialog div + //r+= '
    '; //reset button and its div + r += divRowDef; + + for (j = 0; j < iLen; j++) { + + //if last check close div + if (j % numRow == 0 && j != 0) { + r += divClose + divRowDef; + } + + //check button + r += '' + aData[j] + '
    '; + + var checkbox = $(r); + th.html(checkbox); + th.wrapInner(''); + //on every checkbox selection + checkbox.change(function () { + + var search = ''; + var or = '|'; //var for select checks in 'or' into the regex + var resSize = $('input:checkbox[name="' + localLabel + '"]:checked').size(); + $('input:checkbox[name="' + localLabel + '"]:checked').each(function (index) { + + //search = search + ' ' + $(this).val(); + //concatenation for selected checks in or + if ((index == 0 && resSize == 1) + || (index != 0 && index == resSize - 1)) { + or = ''; + } + //trim + search = search.replace(/^\s+|\s+$/g, ""); + search = search + $(this).val() + or; + or = '|'; + + }); + + for (var jj = 0; jj < iLen; jj++) { + if (search != "") { + $('#' + aData[jj]).removeClass("search_init"); + } else { + $('#' + aData[jj]).addClass("search_init"); + } + } + + //execute search + oTable.fnFilter(search, index, true, false); + fnOnFiltered(); + }); + } + + //filter button + $('#' + buttonId).button(); + //dialog + $('#' + checkToggleDiv).dialog({ + //height: 140, + autoOpen: false, + //show: "blind", + hide: "blind", + buttons: [{ + text: "Reset", + click: function () { + //$('#'+buttonId).removeClass("filter_selected"); //LM remove border if filter selected + $('input:checkbox[name="' + localLabel + '"]:checked').each(function (index3) { + $(this).attr('checked', false); + $(this).addClass("search_init"); + }); + oTable.fnFilter('', index, true, false); + fnOnFiltered(); + return false; + } + }, + { + text: "Close", + click: function () { $(this).dialog("close"); } + } + ] + }); + + + $('#' + buttonId).click(function () { + + $('#' + checkToggleDiv).dialog('open'); + var target = $(this); + $('#' + checkToggleDiv).dialog("widget").position({ my: 'top', + at: 'bottom', + of: target + }); + + return false; + }); + + var fnOnFilteredCurrent = fnOnFiltered; + + fnOnFiltered = function () { + var target = $('#' + buttonId); + $('#' + checkToggleDiv).dialog("widget").position({ my: 'top', + at: 'bottom', + of: target + }); + fnOnFilteredCurrent(); + }; + //reset + /* + $('#'+buttonId+"Reset").button(); + $('#'+buttonId+"Reset").click(function(){ + $('#'+buttonId).removeClass("filter_selected"); //LM remove border if filter selected + $('input:checkbox[name="'+localLabel+'"]:checked').each(function(index3) { + $(this).attr('checked', false); + $(this).addClass("search_init"); + }); + oTable.fnFilter('', index, true, false); + return false; + }); + */ + } + + + + + function _fnRangeLabelPart(iPlace) { + switch (iPlace) { + case 0: + return sRangeFormat.substring(0, sRangeFormat.indexOf("{from}")); + case 1: + return sRangeFormat.substring(sRangeFormat.indexOf("{from}") + 6, sRangeFormat.indexOf("{to}")); + default: + return sRangeFormat.substring(sRangeFormat.indexOf("{to}") + 4); + } + } + + + + + var oTable = this; + + var defaults = { + sPlaceHolder: "foot", + sRangeSeparator: "~", + iFilteringDelay: 500, + aoColumns: null, + sRangeFormat: "From {from} to {to}", + sDateFromToken: "from", + sDateToToken: "to" + }; + + var properties = $.extend(defaults, options); + + return this.each(function () { + + if (!oTable.fnSettings().oFeatures.bFilter) + return; + asInitVals = new Array(); + + var aoFilterCells = oTable.fnSettings().aoFooter[0]; + + var oHost = oTable.fnSettings().nTFoot; //Before fix for ColVis + var sFilterRow = "tr"; //Before fix for ColVis + + if (properties.sPlaceHolder == "head:after") { + var tr = $("tr:first", oTable.fnSettings().nTHead).detach(); + //tr.appendTo($(oTable.fnSettings().nTHead)); + if (oTable.fnSettings().bSortCellsTop) { + tr.prependTo($(oTable.fnSettings().nTHead)); + //tr.appendTo($("thead", oTable)); + aoFilterCells = oTable.fnSettings().aoHeader[1]; + } + else { + tr.appendTo($(oTable.fnSettings().nTHead)); + //tr.prependTo($("thead", oTable)); + aoFilterCells = oTable.fnSettings().aoHeader[0]; + } + + sFilterRow = "tr:last"; + oHost = oTable.fnSettings().nTHead; + + } else if (properties.sPlaceHolder == "head:before") { + + if (oTable.fnSettings().bSortCellsTop) { + var tr = $("tr:first", oTable.fnSettings().nTHead).detach(); + tr.appendTo($(oTable.fnSettings().nTHead)); + aoFilterCells = oTable.fnSettings().aoHeader[1]; + } else { + aoFilterCells = oTable.fnSettings().aoHeader[0]; + } + /*else { + //tr.prependTo($("thead", oTable)); + sFilterRow = "tr:first"; + }*/ + + sFilterRow = "tr:first"; + + oHost = oTable.fnSettings().nTHead; + + + } + + //$(sFilterRow + " th", oHost).each(function (index) {//bug with ColVis + $(aoFilterCells).each(function (index) {//fix for ColVis + i = index; + var aoColumn = { type: "text", + bRegex: false, + bSmart: true, + iMaxLenght: -1, + iFilterLength: 0 + }; + if (properties.aoColumns != null) { + if (properties.aoColumns.length < i || properties.aoColumns[i] == null) + return; + aoColumn = properties.aoColumns[i]; + } + //label = $(this).text(); //Before fix for ColVis + label = $($(this)[0].cell).text(); //Fix for ColVis + if (aoColumn.sSelector == null) { + //th = $($(this)[0]);//Before fix for ColVis + th = $($(this)[0].cell); //Fix for ColVis + } + else { + th = $(aoColumn.sSelector); + if (th.length == 0) + th = $($(this)[0].cell); + } + + if (aoColumn != null) { + if (aoColumn.sRangeFormat != null) + sRangeFormat = aoColumn.sRangeFormat; + else + sRangeFormat = properties.sRangeFormat; + switch (aoColumn.type) { + case "null": + break; + case "number": + fnCreateInput(oTable, true, false, true, aoColumn.iFilterLength, aoColumn.iMaxLenght); + break; + case "select": + if (aoColumn.bRegex != true) + aoColumn.bRegex = false; + fnCreateSelect(oTable, aoColumn.values, aoColumn.bRegex, aoColumn.selected); + break; + case "number-range": + fnCreateRangeInput(oTable); + break; + case "date-range": + fnCreateDateRangeInput(oTable); + break; + case "checkbox": + fnCreateCheckbox(oTable, aoColumn.values); + break; + case "text": + default: + bRegex = (aoColumn.bRegex == null ? false : aoColumn.bRegex); + bSmart = (aoColumn.bSmart == null ? false : aoColumn.bSmart); + fnCreateInput(oTable, bRegex, bSmart, false, aoColumn.iFilterLength, aoColumn.iMaxLenght); + break; + + } + } + }); + + for (j = 0; j < aiCustomSearch_Indexes.length; j++) { + //var index = aiCustomSearch_Indexes[j]; + var fnSearch_ = function () { + var id = oTable.attr("id"); + return $("#" + id + "_range_from_" + aiCustomSearch_Indexes[j]).val() + properties.sRangeSeparator + $("#" + id + "_range_to_" + aiCustomSearch_Indexes[j]).val() + } + afnSearch_.push(fnSearch_); + } + + if (oTable.fnSettings().oFeatures.bServerSide) { + + var fnServerDataOriginal = oTable.fnSettings().fnServerData; + + oTable.fnSettings().fnServerData = function (sSource, aoData, fnCallback) { + + for (j = 0; j < aiCustomSearch_Indexes.length; j++) { + var index = aiCustomSearch_Indexes[j]; + + for (k = 0; k < aoData.length; k++) { + if (aoData[k].name == "sSearch_" + index) + aoData[k].value = afnSearch_[j](); + } + } + aoData.push({ "name": "sRangeSeparator", "value": properties.sRangeSeparator }); + + if (fnServerDataOriginal != null) { + try { + fnServerDataOriginal(sSource, aoData, fnCallback, oTable.fnSettings()); //TODO: See Issue 18 + } catch (ex) { + fnServerDataOriginal(sSource, aoData, fnCallback); + } + } + else { + $.getJSON(sSource, aoData, function (json) { + fnCallback(json) + }); + } + }; + + } + + }); + + }; + + + + +})(jQuery); diff --git a/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.min.js b/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.min.js new file mode 100644 index 0000000..02694a4 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/lib/jquery/plugins/jquery.dataTables.min.js @@ -0,0 +1,155 @@ +/* + * File: jquery.dataTables.min.js + * Version: 1.9.4 + * Author: Allan Jardine (www.sprymedia.co.uk) + * Info: www.datatables.net + * + * Copyright 2008-2012 Allan Jardine, all rights reserved. + * + * This source file is free software, under either the GPL v2 license or a + * BSD style license, available at: + * http://datatables.net/license_gpl2 + * http://datatables.net/license_bsd + * + * This source file 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 license files for details. + */ +(function(X,l,n){var L=function(h){var j=function(e){function o(a,b){var c=j.defaults.columns,d=a.aoColumns.length,c=h.extend({},j.models.oColumn,c,{sSortingClass:a.oClasses.sSortable,sSortingClassJUI:a.oClasses.sSortJUI,nTh:b?b:l.createElement("th"),sTitle:c.sTitle?c.sTitle:b?b.innerHTML:"",aDataSort:c.aDataSort?c.aDataSort:[d],mData:c.mData?c.oDefaults:d});a.aoColumns.push(c);if(a.aoPreSearchCols[d]===n||null===a.aoPreSearchCols[d])a.aoPreSearchCols[d]=h.extend({},j.models.oSearch);else if(c=a.aoPreSearchCols[d], +c.bRegex===n&&(c.bRegex=!0),c.bSmart===n&&(c.bSmart=!0),c.bCaseInsensitive===n)c.bCaseInsensitive=!0;m(a,d,null)}function m(a,b,c){var d=a.aoColumns[b];c!==n&&null!==c&&(c.mDataProp&&!c.mData&&(c.mData=c.mDataProp),c.sType!==n&&(d.sType=c.sType,d._bAutoType=!1),h.extend(d,c),p(d,c,"sWidth","sWidthOrig"),c.iDataSort!==n&&(d.aDataSort=[c.iDataSort]),p(d,c,"aDataSort"));var i=d.mRender?Q(d.mRender):null,f=Q(d.mData);d.fnGetData=function(a,b){var c=f(a,b);return d.mRender&&b&&""!==b?i(c,b,a):c};d.fnSetData= +L(d.mData);a.oFeatures.bSort||(d.bSortable=!1);!d.bSortable||-1==h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortableNone,d.sSortingClassJUI=""):-1==h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortable,d.sSortingClassJUI=a.oClasses.sSortJUI):-1!=h.inArray("asc",d.asSorting)&&-1==h.inArray("desc",d.asSorting)?(d.sSortingClass=a.oClasses.sSortableAsc,d.sSortingClassJUI=a.oClasses.sSortJUIAscAllowed):-1== +h.inArray("asc",d.asSorting)&&-1!=h.inArray("desc",d.asSorting)&&(d.sSortingClass=a.oClasses.sSortableDesc,d.sSortingClassJUI=a.oClasses.sSortJUIDescAllowed)}function k(a){if(!1===a.oFeatures.bAutoWidth)return!1;da(a);for(var b=0,c=a.aoColumns.length;bj[f])d(a.aoColumns.length+j[f],b[i]);else if("string"===typeof j[f]){e=0;for(w=a.aoColumns.length;eb&&a[d]--; -1!=c&&a.splice(c,1)}function S(a,b,c){var d=a.aoColumns[c];return d.fnRender({iDataRow:b,iDataColumn:c,oSettings:a,aData:a.aoData[b]._aData,mDataProp:d.mData},v(a,b,c,"display"))}function ea(a,b){var c=a.aoData[b],d;if(null===c.nTr){c.nTr=l.createElement("tr");c.nTr._DT_RowIndex=b;c._aData.DT_RowId&&(c.nTr.id=c._aData.DT_RowId);c._aData.DT_RowClass&& +(c.nTr.className=c._aData.DT_RowClass);for(var i=0,f=a.aoColumns.length;i=a.fnRecordsDisplay()?0:a.iInitDisplayStart,a.iInitDisplayStart=-1,y(a));if(a.bDeferLoading)a.bDeferLoading=!1,a.iDraw++;else if(a.oFeatures.bServerSide){if(!a.bDestroying&&!wa(a))return}else a.iDraw++;if(0!==a.aiDisplay.length){var g= +a._iDisplayStart;d=a._iDisplayEnd;a.oFeatures.bServerSide&&(g=0,d=a.aoData.length);for(;g
    ")[0];a.nTable.parentNode.insertBefore(b,a.nTable);a.nTableWrapper=h('
    ')[0];a.nTableReinsertBefore=a.nTable.nextSibling;for(var c=a.nTableWrapper,d=a.sDom.split(""),i,f,g,e,w,o,k,m=0;m
    ")[0];w=d[m+ +1];if("'"==w||'"'==w){o="";for(k=2;d[m+k]!=w;)o+=d[m+k],k++;"H"==o?o=a.oClasses.sJUIHeader:"F"==o&&(o=a.oClasses.sJUIFooter);-1!=o.indexOf(".")?(w=o.split("."),e.id=w[0].substr(1,w[0].length-1),e.className=w[1]):"#"==o.charAt(0)?e.id=o.substr(1,o.length-1):e.className=o;m+=k}c.appendChild(e);c=e}else if(">"==g)c=c.parentNode;else if("l"==g&&a.oFeatures.bPaginate&&a.oFeatures.bLengthChange)i=ya(a),f=1;else if("f"==g&&a.oFeatures.bFilter)i=za(a),f=1;else if("r"==g&&a.oFeatures.bProcessing)i=Aa(a),f= +1;else if("t"==g)i=Ba(a),f=1;else if("i"==g&&a.oFeatures.bInfo)i=Ca(a),f=1;else if("p"==g&&a.oFeatures.bPaginate)i=Da(a),f=1;else if(0!==j.ext.aoFeatures.length){e=j.ext.aoFeatures;k=0;for(w=e.length;k'):""===c?'':c+' ',d=l.createElement("div");d.className=a.oClasses.sFilter;d.innerHTML="";a.aanFeatures.f||(d.id=a.sTableId+"_filter");c=h('input[type="text"]',d);d._DT_Input=c[0];c.val(b.sSearch.replace('"',"""));c.bind("keyup.DT",function(){for(var c=a.aanFeatures.f,d=this.value===""?"":this.value, +g=0,e=c.length;g=b.length)a.aiDisplay.splice(0,a.aiDisplay.length),a.aiDisplay=a.aiDisplayMaster.slice();else if(a.aiDisplay.length==a.aiDisplayMaster.length||i.sSearch.length>b.length||1==c||0!==b.indexOf(i.sSearch)){a.aiDisplay.splice(0, +a.aiDisplay.length);la(a,1);for(b=0;b").html(c).text()); +return c.replace(/[\n\r]/g," ")}function ma(a,b,c,d){if(c)return a=b?a.split(" "):oa(a).split(" "),a="^(?=.*?"+a.join(")(?=.*?")+").*$",RegExp(a,d?"i":"");a=b?a:oa(a);return RegExp(a,d?"i":"")}function Ja(a,b){return"function"===typeof j.ext.ofnSearch[b]?j.ext.ofnSearch[b](a):null===a?"":"html"==b?a.replace(/[\r\n]/g," ").replace(/<.*?>/g,""):"string"===typeof a?a.replace(/[\r\n]/g," "):a}function oa(a){return a.replace(RegExp("(\\/|\\.|\\*|\\+|\\?|\\||\\(|\\)|\\[|\\]|\\{|\\}|\\\\|\\$|\\^|\\-)","g"), +"\\$1")}function Ca(a){var b=l.createElement("div");b.className=a.oClasses.sInfo;a.aanFeatures.i||(a.aoDrawCallback.push({fn:Ka,sName:"information"}),b.id=a.sTableId+"_info");a.nTable.setAttribute("aria-describedby",a.sTableId+"_info");return b}function Ka(a){if(a.oFeatures.bInfo&&0!==a.aanFeatures.i.length){var b=a.oLanguage,c=a._iDisplayStart+1,d=a.fnDisplayEnd(),i=a.fnRecordsTotal(),f=a.fnRecordsDisplay(),g;g=0===f?b.sInfoEmpty:b.sInfo;f!=i&&(g+=" "+b.sInfoFiltered);g+=b.sInfoPostFix;g=ja(a,g); +null!==b.fnInfoCallback&&(g=b.fnInfoCallback.call(a.oInstance,a,c,d,i,f,g));a=a.aanFeatures.i;b=0;for(c=a.length;b",c,d,i=a.aLengthMenu;if(2==i.length&&"object"===typeof i[0]&&"object"===typeof i[1]){c=0;for(d=i[0].length;c'+i[1][c]+""}else{c=0;for(d=i.length;c'+i[c]+""}b+="";i=l.createElement("div");a.aanFeatures.l|| +(i.id=a.sTableId+"_length");i.className=a.oClasses.sLength;i.innerHTML="";h('select option[value="'+a._iDisplayLength+'"]',i).attr("selected",!0);h("select",i).bind("change.DT",function(){var b=h(this).val(),i=a.aanFeatures.l;c=0;for(d=i.length;ca.aiDisplay.length||-1==a._iDisplayLength?a.aiDisplay.length:a._iDisplayStart+a._iDisplayLength}function Da(a){if(a.oScroll.bInfinite)return null;var b=l.createElement("div");b.className=a.oClasses.sPaging+a.sPaginationType;j.ext.oPagination[a.sPaginationType].fnInit(a, +b,function(a){y(a);x(a)});a.aanFeatures.p||a.aoDrawCallback.push({fn:function(a){j.ext.oPagination[a.sPaginationType].fnUpdate(a,function(a){y(a);x(a)})},sName:"pagination"});return b}function qa(a,b){var c=a._iDisplayStart;if("number"===typeof b)a._iDisplayStart=b*a._iDisplayLength,a._iDisplayStart>a.fnRecordsDisplay()&&(a._iDisplayStart=0);else if("first"==b)a._iDisplayStart=0;else if("previous"==b)a._iDisplayStart=0<=a._iDisplayLength?a._iDisplayStart-a._iDisplayLength:0,0>a._iDisplayStart&&(a._iDisplayStart= +0);else if("next"==b)0<=a._iDisplayLength?a._iDisplayStart+a._iDisplayLengthh(a.nTable).height()-a.oScroll.iLoadGap&&a.fnDisplayEnd()d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(h(a.nTable).outerWidth()-a.oScroll.iBarWidth)}else""!==a.oScroll.sXInner?a.nTable.style.width= +q(a.oScroll.sXInner):i==h(d).width()&&h(d).height()i-a.oScroll.iBarWidth&&(a.nTable.style.width=q(i))):a.nTable.style.width=q(i);i=h(a.nTable).outerWidth();C(s,e);C(function(a){p.push(q(h(a).width()))},e);C(function(a,b){a.style.width=p[b]},g);h(e).height(0);null!==a.nTFoot&&(C(s,j),C(function(a){n.push(q(h(a).width()))},j),C(function(a,b){a.style.width=n[b]},o),h(j).height(0));C(function(a,b){a.innerHTML= +"";a.style.width=p[b]},e);null!==a.nTFoot&&C(function(a,b){a.innerHTML="";a.style.width=n[b]},j);if(h(a.nTable).outerWidth()d.offsetHeight||"scroll"==h(d).css("overflow-y")?i+a.oScroll.iBarWidth:i;if(r&&(d.scrollHeight>d.offsetHeight||"scroll"==h(d).css("overflow-y")))a.nTable.style.width=q(g-a.oScroll.iBarWidth);d.style.width=q(g);a.nScrollHead.style.width=q(g);null!==a.nTFoot&&(a.nScrollFoot.style.width=q(g));""===a.oScroll.sX?D(a,1,"The table cannot fit into the current element which will cause column misalignment. The table has been drawn at its minimum possible width."): +""!==a.oScroll.sXInner&&D(a,1,"The table cannot fit into the current element which will cause column misalignment. Increase the sScrollXInner value or remove it to allow automatic calculation")}else d.style.width=q("100%"),a.nScrollHead.style.width=q("100%"),null!==a.nTFoot&&(a.nScrollFoot.style.width=q("100%"));""===a.oScroll.sY&&r&&(d.style.height=q(a.nTable.offsetHeight+a.oScroll.iBarWidth));""!==a.oScroll.sY&&a.oScroll.bCollapse&&(d.style.height=q(a.oScroll.sY),r=""!==a.oScroll.sX&&a.nTable.offsetWidth> +d.offsetWidth?a.oScroll.iBarWidth:0,a.nTable.offsetHeightd.clientHeight||"scroll"==h(d).css("overflow-y");b.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px";null!==a.nTFoot&&(R.style.width=q(r),l.style.width=q(r),l.style.paddingRight=c?a.oScroll.iBarWidth+"px":"0px");h(d).scroll();if(a.bSorted||a.bFiltered)d.scrollTop=0}function C(a,b,c){for(var d= +0,i=0,f=b.length,g,e;itd",b));j=N(a,f);for(f=d=0;fc)return null;if(null===a.aoData[c].nTr){var d=l.createElement("td");d.innerHTML=v(a,c,b,"");return d}return J(a,c)[b]}function Pa(a,b){for(var c=-1,d=-1,i=0;i/g,"");e.length>c&&(c=e.length,d=i)}return d}function q(a){if(null===a)return"0px";if("number"==typeof a)return 0>a?"0px":a+"px";var b=a.charCodeAt(a.length-1); +return 48>b||57/g,""),i=q[c].nTh,i.removeAttribute("aria-sort"),i.removeAttribute("aria-label"),q[c].bSortable?0d&&d++;f=RegExp(f+"[123]");var o;b=0;for(c=a.length;b
    ')[0];l.body.appendChild(b);a.oBrowser.bScrollOversize= +100===h("#DT_BrowserTest",b)[0].offsetWidth?!0:!1;l.body.removeChild(b)}function Va(a){return function(){var b=[s(this[j.ext.iApiIndex])].concat(Array.prototype.slice.call(arguments));return j.ext.oApi[a].apply(this,b)}}var U=/\[.*?\]$/,Wa=X.JSON?JSON.stringify:function(a){var b=typeof a;if("object"!==b||null===a)return"string"===b&&(a='"'+a+'"'),a+"";var c,d,e=[],f=h.isArray(a);for(c in a)d=a[c],b=typeof d,"string"===b?d='"'+d+'"':"object"===b&&null!==d&&(d=Wa(d)),e.push((f?"":'"'+c+'":')+d);return(f? +"[":"{")+e+(f?"]":"}")};this.$=function(a,b){var c,d,e=[],f;d=s(this[j.ext.iApiIndex]);var g=d.aoData,o=d.aiDisplay,k=d.aiDisplayMaster;b||(b={});b=h.extend({},{filter:"none",order:"current",page:"all"},b);if("current"==b.page){c=d._iDisplayStart;for(d=d.fnDisplayEnd();c=d.fnRecordsDisplay()&&(d._iDisplayStart-=d._iDisplayLength,0>d._iDisplayStart&&(d._iDisplayStart=0));if(c===n||c)y(d),x(d);return g};this.fnDestroy=function(a){var b=s(this[j.ext.iApiIndex]),c=b.nTableWrapper.parentNode,d=b.nTBody,i,f,a=a===n?!1:a;b.bDestroying=!0;A(b,"aoDestroyCallback","destroy",[b]);if(!a){i=0;for(f=b.aoColumns.length;itr>td."+b.oClasses.sRowEmpty,b.nTable).parent().remove();b.nTable!=b.nTHead.parentNode&&(h(b.nTable).children("thead").remove(),b.nTable.appendChild(b.nTHead));b.nTFoot&&b.nTable!=b.nTFoot.parentNode&&(h(b.nTable).children("tfoot").remove(),b.nTable.appendChild(b.nTFoot));b.nTable.parentNode.removeChild(b.nTable);h(b.nTableWrapper).remove();b.aaSorting=[];b.aaSortingFixed=[];P(b);h(T(b)).removeClass(b.asStripeClasses.join(" "));h("th, td",b.nTHead).removeClass([b.oClasses.sSortable,b.oClasses.sSortableAsc, +b.oClasses.sSortableDesc,b.oClasses.sSortableNone].join(" "));b.bJUI&&(h("th span."+b.oClasses.sSortIcon+", td span."+b.oClasses.sSortIcon,b.nTHead).remove(),h("th, td",b.nTHead).each(function(){var a=h("div."+b.oClasses.sSortJUIWrapper,this),c=a.contents();h(this).append(c);a.remove()}));!a&&b.nTableReinsertBefore?c.insertBefore(b.nTable,b.nTableReinsertBefore):a||c.appendChild(b.nTable);i=0;for(f=b.aoData.length;i=t(d);if(!m)for(e=a;et<"F"ip>')):h.extend(g.oClasses,j.ext.oStdClasses);h(this).addClass(g.oClasses.sTable);if(""!==g.oScroll.sX||""!==g.oScroll.sY)g.oScroll.iBarWidth=Qa();g.iInitDisplayStart===n&&(g.iInitDisplayStart=e.iDisplayStart, +g._iDisplayStart=e.iDisplayStart);e.bStateSave&&(g.oFeatures.bStateSave=!0,Sa(g,e),z(g,"aoDrawCallback",ra,"state_save"));null!==e.iDeferLoading&&(g.bDeferLoading=!0,a=h.isArray(e.iDeferLoading),g._iRecordsDisplay=a?e.iDeferLoading[0]:e.iDeferLoading,g._iRecordsTotal=a?e.iDeferLoading[1]:e.iDeferLoading);null!==e.aaData&&(f=!0);""!==e.oLanguage.sUrl?(g.oLanguage.sUrl=e.oLanguage.sUrl,h.getJSON(g.oLanguage.sUrl,null,function(a){pa(a);h.extend(true,g.oLanguage,e.oLanguage,a);ba(g)}),i=!0):h.extend(!0, +g.oLanguage,e.oLanguage);null===e.asStripeClasses&&(g.asStripeClasses=[g.oClasses.sStripeOdd,g.oClasses.sStripeEven]);b=g.asStripeClasses.length;g.asDestroyStripes=[];if(b){c=!1;d=h(this).children("tbody").children("tr:lt("+b+")");for(a=0;a=g.aoColumns.length&&(g.aaSorting[a][0]=0);var k=g.aoColumns[g.aaSorting[a][0]];g.aaSorting[a][2]===n&&(g.aaSorting[a][2]=0);e.aaSorting===n&&g.saved_aaSorting===n&&(g.aaSorting[a][1]= +k.asSorting[0]);c=0;for(d=k.asSorting.length;c=parseInt(n,10)};j.fnIsDataTable=function(e){for(var h=j.settings,m=0;me)return e;for(var h=e+"",e=h.split(""),j="",h=h.length,k=0;k'+k.sPrevious+''+k.sNext+"":'';h(j).append(k);var l=h("a",j), +k=l[0],l=l[1];e.oApi._fnBindAction(k,{action:"previous"},n);e.oApi._fnBindAction(l,{action:"next"},n);e.aanFeatures.p||(j.id=e.sTableId+"_paginate",k.id=e.sTableId+"_previous",l.id=e.sTableId+"_next",k.setAttribute("aria-controls",e.sTableId),l.setAttribute("aria-controls",e.sTableId))},fnUpdate:function(e){if(e.aanFeatures.p)for(var h=e.oClasses,j=e.aanFeatures.p,k,l=0,n=j.length;l'+k.sFirst+''+k.sPrevious+''+k.sNext+''+k.sLast+"");var t=h("a",j),k=t[0],l=t[1],r=t[2],t=t[3];e.oApi._fnBindAction(k,{action:"first"},n);e.oApi._fnBindAction(l,{action:"previous"},n);e.oApi._fnBindAction(r,{action:"next"},n);e.oApi._fnBindAction(t,{action:"last"},n);e.aanFeatures.p||(j.id=e.sTableId+"_paginate",k.id=e.sTableId+"_first",l.id=e.sTableId+"_previous",r.id=e.sTableId+"_next",t.id=e.sTableId+"_last")}, +fnUpdate:function(e,o){if(e.aanFeatures.p){var m=j.ext.oPagination.iFullNumbersShowPages,k=Math.floor(m/2),l=Math.ceil(e.fnRecordsDisplay()/e._iDisplayLength),n=Math.ceil(e._iDisplayStart/e._iDisplayLength)+1,t="",r,B=e.oClasses,u,M=e.aanFeatures.p,L=function(h){e.oApi._fnBindAction(this,{page:h+r-1},function(h){e.oApi._fnPageChange(e,h.data.page);o(e);h.preventDefault()})};-1===e._iDisplayLength?n=k=r=1:l=l-k?(r=l-m+1,k=l):(r=n-Math.ceil(m/2)+1,k=r+m-1);for(m=r;m<=k;m++)t+= +n!==m?''+e.fnFormatNumber(m)+"":''+e.fnFormatNumber(m)+"";m=0;for(k=M.length;mh?1:0},"string-desc":function(e,h){return eh?-1:0},"html-pre":function(e){return e.replace(/<.*?>/g,"").toLowerCase()},"html-asc":function(e,h){return eh?1:0},"html-desc":function(e,h){return e< +h?1:e>h?-1:0},"date-pre":function(e){e=Date.parse(e);if(isNaN(e)||""===e)e=Date.parse("01/01/1970 00:00:00");return e},"date-asc":function(e,h){return e-h},"date-desc":function(e,h){return h-e},"numeric-pre":function(e){return"-"==e||""===e?0:1*e},"numeric-asc":function(e,h){return e-h},"numeric-desc":function(e,h){return h-e}});h.extend(j.ext.aTypes,[function(e){if("number"===typeof e)return"numeric";if("string"!==typeof e)return null;var h,j=!1;h=e.charAt(0);if(-1=="0123456789-".indexOf(h))return null; +for(var k=1;k")?"html":null}]);h.fn.DataTable=j;h.fn.dataTable=j;h.fn.dataTableSettings=j.settings;h.fn.dataTableExt=j.ext};"function"===typeof define&&define.amd?define(["jquery"],L):jQuery&&!jQuery.fn.dataTable&& +L(jQuery)})(window,document); diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/datatables.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/datatables.inc new file mode 100644 index 0000000..703d1e3 --- /dev/null +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/datatables.inc @@ -0,0 +1,20 @@ + + + \ No newline at end of file diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/acqui-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/acqui-home.tt index 34aa8e9..2ee9d0b 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/acqui-home.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/acqui-home.tt @@ -2,9 +2,7 @@ Koha › Acquisitions [% INCLUDE 'doc-head-close.inc' %] - -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - - +[% INCLUDE 'datatables.inc' %] - +[% INCLUDE 'datatables.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt index 525ea66..dff9957 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt @@ -8,9 +8,7 @@ } - -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] [% INCLUDE 'calendar.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] [% INCLUDE 'calendar.inc' %] - -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] [% INCLUDE 'greybox.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] + + \ No newline at end of file diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/acqui-home.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/acqui-home.tt index 34aa8e9..2ee9d0b 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/acqui-home.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/acqui-home.tt @@ -2,9 +2,7 @@ Koha › Acquisitions [% INCLUDE 'doc-head-close.inc' %] - -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - - +[% INCLUDE 'datatables.inc' %] - +[% INCLUDE 'datatables.inc' %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt index 525ea66..dff9957 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/acqui/booksellers.tt @@ -8,9 +8,7 @@ } - -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] [% INCLUDE 'calendar.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] [% INCLUDE 'calendar.inc' %] - -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] [% INCLUDE 'greybox.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] -[% INCLUDE 'datatables-strings.inc' %] - +[% INCLUDE 'datatables.inc' %] +[% END %] [% IF ( op_else ) %] @@ -135,12 +149,13 @@ $(document).ready(function() { [% ELSE %] - +[% END %] +[% IF ( op_save ) %] + [% END %] @@ -150,12 +165,13 @@ $(document).ready(function() { calcNewsuggTotal(); });