Bugzilla – Attachment 45193 Details for
Bug 12772
Add item type and on-hold status to overdue notice/status triggers tool
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 12772 - Reworked overdue_notices.pl script
Bug-12772---Reworked-overduenoticespl-script.patch (text/plain), 38.48 KB, created by
Eivin Giske Skaaren
on 2015-11-26 19:01:46 UTC
(
hide
)
Description:
Bug 12772 - Reworked overdue_notices.pl script
Filename:
MIME Type:
Creator:
Eivin Giske Skaaren
Created:
2015-11-26 19:01:46 UTC
Size:
38.48 KB
patch
obsolete
>From a67d3351db8a79112bb4fc18b301d3cb85bde4c8 Mon Sep 17 00:00:00 2001 >From: mxbeaulieu <maxime.beaulieu@inlibro.com> >Date: Wed, 12 Aug 2015 15:44:20 -0400 >Subject: [PATCH] Bug 12772 - Reworked overdue_notices.pl script > > modified: misc/cronjobs/overdue_notices.pl >--- > misc/cronjobs/overdue_notices.pl | 695 ++++++++++++++++---------------------- > 1 file changed, 288 insertions(+), 407 deletions(-) > >diff --git a/misc/cronjobs/overdue_notices.pl b/misc/cronjobs/overdue_notices.pl >index 98b0a25..8a68744 100755 >--- a/misc/cronjobs/overdue_notices.pl >+++ b/misc/cronjobs/overdue_notices.pl >@@ -316,71 +316,43 @@ pod2usage( -verbose => 2 ) if $man; > > cronlogaction(); > >-if ( defined $csvfilename && $csvfilename =~ /^-/ ) { >- warn qq(using "$csvfilename" as filename, that seems odd); >+sub VERBOSE{ >+ if ($verbose){ >+ printf STDERR "%s\n", shift; >+ } > } > >-my @overduebranches = C4::Overdues::GetBranchcodesWithOverdueRules(); # Branches with overdue rules >-my @branches; # Branches passed as parameter with overdue rules >-my $branchcount = scalar(@overduebranches); >- >-my $overduebranch_word = scalar @overduebranches > 1 ? 'branches' : 'branch'; >-my $branchcodes_word = scalar @branchcodes > 1 ? 'branches' : 'branch'; >- >-my $PrintNoticesMaxLines = C4::Context->preference('PrintNoticesMaxLines'); >- >-if ($branchcount) { >- $verbose and warn "Found $branchcount $overduebranch_word with first message enabled: " . join( ', ', map { "'$_'" } @overduebranches ), "\n"; >-} else { >- die 'No branches with active overduerules'; >+if ( defined $csvfilename && $csvfilename =~ /^-/ ) { >+ warn qq(using "$csvfilename" as filename, that seems odd); > } > >-if (@branchcodes) { >- $verbose and warn "$branchcodes_word @branchcodes passed on parameter\n"; >- >- # Getting libraries which have overdue rules >- my %seen = map { $_ => 1 } @branchcodes; >- @branches = grep { $seen{$_} } @overduebranches; >- >- >- if (@branches) { >- >- my $branch_word = scalar @branches > 1 ? 'branches' : 'branch'; >- $verbose and warn "$branch_word @branches have overdue rules\n"; >- >- } else { >- >- $verbose and warn "No active overduerules for $branchcodes_word '@branchcodes'\n"; >- ( scalar grep { '' eq $_ } @branches ) >- or die "No active overduerules for DEFAULT either!"; >- $verbose and warn "Falling back on default rules for @branchcodes\n"; >- @branches = (''); >- } >-} > my $date_to_run; > my $date; > if ( $date_input ){ >+ $date = $dbh->quote($date); > eval { >- $date_to_run = dt_from_string( $date_input, 'iso' ); >+ $date_to_run = dt_from_string( $date_input ); > }; >- die "$date_input is not a valid date, aborting! Use a date in format YYYY-MM-DD." >+ die "$date_input is not a valid date, aborting!" > if $@ or not $date_to_run; > >- # It's certainly useless to escape $date_input >- # dt_from_string should not return something if $date_input is not correctly set. >- $date = $dbh->quote( $date_input ); > } > else { > $date="NOW()"; > $date_to_run = dt_from_string(); > } > >+## >+## Some file/html preparation ? >+## >+ >+my $printNoticesMaxLines = C4::Context->preference('PrintNoticesMaxLines'); >+ > # these are the fields that will be substituted into <<item.content>> > my @item_content_fields = split( /,/, $itemscontent ); > > binmode( STDOUT, ':encoding(UTF-8)' ); > >- > our $csv; # the Text::CSV_XS object > our $csv_fh; # the filehandle to the CSV file. > if ( defined $csvfilename ) { >@@ -392,26 +364,24 @@ if ( defined $csvfilename ) { > } else { > open $csv_fh, ">", $csvfilename or die "unable to open $csvfilename: $!"; > } >- if ( $csv->combine(qw(name surname address1 address2 zipcode city country email phone cardnumber itemcount itemsinfo branchname letternumber)) ) { >+ if ( $csv->combine(qw(name surname address1 address2 zipcode city country email itemcount itemsinfo)) ) { > print $csv_fh $csv->string, "\n"; > } else { >- $verbose and warn 'combine failed on argument: ' . $csv->error_input; >+ VERBOSE( 'combine failed on argument: ' . $csv->error_input); > } > } > >-@branches = @overduebranches unless @branches; > our $fh; > if ( defined $htmlfilename ) { > if ( $htmlfilename eq '' ) { > $fh = *STDOUT; > } else { > my $today = DateTime->now(time_zone => C4::Context->tz ); >- open $fh, ">:encoding(UTF-8)",File::Spec->catdir ($htmlfilename,"notices-".$today->ymd().".html"); >+ open $fh, ">",File::Spec->catdir ($htmlfilename,"notices-".$today->ymd().".html"); > } > > print $fh "<html>\n"; > print $fh "<head>\n"; >- print $fh "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />\n"; > print $fh "<style type='text/css'>\n"; > print $fh "pre {page-break-after: always;}\n"; > print $fh "pre {white-space: pre-wrap;}\n"; >@@ -431,388 +401,300 @@ elsif ( defined $text_filename ) { > } > } > >-foreach my $branchcode (@branches) { >- if ( C4::Context->preference('OverdueNoticeCalendar') ) { >- my $calendar = Koha::Calendar->new( branchcode => $branchcode ); >- if ( $calendar->is_holiday($date_to_run) ) { >- next; >- } >- } >- >- my $branch_details = C4::Branch::GetBranchDetail($branchcode); >- my $admin_email_address = $branch_details->{'branchemail'} >- || C4::Context->preference('KohaAdminEmailAddress'); >- my @output_chunks; # may be sent to mail or stdout or csv file. >- >- $verbose and warn sprintf "branchcode : '%s' using %s\n", $branchcode, $admin_email_address; >- >- my $sth2 = $dbh->prepare( <<"END_SQL" ); >-SELECT biblio.*, items.*, issues.*, biblioitems.itemtype, TO_DAYS($date)-TO_DAYS(date_due) AS days_overdue, branchname >- FROM issues,items,biblio, biblioitems, branches b >- WHERE items.itemnumber=issues.itemnumber >+## >+## sql queries >+## >+my $sqlIssues = "SELECT biblio.*, items.*, issues.*, biblioitems.itemtype, TO_DAYS($date)-TO_DAYS(date_due) AS days_overdue >+ FROM issues,items,biblio, biblioitems >+ WHERE items.itemnumber=issues.itemnumber > AND biblio.biblionumber = items.biblionumber >- AND b.branchcode = items.homebranch > AND biblio.biblionumber = biblioitems.biblionumber >- AND issues.borrowernumber = ? >-END_SQL >- >- my $query = "SELECT * FROM overduerules WHERE delay1 IS NOT NULL AND branchcode = ? "; >- $query .= " AND categorycode IN (".join( ',' , ('?') x @myborcat ).") " if (@myborcat); >- $query .= " AND categorycode NOT IN (".join( ',' , ('?') x @myborcatout ).") " if (@myborcatout); >- >- my $rqoverduerules = $dbh->prepare($query); >- $rqoverduerules->execute($branchcode, @myborcat, @myborcatout); >- >- # We get default rules is there is no rule for this branch >- if($rqoverduerules->rows == 0){ >- $query = "SELECT * FROM overduerules WHERE delay1 IS NOT NULL AND branchcode = '' "; >- $query .= " AND categorycode IN (".join( ',' , ('?') x @myborcat ).") " if (@myborcat); >- $query .= " AND categorycode NOT IN (".join( ',' , ('?') x @myborcatout ).") " if (@myborcatout); >- >- $rqoverduerules = $dbh->prepare($query); >- $rqoverduerules->execute(@myborcat, @myborcatout); >- } >- >- # my $outfile = 'overdues_' . ( $mybranch || $branchcode || 'default' ); >- while ( my $overdue_rules = $rqoverduerules->fetchrow_hashref ) { >- PERIOD: foreach my $i ( 1 .. 3 ) { >- >- $verbose and warn "branch '$branchcode', categorycode = $overdue_rules->{categorycode} pass $i\n"; >+ AND TO_DAYS($date)-TO_DAYS(date_due) BETWEEN 1 AND $MAX "; >+ >+my $sqlBorrowers = "SELECT issues.borrowernumber, firstname, surname, address, address2, city, zipcode, >+ country, email, emailpro, B_email, smsalertnumber, borrowers.categorycode >+ FROM issues,borrowers,categories >+ WHERE issues.borrowernumber=borrowers.borrowernumber >+ AND borrowers.categorycode=categories.categorycode >+ AND TO_DAYS($date)-TO_DAYS(date_due) BETWEEN 1 AND $MAX >+ AND categories.overduenoticerequired=1 "; >+ >+my $sqlRules = "SELECT * >+ FROM overduerules >+ WHERE delay != 0 >+ AND letter <> '' >+ ORDER BY branchcode desc, categorycode desc, itemtype desc, onhold desc, delay desc"; >+ >+my $sqlMTT = "SELECT message_transport_type from overduerules_transport_types where overduerules_id = ?"; >+ >+my $sqlReserves = "SELECT distinct(biblionumber) FROM reserves"; >+ >+## >+## customized depending on parameters >+## >+if(@branchcodes){ >+ $sqlIssues .= " AND issues.branchcode IN ('" . join ("','", @branchcodes) . "')"; >+} >+if(@myborcat){ >+ $sqlBorrowers .= " AND borrower.categorycode IN ('" . join ("','", @myborcat) . "')"; >+} >+if(@myborcatout){ >+ $sqlBorrowers .= " AND borrower.categorycode NOT IN ('" . join ("','", @myborcatout) . "')"; >+} > >- my $mindays = $overdue_rules->{"delay$i"}; # the notice will be sent after mindays days (grace period) >- my $maxdays = ( >- $overdue_rules->{ "delay" . ( $i + 1 ) } >- ? $overdue_rules->{ "delay" . ( $i + 1 ) } - 1 >- : ($MAX) >- ); # issues being more than maxdays late are managed somewhere else. (borrower probably suspended) >+## >+## collect everything in meaningful hashes >+## >+my $hrBorrowers = $dbh->selectall_hashref($sqlBorrowers, 'borrowernumber'); >+VERBOSE("$sqlBorrowers\nReturned " . (scalar keys $hrBorrowers) . " borrowers with issues."); >+my $hrOverdueIssues = $dbh->selectall_hashref($sqlIssues, 'itemnumber' ); >+VERBOSE("$sqlIssues\nReturned " . (scalar keys $hrOverdueIssues) . " overdue issues."); >+my $arRules = $dbh->selectall_arrayref($sqlRules, { Slice => {} } ); >+VERBOSE("\nRule order:\nId\tBranch\tCat\tItem\tHold\tDelay\tDebarred\tLetter"); >+foreach my $rule (@$arRules){ >+ $rule->{mtt} = $dbh->selectcol_arrayref($sqlMTT, undef, $rule->{overduerules_id}); >+ VERBOSE("$rule->{id}\t$rule->{branchcode}\t$rule->{categorycode}\t$rule->{itemtype}\t$rule->{onhold}\t$rule->{delay}\t$rule->{debarred}\t$rule->{letter}"); >+} >+my $hrReserves = $dbh->selectall_hashref($sqlReserves, 'biblionumber'); >+VERBOSE("$sqlReserves\nReturned " . (scalar keys $hrReserves) . " unique reserves."); >+my %hBranches; >+my %hChunks; # messages to send once per branch to the administrator >+ >+## >+## For each issue, determine the most meaningful rule that applies >+## and associate it to the borrower >+## >+ >+my $whichItemType = C4::Context->preference('item-level_itypes') ? 'itype' : 'itemtype'; >+foreach my $in (keys $hrOverdueIssues){ >+ my $issue = $hrOverdueIssues->{$in}; >+ VERBOSE("Processing issue $in. branchcode: $issue->{branchcode}, borrower: $issue->{borrowernumber}."); >+ foreach my $rule(@$arRules){ >+ if( ($rule->{branchcode} eq '' || $rule->{branchcode} eq $issue->{branchcode}) && >+ ($rule->{categorycode} eq '' || $rule->{categorycode} eq $hrBorrowers->{$issue->{borrowernumber}}->{categorycode}) && >+ ($rule->{itemtype} eq '' || $rule->{itemtype} eq $issue->{$whichItemType}) && >+ (!$rule->{onhold} || defined $hrReserves->{$issue->{biblionumber}}) >+ ) >+ { >+ # limit the creation of calendar objects >+ if(!defined $hBranches{$issue->{branchcode}}){ >+ $hBranches{$issue->{branchcode}} = C4::Branch::GetBranchDetail($issue->{branchcode}); >+ $hBranches{$issue->{branchcode}}{CALENDAR} = Koha::Calendar->new( branchcode => $issue->{branchcode} ); >+ } > >- next unless defined $mindays; >+ # validate number of days overdue vs delay >+ if ( C4::Context->preference('OverdueNoticeCalendar') ){ >+ my $days_between = $hBranches{$issue->{branchcode}}{CALENDAR}->days_between( dt_from_string($issue->{date_due}), $date_to_run ); >+ $issue->{days_overdue} = $days_between->in_units('days'); >+ } >+ next if ( $triggered && $rule->{delay} != $issue->{days_overdue}); # on "triggered". we only look for exact matches >+ next if (!$triggered && $rule->{delay} > $issue->{days_overdue}); > >- if ( !$overdue_rules->{"letter$i"} ) { >- $verbose and warn "No letter$i code for branch '$branchcode'"; >- next PERIOD; >+ # validate the letter >+ unless(C4::Letters::getletter( 'circulation', $rule->{letter}, $issue->{branchcode} )){ >+ VERBOSE("Message '$rule->{letter}' content not found"); >+ last; # if no letter > } > >- # $letter->{'content'} is the text of the mail that is sent. >- # this text contains fields that are replaced by their value. Those fields must be written between brackets >- # The following fields are available : >- # itemcount is interpreted here as the number of items in the overdue range defined by the current notice or all overdues < max if(-list-all). >- # <date> <itemcount> <firstname> <lastname> <address1> <address2> <address3> <city> <postcode> <country> >- >- my $borrower_sql = <<'END_SQL'; >-SELECT issues.borrowernumber, firstname, surname, address, address2, city, zipcode, country, email, emailpro, B_email, smsalertnumber, phone, cardnumber, >-TO_DAYS(?)-TO_DAYS(date_due) as difference, date_due >-FROM issues,borrowers,categories >-WHERE issues.borrowernumber=borrowers.borrowernumber >-AND borrowers.categorycode=categories.categorycode >-END_SQL >- my @borrower_parameters; >- push @borrower_parameters, $date_to_run->datetime(); >- if ($branchcode) { >- $borrower_sql .= ' AND issues.branchcode=? '; >- push @borrower_parameters, $branchcode; >+ # we found the best rule to apply, let's store the branchcode/lettter combo into the borrower >+ my $arItems = $hrBorrowers->{$issue->{borrowernumber}}{NOTICES}{$issue->{branchcode}}{$rule->{letter}}{ITEMS} ||= []; >+ push $arItems, $issue->{itemnumber}; >+ # And note that we union the transport types, so IF the user set two similar alerts (except for delay and mtt), then >+ # only one message will be sent to each of the transport specified by both rules together >+ my $hrMtts = $hrBorrowers->{$issue->{borrowernumber}}{NOTICES}{$issue->{branchcode}}{$rule->{letter}}{MTTS} ||= {}; >+ foreach my $mtt(@{$rule->{mtt}}){ >+ $hrMtts->{$mtt} = 1; > } >- if ( $overdue_rules->{categorycode} ) { >- $borrower_sql .= ' AND borrowers.categorycode=? '; >- push @borrower_parameters, $overdue_rules->{categorycode}; >+ VERBOSE("User $hrBorrowers->{$issue->{borrowernumber}}{surname}, Branch $issue->{branchcode}, Letter $rule->{letter} : Item $issue->{itemnumber}"); >+ >+ # block the user if needed >+ if ( $rule->{"debarred"} ) { >+ AddUniqueDebarment({ >+ borrowernumber => $issue->{borrowernumber}, >+ type => 'OVERDUES', >+ comment => "Restriction added by overdues process " . output_pref( dt_from_string() ), >+ }); >+ VERBOSE("debarring user $issue->{borrowernumber} (" . $hrBorrowers->{$issue->{borrowernumber}}{surname} . ")"); > } >- $borrower_sql .= ' AND categories.overduenoticerequired=1 ORDER BY issues.borrowernumber'; >- >- # $sth gets borrower info iff at least one overdue item has triggered the overdue action. >- my $sth = $dbh->prepare($borrower_sql); >- $sth->execute(@borrower_parameters); >- >- $verbose and warn $borrower_sql . "\n $branchcode | " . $overdue_rules->{'categorycode'} . "\n ($mindays, $maxdays, ". $date_to_run->datetime() .")\nreturns " . $sth->rows . " rows"; >- my $borrowernumber; >- while ( my $data = $sth->fetchrow_hashref ) { >- >- next unless ( DateTime->compare( $date_to_run, dt_from_string($data->{date_due})) ) == 1; >- >- # check the borrower has at least one item that matches >- my $days_between; >- if ( C4::Context->preference('OverdueNoticeCalendar') ) >- { >- my $calendar = >- Koha::Calendar->new( branchcode => $branchcode ); >- $days_between = >- $calendar->days_between( dt_from_string($data->{date_due}), >- $date_to_run ); >- } >- else { >- $days_between = >- $date_to_run->delta_days( dt_from_string($data->{date_due}) ); >- } >- $days_between = $days_between->in_units('days'); >- if ($triggered) { >- if ( $mindays != $days_between ) { >- next; >- } >- } >- else { >- unless ( $days_between >= $mindays >- && $days_between <= $maxdays ) >- { >- next; >- } >- } >- if (defined $borrowernumber && $borrowernumber eq $data->{'borrowernumber'}){ >-# we have already dealt with this borrower >- $verbose and warn "already dealt with this borrower $borrowernumber"; >- next; >- } >- $borrowernumber = $data->{'borrowernumber'}; >- my $borr = >- $data->{'firstname'} . ', ' >- . $data->{'surname'} . ' (' >- . $borrowernumber . ')'; >- $verbose >- and warn "borrower $borr has items triggering level $i."; >- >- @emails_to_use = (); >- my $notice_email = >- C4::Members::GetNoticeEmailAddress($borrowernumber); >- unless ($nomail) { >- if (@emails) { >- foreach (@emails) { >- push @emails_to_use, $data->{$_} if ( $data->{$_} ); >- } >- } >- else { >- push @emails_to_use, $notice_email if ($notice_email); >- } >- } >+ last; # we found a rule, let's move to the next issue >+ } >+ } >+} > >- my $letter = C4::Letters::getletter( 'circulation', $overdue_rules->{"letter$i"}, $branchcode ); >+## >+## Main loop >+## >+VERBOSE("Main loop."); >+foreach my $borrowernumber(keys $hrBorrowers){ >+ if(!defined $hrBorrowers->{$borrowernumber}{NOTICES}){ >+ VERBOSE("User $hrBorrowers->{$borrowernumber}{surname} has no notice."); >+ next; >+ } >+ # for each branch >+ foreach my $branchcode (keys $hrBorrowers->{$borrowernumber}{NOTICES}){ >+ my $admin_email_address = $hBranches{$branchcode}{'branchemail'} || C4::Context->preference('KohaAdminEmailAddress'); >+ if($hBranches{$branchcode}{CALENDAR}->is_holiday($date_to_run)){ >+ VERBOSE("$date_to_run is a holiday at branch $branchcode"); >+ next; >+ } > >- unless ($letter) { >- $verbose and warn qq|Message '$overdue_rules->{"letter$i"}' content not found|; >+ # for each letter >+ foreach my $lettercode (keys $hrBorrowers->{$borrowernumber}{NOTICES}{$branchcode}){ >+ @emails_to_use = (); >+ my $notice_email = C4::Members::GetNoticeEmailAddress($borrowernumber); >+ unless ($nomail) { >+ if (@emails) { >+ @emails_to_use = @emails; >+ # foreach (@emails) { >+# push @emails_to_use, $data->{$_} if ( $data->{$_} ); >+ # } >+ }else{ >+ push @emails_to_use, $notice_email if ($notice_email); >+ } >+ } > >- # might as well skip while PERIOD, no other borrowers are going to work. >- # FIXME : Does this mean a letter must be defined in order to trigger a debar ? >- next PERIOD; >+ # finally, the items >+ my $arItems = $hrBorrowers->{$borrowernumber}{NOTICES}{$branchcode}{$lettercode}{ITEMS}; >+ if(!defined $arItems){ >+ VERBOSE("No item for borrower $borrowernumber"); >+ next; >+ } >+ my $itemcount = 0; >+ my $titles = ""; >+ my @items = (); >+ >+ my $j = 0; >+ my $exceededPrintNoticesMaxLines = 0; >+ foreach my $itemnumber(@{$arItems}){ >+ if ( ( scalar(@emails_to_use) == 0 || $nomail ) && $printNoticesMaxLines && $j >= $printNoticesMaxLines ) { >+ $exceededPrintNoticesMaxLines = 1; >+ last; > } >- >- if ( $overdue_rules->{"debarred$i"} ) { >- >- #action taken is debarring >- AddUniqueDebarment( >- { >- borrowernumber => $borrowernumber, >- type => 'OVERDUES', >- comment => "Restriction added by overdues process " >- . output_pref( dt_from_string() ), >- } >- ); >- $verbose and warn "debarring $borr\n"; >+ $j++; >+ my $item = $hrOverdueIssues->{$itemnumber}; >+ my @item_info = map { $_ =~ /^date|date$/ ? format_date( $item->{$_} ) : $item->{$_} || '' } @item_content_fields; >+ $titles .= join("\t", @item_info) . "\n"; >+ $itemcount++; >+ push @items, $item; >+ } >+ >+ # the transport types (email, sms...) >+ my @message_transport_types = keys $hrBorrowers->{$borrowernumber}{NOTICES}{$branchcode}{$lettercode}{MTTS}; >+ my $print_sent = 0; # A print notice is not yet sent for this patron >+ for my $mtt ( @message_transport_types ) { >+ my $letter = parse_letter( { >+ letter_code => $lettercode, >+ borrowernumber => $borrowernumber, >+ branchcode => $branchcode, >+ items => \@items, >+ substitute => { # this appears to be a hack to overcome incomplete features in this code. >+ bib => $hBranches{$branchcode}{'branchname'}, # maybe 'bib' is a typo for 'lib<rary>'? >+ 'items.content' => $titles, >+ 'count' => $itemcount, >+ }, >+ message_transport_type => $mtt, >+ } ); >+ unless ($letter) { >+ VERBOSE("Message '$lettercode' content not found (transport $mtt, branch $branchcode)"); >+ next; > } >- my @params = ($borrowernumber); >- $verbose and warn "STH2 PARAMS: borrowernumber = $borrowernumber"; >- >- $sth2->execute(@params); >- my $itemcount = 0; >- my $titles = ""; >- my @items = (); >- >- my $j = 0; >- my $exceededPrintNoticesMaxLines = 0; >- while ( my $item_info = $sth2->fetchrow_hashref() ) { >- next unless ( DateTime->compare( $date_to_run, dt_from_string($item_info->{date_due})) ) == 1; >- >- if ( C4::Context->preference('OverdueNoticeCalendar') ) { >- my $calendar = >- Koha::Calendar->new( branchcode => $branchcode ); >- $days_between = >- $calendar->days_between( >- dt_from_string( $item_info->{date_due} ), $date_to_run ); >- } >- else { >- $days_between = >- $date_to_run->delta_days( >- dt_from_string( $item_info->{date_due} ) ); >- } >- $days_between = $days_between->in_units('days'); >- if ($listall){ >- unless ($days_between >= 1 and $days_between <= $MAX){ >- next; >- } >- } >- else { >- if ($triggered) { >- if ( $mindays != $days_between ) { >- next; >- } >- } >- else { >- unless ( $days_between >= $mindays >- && $days_between <= $maxdays ) >- { >- next; >- } >- } >- } > >- if ( ( scalar(@emails_to_use) == 0 || $nomail ) && $PrintNoticesMaxLines && $j >= $PrintNoticesMaxLines ) { >- $exceededPrintNoticesMaxLines = 1; >- last; >- } >- $j++; >- my @item_info = map { $_ =~ /^date|date$/ ? >- eval { output_pref( { dt => dt_from_string( $item_info->{$_} ), dateonly => 1 } ); } >- : >- $item_info->{$_} || '' } @item_content_fields; >- $titles .= join("\t", @item_info) . "\n"; >- $itemcount++; >- push @items, $item_info; >+ if ( $exceededPrintNoticesMaxLines ) { >+ $letter->{'content'} .= "List too long for form; please check your account online for a complete list of your overdue items."; > } >- $sth2->finish; >- >- my @message_transport_types = @{ GetOverdueMessageTransportTypes( $branchcode, $overdue_rules->{categorycode}, $i) }; >- @message_transport_types = @{ GetOverdueMessageTransportTypes( q{}, $overdue_rules->{categorycode}, $i) } >- unless @message_transport_types; >- >- >- my $print_sent = 0; # A print notice is not yet sent for this patron >- for my $mtt ( @message_transport_types ) { >- >- my $letter = parse_overdues_letter( >- { letter_code => $overdue_rules->{"letter$i"}, >- borrowernumber => $borrowernumber, >- branchcode => $branchcode, >- items => \@items, >- substitute => { # this appears to be a hack to overcome incomplete features in this code. >- bib => $branch_details->{'branchname'}, # maybe 'bib' is a typo for 'lib<rary>'? >- 'items.content' => $titles, >- 'count' => $itemcount, >- }, >- message_transport_type => $mtt, >- } >- ); >- unless ($letter) { >- $verbose and warn qq|Message '$overdue_rules->{"letter$i"}' content not found|; >- # this transport doesn't have a configured notice, so try another >- next; >- } > >- if ( $exceededPrintNoticesMaxLines ) { >- $letter->{'content'} .= "List too long for form; please check your account online for a complete list of your overdue items."; >- } >+ my @misses = grep { /./ } map { /^([^>]*)[>]+/; ( $1 || '' ); } split /\</, $letter->{'content'}; >+ if (@misses) { >+ VERBOSE( "The following terms were not matched and replaced: \n\t" . join "\n\t", @misses ); >+ } > >- my @misses = grep { /./ } map { /^([^>]*)[>]+/; ( $1 || '' ); } split /\</, $letter->{'content'}; >- if (@misses) { >- $verbose and warn "The following terms were not matched and replaced: \n\t" . join "\n\t", @misses; >+ if ($nomail) { >+ $hChunks{$admin_email_address} ||= []; >+ push $hChunks{$admin_email_address}, prepare_letter_for_printing( { >+ letter => $letter, >+ borrowernumber => $borrowernumber, >+ firstname => $hrBorrowers->{$borrowernumber}->{'firstname'}, >+ lastname => $hrBorrowers->{$borrowernumber}->{'surname'}, >+ address1 => $hrBorrowers->{$borrowernumber}->{'address'}, >+ address2 => $hrBorrowers->{$borrowernumber}->{'address2'}, >+ city => $hrBorrowers->{$borrowernumber}->{'city'}, >+ postcode => $hrBorrowers->{$borrowernumber}->{'zipcode'}, >+ country => $hrBorrowers->{$borrowernumber}->{'country'}, >+ email => $notice_email, >+ itemcount => $itemcount, >+ titles => $titles, >+ outputformat => defined $csvfilename ? 'csv' : defined $htmlfilename ? 'html' : defined $text_filename ? 'text' : '', >+ } ); >+ } else { >+ if ( ($mtt eq 'email' and not scalar @emails_to_use) or ($mtt eq 'sms' and not $hrBorrowers->{$borrowernumber}->{smsalertnumber}) ) { >+ # email or sms is requested but not exist, do a print. >+ $mtt = 'print'; > } >- >- if ($nomail) { >- push @output_chunks, >- prepare_letter_for_printing( >- { letter => $letter, >- borrowernumber => $borrowernumber, >- firstname => $data->{'firstname'}, >- lastname => $data->{'surname'}, >- address1 => $data->{'address'}, >- address2 => $data->{'address2'}, >- city => $data->{'city'}, >- phone => $data->{'phone'}, >- cardnumber => $data->{'cardnumber'}, >- branchname => $branch_details->{'branchname'}, >- letternumber => $i, >- postcode => $data->{'zipcode'}, >- country => $data->{'country'}, >- email => $notice_email, >- itemcount => $itemcount, >- titles => $titles, >- outputformat => defined $csvfilename ? 'csv' : defined $htmlfilename ? 'html' : defined $text_filename ? 'text' : '', >+ unless ( $mtt eq 'print' and $print_sent == 1 ) { >+ # Just sent a print if not already done. >+ C4::Letters::EnqueueLetter( >+ { letter => $letter, >+ borrowernumber => $borrowernumber, >+ message_transport_type => $mtt, >+ from_address => $admin_email_address, >+ to_address => join(',', @emails_to_use), > } >- ); >- } else { >- if ( ($mtt eq 'email' and not scalar @emails_to_use) or ($mtt eq 'sms' and not $data->{smsalertnumber}) ) { >- # email or sms is requested but not exist, do a print. >- $mtt = 'print'; >- push @output_chunks, >- prepare_letter_for_printing( >- { letter => $letter, >- borrowernumber => $borrowernumber, >- firstname => $data->{'firstname'}, >- lastname => $data->{'surname'}, >- address1 => $data->{'address'}, >- address2 => $data->{'address2'}, >- city => $data->{'city'}, >- postcode => $data->{'zipcode'}, >- country => $data->{'country'}, >- email => $notice_email, >- itemcount => $itemcount, >- titles => $titles, >- outputformat => defined $csvfilename ? 'csv' : defined $htmlfilename ? 'html' : defined $text_filename ? 'text' : '', >- } >- ); >- } >- unless ( $mtt eq 'print' and $print_sent == 1 ) { >- # Just sent a print if not already done. >- C4::Letters::EnqueueLetter( >- { letter => $letter, >- borrowernumber => $borrowernumber, >- message_transport_type => $mtt, >- from_address => $admin_email_address, >- to_address => join(',', @emails_to_use), >- } >- ); >- # A print notice should be sent only once per overdue level. >- # Without this check, a print could be sent twice or more if the library checks sms and email and print and the patron has no email or sms number. >- $print_sent = 1 if $mtt eq 'print'; >- } >+ ); >+ # A print notice should be sent only once per overdue level. >+ # Without this check, a print could be sent twice or more if the library checks sms and email and print and the patron has no email or sms number. >+ $print_sent = 1 if $mtt eq 'print'; > } > } > } >- $sth->finish; > } > } >+} > >- if (@output_chunks) { >- if ( defined $csvfilename ) { >- print $csv_fh @output_chunks; >- } >- elsif ( defined $htmlfilename ) { >- print $fh @output_chunks; >- } >- elsif ( defined $text_filename ) { >- print $fh @output_chunks; >- } >- elsif ($nomail){ >- local $, = "\f"; # pagebreak >- print @output_chunks; >- } >- # Generate the content of the csv with headers >- my $content; >- if ( defined $csvfilename ) { >- my $delimiter = C4::Context->preference('delimiter') || ';'; >- $content = join($delimiter, qw(title name surname address1 address2 zipcode city country email itemcount itemsinfo due_date issue_date)) . "\n"; >- } >- else { >- $content = ""; >- } >- $content .= join( "\n", @output_chunks ); >- >- my $attachment = { >- filename => defined $csvfilename ? 'attachment.csv' : 'attachment.txt', >- type => 'text/plain', >- content => $content, >- }; >- >- my $letter = { >- title => 'Overdue Notices', >- content => 'These messages were not sent directly to the patrons.', >- }; >- C4::Letters::EnqueueLetter( >- { letter => $letter, >- borrowernumber => undef, >- message_transport_type => 'email', >- attachments => [$attachment], >- to_address => $admin_email_address, >- } >- ); >+foreach my $admin_email_address (keys %hChunks) { >+ my @output_chunks = @{$hChunks{$admin_email_address}}; >+ if ( defined $csvfilename ) { >+ print $csv_fh @output_chunks; >+ } >+ elsif ( defined $htmlfilename ) { >+ print $fh @output_chunks; >+ } >+ elsif ( defined $text_filename ) { >+ print $fh @output_chunks; >+ } >+ elsif ($nomail){ >+ local $, = "\f"; # pagebreak >+ print @output_chunks; >+ } >+ # Generate the content of the csv with headers >+ my $content; >+ if ( defined $csvfilename ) { >+ my $delimiter = C4::Context->preference('delimiter') || ';'; >+ $content = join($delimiter, qw(title name surname address1 address2 zipcode city country email itemcount itemsinfo due_date issue_date)) . "\n"; > } >+ else { >+ $content = ""; >+ } >+ $content .= join( "\n", @output_chunks ); >+ >+ my $attachment = { >+ filename => defined $csvfilename ? 'attachment.csv' : 'attachment.txt', >+ type => 'text/plain', >+ content => $content, >+ }; > >+ my $letter = { >+ title => 'Overdue Notices', >+ content => 'These messages were not sent directly to the patrons.', >+ }; >+ C4::Letters::EnqueueLetter( { >+ letter => $letter, >+ borrowernumber => undef, >+ message_transport_type => 'email', >+ attachments => [$attachment], >+ to_address => $admin_email_address, >+ } ); > } >+ > if ($csvfilename) { > # note that we're not testing on $csv_fh to prevent closing > # STDOUT. >@@ -820,11 +702,11 @@ if ($csvfilename) { > } > > if ( defined $htmlfilename ) { >- print $fh "</body>\n"; >- print $fh "</html>\n"; >- close $fh; >+ print $fh "</body>\n"; >+ print $fh "</html>\n"; >+ close $fh; > } elsif ( defined $text_filename ) { >- close $fh; >+ close $fh; > } > > =head1 INTERNAL METHODS >@@ -861,8 +743,7 @@ sub prepare_letter_for_printing { > if ( exists $params->{'outputformat'} && $params->{'outputformat'} eq 'csv' ) { > if ($csv->combine( > $params->{'firstname'}, $params->{'lastname'}, $params->{'address1'}, $params->{'address2'}, $params->{'postcode'}, >- $params->{'city'}, $params->{'country'}, $params->{'email'}, $params->{'phone'}, $params->{'cardnumber'}, >- $params->{'itemcount'}, $params->{'titles'}, $params->{'branchname'}, $params->{'letternumber'} >+ $params->{'city'}, $params->{'country'}, $params->{'email'}, $params->{'itemcount'}, $params->{'titles'} > ) > ) { > return $csv->string, "\n"; >-- >1.7.10.4
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 12772
:
41477
|
41478
|
41479
|
41480
|
41855
|
42126
|
45184
|
45185
|
45186
|
45187
|
45188
|
45189
|
45190
|
45191
|
45192
|
45193
|
45194
|
45195
|
45196
|
45197
|
45198
|
45199
|
45200
|
45201
|
45202
|
45203
|
45204
|
45544
|
45545
|
45546
|
45547
|
45548
|
45549
|
45550
|
45551
|
45552
|
56063
|
56077