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

(-)a/C4/Circulation.pm (-166 / +149 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 1275-1281 sub AddIssue { Link Here
1275
        ## If item was lost, it has now been found, reverse any list item charges if neccessary.
1276
        ## If item was lost, it has now been found, reverse any list item charges if neccessary.
1276
        if ( $item->{'itemlost'} ) {
1277
        if ( $item->{'itemlost'} ) {
1277
            if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) {
1278
            if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) {
1278
                _FixAccountForLostAndReturned( $item->{'itemnumber'}, undef, $item->{'barcode'} );
1279
                _FixAccountForLostAndReturned( $item->{'itemnumber'} );
1279
            }
1280
            }
1280
        }
1281
        }
1281
1282
Lines 1812-1820 sub AddReturn { Link Here
1812
                if ( $amount > 0
1813
                if ( $amount > 0
1813
                    && C4::Context->preference('finesMode') eq 'production' )
1814
                    && C4::Context->preference('finesMode') eq 'production' )
1814
                {
1815
                {
1815
                    C4::Overdues::UpdateFine( $issue->{itemnumber},
1816
                    C4::Overdues::UpdateFine(
1816
                        $issue->{borrowernumber},
1817
                        {
1817
                        $amount, $type, output_pref($datedue) );
1818
                            itemnumber     => $issue->{itemnumber},
1819
                            borrowernumber => $issue->{borrowernumber},
1820
                            amount         => $amount,
1821
                            due            => output_pref($datedue),
1822
                            issue_id       => $issue->{issue_id}
1823
                        }
1824
                    );
1818
                }
1825
                }
1819
            }
1826
            }
1820
1827
Lines 1864-1881 sub AddReturn { Link Here
1864
        $messages->{'WasLost'} = 1;
1871
        $messages->{'WasLost'} = 1;
1865
1872
1866
        if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) {
1873
        if ( C4::Context->preference('RefundLostItemFeeOnReturn' ) ) {
1867
            _FixAccountForLostAndReturned($item->{'itemnumber'}, $borrowernumber, $barcode);    # can tolerate undef $borrowernumber
1874
            _FixAccountForLostAndReturned( $item->{'itemnumber'} );
1868
            $messages->{'LostItemFeeRefunded'} = 1;
1875
            $messages->{'LostItemFeeRefunded'} = 1;
1869
        }
1876
        }
1870
    }
1877
    }
1871
1878
1872
    # fix up the overdues in accounts...
1879
    # fix up the overdues in accounts...
1873
    if ($borrowernumber) {
1880
    if ($borrowernumber) {
1874
        my $fix = _FixOverduesOnReturn($borrowernumber, $item->{itemnumber}, $exemptfine, $dropbox);
1881
        _FixOverduesOnReturn(
1875
        defined($fix) or warn "_FixOverduesOnReturn($borrowernumber, $item->{itemnumber}...) failed!";  # zero is OK, check defined
1882
            {
1883
                exempt_fine => $exemptfine,
1884
                dropbox     => $dropbox,
1885
                issue       => $issue,
1886
            }
1887
        );
1876
        
1888
        
1877
        if ( $issue->{overdue} && $issue->{date_due} ) {
1889
        if ( $issue->{overdue} && $issue->{date_due} ) {
1878
# fix fine days
1890
            # fix fine days
1879
            my $debardate =
1891
            my $debardate =
1880
              _debar_user_on_return( $borrower, $item, $issue->{date_due}, $today );
1892
              _debar_user_on_return( $borrower, $item, $issue->{date_due}, $today );
1881
            $messages->{Debarred} = $debardate if ($debardate);
1893
            $messages->{Debarred} = $debardate if ($debardate);
Lines 2093-2231 Internal function, called only by AddReturn Link Here
2093
=cut
2105
=cut
2094
2106
2095
sub _FixOverduesOnReturn {
2107
sub _FixOverduesOnReturn {
2096
    my ($borrowernumber, $item);
2108
    my ( $params ) = @_;
2097
    unless ($borrowernumber = shift) {
2109
2098
        warn "_FixOverduesOnReturn() not supplied valid borrowernumber";
2110
    my $exemptfine = $params->{exempt_fine};
2099
        return;
2111
    my $dropbox    = $params->{dropbox};
2100
    }
2112
    my $issue      = $params->{issue};
2101
    unless ($item = shift) {
2113
2102
        warn "_FixOverduesOnReturn() not supplied valid itemnumber";
2103
        return;
2104
    }
2105
    my ($exemptfine, $dropbox) = @_;
2106
    my $dbh = C4::Context->dbh;
2114
    my $dbh = C4::Context->dbh;
2107
2115
2108
    # check for overdue fine
2116
    my $schema = Koha::Database->new()->schema;
2109
    my $sth = $dbh->prepare(
2117
    my $fine =
2110
"SELECT * FROM accountlines WHERE (borrowernumber = ?) AND (itemnumber = ?) AND (accounttype='FU' OR accounttype='O')"
2118
      $schema->resultset('AccountDebit')
2111
    );
2119
      ->single( { issue_id => $issue->{issue_id}, type => Koha::Accounts::DebitTypes::Fine() } );
2112
    $sth->execute( $borrowernumber, $item );
2113
2120
2114
    # alter fine to show that the book has been returned
2121
    return unless ( $fine );
2115
    my $data = $sth->fetchrow_hashref;
2122
2116
    return 0 unless $data;    # no warning, there's just nothing to fix
2123
    $fine->accruing(0);
2117
2124
2118
    my $uquery;
2119
    my @bind = ($data->{'accountlines_id'});
2120
    if ($exemptfine) {
2125
    if ($exemptfine) {
2121
        $uquery = "update accountlines set accounttype='FFOR', amountoutstanding=0";
2126
        AddCredit(
2122
        if (C4::Context->preference("FinesLog")) {
2127
            {
2123
            &logaction("FINES", 'MODIFY',$borrowernumber,"Overdue forgiven: item $item");
2128
                borrower => $fine->borrowernumber(),
2124
        }
2129
                amount   => $fine->amount_original(),
2125
    } elsif ($dropbox && $data->{lastincrement}) {
2130
                debit_id => $fine->debit_id(),
2126
        my $outstanding = $data->{amountoutstanding} - $data->{lastincrement} ;
2131
                type     => Koha::Accounts::CreditTypes::Forgiven(),
2127
        my $amt = $data->{amount} - $data->{lastincrement} ;
2132
            }
2133
        );
2128
        if (C4::Context->preference("FinesLog")) {
2134
        if (C4::Context->preference("FinesLog")) {
2129
            &logaction("FINES", 'MODIFY',$borrowernumber,"Dropbox adjustment $amt, item $item");
2135
            &logaction(
2136
                "FINES", 'MODIFY',
2137
                $issue->{borrowernumber},
2138
                "Overdue forgiven: item " . $issue->{itemnumber}
2139
            );
2130
        }
2140
        }
2131
         $uquery = "update accountlines set accounttype='F' ";
2141
    } elsif ($dropbox && $fine->amount_last_increment() != $fine->amount_original() ) {
2132
         if($outstanding  >= 0 && $amt >=0) {
2142
        if ( C4::Context->preference("FinesLog") ) {
2133
            $uquery .= ", amount = ? , amountoutstanding=? ";
2143
            &logaction( "FINES", 'MODIFY', $issue->{borrowernumber},
2134
            unshift @bind, ($amt, $outstanding) ;
2144
                    "Dropbox adjustment "
2145
                  . $fine->amount_last_increment()
2146
                  . ", item " . $issue->{itemnumber} );
2135
        }
2147
        }
2136
    } else {
2148
        $fine->amount_original(
2137
        $uquery = "update accountlines set accounttype='F' ";
2149
            $fine->amount_original() - $fine->amount_last_increment() );
2150
        $fine->amount_outstanding(
2151
            $fine->amount_outstanding - $fine->amount_last_increment() );
2152
        $schema->resultset('AccountOffset')->create(
2153
            {
2154
                debit_id => $fine->debit_id(),
2155
                type     => Koha::Accounts::OffsetTypes::Dropbox(),
2156
                amount   => $fine->amount_last_increment() * -1,
2157
            }
2158
        );
2138
    }
2159
    }
2139
    $uquery .= " where (accountlines_id = ?)";
2160
2140
    my $usth = $dbh->prepare($uquery);
2161
    return $fine->update();
2141
    return $usth->execute(@bind);
2142
}
2162
}
2143
2163
2144
=head2 _FixAccountForLostAndReturned
2164
=head2 _FixAccountForLostAndReturned
2145
2165
2146
  &_FixAccountForLostAndReturned($itemnumber, [$borrowernumber, $barcode]);
2166
  &_FixAccountForLostAndReturned($itemnumber);
2147
2148
Calculates the charge for a book lost and returned.
2149
2167
2150
Internal function, not exported, called only by AddReturn.
2168
  Refunds a lost item fee in necessary
2151
2152
FIXME: This function reflects how inscrutable fines logic is.  Fix both.
2153
FIXME: Give a positive return value on success.  It might be the $borrowernumber who received credit, or the amount forgiven.
2154
2169
2155
=cut
2170
=cut
2156
2171
2157
sub _FixAccountForLostAndReturned {
2172
sub _FixAccountForLostAndReturned {
2158
    my $itemnumber     = shift or return;
2173
    my ( $itemnumber ) = @_;
2159
    my $borrowernumber = @_ ? shift : undef;
2174
2160
    my $item_id        = @_ ? shift : $itemnumber;  # Send the barcode if you want that logged in the description
2175
    my $schema = Koha::Database->new()->schema;
2161
    my $dbh = C4::Context->dbh;
2176
2162
    # check for charge made for lost book
2177
    # Find the last issue for this item
2163
    my $sth = $dbh->prepare("SELECT * FROM accountlines WHERE itemnumber = ? AND accounttype IN ('L', 'Rep', 'W') ORDER BY date DESC, accountno DESC");
2178
    my $issue =
2164
    $sth->execute($itemnumber);
2179
      $schema->resultset('Issue')->single( { itemnumber => $itemnumber } );
2165
    my $data = $sth->fetchrow_hashref;
2180
    $issue ||=
2166
    $data or return;    # bail if there is nothing to do
2181
      $schema->resultset('OldIssue')->single( { itemnumber => $itemnumber } );
2167
    $data->{accounttype} eq 'W' and return;    # Written off
2182
2168
2183
    return unless $issue;
2169
    # writeoff this amount
2184
2170
    my $offset;
2185
    # Find a lost fee for this issue
2171
    my $amount = $data->{'amount'};
2186
    my $debit = $schema->resultset('AccountDebit')->single(
2172
    my $acctno = $data->{'accountno'};
2187
        {
2173
    my $amountleft;                                             # Starts off undef/zero.
2188
            issue_id => $issue->issue_id(),
2174
    if ($data->{'amountoutstanding'} == $amount) {
2189
            type     => Koha::Accounts::DebitTypes::Lost()
2175
        $offset     = $data->{'amount'};
2176
        $amountleft = 0;                                        # Hey, it's zero here, too.
2177
    } else {
2178
        $offset     = $amount - $data->{'amountoutstanding'};   # Um, isn't this the same as ZERO?  We just tested those two things are ==
2179
        $amountleft = $data->{'amountoutstanding'} - $amount;   # Um, isn't this the same as ZERO?  We just tested those two things are ==
2180
    }
2181
    my $usth = $dbh->prepare("UPDATE accountlines SET accounttype = 'LR',amountoutstanding='0'
2182
        WHERE (accountlines_id = ?)");
2183
    $usth->execute($data->{'accountlines_id'});      # We might be adjusting an account for some OTHER borrowernumber now.  Not the one we passed in.
2184
    #check if any credit is left if so writeoff other accounts
2185
    my $nextaccntno = getnextacctno($data->{'borrowernumber'});
2186
    $amountleft *= -1 if ($amountleft < 0);
2187
    if ($amountleft > 0) {
2188
        my $msth = $dbh->prepare("SELECT * FROM accountlines WHERE (borrowernumber = ?)
2189
                            AND (amountoutstanding >0) ORDER BY date");     # might want to order by amountoustanding ASC (pay smallest first)
2190
        $msth->execute($data->{'borrowernumber'});
2191
        # offset transactions
2192
        my $newamtos;
2193
        my $accdata;
2194
        while (($accdata=$msth->fetchrow_hashref) and ($amountleft>0)){
2195
            if ($accdata->{'amountoutstanding'} < $amountleft) {
2196
                $newamtos = 0;
2197
                $amountleft -= $accdata->{'amountoutstanding'};
2198
            }  else {
2199
                $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
2200
                $amountleft = 0;
2201
            }
2202
            my $thisacct = $accdata->{'accountlines_id'};
2203
            # FIXME: move prepares outside while loop!
2204
            my $usth = $dbh->prepare("UPDATE accountlines SET amountoutstanding= ?
2205
                    WHERE (accountlines_id = ?)");
2206
            $usth->execute($newamtos,$thisacct);
2207
            $usth = $dbh->prepare("INSERT INTO accountoffsets
2208
                (borrowernumber, accountno, offsetaccount,  offsetamount)
2209
                VALUES
2210
                (?,?,?,?)");
2211
            $usth->execute($data->{'borrowernumber'},$accdata->{'accountno'},$nextaccntno,$newamtos);
2212
        }
2190
        }
2213
    }
2191
    );
2214
    $amountleft *= -1 if ($amountleft > 0);
2192
2215
    my $desc = "Item Returned " . $item_id;
2193
    return unless $debit;
2216
    $usth = $dbh->prepare("INSERT INTO accountlines
2194
2217
        (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding)
2195
    # Check for an existing found credit for this debit, if there is one, the fee has already been refunded and we do nothing
2218
        VALUES (?,?,now(),?,?,'CR',?)");
2196
    my @credits = $debit->account_offsets->search_related('credit', { 'credit.type' => Koha::Accounts::CreditTypes::Found() });
2219
    $usth->execute($data->{'borrowernumber'},$nextaccntno,0-$amount,$desc,$amountleft);
2197
2220
    if ($borrowernumber) {
2198
    return if @credits;
2221
        # FIXME: same as query above.  use 1 sth for both
2199
2222
        $usth = $dbh->prepare("INSERT INTO accountoffsets
2200
    # Ok, so we know we have an unrefunded lost item fee, let's refund it
2223
            (borrowernumber, accountno, offsetaccount,  offsetamount)
2201
    CreditLostItem(
2224
            VALUES (?,?,?,?)");
2202
        {
2225
        $usth->execute($borrowernumber, $data->{'accountno'}, $nextaccntno, $offset);
2203
            borrower => $issue->borrower(),
2226
    }
2204
            debit    => $debit
2205
        }
2206
    );
2207
2227
    ModItem({ paidfor => '' }, undef, $itemnumber);
2208
    ModItem({ paidfor => '' }, undef, $itemnumber);
2228
    return;
2229
}
2209
}
2230
2210
2231
=head2 _GetCircControlBranch
2211
=head2 _GetCircControlBranch
Lines 2584-2602 sub AddRenewal { Link Here
2584
    # Charge a new rental fee, if applicable?
2564
    # Charge a new rental fee, if applicable?
2585
    my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber );
2565
    my ( $charge, $type ) = GetIssuingCharges( $itemnumber, $borrowernumber );
2586
    if ( $charge > 0 ) {
2566
    if ( $charge > 0 ) {
2587
        my $accountno = getnextacctno( $borrowernumber );
2588
        my $item = GetBiblioFromItemNumber($itemnumber);
2567
        my $item = GetBiblioFromItemNumber($itemnumber);
2589
        my $manager_id = 0;
2568
2590
        $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv; 
2569
        my $borrower =
2591
        $sth = $dbh->prepare(
2570
          Koha::Database->new()->schema->resultset('Borrower')
2592
                "INSERT INTO accountlines
2571
          ->find($borrowernumber);
2593
                    (date, borrowernumber, accountno, amount, manager_id,
2572
2594
                    description,accounttype, amountoutstanding, itemnumber)
2573
        AddDebit(
2595
                    VALUES (now(),?,?,?,?,?,?,?,?)"
2574
            {
2575
                borrower   => $borrower,
2576
                itemnumber => $itemnumber,
2577
                amount     => $charge,
2578
                type       => Koha::Accounts::DebitTypes::Rental(),
2579
                description =>
2580
                  "Renewal of Rental Item $item->{'title'} $item->{'barcode'}"
2581
            }
2596
        );
2582
        );
2597
        $sth->execute( $borrowernumber, $accountno, $charge, $manager_id,
2598
            "Renewal of Rental Item $item->{'title'} $item->{'barcode'}",
2599
            'Rent', $charge, $itemnumber );
2600
    }
2583
    }
2601
2584
2602
    # Send a renewal slip according to checkout alert preferencei
2585
    # Send a renewal slip according to checkout alert preferencei
Lines 2767-2791 sub _get_discount_from_rule { Link Here
2767
2750
2768
=head2 AddIssuingCharge
2751
=head2 AddIssuingCharge
2769
2752
2770
  &AddIssuingCharge( $itemno, $borrowernumber, $charge )
2753
  &AddIssuingCharge( $itemnumber, $borrowernumber, $amount )
2771
2754
2772
=cut
2755
=cut
2773
2756
2774
sub AddIssuingCharge {
2757
sub AddIssuingCharge {
2775
    my ( $itemnumber, $borrowernumber, $charge ) = @_;
2758
    my ( $itemnumber, $borrowernumber, $amount ) = @_;
2776
    my $dbh = C4::Context->dbh;
2759
2777
    my $nextaccntno = getnextacctno( $borrowernumber );
2760
    return AddDebit(
2778
    my $manager_id = 0;
2761
        {
2779
    $manager_id = C4::Context->userenv->{'number'} if C4::Context->userenv;
2762
            borrower       => Koha::Database->new()->schema->resultset('Borrower')->find($borrowernumber),
2780
    my $query ="
2763
            itemnumber     => $itemnumber,
2781
        INSERT INTO accountlines
2764
            amount         => $amount,
2782
            (borrowernumber, itemnumber, accountno,
2765
            type           => Koha::Accounts::DebitTypes::Rental(),
2783
            date, amount, description, accounttype,
2766
        }
2784
            amountoutstanding, manager_id)
2767
    );
2785
        VALUES (?, ?, ?,now(), ?, 'Rental', 'Rent',?,?)
2786
    ";
2787
    my $sth = $dbh->prepare($query);
2788
    $sth->execute( $borrowernumber, $itemnumber, $nextaccntno, $charge, $charge, $manager_id );
2789
}
2768
}
2790
2769
2791
=head2 GetTransfers
2770
=head2 GetTransfers
Lines 3304-3333 sub ReturnLostItem{ Link Here
3304
sub LostItem{
3283
sub LostItem{
3305
    my ($itemnumber, $mark_returned) = @_;
3284
    my ($itemnumber, $mark_returned) = @_;
3306
3285
3307
    my $dbh = C4::Context->dbh();
3286
    my $schema = Koha::Database->new()->schema;
3308
    my $sth=$dbh->prepare("SELECT issues.*,items.*,biblio.title 
3309
                           FROM issues 
3310
                           JOIN items USING (itemnumber) 
3311
                           JOIN biblio USING (biblionumber)
3312
                           WHERE issues.itemnumber=?");
3313
    $sth->execute($itemnumber);
3314
    my $issues=$sth->fetchrow_hashref();
3315
3287
3316
    # If a borrower lost the item, add a replacement cost to the their record
3288
    my $issue =
3317
    if ( my $borrowernumber = $issues->{borrowernumber} ){
3289
      $schema->resultset('Issue')->single( { itemnumber => $itemnumber } );
3318
        my $borrower = C4::Members::GetMemberDetails( $borrowernumber );
3319
3290
3291
    my ( $borrower, $item );
3292
3293
    if ( $issue ) {
3294
        $borrower = $issue->borrower();
3295
        $item     = $issue->item();
3296
    }
3297
3298
    # If a borrower lost the item, add a replacement cost to the their record
3299
    if ( $borrower ){
3320
        if (C4::Context->preference('WhenLostForgiveFine')){
3300
        if (C4::Context->preference('WhenLostForgiveFine')){
3321
            my $fix = _FixOverduesOnReturn($borrowernumber, $itemnumber, 1, 0); # 1, 0 = exemptfine, no-dropbox
3301
            _FixOverduesOnReturn(
3322
            defined($fix) or warn "_FixOverduesOnReturn($borrowernumber, $itemnumber...) failed!";  # zero is OK, check defined
3302
                {
3303
                    exempt_fine => 1,
3304
                    dropbox     => 0,
3305
                    issue       => $issue,
3306
                }
3307
            );
3323
        }
3308
        }
3324
        if (C4::Context->preference('WhenLostChargeReplacementFee')){
3309
        if ( C4::Context->preference('WhenLostChargeReplacementFee') ) {
3325
            C4::Accounts::chargelostitem($borrowernumber, $itemnumber, $issues->{'replacementprice'}, "Lost Item $issues->{'title'} $issues->{'barcode'}");
3310
            DebitLostItem( { borrower => $borrower, issue => $issue } );
3326
            #FIXME : Should probably have a way to distinguish this from an item that really was returned.
3327
            #warn " $issues->{'borrowernumber'}  /  $itemnumber ";
3328
        }
3311
        }
3329
3312
3330
        MarkIssueReturned($borrowernumber,$itemnumber,undef,undef,$borrower->{'privacy'}) if $mark_returned;
3313
        MarkIssueReturned( $borrower->borrowernumber(), $item->itemnumber(), undef, undef, $borrower->privacy() ) if $mark_returned;
3331
    }
3314
    }
3332
}
3315
}
3333
3316
(-)a/C4/Members.pm (-118 / +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 83-90 BEGIN { Link Here
83
        &GetHideLostItemsPreference
83
        &GetHideLostItemsPreference
84
84
85
        &IsMemberBlocked
85
        &IsMemberBlocked
86
        &GetMemberAccountRecords
87
        &GetBorNotifyAcctRecord
88
86
89
        &GetborCatFromCatType
87
        &GetborCatFromCatType
90
        &GetBorrowercategory
88
        &GetBorrowercategory
Lines 338-346 sub GetMemberDetails { Link Here
338
        return;
336
        return;
339
    }
337
    }
340
    my $borrower = $sth->fetchrow_hashref;
338
    my $borrower = $sth->fetchrow_hashref;
341
    my ($amount) = GetMemberAccountRecords( $borrowernumber);
342
    $borrower->{'amountoutstanding'} = $amount;
343
    # FIXME - patronflags calls GetMemberAccountRecords... just have patronflags return $amount
344
    my $flags = patronflags( $borrower);
339
    my $flags = patronflags( $borrower);
345
    my $accessflagshash;
340
    my $accessflagshash;
346
341
Lines 432-454 The "message" field that comes from the DB is OK. Link Here
432
# FIXME rename this function.
427
# FIXME rename this function.
433
sub patronflags {
428
sub patronflags {
434
    my %flags;
429
    my %flags;
435
    my ( $patroninformation) = @_;
430
    my ($patroninformation) = @_;
436
    my $dbh=C4::Context->dbh;
431
    my $dbh = C4::Context->dbh;
437
    my ($balance, $owing) = GetMemberAccountBalance( $patroninformation->{'borrowernumber'});
432
    if ( $patroninformation->{account_balance} > 0 ) {
438
    if ( $owing > 0 ) {
439
        my %flaginfo;
433
        my %flaginfo;
440
        my $noissuescharge = C4::Context->preference("noissuescharge") || 5;
434
        my $noissuescharge = C4::Context->preference("noissuescharge") || 5;
441
        $flaginfo{'message'} = sprintf 'Patron owes %.02f', $owing;
435
        $flaginfo{'amount'}  = $patroninformation->{account_balance};
442
        $flaginfo{'amount'}  = sprintf "%.02f", $owing;
436
        if (  $patroninformation->{account_balance} > $noissuescharge && !C4::Context->preference("AllowFineOverride") ) {
443
        if ( $owing > $noissuescharge && !C4::Context->preference("AllowFineOverride") ) {
444
            $flaginfo{'noissues'} = 1;
437
            $flaginfo{'noissues'} = 1;
445
        }
438
        }
446
        $flags{'CHARGES'} = \%flaginfo;
439
        $flags{'CHARGES'} = \%flaginfo;
447
    }
440
    }
448
    elsif ( $balance < 0 ) {
441
    elsif ( $patroninformation->{account_balance} < 0 ) {
449
        my %flaginfo;
442
        my %flaginfo;
450
        $flaginfo{'message'} = sprintf 'Patron has credit of %.02f', -$balance;
443
        $flaginfo{'amount'}  = $patroninformation->{account_balance};
451
        $flaginfo{'amount'}  = sprintf "%.02f", $balance;
452
        $flags{'CREDITS'} = \%flaginfo;
444
        $flags{'CREDITS'} = \%flaginfo;
453
    }
445
    }
454
    if (   $patroninformation->{'gonenoaddress'}
446
    if (   $patroninformation->{'gonenoaddress'}
Lines 691-697 sub GetMemberIssuesAndFines { Link Here
691
    $sth->execute($borrowernumber);
683
    $sth->execute($borrowernumber);
692
    my $overdue_count = $sth->fetchrow_arrayref->[0];
684
    my $overdue_count = $sth->fetchrow_arrayref->[0];
693
685
694
    $sth = $dbh->prepare("SELECT SUM(amountoutstanding) FROM accountlines WHERE borrowernumber = ?");
686
    $sth = $dbh->prepare("SELECT account_balance FROM borrowers WHERE borrowernumber = ?");
695
    $sth->execute($borrowernumber);
687
    $sth->execute($borrowernumber);
696
    my $total_fines = $sth->fetchrow_arrayref->[0];
688
    my $total_fines = $sth->fetchrow_arrayref->[0];
697
689
Lines 1167-1223 sub GetAllIssues { Link Here
1167
}
1159
}
1168
1160
1169
1161
1170
=head2 GetMemberAccountRecords
1171
1172
  ($total, $acctlines, $count) = &GetMemberAccountRecords($borrowernumber);
1173
1174
Looks up accounting data for the patron with the given borrowernumber.
1175
1176
C<&GetMemberAccountRecords> returns a three-element array. C<$acctlines> is a
1177
reference-to-array, where each element is a reference-to-hash; the
1178
keys are the fields of the C<accountlines> table in the Koha database.
1179
C<$count> is the number of elements in C<$acctlines>. C<$total> is the
1180
total amount outstanding for all of the account lines.
1181
1182
=cut
1183
1184
sub GetMemberAccountRecords {
1185
    my ($borrowernumber) = @_;
1186
    my $dbh = C4::Context->dbh;
1187
    my @acctlines;
1188
    my $numlines = 0;
1189
    my $strsth      = qq(
1190
                        SELECT * 
1191
                        FROM accountlines 
1192
                        WHERE borrowernumber=?);
1193
    $strsth.=" ORDER BY date desc,timestamp DESC";
1194
    my $sth= $dbh->prepare( $strsth );
1195
    $sth->execute( $borrowernumber );
1196
1197
    my $total = 0;
1198
    while ( my $data = $sth->fetchrow_hashref ) {
1199
        if ( $data->{itemnumber} ) {
1200
            my $biblio = GetBiblioFromItemNumber( $data->{itemnumber} );
1201
            $data->{biblionumber} = $biblio->{biblionumber};
1202
            $data->{title}        = $biblio->{title};
1203
        }
1204
        $acctlines[$numlines] = $data;
1205
        $numlines++;
1206
        $total += int(1000 * $data->{'amountoutstanding'}); # convert float to integer to avoid round-off errors
1207
    }
1208
    $total /= 1000;
1209
    return ( $total, \@acctlines,$numlines);
1210
}
1211
1212
=head2 GetMemberAccountBalance
1162
=head2 GetMemberAccountBalance
1213
1163
1214
  ($total_balance, $non_issue_balance, $other_charges) = &GetMemberAccountBalance($borrowernumber);
1164
  ($total_balance, $non_issue_balance, $other_charges) = &GetMemberAccountBalance($borrowernumber);
1215
1165
1216
Calculates amount immediately owing by the patron - non-issue charges.
1166
Calculates amount immediately owing by the patron - non-issue charges.
1217
Based on GetMemberAccountRecords.
1218
Charges exempt from non-issue are:
1167
Charges exempt from non-issue are:
1219
* Res (reserves)
1168
* HOLD fees (reserves)
1220
* Rent (rental) if RentalsInNoissuesCharge syspref is set to false
1169
* RENTAL if RentalsInNoissuesCharge syspref is set to false
1221
* Manual invoices if ManInvInNoissuesCharge syspref is set to false
1170
* Manual invoices if ManInvInNoissuesCharge syspref is set to false
1222
1171
1223
=cut
1172
=cut
Lines 1225-1294 Charges exempt from non-issue are: Link Here
1225
sub GetMemberAccountBalance {
1174
sub GetMemberAccountBalance {
1226
    my ($borrowernumber) = @_;
1175
    my ($borrowernumber) = @_;
1227
1176
1228
    my $ACCOUNT_TYPE_LENGTH = 5; # this is plain ridiculous...
1177
    my $borrower =
1178
      Koha::Database->new()->schema->resultset('Borrower')
1179
      ->find($borrowernumber);
1229
1180
1230
    my @not_fines = ('Res');
1181
    my @not_fines;
1231
    push @not_fines, 'Rent' unless C4::Context->preference('RentalsInNoissuesCharge');
1232
    unless ( C4::Context->preference('ManInvInNoissuesCharge') ) {
1233
        my $dbh = C4::Context->dbh;
1234
        my $man_inv_types = $dbh->selectcol_arrayref(qq{SELECT authorised_value FROM authorised_values WHERE category = 'MANUAL_INV'});
1235
        push @not_fines, map substr($_, 0, $ACCOUNT_TYPE_LENGTH), @$man_inv_types;
1236
    }
1237
    my %not_fine = map {$_ => 1} @not_fines;
1238
1182
1239
    my ($total, $acctlines) = GetMemberAccountRecords($borrowernumber);
1183
    push( @not_fines, Koha::Accounts::DebitTypes::Hold() );
1240
    my $other_charges = 0;
1241
    foreach (@$acctlines) {
1242
        $other_charges += $_->{amountoutstanding} if $not_fine{ substr($_->{accounttype}, 0, $ACCOUNT_TYPE_LENGTH) };
1243
    }
1244
1245
    return ( $total, $total - $other_charges, $other_charges);
1246
}
1247
1248
=head2 GetBorNotifyAcctRecord
1249
1250
  ($total, $acctlines, $count) = &GetBorNotifyAcctRecord($params,$notifyid);
1251
1184
1252
Looks up accounting data for the patron with the given borrowernumber per file number.
1185
    push( @not_fines, Koha::Accounts::DebitTypes::Rental() )
1186
      unless C4::Context->preference('RentalsInNoissuesCharge');
1253
1187
1254
C<&GetBorNotifyAcctRecord> returns a three-element array. C<$acctlines> is a
1188
    unless ( C4::Context->preference('ManInvInNoissuesCharge') ) {
1255
reference-to-array, where each element is a reference-to-hash; the
1189
        my $dbh           = C4::Context->dbh;
1256
keys are the fields of the C<accountlines> table in the Koha database.
1190
        my $man_inv_types = $dbh->selectcol_arrayref(
1257
C<$count> is the number of elements in C<$acctlines>. C<$total> is the
1191
            qq{SELECT authorised_value FROM authorised_values WHERE category = 'MANUAL_INV'}
1258
total amount outstanding for all of the account lines.
1192
        );
1259
1193
        push( @not_fines, @$man_inv_types );
1260
=cut
1194
    }
1261
1195
1262
sub GetBorNotifyAcctRecord {
1196
    my $other_charges =
1263
    my ( $borrowernumber, $notifyid ) = @_;
1197
      Koha::Database->new()->schema->resultset('AccountDebit')->search(
1264
    my $dbh = C4::Context->dbh;
1198
        {
1265
    my @acctlines;
1199
            borrowernumber => $borrowernumber,
1266
    my $numlines = 0;
1200
            type           => { -not_in => \@not_fines }
1267
    my $sth = $dbh->prepare(
1268
            "SELECT * 
1269
                FROM accountlines 
1270
                WHERE borrowernumber=? 
1271
                    AND notify_id=? 
1272
                    AND amountoutstanding != '0' 
1273
                ORDER BY notify_id,accounttype
1274
                ");
1275
1276
    $sth->execute( $borrowernumber, $notifyid );
1277
    my $total = 0;
1278
    while ( my $data = $sth->fetchrow_hashref ) {
1279
        if ( $data->{itemnumber} ) {
1280
            my $biblio = GetBiblioFromItemNumber( $data->{itemnumber} );
1281
            $data->{biblionumber} = $biblio->{biblionumber};
1282
            $data->{title}        = $biblio->{title};
1283
        }
1201
        }
1284
        $acctlines[$numlines] = $data;
1202
      )->get_column('amount_outstanding')->sum();
1285
        $numlines++;
1203
1286
        $total += int(100 * $data->{'amountoutstanding'});
1204
    return (
1287
    }
1205
        $borrower->account_balance(),
1288
    $total /= 100;
1206
        $borrower->account_balance() - $other_charges,
1289
    return ( $total, \@acctlines, $numlines );
1207
        $other_charges
1208
    );
1290
}
1209
}
1291
1210
1211
1292
=head2 checkuniquemember (OUEST-PROVENCE)
1212
=head2 checkuniquemember (OUEST-PROVENCE)
1293
1213
1294
  ($result,$categorycode)  = &checkuniquemember($collectivity,$surname,$firstname,$dateofbirth);
1214
  ($result,$categorycode)  = &checkuniquemember($collectivity,$surname,$firstname,$dateofbirth);
(-)a/C4/Overdues.pm (-231 / +114 lines)
Lines 25-33 use Date::Calc qw/Today Date_to_Days/; Link Here
25
use Date::Manip qw/UnixDate/;
25
use Date::Manip qw/UnixDate/;
26
use C4::Circulation;
26
use C4::Circulation;
27
use C4::Context;
27
use C4::Context;
28
use C4::Accounts;
29
use C4::Log; # logaction
28
use C4::Log; # logaction
30
use C4::Debug;
29
use C4::Debug;
30
use Koha::Database;
31
use Koha::DateUtils;
32
use Koha::Accounts::OffsetTypes;
33
use Koha::Accounts::DebitTypes;
31
34
32
use vars qw($VERSION @ISA @EXPORT);
35
use vars qw($VERSION @ISA @EXPORT);
33
36
Lines 41-52 BEGIN { Link Here
41
        &CalcFine
44
        &CalcFine
42
        &Getoverdues
45
        &Getoverdues
43
        &checkoverdues
46
        &checkoverdues
44
        &NumberNotifyId
45
        &AmountNotify
46
        &UpdateFine
47
        &UpdateFine
47
        &GetFine
48
        &GetFine
48
        
49
        
49
        &CheckItemNotify
50
        &GetOverduesForBranch
50
        &GetOverduesForBranch
51
        &RemoveNotifyLine
51
        &RemoveNotifyLine
52
        &AddNotifyLine
52
        &AddNotifyLine
Lines 456-609 sub GetIssuesIteminfo { Link Here
456
456
457
=head2 UpdateFine
457
=head2 UpdateFine
458
458
459
    &UpdateFine($itemnumber, $borrowernumber, $amount, $type, $description);
459
    UpdateFine(
460
        {
461
            itemnumber     => $itemnumber,
462
            borrowernumber => $borrowernumber,
463
            amount         => $amount,
464
            due            => $due,
465
            issue_id       => $issue_id
466
        }
467
    );
460
468
461
(Note: the following is mostly conjecture and guesswork.)
469
Updates the fine owed on an overdue item.
462
470
463
Updates the fine owed on an overdue book.
471
C<$itemnumber> is the items's id.
464
472
465
C<$itemnumber> is the book's item number.
473
C<$borrowernumber> is the id of the patron who currently
474
has the item on loan.
466
475
467
C<$borrowernumber> is the borrower number of the patron who currently
476
C<$amount> is the total amount of the fine owed by the patron.
468
has the book on loan.
469
477
470
C<$amount> is the current amount owed by the patron.
478
C<&UpdateFine> updates the amount owed for a given fine if an issue_id
479
is passed to it. Otherwise, a new fine will be created.
471
480
472
C<$type> will be used in the description of the fine.
481
=cut
473
482
474
C<$description> is a string that must be present in the description of
483
sub UpdateFine {
475
the fine. I think this is expected to be a date in DD/MM/YYYY format.
484
    my ($params) = @_;
476
485
477
C<&UpdateFine> looks up the amount currently owed on the given item
486
    my $itemnumber     = $params->{itemnumber};
478
and sets it to C<$amount>, creating, if necessary, a new entry in the
487
    my $borrowernumber = $params->{borrowernumber};
479
accountlines table of the Koha database.
488
    my $amount         = $params->{amount};
489
    my $due            = $params->{due};
490
    my $issue_id       = $params->{issue_id};
480
491
481
=cut
492
    my $schema = Koha::Database->new()->schema;
482
493
483
#
494
    my $borrower = $schema->resultset('Borrower')->find($borrowernumber);
484
# Question: Why should the caller have to
485
# specify both the item number and the borrower number? A book can't
486
# be on loan to two different people, so the item number should be
487
# sufficient.
488
#
489
# Possible Answer: You might update a fine for a damaged item, *after* it is returned.
490
#
491
sub UpdateFine {
492
    my ( $itemnum, $borrowernumber, $amount, $type, $due ) = @_;
493
	$debug and warn "UpdateFine($itemnum, $borrowernumber, $amount, " . ($type||'""') . ", $due) called";
494
    my $dbh = C4::Context->dbh;
495
    # FIXME - What exactly is this query supposed to do? It looks up an
496
    # entry in accountlines that matches the given item and borrower
497
    # numbers, where the description contains $due, and where the
498
    # account type has one of several values, but what does this _mean_?
499
    # Does it look up existing fines for this item?
500
    # FIXME - What are these various account types? ("FU", "O", "F", "M")
501
	#	"L"   is LOST item
502
	#   "A"   is Account Management Fee
503
	#   "N"   is New Card
504
	#   "M"   is Sundry
505
	#   "O"   is Overdue ??
506
	#   "F"   is Fine ??
507
	#   "FU"  is Fine UPDATE??
508
	#	"Pay" is Payment
509
	#   "REF" is Cash Refund
510
    my $sth = $dbh->prepare(
511
        "SELECT * FROM accountlines
512
        WHERE borrowernumber=?
513
        AND   accounttype IN ('FU','O','F','M')"
514
    );
515
    $sth->execute( $borrowernumber );
516
    my $data;
517
    my $total_amount_other = 0.00;
518
    my $due_qr = qr/$due/;
519
    # Cycle through the fines and
520
    # - find line that relates to the requested $itemnum
521
    # - accumulate fines for other items
522
    # so we can update $itemnum fine taking in account fine caps
523
    while (my $rec = $sth->fetchrow_hashref) {
524
        if ($rec->{itemnumber} == $itemnum && $rec->{description} =~ /$due_qr/) {
525
            if ($data) {
526
                warn "Not a unique accountlines record for item $itemnum borrower $borrowernumber";
527
            } else {
528
                $data = $rec;
529
                next;
530
            }
531
        }
532
        $total_amount_other += $rec->{'amountoutstanding'};
533
    }
534
495
535
    if (my $maxfine = C4::Context->preference('MaxFine')) {
496
    if ( my $maxfine = C4::Context->preference('MaxFine') ) {
536
        if ($total_amount_other + $amount > $maxfine) {
497
        if ( $borrower->account_balance() + $amount > $maxfine ) {
537
            my $new_amount = $maxfine - $total_amount_other;
498
            my $new_amount = $maxfine - $borrower->account_balance();
538
            return if $new_amount <= 0.00;
499
            warn "Reducing fine for item $itemnumber borrower $borrowernumber from $amount to $new_amount - MaxFine reached";
539
            warn "Reducing fine for item $itemnum borrower $borrowernumber from $amount to $new_amount - MaxFine reached";
500
            if ( $new_amount <= 0 ) {
501
                warn "Fine reduced to a non-positive ammount. Fine not created.";
502
                return;
503
            }
540
            $amount = $new_amount;
504
            $amount = $new_amount;
541
        }
505
        }
542
    }
506
    }
543
507
544
    if ( $data ) {
508
    my $timestamp = get_timestamp();
545
509
546
		# we're updating an existing fine.  Only modify if amount changed
510
    my $fine =
547
        # Note that in the current implementation, you cannot pay against an accruing fine
511
      $schema->resultset('AccountDebit')->single( { issue_id => $issue_id, type => Koha::Accounts::DebitTypes::Fine } );
548
        # (i.e. , of accounttype 'FU').  Doing so will break accrual.
512
549
    	if ( $data->{'amount'} != $amount ) {
513
    my $offset = 0;
550
            my $diff = $amount - $data->{'amount'};
514
    if ($fine) {
551
	    #3341: diff could be positive or negative!
515
        if (
552
            my $out  = $data->{'amountoutstanding'} + $diff;
516
            sprintf( "%.6f", $fine->amount_original() )
553
            my $query = "
517
            ne
554
                UPDATE accountlines
518
            sprintf( "%.6f", $amount ) )
555
				SET date=now(), amount=?, amountoutstanding=?,
519
        {
556
					lastincrement=?, accounttype='FU'
520
            my $difference = $amount - $fine->amount_original();
557
	  			WHERE borrowernumber=?
521
558
				AND   itemnumber=?
522
            $fine->amount_original( $fine->amount_original() + $difference );
559
				AND   accounttype IN ('FU','O')
523
            $fine->amount_outstanding( $fine->amount_outstanding() + $difference );
560
				AND   description LIKE ?
524
            $fine->amount_last_increment($difference);
561
				LIMIT 1 ";
525
            $fine->updated_on($timestamp);
562
            my $sth2 = $dbh->prepare($query);
526
            $fine->update();
563
			# FIXME: BOGUS query cannot ensure uniqueness w/ LIKE %x% !!!
527
564
			# 		LIMIT 1 added to prevent multiple affected lines
528
            $offset = 1;
565
			# FIXME: accountlines table needs unique key!! Possibly a combo of borrowernumber and accountline.  
566
			# 		But actually, we should just have a regular autoincrementing PK and forget accountline,
567
			# 		including the bogus getnextaccountno function (doesn't prevent conflict on simultaneous ops).
568
			# FIXME: Why only 2 account types here?
569
			$debug and print STDERR "UpdateFine query: $query\n" .
570
				"w/ args: $amount, $out, $diff, $data->{'borrowernumber'}, $data->{'itemnumber'}, \"\%$due\%\"\n";
571
            $sth2->execute($amount, $out, $diff, $data->{'borrowernumber'}, $data->{'itemnumber'}, "%$due%");
572
        } else {
573
            #      print "no update needed $data->{'amount'}"
574
        }
529
        }
575
    } else {
530
    }
576
        my $sth4 = $dbh->prepare(
531
    else {
577
            "SELECT title FROM biblio LEFT JOIN items ON biblio.biblionumber=items.biblionumber WHERE items.itemnumber=?"
532
        my $item = $schema->resultset('Item')->find($itemnumber);
533
534
        $fine = $schema->resultset('AccountDebit')->create(
535
            {
536
                borrowernumber        => $borrowernumber,
537
                itemnumber            => $itemnumber,
538
                issue_id              => $issue_id,
539
                type                  => Koha::Accounts::DebitTypes::Fine(),
540
                accruing              => 1,
541
                amount_original       => $amount,
542
                amount_outstanding    => $amount,
543
                amount_last_increment => $amount,
544
                description           => $item->biblio()->title() . " / Due:$due",
545
                created_on            => $timestamp,
546
            }
578
        );
547
        );
579
        $sth4->execute($itemnum);
548
580
        my $title = $sth4->fetchrow;
549
        $offset = 1;
581
582
#         #   print "not in account";
583
#         my $sth3 = $dbh->prepare("Select max(accountno) from accountlines");
584
#         $sth3->execute;
585
# 
586
#         # FIXME - Make $accountno a scalar.
587
#         my @accountno = $sth3->fetchrow_array;
588
#         $sth3->finish;
589
#         $accountno[0]++;
590
# begin transaction
591
		my $nextaccntno = C4::Accounts::getnextacctno($borrowernumber);
592
		my $desc = ($type ? "$type " : '') . "$title $due";	# FIXEDME, avoid whitespace prefix on empty $type
593
		my $query = "INSERT INTO accountlines
594
		    (borrowernumber,itemnumber,date,amount,description,accounttype,amountoutstanding,lastincrement,accountno)
595
			    VALUES (?,?,now(),?,?,'FU',?,?,?)";
596
		my $sth2 = $dbh->prepare($query);
597
		$debug and print STDERR "UpdateFine query: $query\nw/ args: $borrowernumber, $itemnum, $amount, $desc, $amount, $amount, $nextaccntno\n";
598
        $sth2->execute($borrowernumber, $itemnum, $amount, $desc, $amount, $amount, $nextaccntno);
599
    }
550
    }
600
    # logging action
551
601
    &logaction(
552
    $schema->resultset('AccountOffset')->create(
602
        "FINES",
553
        {
603
        $type,
554
            debit_id   => $fine->debit_id(),
555
            amount     => $fine->amount_last_increment(),
556
            created_on => $timestamp,
557
            type       => Koha::Accounts::OffsetTypes::Fine(),
558
        }
559
    ) if $offset;
560
561
    $borrower->account_balance( $borrower->account_balance + $fine->amount_last_increment() );
562
    $borrower->update();
563
564
    logaction( "FINES", Koha::Accounts::DebitTypes::Fine(),
604
        $borrowernumber,
565
        $borrowernumber,
605
        "due=".$due."  amount=".$amount." itemnumber=".$itemnum
566
        "due=" . $due . "  amount=" . $amount . " itemnumber=" . $itemnumber )
606
        ) if C4::Context->preference("FinesLog");
567
      if C4::Context->preference("FinesLog");
607
}
568
}
608
569
609
=head2 BorType
570
=head2 BorType
Lines 644-713 C<$borrowernumber> is the borrowernumber Link Here
644
=cut 
605
=cut 
645
606
646
sub GetFine {
607
sub GetFine {
647
    my ( $itemnum, $borrowernumber ) = @_;
608
    my ( $itemnumber, $borrowernumber ) = @_;
648
    my $dbh   = C4::Context->dbh();
649
    my $query = q|SELECT sum(amountoutstanding) as fineamount FROM accountlines
650
    where accounttype like 'F%'
651
  AND amountoutstanding > 0 AND itemnumber = ? AND borrowernumber=?|;
652
    my $sth = $dbh->prepare($query);
653
    $sth->execute( $itemnum, $borrowernumber );
654
    my $fine = $sth->fetchrow_hashref();
655
    if ($fine->{fineamount}) {
656
        return $fine->{fineamount};
657
    }
658
    return 0;
659
}
660
661
=head2 NumberNotifyId
662
663
    (@notify) = &NumberNotifyId($borrowernumber);
664
665
Returns amount for all file per borrowers
666
C<@notify> array contains all file per borrowers
667
668
C<$notify_id> contains the file number for the borrower number nad item number
669
670
=cut
671
672
sub NumberNotifyId{
673
    my ($borrowernumber)=@_;
674
    my $dbh = C4::Context->dbh;
675
    my $query=qq|    SELECT distinct(notify_id)
676
            FROM accountlines
677
            WHERE borrowernumber=?|;
678
    my @notify;
679
    my $sth = $dbh->prepare($query);
680
    $sth->execute($borrowernumber);
681
    while ( my ($numberofnotify) = $sth->fetchrow ) {
682
        push( @notify, $numberofnotify );
683
    }
684
    return (@notify);
685
}
686
687
=head2 AmountNotify
688
689
    ($totalnotify) = &AmountNotify($notifyid);
690
691
Returns amount for all file per borrowers
692
C<$notifyid> is the file number
693
609
694
C<$totalnotify> contains amount of a file
610
    my $schema = Koha::Database->new()->schema;
695
611
696
C<$notify_id> contains the file number for the borrower number and item number
612
    my $amount_outstanding = $schema->resultset('AccountDebit')->search(
613
        {
614
            itemnumber     => $itemnumber,
615
            borrowernumber => $borrowernumber,
616
            type           => Koha::Accounts::DebitTypes::Fine(),
617
        },
618
    )->get_column('amount_outstanding')->sum();
697
619
698
=cut
620
    return $amount_outstanding;
699
700
sub AmountNotify{
701
    my ($notifyid,$borrowernumber)=@_;
702
    my $dbh = C4::Context->dbh;
703
    my $query=qq|    SELECT sum(amountoutstanding)
704
            FROM accountlines
705
            WHERE notify_id=? AND borrowernumber = ?|;
706
    my $sth=$dbh->prepare($query);
707
	$sth->execute($notifyid,$borrowernumber);
708
	my $totalnotify=$sth->fetchrow;
709
    $sth->finish;
710
    return ($totalnotify);
711
}
621
}
712
622
713
=head2 GetItems
623
=head2 GetItems
Lines 759-785 sub GetBranchcodesWithOverdueRules { Link Here
759
    return @branches;
669
    return @branches;
760
}
670
}
761
671
762
=head2 CheckItemNotify
763
764
Sql request to check if the document has alreday been notified
765
this function is not exported, only used with GetOverduesForBranch
766
767
=cut
768
769
sub CheckItemNotify {
770
    my ($notify_id,$notify_level,$itemnumber) = @_;
771
    my $dbh = C4::Context->dbh;
772
    my $sth = $dbh->prepare("
773
    SELECT COUNT(*)
774
     FROM notifys
775
    WHERE notify_id    = ?
776
     AND  notify_level = ? 
777
     AND  itemnumber   = ? ");
778
    $sth->execute($notify_id,$notify_level,$itemnumber);
779
    my $notified = $sth->fetchrow;
780
    return ($notified);
781
}
782
783
=head2 GetOverduesForBranch
672
=head2 GetOverduesForBranch
784
673
785
Sql request for display all information for branchoverdues.pl
674
Sql request for display all information for branchoverdues.pl
Lines 804-809 sub GetOverduesForBranch { Link Here
804
               biblio.title,
693
               biblio.title,
805
               biblio.author,
694
               biblio.author,
806
               biblio.biblionumber,
695
               biblio.biblionumber,
696
               issues.issue_id,
807
               issues.date_due,
697
               issues.date_due,
808
               issues.returndate,
698
               issues.returndate,
809
               issues.branchcode,
699
               issues.branchcode,
Lines 814-838 sub GetOverduesForBranch { Link Here
814
                items.location,
704
                items.location,
815
                items.itemnumber,
705
                items.itemnumber,
816
            itemtypes.description,
706
            itemtypes.description,
817
         accountlines.notify_id,
707
            account_debits.amount_outstanding
818
         accountlines.notify_level,
708
    FROM  account_debits
819
         accountlines.amountoutstanding
709
    LEFT JOIN issues      ON    issues.itemnumber     = account_debits.itemnumber
820
    FROM  accountlines
710
                          AND   issues.borrowernumber = account_debits.borrowernumber
821
    LEFT JOIN issues      ON    issues.itemnumber     = accountlines.itemnumber
711
    LEFT JOIN borrowers   ON borrowers.borrowernumber = account_debits.borrowernumber
822
                          AND   issues.borrowernumber = accountlines.borrowernumber
823
    LEFT JOIN borrowers   ON borrowers.borrowernumber = accountlines.borrowernumber
824
    LEFT JOIN items       ON     items.itemnumber     = issues.itemnumber
712
    LEFT JOIN items       ON     items.itemnumber     = issues.itemnumber
825
    LEFT JOIN biblio      ON      biblio.biblionumber =  items.biblionumber
713
    LEFT JOIN biblio      ON      biblio.biblionumber =  items.biblionumber
826
    LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
714
    LEFT JOIN biblioitems ON biblioitems.biblioitemnumber = items.biblioitemnumber
827
    LEFT JOIN itemtypes   ON itemtypes.itemtype       = $itype_link
715
    LEFT JOIN itemtypes   ON itemtypes.itemtype       = $itype_link
828
    LEFT JOIN branches    ON  branches.branchcode     = issues.branchcode
716
    LEFT JOIN branches    ON  branches.branchcode     = issues.branchcode
829
    WHERE (accountlines.amountoutstanding  != '0.000000')
717
    WHERE (account_debits.amount_outstanding  != '0.000000')
830
      AND (accountlines.accounttype         = 'FU'      )
718
      AND (account_debits.type = 'FINE')
719
      AND (account_debits.accruing = 1 )
831
      AND (issues.branchcode =  ?   )
720
      AND (issues.branchcode =  ?   )
832
      AND (issues.date_due  < NOW())
721
      AND (issues.date_due  < NOW())
833
    ";
722
    ";
834
    my @getoverdues;
723
    my @getoverdues;
835
    my $i = 0;
836
    my $sth;
724
    my $sth;
837
    if ($location) {
725
    if ($location) {
838
        $sth = $dbh->prepare("$select AND items.location = ? ORDER BY borrowers.surname, borrowers.firstname");
726
        $sth = $dbh->prepare("$select AND items.location = ? ORDER BY borrowers.surname, borrowers.firstname");
Lines 842-853 sub GetOverduesForBranch { Link Here
842
        $sth->execute($branch);
730
        $sth->execute($branch);
843
    }
731
    }
844
    while ( my $data = $sth->fetchrow_hashref ) {
732
    while ( my $data = $sth->fetchrow_hashref ) {
845
    #check if the document has already been notified
733
        push( @getoverdues, $data );
846
        my $countnotify = CheckItemNotify($data->{'notify_id'}, $data->{'notify_level'}, $data->{'itemnumber'});
847
        if ($countnotify eq '0') {
848
            $getoverdues[$i] = $data;
849
            $i++;
850
        }
851
    }
734
    }
852
    return (@getoverdues);
735
    return (@getoverdues);
853
}
736
}
(-)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 / +15 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-53 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
    warn("RECORD:$borrowernumber::$amt");
50
50
    recordpayment( $borrowernumber, $amt );
51
    warn("RECORD:$borrowernumber::$amount");
52
53
    my $borrower = Koha::Database->new()->schema->resultset('Borrower')
54
      ->find( $borrowernumber );
55
    AddCredit(
56
        {
57
            borrower => $borrower,
58
            amount   => $amount,
59
            notes    => 'via SIP2',
60
        }
61
    );
51
}
62
}
52
63
53
#sub DESTROY {
64
#sub DESTROY {
54
- 

Return to bug 6427