# 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; FIXME - Bug 2505
-use Date::Calc qw/Today Date_to_Days/;
-use Date::Manip qw/UnixDate/;
+use Modern::Perl;
+use Date::Calc qw( Today );
+use Date::Manip qw( UnixDate );
use List::MoreUtils qw( uniq );
-use POSIX qw( floor ceil );
-use Locale::Currency::Format 1.28;
-use Carp;
+use POSIX qw( ceil floor );
+use Locale::Currency::Format 1.28 qw( currency_format FMT_SYMBOL );
+use Carp qw( carp );
-use C4::Circulation;
use C4::Context;
use C4::Accounts;
-use C4::Log; # logaction
-use C4::Debug;
-use Koha::DateUtils;
-use Koha::Account::Line;
+use Koha::Logger;
use Koha::Account::Lines;
-use Koha::IssuingRules;
+use Koha::Account::Offsets;
use Koha::Libraries;
+use Koha::Recalls;
-use vars qw(@ISA @EXPORT);
-
+our (@ISA, @EXPORT_OK);
BEGIN {
require Exporter;
@ISA = qw(Exporter);
# subs to rename (and maybe merge some...)
- push @EXPORT, qw(
- &CalcFine
- &Getoverdues
- &checkoverdues
- &NumberNotifyId
- &AmountNotify
- &UpdateFine
- &GetFine
- &get_chargeable_units
- &CheckItemNotify
- &GetOverduesForBranch
- &RemoveNotifyLine
- &AddNotifyLine
- &GetOverdueMessageTransportTypes
- &parse_overdues_letter
- );
-
- # subs to remove
- push @EXPORT, qw(
- &BorType
- );
-
- # check that an equivalent don't exist already before moving
-
- # subs to move to Circulation.pm
- push @EXPORT, qw(
- &GetIssuesIteminfo
- );
-
- # subs to move to Biblio.pm
- push @EXPORT, qw(
- &GetItems
+ @EXPORT_OK = qw(
+ CalcFine
+ Getoverdues
+ checkoverdues
+ UpdateFine
+ GetFine
+ GetBranchcodesWithOverdueRules
+ get_chargeable_units
+ GetOverduesForBranch
+ GetOverdueMessageTransportTypes
+ parse_overdues_letter
+ GetIssuesIteminfo
);
}
my $statement;
if ( C4::Context->preference('item-level_itypes') ) {
$statement = "
- SELECT issues.*, items.itype as itemtype, items.homebranch, items.barcode, items.itemlost, items.replacementprice
+ SELECT issues.*, items.itype as itemtype, items.homebranch, items.barcode, items.itemlost, items.replacementprice, items.biblionumber
FROM issues
LEFT JOIN items USING (itemnumber)
WHERE date_due < NOW()
";
} else {
$statement = "
- SELECT issues.*, biblioitems.itemtype, items.itype, items.homebranch, items.barcode, items.itemlost, replacementprice
+ SELECT issues.*, biblioitems.itemtype, items.itype, items.homebranch, items.barcode, items.itemlost, replacementprice, items.biblionumber
FROM issues
LEFT JOIN items USING (itemnumber)
LEFT JOIN biblioitems USING (biblioitemnumber)
sub checkoverdues {
my $borrowernumber = shift or return;
- # don't select biblioitems.marcxml... too slow on large systems
my $sth = C4::Context->dbh->prepare(
"SELECT biblio.*, items.*, issues.*,
biblioitems.volume,
=head2 CalcFine
- ($amount, $chargename, $units_minus_grace, $chargeable_units) = &CalcFine($item,
+ ($amount, $units_minus_grace, $chargeable_units) = &CalcFine($item,
$categorycode, $branch,
$start_dt, $end_dt );
Fines scripts should just supply the date range over which to calculate the fine.
-C<&CalcFine> returns four values:
+C<&CalcFine> returns three values:
C<$amount> is the fine owed by the patron (see above).
-C<$chargename> is the chargename field from the applicable record in
-the categoryitem table, whatever that is.
-
C<$units_minus_grace> is the number of chargeable units minus the grace period
C<$chargeable_units> is the number of chargeable units (days between start and end dates, Calendar adjusted where needed,
sub CalcFine {
my ( $item, $bortype, $branchcode, $due_dt, $end_date ) = @_;
+
+ # Skip calculations if item is not overdue
+ return ( 0, 0, 0 ) unless (DateTime->compare( $due_dt, $end_date ) == -1);
+
my $start_date = $due_dt->clone();
# get issuingrules (fines part will be used)
my $itemtype = $item->{itemtype} || $item->{itype};
- my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule({ categorycode => $bortype, itemtype => $itemtype, branchcode => $branchcode });
+ my $issuing_rule = Koha::CirculationRules->get_effective_rules(
+ {
+ categorycode => $bortype,
+ itemtype => $itemtype,
+ branchcode => $branchcode,
+ rules => [
+ 'lengthunit',
+ 'firstremind',
+ 'chargeperiod',
+ 'chargeperiod_charge_at',
+ 'fine',
+ 'overduefinescap',
+ 'cap_fine_to_replacement_price',
+ 'recall_overdue_fine',
+ ]
+ }
+ );
+
+ $itemtype = Koha::ItemTypes->find($itemtype);
return unless $issuing_rule; # If not rule exist, there is no fine
- my $fine_unit = $issuing_rule->lengthunit || 'days';
+ my $fine_unit = $issuing_rule->{lengthunit} || 'days';
my $chargeable_units = get_chargeable_units($fine_unit, $start_date, $end_date, $branchcode);
- my $units_minus_grace = $chargeable_units - $issuing_rule->firstremind;
+ my $units_minus_grace = $chargeable_units - ($issuing_rule->{firstremind} || 0);
my $amount = 0;
- if ( $issuing_rule->chargeperiod && ( $units_minus_grace > 0 ) ) {
+ if ( $issuing_rule->{chargeperiod} && ( $units_minus_grace > 0 ) ) {
my $units = C4::Context->preference('FinesIncludeGracePeriod') ? $chargeable_units : $units_minus_grace;
- my $charge_periods = $units / $issuing_rule->chargeperiod;
+ my $charge_periods = $units / $issuing_rule->{chargeperiod};
# If chargeperiod_charge_at = 1, we charge a fine at the start of each charge period
# if chargeperiod_charge_at = 0, we charge at the end of each charge period
- $charge_periods = $issuing_rule->chargeperiod_charge_at == 1 ? ceil($charge_periods) : floor($charge_periods);
- $amount = $charge_periods * $issuing_rule->fine;
+ $charge_periods = defined $issuing_rule->{chargeperiod_charge_at} && $issuing_rule->{chargeperiod_charge_at} == 1 ? ceil($charge_periods) : floor($charge_periods);
+
+ # check if item has been recalled. recall should have been marked Overdue by cronjob, so only look at overdue recalls
+ # only charge using recall_overdue_fine if there is an item-level recall for this particular item, OR a biblio-level recall
+ my @recalls = Koha::Recalls->search({ biblio_id => $item->{biblionumber}, status => 'overdue' })->as_list;
+ my $bib_level_recall = 0;
+ $bib_level_recall = 1 if scalar @recalls > 0;
+ foreach my $recall ( @recalls ) {
+ if ( $recall->item_level and $recall->item_id == $item->{itemnumber} and $issuing_rule->{recall_overdue_fine} ) {
+ $bib_level_recall = 0;
+ $amount = $charge_periods * $issuing_rule->{recall_overdue_fine};
+ last;
+ }
+ }
+ if ( $bib_level_recall and $issuing_rule->{recall_overdue_fine} ) {
+ # biblio-level recall
+ $amount = $charge_periods * $issuing_rule->{recall_overdue_fine};
+ }
+ if ( scalar @recalls == 0 && $issuing_rule->{fine}) {
+ # no recall, use normal fine amount
+ $amount = $charge_periods * $issuing_rule->{fine};
+ }
} # else { # a zero (or null) chargeperiod or negative units_minus_grace value means no charge. }
- $amount = $issuing_rule->overduefinescap if $issuing_rule->overduefinescap && $amount > $issuing_rule->overduefinescap;
- $amount = $item->{replacementprice} if ( $issuing_rule->cap_fine_to_replacement_price && $item->{replacementprice} && $amount > $item->{replacementprice} );
- $debug and warn sprintf("CalcFine returning (%s, %s, %s, %s)", $amount, $issuing_rule->chargename, $units_minus_grace, $chargeable_units);
- return ($amount, $issuing_rule->chargename, $units_minus_grace, $chargeable_units);
- # FIXME: chargename is NEVER populated anywhere.
+ $amount = $issuing_rule->{overduefinescap} if $issuing_rule->{overduefinescap} && $amount > $issuing_rule->{overduefinescap};
+
+ # This must be moved to Koha::Item (see also similar code in C4::Accounts::chargelostitem
+ $item->{replacementprice} ||= $itemtype->defaultreplacecost
+ if $itemtype
+ && ( ! defined $item->{replacementprice} || $item->{replacementprice} == 0 )
+ && C4::Context->preference("useDefaultReplacementCost");
+
+ $amount = $item->{replacementprice} if ( $issuing_rule->{cap_fine_to_replacement_price} && $item->{replacementprice} && $amount > $item->{replacementprice} );
+
+ return ($amount, $units_minus_grace, $chargeable_units);
}
=head2 UpdateFine
- &UpdateFine({ issue_id => $issue_id, itemnumber => $itemnumber, borrwernumber => $borrowernumber, amount => $amount, type => $type, $due => $date_due });
+ &UpdateFine(
+ {
+ issue_id => $issue_id,
+ itemnumber => $itemnumber,
+ borrowernumber => $borrowernumber,
+ amount => $amount,
+ due => $date_due
+ }
+ );
(Note: the following is mostly conjecture and guesswork.)
C<$amount> is the current amount owed by the patron.
-C<$type> will be used in the description of the fine.
-
C<$due> is the due date formatted to the currently specified date format
C<&UpdateFine> looks up the amount currently owed on the given item
my $itemnum = $params->{itemnumber};
my $borrowernumber = $params->{borrowernumber};
my $amount = $params->{amount};
- my $type = $params->{type};
- my $due = $params->{due};
-
- $debug and warn "UpdateFine({ itemnumber => $itemnum, borrowernumber => $borrowernumber, type => $type, due => $due, issue_id => $issue_id})";
+ my $due = $params->{due} // q{};
unless ( $issue_id ) {
carp("No issue_id passed in!");
}
my $dbh = C4::Context->dbh;
- # FIXME - What exactly is this query supposed to do? It looks up an
- # entry in accountlines that matches the given item and borrower
- # numbers, where the description contains $due, and where the
- # account type has one of several values, but what does this _mean_?
- # Does it look up existing fines for this item?
- # FIXME - What are these various account types? ("FU", "O", "F", "M")
- # "L" is LOST item
- # "A" is Account Management Fee
- # "N" is New Card
- # "M" is Sundry
- # "O" is Overdue ??
- # "F" is Fine ??
- # "FU" is Fine UPDATE??
- # "Pay" is Payment
- # "REF" is Cash Refund
- my $sth = $dbh->prepare(
- "SELECT * FROM accountlines
- WHERE borrowernumber=? AND
- (( accounttype IN ('O','F','M') AND amountoutstanding<>0 ) OR
- accounttype = 'FU' )"
+ my $overdues = Koha::Account::Lines->search(
+ {
+ borrowernumber => $borrowernumber,
+ debit_type_code => 'OVERDUE'
+ }
);
- $sth->execute( $borrowernumber );
- my $data;
+
+ my $accountline;
my $total_amount_other = 0.00;
my $due_qr = qr/$due/;
# Cycle through the fines and
# - find line that relates to the requested $itemnum
# - accumulate fines for other items
# so we can update $itemnum fine taking in account fine caps
- while (my $rec = $sth->fetchrow_hashref) {
- if ( $rec->{issue_id} == $issue_id && $rec->{accounttype} eq 'FU' ) {
- if ($data) {
- warn "Not a unique accountlines record for issue_id $issue_id";
+ while (my $overdue = $overdues->next) {
+ if ( defined $overdue->issue_id && $overdue->issue_id == $issue_id && $overdue->status eq 'UNRETURNED' ) {
+ if ($accountline) {
+ Koha::Logger->get->debug("Not a unique accountlines record for issue_id $issue_id"); # FIXME Do we really need to log that?
#FIXME Should we still count this one in total_amount ??
}
else {
- $data = $rec;
- next;
+ $accountline = $overdue;
}
}
- $total_amount_other += $rec->{'amountoutstanding'};
+ $total_amount_other += $overdue->amountoutstanding;
}
- if (my $maxfine = C4::Context->preference('MaxFine')) {
- if ($total_amount_other + $amount > $maxfine) {
- my $new_amount = $maxfine - $total_amount_other;
- return if $new_amount <= 0.00;
- warn "Reducing fine for item $itemnum borrower $borrowernumber from $amount to $new_amount - MaxFine reached";
- $amount = $new_amount;
+ if ( my $maxfine = C4::Context->preference('MaxFine') ) {
+ my $maxIncrease = $maxfine - $total_amount_other;
+ return if Koha::Number::Price->new($maxIncrease)->round <= 0.00;
+ if ($accountline) {
+ if ( ( $amount - $accountline->amount ) > $maxIncrease ) {
+ my $new_amount = $accountline->amount + $maxIncrease;
+ Koha::Logger->get->debug("Reducing fine for item $itemnum borrower $borrowernumber from $amount to $new_amount - MaxFine reached");
+ $amount = $new_amount;
+ }
+ }
+ elsif ( $amount > $maxIncrease ) {
+ Koha::Logger->get->debug("Reducing fine for item $itemnum borrower $borrowernumber from $amount to $maxIncrease - MaxFine reached");
+ $amount = $maxIncrease;
}
}
- if ( $data ) {
- # we're updating an existing fine. Only modify if amount changed
- # Note that in the current implementation, you cannot pay against an accruing fine
- # (i.e. , of accounttype 'FU'). Doing so will break accrual.
- if ( $data->{'amount'} != $amount ) {
- my $accountline = Koha::Account::Lines->find( $data->{accountlines_id} );
- my $diff = $amount - $data->{'amount'};
-
- #3341: diff could be positive or negative!
- my $out = $data->{'amountoutstanding'} + $diff;
-
- $accountline->set(
+ if ( $accountline ) {
+ if ( Koha::Number::Price->new($accountline->amount)->round != Koha::Number::Price->new($amount)->round ) {
+ $accountline->adjust(
{
- date => dt_from_string(),
- amount => $amount,
- amountoutstanding => $out,
- lastincrement => $diff,
- accounttype => 'FU',
+ amount => $amount,
+ type => 'overdue_update',
+ interface => C4::Context->interface
}
- )->store();
+ );
}
} else {
if ( $amount ) { # Don't add new fines with an amount of 0
);
$sth4->execute($itemnum);
my $title = $sth4->fetchrow;
+ my $desc = "$title $due";
- my $nextaccntno = C4::Accounts::getnextacctno($borrowernumber);
-
- my $desc = ( $type ? "$type " : '' ) . "$title $due"; # FIXEDME, avoid whitespace prefix on empty $type
-
- my $accountline = Koha::Account::Line->new(
+ my $account = Koha::Account->new({ patron_id => $borrowernumber });
+ $accountline = $account->add_debit(
{
- borrowernumber => $borrowernumber,
- itemnumber => $itemnum,
- date => dt_from_string(),
- amount => $amount,
- description => $desc,
- accounttype => 'FU',
- amountoutstanding => $amount,
- lastincrement => $amount,
- accountno => $nextaccntno,
- issue_id => $issue_id,
+ amount => $amount,
+ description => $desc,
+ note => undef,
+ user_id => undef,
+ interface => C4::Context->interface,
+ library_id => undef, #FIXME: Should we grab the checkout or circ-control branch here perhaps?
+ type => 'OVERDUE',
+ item_id => $itemnum,
+ issue_id => $issue_id,
}
- )->store();
+ );
}
}
- # logging action
- &logaction(
- "FINES",
- $type,
- $borrowernumber,
- "due=".$due." amount=".$amount." itemnumber=".$itemnum
- ) if C4::Context->preference("FinesLog");
-}
-
-=head2 BorType
-
- $borrower = &BorType($borrowernumber);
-
-Looks up a patron by borrower number.
-
-C<$borrower> is a reference-to-hash whose keys are all of the fields
-from the borrowers and categories tables of the Koha database. Thus,
-C<$borrower> contains all information about both the borrower and
-category he or she belongs to.
-
-=cut
-
-sub BorType {
- my ($borrowernumber) = @_;
- my $dbh = C4::Context->dbh;
- my $sth = $dbh->prepare(
- "SELECT * from borrowers
- LEFT JOIN categories ON borrowers.categorycode=categories.categorycode
- WHERE borrowernumber=?"
- );
- $sth->execute($borrowernumber);
- return $sth->fetchrow_hashref;
}
=head2 GetFine
my ( $itemnum, $borrowernumber ) = @_;
my $dbh = C4::Context->dbh();
my $query = q|SELECT sum(amountoutstanding) as fineamount FROM accountlines
- where accounttype like 'F%'
+ WHERE debit_type_code = 'OVERDUE'
AND amountoutstanding > 0 AND borrowernumber=?|;
my @query_param;
push @query_param, $borrowernumber;
return 0;
}
-=head2 NumberNotifyId
-
- (@notify) = &NumberNotifyId($borrowernumber);
-
-Returns amount for all file per borrowers
-C<@notify> array contains all file per borrowers
-
-C<$notify_id> contains the file number for the borrower number nad item number
-
-=cut
-
-sub NumberNotifyId{
- my ($borrowernumber)=@_;
- my $dbh = C4::Context->dbh;
- my $query=qq| SELECT distinct(notify_id)
- FROM accountlines
- WHERE borrowernumber=?|;
- my @notify;
- my $sth = $dbh->prepare($query);
- $sth->execute($borrowernumber);
- while ( my ($numberofnotify) = $sth->fetchrow ) {
- push( @notify, $numberofnotify );
- }
- return (@notify);
-}
-
-=head2 AmountNotify
-
- ($totalnotify) = &AmountNotify($notifyid);
-
-Returns amount for all file per borrowers
-C<$notifyid> is the file number
-
-C<$totalnotify> contains amount of a file
-
-C<$notify_id> contains the file number for the borrower number and item number
-
-=cut
-
-sub AmountNotify{
- my ($notifyid,$borrowernumber)=@_;
- my $dbh = C4::Context->dbh;
- my $query=qq| SELECT sum(amountoutstanding)
- FROM accountlines
- WHERE notify_id=? AND borrowernumber = ?|;
- my $sth=$dbh->prepare($query);
- $sth->execute($notifyid,$borrowernumber);
- my $totalnotify=$sth->fetchrow;
- $sth->finish;
- return ($totalnotify);
-}
-
-=head2 GetItems
-
- ($items) = &GetItems($itemnumber);
-
-Returns the list of all delays from overduerules.
-
-C<$items> is a reference-to-hash whose keys are all of the fields
-from the items tables of the Koha database. Thus,
-
-C<$itemnumber> contains the borrower categorycode
-
-=cut
-
-# FIXME: This is a bad function to have here.
-# Shouldn't it be in C4::Items?
-# Shouldn't it be called GetItem since you only get 1 row?
-# Shouldn't it be called GetItem since you give it only 1 itemnumber?
-
-sub GetItems {
- my $itemnumber = shift or return;
- my $query = qq|SELECT *
- FROM items
- WHERE itemnumber=?|;
- my $sth = C4::Context->dbh->prepare($query);
- $sth->execute($itemnumber);
- my ($items) = $sth->fetchrow_hashref;
- return ($items);
-}
-
=head2 GetBranchcodesWithOverdueRules
my @branchcodes = C4::Overdues::GetBranchcodesWithOverdueRules()
|);
if ( $branchcodes->[0] eq '' ) {
# If a default rule exists, all branches should be returned
- return map { $_->branchcode } Koha::Libraries->search({}, { order_by => 'branchname' });
+ return Koha::Libraries->search({}, { order_by => 'branchname' })->get_column('branchcode');
}
return @$branchcodes;
}
-=head2 CheckItemNotify
-
-Sql request to check if the document has alreday been notified
-this function is not exported, only used with GetOverduesForBranch
-
-=cut
-
-sub CheckItemNotify {
- my ($notify_id,$notify_level,$itemnumber) = @_;
- my $dbh = C4::Context->dbh;
- my $sth = $dbh->prepare("
- SELECT COUNT(*)
- FROM notifys
- WHERE notify_id = ?
- AND notify_level = ?
- AND itemnumber = ? ");
- $sth->execute($notify_id,$notify_level,$itemnumber);
- my $notified = $sth->fetchrow;
- return ($notified);
-}
-
=head2 GetOverduesForBranch
Sql request for display all information for branchoverdues.pl
borrowers.phone,
borrowers.email,
biblio.title,
+ biblio.subtitle,
+ biblio.medium,
+ biblio.part_number,
+ biblio.part_name,
biblio.author,
biblio.biblionumber,
issues.date_due,
items.location,
items.itemnumber,
itemtypes.description,
- accountlines.notify_id,
- accountlines.notify_level,
accountlines.amountoutstanding
FROM accountlines
LEFT JOIN issues ON issues.itemnumber = accountlines.itemnumber
LEFT JOIN itemtypes ON itemtypes.itemtype = $itype_link
LEFT JOIN branches ON branches.branchcode = issues.branchcode
WHERE (accountlines.amountoutstanding != '0.000000')
- AND (accountlines.accounttype = 'FU' )
+ AND (accountlines.debit_type_code = 'OVERDUE' )
+ AND (accountlines.status = 'UNRETURNED' )
AND (issues.branchcode = ? )
AND (issues.date_due < NOW())
";
- my @getoverdues;
- my $i = 0;
- my $sth;
if ($location) {
- $sth = $dbh->prepare("$select AND items.location = ? ORDER BY borrowers.surname, borrowers.firstname");
- $sth->execute($branch, $location);
+ my $q = "$select AND items.location = ? ORDER BY borrowers.surname, borrowers.firstname";
+ return @{ $dbh->selectall_arrayref($q, { Slice => {} }, $branch, $location ) };
} else {
- $sth = $dbh->prepare("$select ORDER BY borrowers.surname, borrowers.firstname");
- $sth->execute($branch);
- }
- while ( my $data = $sth->fetchrow_hashref ) {
- #check if the document has already been notified
- my $countnotify = CheckItemNotify($data->{'notify_id'}, $data->{'notify_level'}, $data->{'itemnumber'});
- if ($countnotify eq '0') {
- $getoverdues[$i] = $data;
- $i++;
- }
- }
- return (@getoverdues);
-}
-
-
-=head2 AddNotifyLine
-
- &AddNotifyLine($borrowernumber, $itemnumber, $overduelevel, $method, $notifyId)
-
-Create a line into notify, if the method is phone, the notification_send_date is implemented to
-
-=cut
-
-sub AddNotifyLine {
- my ( $borrowernumber, $itemnumber, $overduelevel, $method, $notifyId ) = @_;
- my $dbh = C4::Context->dbh;
- if ( $method eq "phone" ) {
- my $sth = $dbh->prepare(
- "INSERT INTO notifys (borrowernumber,itemnumber,notify_date,notify_send_date,notify_level,method,notify_id)
- VALUES (?,?,now(),now(),?,?,?)"
- );
- $sth->execute( $borrowernumber, $itemnumber, $overduelevel, $method,
- $notifyId );
- }
- else {
- my $sth = $dbh->prepare(
- "INSERT INTO notifys (borrowernumber,itemnumber,notify_date,notify_level,method,notify_id)
- VALUES (?,?,now(),?,?,?)"
- );
- $sth->execute( $borrowernumber, $itemnumber, $overduelevel, $method,
- $notifyId );
+ my $q = "$select ORDER BY borrowers.surname, borrowers.firstname";
+ return @{ $dbh->selectall_arrayref($q, { Slice => {} }, $branch ) };
}
- return 1;
-}
-
-=head2 RemoveNotifyLine
-
- &RemoveNotifyLine( $borrowernumber, $itemnumber, $notify_date );
-
-Cancel a notification
-
-=cut
-
-sub RemoveNotifyLine {
- my ( $borrowernumber, $itemnumber, $notify_date ) = @_;
- my $dbh = C4::Context->dbh;
- my $sth = $dbh->prepare(
- "DELETE FROM notifys
- WHERE
- borrowernumber=?
- AND itemnumber=?
- AND notify_date=?"
- );
- $sth->execute( $borrowernumber, $itemnumber, $notify_date );
- return 1;
}
=head2 GetOverdueMessageTransportTypes
# Put 'print' in first if exists
# It avoid to sent a print notice with an email or sms template is no email or sms is defined
@mtts = uniq( 'print', @mtts )
- if grep {/^print$/} @mtts;
+ if grep { $_ eq 'print' } @mtts;
return \@mtts;
}
return unless ( exists $params->{$required} && $params->{$required} );
}
+ my $patron = Koha::Patrons->find( $params->{borrowernumber} );
+
my $substitute = $params->{'substitute'} || {};
- $substitute->{today} ||= output_pref( { dt => dt_from_string, dateonly => 1} );
my %tables = ( 'borrowers' => $params->{'borrowernumber'} );
if ( my $p = $params->{'branchcode'} ) {
my @item_tables;
if ( my $i = $params->{'items'} ) {
- my $item_format = '';
foreach my $item (@$i) {
my $fine = GetFine($item->{'itemnumber'}, $params->{'borrowernumber'});
- if ( !$item_format and defined $params->{'letter'}->{'content'} ) {
- $params->{'letter'}->{'content'} =~ m/(<item>.*<\/item>)/;
- $item_format = $1;
- }
-
$item->{'fine'} = currency_format($currency_format, "$fine", FMT_SYMBOL);
# if active currency isn't correct ISO code fallback to sprintf
$item->{'fine'} = sprintf('%.2f', $fine) unless $item->{'fine'};
module => 'circulation',
letter_code => $params->{'letter_code'},
branchcode => $params->{'branchcode'},
+ lang => $patron->lang,
tables => \%tables,
+ loops => {
+ overdues => [ map { $_->{items}->{itemnumber} } @item_tables ],
+ },
substitute => $substitute,
repeat => { item => \@item_tables },
message_transport_type => $params->{message_transport_type},