Lines 108-114
any CSV files. Defaults to 90 to match F<longoverdues.pl>.
Link Here
|
108 |
=item B<--library> |
108 |
=item B<--library> |
109 |
|
109 |
|
110 |
select overdues for one specific library. Use the value in the |
110 |
select overdues for one specific library. Use the value in the |
111 |
branches.branchcode table. This option can be repeated in order |
111 |
branches.branchcode table. This option can be repeated in order |
112 |
to select overdues for a group of libraries. |
112 |
to select overdues for a group of libraries. |
113 |
|
113 |
|
114 |
=item B<--csv> |
114 |
=item B<--csv> |
Lines 142-147
defaults to due date,title,barcode,author
Link Here
|
142 |
Other possible values come from fields in the biblios, items and |
142 |
Other possible values come from fields in the biblios, items and |
143 |
issues tables. |
143 |
issues tables. |
144 |
|
144 |
|
|
|
145 |
=item B<--itemtypes> |
146 |
|
147 |
Repeatable field, that permits to select only some item types. |
148 |
|
149 |
=item B<--itemtypesout> |
150 |
|
151 |
Repeatable field, that permits to exclude some item types. |
152 |
|
145 |
=item B<--borcat> |
153 |
=item B<--borcat> |
146 |
|
154 |
|
147 |
Repeatable field, that permits to select only some patron categories. |
155 |
Repeatable field, that permits to select only some patron categories. |
Lines 152-164
Repeatable field, that permits to exclude some patron categories.
Link Here
|
152 |
|
160 |
|
153 |
=item B<-t> | B<--triggered> |
161 |
=item B<-t> | B<--triggered> |
154 |
|
162 |
|
155 |
This option causes a notice to be generated if and only if |
163 |
This option causes a notice to be generated if and only if |
156 |
an item is overdue by the number of days defined in a notice trigger. |
164 |
an item is overdue by the number of days defined in a notice trigger. |
157 |
|
165 |
|
158 |
By default, a notice is sent each time the script runs, which is suitable for |
166 |
By default, a notice is sent each time the script runs, which is suitable for |
159 |
less frequent run cron script, but requires syncing notice triggers with |
167 |
less frequent run cron script, but requires syncing notice triggers with |
160 |
the cron schedule to ensure proper behavior. |
168 |
the cron schedule to ensure proper behavior. |
161 |
Add the --triggered option for daily cron, at the risk of no notice |
169 |
Add the --triggered option for daily cron, at the risk of no notice |
162 |
being generated if the cron fails to run on time. |
170 |
being generated if the cron fails to run on time. |
163 |
|
171 |
|
164 |
=item B<--test> |
172 |
=item B<--test> |
Lines 170-176
for debugging configuration.
Link Here
|
170 |
|
178 |
|
171 |
=item B<--list-all> |
179 |
=item B<--list-all> |
172 |
|
180 |
|
173 |
Default items.content lists only those items that fall in the |
181 |
Default items.content lists only those items that fall in the |
174 |
range of the currently processing notice. |
182 |
range of the currently processing notice. |
175 |
Choose --list-all to include all overdue items in the list (limited by B<--max> setting). |
183 |
Choose --list-all to include all overdue items in the list (limited by B<--max> setting). |
176 |
|
184 |
|
Lines 307-312
my $text_filename;
Link Here
|
307 |
my $triggered = 0; |
315 |
my $triggered = 0; |
308 |
my $listall = 0; |
316 |
my $listall = 0; |
309 |
my $itemscontent = join( ',', qw( date_due title barcode author itemnumber ) ); |
317 |
my $itemscontent = join( ',', qw( date_due title barcode author itemnumber ) ); |
|
|
318 |
my @myitemtypes; |
319 |
my @myitemtypesout; |
310 |
my @myborcat; |
320 |
my @myborcat; |
311 |
my @myborcatout; |
321 |
my @myborcatout; |
312 |
my ( $date_input, $today ); |
322 |
my ( $date_input, $today ); |
Lines 325-330
GetOptions(
Link Here
|
325 |
'html:s' => \$htmlfilename, # this optional argument gets '' if not supplied. |
335 |
'html:s' => \$htmlfilename, # this optional argument gets '' if not supplied. |
326 |
'text:s' => \$text_filename, # this optional argument gets '' if not supplied. |
336 |
'text:s' => \$text_filename, # this optional argument gets '' if not supplied. |
327 |
'itemscontent=s' => \$itemscontent, |
337 |
'itemscontent=s' => \$itemscontent, |
|
|
338 |
'itemtypes=s' => \@myitemtypes, |
339 |
'itemtypeouts=s' => \@myitemtypesout, |
328 |
'list-all' => \$listall, |
340 |
'list-all' => \$listall, |
329 |
't|triggered' => \$triggered, |
341 |
't|triggered' => \$triggered, |
330 |
'test' => \$test_mode, |
342 |
'test' => \$test_mode, |
Lines 499-550
END_SQL
Link Here
|
499 |
@categories = Koha::Patron::Categories->search()->get_column('categorycode'); |
511 |
@categories = Koha::Patron::Categories->search()->get_column('categorycode'); |
500 |
} |
512 |
} |
501 |
|
513 |
|
|
|
514 |
my @itemtypes; |
515 |
if (@myitemtypes) { |
516 |
@itemtypes = @myitemtypes; |
517 |
} elsif (@myitemtypesout) { |
518 |
@itemtypes = |
519 |
Koha::ItemTypes->search( { itemtype => { 'not_in' => \@myitemtypesout } } )->get_column('itemtype'); |
520 |
} else { |
521 |
@itemtypes = Koha::ItemTypes->search()->get_column('itemtype'); |
522 |
} |
523 |
|
502 |
for my $category (@categories) { |
524 |
for my $category (@categories) { |
503 |
my $i = 0; |
525 |
for my $itemtype (@itemtypes) { |
504 |
PERIOD: while (1) { |
526 |
my $i = 0; |
505 |
$i++; |
527 |
PERIOD: while (1) { |
506 |
my $j = $i + 1; |
528 |
$i++; |
507 |
my $overdue_rules = Koha::CirculationRules->get_effective_rules( |
529 |
my $j = $i + 1; |
508 |
{ |
530 |
my $overdue_rules = Koha::CirculationRules->get_effective_rules( |
509 |
rules => [ |
531 |
{ |
510 |
"overdue_$i" . '_delay', "overdue_$i" . '_notice', "overdue_$i" . '_mtt', |
532 |
rules => [ |
511 |
"overdue_$i" . '_restrict', "overdue_$j" . '_delay' |
533 |
"overdue_$i" . '_delay', "overdue_$i" . '_notice', "overdue_$i" . '_mtt', |
512 |
], |
534 |
"overdue_$i" . '_restrict', "overdue_$j" . '_delay' |
513 |
categorycode => $category, |
535 |
], |
514 |
branchcode => $branchcode |
536 |
categorycode => $category, |
515 |
} |
537 |
branchcode => $branchcode, |
516 |
); |
538 |
itemtype => $itemtype, |
517 |
$verbose and warn "branch '$branchcode', categorycode = $category pass $i\n"; |
539 |
} |
|
|
540 |
); |
541 |
$verbose and warn "branch '$branchcode', categorycode = $category, itemtype = $itemtype, pass $i\n"; |
518 |
|
542 |
|
519 |
if ( !$overdue_rules->{ "overdue_$i" . '_delay' } ) { |
543 |
if ( !defined( $overdue_rules->{ "overdue_$i" . '_delay' } ) ) { |
520 |
last PERIOD; |
544 |
last PERIOD; |
521 |
} |
545 |
} |
522 |
|
546 |
|
523 |
my $mindays = |
547 |
my $mindays = |
524 |
$overdue_rules->{ "overdue_$i" . '_delay' }; # the notice will be sent after mindays days (grace period) |
548 |
$overdue_rules->{ "overdue_$i" . '_delay' } |
525 |
my $maxdays = ( |
549 |
; # the notice will be sent after mindays days (grace period) |
526 |
$overdue_rules->{ "overdue_$j" . '_delay' } |
550 |
my $maxdays = ( |
527 |
? $overdue_rules->{ "overdue_$j" . '_delay' } - 1 |
551 |
$overdue_rules->{ "overdue_$j" . '_delay' } |
528 |
: ($MAX) |
552 |
? $overdue_rules->{ "overdue_$j" . '_delay' } - 1 |
529 |
); # issues being more than maxdays late are managed somewhere else. (borrower probably suspended) |
553 |
: ($MAX) |
|
|
554 |
); # issues being more than maxdays late are managed somewhere else. (borrower probably suspended) |
530 |
|
555 |
|
531 |
next unless defined $mindays; |
556 |
next unless defined $mindays; |
532 |
|
557 |
|
533 |
if ( !$overdue_rules->{ "overdue_$i" . '_notice' } ) { |
558 |
if ( !$overdue_rules->{ "overdue_$i" . '_notice' } ) { |
534 |
$verbose and warn sprintf "No letter code found for pass %s\n", $i; |
559 |
$verbose and warn sprintf "No letter code found for pass %s\n", $i; |
535 |
next PERIOD; |
560 |
next PERIOD; |
536 |
} |
561 |
} |
537 |
$verbose |
562 |
$verbose |
538 |
and warn sprintf "Using letter code '%s' for pass %s\n", $overdue_rules->{ "overdue_$i" . '_notice' }, |
563 |
and warn sprintf "Using letter code '%s' for pass %s\n", |
539 |
$i; |
564 |
$overdue_rules->{ "overdue_$i" . '_notice' }, $i; |
540 |
|
565 |
|
541 |
# $letter->{'content'} is the text of the mail that is sent. |
566 |
# $letter->{'content'} is the text of the mail that is sent. |
542 |
# this text contains fields that are replaced by their value. Those fields must be written between brackets |
567 |
# this text contains fields that are replaced by their value. Those fields must be written between brackets |
543 |
# The following fields are available : |
568 |
# The following fields are available : |
544 |
# 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). |
569 |
# 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). |
545 |
# <date> <itemcount> <firstname> <lastname> <address1> <address2> <address3> <city> <postcode> <country> |
570 |
# <date> <itemcount> <firstname> <lastname> <address1> <address2> <address3> <city> <postcode> <country> |
546 |
|
571 |
|
547 |
my $borrower_sql = <<"END_SQL"; |
572 |
my $borrower_sql = <<"END_SQL"; |
548 |
SELECT issues.borrowernumber, firstname, surname, address, address2, city, zipcode, country, email, emailpro, B_email, smsalertnumber, phone, cardnumber, date_due |
573 |
SELECT issues.borrowernumber, firstname, surname, address, address2, city, zipcode, country, email, emailpro, B_email, smsalertnumber, phone, cardnumber, date_due |
549 |
FROM issues,borrowers,categories,items |
574 |
FROM issues,borrowers,categories,items |
550 |
WHERE issues.borrowernumber=borrowers.borrowernumber |
575 |
WHERE issues.borrowernumber=borrowers.borrowernumber |
Lines 553-823
AND issues.itemnumber = items.itemnumber
Link Here
|
553 |
AND items.itemlost = 0 |
578 |
AND items.itemlost = 0 |
554 |
AND TO_DAYS($date)-TO_DAYS(issues.date_due) >= 0 |
579 |
AND TO_DAYS($date)-TO_DAYS(issues.date_due) >= 0 |
555 |
END_SQL |
580 |
END_SQL |
556 |
my @borrower_parameters; |
581 |
my @borrower_parameters; |
557 |
if ($branchcode) { |
582 |
if ($branchcode) { |
558 |
if ($owning_library) { |
583 |
if ($owning_library) { |
559 |
$borrower_sql .= ' AND items.homebranch=? '; |
584 |
$borrower_sql .= ' AND items.homebranch=? '; |
560 |
} else { |
|
|
561 |
$borrower_sql .= ' AND issues.branchcode=? '; |
562 |
} |
563 |
push @borrower_parameters, $branchcode; |
564 |
} |
565 |
if ($category) { |
566 |
$borrower_sql .= ' AND borrowers.categorycode=? '; |
567 |
push @borrower_parameters, $category; |
568 |
} |
569 |
$borrower_sql .= ' AND categories.overduenoticerequired=1 ORDER BY issues.borrowernumber'; |
570 |
|
571 |
# $sth gets borrower info iff at least one overdue item has triggered the overdue action. |
572 |
my $sth = $dbh->prepare($borrower_sql); |
573 |
$sth->execute(@borrower_parameters); |
574 |
|
575 |
if ( $verbose > 1 ) { |
576 |
warn sprintf "--------Borrower SQL------\n"; |
577 |
warn $borrower_sql |
578 |
. "\n $branchcode | " |
579 |
. $category |
580 |
. "\n ($mindays, $maxdays, " |
581 |
. $date_to_run->datetime() . ")\n"; |
582 |
warn sprintf "--------------------------\n"; |
583 |
} |
584 |
$verbose and warn sprintf "Found %s borrowers with overdues\n", $sth->rows; |
585 |
my $borrowernumber; |
586 |
while ( my $data = $sth->fetchrow_hashref ) { |
587 |
|
588 |
# check the borrower has at least one item that matches |
589 |
my $days_between; |
590 |
if ( C4::Context->preference('OverdueNoticeCalendar') ) { |
591 |
$days_between = $calendar->days_between( |
592 |
dt_from_string( $data->{date_due} ), |
593 |
$date_to_run |
594 |
); |
595 |
} else { |
596 |
$days_between = |
597 |
$date_to_run->delta_days( dt_from_string( $data->{date_due} ) ); |
598 |
} |
599 |
$days_between = $days_between->in_units('days'); |
600 |
if ($triggered) { |
601 |
if ( $mindays != $days_between ) { |
602 |
next; |
603 |
} |
604 |
} else { |
605 |
unless ( $days_between >= $mindays |
606 |
&& $days_between <= $maxdays ) |
607 |
{ |
608 |
next; |
609 |
} |
610 |
} |
611 |
if ( defined $borrowernumber && $borrowernumber eq $data->{'borrowernumber'} ) { |
612 |
|
613 |
# we have already dealt with this borrower |
614 |
$verbose and warn "already dealt with this borrower $borrowernumber"; |
615 |
next; |
616 |
} |
617 |
$borrowernumber = $data->{'borrowernumber'}; |
618 |
next if ( $patron_homelibrary && $already_queued{"$borrowernumber$i"} ); |
619 |
my $borr = sprintf( |
620 |
"%s%s%s (%s)", |
621 |
$data->{'surname'} || '', |
622 |
$data->{'firstname'} && $data->{'surname'} ? ', ' : '', |
623 |
$data->{'firstname'} || '', |
624 |
$borrowernumber |
625 |
); |
626 |
$verbose and warn "borrower $borr has items triggering level $i.\n"; |
627 |
|
628 |
my $patron = Koha::Patrons->find($borrowernumber); |
629 |
if ($patron_homelibrary) { |
630 |
$branchcode = $patron->branchcode; |
631 |
$library = Koha::Libraries->find($branchcode); |
632 |
$admin_email_address = $library->from_email_address; |
633 |
$branch_email_address = C4::Context->preference('AddressForFailedOverdueNotices') |
634 |
|| $library->inbound_email_address; |
635 |
} |
636 |
@emails_to_use = (); |
637 |
my $notice_email = $patron->notice_email_address; |
638 |
unless ($nomail) { |
639 |
if (@emails) { |
640 |
foreach (@emails) { |
641 |
push @emails_to_use, $data->{$_} if ( $data->{$_} ); |
642 |
} |
643 |
} else { |
585 |
} else { |
644 |
push @emails_to_use, $notice_email if ($notice_email); |
586 |
$borrower_sql .= ' AND issues.branchcode=? '; |
645 |
} |
587 |
} |
|
|
588 |
push @borrower_parameters, $branchcode; |
646 |
} |
589 |
} |
647 |
|
590 |
if ($category) { |
648 |
my $letter = Koha::Notice::Templates->find_effective_template( |
591 |
$borrower_sql .= ' AND borrowers.categorycode=? '; |
649 |
{ |
592 |
push @borrower_parameters, $category; |
650 |
module => 'circulation', |
|
|
651 |
code => $overdue_rules->{ "overdue_$i" . '_notice' }, |
652 |
branchcode => $branchcode, |
653 |
lang => $patron->lang |
654 |
} |
655 |
); |
656 |
|
657 |
unless ($letter) { |
658 |
$verbose and warn qq|Message '$overdue_rules->{"overdue_$i"."_notice"}' content not found|; |
659 |
|
660 |
# might as well skip while PERIOD, no other borrowers are going to work. |
661 |
# FIXME : Does this mean a letter must be defined in order to trigger a debar ? |
662 |
next PERIOD; |
663 |
} |
593 |
} |
664 |
|
594 |
$borrower_sql .= ' AND categories.overduenoticerequired=1 ORDER BY issues.borrowernumber'; |
665 |
if ( $overdue_rules->{ "overdue_$i" . '_restrict' } ) { |
595 |
|
666 |
|
596 |
# $sth gets borrower info iff at least one overdue item has triggered the overdue action. |
667 |
#action taken is debarring |
597 |
my $sth = $dbh->prepare($borrower_sql); |
668 |
AddUniqueDebarment( |
598 |
$sth->execute(@borrower_parameters); |
669 |
{ |
599 |
|
670 |
borrowernumber => $borrowernumber, |
600 |
if ( $verbose > 1 ) { |
671 |
type => 'OVERDUES', |
601 |
warn sprintf "--------Borrower SQL------\n"; |
672 |
comment => "OVERDUES_PROCESS " . output_pref( dt_from_string() ), |
602 |
warn $borrower_sql |
673 |
} |
603 |
. "\n $branchcode | " |
674 |
) unless $test_mode; |
604 |
. $category |
675 |
$verbose and warn "debarring $borr\n"; |
605 |
. "\n ($mindays, $maxdays, " |
|
|
606 |
. $date_to_run->datetime() . ")\n"; |
607 |
warn sprintf "--------------------------\n"; |
676 |
} |
608 |
} |
677 |
my @params = $patron_homelibrary ? ($borrowernumber) : ( $borrowernumber, $branchcode ); |
609 |
$verbose and warn sprintf "Found %s borrowers with overdues\n", $sth->rows; |
|
|
610 |
my $borrowernumber; |
611 |
while ( my $data = $sth->fetchrow_hashref ) { |
678 |
|
612 |
|
679 |
$sth2->execute(@params); |
613 |
# check the borrower has at least one item that matches |
680 |
my $itemcount = 0; |
614 |
my $days_between; |
681 |
my $titles = ""; |
|
|
682 |
my @items = (); |
683 |
|
684 |
my $j = 0; |
685 |
my $exceededPrintNoticesMaxLines = 0; |
686 |
while ( my $item_info = $sth2->fetchrow_hashref() ) { |
687 |
if ( C4::Context->preference('OverdueNoticeCalendar') ) { |
615 |
if ( C4::Context->preference('OverdueNoticeCalendar') ) { |
688 |
$days_between = |
616 |
$days_between = $calendar->days_between( |
689 |
$calendar->days_between( dt_from_string( $item_info->{date_due} ), $date_to_run ); |
617 |
dt_from_string( $data->{date_due} ), |
|
|
618 |
$date_to_run |
619 |
); |
690 |
} else { |
620 |
} else { |
691 |
$days_between = $date_to_run->delta_days( dt_from_string( $item_info->{date_due} ) ); |
621 |
$days_between = |
|
|
622 |
$date_to_run->delta_days( dt_from_string( $data->{date_due} ) ); |
692 |
} |
623 |
} |
693 |
$days_between = $days_between->in_units('days'); |
624 |
$days_between = $days_between->in_units('days'); |
694 |
if ($listall) { |
625 |
if ($triggered) { |
695 |
unless ( $days_between >= 1 and $days_between <= $MAX ) { |
626 |
if ( $mindays != $days_between ) { |
696 |
next; |
627 |
next; |
697 |
} |
628 |
} |
698 |
} else { |
629 |
} else { |
699 |
if ($triggered) { |
630 |
unless ( $days_between >= $mindays |
700 |
if ( $mindays != $days_between ) { |
631 |
&& $days_between <= $maxdays ) |
701 |
next; |
632 |
{ |
702 |
} |
633 |
next; |
703 |
} else { |
|
|
704 |
unless ( $days_between >= $mindays |
705 |
&& $days_between <= $maxdays ) |
706 |
{ |
707 |
next; |
708 |
} |
709 |
} |
634 |
} |
710 |
} |
635 |
} |
|
|
636 |
if ( defined $borrowernumber && $borrowernumber eq $data->{'borrowernumber'} ) { |
711 |
|
637 |
|
712 |
if ( ( scalar(@emails_to_use) == 0 || $nomail ) |
638 |
# we have already dealt with this borrower |
713 |
&& $PrintNoticesMaxLines |
639 |
$verbose and warn "already dealt with this borrower $borrowernumber"; |
714 |
&& $j >= $PrintNoticesMaxLines ) |
640 |
next; |
715 |
{ |
641 |
} |
716 |
$exceededPrintNoticesMaxLines = 1; |
642 |
$borrowernumber = $data->{'borrowernumber'}; |
717 |
last; |
643 |
next if ( $patron_homelibrary && $already_queued{"$borrowernumber$i"} ); |
|
|
644 |
my $borr = sprintf( |
645 |
"%s%s%s (%s)", |
646 |
$data->{'surname'} || '', |
647 |
$data->{'firstname'} && $data->{'surname'} ? ', ' : '', |
648 |
$data->{'firstname'} || '', |
649 |
$borrowernumber |
650 |
); |
651 |
$verbose and warn "borrower $borr has items triggering level $i.\n"; |
652 |
|
653 |
my $patron = Koha::Patrons->find($borrowernumber); |
654 |
if ($patron_homelibrary) { |
655 |
$branchcode = $patron->branchcode; |
656 |
$library = Koha::Libraries->find($branchcode); |
657 |
$admin_email_address = $library->from_email_address; |
658 |
$branch_email_address = C4::Context->preference('AddressForFailedOverdueNotices') |
659 |
|| $library->inbound_email_address; |
660 |
} |
661 |
@emails_to_use = (); |
662 |
my $notice_email = $patron->notice_email_address; |
663 |
unless ($nomail) { |
664 |
if (@emails) { |
665 |
foreach (@emails) { |
666 |
push @emails_to_use, $data->{$_} if ( $data->{$_} ); |
667 |
} |
668 |
} else { |
669 |
push @emails_to_use, $notice_email if ($notice_email); |
670 |
} |
718 |
} |
671 |
} |
719 |
next if $patron_homelibrary and !grep { $seen{ $item_info->{branchcode} } } @branches; |
|
|
720 |
$j++; |
721 |
|
672 |
|
722 |
$titles .= C4::Letters::get_item_content( |
673 |
my $letter = Koha::Notice::Templates->find_effective_template( |
723 |
{ item => $item_info, item_content_fields => \@item_content_fields, dateonly => 1 } ); |
674 |
{ |
724 |
$itemcount++; |
675 |
module => 'circulation', |
725 |
push @items, $item_info; |
676 |
code => $overdue_rules->{ "overdue_$i" . '_notice' }, |
726 |
} |
677 |
branchcode => $branchcode, |
727 |
$sth2->finish; |
678 |
lang => $patron->lang |
|
|
679 |
} |
680 |
); |
728 |
|
681 |
|
729 |
my @message_transport_types = split( /,/, $overdue_rules->{ "overdue_$i" . '_mtt' } ); |
682 |
unless ($letter) { |
|
|
683 |
$verbose and warn qq|Message '$overdue_rules->{"overdue_$i"."_notice"}' content not found|; |
730 |
|
684 |
|
731 |
my $print_sent = 0; # A print notice is not yet sent for this patron |
685 |
# might as well skip while PERIOD, no other borrowers are going to work. |
732 |
for my $mtt (@message_transport_types) { |
686 |
# FIXME : Does this mean a letter must be defined in order to trigger a debar ? |
733 |
next if $mtt eq 'itiva'; |
687 |
next PERIOD; |
734 |
my $effective_mtt = $mtt; |
|
|
735 |
if ( ( $mtt eq 'email' and not scalar @emails_to_use ) |
736 |
or ( $mtt eq 'sms' and not $data->{smsalertnumber} ) ) |
737 |
{ |
738 |
# email or sms is requested but not exist, do a print. |
739 |
$effective_mtt = 'print'; |
740 |
} |
688 |
} |
741 |
splice @items, $PrintNoticesMaxLines |
|
|
742 |
if $effective_mtt eq 'print' && $PrintNoticesMaxLines && scalar @items > $PrintNoticesMaxLines; |
743 |
|
689 |
|
744 |
#catch the case where we are sending a print to someone with an email |
690 |
if ( $overdue_rules->{ "overdue_$i" . '_restrict' } ) { |
745 |
|
691 |
|
746 |
my $letter_exists = Koha::Notice::Templates->find_effective_template( |
692 |
#action taken is debarring |
747 |
{ |
693 |
AddUniqueDebarment( |
748 |
module => 'circulation', |
694 |
{ |
749 |
code => $overdue_rules->{ "overdue_$i" . '_notice' }, |
695 |
borrowernumber => $borrowernumber, |
750 |
message_transport_type => $effective_mtt, |
696 |
type => 'OVERDUES', |
751 |
branchcode => $branchcode, |
697 |
comment => "OVERDUES_PROCESS " . output_pref( dt_from_string() ), |
752 |
lang => $patron->lang |
698 |
} |
|
|
699 |
) unless $test_mode; |
700 |
$verbose and warn "debarring $borr\n"; |
701 |
} |
702 |
my @params = $patron_homelibrary ? ($borrowernumber) : ( $borrowernumber, $branchcode ); |
703 |
|
704 |
$sth2->execute(@params); |
705 |
my $itemcount = 0; |
706 |
my $titles = ""; |
707 |
my @items = (); |
708 |
|
709 |
my $j = 0; |
710 |
my $exceededPrintNoticesMaxLines = 0; |
711 |
while ( my $item_info = $sth2->fetchrow_hashref() ) { |
712 |
if ( C4::Context->preference('OverdueNoticeCalendar') ) { |
713 |
$days_between = |
714 |
$calendar->days_between( dt_from_string( $item_info->{date_due} ), $date_to_run ); |
715 |
} else { |
716 |
$days_between = $date_to_run->delta_days( dt_from_string( $item_info->{date_due} ) ); |
717 |
} |
718 |
$days_between = $days_between->in_units('days'); |
719 |
if ($listall) { |
720 |
unless ( $days_between >= 1 and $days_between <= $MAX ) { |
721 |
next; |
722 |
} |
723 |
} else { |
724 |
if ($triggered) { |
725 |
if ( $mindays != $days_between ) { |
726 |
next; |
727 |
} |
728 |
} else { |
729 |
unless ( $days_between >= $mindays |
730 |
&& $days_between <= $maxdays ) |
731 |
{ |
732 |
next; |
733 |
} |
734 |
} |
753 |
} |
735 |
} |
754 |
); |
|
|
755 |
|
736 |
|
756 |
my $letter = parse_overdues_letter( |
737 |
if ( ( scalar(@emails_to_use) == 0 || $nomail ) |
|
|
738 |
&& $PrintNoticesMaxLines |
739 |
&& $j >= $PrintNoticesMaxLines ) |
757 |
{ |
740 |
{ |
758 |
letter_code => $overdue_rules->{ "overdue_$i" . '_notice' }, |
741 |
$exceededPrintNoticesMaxLines = 1; |
759 |
borrowernumber => $borrowernumber, |
742 |
last; |
760 |
branchcode => $branchcode, |
|
|
761 |
items => \@items, |
762 |
substitute => { # this appears to be a hack to overcome incomplete features in this code. |
763 |
bib => $library->branchname, # maybe 'bib' is a typo for 'lib<rary>'? |
764 |
'items.content' => $titles, |
765 |
'count' => $itemcount, |
766 |
}, |
767 |
|
768 |
# If there is no template defined for the requested letter |
769 |
# Fallback on the original type |
770 |
message_transport_type => $letter_exists ? $effective_mtt : $mtt, |
771 |
} |
743 |
} |
772 |
); |
744 |
next if $patron_homelibrary and !grep { $seen{ $item_info->{branchcode} } } @branches; |
773 |
unless ( $letter && $letter->{content} ) { |
745 |
$j++; |
774 |
$verbose and warn qq|Message '$overdue_rules->{"overdue_$i"."_notice"}' content not found|; |
|
|
775 |
|
746 |
|
776 |
# this transport doesn't have a configured notice, so try another |
747 |
$titles .= C4::Letters::get_item_content( |
777 |
next; |
748 |
{ item => $item_info, item_content_fields => \@item_content_fields, dateonly => 1 } ); |
|
|
749 |
$itemcount++; |
750 |
push @items, $item_info; |
778 |
} |
751 |
} |
|
|
752 |
$sth2->finish; |
779 |
|
753 |
|
780 |
if ($exceededPrintNoticesMaxLines) { |
754 |
my @message_transport_types = split( /,/, $overdue_rules->{ "overdue_$i" . '_mtt' } ); |
781 |
$letter->{'content'} .= |
|
|
782 |
"List too long for form; please check your account online for a complete list of your overdue items."; |
783 |
} |
784 |
|
755 |
|
785 |
my @misses = grep { /./ } map { /^([^>]*)[>]+/; ( $1 || '' ); } split /\</, $letter->{'content'}; |
756 |
my $print_sent = 0; # A print notice is not yet sent for this patron |
786 |
if (@misses) { |
757 |
for my $mtt (@message_transport_types) { |
787 |
$verbose |
758 |
next if $mtt eq 'itiva'; |
788 |
and warn "The following terms were not matched and replaced: \n\t" . join "\n\t", @misses; |
759 |
my $effective_mtt = $mtt; |
789 |
} |
760 |
if ( ( $mtt eq 'email' and not scalar @emails_to_use ) |
|
|
761 |
or ( $mtt eq 'sms' and not $data->{smsalertnumber} ) ) |
762 |
{ |
763 |
# email or sms is requested but not exist, do a print. |
764 |
$effective_mtt = 'print'; |
765 |
} |
766 |
splice @items, $PrintNoticesMaxLines |
767 |
if $effective_mtt eq 'print' |
768 |
&& $PrintNoticesMaxLines |
769 |
&& scalar @items > $PrintNoticesMaxLines; |
770 |
|
771 |
#catch the case where we are sending a print to someone with an email |
772 |
|
773 |
my $letter_exists = Koha::Notice::Templates->find_effective_template( |
774 |
{ |
775 |
module => 'circulation', |
776 |
code => $overdue_rules->{ "overdue_$i" . '_notice' }, |
777 |
message_transport_type => $effective_mtt, |
778 |
branchcode => $branchcode, |
779 |
lang => $patron->lang |
780 |
} |
781 |
); |
790 |
|
782 |
|
791 |
if ($nomail) { |
783 |
my $letter = parse_overdues_letter( |
792 |
push @output_chunks, |
|
|
793 |
prepare_letter_for_printing( |
794 |
{ |
784 |
{ |
795 |
letter => $letter, |
785 |
letter_code => $overdue_rules->{ "overdue_$i" . '_notice' }, |
796 |
borrowernumber => $borrowernumber, |
786 |
borrowernumber => $borrowernumber, |
797 |
firstname => $data->{'firstname'}, |
787 |
branchcode => $branchcode, |
798 |
lastname => $data->{'surname'}, |
788 |
items => \@items, |
799 |
address1 => $data->{'address'}, |
789 |
substitute => |
800 |
address2 => $data->{'address2'}, |
790 |
{ # this appears to be a hack to overcome incomplete features in this code. |
801 |
city => $data->{'city'}, |
791 |
bib => $library->branchname, # maybe 'bib' is a typo for 'lib<rary>'? |
802 |
phone => $data->{'phone'}, |
792 |
'items.content' => $titles, |
803 |
cardnumber => $data->{'cardnumber'}, |
793 |
'count' => $itemcount, |
804 |
branchname => $library->branchname, |
794 |
}, |
805 |
letternumber => $i, |
795 |
|
806 |
postcode => $data->{'zipcode'}, |
796 |
# If there is no template defined for the requested letter |
807 |
country => $data->{'country'}, |
797 |
# Fallback on the original type |
808 |
email => $notice_email, |
798 |
message_transport_type => $letter_exists ? $effective_mtt : $mtt, |
809 |
itemcount => $itemcount, |
|
|
810 |
titles => $titles, |
811 |
outputformat => defined $csvfilename ? 'csv' |
812 |
: defined $htmlfilename ? 'html' |
813 |
: defined $text_filename ? 'text' |
814 |
: '', |
815 |
} |
799 |
} |
816 |
); |
800 |
); |
817 |
} else { |
801 |
unless ( $letter && $letter->{content} ) { |
818 |
if ( ( $mtt eq 'email' and not scalar @emails_to_use ) |
802 |
$verbose and warn qq|Message '$overdue_rules->{"overdue_$i"."_notice"}' content not found|; |
819 |
or ( $mtt eq 'sms' and not $data->{smsalertnumber} ) ) |
803 |
|
820 |
{ |
804 |
# this transport doesn't have a configured notice, so try another |
|
|
805 |
next; |
806 |
} |
807 |
|
808 |
if ($exceededPrintNoticesMaxLines) { |
809 |
$letter->{'content'} .= |
810 |
"List too long for form; please check your account online for a complete list of your overdue items."; |
811 |
} |
812 |
|
813 |
my @misses = grep { /./ } map { /^([^>]*)[>]+/; ( $1 || '' ); } split /\</, |
814 |
$letter->{'content'}; |
815 |
if (@misses) { |
816 |
$verbose |
817 |
and warn "The following terms were not matched and replaced: \n\t" . join "\n\t", |
818 |
@misses; |
819 |
} |
820 |
|
821 |
if ($nomail) { |
821 |
push @output_chunks, |
822 |
push @output_chunks, |
822 |
prepare_letter_for_printing( |
823 |
prepare_letter_for_printing( |
823 |
{ |
824 |
{ |
Lines 828-833
END_SQL
Link Here
|
828 |
address1 => $data->{'address'}, |
829 |
address1 => $data->{'address'}, |
829 |
address2 => $data->{'address2'}, |
830 |
address2 => $data->{'address2'}, |
830 |
city => $data->{'city'}, |
831 |
city => $data->{'city'}, |
|
|
832 |
phone => $data->{'phone'}, |
833 |
cardnumber => $data->{'cardnumber'}, |
834 |
branchname => $library->branchname, |
835 |
letternumber => $i, |
831 |
postcode => $data->{'zipcode'}, |
836 |
postcode => $data->{'zipcode'}, |
832 |
country => $data->{'country'}, |
837 |
country => $data->{'country'}, |
833 |
email => $notice_email, |
838 |
email => $notice_email, |
Lines 839-868
END_SQL
Link Here
|
839 |
: '', |
844 |
: '', |
840 |
} |
845 |
} |
841 |
); |
846 |
); |
842 |
} |
847 |
} else { |
843 |
unless ( $effective_mtt eq 'print' and $print_sent == 1 ) { |
848 |
if ( ( $mtt eq 'email' and not scalar @emails_to_use ) |
844 |
|
849 |
or ( $mtt eq 'sms' and not $data->{smsalertnumber} ) ) |
845 |
# Just sent a print if not already done. |
850 |
{ |
846 |
C4::Letters::EnqueueLetter( |
851 |
push @output_chunks, |
847 |
{ |
852 |
prepare_letter_for_printing( |
848 |
letter => $letter, |
853 |
{ |
849 |
borrowernumber => $borrowernumber, |
854 |
letter => $letter, |
850 |
message_transport_type => $effective_mtt, |
855 |
borrowernumber => $borrowernumber, |
851 |
from_address => $admin_email_address, |
856 |
firstname => $data->{'firstname'}, |
852 |
to_address => join( ',', @emails_to_use ), |
857 |
lastname => $data->{'surname'}, |
853 |
reply_address => $library->inbound_email_address, |
858 |
address1 => $data->{'address'}, |
854 |
} |
859 |
address2 => $data->{'address2'}, |
855 |
) unless $test_mode; |
860 |
city => $data->{'city'}, |
856 |
|
861 |
postcode => $data->{'zipcode'}, |
857 |
# A print notice should be sent only once per overdue level. |
862 |
country => $data->{'country'}, |
858 |
# 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. |
863 |
email => $notice_email, |
859 |
$print_sent = 1 if $effective_mtt eq 'print'; |
864 |
itemcount => $itemcount, |
|
|
865 |
titles => $titles, |
866 |
outputformat => defined $csvfilename ? 'csv' |
867 |
: defined $htmlfilename ? 'html' |
868 |
: defined $text_filename ? 'text' |
869 |
: '', |
870 |
} |
871 |
); |
872 |
} |
873 |
unless ( $effective_mtt eq 'print' and $print_sent == 1 ) { |
874 |
|
875 |
# Just sent a print if not already done. |
876 |
C4::Letters::EnqueueLetter( |
877 |
{ |
878 |
letter => $letter, |
879 |
borrowernumber => $borrowernumber, |
880 |
message_transport_type => $effective_mtt, |
881 |
from_address => $admin_email_address, |
882 |
to_address => join( ',', @emails_to_use ), |
883 |
reply_address => $library->inbound_email_address, |
884 |
} |
885 |
) unless $test_mode; |
886 |
|
887 |
# A print notice should be sent only once per overdue level. |
888 |
# 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. |
889 |
$print_sent = 1 if $effective_mtt eq 'print'; |
890 |
} |
860 |
} |
891 |
} |
861 |
} |
892 |
} |
|
|
893 |
$already_queued{"$borrowernumber$i"} = 1; |
862 |
} |
894 |
} |
863 |
$already_queued{"$borrowernumber$i"} = 1; |
895 |
$sth->finish; |
864 |
} |
896 |
} |
865 |
$sth->finish; |
|
|
866 |
} |
897 |
} |
867 |
} |
898 |
} |
868 |
|
899 |
|
869 |
- |
|
|