use Koha::AuthorisedValues;
use Koha::DateUtils;
use Koha::Calendar;
+use Koha::Checkouts;
+use Koha::IssuingRules;
use Koha::Items;
use Koha::Patrons;
use Koha::Patron::Debarments;
&AddRenewal
&GetRenewCount
&GetSoonestRenewDate
+ &GetLatestAutoRenewDate
&GetItemIssue
- &GetItemIssues
&GetIssuingCharges
- &GetIssuingRule
&GetBranchBorrowerCircRule
&GetBranchItemRule
&GetBiblioIssues
&GetOpenIssue
- &AnonymiseIssueHistory
&CheckIfIssuedToPatron
&IsItemIssued
GetTopIssues
# given branch, patron category, and item type, determine
# applicable issuing rule
- my $issuing_rule = GetIssuingRule($cat_borrower, $type, $branch);
+ my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
+ { categorycode => $cat_borrower,
+ itemtype => $type,
+ branchcode => $branch
+ }
+ );
+
# if a rule is found and has a loan limit set, count
# how many loans the patron already has that meet that
# rule
- if (defined($issuing_rule) and defined($issuing_rule->{'maxissueqty'})) {
+ if (defined($issuing_rule) and defined($issuing_rule->maxissueqty)) {
my @bind_params;
my $count_query = q|
SELECT COUNT(*) AS total, COALESCE(SUM(onsite_checkout), 0) AS onsite_checkouts
JOIN items USING (itemnumber)
|;
- my $rule_itemtype = $issuing_rule->{itemtype};
+ my $rule_itemtype = $issuing_rule->itemtype;
if ($rule_itemtype eq "*") {
# matching rule has the default item type, so count only
# those existing loans that don't fall under a more
AND itemtype <> '*'
) ";
}
- push @bind_params, $issuing_rule->{branchcode};
- push @bind_params, $issuing_rule->{categorycode};
+ push @bind_params, $issuing_rule->branchcode;
+ push @bind_params, $issuing_rule->categorycode;
push @bind_params, $cat_borrower;
} else {
# rule has specific item type, so count loans of that
$count_query .= " AND borrowernumber = ? ";
push @bind_params, $borrower->{'borrowernumber'};
- my $rule_branch = $issuing_rule->{branchcode};
+ my $rule_branch = $issuing_rule->branchcode;
if ($rule_branch ne "*") {
if (C4::Context->preference('CircControl') eq 'PickupLibrary') {
$count_query .= " AND issues.branchcode = ? ";
my ( $checkout_count, $onsite_checkout_count ) = $dbh->selectrow_array( $count_query, {}, @bind_params );
- my $max_checkouts_allowed = $issuing_rule->{maxissueqty};
- my $max_onsite_checkouts_allowed = $issuing_rule->{maxonsiteissueqty};
+ my $max_checkouts_allowed = $issuing_rule->maxissueqty;
+ my $max_onsite_checkouts_allowed = $issuing_rule->maxonsiteissueqty;
if ( $onsite_checkout ) {
if ( $onsite_checkout_count >= $max_onsite_checkouts_allowed ) {
}
}
+ if ( not defined( $issuing_rule ) and not defined($branch_borrower_circ_rule->{maxissueqty}) ) {
+ return { reason => 'NO_RULE_DEFINED', max_allowed => 0 };
+ }
+
# OK, the patron can issue !!!
return;
}
=over 4
-=item C<$borrower> hash with borrower informations (from GetMember or GetMemberDetails)
+=item C<$borrower> hash with borrower informations (from GetMember)
=item C<$barcode> is the bar code of the book being issued.
branch => C4::Context->userenv->{'branch'},
type => 'localuse',
itemnumber => $item->{'itemnumber'},
- itemtype => $item->{'itemtype'},
+ itemtype => $item->{'itype'},
borrowernumber => $borrower->{'borrowernumber'},
ccode => $item->{'ccode'}}
);
ModDateLastSeen( $item->{'itemnumber'} );
return( { STATS => 1 }, {});
}
- if ( ref $borrower->{flags} ) {
- if ( $borrower->{flags}->{GNA} ) {
+
+ my $flags = C4::Members::patronflags( $borrower );
+ if ( ref $flags ) {
+ if ( $flags->{GNA} ) {
$issuingimpossible{GNA} = 1;
}
- if ( $borrower->{flags}->{'LOST'} ) {
+ if ( $flags->{'LOST'} ) {
$issuingimpossible{CARD_LOST} = 1;
}
- if ( $borrower->{flags}->{'DBARRED'} ) {
+ if ( $flags->{'DBARRED'} ) {
$issuingimpossible{DEBARRED} = 1;
}
}
if ( $rentalConfirmation ){
my ($rentalCharge) = GetIssuingCharges( $item->{'itemnumber'}, $borrower->{'borrowernumber'} );
if ( $rentalCharge > 0 ){
- $rentalCharge = sprintf("%.02f", $rentalCharge);
$needsconfirmation{RENTALCHARGE} = $rentalCharge;
}
}
require C4::Serials;
my $is_a_subscription = C4::Serials::CountSubscriptionFromBiblionumber($biblionumber);
unless ($is_a_subscription) {
- my $issues = GetIssues( {
- borrowernumber => $borrower->{borrowernumber},
- biblionumber => $biblionumber,
- } );
- my @issues = $issues ? @$issues : ();
+ my $checkouts = Koha::Checkouts->search(
+ {
+ borrowernumber => $borrower->{borrowernumber},
+ biblionumber => $biblionumber,
+ },
+ {
+ join => 'item',
+ }
+ );
# if we get here, we don't already have a loan on this item,
# so if there are any loans on this bib, ask for confirmation
- if (scalar @issues > 0) {
+ if ( $checkouts->count ) {
$needsconfirmation{BIBLIO_ALREADY_ISSUED} = 1;
}
}
my $decreaseLoanHighHoldsDuration = C4::Context->preference('decreaseLoanHighHoldsDuration');
my $reduced_datedue = $calendar->addDate( $issuedate, $decreaseLoanHighHoldsDuration );
+ $reduced_datedue->set_hour($orig_due->hour);
+ $reduced_datedue->set_minute($orig_due->minute);
+ $reduced_datedue->truncate( to => 'minute' );
if ( DateTime->compare( $reduced_datedue, $orig_due ) == -1 ) {
$return_data->{exceeded} = 1;
=over 4
-=item C<$borrower> is a hash with borrower informations (from GetMember or GetMemberDetails).
+=item C<$borrower> is a hash with borrower informations (from GetMember).
=item C<$barcode> is the barcode of the item being issued.
# If automatic renewal wasn't selected while issuing, set the value according to the issuing rule.
unless ($auto_renew) {
- my $issuingrule = GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $branch );
- $auto_renew = $issuingrule->{auto_renew};
+ my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
+ { categorycode => $borrower->{categorycode},
+ itemtype => $item->{itype},
+ branchcode => $branch
+ }
+ );
+
+ $auto_renew = $issuing_rule->auto_renew if $issuing_rule;
}
# Record in the database the fact that the book was issued.
sub GetHardDueDate {
my ( $borrowertype, $itemtype, $branchcode ) = @_;
- my $rule = GetIssuingRule( $borrowertype, $itemtype, $branchcode );
+ my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
+ { categorycode => $borrowertype,
+ itemtype => $itemtype,
+ branchcode => $branchcode
+ }
+ );
+
- if ( defined( $rule ) ) {
- if ( $rule->{hardduedate} ) {
- return (dt_from_string($rule->{hardduedate}, 'iso'),$rule->{hardduedatecompare});
+ if ( defined( $issuing_rule ) ) {
+ if ( $issuing_rule->hardduedate ) {
+ return (dt_from_string($issuing_rule->hardduedate, 'iso'),$issuing_rule->hardduedatecompare);
} else {
return (undef, undef);
}
}
}
-=head2 GetIssuingRule
-
- my $irule = &GetIssuingRule($borrowertype,$itemtype,branchcode)
-
-FIXME - This is a copy-paste of GetLoanLength
-as a stop-gap. Do not wish to change API for GetLoanLength
-this close to release.
-
-Get the issuing rule for an itemtype, a borrower type and a branch
-Returns a hashref from the issuingrules table.
-
-=cut
-
-sub GetIssuingRule {
- my ( $borrowertype, $itemtype, $branchcode ) = @_;
- my $dbh = C4::Context->dbh;
- my $sth = $dbh->prepare( "select * from issuingrules where categorycode=? and itemtype=? and branchcode=?" );
- my $irule;
-
- $sth->execute( $borrowertype, $itemtype, $branchcode );
- $irule = $sth->fetchrow_hashref;
- return $irule if defined($irule) ;
-
- $sth->execute( $borrowertype, "*", $branchcode );
- $irule = $sth->fetchrow_hashref;
- return $irule if defined($irule) ;
-
- $sth->execute( "*", $itemtype, $branchcode );
- $irule = $sth->fetchrow_hashref;
- return $irule if defined($irule) ;
-
- $sth->execute( "*", "*", $branchcode );
- $irule = $sth->fetchrow_hashref;
- return $irule if defined($irule) ;
-
- $sth->execute( $borrowertype, $itemtype, "*" );
- $irule = $sth->fetchrow_hashref;
- return $irule if defined($irule) ;
-
- $sth->execute( $borrowertype, "*", "*" );
- $irule = $sth->fetchrow_hashref;
- return $irule if defined($irule) ;
-
- $sth->execute( "*", $itemtype, "*" );
- $irule = $sth->fetchrow_hashref;
- return $irule if defined($irule) ;
-
- $sth->execute( "*", "*", "*" );
- $irule = $sth->fetchrow_hashref;
- return $irule if defined($irule) ;
-
- # if no rule matches,
- return;
-}
-
=head2 GetBranchBorrowerCircRule
my $branch_cat_rule = GetBranchBorrowerCircRule($branchcode, $categorycode);
}
my $itemnumber = $item->{ itemnumber };
- my $biblio = GetBiblioData( $item->{ biblionumber } );
- my $itemtype = ( C4::Context->preference("item-level_itypes") )
- ? $item->{ itype }
- : $biblio->{ itemtype };
+
+ my $item_level_itypes = C4::Context->preference("item-level_itypes");
+ my $biblio = $item_level_itypes ? undef : GetBiblioData( $item->{ biblionumber } ); # don't get bib data unless we need it
+ my $itemtype = $item_level_itypes ? $item->{itype} : $biblio->{itemtype};
my $issue = GetItemIssue($itemnumber);
if ($issue and $issue->{borrowernumber}) {
- $borrower = C4::Members::GetMemberDetails($issue->{borrowernumber})
+ $borrower = C4::Members::GetMember( borrowernumber => $issue->{borrowernumber} )
or die "Data inconsistency: barcode $barcode (itemnumber:$itemnumber) claims to be issued to non-existent borrowernumber '$issue->{borrowernumber}'\n"
. Dumper($issue) . "\n";
} else {
die "Fatal error: the patron ($borrowernumber) has requested their circulation history be anonymized on check-in, but the AnonymousPatron system preference is empty or not set correctly."
unless C4::Members::GetMember( borrowernumber => $anonymouspatron );
}
+ my $database = Koha::Database->new();
+ my $schema = $database->schema;
my $dbh = C4::Context->dbh;
+
+ my $issue_id = $dbh->selectrow_array(
+ q|SELECT issue_id FROM issues WHERE itemnumber = ?|,
+ undef, $itemnumber
+ );
+
my $query = 'UPDATE issues SET returndate=';
my @bind;
if ($dropbox_branch) {
} else {
$query .= ' now() ';
}
- $query .= ' WHERE borrowernumber = ? AND itemnumber = ?';
- push @bind, $borrowernumber, $itemnumber;
- # FIXME transaction
- my $sth_upd = $dbh->prepare($query);
- $sth_upd->execute(@bind);
- my $sth_copy = $dbh->prepare('INSERT INTO old_issues SELECT * FROM issues
- WHERE borrowernumber = ?
- AND itemnumber = ?');
- $sth_copy->execute($borrowernumber, $itemnumber);
- # anonymise patron checkout immediately if $privacy set to 2 and AnonymousPatron is set to a valid borrowernumber
- if ( $privacy == 2) {
- my $sth_ano = $dbh->prepare("UPDATE old_issues SET borrowernumber=?
- WHERE borrowernumber = ?
- AND itemnumber = ?");
- $sth_ano->execute($anonymouspatron, $borrowernumber, $itemnumber);
- }
- my $sth_del = $dbh->prepare("DELETE FROM issues
- WHERE borrowernumber = ?
- AND itemnumber = ?");
- $sth_del->execute($borrowernumber, $itemnumber);
+ $query .= ' WHERE issue_id = ?';
+ push @bind, $issue_id;
- ModItem( { 'onloan' => undef }, undef, $itemnumber );
+ # FIXME Improve the return value and handle it from callers
+ $schema->txn_do(sub {
+ $dbh->do( $query, undef, @bind );
- if ( C4::Context->preference('StoreLastBorrower') ) {
- my $item = Koha::Items->find( $itemnumber );
- my $patron = Koha::Patrons->find( $borrowernumber );
- $item->last_returned_by( $patron );
- }
+ my $id_already_exists = $dbh->selectrow_array(
+ q|SELECT COUNT(*) FROM old_issues WHERE issue_id = ?|,
+ undef, $issue_id
+ );
+
+ if ( $id_already_exists ) {
+ my $new_issue_id = $dbh->selectrow_array(q|SELECT MAX(issue_id)+1 FROM old_issues|);
+ $dbh->do(
+ q|UPDATE issues SET issue_id = ? WHERE issue_id = ?|,
+ undef, $new_issue_id, $issue_id
+ );
+ $issue_id = $new_issue_id;
+ }
+
+ $dbh->do(q|INSERT INTO old_issues SELECT * FROM issues WHERE issue_id = ?|, undef, $issue_id);
+
+ # anonymise patron checkout immediately if $privacy set to 2 and AnonymousPatron is set to a valid borrowernumber
+ if ( $privacy == 2) {
+ $dbh->do(q|UPDATE old_issues SET borrowernumber=? WHERE issue_id = ?|, undef, $anonymouspatron, $issue_id);
+ }
+
+ $dbh->do(q|DELETE FROM issues WHERE issue_id = ?|, undef, $issue_id);
+
+ ModItem( { 'onloan' => undef }, undef, $itemnumber );
+
+ if ( C4::Context->preference('StoreLastBorrower') ) {
+ my $item = Koha::Items->find( $itemnumber );
+ my $patron = Koha::Patrons->find( $borrowernumber );
+ $item->last_returned_by( $patron );
+ }
+ });
}
=head2 _debar_user_on_return
my $branchcode = _GetCircControlBranch( $item, $borrower );
my $circcontrol = C4::Context->preference('CircControl');
- my $issuingrule =
- GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $branchcode );
- my $finedays = $issuingrule->{finedays};
- my $unit = $issuingrule->{lengthunit};
+ my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
+ { categorycode => $borrower->{categorycode},
+ itemtype => $item->{itype},
+ branchcode => $branchcode
+ }
+ );
+ my $finedays = $issuing_rule ? $issuing_rule->finedays : undef;
+ my $unit = $issuing_rule ? $issuing_rule->lengthunit : undef;
my $chargeable_units = C4::Overdues::get_chargeable_units($unit, $dt_due, $dt_today, $branchcode);
if ($finedays) {
# grace period is measured in the same units as the loan
my $grace =
- DateTime::Duration->new( $unit => $issuingrule->{firstremind} );
+ DateTime::Duration->new( $unit => $issuing_rule->firstremind );
my $deltadays = DateTime::Duration->new(
days => $chargeable_units
# If the max suspension days is < than the suspension days
# the suspension days is limited to this maximum period.
- my $max_sd = $issuingrule->{maxsuspensiondays};
+ my $max_sd = $issuing_rule->maxsuspensiondays;
if ( defined $max_sd ) {
$max_sd = DateTime::Duration->new( days => $max_sd );
$suspension_days = $max_sd
}
-=head2 GetIssues
-
- $issues = GetIssues({}); # return all issues!
- $issues = GetIssues({ borrowernumber => $borrowernumber, biblionumber => $biblionumber });
-
-Returns all pending issues that match given criteria.
-Returns a arrayref or undef if an error occurs.
-
-Allowed criteria are:
-
-=over 2
-
-=item * borrowernumber
-
-=item * biblionumber
-
-=item * itemnumber
-
-=back
-
-=cut
-
-sub GetIssues {
- my ($criteria) = @_;
-
- # Build filters
- my @filters;
- my @allowed = qw(borrowernumber biblionumber itemnumber);
- foreach (@allowed) {
- if (defined $criteria->{$_}) {
- push @filters, {
- field => $_,
- value => $criteria->{$_},
- };
- }
- }
-
- # Do we need to join other tables ?
- my %join;
- if (defined $criteria->{biblionumber}) {
- $join{items} = 1;
- }
-
- # Build SQL query
- my $where = '';
- if (@filters) {
- $where = "WHERE " . join(' AND ', map { "$_->{field} = ?" } @filters);
- }
- my $query = q{
- SELECT issues.*
- FROM issues
- };
- if (defined $join{items}) {
- $query .= q{
- LEFT JOIN items ON (issues.itemnumber = items.itemnumber)
- };
- }
- $query .= $where;
-
- # Execute SQL query
- my $dbh = C4::Context->dbh;
- my $sth = $dbh->prepare($query);
- my $rv = $sth->execute(map { $_->{value} } @filters);
-
- return $rv ? $sth->fetchall_arrayref({}) : undef;
-}
-
-=head2 GetItemIssues
-
- $issues = &GetItemIssues($itemnumber, $history);
-
-Returns patrons that have issued a book
-
-C<$itemnumber> is the itemnumber
-C<$history> is false if you just want the current "issuer" (if any)
-and true if you want issues history from old_issues also.
-
-Returns reference to an array of hashes
-
-=cut
-
-sub GetItemIssues {
- my ( $itemnumber, $history ) = @_;
-
- my $today = DateTime->now( time_zome => C4::Context->tz); # get today date
- $today->truncate( to => 'minute' );
- my $sql = "SELECT * FROM issues
- JOIN borrowers USING (borrowernumber)
- JOIN items USING (itemnumber)
- WHERE issues.itemnumber = ? ";
- if ($history) {
- $sql .= "UNION ALL
- SELECT * FROM old_issues
- LEFT JOIN borrowers USING (borrowernumber)
- JOIN items USING (itemnumber)
- WHERE old_issues.itemnumber = ? ";
- }
- $sql .= "ORDER BY date_due DESC";
- my $sth = C4::Context->dbh->prepare($sql);
- if ($history) {
- $sth->execute($itemnumber, $itemnumber);
- } else {
- $sth->execute($itemnumber);
- }
- my $results = $sth->fetchall_arrayref({});
- foreach (@$results) {
- my $date_due = dt_from_string($_->{date_due},'sql');
- $date_due->truncate( to => 'minute' );
-
- $_->{overdue} = (DateTime->compare($date_due, $today) == -1) ? 1 : 0;
- }
- return $results;
-}
-
=head2 GetBiblioIssues
$issues = GetBiblioIssues($biblionumber);
# can be filled with available items. We can get the union of the sets simply
# by pushing all the elements onto an array and removing the duplicates.
my @reservable;
- foreach my $b (@borrowernumbers) {
- my ($borr) = C4::Members::GetMemberDetails($b);
- foreach my $i (@itemnumbers) {
- my $item = GetItem($i);
- if ( IsAvailableForItemLevelRequest( $item, $borr )
- && CanItemBeReserved( $b, $i )
- && !IsItemOnHoldAndFound($i) )
- {
- push( @reservable, $i );
+ my %borrowers;
+ ITEM: foreach my $i (@itemnumbers) {
+ my $item = GetItem($i);
+ next if IsItemOnHoldAndFound($i);
+ for my $b (@borrowernumbers) {
+ my $borr = $borrowers{$b}//= C4::Members::GetMember(borrowernumber => $b);
+ next unless IsAvailableForItemLevelRequest($item, $borr);
+ next unless CanItemBeReserved($b,$i);
+
+ push @reservable, $i;
+ if (@reservable >= @borrowernumbers) {
+ $resfound = 0;
+ last ITEM;
}
+ last;
}
}
-
- @reservable = uniq(@reservable);
-
- if ( @reservable >= @borrowernumbers ) {
- $resfound = 0;
- }
}
}
return ( 0, "on_reserve" ) if $resfound; # '' when no hold was found
return ( 1, undef ) if $override_limit;
my $branchcode = _GetCircControlBranch( $item, $borrower );
- my $issuingrule =
- GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $branchcode );
+ my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
+ { categorycode => $borrower->{categorycode},
+ itemtype => $item->{itype},
+ branchcode => $branchcode
+ }
+ );
return ( 0, "too_many" )
- if $issuingrule->{renewalsallowed} <= $itemissue->{renewals};
+ if not $issuing_rule or $issuing_rule->renewalsallowed <= $itemissue->{renewals};
my $overduesblockrenewing = C4::Context->preference('OverduesBlockRenewing');
my $restrictionblockrenewing = C4::Context->preference('RestrictionBlockRenewing');
return ( 0, 'overdue');
}
- if ( defined $issuingrule->{norenewalbefore}
- and $issuingrule->{norenewalbefore} ne "" )
+ if ( $itemissue->{auto_renew}
+ and defined $issuing_rule->no_auto_renewal_after
+ and $issuing_rule->no_auto_renewal_after ne "" ) {
+
+ # Get issue_date and add no_auto_renewal_after
+ # If this is greater than today, it's too late for renewal.
+ my $maximum_renewal_date = dt_from_string($itemissue->{issuedate});
+ $maximum_renewal_date->add(
+ $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
+ );
+ my $now = dt_from_string;
+ if ( $now >= $maximum_renewal_date ) {
+ return ( 0, "auto_too_late" );
+ }
+ }
+
+ if ( defined $issuing_rule->norenewalbefore
+ and $issuing_rule->norenewalbefore ne "" )
{
# Calculate soonest renewal by subtracting 'No renewal before' from due date
my $soonestrenewal =
$itemissue->{date_due}->clone()
->subtract(
- $issuingrule->{lengthunit} => $issuingrule->{norenewalbefore} );
+ $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
# Depending on syspref reset the exact time, only check the date
if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
- and $issuingrule->{lengthunit} eq 'days' )
+ and $issuing_rule->lengthunit eq 'days' )
{
$soonestrenewal->truncate( to => 'day' );
}
# Fallback for automatic renewals:
# If norenewalbefore is undef, don't renew before due date.
- elsif ( $itemissue->{auto_renew} ) {
+ if ( $itemissue->{auto_renew} ) {
my $now = dt_from_string;
return ( 0, "auto_renew" )
if $now >= $itemissue->{date_due};
# Send a renewal slip according to checkout alert preferencei
if ( C4::Context->preference('RenewalSendNotice') eq '1' ) {
- $borrower = C4::Members::GetMemberDetails( $borrowernumber, 0 );
+ $borrower = C4::Members::GetMember( borrowernumber => $borrowernumber );
my $circulation_alert = 'C4::ItemCirculationAlertPreference';
my %conditions = (
branchcode => $branch,
}
# Log the renewal
- UpdateStats({branch => $branch,
- type => 'renew',
- amount => $charge,
- itemnumber => $itemnumber,
- itemtype => $item->{itype},
- borrowernumber => $borrowernumber,
- ccode => $item->{'ccode'}}
- );
- return $datedue;
+ UpdateStats(
+ {
+ branch => C4::Context->userenv ? C4::Context->userenv->{branch} : $branch,
+ type => 'renew',
+ amount => $charge,
+ itemnumber => $itemnumber,
+ itemtype => $item->{itype},
+ borrowernumber => $borrowernumber,
+ ccode => $item->{'ccode'}
+ }
+ );
+
+ return $datedue;
}
sub GetRenewCount {
$renewcount = $data->{'renewals'} if $data->{'renewals'};
# $item and $borrower should be calculated
my $branchcode = _GetCircControlBranch($item, $borrower);
-
- my $issuingrule = GetIssuingRule($borrower->{categorycode}, $item->{itype}, $branchcode);
-
- $renewsallowed = $issuingrule->{'renewalsallowed'};
+
+ my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
+ { categorycode => $borrower->{categorycode},
+ itemtype => $item->{itype},
+ branchcode => $branchcode
+ }
+ );
+
+ $renewsallowed = $issuing_rule ? $issuing_rule->renewalsallowed : undef; # FIXME Just replace undef with 0 to get what we expected. But what about the side-effects? TODO LATER
$renewsleft = $renewsallowed - $renewcount;
if($renewsleft < 0){ $renewsleft = 0; }
return ( $renewcount, $renewsallowed, $renewsleft );
my $itemissue = GetItemIssue($itemnumber) or return;
$borrowernumber ||= $itemissue->{borrowernumber};
- my $borrower = C4::Members::GetMemberDetails($borrowernumber)
+ my $borrower = C4::Members::GetMember( borrowernumber => $borrowernumber )
or return;
my $branchcode = _GetCircControlBranch( $item, $borrower );
- my $issuingrule =
- GetIssuingRule( $borrower->{categorycode}, $item->{itype}, $branchcode );
+ my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
+ { categorycode => $borrower->{categorycode},
+ itemtype => $item->{itype},
+ branchcode => $branchcode
+ }
+ );
my $now = dt_from_string;
+ return $now unless $issuing_rule;
- if ( defined $issuingrule->{norenewalbefore}
- and $issuingrule->{norenewalbefore} ne "" )
+ if ( defined $issuing_rule->norenewalbefore
+ and $issuing_rule->norenewalbefore ne "" )
{
my $soonestrenewal =
$itemissue->{date_due}->clone()
->subtract(
- $issuingrule->{lengthunit} => $issuingrule->{norenewalbefore} );
+ $issuing_rule->lengthunit => $issuing_rule->norenewalbefore );
if ( C4::Context->preference('NoRenewalBeforePrecision') eq 'date'
- and $issuingrule->{lengthunit} eq 'days' )
+ and $issuing_rule->lengthunit eq 'days' )
{
$soonestrenewal->truncate( to => 'day' );
}
return $now;
}
+=head2 GetLatestAutoRenewDate
+
+ $NoAutoRenewalAfterThisDate = &GetLatestAutoRenewDate($borrowernumber, $itemnumber);
+
+Find out the latest possible auto renew date of a borrowed item.
+
+C<$borrowernumber> is the borrower number of the patron who currently
+has the item on loan.
+
+C<$itemnumber> is the number of the item to renew.
+
+C<$GetLatestAutoRenewDate> returns the DateTime of the latest possible
+auto renew date, based on the value "No auto renewal after" of the applicable
+issuing rule.
+Returns undef if there is no date specify in the circ rules or if the patron, loan,
+or item cannot be found.
+
+=cut
+
+sub GetLatestAutoRenewDate {
+ my ( $borrowernumber, $itemnumber ) = @_;
+
+ my $dbh = C4::Context->dbh;
+
+ my $item = GetItem($itemnumber) or return;
+ my $itemissue = GetItemIssue($itemnumber) or return;
+
+ $borrowernumber ||= $itemissue->{borrowernumber};
+ my $borrower = C4::Members::GetMember( borrowernumber => $borrowernumber )
+ or return;
+
+ my $branchcode = _GetCircControlBranch( $item, $borrower );
+ my $issuing_rule = Koha::IssuingRules->get_effective_issuing_rule(
+ { categorycode => $borrower->{categorycode},
+ itemtype => $item->{itype},
+ branchcode => $branchcode
+ }
+ );
+
+ return unless $issuing_rule;
+ return if not $issuing_rule->no_auto_renewal_after
+ or $issuing_rule->no_auto_renewal_after eq '';
+
+ my $maximum_renewal_date = dt_from_string($itemissue->{issuedate});
+ $maximum_renewal_date->add(
+ $issuing_rule->lengthunit => $issuing_rule->no_auto_renewal_after
+ );
+
+ return $maximum_renewal_date;
+}
+
+
=head2 GetIssuingCharges
($charge, $item_type) = &GetIssuingCharges($itemnumber, $borrowernumber);
my $discount = _get_discount_from_rule($discount_rules, $branch, $item_type);
$charge = ( $charge * ( 100 - $discount ) ) / 100;
}
+ if ($charge) {
+ $charge = sprintf '%.2f', $charge; # ensure no fractions of a penny returned
+ }
}
return ( $charge, $item_type );
my $query = '
SELECT datesent,
frombranch,
- tobranch
+ tobranch,
+ branchtransfer_id
FROM branchtransfers
WHERE itemnumber = ?
AND datearrived IS NULL
return unless ( $frombranch && $tobranch );
my $dbh = C4::Context->dbh;
my $query = "
- SELECT itemnumber,datesent,frombranch
+ SELECT branchtransfer_id,itemnumber,datesent,frombranch
FROM branchtransfers
WHERE frombranch=?
AND tobranch=?
return $sth->execute($itemnumber);
}
-=head2 AnonymiseIssueHistory
-
- ($rows,$err_history_not_deleted) = AnonymiseIssueHistory($date,$borrowernumber)
-
-This function write NULL instead of C<$borrowernumber> given on input arg into the table issues.
-if C<$borrowernumber> is not set, it will delete the issue history for all borrower older than C<$date>.
-
-If c<$borrowernumber> is set, it will delete issue history for only that borrower, regardless of their opac privacy
-setting (force delete).
-
-return the number of affected rows and a value that evaluates to true if an error occurred deleting the history.
-
-=cut
-
-sub AnonymiseIssueHistory {
- my $date = shift;
- my $borrowernumber = shift;
- my $dbh = C4::Context->dbh;
- my $query = "
- UPDATE old_issues
- SET borrowernumber = ?
- WHERE returndate < ?
- AND borrowernumber IS NOT NULL
- ";
-
- # The default of 0 does not work due to foreign key constraints
- # The anonymisation should not fail quietly if AnonymousPatron is not a valid entry
- # Set it to undef (NULL)
- my $anonymouspatron = C4::Context->preference('AnonymousPatron') || undef;
- my @bind_params = ($anonymouspatron, $date);
- if (defined $borrowernumber) {
- $query .= " AND borrowernumber = ?";
- push @bind_params, $borrowernumber;
- } else {
- $query .= " AND (SELECT privacy FROM borrowers WHERE borrowers.borrowernumber=old_issues.borrowernumber) <> 0";
- }
- my $sth = $dbh->prepare($query);
- $sth->execute(@bind_params);
- my $anonymisation_err = $dbh->err;
- my $rows_affected = $sth->rows; ### doublecheck row count return function
- return ($rows_affected, $anonymisation_err);
-}
-
=head2 SendCirculationAlert
Send out a C<check-in> or C<checkout> alert using the messaging system.
# If a borrower lost the item, add a replacement cost to the their record
if ( my $borrowernumber = $issues->{borrowernumber} ){
- my $borrower = C4::Members::GetMemberDetails( $borrowernumber );
+ my $borrower = C4::Members::GetMember( borrowernumber => $borrowernumber );
if (C4::Context->preference('WhenLostForgiveFine')){
my $fix = _FixOverduesOnReturn($borrowernumber, $itemnumber, 1, 0); # 1, 0 = exemptfine, no-dropbox
sub ProcessOfflineIssue {
my $operation = shift;
- my $borrower = C4::Members::GetMemberDetails( undef, $operation->{cardnumber} ); # Get borrower from operation cardnumber
+ my $borrower = C4::Members::GetMember( cardnumber => $operation->{cardnumber} );
if ( $borrower->{borrowernumber} ) {
my $itemnumber = C4::Items::GetItemnumberFromBarcode( $operation->{barcode} );