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

(-)a/C4/Circulation.pm (-179 / +167 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 C4::ItemCirculationAlertPreference;
34
use C4::ItemCirculationAlertPreference;
35
use C4::Message;
35
use C4::Message;
36
use C4::Debug;
36
use C4::Debug;
Lines 48-53 use Data::Dumper; Link Here
48
use Koha::DateUtils;
48
use Koha::DateUtils;
49
use Koha::Calendar;
49
use Koha::Calendar;
50
use Koha::Borrower::Debarments;
50
use Koha::Borrower::Debarments;
51
use Koha::Database;
51
use Carp;
52
use Carp;
52
use Date::Calc qw(
53
use Date::Calc qw(
53
  Today
54
  Today
Lines 1273-1279 sub AddIssue { Link Here
1273
        ## If item was lost, it has now been found, reverse any list item charges if neccessary.
1274
        ## If item was lost, it has now been found, reverse any list item charges if neccessary.
1274
        if ( $item->{'itemlost'} ) {
1275
        if ( $item->{'itemlost'} ) {
1275
            if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) {
1276
            if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) {
1276
                _FixAccountForLostAndReturned( $item->{'itemnumber'}, undef, $item->{'barcode'} );
1277
                _FixAccountForLostAndReturned( $item->{'itemnumber'} );
1277
            }
1278
            }
1278
        }
1279
        }
1279
1280
Lines 1814-1834 sub AddReturn { Link Here
1814
1815
1815
                $type ||= q{};
1816
                $type ||= q{};
1816
1817
1817
                if ( C4::Context->preference('finesMode') eq 'production' ) {
1818
                if ( $amount > 0
1818
                    if ( $amount > 0 ) {
1819
                    && C4::Context->preference('finesMode') eq 'production' )
1819
                        C4::Overdues::UpdateFine( $issue->{itemnumber},
1820
                {
1820
                            $issue->{borrowernumber},
1821
                    C4::Overdues::UpdateFine(
1821
                            $amount, $type, output_pref($datedue) );
1822
                        {
1822
                    }
1823
                            itemnumber     => $issue->{itemnumber},
1823
                    elsif ($return_date) {
1824
                            borrowernumber => $issue->{borrowernumber},
1824
1825
                            amount         => $amount,
1825
                       # Backdated returns may have fines that shouldn't exist,
1826
                            due            => output_pref($datedue),
1826
                       # so in this case, we need to drop those fines to 0
1827
                            issue_id       => $issue->{issue_id}
1827
1828
                        }
1828
                        C4::Overdues::UpdateFine( $issue->{itemnumber},
1829
                    );
1829
                            $issue->{borrowernumber},
1830
                }
1830
                            0, $type, output_pref($datedue) );
1831
                elsif ($return_date) {
1831
                    }
1832
1833
                    # Backdated returns may have fines that shouldn't exist,
1834
                    # so in this case, we need to drop those fines to 0
1835
                    C4::Overdues::UpdateFine(
1836
                        {
1837
                            itemnumber     => $issue->{itemnumber},
1838
                            borrowernumber => $issue->{borrowernumber},
1839
                            amount         => 0,
1840
                            due            => output_pref($datedue),
1841
                            issue_id       => $issue->{issue_id}
1842
                        }
1843
                    );
1832
                }
1844
                }
1833
            }
1845
            }
1834
1846
Lines 1878-1892 sub AddReturn { Link Here
1878
        $messages->{'WasLost'} = 1;
1890
        $messages->{'WasLost'} = 1;
1879
1891
1880
        if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) {
1892
        if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) {
1881
            _FixAccountForLostAndReturned($item->{'itemnumber'}, $borrowernumber, $barcode);    # can tolerate undef $borrowernumber
1893
            _FixAccountForLostAndReturned( $item->{'itemnumber'} );
1882
            $messages->{'LostItemFeeRefunded'} = 1;
1894
            $messages->{'LostItemFeeRefunded'} = 1;
1883
        }
1895
        }
1884
    }
1896
    }
1885
1897
1886
    # fix up the overdues in accounts...
1898
    # fix up the overdues in accounts...
1887
    if ($borrowernumber) {
1899
    if ($borrowernumber) {
1888
        my $fix = _FixOverduesOnReturn($borrowernumber, $item->{itemnumber}, $exemptfine, $dropbox);
1900
        _FixOverduesOnReturn(
1889
        defined($fix) or warn "_FixOverduesOnReturn($borrowernumber, $item->{itemnumber}...) failed!";  # zero is OK, check defined
1901
            {
1902
                exempt_fine => $exemptfine,
1903
                dropbox     => $dropbox,
1904
                issue       => $issue,
1905
            }
1906
        );
1890
        
1907
        
1891
        if ( $issue->{overdue} && $issue->{date_due} ) {
1908
        if ( $issue->{overdue} && $issue->{date_due} ) {
1892
        # fix fine days
1909
        # fix fine days
Lines 2121-2259 Internal function, called only by AddReturn Link Here
2121
=cut
2138
=cut
2122
2139
2123
sub _FixOverduesOnReturn {
2140
sub _FixOverduesOnReturn {
2124
    my ($borrowernumber, $item);
2141
    my ( $params ) = @_;
2125
    unless ($borrowernumber = shift) {
2142
2126
        warn "_FixOverduesOnReturn() not supplied valid borrowernumber";
2143
    my $exemptfine = $params->{exempt_fine};
2127
        return;
2144
    my $dropbox    = $params->{dropbox};
2128
    }
2145
    my $issue      = $params->{issue};
2129
    unless ($item = shift) {
2146
2130
        warn "_FixOverduesOnReturn() not supplied valid itemnumber";
2131
        return;
2132
    }
2133
    my ($exemptfine, $dropbox) = @_;
2134
    my $dbh = C4::Context->dbh;
2147
    my $dbh = C4::Context->dbh;
2135
2148
2136
    # check for overdue fine
2149
    my $schema = Koha::Database->new()->schema;
2137
    my $sth = $dbh->prepare(
2150
    my $fine =
2138
"SELECT * FROM accountlines WHERE (borrowernumber = ?) AND (itemnumber = ?) AND (accounttype='FU' OR accounttype='O')"
2151
      $schema->resultset('AccountDebit')
2139
    );
2152
      ->single( { issue_id => $issue->{issue_id}, type => Koha::Accounts::DebitTypes::Fine() } );
2140
    $sth->execute( $borrowernumber, $item );
2141
2153
2142
    # alter fine to show that the book has been returned
2154
    return unless ( $fine );
2143
    my $data = $sth->fetchrow_hashref;
2155
2144
    return 0 unless $data;    # no warning, there's just nothing to fix
2156
    $fine->accruing(0);
2145
2157
2146
    my $uquery;
2147
    my @bind = ($data->{'accountlines_id'});
2148
    if ($exemptfine) {
2158
    if ($exemptfine) {
2149
        $uquery = "update accountlines set accounttype='FFOR', amountoutstanding=0";
2159
        AddCredit(
2150
        if (C4::Context->preference("FinesLog")) {
2160
            {
2151
            &logaction("FINES", 'MODIFY',$borrowernumber,"Overdue forgiven: item $item");
2161
                borrower => $fine->borrowernumber(),
2152
        }
2162
                amount   => $fine->amount_original(),
2153
    } elsif ($dropbox && $data->{lastincrement}) {
2163
                debit_id => $fine->debit_id(),
2154
        my $outstanding = $data->{amountoutstanding} - $data->{lastincrement} ;
2164
                type     => Koha::Accounts::CreditTypes::Forgiven(),
2155
        my $amt = $data->{amount} - $data->{lastincrement} ;
2165
            }
2166
        );
2156
        if (C4::Context->preference("FinesLog")) {
2167
        if (C4::Context->preference("FinesLog")) {
2157
            &logaction("FINES", 'MODIFY',$borrowernumber,"Dropbox adjustment $amt, item $item");
2168
            &logaction(
2158
        }
2169
                "FINES", 'MODIFY',
2159
         $uquery = "update accountlines set accounttype='F' ";
2170
                $issue->{borrowernumber},
2160
         if($outstanding  >= 0 && $amt >=0) {
2171
                "Overdue forgiven: item " . $issue->{itemnumber}
2161
            $uquery .= ", amount = ? , amountoutstanding=? ";
2172
            );
2162
            unshift @bind, ($amt, $outstanding) ;
2163
        }
2173
        }
2164
    } else {
2174
    } elsif ($dropbox && $fine->amount_last_increment() != $fine->amount_original() ) {
2165
        $uquery = "update accountlines set accounttype='F' ";
2175
        if ( C4::Context->preference("FinesLog") ) {
2176
            &logaction( "FINES", 'MODIFY', $issue->{borrowernumber},
2177
                    "Dropbox adjustment "
2178
                  . $fine->amount_last_increment()
2179
                  . ", item " . $issue->{itemnumber} );
2180
        }
2181
        $fine->amount_original(
2182
            $fine->amount_original() - $fine->amount_last_increment() );
2183
        $fine->amount_outstanding(
2184
            $fine->amount_outstanding - $fine->amount_last_increment() );
2185
        $schema->resultset('AccountOffset')->create(
2186
            {
2187
                debit_id => $fine->debit_id(),
2188
                type     => Koha::Accounts::OffsetTypes::Dropbox(),
2189
                amount   => $fine->amount_last_increment() * -1,
2190
            }
2191
        );
2166
    }
2192
    }
2167
    $uquery .= " where (accountlines_id = ?)";
2193
2168
    my $usth = $dbh->prepare($uquery);
2194
    return $fine->update();
2169
    return $usth->execute(@bind);
2170
}
2195
}
2171
2196
2172
=head2 _FixAccountForLostAndReturned
2197
=head2 _FixAccountForLostAndReturned
2173
2198
2174
  &_FixAccountForLostAndReturned($itemnumber, [$borrowernumber, $barcode]);
2199
  &_FixAccountForLostAndReturned($itemnumber);
2175
2200
2176
Calculates the charge for a book lost and returned.
2201
  Refunds a lost item fee in necessary
2177
2178
Internal function, not exported, called only by AddReturn.
2179
2180
FIXME: This function reflects how inscrutable fines logic is.  Fix both.
2181
FIXME: Give a positive return value on success.  It might be the $borrowernumber who received credit, or the amount forgiven.
2182
2202
2183
=cut
2203
=cut
2184
2204
2185
sub _FixAccountForLostAndReturned {
2205
sub _FixAccountForLostAndReturned {
2186
    my $itemnumber     = shift or return;
2206
    my ( $itemnumber ) = @_;
2187
    my $borrowernumber = @_ ? shift : undef;
2207
2188
    my $item_id        = @_ ? shift : $itemnumber;  # Send the barcode if you want that logged in the description
2208
    my $schema = Koha::Database->new()->schema;
2189
    my $dbh = C4::Context->dbh;
2209
2190
    # check for charge made for lost book
2210
    # Find the last issue for this item
2191
    my $sth = $dbh->prepare("SELECT * FROM accountlines WHERE itemnumber = ? AND accounttype IN ('L', 'Rep', 'W') ORDER BY date DESC, accountno DESC");
2211
    my $issue =
2192
    $sth->execute($itemnumber);
2212
      $schema->resultset('Issue')->single( { itemnumber => $itemnumber } );
2193
    my $data = $sth->fetchrow_hashref;
2213
    $issue ||=
2194
    $data or return;    # bail if there is nothing to do
2214
      $schema->resultset('OldIssue')->single( { itemnumber => $itemnumber } );
2195
    $data->{accounttype} eq 'W' and return;    # Written off
2215
2196
2216
    return unless $issue;
2197
    # writeoff this amount
2217
2198
    my $offset;
2218
    # Find a lost fee for this issue
2199
    my $amount = $data->{'amount'};
2219
    my $debit = $schema->resultset('AccountDebit')->single(
2200
    my $acctno = $data->{'accountno'};
2220
        {
2201
    my $amountleft;                                             # Starts off undef/zero.
2221
            issue_id => $issue->issue_id(),
2202
    if ($data->{'amountoutstanding'} == $amount) {
2222
            type     => Koha::Accounts::DebitTypes::Lost()
2203
        $offset     = $data->{'amount'};
2223
        }
2204
        $amountleft = 0;                                        # Hey, it's zero here, too.
2224
    );
2205
    } else {
2225
2206
        $offset     = $amount - $data->{'amountoutstanding'};   # Um, isn't this the same as ZERO?  We just tested those two things are ==
2226
    return unless $debit;
2207
        $amountleft = $data->{'amountoutstanding'} - $amount;   # Um, isn't this the same as ZERO?  We just tested those two things are ==
2227
2208
    }
2228
    # Check for an existing found credit for this debit, if there is one, the fee has already been refunded and we do nothing
2209
    my $usth = $dbh->prepare("UPDATE accountlines SET accounttype = 'LR',amountoutstanding='0'
2229
    my @credits = $debit->account_offsets->search_related('credit', { 'credit.type' => Koha::Accounts::CreditTypes::Found() });
2210
        WHERE (accountlines_id = ?)");
2230
2211
    $usth->execute($data->{'accountlines_id'});      # We might be adjusting an account for some OTHER borrowernumber now.  Not the one we passed in.
2231
    return if @credits;
2212
    #check if any credit is left if so writeoff other accounts
2232
2213
    my $nextaccntno = getnextacctno($data->{'borrowernumber'});
2233
    # Ok, so we know we have an unrefunded lost item fee, let's refund it
2214
    $amountleft *= -1 if ($amountleft < 0);
2234
    CreditLostItem(
2215
    if ($amountleft > 0) {
2235
        {
2216
        my $msth = $dbh->prepare("SELECT * FROM accountlines WHERE (borrowernumber = ?)
2236
            borrower => $issue->borrower(),
2217
                            AND (amountoutstanding >0) ORDER BY date");     # might want to order by amountoustanding ASC (pay smallest first)
2237
            debit    => $debit
2218
        $msth->execute($data->{'borrowernumber'});
2238
        }
2219
        # offset transactions
2239
    );
2220
        my $newamtos;
2240
2221
        my $accdata;
2222
        while (($accdata=$msth->fetchrow_hashref) and ($amountleft>0)){
2223
            if ($accdata->{'amountoutstanding'} < $amountleft) {
2224
                $newamtos = 0;
2225
                $amountleft -= $accdata->{'amountoutstanding'};
2226
            }  else {
2227
                $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
2228
                $amountleft = 0;
2229
            }
2230
            my $thisacct = $accdata->{'accountlines_id'};
2231
            # FIXME: move prepares outside while loop!
2232
            my $usth = $dbh->prepare("UPDATE accountlines SET amountoutstanding= ?
2233
                    WHERE (accountlines_id = ?)");
2234
            $usth->execute($newamtos,$thisacct);
2235
            $usth = $dbh->prepare("INSERT INTO accountoffsets
2236
                (borrowernumber, accountno, offsetaccount,  offsetamount)
2237
                VALUES
2238
                (?,?,?,?)");
2239
            $usth->execute($data->{'borrowernumber'},$accdata->{'accountno'},$nextaccntno,$newamtos);
2240
        }
2241
    }
2242
    $amountleft *= -1 if ($amountleft > 0);
2243
    my $desc = "Item Returned " . $item_id;
2244
    $usth = $dbh->prepare("INSERT INTO accountlines
2245
        (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
2246
        VALUES (?,?,now(),?,?,'CR',?)");
2247
    $usth->execute($data->{'borrowernumber'},$nextaccntno,0-$amount,$desc,$amountleft);
2248
    if ($borrowernumber) {
2249
        # FIXME: same as query above.  use 1 sth for both
2250
        $usth = $dbh->prepare("INSERT INTO accountoffsets
2251
            (borrowernumber, accountno, offsetaccount,  offsetamount)
2252
            VALUES (?,?,?,?)");
2253
        $usth->execute($borrowernumber, $data->{'accountno'}, $nextaccntno, $offset);
2254
    }
2255
    ModItem({ paidfor => '' }, undef, $itemnumber);
2241
    ModItem({ paidfor => '' }, undef, $itemnumber);
2256
    return;
2257
}
2242
}
2258
2243
2259
=head2 _GetCircControlBranch
2244
=head2 _GetCircControlBranch
Lines 2697-2715 sub AddRenewal { Link Here
2697
    # Charge a new rental fee, if applicable?
2682
    # Charge a new rental fee, if applicable?
2698
    my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber );
2683
    my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber );
2699
    if ( $charge > 0 ) {
2684
    if ( $charge > 0 ) {
2700
        my $accountno = getnextacctno( $borrowernumber );
2701
        my $item = GetBiblioFromItemNumber($itemnumber);
2685
        my $item = GetBiblioFromItemNumber($itemnumber);
2702
        my $manager_id = 0;
2686
2703
        $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; 
2687
        my $borrower =
2704
        $sth = $dbh->prepare(
2688
          Koha::Database->new()->schema->resultset('Borrower')
2705
                "INSERT INTO accountlines
2689
          ->find($borrowernumber);
2706
                    (date, borrowernumber, accountno, amount, manager_id,
2690
2707
                    description,accounttype, amountoutstanding, itemnumber)
2691
        AddDebit(
2708
                    VALUES (now(),?,?,?,?,?,?,?,?)"
2692
            {
2693
                borrower   => $borrower,
2694
                itemnumber => $itemnumber,
2695
                amount     => $charge,
2696
                type       => Koha::Accounts::DebitTypes::Rental(),
2697
                description =>
2698
                  "Renewal of Rental Item $item->{'title'} $item->{'barcode'}"
2699
            }
2709
        );
2700
        );
2710
        $sth->execute( $borrowernumber, $accountno, $charge, $manager_id,
2711
            "Renewal of Rental Item $item->{'title'} $item->{'barcode'}",
2712
            'Rent', $charge, $itemnumber );
2713
    }
2701
    }
2714
2702
2715
    # Send a renewal slip according to checkout alert preferencei
2703
    # Send a renewal slip according to checkout alert preferencei
Lines 2928-2952 sub _get_discount_from_rule { Link Here
2928
2916
2929
=head2 AddIssuingCharge
2917
=head2 AddIssuingCharge
2930
2918
2931
  &AddIssuingCharge( $itemno, $borrowernumber, $charge )
2919
  &AddIssuingCharge( $itemnumber, $borrowernumber, $amount )
2932
2920
2933
=cut
2921
=cut
2934
2922
2935
sub AddIssuingCharge {
2923
sub AddIssuingCharge {
2936
    my ( $itemnumber, $borrowernumber, $charge ) = @_;
2924
    my ( $itemnumber, $borrowernumber, $amount ) = @_;
2937
    my $dbh = C4::Context->dbh;
2925
2938
    my $nextaccntno = getnextacctno( $borrowernumber );
2926
    return AddDebit(
2939
    my $manager_id = 0;
2927
        {
2940
    $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
2928
            borrower       => Koha::Database->new()->schema->resultset('Borrower')->find($borrowernumber),
2941
    my $query ="
2929
            itemnumber     => $itemnumber,
2942
        INSERT INTO accountlines
2930
            amount         => $amount,
2943
            (borrowernumber, itemnumber, accountno,
2931
            type           => Koha::Accounts::DebitTypes::Rental(),
2944
            date, amount, description, accounttype,
2932
        }
2945
            amountoutstanding, manager_id)
2933
    );
2946
        VALUES (?, ?, ?,now(), ?, 'Rental', 'Rent',?,?)
2947
    ";
2948
    my $sth = $dbh->prepare($query);
2949
    $sth->execute( $borrowernumber, $itemnumber, $nextaccntno, $charge, $charge, $manager_id );
2950
}
2934
}
2951
2935
2952
=head2 GetTransfers
2936
=head2 GetTransfers
Lines 3465-3494 sub ReturnLostItem{ Link Here
3465
sub LostItem{
3449
sub LostItem{
3466
    my ($itemnumber, $mark_returned) = @_;
3450
    my ($itemnumber, $mark_returned) = @_;
3467
3451
3468
    my $dbh = C4::Context->dbh();
3452
    my $schema = Koha::Database->new()->schema;
3469
    my $sth=$dbh->prepare("SELECT issues.*,items.*,biblio.title 
3470
                           FROM issues 
3471
                           JOIN items USING (itemnumber) 
3472
                           JOIN biblio USING (biblionumber)
3473
                           WHERE issues.itemnumber=?");
3474
    $sth->execute($itemnumber);
3475
    my $issues=$sth->fetchrow_hashref();
3476
3453
3477
    # If a borrower lost the item, add a replacement cost to the their record
3454
    my $issue =
3478
    if ( my $borrowernumber = $issues->{borrowernumber} ){
3455
      $schema->resultset('Issue')->single( { itemnumber => $itemnumber } );
3479
        my $borrower = C4::Members::GetMemberDetails( $borrowernumber );
3456
3457
    my ( $borrower, $item );
3458
3459
    if ( $issue ) {
3460
        $borrower = $issue->borrower();
3461
        $item     = $issue->item();
3462
    }
3480
3463
3464
    # If a borrower lost the item, add a replacement cost to the their record
3465
    if ( $borrower ){
3481
        if (C4::Context->preference('WhenLostForgiveFine')){
3466
        if (C4::Context->preference('WhenLostForgiveFine')){
3482
            my $fix = _FixOverduesOnReturn($borrowernumber, $itemnumber, 1, 0); # 1, 0 = exemptfine, no-dropbox
3467
            _FixOverduesOnReturn(
3483
            defined($fix) or warn "_FixOverduesOnReturn($borrowernumber, $itemnumber...) failed!";  # zero is OK, check defined
3468
                {
3469
                    exempt_fine => 1,
3470
                    dropbox     => 0,
3471
                    issue       => $issue,
3472
                }
3473
            );
3484
        }
3474
        }
3485
        if (C4::Context->preference('WhenLostChargeReplacementFee')){
3475
        if ( C4::Context->preference('WhenLostChargeReplacementFee') ) {
3486
            C4::Accounts::chargelostitem($borrowernumber, $itemnumber, $issues->{'replacementprice'}, "Lost Item $issues->{'title'} $issues->{'barcode'}");
3476
            DebitLostItem( { borrower => $borrower, issue => $issue } );
3487
            #FIXME : Should probably have a way to distinguish this from an item that really was returned.
3488
            #warn " $issues->{'borrowernumber'}  /  $itemnumber ";
3489
        }
3477
        }
3490
3478
3491
        MarkIssueReturned($borrowernumber,$itemnumber,undef,undef,$borrower->{'privacy'}) if $mark_returned;
3479
        MarkIssueReturned( $borrower->borrowernumber(), $item->itemnumber(), undef, undef, $borrower->privacy() ) if $mark_returned;
3492
    }
3480
    }
3493
}
3481
}
3494
3482
(-)a/C4/Members.pm (-115 / +38 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::SQLHelper qw(InsertInTable UpdateInTable SearchInTable);
34
use C4::SQLHelper qw(InsertInTable UpdateInTable SearchInTable);
Lines 41-46 use Koha::DateUtils; Link Here
41
use Koha::Borrower::Debarments qw(IsDebarred);
40
use Koha::Borrower::Debarments qw(IsDebarred);
42
use Text::Unaccent qw( unac_string );
41
use Text::Unaccent qw( unac_string );
43
use Koha::AuthUtils qw(hash_password);
42
use Koha::AuthUtils qw(hash_password);
43
use Koha::Accounts::DebitTypes;
44
44
45
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug);
45
our ($VERSION,@ISA,@EXPORT,@EXPORT_OK,$debug);
46
46
Lines 80-87 BEGIN { Link Here
80
        &GetHideLostItemsPreference
80
        &GetHideLostItemsPreference
81
81
82
        &IsMemberBlocked
82
        &IsMemberBlocked
83
        &GetMemberAccountRecords
84
        &GetBorNotifyAcctRecord
85
83
86
        &GetborCatFromCatType
84
        &GetborCatFromCatType
87
        &GetBorrowercategory
85
        &GetBorrowercategory
Lines 461-483 The "message" field that comes from the DB is OK. Link Here
461
# FIXME rename this function.
459
# FIXME rename this function.
462
sub patronflags {
460
sub patronflags {
463
    my %flags;
461
    my %flags;
464
    my ( $patroninformation) = @_;
462
    my ($patroninformation) = @_;
465
    my $dbh=C4::Context->dbh;
463
    my $dbh = C4::Context->dbh;
466
    my ($balance, $owing) = GetMemberAccountBalance( $patroninformation->{'borrowernumber'});
464
    if ( $patroninformation->{account_balance} > 0 ) {
467
    if ( $owing > 0 ) {
468
        my %flaginfo;
465
        my %flaginfo;
469
        my $noissuescharge = C4::Context->preference("noissuescharge") || 5;
466
        my $noissuescharge = C4::Context->preference("noissuescharge") || 5;
470
        $flaginfo{'message'} = sprintf 'Patron owes %.02f', $owing;
467
        $flaginfo{'amount'}  = $patroninformation->{account_balance};
471
        $flaginfo{'amount'}  = sprintf "%.02f", $owing;
468
        if (  $patroninformation->{account_balance} > $noissuescharge && !C4::Context->preference("AllowFineOverride") ) {
472
        if ( $owing > $noissuescharge && !C4::Context->preference("AllowFineOverride") ) {
473
            $flaginfo{'noissues'} = 1;
469
            $flaginfo{'noissues'} = 1;
474
        }
470
        }
475
        $flags{'CHARGES'} = \%flaginfo;
471
        $flags{'CHARGES'} = \%flaginfo;
476
    }
472
    }
477
    elsif ( $balance < 0 ) {
473
    elsif ( $patroninformation->{account_balance} < 0 ) {
478
        my %flaginfo;
474
        my %flaginfo;
479
        $flaginfo{'message'} = sprintf 'Patron has credit of %.02f', -$balance;
475
        $flaginfo{'amount'}  = $patroninformation->{account_balance};
480
        $flaginfo{'amount'}  = sprintf "%.02f", $balance;
481
        $flags{'CREDITS'} = \%flaginfo;
476
        $flags{'CREDITS'} = \%flaginfo;
482
    }
477
    }
483
    if (   $patroninformation->{'gonenoaddress'}
478
    if (   $patroninformation->{'gonenoaddress'}
Lines 720-726 sub GetMemberIssuesAndFines { Link Here
720
    $sth->execute($borrowernumber);
715
    $sth->execute($borrowernumber);
721
    my $overdue_count = $sth->fetchrow_arrayref->[0];
716
    my $overdue_count = $sth->fetchrow_arrayref->[0];
722
717
723
    $sth = $dbh->prepare("SELECT SUM(amountoutstanding) FROM accountlines WHERE borrowernumber = ?");
718
    $sth = $dbh->prepare("SELECT account_balance FROM borrowers WHERE borrowernumber = ?");
724
    $sth->execute($borrowernumber);
719
    $sth->execute($borrowernumber);
725
    my $total_fines = $sth->fetchrow_arrayref->[0];
720
    my $total_fines = $sth->fetchrow_arrayref->[0];
726
721
Lines 1196-1252 sub GetAllIssues { Link Here
1196
}
1191
}
1197
1192
1198
1193
1199
=head2 GetMemberAccountRecords
1200
1201
  ($total, $acctlines, $count) = &GetMemberAccountRecords($borrowernumber);
1202
1203
Looks up accounting data for the patron with the given borrowernumber.
1204
1205
C<&GetMemberAccountRecords> returns a three-element array. C<$acctlines> is a
1206
reference-to-array, where each element is a reference-to-hash; the
1207
keys are the fields of the C<accountlines> table in the Koha database.
1208
C<$count> is the number of elements in C<$acctlines>. C<$total> is the
1209
total amount outstanding for all of the account lines.
1210
1211
=cut
1212
1213
sub GetMemberAccountRecords {
1214
    my ($borrowernumber) = @_;
1215
    my $dbh = C4::Context->dbh;
1216
    my @acctlines;
1217
    my $numlines = 0;
1218
    my $strsth      = qq(
1219
                        SELECT * 
1220
                        FROM accountlines 
1221
                        WHERE borrowernumber=?);
1222
    $strsth.=" ORDER BY date desc,timestamp DESC";
1223
    my $sth= $dbh->prepare( $strsth );
1224
    $sth->execute( $borrowernumber );
1225
1226
    my $total = 0;
1227
    while ( my $data = $sth->fetchrow_hashref ) {
1228
        if ( $data->{itemnumber} ) {
1229
            my $biblio = GetBiblioFromItemNumber( $data->{itemnumber} );
1230
            $data->{biblionumber} = $biblio->{biblionumber};
1231
            $data->{title}        = $biblio->{title};
1232
        }
1233
        $acctlines[$numlines] = $data;
1234
        $numlines++;
1235
        $total += int(1000 * $data->{'amountoutstanding'}); # convert float to integer to avoid round-off errors
1236
    }
1237
    $total /= 1000;
1238
    return ( $total, \@acctlines,$numlines);
1239
}
1240
1241
=head2 GetMemberAccountBalance
1194
=head2 GetMemberAccountBalance
1242
1195
1243
  ($total_balance, $non_issue_balance, $other_charges) = &GetMemberAccountBalance($borrowernumber);
1196
  ($total_balance, $non_issue_balance, $other_charges) = &GetMemberAccountBalance($borrowernumber);
1244
1197
1245
Calculates amount immediately owing by the patron - non-issue charges.
1198
Calculates amount immediately owing by the patron - non-issue charges.
1246
Based on GetMemberAccountRecords.
1247
Charges exempt from non-issue are:
1199
Charges exempt from non-issue are:
1248
* Res (reserves)
1200
* HOLD fees (reserves)
1249
* Rent (rental) if RentalsInNoissuesCharge syspref is set to false
1201
* RENTAL if RentalsInNoissuesCharge syspref is set to false
1250
* Manual invoices if ManInvInNoissuesCharge syspref is set to false
1202
* Manual invoices if ManInvInNoissuesCharge syspref is set to false
1251
1203
1252
=cut
1204
=cut
Lines 1254-1323 Charges exempt from non-issue are: Link Here
1254
sub GetMemberAccountBalance {
1206
sub GetMemberAccountBalance {
1255
    my ($borrowernumber) = @_;
1207
    my ($borrowernumber) = @_;
1256
1208
1257
    my $ACCOUNT_TYPE_LENGTH = 5; # this is plain ridiculous...
1209
    my $borrower =
1210
      Koha::Database->new()->schema->resultset('Borrower')
1211
      ->find($borrowernumber);
1258
1212
1259
    my @not_fines = ('Res');
1213
    my @not_fines;
1260
    push @not_fines, 'Rent' unless C4::Context->preference('RentalsInNoissuesCharge');
1261
    unless ( C4::Context->preference('ManInvInNoissuesCharge') ) {
1262
        my $dbh = C4::Context->dbh;
1263
        my $man_inv_types = $dbh->selectcol_arrayref(qq{SELECT authorised_value FROM authorised_values WHERE category = 'MANUAL_INV'});
1264
        push @not_fines, map substr($_, 0, $ACCOUNT_TYPE_LENGTH), @$man_inv_types;
1265
    }
1266
    my %not_fine = map {$_ => 1} @not_fines;
1267
1214
1268
    my ($total, $acctlines) = GetMemberAccountRecords($borrowernumber);
1215
    push( @not_fines, Koha::Accounts::DebitTypes::Hold() );
1269
    my $other_charges = 0;
1270
    foreach (@$acctlines) {
1271
        $other_charges += $_->{amountoutstanding} if $not_fine{ substr($_->{accounttype}, 0, $ACCOUNT_TYPE_LENGTH) };
1272
    }
1273
1274
    return ( $total, $total - $other_charges, $other_charges);
1275
}
1276
1277
=head2 GetBorNotifyAcctRecord
1278
1279
  ($total, $acctlines, $count) = &GetBorNotifyAcctRecord($params,$notifyid);
1280
1216
1281
Looks up accounting data for the patron with the given borrowernumber per file number.
1217
    push( @not_fines, Koha::Accounts::DebitTypes::Rental() )
1218
      unless C4::Context->preference('RentalsInNoissuesCharge');
1282
1219
1283
C<&GetBorNotifyAcctRecord> returns a three-element array. C<$acctlines> is a
1220
    unless ( C4::Context->preference('ManInvInNoissuesCharge') ) {
1284
reference-to-array, where each element is a reference-to-hash; the
1221
        my $dbh           = C4::Context->dbh;
1285
keys are the fields of the C<accountlines> table in the Koha database.
1222
        my $man_inv_types = $dbh->selectcol_arrayref(
1286
C<$count> is the number of elements in C<$acctlines>. C<$total> is the
1223
            qq{SELECT authorised_value FROM authorised_values WHERE category = 'MANUAL_INV'}
1287
total amount outstanding for all of the account lines.
1224
        );
1288
1225
        push( @not_fines, @$man_inv_types );
1289
=cut
1226
    }
1290
1227
1291
sub GetBorNotifyAcctRecord {
1228
    my $other_charges =
1292
    my ( $borrowernumber, $notifyid ) = @_;
1229
      Koha::Database->new()->schema->resultset('AccountDebit')->search(
1293
    my $dbh = C4::Context->dbh;
1230
        {
1294
    my @acctlines;
1231
            borrowernumber => $borrowernumber,
1295
    my $numlines = 0;
1232
            type           => { -not_in => \@not_fines }
1296
    my $sth = $dbh->prepare(
1297
            "SELECT * 
1298
                FROM accountlines 
1299
                WHERE borrowernumber=? 
1300
                    AND notify_id=? 
1301
                    AND amountoutstanding != '0' 
1302
                ORDER BY notify_id,accounttype
1303
                ");
1304
1305
    $sth->execute( $borrowernumber, $notifyid );
1306
    my $total = 0;
1307
    while ( my $data = $sth->fetchrow_hashref ) {
1308
        if ( $data->{itemnumber} ) {
1309
            my $biblio = GetBiblioFromItemNumber( $data->{itemnumber} );
1310
            $data->{biblionumber} = $biblio->{biblionumber};
1311
            $data->{title}        = $biblio->{title};
1312
        }
1233
        }
1313
        $acctlines[$numlines] = $data;
1234
      )->get_column('amount_outstanding')->sum();
1314
        $numlines++;
1235
1315
        $total += int(100 * $data->{'amountoutstanding'});
1236
    return (
1316
    }
1237
        $borrower->account_balance(),
1317
    $total /= 100;
1238
        $borrower->account_balance() - $other_charges,
1318
    return ( $total, \@acctlines, $numlines );
1239
        $other_charges
1240
    );
1319
}
1241
}
1320
1242
1243
1321
=head2 checkuniquemember (OUEST-PROVENCE)
1244
=head2 checkuniquemember (OUEST-PROVENCE)
1322
1245
1323
  ($result,$categorycode)  = &checkuniquemember($collectivity,$surname,$firstname,$dateofbirth);
1246
  ($result,$categorycode)  = &checkuniquemember($collectivity,$surname,$firstname,$dateofbirth);
(-)a/C4/Overdues.pm (-231 / +114 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-54 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
        
51
        
51
        &CheckItemNotify
52
        &GetOverduesForBranch
52
        &GetOverduesForBranch
53
        &RemoveNotifyLine
53
        &RemoveNotifyLine
54
        &AddNotifyLine
54
        &AddNotifyLine
Lines 459-612 sub GetIssuesIteminfo { Link Here
459
459
460
=head2 UpdateFine
460
=head2 UpdateFine
461
461
462
    &UpdateFine($itemnumber, $borrowernumber, $amount, $type, $description);
462
    UpdateFine(
463
        {
464
            itemnumber     => $itemnumber,
465
            borrowernumber => $borrowernumber,
466
            amount         => $amount,
467
            due            => $due,
468
            issue_id       => $issue_id
469
        }
470
    );
463
471
464
(Note: the following is mostly conjecture and guesswork.)
472
Updates the fine owed on an overdue item.
465
473
466
Updates the fine owed on an overdue book.
474
C<$itemnumber> is the items's id.
467
475
468
C<$itemnumber> is the book's item number.
476
C<$borrowernumber> is the id of the patron who currently
477
has the item on loan.
469
478
470
C<$borrowernumber> is the borrower number of the patron who currently
479
C<$amount> is the total amount of the fine owed by the patron.
471
has the book on loan.
472
480
473
C<$amount> is the current amount owed by the patron.
481
C<&UpdateFine> updates the amount owed for a given fine if an issue_id
482
is passed to it. Otherwise, a new fine will be created.
474
483
475
C<$type> will be used in the description of the fine.
484
=cut
476
485
477
C<$description> is a string that must be present in the description of
486
sub UpdateFine {
478
the fine. I think this is expected to be a date in DD/MM/YYYY format.
487
    my ($params) = @_;
479
488
480
C<&UpdateFine> looks up the amount currently owed on the given item
489
    my $itemnumber     = $params->{itemnumber};
481
and sets it to C<$amount>, creating, if necessary, a new entry in the
490
    my $borrowernumber = $params->{borrowernumber};
482
accountlines table of the Koha database.
491
    my $amount         = $params->{amount};
492
    my $due            = $params->{due};
493
    my $issue_id       = $params->{issue_id};
483
494
484
=cut
495
    my $schema = Koha::Database->new()->schema;
485
496
486
#
497
    my $borrower = $schema->resultset('Borrower')->find($borrowernumber);
487
# Question: Why should the caller have to
488
# specify both the item number and the borrower number? A book can't
489
# be on loan to two different people, so the item number should be
490
# sufficient.
491
#
492
# Possible Answer: You might update a fine for a damaged item, *after* it is returned.
493
#
494
sub UpdateFine {
495
    my ( $itemnum, $borrowernumber, $amount, $type, $due ) = @_;
496
	$debug and warn "UpdateFine($itemnum, $borrowernumber, $amount, " . ($type||'""') . ", $due) called";
497
    my $dbh = C4::Context->dbh;
498
    # FIXME - What exactly is this query supposed to do? It looks up an
499
    # entry in accountlines that matches the given item and borrower
500
    # numbers, where the description contains $due, and where the
501
    # account type has one of several values, but what does this _mean_?
502
    # Does it look up existing fines for this item?
503
    # FIXME - What are these various account types? ("FU", "O", "F", "M")
504
	#	"L"   is LOST item
505
	#   "A"   is Account Management Fee
506
	#   "N"   is New Card
507
	#   "M"   is Sundry
508
	#   "O"   is Overdue ??
509
	#   "F"   is Fine ??
510
	#   "FU"  is Fine UPDATE??
511
	#	"Pay" is Payment
512
	#   "REF" is Cash Refund
513
    my $sth = $dbh->prepare(
514
        "SELECT * FROM accountlines
515
        WHERE borrowernumber=?
516
        AND   accounttype IN ('FU','O','F','M')"
517
    );
518
    $sth->execute( $borrowernumber );
519
    my $data;
520
    my $total_amount_other = 0.00;
521
    my $due_qr = qr/$due/;
522
    # Cycle through the fines and
523
    # - find line that relates to the requested $itemnum
524
    # - accumulate fines for other items
525
    # so we can update $itemnum fine taking in account fine caps
526
    while (my $rec = $sth->fetchrow_hashref) {
527
        if ($rec->{itemnumber} == $itemnum && $rec->{description} =~ /$due_qr/) {
528
            if ($data) {
529
                warn "Not a unique accountlines record for item $itemnum borrower $borrowernumber";
530
            } else {
531
                $data = $rec;
532
                next;
533
            }
534
        }
535
        $total_amount_other += $rec->{'amountoutstanding'};
536
    }
537
498
538
    if (my $maxfine = C4::Context->preference('MaxFine')) {
499
    if ( my $maxfine = C4::Context->preference('MaxFine') ) {
539
        if ($total_amount_other + $amount > $maxfine) {
500
        if ( $borrower->account_balance() + $amount > $maxfine ) {
540
            my $new_amount = $maxfine - $total_amount_other;
501
            my $new_amount = $maxfine - $borrower->account_balance();
541
            return if $new_amount <= 0.00;
502
            warn "Reducing fine for item $itemnumber borrower $borrowernumber from $amount to $new_amount - MaxFine reached";
542
            warn "Reducing fine for item $itemnum borrower $borrowernumber from $amount to $new_amount - MaxFine reached";
503
            if ( $new_amount <= 0 ) {
504
                warn "Fine reduced to a non-positive ammount. Fine not created.";
505
                return;
506
            }
543
            $amount = $new_amount;
507
            $amount = $new_amount;
544
        }
508
        }
545
    }
509
    }
546
510
547
    if ( $data ) {
511
    my $timestamp = get_timestamp();
548
512
549
		# we're updating an existing fine.  Only modify if amount changed
513
    my $fine =
550
        # Note that in the current implementation, you cannot pay against an accruing fine
514
      $schema->resultset('AccountDebit')->single( { issue_id => $issue_id, type => Koha::Accounts::DebitTypes::Fine } );
551
        # (i.e. , of accounttype 'FU').  Doing so will break accrual.
515
552
    	if ( $data->{'amount'} != $amount ) {
516
    my $offset = 0;
553
            my $diff = $amount - $data->{'amount'};
517
    if ($fine) {
554
	    #3341: diff could be positive or negative!
518
        if (
555
            my $out  = $data->{'amountoutstanding'} + $diff;
519
            sprintf( "%.6f", $fine->amount_original() )
556
            my $query = "
520
            ne
557
                UPDATE accountlines
521
            sprintf( "%.6f", $amount ) )
558
				SET date=now(), amount=?, amountoutstanding=?,
522
        {
559
					lastincrement=?, accounttype='FU'
523
            my $difference = $amount - $fine->amount_original();
560
	  			WHERE borrowernumber=?
524
561
				AND   itemnumber=?
525
            $fine->amount_original( $fine->amount_original() + $difference );
562
				AND   accounttype IN ('FU','O')
526
            $fine->amount_outstanding( $fine->amount_outstanding() + $difference );
563
				AND   description LIKE ?
527
            $fine->amount_last_increment($difference);
564
				LIMIT 1 ";
528
            $fine->updated_on($timestamp);
565
            my $sth2 = $dbh->prepare($query);
529
            $fine->update();
566
			# FIXME: BOGUS query cannot ensure uniqueness w/ LIKE %x% !!!
530
567
			# 		LIMIT 1 added to prevent multiple affected lines
531
            $offset = 1;
568
			# FIXME: accountlines table needs unique key!! Possibly a combo of borrowernumber and accountline.  
569
			# 		But actually, we should just have a regular autoincrementing PK and forget accountline,
570
			# 		including the bogus getnextaccountno function (doesn't prevent conflict on simultaneous ops).
571
			# FIXME: Why only 2 account types here?
572
			$debug and print STDERR "UpdateFine query: $query\n" .
573
				"w/ args: $amount, $out, $diff, $data->{'borrowernumber'}, $data->{'itemnumber'}, \"\%$due\%\"\n";
574
            $sth2->execute($amount, $out, $diff, $data->{'borrowernumber'}, $data->{'itemnumber'}, "%$due%");
575
        } else {
576
            #      print "no update needed $data->{'amount'}"
577
        }
532
        }
578
    } else {
533
    }
579
        my $sth4 = $dbh->prepare(
534
    else {
580
            "SELECT title FROM biblio LEFT JOIN items ON biblio.biblionumber=items.biblionumber WHERE items.itemnumber=?"
535
        my $item = $schema->resultset('Item')->find($itemnumber);
536
537
        $fine = $schema->resultset('AccountDebit')->create(
538
            {
539
                borrowernumber        => $borrowernumber,
540
                itemnumber            => $itemnumber,
541
                issue_id              => $issue_id,
542
                type                  => Koha::Accounts::DebitTypes::Fine(),
543
                accruing              => 1,
544
                amount_original       => $amount,
545
                amount_outstanding    => $amount,
546
                amount_last_increment => $amount,
547
                description           => $item->biblio()->title() . " / Due:$due",
548
                created_on            => $timestamp,
549
            }
581
        );
550
        );
582
        $sth4->execute($itemnum);
551
583
        my $title = $sth4->fetchrow;
552
        $offset = 1;
584
585
#         #   print "not in account";
586
#         my $sth3 = $dbh->prepare("Select max(accountno) from accountlines");
587
#         $sth3->execute;
588
# 
589
#         # FIXME - Make $accountno a scalar.
590
#         my @accountno = $sth3->fetchrow_array;
591
#         $sth3->finish;
592
#         $accountno[0]++;
593
# begin transaction
594
		my $nextaccntno = C4::Accounts::getnextacctno($borrowernumber);
595
		my $desc = ($type ? "$type " : '') . "$title $due";	# FIXEDME, avoid whitespace prefix on empty $type
596
		my $query = "INSERT INTO accountlines
597
		    (borrowernumber,itemnumber,date,amount,description,accounttype,amountoutstanding,lastincrement,accountno)
598
			    VALUES (?,?,now(),?,?,'FU',?,?,?)";
599
		my $sth2 = $dbh->prepare($query);
600
		$debug and print STDERR "UpdateFine query: $query\nw/ args: $borrowernumber, $itemnum, $amount, $desc, $amount, $amount, $nextaccntno\n";
601
        $sth2->execute($borrowernumber, $itemnum, $amount, $desc, $amount, $amount, $nextaccntno);
602
    }
553
    }
603
    # logging action
554
604
    &logaction(
555
    $schema->resultset('AccountOffset')->create(
605
        "FINES",
556
        {
606
        $type,
557
            debit_id   => $fine->debit_id(),
558
            amount     => $fine->amount_last_increment(),
559
            created_on => $timestamp,
560
            type       => Koha::Accounts::OffsetTypes::Fine(),
561
        }
562
    ) if $offset;
563
564
    $borrower->account_balance( $borrower->account_balance + $fine->amount_last_increment() );
565
    $borrower->update();
566
567
    logaction( "FINES", Koha::Accounts::DebitTypes::Fine(),
607
        $borrowernumber,
568
        $borrowernumber,
608
        "due=".$due."  amount=".$amount." itemnumber=".$itemnum
569
        "due=" . $due . "  amount=" . $amount . " itemnumber=" . $itemnumber )
609
        ) if C4::Context->preference("FinesLog");
570
      if C4::Context->preference("FinesLog");
610
}
571
}
611
572
612
=head2 BorType
573
=head2 BorType
Lines 647-716 C<$borrowernumber> is the borrowernumber Link Here
647
=cut 
608
=cut 
648
609
649
sub GetFine {
610
sub GetFine {
650
    my ( $itemnum, $borrowernumber ) = @_;
611
    my ( $itemnumber, $borrowernumber ) = @_;
651
    my $dbh   = C4::Context->dbh();
652
    my $query = q|SELECT sum(amountoutstanding) as fineamount FROM accountlines
653
    where accounttype like 'F%'
654
  AND amountoutstanding > 0 AND itemnumber = ? AND borrowernumber=?|;
655
    my $sth = $dbh->prepare($query);
656
    $sth->execute( $itemnum, $borrowernumber );
657
    my $fine = $sth->fetchrow_hashref();
658
    if ($fine->{fineamount}) {
659
        return $fine->{fineamount};
660
    }
661
    return 0;
662
}
663
664
=head2 NumberNotifyId
665
666
    (@notify) = &NumberNotifyId($borrowernumber);
667
668
Returns amount for all file per borrowers
669
C<@notify> array contains all file per borrowers
670
671
C<$notify_id> contains the file number for the borrower number nad item number
672
673
=cut
674
675
sub NumberNotifyId{
676
    my ($borrowernumber)=@_;
677
    my $dbh = C4::Context->dbh;
678
    my $query=qq|    SELECT distinct(notify_id)
679
            FROM accountlines
680
            WHERE borrowernumber=?|;
681
    my @notify;
682
    my $sth = $dbh->prepare($query);
683
    $sth->execute($borrowernumber);
684
    while ( my ($numberofnotify) = $sth->fetchrow ) {
685
        push( @notify, $numberofnotify );
686
    }
687
    return (@notify);
688
}
689
612
690
=head2 AmountNotify
613
    my $schema = Koha::Database->new()->schema;
691
614
692
    ($totalnotify) = &AmountNotify($notifyid);
615
    my $amount_outstanding = $schema->resultset('AccountDebit')->search(
616
        {
617
            itemnumber     => $itemnumber,
618
            borrowernumber => $borrowernumber,
619
            type           => Koha::Accounts::DebitTypes::Fine(),
620
        },
621
    )->get_column('amount_outstanding')->sum();
693
622
694
Returns amount for all file per borrowers
623
    return $amount_outstanding;
695
C<$notifyid> is the file number
696
697
C<$totalnotify> contains amount of a file
698
699
C<$notify_id> contains the file number for the borrower number and item number
700
701
=cut
702
703
sub AmountNotify{
704
    my ($notifyid,$borrowernumber)=@_;
705
    my $dbh = C4::Context->dbh;
706
    my $query=qq|    SELECT sum(amountoutstanding)
707
            FROM accountlines
708
            WHERE notify_id=? AND borrowernumber = ?|;
709
    my $sth=$dbh->prepare($query);
710
	$sth->execute($notifyid,$borrowernumber);
711
	my $totalnotify=$sth->fetchrow;
712
    $sth->finish;
713
    return ($totalnotify);
714
}
624
}
715
625
716
=head2 GetItems
626
=head2 GetItems
Lines 762-788 sub GetBranchcodesWithOverdueRules { Link Here
762
    return @branches;
672
    return @branches;
763
}
673
}
764
674
765
=head2 CheckItemNotify
766
767
Sql request to check if the document has alreday been notified
768
this function is not exported, only used with GetOverduesForBranch
769
770
=cut
771
772
sub CheckItemNotify {
773
    my ($notify_id,$notify_level,$itemnumber) = @_;
774
    my $dbh = C4::Context->dbh;
775
    my $sth = $dbh->prepare("
776
    SELECT COUNT(*)
777
     FROM notifys
778
    WHERE notify_id    = ?
779
     AND  notify_level = ? 
780
     AND  itemnumber   = ? ");
781
    $sth->execute($notify_id,$notify_level,$itemnumber);
782
    my $notified = $sth->fetchrow;
783
    return ($notified);
784
}
785
786
=head2 GetOverduesForBranch
675
=head2 GetOverduesForBranch
787
676
788
Sql request for display all information for branchoverdues.pl
677
Sql request for display all information for branchoverdues.pl
Lines 808-813 sub GetOverduesForBranch { Link Here
808
               biblio.title,
697
               biblio.title,
809
               biblio.author,
698
               biblio.author,
810
               biblio.biblionumber,
699
               biblio.biblionumber,
700
               issues.issue_id,
811
               issues.date_due,
701
               issues.date_due,
812
               issues.returndate,
702
               issues.returndate,
813
               issues.branchcode,
703
               issues.branchcode,
Lines 818-842 sub GetOverduesForBranch { Link Here
818
                items.location,
708
                items.location,
819
                items.itemnumber,
709
                items.itemnumber,
820
            itemtypes.description,
710
            itemtypes.description,
821
         accountlines.notify_id,
711
            account_debits.amount_outstanding
822
         accountlines.notify_level,
712
    FROM  account_debits
823
         accountlines.amountoutstanding
713
    LEFT JOIN issues      ON    issues.itemnumber     = account_debits.itemnumber
824
    FROM  accountlines
714
                          AND   issues.borrowernumber = account_debits.borrowernumber
825
    LEFT JOIN issues      ON    issues.itemnumber     = accountlines.itemnumber
715
    LEFT JOIN borrowers   ON borrowers.borrowernumber = account_debits.borrowernumber
826
                          AND   issues.borrowernumber = accountlines.borrowernumber
827
    LEFT JOIN borrowers   ON borrowers.borrowernumber = accountlines.borrowernumber
828
    LEFT JOIN items       ON     items.itemnumber     = issues.itemnumber
716
    LEFT JOIN items       ON     items.itemnumber     = issues.itemnumber
829
    LEFT JOIN biblio      ON      biblio.biblionumber =  items.biblionumber
717
    LEFT JOIN biblio      ON      biblio.biblionumber =  items.biblionumber
830
    LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
718
    LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
831
    LEFT JOIN itemtypes   ON itemtypes.itemtype       = $itype_link
719
    LEFT JOIN itemtypes   ON itemtypes.itemtype       = $itype_link
832
    LEFT JOIN branches    ON  branches.branchcode     = issues.branchcode
720
    LEFT JOIN branches    ON  branches.branchcode     = issues.branchcode
833
    WHERE (accountlines.amountoutstanding  != '0.000000')
721
    WHERE (account_debits.amount_outstanding  != '0.000000')
834
      AND (accountlines.accounttype         = 'FU'      )
722
      AND (account_debits.type = 'FINE')
723
      AND (account_debits.accruing = 1 )
835
      AND (issues.branchcode =  ?   )
724
      AND (issues.branchcode =  ?   )
836
      AND (issues.date_due  < NOW())
725
      AND (issues.date_due  < NOW())
837
    ";
726
    ";
838
    my @getoverdues;
727
    my @getoverdues;
839
    my $i = 0;
840
    my $sth;
728
    my $sth;
841
    if ($location) {
729
    if ($location) {
842
        $sth = $dbh->prepare("$select AND items.location = ? ORDER BY borrowers.surname, borrowers.firstname");
730
        $sth = $dbh->prepare("$select AND items.location = ? ORDER BY borrowers.surname, borrowers.firstname");
Lines 846-857 sub GetOverduesForBranch { Link Here
846
        $sth->execute($branch);
734
        $sth->execute($branch);
847
    }
735
    }
848
    while ( my $data = $sth->fetchrow_hashref ) {
736
    while ( my $data = $sth->fetchrow_hashref ) {
849
    #check if the document has already been notified
737
        push( @getoverdues, $data );
850
        my $countnotify = CheckItemNotify($data->{'notify_id'}, $data->{'notify_level'}, $data->{'itemnumber'});
851
        if ($countnotify eq '0') {
852
            $getoverdues[$i] = $data;
853
            $i++;
854
        }
855
    }
738
    }
856
    return (@getoverdues);
739
    return (@getoverdues);
857
}
740
}
(-)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 172-190 sub AddReserve { Link Here
172
        $waitingdate = $resdate;
171
        $waitingdate = $resdate;
173
    }
172
    }
174
173
175
    #eval {
176
    # updates take place here
177
    if ( $fee > 0 ) {
174
    if ( $fee > 0 ) {
178
        my $nextacctno = &getnextacctno( $borrowernumber );
175
        AddDebit(
179
        my $query      = qq/
176
            {
180
        INSERT INTO accountlines
177
                borrowernumber => $borrowernumber,
181
            (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
178
                itemnumber     => $checkitem,
182
        VALUES
179
                amount         => $fee,
183
            (?,?,now(),?,?,'Res',?)
180
                type           => Koha::Accounts::DebitTypes::Hold(),
184
    /;
181
                description    => "Hold fee - $title",
185
        my $usth = $dbh->prepare($query);
182
                notes          => "Record ID: $biblionumber",
186
        $usth->execute( $borrowernumber, $nextacctno, $fee,
183
            }
187
            "Reserve Charge - $title", $fee );
184
        );
188
    }
185
    }
189
186
190
    #if ($const eq 'a'){
187
    #if ($const eq 'a'){
(-)a/C4/SIP/ILS/Patron.pm (-1 / +1 lines)
Lines 85-91 sub new { Link Here
85
        hold_ok         => ( !$debarred && !$expired ),
85
        hold_ok         => ( !$debarred && !$expired ),
86
        card_lost       => ( $kp->{lost} || $kp->{gonenoaddress} || $flags->{LOST} ),
86
        card_lost       => ( $kp->{lost} || $kp->{gonenoaddress} || $flags->{LOST} ),
87
        claims_returned => 0,
87
        claims_returned => 0,
88
        fines           => $fines_amount, # GetMemberAccountRecords($kp->{borrowernumber})
88
        fines           => $fines_amount,
89
        fees            => 0,             # currently not distinct from fines
89
        fees            => 0,             # currently not distinct from fines
90
        recall_overdue  => 0,
90
        recall_overdue  => 0,
91
        items_billed    => 0,
91
        items_billed    => 0,
(-)a/C4/SIP/ILS/Transaction/FeePayment.pm (-5 / +18 lines)
Lines 20-26 use strict; Link Here
20
# with Koha; if not, write to the Free Software Foundation, Inc.,
20
# with Koha; if not, write to the Free Software Foundation, Inc.,
21
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
22
23
use C4::Accounts qw(recordpayment);
23
use Koha::Accounts qw(AddCredit);
24
use Koha::Database;
24
use ILS;
25
use ILS;
25
use parent qw(ILS::Transaction);
26
use parent qw(ILS::Transaction);
26
27
Lines 45-54 sub new { Link Here
45
sub pay {
46
sub pay {
46
    my $self           = shift;
47
    my $self           = shift;
47
    my $borrowernumber = shift;
48
    my $borrowernumber = shift;
48
    my $amt            = shift;
49
    my $amount         = shift;
49
    my $type           = shift;
50
    my $type           = shift;
50
    warn("RECORD:$borrowernumber::$amt");
51
51
    recordpayment( $borrowernumber, $amt,$type );
52
    warn("RECORD:$borrowernumber::$amount");
53
54
    my $borrower =
55
      Koha::Database->new()->schema->resultset('Borrower')
56
      ->find($borrowernumber);
57
58
    AddCredit(
59
        {
60
            borrower => $borrower,
61
            amount   => $amount,
62
            notes    => 'via SIP2',
63
            type     => $type,
64
        }
65
    );
52
}
66
}
53
67
54
#sub DESTROY {
68
#sub DESTROY {
55
- 

Return to bug 6427