View | Details | Raw Unified | Return to bug 6427
Collapse All | Expand All

(-)a/C4/Circulation.pm (-209 / +215 lines)
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
2191
   &_FixOverduesOnReturn($brn,$itm, $exemptfine, $dropboxmode);
2192
2193
C<$brn> borrowernumber
2194
2213
2195
C<$itm> itemnumber
2214
   _FinalizeFine({
2215
        exempt_fine => $exempt_fine,
2216
        dropbox     => $dropbox,
2217
        issue       => $issue,
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 2793-2806 sub AddRenewal { Link Here
2793
    my $dbh = C4::Context->dbh;
2790
    my $dbh = C4::Context->dbh;
2794
2791
2795
    # Find the issues record for this book
2792
    # Find the issues record for this book
2796
    my $sth =
2793
    my $issue = Koha::Database->new()->schema->resultset('Issue')->single({ itemnumber => $itemnumber });
2797
      $dbh->prepare("SELECT * FROM issues WHERE itemnumber = ?");
2798
    $sth->execute( $itemnumber );
2799
    my $issuedata = $sth->fetchrow_hashref;
2800
2794
2801
    return unless ( $issuedata );
2795
    return unless ( $issue );
2802
2796
2803
    $borrowernumber ||= $issuedata->{borrowernumber};
2797
    $borrowernumber ||= $issue->get_column('borrowernumber');
2804
2798
2805
    if ( defined $datedue && ref $datedue ne 'DateTime' ) {
2799
    if ( defined $datedue && ref $datedue ne 'DateTime' ) {
2806
        carp 'Invalid date passed to AddRenewal.';
2800
        carp 'Invalid date passed to AddRenewal.';
Lines 2816-2856 sub AddRenewal { Link Here
2816
        my $itemtype = (C4::Context->preference('item-level_itypes')) ? $biblio->{'itype'} : $biblio->{'itemtype'};
2810
        my $itemtype = (C4::Context->preference('item-level_itypes')) ? $biblio->{'itype'} : $biblio->{'itemtype'};
2817
2811
2818
        $datedue = (C4::Context->preference('RenewalPeriodBase') eq 'date_due') ?
2812
        $datedue = (C4::Context->preference('RenewalPeriodBase') eq 'date_due') ?
2819
                                        dt_from_string( $issuedata->{date_due} ) :
2813
                                        dt_from_string( $issue->get_column('date_due') ) :
2820
                                        DateTime->now( time_zone => C4::Context->tz());
2814
                                        DateTime->now( time_zone => C4::Context->tz());
2821
        $datedue =  CalcDateDue($datedue, $itemtype, $issuedata->{'branchcode'}, $borrower, 'is a renewal');
2815
        $datedue =  CalcDateDue($datedue, $itemtype, $issue->get_column('branchcode'), $borrower, 'is a renewal');
2822
    }
2816
    }
2823
2817
2824
    # Update the issues record to have the new due date, and a new count
2818
    # Update the issues record to have the new due date, and a new count
2825
    # of how many times it has been renewed.
2819
    # of how many times it has been renewed.
2826
    my $renews = $issuedata->{'renewals'} + 1;
2820
    $issue->update(
2827
    $sth = $dbh->prepare("UPDATE issues SET date_due = ?, renewals = ?, lastreneweddate = ?
2821
        {
2828
                            WHERE borrowernumber=? 
2822
            date_due        => $datedue->strftime('%Y-%m-%d %H:%M'),
2829
                            AND itemnumber=?"
2823
            renewals        => $issue->renewals() + 1,
2824
            lastreneweddate => $lastreneweddate,
2825
        }
2830
    );
2826
    );
2831
2827
2832
    $sth->execute( $datedue->strftime('%Y-%m-%d %H:%M'), $renews, $lastreneweddate, $borrowernumber, $itemnumber );
2833
2828
2834
    # Update the renewal count on the item, and tell zebra to reindex
2829
    # Update the renewal count on the item, and tell zebra to reindex
2835
    $renews = $biblio->{'renewals'} + 1;
2830
    my $renews = $biblio->{'renewals'} + 1;
2836
    ModItem({ renewals => $renews, onloan => $datedue->strftime('%Y-%m-%d %H:%M')}, $biblio->{'biblionumber'}, $itemnumber);
2831
    ModItem({ renewals => $renews, onloan => $datedue->strftime('%Y-%m-%d %H:%M')}, $biblio->{'biblionumber'}, $itemnumber);
2837
2832
2838
    # Charge a new rental fee, if applicable?
2833
    # Charge a new rental fee, if applicable?
2839
    my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber );
2834
    my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber );
2840
    if ( $charge > 0 ) {
2835
    if ( $charge > 0 ) {
2841
        my $accountno = getnextacctno( $borrowernumber );
2842
        my $item = GetBiblioFromItemNumber($itemnumber);
2836
        my $item = GetBiblioFromItemNumber($itemnumber);
2843
        my $manager_id = 0;
2837
2844
        $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; 
2838
        my $borrower =
2845
        $sth = $dbh->prepare(
2839
          Koha::Database->new()->schema->resultset('Borrower')
2846
                "INSERT INTO accountlines
2840
          ->find($borrowernumber);
2847
                    (date, borrowernumber, accountno, amount, manager_id,
2841
2848
                    description,accounttype, amountoutstanding, itemnumber)
2842
        AddDebit(
2849
                    VALUES (now(),?,?,?,?,?,?,?,?)"
2843
            {
2844
                borrower   => $borrower,
2845
                itemnumber => $itemnumber,
2846
                amount     => $charge,
2847
                type       => Koha::Accounts::DebitTypes::Rental(),
2848
                description =>
2849
                  "Renewal of Rental Item $item->{'title'} $item->{'barcode'}"
2850
            }
2850
        );
2851
        );
2851
        $sth->execute( $borrowernumber, $accountno, $charge, $manager_id,
2852
            "Renewal of Rental Item $item->{'title'} $item->{'barcode'}",
2853
            'Rent', $charge, $itemnumber );
2854
    }
2852
    }
2855
2853
2856
    # Send a renewal slip according to checkout alert preferencei
2854
    # Send a renewal slip according to checkout alert preferencei
Lines 2892-2897 sub AddRenewal { Link Here
2892
                borrowernumber => $borrowernumber,
2890
                borrowernumber => $borrowernumber,
2893
                ccode => $item->{'ccode'}}
2891
                ccode => $item->{'ccode'}}
2894
                );
2892
                );
2893
2894
    _FinalizeFine( { issue => $issue } );
2895
2895
	return $datedue;
2896
	return $datedue;
2896
}
2897
}
2897
2898
Lines 3076-3100 sub _get_discount_from_rule { Link Here
3076
3077
3077
=head2 AddIssuingCharge
3078
=head2 AddIssuingCharge
3078
3079
3079
  &AddIssuingCharge( $itemno, $borrowernumber, $charge )
3080
  &AddIssuingCharge( $itemnumber, $borrowernumber, $amount )
3080
3081
3081
=cut
3082
=cut
3082
3083
3083
sub AddIssuingCharge {
3084
sub AddIssuingCharge {
3084
    my ( $itemnumber, $borrowernumber, $charge ) = @_;
3085
    my ( $itemnumber, $borrowernumber, $amount ) = @_;
3085
    my $dbh = C4::Context->dbh;
3086
3086
    my $nextaccntno = getnextacctno( $borrowernumber );
3087
    return AddDebit(
3087
    my $manager_id = 0;
3088
        {
3088
    $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
3089
            borrower       => Koha::Database->new()->schema->resultset('Borrower')->find($borrowernumber),
3089
    my $query ="
3090
            itemnumber     => $itemnumber,
3090
        INSERT INTO accountlines
3091
            amount         => $amount,
3091
            (borrowernumber, itemnumber, accountno,
3092
            type           => Koha::Accounts::DebitTypes::Rental(),
3092
            date, amount, description, accounttype,
3093
        }
3093
            amountoutstanding, manager_id)
3094
    );
3094
        VALUES (?, ?, ?,now(), ?, 'Rental', 'Rent',?,?)
3095
    ";
3096
    my $sth = $dbh->prepare($query);
3097
    $sth->execute( $borrowernumber, $itemnumber, $nextaccntno, $charge, $charge, $manager_id );
3098
}
3095
}
3099
3096
3100
=head2 GetTransfers
3097
=head2 GetTransfers
Lines 3628-3657 sub ReturnLostItem{ Link Here
3628
sub LostItem{
3625
sub LostItem{
3629
    my ($itemnumber, $mark_returned) = @_;
3626
    my ($itemnumber, $mark_returned) = @_;
3630
3627
3631
    my $dbh = C4::Context->dbh();
3628
    my $schema = Koha::Database->new()->schema;
3632
    my $sth=$dbh->prepare("SELECT issues.*,items.*,biblio.title 
3633
                           FROM issues 
3634
                           JOIN items USING (itemnumber) 
3635
                           JOIN biblio USING (biblionumber)
3636
                           WHERE issues.itemnumber=?");
3637
    $sth->execute($itemnumber);
3638
    my $issues=$sth->fetchrow_hashref();
3639
3629
3640
    # If a borrower lost the item, add a replacement cost to the their record
3630
    my $issue =
3641
    if ( my $borrowernumber = $issues->{borrowernumber} ){
3631
      $schema->resultset('Issue')->single( { itemnumber => $itemnumber } );
3642
        my $borrower = C4::Members::GetMemberDetails( $borrowernumber );
3643
3632
3633
    my ( $borrower, $item );
3634
3635
    if ( $issue ) {
3636
        $borrower = $issue->borrower();
3637
        $item     = $issue->item();
3638
    }
3639
3640
    # If a borrower lost the item, add a replacement cost to the their record
3641
    if ( $borrower ){
3644
        if (C4::Context->preference('WhenLostForgiveFine')){
3642
        if (C4::Context->preference('WhenLostForgiveFine')){
3645
            my $fix = _FixOverduesOnReturn($borrowernumber, $itemnumber, 1, 0); # 1, 0 = exemptfine, no-dropbox
3643
            _FinalizeFine(
3646
            defined($fix) or warn "_FixOverduesOnReturn($borrowernumber, $itemnumber...) failed!";  # zero is OK, check defined
3644
                {
3645
                    exempt_fine => 1,
3646
                    dropbox     => 0,
3647
                    issue       => $issue,
3648
                }
3649
            );
3647
        }
3650
        }
3648
        if (C4::Context->preference('WhenLostChargeReplacementFee')){
3651
        if ( C4::Context->preference('WhenLostChargeReplacementFee') ) {
3649
            C4::Accounts::chargelostitem($borrowernumber, $itemnumber, $issues->{'replacementprice'}, "Lost Item $issues->{'title'} $issues->{'barcode'}");
3652
            DebitLostItem( { borrower => $borrower, issue => $issue } );
3650
            #FIXME : Should probably have a way to distinguish this from an item that really was returned.
3651
            #warn " $issues->{'borrowernumber'}  /  $itemnumber ";
3652
        }
3653
        }
3653
3654
3654
        MarkIssueReturned($borrowernumber,$itemnumber,undef,undef,$borrower->{'privacy'}) if $mark_returned;
3655
        MarkIssueReturned( $borrower->borrowernumber(), $item->itemnumber(), undef, undef, $borrower->privacy() ) if $mark_returned;
3655
    }
3656
    }
3656
}
3657
}
3657
3658
Lines 3769-3778 sub ProcessOfflineIssue { Link Here
3769
sub ProcessOfflinePayment {
3770
sub ProcessOfflinePayment {
3770
    my $operation = shift;
3771
    my $operation = shift;
3771
3772
3772
    my $borrower = C4::Members::GetMemberDetails( undef, $operation->{cardnumber} ); # Get borrower from operation cardnumber
3773
    AddCredit(
3773
    my $amount = $operation->{amount};
3774
        {
3774
3775
            borrower => Koha::Database->new()->schema->resultset('Borrower')
3775
    recordpayment( $borrower->{borrowernumber}, $amount );
3776
              ->single( { cardnumber => $operation->{cardnumber} } ),
3777
            amount => $operation->{amount},
3778
            notes  => 'via offline circulation',
3779
            type   => Koha::Accounts::CreditTypes::Payment,
3780
        }
3781
    );
3776
3782
3777
    return "Success."
3783
    return "Success."
3778
}
3784
}
(-)a/C4/ILSDI/Services.pm (-5 / +4 lines)
Lines 24-30 use C4::Members; Link Here
24
use C4::Items;
24
use C4::Items;
25
use C4::Circulation;
25
use C4::Circulation;
26
use C4::Branch;
26
use C4::Branch;
27
use C4::Accounts;
28
use C4::Biblio;
27
use C4::Biblio;
29
use C4::Reserves qw(AddReserve GetReservesFromBiblionumber GetReservesFromBorrowernumber CanBookBeReserved CanItemBeReserved IsAvailableForItemLevelRequest);
28
use C4::Reserves qw(AddReserve GetReservesFromBiblionumber GetReservesFromBorrowernumber CanBookBeReserved CanItemBeReserved IsAvailableForItemLevelRequest);
30
use C4::Context;
29
use C4::Context;
Lines 34-39 use HTML::Entities; Link Here
34
use CGI qw ( -utf8 );
33
use CGI qw ( -utf8 );
35
use DateTime;
34
use DateTime;
36
use C4::Auth;
35
use C4::Auth;
36
use Koha::Database;
37
37
38
=head1 NAME
38
=head1 NAME
39
39
Lines 387-396 sub GetPatronInfo { Link Here
387
387
388
    # Fines management
388
    # Fines management
389
    if ( $cgi->param('show_fines') eq "1" ) {
389
    if ( $cgi->param('show_fines') eq "1" ) {
390
        my @charges;
390
        my @charges =
391
        for ( my $i = 1 ; my @charge = getcharges( $borrowernumber, undef, $i ) ; $i++ ) {
391
          Koha::Database->new()->schema()->resultset('AccountDebit')
392
            push( @charges, @charge );
392
          ->search( { borrowernumber => $borrowernumber } );
393
        }
394
        $borrower->{'fines'}->{'fine'} = \@charges;
393
        $borrower->{'fines'}->{'fine'} = \@charges;
395
    }
394
    }
396
395
(-)a/C4/Members.pm (-134 / +54 lines)
Lines 29-35 use Date::Calc qw/Today Add_Delta_YM check_date Date_to_Days/; Link Here
29
use C4::Log; # logaction
29
use C4::Log; # logaction
30
use C4::Overdues;
30
use C4::Overdues;
31
use C4::Reserves;
31
use C4::Reserves;
32
use C4::Accounts;
33
use C4::Biblio;
32
use C4::Biblio;
34
use C4::Letters;
33
use C4::Letters;
35
use C4::Members::Attributes qw(SearchIdMatchingAttribute UpdateBorrowerAttribute);
34
use C4::Members::Attributes qw(SearchIdMatchingAttribute UpdateBorrowerAttribute);
Lines 45-50 use Module::Load; Link Here
45
if ( C4::Context->preference('NorwegianPatronDBEnable') && C4::Context->preference('NorwegianPatronDBEnable') == 1 ) {
44
if ( C4::Context->preference('NorwegianPatronDBEnable') && C4::Context->preference('NorwegianPatronDBEnable') == 1 ) {
46
    load Koha::NorwegianPatronDB, qw( NLUpdateHashedPIN NLEncryptPIN NLSync );
45
    load Koha::NorwegianPatronDB, qw( NLUpdateHashedPIN NLEncryptPIN NLSync );
47
}
46
}
47
use Koha::Accounts::DebitTypes;
48
48
49
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug);
49
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug);
50
50
Lines 84-91 BEGIN { Link Here
84
        &GetHideLostItemsPreference
84
        &GetHideLostItemsPreference
85
85
86
        &IsMemberBlocked
86
        &IsMemberBlocked
87
        &GetMemberAccountRecords
88
        &GetBorNotifyAcctRecord
89
87
90
        &GetborCatFromCatType
88
        &GetborCatFromCatType
91
        &GetBorrowercategory
89
        &GetBorrowercategory
Lines 226-234 sub GetMemberDetails { Link Here
226
    }
224
    }
227
    my $borrower = $sth->fetchrow_hashref;
225
    my $borrower = $sth->fetchrow_hashref;
228
    return unless $borrower;
226
    return unless $borrower;
229
    my ($amount) = GetMemberAccountRecords($borrower->{borrowernumber});
227
    $borrower->{amountoutstanding} = $borrower->{account_balance};
230
    $borrower->{'amountoutstanding'} = $amount;
228
    # FIXME - find all references to $borrower->{amountoutstanding}, replace with $borrower->{account_balance}
231
    # FIXME - patronflags calls GetMemberAccountRecords... just have patronflags return $amount
232
    my $flags = patronflags( $borrower);
229
    my $flags = patronflags( $borrower);
233
    my $accessflagshash;
230
    my $accessflagshash;
234
231
Lines 332-354 The "message" field that comes from the DB is OK. Link Here
332
# FIXME rename this function.
329
# FIXME rename this function.
333
sub patronflags {
330
sub patronflags {
334
    my %flags;
331
    my %flags;
335
    my ( $patroninformation) = @_;
332
    my ($patroninformation) = @_;
336
    my $dbh=C4::Context->dbh;
333
    my $dbh = C4::Context->dbh;
337
    my ($balance, $owing) = GetMemberAccountBalance( $patroninformation->{'borrowernumber'});
334
    if ( $patroninformation->{account_balance} > 0 ) {
338
    if ( $owing > 0 ) {
339
        my %flaginfo;
335
        my %flaginfo;
340
        my $noissuescharge = C4::Context->preference("noissuescharge") || 5;
336
        my $noissuescharge = C4::Context->preference("noissuescharge") || 5;
341
        $flaginfo{'message'} = sprintf 'Patron owes %.02f', $owing;
337
        $flaginfo{'amount'}  = $patroninformation->{account_balance};
342
        $flaginfo{'amount'}  = sprintf "%.02f", $owing;
338
        if (  $patroninformation->{account_balance} > $noissuescharge && !C4::Context->preference("AllowFineOverride") ) {
343
        if ( $owing > $noissuescharge && !C4::Context->preference("AllowFineOverride") ) {
344
            $flaginfo{'noissues'} = 1;
339
            $flaginfo{'noissues'} = 1;
345
        }
340
        }
346
        $flags{'CHARGES'} = \%flaginfo;
341
        $flags{'CHARGES'} = \%flaginfo;
347
    }
342
    }
348
    elsif ( $balance < 0 ) {
343
    elsif ( $patroninformation->{account_balance} < 0 ) {
349
        my %flaginfo;
344
        my %flaginfo;
350
        $flaginfo{'message'} = sprintf 'Patron has credit of %.02f', -$balance;
345
        $flaginfo{'amount'}  = $patroninformation->{account_balance};
351
        $flaginfo{'amount'}  = sprintf "%.02f", $balance;
352
        $flags{'CREDITS'} = \%flaginfo;
346
        $flags{'CREDITS'} = \%flaginfo;
353
    }
347
    }
354
    if (   $patroninformation->{'gonenoaddress'}
348
    if (   $patroninformation->{'gonenoaddress'}
Lines 593-599 sub GetMemberIssuesAndFines { Link Here
593
    $sth->execute($borrowernumber);
587
    $sth->execute($borrowernumber);
594
    my $overdue_count = $sth->fetchrow_arrayref->[0];
588
    my $overdue_count = $sth->fetchrow_arrayref->[0];
595
589
596
    $sth = $dbh->prepare("SELECT SUM(amountoutstanding) FROM accountlines WHERE borrowernumber = ?");
590
    $sth = $dbh->prepare("SELECT account_balance FROM borrowers WHERE borrowernumber = ?");
597
    $sth->execute($borrowernumber);
591
    $sth->execute($borrowernumber);
598
    my $total_fines = $sth->fetchrow_arrayref->[0];
592
    my $total_fines = $sth->fetchrow_arrayref->[0];
599
593
Lines 1150-1206 sub GetAllIssues { Link Here
1150
}
1144
}
1151
1145
1152
1146
1153
=head2 GetMemberAccountRecords
1154
1155
  ($total, $acctlines, $count) = &GetMemberAccountRecords($borrowernumber);
1156
1157
Looks up accounting data for the patron with the given borrowernumber.
1158
1159
C<&GetMemberAccountRecords> returns a three-element array. C<$acctlines> is a
1160
reference-to-array, where each element is a reference-to-hash; the
1161
keys are the fields of the C<accountlines> table in the Koha database.
1162
C<$count> is the number of elements in C<$acctlines>. C<$total> is the
1163
total amount outstanding for all of the account lines.
1164
1165
=cut
1166
1167
sub GetMemberAccountRecords {
1168
    my ($borrowernumber) = @_;
1169
    my $dbh = C4::Context->dbh;
1170
    my @acctlines;
1171
    my $numlines = 0;
1172
    my $strsth      = qq(
1173
                        SELECT * 
1174
                        FROM accountlines 
1175
                        WHERE borrowernumber=?);
1176
    $strsth.=" ORDER BY date desc,timestamp DESC";
1177
    my $sth= $dbh->prepare( $strsth );
1178
    $sth->execute( $borrowernumber );
1179
1180
    my $total = 0;
1181
    while ( my $data = $sth->fetchrow_hashref ) {
1182
        if ( $data->{itemnumber} ) {
1183
            my $biblio = GetBiblioFromItemNumber( $data->{itemnumber} );
1184
            $data->{biblionumber} = $biblio->{biblionumber};
1185
            $data->{title}        = $biblio->{title};
1186
        }
1187
        $acctlines[$numlines] = $data;
1188
        $numlines++;
1189
        $total += int(1000 * $data->{'amountoutstanding'}); # convert float to integer to avoid round-off errors
1190
    }
1191
    $total /= 1000;
1192
    return ( $total, \@acctlines,$numlines);
1193
}
1194
1195
=head2 GetMemberAccountBalance
1147
=head2 GetMemberAccountBalance
1196
1148
1197
  ($total_balance, $non_issue_balance, $other_charges) = &GetMemberAccountBalance($borrowernumber);
1149
  ($total_balance, $non_issue_balance, $other_charges) = &GetMemberAccountBalance($borrowernumber);
1198
1150
1199
Calculates amount immediately owing by the patron - non-issue charges.
1151
Calculates amount immediately owing by the patron - non-issue charges.
1200
Based on GetMemberAccountRecords.
1201
Charges exempt from non-issue are:
1152
Charges exempt from non-issue are:
1202
* Res (reserves)
1153
* HOLD fees (reserves)
1203
* Rent (rental) if RentalsInNoissuesCharge syspref is set to false
1154
* RENTAL if RentalsInNoissuesCharge syspref is set to false
1204
* Manual invoices if ManInvInNoissuesCharge syspref is set to false
1155
* Manual invoices if ManInvInNoissuesCharge syspref is set to false
1205
1156
1206
=cut
1157
=cut
Lines 1208-1278 Charges exempt from non-issue are: Link Here
1208
sub GetMemberAccountBalance {
1159
sub GetMemberAccountBalance {
1209
    my ($borrowernumber) = @_;
1160
    my ($borrowernumber) = @_;
1210
1161
1211
    my $ACCOUNT_TYPE_LENGTH = 5; # this is plain ridiculous...
1162
    my $borrower =
1163
      Koha::Database->new()->schema->resultset('Borrower')
1164
      ->find($borrowernumber);
1212
1165
1213
    my @not_fines;
1166
    my @not_fines;
1214
    push @not_fines, 'Res' unless C4::Context->preference('HoldsInNoissuesCharge');
1215
    push @not_fines, 'Rent' unless C4::Context->preference('RentalsInNoissuesCharge');
1216
    unless ( C4::Context->preference('ManInvInNoissuesCharge') ) {
1217
        my $dbh = C4::Context->dbh;
1218
        my $man_inv_types = $dbh->selectcol_arrayref(qq{SELECT authorised_value FROM authorised_values WHERE category = 'MANUAL_INV'});
1219
        push @not_fines, map substr($_, 0, $ACCOUNT_TYPE_LENGTH), @$man_inv_types;
1220
    }
1221
    my %not_fine = map {$_ => 1} @not_fines;
1222
1223
    my ($total, $acctlines) = GetMemberAccountRecords($borrowernumber);
1224
    my $other_charges = 0;
1225
    foreach (@$acctlines) {
1226
        $other_charges += $_->{amountoutstanding} if $not_fine{ substr($_->{accounttype}, 0, $ACCOUNT_TYPE_LENGTH) };
1227
    }
1228
1229
    return ( $total, $total - $other_charges, $other_charges);
1230
}
1231
1167
1232
=head2 GetBorNotifyAcctRecord
1168
    push( @not_fines, Koha::Accounts::DebitTypes::Hold() );
1233
1169
1234
  ($total, $acctlines, $count) = &GetBorNotifyAcctRecord($params,$notifyid);
1170
    push( @not_fines, Koha::Accounts::DebitTypes::Rental() )
1171
      unless C4::Context->preference('RentalsInNoissuesCharge');
1235
1172
1236
Looks up accounting data for the patron with the given borrowernumber per file number.
1173
    unless ( C4::Context->preference('ManInvInNoissuesCharge') ) {
1237
1174
        my $dbh           = C4::Context->dbh;
1238
C<&GetBorNotifyAcctRecord> returns a three-element array. C<$acctlines> is a
1175
        my $man_inv_types = $dbh->selectcol_arrayref(q{
1239
reference-to-array, where each element is a reference-to-hash; the
1176
            SELECT authorised_value FROM authorised_values WHERE category = 'MANUAL_INV'
1240
keys are the fields of the C<accountlines> table in the Koha database.
1177
        });
1241
C<$count> is the number of elements in C<$acctlines>. C<$total> is the
1178
        push( @not_fines, @$man_inv_types );
1242
total amount outstanding for all of the account lines.
1179
    }
1243
1244
=cut
1245
1180
1246
sub GetBorNotifyAcctRecord {
1181
    my $other_charges =
1247
    my ( $borrowernumber, $notifyid ) = @_;
1182
      Koha::Database->new()->schema->resultset('AccountDebit')->search(
1248
    my $dbh = C4::Context->dbh;
1183
        {
1249
    my @acctlines;
1184
            borrowernumber => $borrowernumber,
1250
    my $numlines = 0;
1185
            type           => { -in => \@not_fines }
1251
    my $sth = $dbh->prepare(
1252
            "SELECT * 
1253
                FROM accountlines 
1254
                WHERE borrowernumber=? 
1255
                    AND notify_id=? 
1256
                    AND amountoutstanding != '0' 
1257
                ORDER BY notify_id,accounttype
1258
                ");
1259
1260
    $sth->execute( $borrowernumber, $notifyid );
1261
    my $total = 0;
1262
    while ( my $data = $sth->fetchrow_hashref ) {
1263
        if ( $data->{itemnumber} ) {
1264
            my $biblio = GetBiblioFromItemNumber( $data->{itemnumber} );
1265
            $data->{biblionumber} = $biblio->{biblionumber};
1266
            $data->{title}        = $biblio->{title};
1267
        }
1186
        }
1268
        $acctlines[$numlines] = $data;
1187
      )->get_column('amount_outstanding')->sum();
1269
        $numlines++;
1188
1270
        $total += int(100 * $data->{'amountoutstanding'});
1189
    return (
1271
    }
1190
        $borrower->account_balance(),
1272
    $total /= 100;
1191
        $borrower->account_balance() - $other_charges,
1273
    return ( $total, \@acctlines, $numlines );
1192
        $other_charges
1193
    );
1274
}
1194
}
1275
1195
1196
1276
=head2 checkuniquemember (OUEST-PROVENCE)
1197
=head2 checkuniquemember (OUEST-PROVENCE)
1277
1198
1278
  ($result,$categorycode)  = &checkuniquemember($collectivity,$surname,$firstname,$dateofbirth);
1199
  ($result,$categorycode)  = &checkuniquemember($collectivity,$surname,$firstname,$dateofbirth);
Lines 2492-2513 Add enrolment fee for a patron if needed. Link Here
2492
2413
2493
sub AddEnrolmentFeeIfNeeded {
2414
sub AddEnrolmentFeeIfNeeded {
2494
    my ( $categorycode, $borrowernumber ) = @_;
2415
    my ( $categorycode, $borrowernumber ) = @_;
2495
    # check for enrollment fee & add it if needed
2416
2496
    my $dbh = C4::Context->dbh;
2417
    my $schema = Koha::Database->new()->schema();
2497
    my $sth = $dbh->prepare(q{
2418
2498
        SELECT enrolmentfee
2419
    my $category = $schema->resultset('Category')->find($categorycode);
2499
        FROM categories
2420
    my $fee      = $category->enrolmentfee();
2500
        WHERE categorycode=?
2421
2501
    });
2422
    if ( $fee && $fee > 0 ) {
2502
    $sth->execute( $categorycode );
2423
        AddDebit(
2503
    if ( $sth->err ) {
2424
            {
2504
        warn sprintf('Database returned the following error: %s', $sth->errstr);
2425
                borrower =>
2505
        return;
2426
                  $schema->resultset('Borrower')->find($borrowernumber),
2506
    }
2427
                type   => Koha::Accounts::DebitTypes::AccountManagementFee(),
2507
    my ($enrolmentfee) = $sth->fetchrow;
2428
                amount => $fee,
2508
    if ($enrolmentfee && $enrolmentfee > 0) {
2429
            }
2509
        # insert fee in patron debts
2430
        );
2510
        C4::Accounts::manualinvoice( $borrowernumber, '', '', 'A', $enrolmentfee );
2511
    }
2431
    }
2512
}
2432
}
2513
2433
(-)a/C4/Overdues.pm (-210 / +144 lines)
Lines 27-35 use List::MoreUtils qw( uniq ); Link Here
27
27
28
use C4::Circulation;
28
use C4::Circulation;
29
use C4::Context;
29
use C4::Context;
30
use C4::Accounts;
31
use C4::Log; # logaction
30
use C4::Log; # logaction
32
use C4::Debug;
31
use C4::Debug;
32
use Koha::Database;
33
use Koha::DateUtils;
34
use Koha::Accounts::OffsetTypes;
35
use Koha::Accounts::DebitTypes;
33
36
34
use vars qw($VERSION @ISA @EXPORT);
37
use vars qw($VERSION @ISA @EXPORT);
35
38
Lines 43-50 BEGIN { Link Here
43
        &CalcFine
46
        &CalcFine
44
        &Getoverdues
47
        &Getoverdues
45
        &checkoverdues
48
        &checkoverdues
46
        &NumberNotifyId
47
        &AmountNotify
48
        &UpdateFine
49
        &UpdateFine
49
        &GetFine
50
        &GetFine
50
        &get_chargeable_units
51
        &get_chargeable_units
Lines 463-611 sub GetIssuesIteminfo { Link Here
463
464
464
=head2 UpdateFine
465
=head2 UpdateFine
465
466
466
    &UpdateFine($itemnumber, $borrowernumber, $amount, $type, $description);
467
    UpdateFine(
468
        {
469
            itemnumber     => $itemnumber,
470
            borrowernumber => $borrowernumber,
471
            amount         => $amount,
472
            due            => $due,
473
            issue_id       => $issue_id
474
        }
475
    );
467
476
468
(Note: the following is mostly conjecture and guesswork.)
477
Updates the fine owed on an overdue item.
469
478
470
Updates the fine owed on an overdue book.
479
C<$itemnumber> is the items's id.
471
480
472
C<$itemnumber> is the book's item number.
481
C<$borrowernumber> is the id of the patron who currently
482
has the item on loan.
473
483
474
C<$borrowernumber> is the borrower number of the patron who currently
484
C<$amount> is the total amount of the fine owed by the patron.
475
has the book on loan.
476
485
477
C<$amount> is the current amount owed by the patron.
486
C<&UpdateFine> updates the amount owed for a given fine if an issue_id
487
is passed to it. Otherwise, a new fine will be created.
478
488
479
C<$type> will be used in the description of the fine.
489
=cut
480
490
481
C<$description> is a string that must be present in the description of
491
sub UpdateFine {
482
the fine. I think this is expected to be a date in DD/MM/YYYY format.
492
    my ($params) = @_;
483
493
484
C<&UpdateFine> looks up the amount currently owed on the given item
494
    my $itemnumber     = $params->{itemnumber};
485
and sets it to C<$amount>, creating, if necessary, a new entry in the
495
    my $borrowernumber = $params->{borrowernumber};
486
accountlines table of the Koha database.
496
    my $amount         = $params->{amount};
497
    my $due            = $params->{due};
498
    my $issue_id       = $params->{issue_id};
487
499
488
=cut
500
    my $schema = Koha::Database->new()->schema;
489
501
490
#
502
    my $borrower = $schema->resultset('Borrower')->find($borrowernumber);
491
# Question: Why should the caller have to
492
# specify both the item number and the borrower number? A book can't
493
# be on loan to two different people, so the item number should be
494
# sufficient.
495
#
496
# Possible Answer: You might update a fine for a damaged item, *after* it is returned.
497
#
498
sub UpdateFine {
499
    my ( $itemnum, $borrowernumber, $amount, $type, $due ) = @_;
500
	$debug and warn "UpdateFine($itemnum, $borrowernumber, $amount, " . ($type||'""') . ", $due) called";
501
    my $dbh = C4::Context->dbh;
502
    # FIXME - What exactly is this query supposed to do? It looks up an
503
    # entry in accountlines that matches the given item and borrower
504
    # numbers, where the description contains $due, and where the
505
    # account type has one of several values, but what does this _mean_?
506
    # Does it look up existing fines for this item?
507
    # FIXME - What are these various account types? ("FU", "O", "F", "M")
508
	#	"L"   is LOST item
509
	#   "A"   is Account Management Fee
510
	#   "N"   is New Card
511
	#   "M"   is Sundry
512
	#   "O"   is Overdue ??
513
	#   "F"   is Fine ??
514
	#   "FU"  is Fine UPDATE??
515
	#	"Pay" is Payment
516
	#   "REF" is Cash Refund
517
    my $sth = $dbh->prepare(
518
        "SELECT * FROM accountlines
519
        WHERE borrowernumber=?
520
        AND   accounttype IN ('FU','O','F','M')"
521
    );
522
    $sth->execute( $borrowernumber );
523
    my $data;
524
    my $total_amount_other = 0.00;
525
    my $due_qr = qr/$due/;
526
    # Cycle through the fines and
527
    # - find line that relates to the requested $itemnum
528
    # - accumulate fines for other items
529
    # so we can update $itemnum fine taking in account fine caps
530
    while (my $rec = $sth->fetchrow_hashref) {
531
        if ($rec->{itemnumber} == $itemnum && $rec->{description} =~ /$due_qr/) {
532
            if ($data) {
533
                warn "Not a unique accountlines record for item $itemnum borrower $borrowernumber";
534
            } else {
535
                $data = $rec;
536
                next;
537
            }
538
        }
539
        $total_amount_other += $rec->{'amountoutstanding'};
540
    }
541
503
542
    if (my $maxfine = C4::Context->preference('MaxFine')) {
504
    if ( my $maxfine = C4::Context->preference('MaxFine') ) {
543
        if ($total_amount_other + $amount > $maxfine) {
505
        if ( $borrower->account_balance() + $amount > $maxfine ) {
544
            my $new_amount = $maxfine - $total_amount_other;
506
            my $new_amount = $maxfine - $borrower->account_balance();
545
            return if $new_amount <= 0.00;
507
            warn "Reducing fine for item $itemnumber borrower $borrowernumber from $amount to $new_amount - MaxFine reached";
546
            warn "Reducing fine for item $itemnum borrower $borrowernumber from $amount to $new_amount - MaxFine reached";
508
            if ( $new_amount <= 0 ) {
509
                warn "Fine reduced to a non-positive ammount. Fine not created.";
510
                return;
511
            }
547
            $amount = $new_amount;
512
            $amount = $new_amount;
548
        }
513
        }
549
    }
514
    }
550
515
551
    if ( $data ) {
516
    my $timestamp = get_timestamp();
552
517
553
		# we're updating an existing fine.  Only modify if amount changed
518
    my $fine = $schema->resultset('AccountDebit')->single(
554
        # Note that in the current implementation, you cannot pay against an accruing fine
519
        {
555
        # (i.e. , of accounttype 'FU').  Doing so will break accrual.
520
            issue_id => $issue_id,
556
    	if ( $data->{'amount'} != $amount ) {
521
            type     => Koha::Accounts::DebitTypes::Fine,
557
            my $diff = $amount - $data->{'amount'};
522
            accruing => 1,
558
	    #3341: diff could be positive or negative!
559
            my $out  = $data->{'amountoutstanding'} + $diff;
560
            my $query = "
561
                UPDATE accountlines
562
				SET date=now(), amount=?, amountoutstanding=?,
563
					lastincrement=?, accounttype='FU'
564
	  			WHERE borrowernumber=?
565
				AND   itemnumber=?
566
				AND   accounttype IN ('FU','O')
567
				AND   description LIKE ?
568
				LIMIT 1 ";
569
            my $sth2 = $dbh->prepare($query);
570
			# FIXME: BOGUS query cannot ensure uniqueness w/ LIKE %x% !!!
571
			# 		LIMIT 1 added to prevent multiple affected lines
572
			# FIXME: accountlines table needs unique key!! Possibly a combo of borrowernumber and accountline.  
573
			# 		But actually, we should just have a regular autoincrementing PK and forget accountline,
574
			# 		including the bogus getnextaccountno function (doesn't prevent conflict on simultaneous ops).
575
			# FIXME: Why only 2 account types here?
576
			$debug and print STDERR "UpdateFine query: $query\n" .
577
				"w/ args: $amount, $out, $diff, $data->{'borrowernumber'}, $data->{'itemnumber'}, \"\%$due\%\"\n";
578
            $sth2->execute($amount, $out, $diff, $data->{'borrowernumber'}, $data->{'itemnumber'}, "%$due%");
579
        } else {
580
            #      print "no update needed $data->{'amount'}"
581
        }
523
        }
582
    } else {
524
    );
583
        if ( $amount ) { # Don't add new fines with an amount of 0
525
584
            my $sth4 = $dbh->prepare(
526
    my $offset = 0;
585
                "SELECT title FROM biblio LEFT JOIN items ON biblio.biblionumber=items.biblionumber WHERE items.itemnumber=?"
527
    my $credit;
586
            );
528
    if ($fine) {
587
            $sth4->execute($itemnum);
529
        if ( $fine->accruing() ) { # Don't update or recreate fines no longer accruing
588
            my $title = $sth4->fetchrow;
530
            if (
589
531
                sprintf( "%.6f", $fine->amount_original() )
590
            my $nextaccntno = C4::Accounts::getnextacctno($borrowernumber);
532
                ne
591
533
                sprintf( "%.6f", $amount ) )
592
            my $desc = ( $type ? "$type " : '' ) . "$title $due";    # FIXEDME, avoid whitespace prefix on empty $type
534
            {
593
535
                my $difference = $amount - $fine->amount_original();
594
            my $query = "INSERT INTO accountlines
536
595
                         (borrowernumber,itemnumber,date,amount,description,accounttype,amountoutstanding,lastincrement,accountno)
537
                # Fine was reduced by a change in circulation rules or another reason
596
                         VALUES (?,?,now(),?,?,'FU',?,?,?)";
538
                # we need to credit the account the difference and zero out the amount outstanding
597
            my $sth2 = $dbh->prepare($query);
539
                if ( $difference < 0 ) {
598
            $debug and print STDERR "UpdateFine query: $query\nw/ args: $borrowernumber, $itemnum, $amount, $desc, $amount, $amount, $nextaccntno\n";
540
                    $fine->amount_outstanding( $fine->amount_outstanding() + $difference );
599
            $sth2->execute( $borrowernumber, $itemnum, $amount, $desc, $amount, $amount, $nextaccntno );
541
542
                    $credit =
543
                      Koha::Database->new()->schema->resultset('AccountCredit')
544
                      ->create(
545
                        {
546
                            borrowernumber => $borrowernumber,
547
                            type => Koha::Accounts::CreditTypes::FineReduction(),
548
                            amount_remaining => abs($difference),
549
                            created_on       => $timestamp,
550
                        }
551
                      );
552
553
                } else {
554
                    $fine->amount_outstanding( $amount );
555
                }
556
557
                $fine->amount_last_increment($difference);
558
                $fine->amount_original( $fine->amount_original() + $difference );
559
                $fine->updated_on($timestamp);
560
                $fine->update();
561
562
                $offset = 1;
563
            }
600
        }
564
        }
601
    }
565
    }
602
    # logging action
566
    elsif ( $amount ) { # No fine to update, don't insert fines of $0.00
603
    &logaction(
567
        my $item = $schema->resultset('Item')->find($itemnumber);
604
        "FINES",
568
605
        $type,
569
        $fine = $schema->resultset('AccountDebit')->create(
570
            {
571
                borrowernumber        => $borrowernumber,
572
                itemnumber            => $itemnumber,
573
                issue_id              => $issue_id,
574
                type                  => Koha::Accounts::DebitTypes::Fine(),
575
                accruing              => 1,
576
                amount_original       => $amount,
577
                amount_outstanding    => $amount,
578
                amount_last_increment => $amount,
579
                description           => $item->biblio()->title() . " / Due:$due",
580
                created_on            => $timestamp,
581
            }
582
        );
583
584
        $offset = 1;
585
    } else { # No fine to update, amount is 0, just return
586
        return;
587
    }
588
589
    $schema->resultset('AccountOffset')->create(
590
        {
591
            debit_id   => $fine->debit_id(),
592
            credit_id  => $credit ? $credit->credit_id() : undef,
593
            amount     => $fine->amount_last_increment(),
594
            created_on => $timestamp,
595
            type       => Koha::Accounts::OffsetTypes::Fine(),
596
        }
597
    ) if $offset;
598
599
    $borrower->account_balance( $borrower->account_balance + $fine->amount_last_increment() );
600
    $borrower->update();
601
602
    logaction( "FINES", Koha::Accounts::DebitTypes::Fine(),
606
        $borrowernumber,
603
        $borrowernumber,
607
        "due=".$due."  amount=".$amount." itemnumber=".$itemnum
604
        "due=" . $due . "  amount=" . $amount . " itemnumber=" . $itemnumber )
608
        ) if C4::Context->preference("FinesLog");
605
      if C4::Context->preference("FinesLog");
609
}
606
}
610
607
611
=head2 BorType
608
=head2 BorType
Lines 667-722 sub GetFine { Link Here
667
    return 0;
664
    return 0;
668
}
665
}
669
666
670
=head2 NumberNotifyId
671
672
    (@notify) = &NumberNotifyId($borrowernumber);
673
674
Returns amount for all file per borrowers
675
C<@notify> array contains all file per borrowers
676
677
C<$notify_id> contains the file number for the borrower number nad item number
678
679
=cut
680
681
sub NumberNotifyId{
682
    my ($borrowernumber)=@_;
683
    my $dbh = C4::Context->dbh;
684
    my $query=qq|    SELECT distinct(notify_id)
685
            FROM accountlines
686
            WHERE borrowernumber=?|;
687
    my @notify;
688
    my $sth = $dbh->prepare($query);
689
    $sth->execute($borrowernumber);
690
    while ( my ($numberofnotify) = $sth->fetchrow ) {
691
        push( @notify, $numberofnotify );
692
    }
693
    return (@notify);
694
}
695
696
=head2 AmountNotify
697
667
698
    ($totalnotify) = &AmountNotify($notifyid);
668
=head2 NumberNotifyId
699
700
Returns amount for all file per borrowers
701
C<$notifyid> is the file number
702
703
C<$totalnotify> contains amount of a file
704
669
705
C<$notify_id> contains the file number for the borrower number and item number
670
    my $schema = Koha::Database->new()->schema;
706
671
707
=cut
672
    my $amount_outstanding = $schema->resultset('AccountDebit')->search(
673
        {
674
            itemnumber     => $itemnumber,
675
            borrowernumber => $borrowernumber,
676
            type           => Koha::Accounts::DebitTypes::Fine(),
677
        },
678
    )->get_column('amount_outstanding')->sum();
708
679
709
sub AmountNotify{
680
    return $amount_outstanding;
710
    my ($notifyid,$borrowernumber)=@_;
711
    my $dbh = C4::Context->dbh;
712
    my $query=qq|    SELECT sum(amountoutstanding)
713
            FROM accountlines
714
            WHERE notify_id=? AND borrowernumber = ?|;
715
    my $sth=$dbh->prepare($query);
716
	$sth->execute($notifyid,$borrowernumber);
717
	my $totalnotify=$sth->fetchrow;
718
    $sth->finish;
719
    return ($totalnotify);
720
}
681
}
721
682
722
=head2 GetItems
683
=head2 GetItems
Lines 772-798 sub GetBranchcodesWithOverdueRules { Link Here
772
    return @$branchcodes;
733
    return @$branchcodes;
773
}
734
}
774
735
775
=head2 CheckItemNotify
776
777
Sql request to check if the document has alreday been notified
778
this function is not exported, only used with GetOverduesForBranch
779
780
=cut
781
782
sub CheckItemNotify {
783
    my ($notify_id,$notify_level,$itemnumber) = @_;
784
    my $dbh = C4::Context->dbh;
785
    my $sth = $dbh->prepare("
786
    SELECT COUNT(*)
787
     FROM notifys
788
    WHERE notify_id    = ?
789
     AND  notify_level = ? 
790
     AND  itemnumber   = ? ");
791
    $sth->execute($notify_id,$notify_level,$itemnumber);
792
    my $notified = $sth->fetchrow;
793
    return ($notified);
794
}
795
796
=head2 GetOverduesForBranch
736
=head2 GetOverduesForBranch
797
737
798
Sql request for display all information for branchoverdues.pl
738
Sql request for display all information for branchoverdues.pl
Lines 818-823 sub GetOverduesForBranch { Link Here
818
               biblio.title,
758
               biblio.title,
819
               biblio.author,
759
               biblio.author,
820
               biblio.biblionumber,
760
               biblio.biblionumber,
761
               issues.issue_id,
821
               issues.date_due,
762
               issues.date_due,
822
               issues.returndate,
763
               issues.returndate,
823
               issues.branchcode,
764
               issues.branchcode,
Lines 828-852 sub GetOverduesForBranch { Link Here
828
                items.location,
769
                items.location,
829
                items.itemnumber,
770
                items.itemnumber,
830
            itemtypes.description,
771
            itemtypes.description,
831
         accountlines.notify_id,
772
            account_debits.amount_outstanding
832
         accountlines.notify_level,
773
    FROM  account_debits
833
         accountlines.amountoutstanding
774
    LEFT JOIN issues      ON    issues.itemnumber     = account_debits.itemnumber
834
    FROM  accountlines
775
                          AND   issues.borrowernumber = account_debits.borrowernumber
835
    LEFT JOIN issues      ON    issues.itemnumber     = accountlines.itemnumber
776
    LEFT JOIN borrowers   ON borrowers.borrowernumber = account_debits.borrowernumber
836
                          AND   issues.borrowernumber = accountlines.borrowernumber
837
    LEFT JOIN borrowers   ON borrowers.borrowernumber = accountlines.borrowernumber
838
    LEFT JOIN items       ON     items.itemnumber     = issues.itemnumber
777
    LEFT JOIN items       ON     items.itemnumber     = issues.itemnumber
839
    LEFT JOIN biblio      ON      biblio.biblionumber =  items.biblionumber
778
    LEFT JOIN biblio      ON      biblio.biblionumber =  items.biblionumber
840
    LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
779
    LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
841
    LEFT JOIN itemtypes   ON itemtypes.itemtype       = $itype_link
780
    LEFT JOIN itemtypes   ON itemtypes.itemtype       = $itype_link
842
    LEFT JOIN branches    ON  branches.branchcode     = issues.branchcode
781
    LEFT JOIN branches    ON  branches.branchcode     = issues.branchcode
843
    WHERE (accountlines.amountoutstanding  != '0.000000')
782
    WHERE (account_debits.amount_outstanding  != '0.000000')
844
      AND (accountlines.accounttype         = 'FU'      )
783
      AND (account_debits.type = 'FINE')
784
      AND (account_debits.accruing = 1 )
845
      AND (issues.branchcode =  ?   )
785
      AND (issues.branchcode =  ?   )
846
      AND (issues.date_due  < NOW())
786
      AND (issues.date_due  < NOW())
847
    ";
787
    ";
848
    my @getoverdues;
788
    my @getoverdues;
849
    my $i = 0;
850
    my $sth;
789
    my $sth;
851
    if ($location) {
790
    if ($location) {
852
        $sth = $dbh->prepare("$select AND items.location = ? ORDER BY borrowers.surname, borrowers.firstname");
791
        $sth = $dbh->prepare("$select AND items.location = ? ORDER BY borrowers.surname, borrowers.firstname");
Lines 856-867 sub GetOverduesForBranch { Link Here
856
        $sth->execute($branch);
795
        $sth->execute($branch);
857
    }
796
    }
858
    while ( my $data = $sth->fetchrow_hashref ) {
797
    while ( my $data = $sth->fetchrow_hashref ) {
859
    #check if the document has already been notified
798
        push( @getoverdues, $data );
860
        my $countnotify = CheckItemNotify($data->{'notify_id'}, $data->{'notify_level'}, $data->{'itemnumber'});
861
        if ($countnotify eq '0') {
862
            $getoverdues[$i] = $data;
863
            $i++;
864
        }
865
    }
799
    }
866
    return (@getoverdues);
800
    return (@getoverdues);
867
}
801
}
(-)a/C4/Reports/Guided.pm (-1 / +1 lines)
Lines 100-106 sub get_table_areas { Link Here
100
    CAT  => [ 'items', 'biblioitems', 'biblio' ],
100
    CAT  => [ 'items', 'biblioitems', 'biblio' ],
101
    PAT  => ['borrowers'],
101
    PAT  => ['borrowers'],
102
    ACQ  => [ 'aqorders', 'biblio', 'items' ],
102
    ACQ  => [ 'aqorders', 'biblio', 'items' ],
103
    ACC  => [ 'borrowers', 'accountlines' ],
103
    ACC  => [ 'borrowers', 'account_credits', 'account_debits' ],
104
    SER  => [ 'serial', 'serialitems', 'subscription', 'subscriptionhistory', 'subscriptionroutinglist', 'biblioitems', 'biblio', 'aqbooksellers' ],
104
    SER  => [ 'serial', 'serialitems', 'subscription', 'subscriptionhistory', 'subscriptionroutinglist', 'biblioitems', 'biblio', 'aqbooksellers' ],
105
    );
105
    );
106
}
106
}
(-)a/C4/Reserves.pm (-13 / +10 lines)
Lines 28-34 use C4::Biblio; Link Here
28
use C4::Members;
28
use C4::Members;
29
use C4::Items;
29
use C4::Items;
30
use C4::Circulation;
30
use C4::Circulation;
31
use C4::Accounts;
32
31
33
# for _koha_notify_reserve
32
# for _koha_notify_reserve
34
use C4::Members::Messaging;
33
use C4::Members::Messaging;
Lines 179-197 sub AddReserve { Link Here
179
        $waitingdate = $resdate;
178
        $waitingdate = $resdate;
180
    }
179
    }
181
180
182
    #eval {
183
    # updates take place here
184
    if ( $fee > 0 ) {
181
    if ( $fee > 0 ) {
185
        my $nextacctno = &getnextacctno( $borrowernumber );
182
        AddDebit(
186
        my $query      = qq{
183
            {
187
        INSERT INTO accountlines
184
                borrowernumber => $borrowernumber,
188
            (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
185
                itemnumber     => $checkitem,
189
        VALUES
186
                amount         => $fee,
190
            (?,?,now(),?,?,'Res',?)
187
                type           => Koha::Accounts::DebitTypes::Hold(),
191
    };
188
                description    => $title,
192
        my $usth = $dbh->prepare($query);
189
                notes          => "Record ID: $biblionumber",
193
        $usth->execute( $borrowernumber, $nextacctno, $fee,
190
            }
194
            "Reserve Charge - $title", $fee );
191
        );
195
    }
192
    }
196
193
197
    #if ($const eq 'a'){
194
    #if ($const eq 'a'){
(-)a/C4/SIP/ILS/Patron.pm (-1 / +2 lines)
Lines 87-93 sub new { Link Here
87
        hold_ok         => ( !$debarred && !$expired && !$fine_blocked),
87
        hold_ok         => ( !$debarred && !$expired && !$fine_blocked),
88
        card_lost       => ( $kp->{lost} || $kp->{gonenoaddress} || $flags->{LOST} ),
88
        card_lost       => ( $kp->{lost} || $kp->{gonenoaddress} || $flags->{LOST} ),
89
        claims_returned => 0,
89
        claims_returned => 0,
90
        fines           => $fines_amount, # GetMemberAccountRecords($kp->{borrowernumber})
90
        fines           => $fines_amount,
91
        fees            => 0,             # currently not distinct from fines
91
        fees            => 0,             # currently not distinct from fines
92
        recall_overdue  => 0,
92
        recall_overdue  => 0,
93
        items_billed    => 0,
93
        items_billed    => 0,
Lines 102-107 sub new { Link Here
102
        inet            => ( !$debarred && !$expired ),
102
        inet            => ( !$debarred && !$expired ),
103
        expired         => $expired,
103
        expired         => $expired,
104
        fee_limit       => $fee_limit,
104
        fee_limit       => $fee_limit,
105
        account_balance => $kp->{account_balance},
105
    );
106
    );
106
    }
107
    }
107
    $debug and warn "patron fines: $ilspatron{fines} ... amountoutstanding: $kp->{amountoutstanding} ... CHARGES->amount: $flags->{CHARGES}->{amount}";
108
    $debug and warn "patron fines: $ilspatron{fines} ... amountoutstanding: $kp->{amountoutstanding} ... CHARGES->amount: $flags->{CHARGES}->{amount}";
(-)a/C4/SIP/ILS/Transaction/FeePayment.pm (-4 / +16 lines)
Lines 20-26 use strict; Link Here
20
# You should have received a copy of the GNU General Public License
20
# You should have received a copy of the GNU General Public License
21
# along with Koha; if not, see <http://www.gnu.org/licenses>.
21
# along with Koha; if not, see <http://www.gnu.org/licenses>.
22
22
23
use C4::Accounts qw(recordpayment);
23
use Koha::Accounts qw(AddCredit);
24
use Koha::Accounts::CreditTypes;
25
use Koha::Database;
26
use C4::SIP::ILS;
24
use parent qw(C4::SIP::ILS::Transaction);
27
use parent qw(C4::SIP::ILS::Transaction);
25
28
26
29
Lines 44-53 sub new { Link Here
44
sub pay {
47
sub pay {
45
    my $self           = shift;
48
    my $self           = shift;
46
    my $borrowernumber = shift;
49
    my $borrowernumber = shift;
47
    my $amt            = shift;
50
    my $amount         = shift;
48
    my $type           = shift;
51
    my $type           = shift;
49
    warn("RECORD:$borrowernumber::$amt");
52
50
    recordpayment( $borrowernumber, $amt,$type );
53
    warn("RECORD:$borrowernumber::$amount");
54
55
    AddCredit(
56
        {
57
            borrower => Koha::Database->new()->schema->resultset('Borrower')->find($borrowernumber),
58
            amount => $amount,
59
            notes  => "via SIP2. Type:$type",
60
            type   => Koha::Accounts::CreditTypes::Payment,
61
        }
62
    );
51
}
63
}
52
64
53
#sub DESTROY {
65
#sub DESTROY {
(-)a/C4/SIP/ILS/Transaction/Renew.pm (+8 lines)
Lines 33-38 sub do_renew_for { Link Here
33
    my $self = shift;
33
    my $self = shift;
34
    my $borrower = shift;
34
    my $borrower = shift;
35
    my ($renewokay,$renewerror) = CanBookBeRenewed($borrower->{borrowernumber},$self->{item}->{itemnumber});
35
    my ($renewokay,$renewerror) = CanBookBeRenewed($borrower->{borrowernumber},$self->{item}->{itemnumber});
36
36
    if ($renewokay) { # ok so far check charges
37
    if ($renewokay) { # ok so far check charges
37
        my ($fee, undef) = GetIssuingCharges($self->{item}->{itemnumber}, $self->{patron}->{borrowernumber});
38
        my ($fee, undef) = GetIssuingCharges($self->{item}->{itemnumber}, $self->{patron}->{borrowernumber});
38
        if ($fee > 0) {
39
        if ($fee > 0) {
Lines 42-49 sub do_renew_for { Link Here
42
                $renewokay = 0;
43
                $renewokay = 0;
43
            }
44
            }
44
        }
45
        }
46
    }
45
47
48
    if ($renewokay) { # ok so far check if patron owes to much money
49
        unless ( $borrower->{account_balance} < C4::Context->preference('OPACFineNoRenewals') ) {
50
            $renewokay = 0;
51
            $renewerror = 'too_many_fines'
52
        }
46
    }
53
    }
54
47
    if ($renewokay){
55
    if ($renewokay){
48
        $self->{due} = undef;
56
        $self->{due} = undef;
49
        my $issue = AddIssue( $borrower, $self->{item}->id, undef, 0 );
57
        my $issue = AddIssue( $borrower, $self->{item}->id, undef, 0 );
(-)a/Koha/DateUtils.pm (-1 / +7 lines)
Lines 20-32 use strict; Link Here
20
use warnings;
20
use warnings;
21
use 5.010;
21
use 5.010;
22
use DateTime;
22
use DateTime;
23
use DateTime::Format::DateParse;
24
use DateTime::Format::MySQL;
23
use C4::Context;
25
use C4::Context;
24
26
25
use base 'Exporter';
27
use base 'Exporter';
26
use version; our $VERSION = qv('1.0.0');
28
use version; our $VERSION = qv('1.0.0');
27
29
28
our @EXPORT = (
30
our @EXPORT = (
29
    qw( dt_from_string output_pref format_sqldatetime )
31
    qw( dt_from_string output_pref format_sqldatetime get_timestamp )
30
);
32
);
31
33
32
=head1 DateUtils
34
=head1 DateUtils
Lines 273-276 sub format_sqldatetime { Link Here
273
    return q{};
275
    return q{};
274
}
276
}
275
277
278
sub get_timestamp {
279
    return DateTime::Format::MySQL->format_datetime( dt_from_string() );
280
}
281
276
1;
282
1;
(-)a/Koha/Template/Plugin/AuthorisedValues.pm (+2 lines)
Lines 77-79 Kyle M Hall <kyle@bywatersolutions.com> Link Here
77
Jonathan Druart <jonathan.druart@biblibre.com>
77
Jonathan Druart <jonathan.druart@biblibre.com>
78
78
79
=cut
79
=cut
80
81
1;
(-)a/Koha/Template/Plugin/Koha.pm (-1 / +5 lines)
Lines 60-63 sub Version { Link Here
60
    };
60
    };
61
}
61
}
62
62
63
sub Get {
64
    my ( $self, $category, $selected, $opac ) = @_;
65
    return GetAuthorisedValues( $category, $selected, $opac );
66
}
67
63
1;
68
1;
64
- 

Return to bug 6427