Lines 30-36
use C4::Items;
Link Here
|
30 |
use C4::Members; |
30 |
use C4::Members; |
31 |
use C4::Dates; |
31 |
use C4::Dates; |
32 |
use C4::Dates qw(format_date); |
32 |
use C4::Dates qw(format_date); |
33 |
use C4::Accounts; |
33 |
use Koha::Accounts; |
|
|
34 |
use Koha::Accounts::CreditTypes; |
34 |
use C4::ItemCirculationAlertPreference; |
35 |
use C4::ItemCirculationAlertPreference; |
35 |
use C4::Message; |
36 |
use C4::Message; |
36 |
use C4::Debug; |
37 |
use C4::Debug; |
Lines 1296-1302
sub AddIssue {
Link Here
|
1296 |
## If item was lost, it has now been found, reverse any list item charges if neccessary. |
1297 |
## If item was lost, it has now been found, reverse any list item charges if neccessary. |
1297 |
if ( $item->{'itemlost'} ) { |
1298 |
if ( $item->{'itemlost'} ) { |
1298 |
if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) { |
1299 |
if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) { |
1299 |
_FixAccountForLostAndReturned( $item->{'itemnumber'}, undef, $item->{'barcode'} ); |
1300 |
_FixAccountForLostAndReturned( $item->{'itemnumber'} ); |
1300 |
} |
1301 |
} |
1301 |
} |
1302 |
} |
1302 |
|
1303 |
|
Lines 1855-1861
sub AddReturn {
Link Here
|
1855 |
} |
1856 |
} |
1856 |
|
1857 |
|
1857 |
if ($borrowernumber) { |
1858 |
if ($borrowernumber) { |
1858 |
if ( ( C4::Context->preference('CalculateFinesOnReturn') && $issue->{'overdue'} ) || $return_date ) { |
1859 |
if ( |
|
|
1860 |
( !$item->{itemlost} ) # skip lost items |
1861 |
&& ( |
1862 |
( |
1863 |
C4::Context->preference('CalculateFinesOnReturn') |
1864 |
&& $issue->{'overdue'} |
1865 |
) |
1866 |
|| $return_date # force fine recalculation in case fine needs reduced |
1867 |
) |
1868 |
) |
1869 |
{ |
1859 |
# we only need to calculate and change the fines if we want to do that on return |
1870 |
# we only need to calculate and change the fines if we want to do that on return |
1860 |
# Should be on for hourly loans |
1871 |
# Should be on for hourly loans |
1861 |
my $control = C4::Context->preference('CircControl'); |
1872 |
my $control = C4::Context->preference('CircControl'); |
Lines 1873-1893
sub AddReturn {
Link Here
|
1873 |
|
1884 |
|
1874 |
$type ||= q{}; |
1885 |
$type ||= q{}; |
1875 |
|
1886 |
|
1876 |
if ( C4::Context->preference('finesMode') eq 'production' ) { |
1887 |
if ( $amount > 0 |
1877 |
if ( $amount > 0 ) { |
1888 |
&& C4::Context->preference('finesMode') eq 'production' ) |
1878 |
C4::Overdues::UpdateFine( $issue->{itemnumber}, |
1889 |
{ |
1879 |
$issue->{borrowernumber}, |
1890 |
C4::Overdues::UpdateFine( |
1880 |
$amount, $type, output_pref($datedue) ); |
1891 |
{ |
1881 |
} |
1892 |
itemnumber => $issue->{itemnumber}, |
1882 |
elsif ($return_date) { |
1893 |
borrowernumber => $issue->{borrowernumber}, |
1883 |
|
1894 |
amount => $amount, |
1884 |
# Backdated returns may have fines that shouldn't exist, |
1895 |
due => output_pref($datedue), |
1885 |
# so in this case, we need to drop those fines to 0 |
1896 |
issue_id => $issue->{issue_id} |
1886 |
|
1897 |
} |
1887 |
C4::Overdues::UpdateFine( $issue->{itemnumber}, |
1898 |
); |
1888 |
$issue->{borrowernumber}, |
1899 |
} |
1889 |
0, $type, output_pref($datedue) ); |
1900 |
elsif ($return_date) { |
1890 |
} |
1901 |
|
|
|
1902 |
# Backdated returns may have fines that shouldn't exist, |
1903 |
# so in this case, we need to drop those fines to 0 |
1904 |
C4::Overdues::UpdateFine( |
1905 |
{ |
1906 |
itemnumber => $issue->{itemnumber}, |
1907 |
borrowernumber => $issue->{borrowernumber}, |
1908 |
amount => 0, |
1909 |
due => output_pref($datedue), |
1910 |
issue_id => $issue->{issue_id} |
1911 |
} |
1912 |
); |
1891 |
} |
1913 |
} |
1892 |
} |
1914 |
} |
1893 |
|
1915 |
|
Lines 1938-1952
sub AddReturn {
Link Here
|
1938 |
$messages->{'WasLost'} = 1; |
1960 |
$messages->{'WasLost'} = 1; |
1939 |
|
1961 |
|
1940 |
if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) { |
1962 |
if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) { |
1941 |
_FixAccountForLostAndReturned($item->{'itemnumber'}, $borrowernumber, $barcode); # can tolerate undef $borrowernumber |
1963 |
_FixAccountForLostAndReturned( $item->{'itemnumber'} ); |
1942 |
$messages->{'LostItemFeeRefunded'} = 1; |
1964 |
$messages->{'LostItemFeeRefunded'} = 1; |
1943 |
} |
1965 |
} |
1944 |
} |
1966 |
} |
1945 |
|
1967 |
|
1946 |
# fix up the overdues in accounts... |
1968 |
# fix up the overdues in accounts... |
1947 |
if ($borrowernumber) { |
1969 |
if ($borrowernumber) { |
1948 |
my $fix = _FixOverduesOnReturn($borrowernumber, $item->{itemnumber}, $exemptfine, $dropbox); |
1970 |
_FinalizeFine( |
1949 |
defined($fix) or warn "_FixOverduesOnReturn($borrowernumber, $item->{itemnumber}...) failed!"; # zero is OK, check defined |
1971 |
{ |
|
|
1972 |
exempt_fine => $exemptfine, |
1973 |
dropbox => $dropbox, |
1974 |
issue => Koha::Database->new()->schema->resultset('OldIssue')->find( $issue->{issue_id} ), |
1975 |
} |
1976 |
); |
1950 |
|
1977 |
|
1951 |
if ( $issue->{overdue} && $issue->{date_due} ) { |
1978 |
if ( $issue->{overdue} && $issue->{date_due} ) { |
1952 |
# fix fine days |
1979 |
# fix fine days |
Lines 2061-2070
of the return. It is ignored when a dropbox_branch is passed in.
Link Here
|
2061 |
C<$privacy> contains the privacy parameter. If the patron has set privacy to 2, |
2088 |
C<$privacy> contains the privacy parameter. If the patron has set privacy to 2, |
2062 |
the old_issue is immediately anonymised |
2089 |
the old_issue is immediately anonymised |
2063 |
|
2090 |
|
2064 |
Ideally, this function would be internal to C<C4::Circulation>, |
|
|
2065 |
not exported, but it is currently needed by one |
2066 |
routine in C<C4::Accounts>. |
2067 |
|
2068 |
=cut |
2091 |
=cut |
2069 |
|
2092 |
|
2070 |
sub MarkIssueReturned { |
2093 |
sub MarkIssueReturned { |
Lines 2186-2340
sub _debar_user_on_return {
Link Here
|
2186 |
return; |
2209 |
return; |
2187 |
} |
2210 |
} |
2188 |
|
2211 |
|
2189 |
=head2 _FixOverduesOnReturn |
2212 |
=head2 _FinalizeFine |
2190 |
|
2213 |
|
2191 |
&_FixOverduesOnReturn($brn,$itm, $exemptfine, $dropboxmode); |
2214 |
_FinalizeFine({ |
2192 |
|
2215 |
exempt_fine => $exempt_fine, |
2193 |
C<$brn> borrowernumber |
2216 |
dropbox => $dropbox, |
2194 |
|
2217 |
issue => $issue, |
2195 |
C<$itm> itemnumber |
2218 |
}); |
2196 |
|
2219 |
|
2197 |
C<$exemptfine> BOOL -- remove overdue charge associated with this issue. |
2220 |
C<$exemptfine> BOOL -- remove overdue charge associated with this issue. |
2198 |
C<$dropboxmode> BOOL -- remove lastincrement on overdue charge associated with this issue. |
2221 |
C<$dropboxmode> BOOL -- remove lastincrement on overdue charge associated with this issue. |
|
|
2222 |
C<$issue> -- DBIx::Class::Row for the issue |
2199 |
|
2223 |
|
2200 |
Internal function, called only by AddReturn |
2224 |
This subrouting closes out the accuruing of a fine, and reduces if it exemptfine or |
|
|
2225 |
dropbox flags are passed in. |
2201 |
|
2226 |
|
2202 |
=cut |
2227 |
=cut |
2203 |
|
2228 |
|
2204 |
sub _FixOverduesOnReturn { |
2229 |
sub _FinalizeFine { |
2205 |
my ($borrowernumber, $item); |
2230 |
my ( $params ) = @_; |
2206 |
unless ($borrowernumber = shift) { |
2231 |
|
2207 |
warn "_FixOverduesOnReturn() not supplied valid borrowernumber"; |
2232 |
my $exemptfine = $params->{exempt_fine}; |
2208 |
return; |
2233 |
my $dropbox = $params->{dropbox}; |
2209 |
} |
2234 |
my $issue = $params->{issue}; |
2210 |
unless ($item = shift) { |
2235 |
|
2211 |
warn "_FixOverduesOnReturn() not supplied valid itemnumber"; |
|
|
2212 |
return; |
2213 |
} |
2214 |
my ($exemptfine, $dropbox) = @_; |
2215 |
my $dbh = C4::Context->dbh; |
2236 |
my $dbh = C4::Context->dbh; |
2216 |
|
2237 |
|
2217 |
# check for overdue fine |
2238 |
my $schema = Koha::Database->new()->schema; |
2218 |
my $sth = $dbh->prepare( |
2239 |
my $fine = $schema->resultset('AccountDebit')->single( |
2219 |
"SELECT * FROM accountlines WHERE (borrowernumber = ?) AND (itemnumber = ?) AND (accounttype='FU' OR accounttype='O')" |
2240 |
{ |
|
|
2241 |
issue_id => $issue->issue_id(), |
2242 |
type => Koha::Accounts::DebitTypes::Fine(), |
2243 |
accruing => 1, |
2244 |
} |
2220 |
); |
2245 |
); |
2221 |
$sth->execute( $borrowernumber, $item ); |
|
|
2222 |
|
2246 |
|
2223 |
# alter fine to show that the book has been returned |
2247 |
return unless ( $fine ); |
2224 |
my $data = $sth->fetchrow_hashref; |
2248 |
|
2225 |
return 0 unless $data; # no warning, there's just nothing to fix |
2249 |
$fine->accruing(0); |
2226 |
|
2250 |
|
2227 |
my $uquery; |
|
|
2228 |
my @bind = ($data->{'accountlines_id'}); |
2229 |
if ($exemptfine) { |
2251 |
if ($exemptfine) { |
2230 |
$uquery = "update accountlines set accounttype='FFOR', amountoutstanding=0"; |
2252 |
AddCredit( |
2231 |
if (C4::Context->preference("FinesLog")) { |
2253 |
{ |
2232 |
&logaction("FINES", 'MODIFY',$borrowernumber,"Overdue forgiven: item $item"); |
2254 |
borrower => $fine->borrowernumber(), |
2233 |
} |
2255 |
amount => $fine->amount_original(), |
2234 |
} elsif ($dropbox && $data->{lastincrement}) { |
2256 |
debit_id => $fine->debit_id(), |
2235 |
my $outstanding = $data->{amountoutstanding} - $data->{lastincrement} ; |
2257 |
type => Koha::Accounts::CreditTypes::Forgiven(), |
2236 |
my $amt = $data->{amount} - $data->{lastincrement} ; |
2258 |
} |
|
|
2259 |
); |
2237 |
if (C4::Context->preference("FinesLog")) { |
2260 |
if (C4::Context->preference("FinesLog")) { |
2238 |
&logaction("FINES", 'MODIFY',$borrowernumber,"Dropbox adjustment $amt, item $item"); |
2261 |
&logaction( |
2239 |
} |
2262 |
"FINES", 'MODIFY', |
2240 |
$uquery = "update accountlines set accounttype='F' "; |
2263 |
$issue->{borrowernumber}, |
2241 |
if($outstanding >= 0 && $amt >=0) { |
2264 |
"Overdue forgiven: item " . $issue->{itemnumber} |
2242 |
$uquery .= ", amount = ? , amountoutstanding=? "; |
2265 |
); |
2243 |
unshift @bind, ($amt, $outstanding) ; |
|
|
2244 |
} |
2266 |
} |
2245 |
} else { |
2267 |
} elsif ($dropbox && $fine->amount_last_increment() != $fine->amount_original() ) { |
2246 |
$uquery = "update accountlines set accounttype='F' "; |
2268 |
if ( C4::Context->preference("FinesLog") ) { |
|
|
2269 |
&logaction( "FINES", 'MODIFY', $issue->{borrowernumber}, |
2270 |
"Dropbox adjustment " |
2271 |
. $fine->amount_last_increment() |
2272 |
. ", item " . $issue->{itemnumber} ); |
2273 |
} |
2274 |
$fine->amount_original( |
2275 |
$fine->amount_original() - $fine->amount_last_increment() ); |
2276 |
$fine->amount_outstanding( |
2277 |
$fine->amount_outstanding - $fine->amount_last_increment() ); |
2278 |
$schema->resultset('AccountOffset')->create( |
2279 |
{ |
2280 |
debit_id => $fine->debit_id(), |
2281 |
type => Koha::Accounts::OffsetTypes::Dropbox(), |
2282 |
amount => $fine->amount_last_increment() * -1, |
2283 |
} |
2284 |
); |
2247 |
} |
2285 |
} |
2248 |
$uquery .= " where (accountlines_id = ?)"; |
2286 |
|
2249 |
my $usth = $dbh->prepare($uquery); |
2287 |
return $fine->update(); |
2250 |
return $usth->execute(@bind); |
|
|
2251 |
} |
2288 |
} |
2252 |
|
2289 |
|
2253 |
=head2 _FixAccountForLostAndReturned |
2290 |
=head2 _FixAccountForLostAndReturned |
2254 |
|
2291 |
|
2255 |
&_FixAccountForLostAndReturned($itemnumber, [$borrowernumber, $barcode]); |
2292 |
&_FixAccountForLostAndReturned($itemnumber); |
2256 |
|
2293 |
|
2257 |
Calculates the charge for a book lost and returned. |
2294 |
Refunds a lost item fee in necessary |
2258 |
|
|
|
2259 |
Internal function, not exported, called only by AddReturn. |
2260 |
|
2261 |
FIXME: This function reflects how inscrutable fines logic is. Fix both. |
2262 |
FIXME: Give a positive return value on success. It might be the $borrowernumber who received credit, or the amount forgiven. |
2263 |
|
2295 |
|
2264 |
=cut |
2296 |
=cut |
2265 |
|
2297 |
|
2266 |
sub _FixAccountForLostAndReturned { |
2298 |
sub _FixAccountForLostAndReturned { |
2267 |
my $itemnumber = shift or return; |
2299 |
my ( $itemnumber ) = @_; |
2268 |
my $borrowernumber = @_ ? shift : undef; |
2300 |
|
2269 |
my $item_id = @_ ? shift : $itemnumber; # Send the barcode if you want that logged in the description |
2301 |
my $schema = Koha::Database->new()->schema; |
2270 |
my $dbh = C4::Context->dbh; |
2302 |
|
2271 |
# check for charge made for lost book |
2303 |
# Find the last issue for this item |
2272 |
my $sth = $dbh->prepare("SELECT * FROM accountlines WHERE itemnumber = ? AND accounttype IN ('L', 'Rep', 'W') ORDER BY date DESC, accountno DESC"); |
2304 |
my $issue = |
2273 |
$sth->execute($itemnumber); |
2305 |
$schema->resultset('Issue')->single( { itemnumber => $itemnumber } ); |
2274 |
my $data = $sth->fetchrow_hashref; |
2306 |
$issue ||= |
2275 |
$data or return; # bail if there is nothing to do |
2307 |
$schema->resultset('OldIssue')->single( { itemnumber => $itemnumber } ); |
2276 |
$data->{accounttype} eq 'W' and return; # Written off |
2308 |
|
2277 |
|
2309 |
return unless $issue; |
2278 |
# writeoff this amount |
2310 |
|
2279 |
my $offset; |
2311 |
# Find a lost fee for this issue |
2280 |
my $amount = $data->{'amount'}; |
2312 |
my $debit = $schema->resultset('AccountDebit')->single( |
2281 |
my $acctno = $data->{'accountno'}; |
2313 |
{ |
2282 |
my $amountleft; # Starts off undef/zero. |
2314 |
issue_id => $issue->issue_id(), |
2283 |
if ($data->{'amountoutstanding'} == $amount) { |
2315 |
type => Koha::Accounts::DebitTypes::Lost() |
2284 |
$offset = $data->{'amount'}; |
2316 |
} |
2285 |
$amountleft = 0; # Hey, it's zero here, too. |
2317 |
); |
2286 |
} else { |
2318 |
|
2287 |
$offset = $amount - $data->{'amountoutstanding'}; # Um, isn't this the same as ZERO? We just tested those two things are == |
2319 |
return unless $debit; |
2288 |
$amountleft = $data->{'amountoutstanding'} - $amount; # Um, isn't this the same as ZERO? We just tested those two things are == |
2320 |
|
2289 |
} |
2321 |
# Check for an existing found credit for this debit, if there is one, the fee has already been refunded and we do nothing |
2290 |
my $usth = $dbh->prepare("UPDATE accountlines SET accounttype = 'LR',amountoutstanding='0' |
2322 |
my @credits = $debit->account_offsets->search_related('credit', { 'credit.type' => Koha::Accounts::CreditTypes::Found() }); |
2291 |
WHERE (accountlines_id = ?)"); |
2323 |
|
2292 |
$usth->execute($data->{'accountlines_id'}); # We might be adjusting an account for some OTHER borrowernumber now. Not the one we passed in. |
2324 |
return if @credits; |
2293 |
#check if any credit is left if so writeoff other accounts |
2325 |
|
2294 |
my $nextaccntno = getnextacctno($data->{'borrowernumber'}); |
2326 |
# Ok, so we know we have an unrefunded lost item fee, let's refund it |
2295 |
$amountleft *= -1 if ($amountleft < 0); |
2327 |
CreditLostItem( |
2296 |
if ($amountleft > 0) { |
2328 |
{ |
2297 |
my $msth = $dbh->prepare("SELECT * FROM accountlines WHERE (borrowernumber = ?) |
2329 |
borrower => $issue->borrower(), |
2298 |
AND (amountoutstanding >0) ORDER BY date"); # might want to order by amountoustanding ASC (pay smallest first) |
2330 |
debit => $debit |
2299 |
$msth->execute($data->{'borrowernumber'}); |
2331 |
} |
2300 |
# offset transactions |
2332 |
); |
2301 |
my $newamtos; |
2333 |
|
2302 |
my $accdata; |
|
|
2303 |
while (($accdata=$msth->fetchrow_hashref) and ($amountleft>0)){ |
2304 |
if ($accdata->{'amountoutstanding'} < $amountleft) { |
2305 |
$newamtos = 0; |
2306 |
$amountleft -= $accdata->{'amountoutstanding'}; |
2307 |
} else { |
2308 |
$newamtos = $accdata->{'amountoutstanding'} - $amountleft; |
2309 |
$amountleft = 0; |
2310 |
} |
2311 |
my $thisacct = $accdata->{'accountlines_id'}; |
2312 |
# FIXME: move prepares outside while loop! |
2313 |
my $usth = $dbh->prepare("UPDATE accountlines SET amountoutstanding= ? |
2314 |
WHERE (accountlines_id = ?)"); |
2315 |
$usth->execute($newamtos,$thisacct); |
2316 |
$usth = $dbh->prepare("INSERT INTO accountoffsets |
2317 |
(borrowernumber, accountno, offsetaccount, offsetamount) |
2318 |
VALUES |
2319 |
(?,?,?,?)"); |
2320 |
$usth->execute($data->{'borrowernumber'},$accdata->{'accountno'},$nextaccntno,$newamtos); |
2321 |
} |
2322 |
} |
2323 |
$amountleft *= -1 if ($amountleft > 0); |
2324 |
my $desc = "Item Returned " . $item_id; |
2325 |
$usth = $dbh->prepare("INSERT INTO accountlines |
2326 |
(borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding) |
2327 |
VALUES (?,?,now(),?,?,'CR',?)"); |
2328 |
$usth->execute($data->{'borrowernumber'},$nextaccntno,0-$amount,$desc,$amountleft); |
2329 |
if ($borrowernumber) { |
2330 |
# FIXME: same as query above. use 1 sth for both |
2331 |
$usth = $dbh->prepare("INSERT INTO accountoffsets |
2332 |
(borrowernumber, accountno, offsetaccount, offsetamount) |
2333 |
VALUES (?,?,?,?)"); |
2334 |
$usth->execute($borrowernumber, $data->{'accountno'}, $nextaccntno, $offset); |
2335 |
} |
2336 |
ModItem({ paidfor => '' }, undef, $itemnumber); |
2334 |
ModItem({ paidfor => '' }, undef, $itemnumber); |
2337 |
return; |
|
|
2338 |
} |
2335 |
} |
2339 |
|
2336 |
|
2340 |
=head2 _GetCircControlBranch |
2337 |
=head2 _GetCircControlBranch |
Lines 2784-2797
sub AddRenewal {
Link Here
|
2784 |
my $dbh = C4::Context->dbh; |
2781 |
my $dbh = C4::Context->dbh; |
2785 |
|
2782 |
|
2786 |
# Find the issues record for this book |
2783 |
# Find the issues record for this book |
2787 |
my $sth = |
2784 |
my $issue = Koha::Database->new()->schema->resultset('Issue')->single({ itemnumber => $itemnumber }); |
2788 |
$dbh->prepare("SELECT * FROM issues WHERE itemnumber = ?"); |
|
|
2789 |
$sth->execute( $itemnumber ); |
2790 |
my $issuedata = $sth->fetchrow_hashref; |
2791 |
|
2785 |
|
2792 |
return unless ( $issuedata ); |
2786 |
return unless ( $issue ); |
2793 |
|
2787 |
|
2794 |
$borrowernumber ||= $issuedata->{borrowernumber}; |
2788 |
$borrowernumber ||= $issue->get_column('borrowernumber'); |
2795 |
|
2789 |
|
2796 |
if ( defined $datedue && ref $datedue ne 'DateTime' ) { |
2790 |
if ( defined $datedue && ref $datedue ne 'DateTime' ) { |
2797 |
carp 'Invalid date passed to AddRenewal.'; |
2791 |
carp 'Invalid date passed to AddRenewal.'; |
Lines 2807-2847
sub AddRenewal {
Link Here
|
2807 |
my $itemtype = (C4::Context->preference('item-level_itypes')) ? $biblio->{'itype'} : $biblio->{'itemtype'}; |
2801 |
my $itemtype = (C4::Context->preference('item-level_itypes')) ? $biblio->{'itype'} : $biblio->{'itemtype'}; |
2808 |
|
2802 |
|
2809 |
$datedue = (C4::Context->preference('RenewalPeriodBase') eq 'date_due') ? |
2803 |
$datedue = (C4::Context->preference('RenewalPeriodBase') eq 'date_due') ? |
2810 |
dt_from_string( $issuedata->{date_due} ) : |
2804 |
dt_from_string( $issue->get_column('date_due') ) : |
2811 |
DateTime->now( time_zone => C4::Context->tz()); |
2805 |
DateTime->now( time_zone => C4::Context->tz()); |
2812 |
$datedue = CalcDateDue($datedue, $itemtype, $issuedata->{'branchcode'}, $borrower, 'is a renewal'); |
2806 |
$datedue = CalcDateDue($datedue, $itemtype, $issue->get_column('branchcode'), $borrower, 'is a renewal'); |
2813 |
} |
2807 |
} |
2814 |
|
2808 |
|
2815 |
# Update the issues record to have the new due date, and a new count |
2809 |
# Update the issues record to have the new due date, and a new count |
2816 |
# of how many times it has been renewed. |
2810 |
# of how many times it has been renewed. |
2817 |
my $renews = $issuedata->{'renewals'} + 1; |
2811 |
$issue->update( |
2818 |
$sth = $dbh->prepare("UPDATE issues SET date_due = ?, renewals = ?, lastreneweddate = ? |
2812 |
{ |
2819 |
WHERE borrowernumber=? |
2813 |
date_due => $datedue->strftime('%Y-%m-%d %H:%M'), |
2820 |
AND itemnumber=?" |
2814 |
renewals => $issue->renewals() + 1, |
|
|
2815 |
lastreneweddate => $lastreneweddate, |
2816 |
} |
2821 |
); |
2817 |
); |
2822 |
|
2818 |
|
2823 |
$sth->execute( $datedue->strftime('%Y-%m-%d %H:%M'), $renews, $lastreneweddate, $borrowernumber, $itemnumber ); |
|
|
2824 |
|
2819 |
|
2825 |
# Update the renewal count on the item, and tell zebra to reindex |
2820 |
# Update the renewal count on the item, and tell zebra to reindex |
2826 |
$renews = $biblio->{'renewals'} + 1; |
2821 |
my $renews = $biblio->{'renewals'} + 1; |
2827 |
ModItem({ renewals => $renews, onloan => $datedue->strftime('%Y-%m-%d %H:%M')}, $biblio->{'biblionumber'}, $itemnumber); |
2822 |
ModItem({ renewals => $renews, onloan => $datedue->strftime('%Y-%m-%d %H:%M')}, $biblio->{'biblionumber'}, $itemnumber); |
2828 |
|
2823 |
|
2829 |
# Charge a new rental fee, if applicable? |
2824 |
# Charge a new rental fee, if applicable? |
2830 |
my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber ); |
2825 |
my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber ); |
2831 |
if ( $charge > 0 ) { |
2826 |
if ( $charge > 0 ) { |
2832 |
my $accountno = getnextacctno( $borrowernumber ); |
|
|
2833 |
my $item = GetBiblioFromItemNumber($itemnumber); |
2827 |
my $item = GetBiblioFromItemNumber($itemnumber); |
2834 |
my $manager_id = 0; |
2828 |
|
2835 |
$manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; |
2829 |
my $borrower = |
2836 |
$sth = $dbh->prepare( |
2830 |
Koha::Database->new()->schema->resultset('Borrower') |
2837 |
"INSERT INTO accountlines |
2831 |
->find($borrowernumber); |
2838 |
(date, borrowernumber, accountno, amount, manager_id, |
2832 |
|
2839 |
description,accounttype, amountoutstanding, itemnumber) |
2833 |
AddDebit( |
2840 |
VALUES (now(),?,?,?,?,?,?,?,?)" |
2834 |
{ |
|
|
2835 |
borrower => $borrower, |
2836 |
itemnumber => $itemnumber, |
2837 |
amount => $charge, |
2838 |
type => Koha::Accounts::DebitTypes::Rental(), |
2839 |
description => |
2840 |
"Renewal of Rental Item $item->{'title'} $item->{'barcode'}" |
2841 |
} |
2841 |
); |
2842 |
); |
2842 |
$sth->execute( $borrowernumber, $accountno, $charge, $manager_id, |
|
|
2843 |
"Renewal of Rental Item $item->{'title'} $item->{'barcode'}", |
2844 |
'Rent', $charge, $itemnumber ); |
2845 |
} |
2843 |
} |
2846 |
|
2844 |
|
2847 |
# Send a renewal slip according to checkout alert preferencei |
2845 |
# Send a renewal slip according to checkout alert preferencei |
Lines 2883-2888
sub AddRenewal {
Link Here
|
2883 |
borrowernumber => $borrowernumber, |
2881 |
borrowernumber => $borrowernumber, |
2884 |
ccode => $item->{'ccode'}} |
2882 |
ccode => $item->{'ccode'}} |
2885 |
); |
2883 |
); |
|
|
2884 |
|
2885 |
_FinalizeFine( { issue => $issue } ); |
2886 |
|
2886 |
return $datedue; |
2887 |
return $datedue; |
2887 |
} |
2888 |
} |
2888 |
|
2889 |
|
Lines 3067-3091
sub _get_discount_from_rule {
Link Here
|
3067 |
|
3068 |
|
3068 |
=head2 AddIssuingCharge |
3069 |
=head2 AddIssuingCharge |
3069 |
|
3070 |
|
3070 |
&AddIssuingCharge( $itemno, $borrowernumber, $charge ) |
3071 |
&AddIssuingCharge( $itemnumber, $borrowernumber, $amount ) |
3071 |
|
3072 |
|
3072 |
=cut |
3073 |
=cut |
3073 |
|
3074 |
|
3074 |
sub AddIssuingCharge { |
3075 |
sub AddIssuingCharge { |
3075 |
my ( $itemnumber, $borrowernumber, $charge ) = @_; |
3076 |
my ( $itemnumber, $borrowernumber, $amount ) = @_; |
3076 |
my $dbh = C4::Context->dbh; |
3077 |
|
3077 |
my $nextaccntno = getnextacctno( $borrowernumber ); |
3078 |
return AddDebit( |
3078 |
my $manager_id = 0; |
3079 |
{ |
3079 |
$manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; |
3080 |
borrower => Koha::Database->new()->schema->resultset('Borrower')->find($borrowernumber), |
3080 |
my $query =" |
3081 |
itemnumber => $itemnumber, |
3081 |
INSERT INTO accountlines |
3082 |
amount => $amount, |
3082 |
(borrowernumber, itemnumber, accountno, |
3083 |
type => Koha::Accounts::DebitTypes::Rental(), |
3083 |
date, amount, description, accounttype, |
3084 |
} |
3084 |
amountoutstanding, manager_id) |
3085 |
); |
3085 |
VALUES (?, ?, ?,now(), ?, 'Rental', 'Rent',?,?) |
|
|
3086 |
"; |
3087 |
my $sth = $dbh->prepare($query); |
3088 |
$sth->execute( $borrowernumber, $itemnumber, $nextaccntno, $charge, $charge, $manager_id ); |
3089 |
} |
3086 |
} |
3090 |
|
3087 |
|
3091 |
=head2 GetTransfers |
3088 |
=head2 GetTransfers |
Lines 3619-3648
sub ReturnLostItem{
Link Here
|
3619 |
sub LostItem{ |
3616 |
sub LostItem{ |
3620 |
my ($itemnumber, $mark_returned) = @_; |
3617 |
my ($itemnumber, $mark_returned) = @_; |
3621 |
|
3618 |
|
3622 |
my $dbh = C4::Context->dbh(); |
3619 |
my $schema = Koha::Database->new()->schema; |
3623 |
my $sth=$dbh->prepare("SELECT issues.*,items.*,biblio.title |
|
|
3624 |
FROM issues |
3625 |
JOIN items USING (itemnumber) |
3626 |
JOIN biblio USING (biblionumber) |
3627 |
WHERE issues.itemnumber=?"); |
3628 |
$sth->execute($itemnumber); |
3629 |
my $issues=$sth->fetchrow_hashref(); |
3630 |
|
3620 |
|
3631 |
# If a borrower lost the item, add a replacement cost to the their record |
3621 |
my $issue = |
3632 |
if ( my $borrowernumber = $issues->{borrowernumber} ){ |
3622 |
$schema->resultset('Issue')->single( { itemnumber => $itemnumber } ); |
3633 |
my $borrower = C4::Members::GetMemberDetails( $borrowernumber ); |
3623 |
|
|
|
3624 |
my ( $borrower, $item ); |
3634 |
|
3625 |
|
|
|
3626 |
if ( $issue ) { |
3627 |
$borrower = $issue->borrower(); |
3628 |
$item = $issue->item(); |
3629 |
} |
3630 |
|
3631 |
# If a borrower lost the item, add a replacement cost to the their record |
3632 |
if ( $borrower ){ |
3635 |
if (C4::Context->preference('WhenLostForgiveFine')){ |
3633 |
if (C4::Context->preference('WhenLostForgiveFine')){ |
3636 |
my $fix = _FixOverduesOnReturn($borrowernumber, $itemnumber, 1, 0); # 1, 0 = exemptfine, no-dropbox |
3634 |
_FinalizeFine( |
3637 |
defined($fix) or warn "_FixOverduesOnReturn($borrowernumber, $itemnumber...) failed!"; # zero is OK, check defined |
3635 |
{ |
|
|
3636 |
exempt_fine => 1, |
3637 |
dropbox => 0, |
3638 |
issue => $issue, |
3639 |
} |
3640 |
); |
3638 |
} |
3641 |
} |
3639 |
if (C4::Context->preference('WhenLostChargeReplacementFee')){ |
3642 |
if ( C4::Context->preference('WhenLostChargeReplacementFee') ) { |
3640 |
C4::Accounts::chargelostitem($borrowernumber, $itemnumber, $issues->{'replacementprice'}, "Lost Item $issues->{'title'} $issues->{'barcode'}"); |
3643 |
DebitLostItem( { borrower => $borrower, issue => $issue } ); |
3641 |
#FIXME : Should probably have a way to distinguish this from an item that really was returned. |
|
|
3642 |
#warn " $issues->{'borrowernumber'} / $itemnumber "; |
3643 |
} |
3644 |
} |
3644 |
|
3645 |
|
3645 |
MarkIssueReturned($borrowernumber,$itemnumber,undef,undef,$borrower->{'privacy'}) if $mark_returned; |
3646 |
MarkIssueReturned( $borrower->borrowernumber(), $item->itemnumber(), undef, undef, $borrower->privacy() ) if $mark_returned; |
3646 |
} |
3647 |
} |
3647 |
} |
3648 |
} |
3648 |
|
3649 |
|
Lines 3760-3769
sub ProcessOfflineIssue {
Link Here
|
3760 |
sub ProcessOfflinePayment { |
3761 |
sub ProcessOfflinePayment { |
3761 |
my $operation = shift; |
3762 |
my $operation = shift; |
3762 |
|
3763 |
|
3763 |
my $borrower = C4::Members::GetMemberDetails( undef, $operation->{cardnumber} ); # Get borrower from operation cardnumber |
3764 |
AddCredit( |
3764 |
my $amount = $operation->{amount}; |
3765 |
{ |
3765 |
|
3766 |
borrower => Koha::Database->new()->schema->resultset('Borrower') |
3766 |
recordpayment( $borrower->{borrowernumber}, $amount ); |
3767 |
->single( { cardnumber => $operation->{cardnumber} } ), |
|
|
3768 |
amount => $operation->{amount}, |
3769 |
notes => 'via offline circulation', |
3770 |
type => Koha::Accounts::CreditTypes::Payment, |
3771 |
} |
3772 |
); |
3767 |
|
3773 |
|
3768 |
return "Success." |
3774 |
return "Success." |
3769 |
} |
3775 |
} |