Bug 19493: Remove few warnings from circulation.pl
[koha.git] / circ / overdue.pl
index e59961a..eea9e05 100755 (executable)
@@ -6,52 +6,59 @@
 #
 # 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 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 3 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.
+# 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 should have received a copy of the GNU General Public License
+# along with Koha; if not, see <http://www.gnu.org/licenses>.
 
-use strict;
-use warnings;
+use Modern::Perl;
 use C4::Context;
 use C4::Output;
-use CGI qw(-oldstyle_urls);
+use CGI qw(-oldstyle_urls -utf8);
 use C4::Auth;
-use C4::Branch;
 use C4::Debug;
-use C4::Dates qw/format_date format_date_in_iso/;
-use Date::Calc qw/Today/;
 use Text::CSV_XS;
+use Koha::DateUtils;
+use DateTime;
+use DateTime::Format::MySQL;
 
 my $input = new CGI;
-my $order           = $input->param('order') || '';
 my $showall         = $input->param('showall');
 my $bornamefilter   = $input->param('borname') || '';
 my $borcatfilter    = $input->param('borcat') || '';
 my $itemtypefilter  = $input->param('itemtype') || '';
 my $borflagsfilter  = $input->param('borflag') || '';
 my $branchfilter    = $input->param('branch') || '';
+my $homebranchfilter    = $input->param('homebranch') || '';
+my $holdingbranchfilter = $input->param('holdingbranch') || '';
 my $op              = $input->param('op') || '';
-my $dateduefrom = format_date_in_iso($input->param( 'dateduefrom' )) || '';
-my $datedueto   = format_date_in_iso($input->param( 'datedueto' )) || '';
+
+my ($dateduefrom, $datedueto);
+if ( $dateduefrom = $input->param('dateduefrom') ) {
+    $dateduefrom = dt_from_string( $dateduefrom );
+}
+if ( $datedueto = $input->param('datedueto') ) {
+    $datedueto = dt_from_string( $datedueto )->set_hour(23)->set_minute(59);
+}
+
 my $isfiltered      = $op =~ /apply/i && $op =~ /filter/i;
 my $noreport        = C4::Context->preference('FilterBeforeOverdueReport') && ! $isfiltered && $op ne "csv";
 
 my ( $template, $loggedinuser, $cookie ) = get_template_and_user(
     {
-        template_name   => "circ/overdue.tmpl",
+        template_name   => "circ/overdue.tt",
         query           => $input,
         type            => "intranet",
         authnotrequired => 0,
-        flagsrequired   => { reports => 1, circulate => "circulate_remaining_permissions" },
+        flagsrequired   => { circulate => "overdues_report" },
         debug           => 1,
     }
 );
@@ -80,12 +87,6 @@ while (my ($itemtype, $description) =$req->fetchrow) {
         itemtypename => $description,
     };
 }
-my $onlymine=C4::Context->preference('IndependantBranches') && 
-             C4::Context->userenv &&
-             C4::Context->userenv->{flags} % 2 !=1 &&
-             C4::Context->userenv->{branch};
-
-$branchfilter = C4::Context->userenv->{'branch'} if ($onlymine && !$branchfilter);
 
 # Filtering by Patron Attributes
 #  @patron_attr_filter_loop        is non empty if there are any patron attribute filters
@@ -93,8 +94,8 @@ $branchfilter = C4::Context->userenv->{'branch'} if ($onlymine && !$branchfilter
 #  %borrowernumber_to_attributes   is populated by those borrowernumbers matching the patron attribute filters
 
 my %cgi_attrcode_to_attrvalues;     # ( patron_attribute_code => [ zero or more attribute filter values from the CGI ] )
-for my $attrcode (grep { /^patron_attr_filter_/ } $input->param) {
-    if (my @attrvalues = grep { length($_) > 0 } $input->param($attrcode)) {
+for my $attrcode (grep { /^patron_attr_filter_/ } $input->multi_param) {
+    if (my @attrvalues = grep { length($_) > 0 } $input->multi_param($attrcode)) {
         $attrcode =~ s/^patron_attr_filter_//;
         $cgi_attrcode_to_attrvalues{$attrcode} = \@attrvalues;
         print STDERR ">>>param($attrcode)[@{[scalar @attrvalues]}] = '@attrvalues'\n" if $debug;
@@ -103,20 +104,6 @@ for my $attrcode (grep { /^patron_attr_filter_/ } $input->param) {
 my $have_pattr_filter_data = keys(%cgi_attrcode_to_attrvalues) > 0;
 
 my @patron_attr_filter_loop;   # array of [ domid cgivalue ismany isclone ordinal code description repeatable authorised_value_category ]
-my @patron_attr_order_loop;    # array of { label => $patron_attr_label, value => $patron_attr_order }
-
-my @sort_roots = qw(borrower title barcode date_due);
-push @sort_roots, map {$_ . " desc"} @sort_roots;
-my @order_loop = ({selected => $order ? 0 : 1});   # initial blank row
-foreach (@sort_roots) {
-    my $tmpl_name = $_;
-    $tmpl_name =~ s/\s/_/g;
-    push @order_loop, {
-        selected => $order eq $_ ? 1 : 0,
-        ordervalue => $_,
-        'order_' . $tmpl_name => 1,
-    };
-}
 
 my $sth = $dbh->prepare('SELECT code,description,repeatable,authorised_value_category
     FROM borrower_attribute_types
@@ -137,19 +124,7 @@ while (my $row = $sth->fetchrow_hashref) {
         $row->{isclone} = $isclone;
         push @patron_attr_filter_loop, { %$row };  # careful: must store a *deep copy* of the modified row
     } continue { $isclone = 1, ++$serial }
-    foreach my $sortorder ('asc', 'desc') {
-        my $ordervalue = "patron_attr_${sortorder}_${code}";
-        push @order_loop, {
-            selected => $order eq $ordervalue ? 1 : 0,
-            ordervalue => $ordervalue,
-            label => $row->{description},
-            $sortorder => 1,
-        };
-    }
 } continue { ++$ordinal }
-for (@patron_attr_order_loop) { $_->{selected} = 1 if $order eq $_->{value} }
-
-$template->param(ORDER_LOOP => \@order_loop);
 
 my %borrowernumber_to_attributes;    # hash of { borrowernumber => { attrcode => [ [val,display], [val,display], ... ] } }
                                      #   i.e. val differs from display when attr is an authorised value
@@ -204,17 +179,16 @@ if (@patron_attr_filter_loop) {
 
 $template->param(
     patron_attr_header_loop => [ map { { header => $_->{description} } } grep { ! $_->{isclone} } @patron_attr_filter_loop ],
-    branchloop   => GetBranchesLoop($branchfilter, $onlymine),
     branchfilter => $branchfilter,
+    homebranchfilter => $homebranchfilter,
+    holdingbranchfilter => $homebranchfilter,
     borcatloop=> \@borcatloop,
     itemtypeloop => \@itemtypeloop,
     patron_attr_filter_loop => \@patron_attr_filter_loop,
     borname => $bornamefilter,
-    order => $order,
     showall => $showall,
-    DHTMLcalendar_dateformat => C4::Dates->DHTMLcalendar(),
-    dateduefrom => $input->param( 'dateduefrom' ) || '',
-    datedueto   => $input->param( 'datedueto' ) || '',
+    dateduefrom => $dateduefrom,
+    datedueto   => $datedueto,
 );
 
 if ($noreport) {
@@ -229,7 +203,9 @@ if ($noreport) {
     #  FIX 2: ensure there are indexes for columns participating in the WHERE clauses, where feasible/reasonable
 
 
-    my $todaysdate = sprintf("%-04.4d-%-02.2d-%02.2d", Today());
+    my $today_dt = DateTime->now(time_zone => C4::Context->tz);
+    $today_dt->truncate(to => 'minute');
+    my $todaysdate = $today_dt->strftime('%Y-%m-%d %H:%M');
 
     $bornamefilter =~s/\*/\%/g;
     $bornamefilter =~s/\?/\_/g;
@@ -247,16 +223,20 @@ if ($noreport) {
         borrowers.country,
         borrowers.phone,
         borrowers.email,
+        borrowers.cardnumber,
         issues.itemnumber,
         issues.issuedate,
         items.barcode,
+        items.homebranch,
+        items.holdingbranch,
         biblio.title,
         biblio.author,
         borrowers.borrowernumber,
         biblio.biblionumber,
         borrowers.branchcode,
         items.itemcallnumber,
-        items.replacementprice
+        items.replacementprice,
+        items.enumchron
       FROM issues
     LEFT JOIN borrowers   ON (issues.borrowernumber=borrowers.borrowernumber )
     LEFT JOIN items       ON (issues.itemnumber=items.itemnumber)
@@ -274,26 +254,31 @@ if ($noreport) {
             $strsth.=" AND biblioitems.itemtype   = '" . $itemtypefilter . "' ";
         }
     }
-    $strsth.=" AND borrowers.flags        = '" . $borflagsfilter . "' " if $borflagsfilter;
+    if ( $borflagsfilter eq 'gonenoaddress' ) {
+        $strsth .= " AND borrowers.gonenoaddress <> 0";
+    }
+    elsif ( $borflagsfilter eq 'debarred' ) {
+        $strsth .= " AND borrowers.debarred >=  CURDATE()" ;
+    }
+    elsif ( $borflagsfilter eq 'lost') {
+        $strsth .= " AND borrowers.lost <> 0";
+    }
     $strsth.=" AND borrowers.branchcode   = '" . $branchfilter   . "' " if $branchfilter;
-    $strsth.=" AND date_due < '" . $datedueto . "' "  if $datedueto;
-    $strsth.=" AND date_due > '" . $dateduefrom . "' " if $dateduefrom;
+    $strsth.=" AND items.homebranch       = '" . $homebranchfilter . "' " if $homebranchfilter;
+    $strsth.=" AND items.holdingbranch    = '" . $holdingbranchfilter . "' " if $holdingbranchfilter;
+    $strsth.=" AND date_due >= ?" if $dateduefrom;
+    $strsth.=" AND date_due <= ?" if $datedueto;
     # restrict patrons (borrowers) to those matching the patron attribute filter(s), if any
     my $bnlist = $have_pattr_filter_data ? join(',',keys %borrowernumber_to_attributes) : '';
     $strsth =~ s/WHERE 1=1/WHERE 1=1 AND borrowers.borrowernumber IN ($bnlist)/ if $bnlist;
     $strsth =~ s/WHERE 1=1/WHERE 0=1/ if $have_pattr_filter_data  && !$bnlist;  # no match if no borrowers matched patron attrs
-    $strsth.=" ORDER BY " . (
-        ($order eq "borrower")                              ? "surname, firstname, date_due"               : 
-        ($order eq "borrower desc")                         ? "surname desc, firstname desc, date_due"     : 
-        ($order eq "title"    or $order eq    "title desc") ? "$order, date_due, surname, firstname"       :
-        ($order eq "barcode"  or $order eq  "barcode desc") ? "items.$order, date_due, surname, firstname" :
-                                ($order eq "date_due desc") ? "date_due DESC, surname, firstname"          :
-                                                            "date_due, surname, firstname"  # default sort order
-    );
+    $strsth.=" ORDER BY date_due, surname, firstname";
     $template->param(sql=>$strsth);
     my $sth=$dbh->prepare($strsth);
-    #warn "overdue.pl : query string ".$strsth;
-    $sth->execute();
+    $sth->execute(
+        ($dateduefrom ? DateTime::Format::MySQL->format_datetime($dateduefrom) : ()),
+        ($datedueto ? DateTime::Format::MySQL->format_datetime($datedueto) : ()),
+    );
 
     my @overduedata;
     while (my $data = $sth->fetchrow_hashref) {
@@ -311,11 +296,12 @@ if ($noreport) {
         }
 
         push @overduedata, {
-            duedate                => format_date($data->{date_due}),
+            duedate                => $data->{date_due},
             borrowernumber         => $data->{borrowernumber},
             barcode                => $data->{barcode},
+            cardnumber             => $data->{cardnumber},
             itemnum                => $data->{itemnumber},
-            issuedate              => format_date($data->{issuedate}),
+            issuedate              => output_pref({ dt => dt_from_string( $data->{issuedate} ), dateonly => 1 }),
             borrowertitle          => $data->{borrowertitle},
             surname                => $data->{surname},
             firstname              => $data->{firstname},
@@ -332,35 +318,15 @@ if ($noreport) {
             title                  => $data->{title},
             author                 => $data->{author},
             branchcode             => $data->{branchcode},
+            homebranchcode         => $data->{homebranchcode},
+            holdingbranchcode      => $data->{holdingbranchcode},
             itemcallnumber         => $data->{itemcallnumber},
             replacementprice       => $data->{replacementprice},
+            enumchron              => $data->{enumchron},
             patron_attr_value_loop => \@patron_attr_value_loop,
         };
     }
 
-    my ($attrorder) = $order =~ /patron_attr_(.*)$/; 
-    my $patrorder = '';
-    my $sortorder = 'asc';
-    if (defined $attrorder) {
-        ($sortorder, $patrorder) = split /_/, $attrorder, 2;
-    }
-    print STDERR ">>> order is $order, patrorder is $patrorder, sortorder is $sortorder\n" if $debug;
-
-    if (my @attrtype = grep { $_->{'code'} eq $patrorder } @patron_attr_filter_loop) {        # sort by patron attrs perhaps?
-        my $ordinal = $attrtype[0]{ordinal};
-        print STDERR ">>> sort ordinal is $ordinal\n" if $debug;
-
-        sub patronattr_sorter_asc {
-            lc $a->{patron_attr_value_loop}[$ordinal]{value}
-            cmp
-            lc $b->{patron_attr_value_loop}[$ordinal]{value} }
-
-        sub patronattr_sorter_des { -patronattr_sorter_asc() }
-
-        my $sorter = $sortorder eq 'desc' ? \&patronattr_sorter_des : \&patronattr_sorter_asc;
-        @overduedata = sort $sorter @overduedata;
-    }
-
     if ($op eq 'csv') {
         binmode(STDOUT, ":encoding(UTF-8)");
         my $csv = build_csv(\@overduedata);
@@ -379,7 +345,7 @@ if ($noreport) {
 
     $template->param(
         csv_param_string        => $csv_param_string,
-        todaysdate              => format_date($todaysdate),
+        todaysdate              => output_pref($today_dt),
         overdueloop             => \@overduedata,
         nnoverdue               => scalar(@overduedata),
         noverdue_is_plural      => scalar(@overduedata) != 1,
@@ -403,7 +369,7 @@ sub build_csv {
     my @lines = ();
 
     # build header ...
-    my @keys = qw /duedate title author borrowertitle name phone barcode email address address2 zipcode city country
+    my @keys = qw /duedate title author borrowertitle firstname surname phone barcode email address address2 zipcode city country
                 branchcode itemcallnumber biblionumber borrowernumber itemnum issuedate replacementprice streetnumber streettype/;
     my $csv = Text::CSV_XS->new();
     $csv->combine(@keys);