+
+BEGIN {
+ # set the version for version checking
+ $VERSION = 3.03;
+ require Exporter;
+ @ISA = qw(Exporter);
+ @EXPORT = qw(
+ &recordpayment &makepayment &manualinvoice
+ &getnextacctno &reconcileaccount &getcharges &getcredits
+ &getrefunds &chargelostitem
+ ); # removed &fixaccounts
+}
+
+=head1 NAME
+
+C4::Accounts - Functions for dealing with Koha accounts
+
+=head1 SYNOPSIS
+
+use C4::Accounts;
+
+=head1 DESCRIPTION
+
+The functions in this module deal with the monetary aspect of Koha,
+including looking up and modifying the amount of money owed by a
+patron.
+
+=head1 FUNCTIONS
+
+=head2 recordpayment
+
+ &recordpayment($borrowernumber, $payment);
+
+Record payment by a patron. C<$borrowernumber> is the patron's
+borrower number. C<$payment> is a floating-point number, giving the
+amount that was paid.
+
+Amounts owed are paid off oldest first. That is, if the patron has a
+$1 fine from Feb. 1, another $1 fine from Mar. 1, and makes a payment
+of $1.50, then the oldest fine will be paid off in full, and $0.50
+will be credited to the next one.
+
+=cut
+
+#'
+sub recordpayment {
+
+ #here we update the account lines
+ my ( $borrowernumber, $data ) = @_;
+ my $dbh = C4::Context->dbh;
+ my $newamtos = 0;
+ my $accdata = "";
+ my $branch = C4::Context->userenv->{'branch'};
+ my $amountleft = $data;
+
+ # begin transaction
+ my $nextaccntno = getnextacctno($borrowernumber);
+
+ # get lines with outstanding amounts to offset
+ my $sth = $dbh->prepare(
+ "SELECT * FROM accountlines
+ WHERE (borrowernumber = ?) AND (amountoutstanding<>0)
+ ORDER BY date"
+ );
+ $sth->execute($borrowernumber);
+
+ # offset transactions
+ while ( ( $accdata = $sth->fetchrow_hashref ) and ( $amountleft > 0 ) ) {
+ if ( $accdata->{'amountoutstanding'} < $amountleft ) {
+ $newamtos = 0;
+ $amountleft -= $accdata->{'amountoutstanding'};
+ }
+ else {
+ $newamtos = $accdata->{'amountoutstanding'} - $amountleft;
+ $amountleft = 0;
+ }
+ my $thisacct = $accdata->{accountno};
+ my $usth = $dbh->prepare(
+ "UPDATE accountlines SET amountoutstanding= ?
+ WHERE (borrowernumber = ?) AND (accountno=?)"
+ );
+ $usth->execute( $newamtos, $borrowernumber, $thisacct );
+ $usth->finish;
+# $usth = $dbh->prepare(
+# "INSERT INTO accountoffsets
+# (borrowernumber, accountno, offsetaccount, offsetamount)
+# VALUES (?,?,?,?)"
+# );
+# $usth->execute( $borrowernumber, $accdata->{'accountno'},
+# $nextaccntno, $newamtos );
+ $usth->finish;
+ }
+
+ # create new line
+ my $usth = $dbh->prepare(
+ "INSERT INTO accountlines
+ (borrowernumber, accountno,date,amount,description,accounttype,amountoutstanding)
+ VALUES (?,?,now(),?,'Payment,thanks','Pay',?)"
+ );
+ $usth->execute( $borrowernumber, $nextaccntno, 0 - $data, 0 - $amountleft );
+ $usth->finish;
+ UpdateStats( $branch, 'payment', $data, '', '', '', $borrowernumber, $nextaccntno );
+ $sth->finish;
+}
+
+=head2 makepayment
+
+ &makepayment($borrowernumber, $acctnumber, $amount, $branchcode);
+
+Records the fact that a patron has paid off the entire amount he or
+she owes.
+
+C<$borrowernumber> is the patron's borrower number. C<$acctnumber> is
+the account that was credited. C<$amount> is the amount paid (this is
+only used to record the payment. It is assumed to be equal to the
+amount owed). C<$branchcode> is the code of the branch where payment
+was made.
+
+=cut
+
+#'
+# FIXME - I'm not at all sure about the above, because I don't
+# understand what the acct* tables in the Koha database are for.
+sub makepayment {
+
+ #here we update both the accountoffsets and the account lines
+ #updated to check, if they are paying off a lost item, we return the item
+ # from their card, and put a note on the item record
+ my ( $borrowernumber, $accountno, $amount, $user, $branch ) = @_;
+ my $dbh = C4::Context->dbh;
+
+ # begin transaction
+ my $nextaccntno = getnextacctno($borrowernumber);
+ my $newamtos = 0;
+ my $sth =
+ $dbh->prepare(
+ "SELECT * FROM accountlines WHERE borrowernumber=? AND accountno=?");
+ $sth->execute( $borrowernumber, $accountno );
+ my $data = $sth->fetchrow_hashref;
+ $sth->finish;
+
+ $dbh->do(
+ "UPDATE accountlines
+ SET amountoutstanding = 0
+ WHERE borrowernumber = $borrowernumber
+ AND accountno = $accountno
+ "
+ );
+
+ # print $updquery;
+# $dbh->do( "
+# INSERT INTO accountoffsets
+# (borrowernumber, accountno, offsetaccount,
+# offsetamount)
+# VALUES ($borrowernumber, $accountno, $nextaccntno, $newamtos)
+# " );
+
+ # create new line
+ my $payment = 0 - $amount;
+ $dbh->do( "
+ INSERT INTO accountlines
+ (borrowernumber, accountno, date, amount,
+ description, accounttype, amountoutstanding)
+ VALUES ($borrowernumber, $nextaccntno, now(), $payment,
+ 'Payment,thanks - $user', 'Pay', 0)
+ " );
+
+ # FIXME - The second argument to &UpdateStats is supposed to be the
+ # branch code.
+ # UpdateStats is now being passed $accountno too. MTJ
+ UpdateStats( $user, 'payment', $amount, '', '', '', $borrowernumber,
+ $accountno );
+ $sth->finish;
+
+ #check to see what accounttype
+ if ( $data->{'accounttype'} eq 'Rep' || $data->{'accounttype'} eq 'L' ) {
+ returnlost( $borrowernumber, $data->{'itemnumber'} );
+ }
+}
+
+=head2 getnextacctno
+
+ $nextacct = &getnextacctno($borrowernumber);
+
+Returns the next unused account number for the patron with the given
+borrower number.
+
+=cut
+
+#'
+# FIXME - Okay, so what does the above actually _mean_?
+sub getnextacctno ($) {
+ my ($borrowernumber) = shift or return undef;
+ my $sth = C4::Context->dbh->prepare(
+ "SELECT accountno+1 FROM accountlines
+ WHERE (borrowernumber = ?)
+ ORDER BY accountno DESC
+ LIMIT 1"
+ );
+ $sth->execute($borrowernumber);
+ return ($sth->fetchrow || 1);
+}
+
+=head2 fixaccounts (removed)
+
+ &fixaccounts($borrowernumber, $accountnumber, $amount);
+
+#'
+# FIXME - I don't understand what this function does.
+sub fixaccounts {
+ my ( $borrowernumber, $accountno, $amount ) = @_;
+ my $dbh = C4::Context->dbh;
+ my $sth = $dbh->prepare(
+ "SELECT * FROM accountlines WHERE borrowernumber=?
+ AND accountno=?"
+ );
+ $sth->execute( $borrowernumber, $accountno );
+ my $data = $sth->fetchrow_hashref;
+
+ # FIXME - Error-checking
+ my $diff = $amount - $data->{'amount'};
+ my $outstanding = $data->{'amountoutstanding'} + $diff;
+ $sth->finish;
+
+ $dbh->do(<<EOT);
+ UPDATE accountlines
+ SET amount = '$amount',
+ amountoutstanding = '$outstanding'
+ WHERE borrowernumber = $borrowernumber
+ AND accountno = $accountno
+EOT
+ # FIXME: exceedingly bad form. Use prepare with placholders ("?") in query and execute args.
+}
+
+=cut
+
+sub returnlost{
+ my ( $borrowernumber, $itemnum ) = @_;
+ C4::Circulation::MarkIssueReturned( $borrowernumber, $itemnum );
+ my $borrower = C4::Members::GetMember( $borrowernumber, 'borrowernumber' );
+ my @datearr = localtime(time);
+ my $date = ( 1900 + $datearr[5] ) . "-" . ( $datearr[4] + 1 ) . "-" . $datearr[3];
+ my $bor = "$borrower->{'firstname'} $borrower->{'surname'} $borrower->{'cardnumber'}";
+ ModItem({ paidfor => "Paid for by $bor $date" }, undef, $itemnum);
+}
+
+
+sub chargelostitem{
+# http://wiki.koha.org/doku.php?id=en:development:kohastatuses
+# lost ==1 Lost, lost==2 longoverdue, lost==3 lost and paid for
+# FIXME: itemlost should be set to 3 after payment is made, should be a warning to the interface that
+# a charge has been added
+# FIXME : if no replacement price, borrower just doesn't get charged?
+
+ my $dbh = C4::Context->dbh();
+ my ($itemnumber) = @_;
+ my $sth=$dbh->prepare("SELECT * FROM issues, items WHERE issues.itemnumber=items.itemnumber and issues.itemnumber=?");
+ $sth->execute($itemnumber);
+ my $issues=$sth->fetchrow_hashref();
+
+ # if a borrower lost the item, add a replacement cost to the their record
+ if ( $issues->{borrowernumber} ){
+
+ # first make sure the borrower hasn't already been charged for this item
+ my $sth1=$dbh->prepare("SELECT * from accountlines
+ WHERE borrowernumber=? AND itemnumber=? and accounttype='L'");
+ $sth1->execute($issues->{'borrowernumber'},$itemnumber);
+ my $existing_charge_hashref=$sth1->fetchrow_hashref();
+
+ # OK, they haven't
+ unless ($existing_charge_hashref) {
+ # This item is on issue ... add replacement cost to the borrower's record and mark it returned
+ # Note that we add this to the account even if there's no replacement price, allowing some other
+ # process (or person) to update it, since we don't handle any defaults for replacement prices.
+ my $accountno = getnextacctno($issues->{'borrowernumber'});
+ my $sth2=$dbh->prepare("INSERT INTO accountlines
+ (borrowernumber,accountno,date,amount,description,accounttype,amountoutstanding,itemnumber)
+ VALUES (?,?,now(),?,?,'L',?,?)");
+ $sth2->execute($issues->{'borrowernumber'},$accountno,$issues->{'replacementprice'},
+ "Lost Item $issues->{'title'} $issues->{'barcode'}",
+ $issues->{'replacementprice'},$itemnumber);
+ $sth2->finish;
+ # FIXME: Log this ?
+ }
+ #FIXME : Should probably have a way to distinguish this from an item that really was returned.
+ warn " $issues->{'borrowernumber'} / $itemnumber ";
+ C4::Circulation::MarkIssueReturned($issues->{borrowernumber},$itemnumber);
+ # Shouldn't MarkIssueReturned do this?
+ ModItem({ onloan => undef }, undef, $itemnumber);
+ }
+ $sth->finish;