diff options
Diffstat (limited to 'FS')
-rw-r--r-- | FS/FS.pm | 6 | ||||
-rw-r--r-- | FS/FS/cust_bill_pay.pm | 69 | ||||
-rw-r--r-- | FS/FS/cust_credit_bill.pm | 2 | ||||
-rw-r--r-- | FS/FS/cust_credit_refund.pm | 58 | ||||
-rw-r--r-- | FS/FS/cust_pay.pm | 20 | ||||
-rw-r--r-- | FS/FS/cust_pay_refund.pm | 187 | ||||
-rw-r--r-- | FS/FS/cust_refund.pm | 105 | ||||
-rw-r--r-- | FS/MANIFEST | 2 | ||||
-rwxr-xr-x | FS/bin/freeside-setup | 15 | ||||
-rw-r--r-- | FS/t/cust_pay_refund.t | 5 |
10 files changed, 330 insertions, 139 deletions
@@ -122,9 +122,11 @@ L<FS::cust_credit> - Credit class L<FS::cust_refund> - Refund class -L<FS::cust_credit_refund> - Refund application class +L<FS::cust_credit_refund> - Refund application to credit class -L<FS::cust_credit_bill> - Credit invoice application class +L<FS::cust_credit_bill> - Credit application to invoice class + +L<FS::cust_pay_refund> - Refund application to payment class L<FS::cust_pay_batch> - Credit card transaction queue class diff --git a/FS/FS/cust_bill_pay.pm b/FS/FS/cust_bill_pay.pm index c8b5525ea..f0cb13296 100644 --- a/FS/FS/cust_bill_pay.pm +++ b/FS/FS/cust_bill_pay.pm @@ -74,60 +74,11 @@ otherwise returns false. sub insert { my $self = shift; - - local $SIG{HUP} = 'IGNORE'; - local $SIG{INT} = 'IGNORE'; - local $SIG{QUIT} = 'IGNORE'; - local $SIG{TERM} = 'IGNORE'; - local $SIG{TSTP} = 'IGNORE'; - local $SIG{PIPE} = 'IGNORE'; - - my $oldAutoCommit = $FS::UID::AutoCommit; - local $FS::UID::AutoCommit = 0; - my $dbh = dbh; - - my $error = $self->check; + my $error = $self->SUPER::insert; return $error if $error; - $error = $self->SUPER::insert; - - my $cust_pay = qsearchs('cust_pay', { 'paynum' => $self->paynum } ) or do { - $dbh->rollback if $oldAutoCommit; - return "unknown cust_pay.paynum: ". $self->paynum; - }; - - my $pay_total = 0; - $pay_total += $_ foreach map { $_->amount } - qsearch('cust_bill_pay', { 'paynum' => $self->paynum } ); - - if ( sprintf("%.2f", $pay_total) > sprintf("%.2f", $cust_pay->paid) ) { - $dbh->rollback if $oldAutoCommit; - return "total cust_bill_pay.amount $pay_total for paynum ". $self->paynum. - " greater than cust_pay.paid ". $cust_pay->paid; - } - - my $cust_bill = $self->cust_bill; - unless ( $cust_bill ) { - $dbh->rollback if $oldAutoCommit; - return "unknown cust_bill.invnum: ". $self->invnum; - }; - - my $bill_total = 0; - $bill_total += $_ foreach map { $_->amount } - qsearch('cust_bill_pay', { 'invnum' => $self->invnum } ); - $bill_total += $_ foreach map { $_->amount } - qsearch('cust_credit_bill', { 'invnum' => $self->invnum } ); - if ( sprintf("%.2f", $bill_total) > sprintf("%.2f", $cust_bill->charged) ) { - $dbh->rollback if $oldAutoCommit; - return "total cust_bill_pay.amount and cust_credit_bill.amount $bill_total". - " for invnum ". $self->invnum. - " greater than cust_bill.charged ". $cust_bill->charged; - } - - $dbh->commit or die $dbh->errstr if $oldAutoCommit; - - if ( $conf->exists('invoice_send_receipts') ) { - my $send_error = $cust_bill->send; + if ( $conf->exists('invoice_send_receipts') ) { + my $send_error = $self->cust_bill->send; warn "Error sending receipt: $send_error\n" if $send_error; } @@ -178,9 +129,23 @@ sub check { return $error if $error; return "amount must be > 0" if $self->amount <= 0; + + return "Unknown invoice" + unless my $cust_bill = + qsearchs( 'cust_bill', { 'invnum' => $self->invnum } ); + + return "Unknown payment" + unless my $cust_pay = + qsearchs( 'cust_pay', { 'paynum' => $self->paynum } ); $self->_date(time) unless $self->_date; + return "Cannot apply more than remaining value of invoice" + unless $self->amount <= $cust_bill->owed; + + return "Cannot apply more than remaining value of payment" + unless $self->amount <= $cust_pay->unapplied; + $self->SUPER::check; } diff --git a/FS/FS/cust_credit_bill.pm b/FS/FS/cust_credit_bill.pm index bd76c2e1a..0e5885f57 100644 --- a/FS/FS/cust_credit_bill.pm +++ b/FS/FS/cust_credit_bill.pm @@ -38,7 +38,7 @@ FS::cust_credit_bill - Object methods for cust_credit_bill records =head1 DESCRIPTION An FS::cust_credit_bill object represents application of a credit (see -L<FS::cust_credit>) to an invoice (see L<FS::cust_bill>). FS::cust_credit +L<FS::cust_credit>) to an invoice (see L<FS::cust_bill>). FS::cust_credit_bill inherits from FS::Record. The following fields are currently supported: =over 4 diff --git a/FS/FS/cust_credit_refund.pm b/FS/FS/cust_credit_refund.pm index d0deae2f3..ff2454d9f 100644 --- a/FS/FS/cust_credit_refund.pm +++ b/FS/FS/cust_credit_refund.pm @@ -70,43 +70,9 @@ otherwise returns false. sub insert { my $self = shift; - - local $SIG{HUP} = 'IGNORE'; - local $SIG{INT} = 'IGNORE'; - local $SIG{QUIT} = 'IGNORE'; - local $SIG{TERM} = 'IGNORE'; - local $SIG{TSTP} = 'IGNORE'; - local $SIG{PIPE} = 'IGNORE'; - - my $oldAutoCommit = $FS::UID::AutoCommit; - local $FS::UID::AutoCommit = 0; - my $dbh = dbh; - - my $error = $self->check; + my $error = $self->SUPER::insert; return $error if $error; - $error = $self->SUPER::insert; - - my $cust_refund = - qsearchs('cust_refund', { 'refundnum' => $self->refundnum } ) - or do { - $dbh->rollback if $oldAutoCommit; - return "unknown cust_refund.refundnum: ". $self->refundnum - }; - - my $refund_total = 0; - $refund_total += $_ foreach map { $_->amount } - qsearch('cust_credit_refund', { 'refundnum' => $self->refundnum } ); - - if ( $refund_total > $cust_refund->refund ) { - $dbh->rollback if $oldAutoCommit; - return "total cust_credit_refund.amount $refund_total for refundnum ". - $self->refundnum. - " greater than cust_refund.refund ". $cust_refund->refund; - } - - $dbh->commit or die $dbh->errstr if $oldAutoCommit; - ''; } @@ -132,8 +98,9 @@ sub replace { =item check -Checks all fields to make sure this is a valid payment. If there is an error, -returns the error, otherwise returns false. Called by the insert method. +Checks all fields to make sure this is a valid refund application. If there is +an error, returns the error, otherwise returns false. Called by the insert +method. =cut @@ -151,10 +118,21 @@ sub check { return "amount must be > 0" if $self->amount <= 0; + return "unknown cust_credit.crednum: ". $self->crednum + unless my $cust_credit = + qsearchs( 'cust_credit', { 'crednum' => $self->crednum } ); + + return "Unknown refund" + unless my $cust_refund = + qsearchs( 'cust_refund', { 'refundnum' => $self->refundnum } ); + $self->_date(time) unless $self->_date; - return "unknown cust_credit.crednum: ". $self->crednum - unless qsearchs( 'cust_credit', { 'crednum' => $self->crednum } ); + return "Cannot apply more than remaining value of credit" + unless $self->amount <= $cust_credit->credited; + + return "Cannot apply more than remaining value of refund" + unless $self->amount <= $cust_refund->unapplied; $self->SUPER::check; } @@ -185,7 +163,7 @@ sub cust_credit { =head1 VERSION -$Id: cust_credit_refund.pm,v 1.10 2003-08-05 00:20:41 khoff Exp $ +$Id: cust_credit_refund.pm,v 1.11 2004-06-29 04:02:44 ivan Exp $ =head1 BUGS diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm index ba9924f99..111de05da 100644 --- a/FS/FS/cust_pay.pm +++ b/FS/FS/cust_pay.pm @@ -9,6 +9,7 @@ use FS::Record qw( dbh qsearch qsearchs dbh ); use FS::Misc qw(send_email); use FS::cust_bill; use FS::cust_bill_pay; +use FS::cust_pay_refund; use FS::cust_main; @ISA = qw( FS::Record ); @@ -371,10 +372,26 @@ sub cust_bill_pay { ; } +=item cust_pay_refund + +Returns all applications of refunds (see L<FS::cust_pay_refund>) to this +payment. + +=cut + +sub cust_pay_refund { + my $self = shift; + sort { $a->_date <=> $b->_date } + qsearch( 'cust_pay_refund', { 'paynum' => $self->paynum } ) + ; +} + + =item unapplied Returns the amount of this payment that is still unapplied; which is -paid minus all payment applications (see L<FS::cust_bill_pay>). +paid minus all payment applications (see L<FS::cust_bill_pay>) and refund +applications (see L<FS::cust_pay_refund>). =cut @@ -382,6 +399,7 @@ sub unapplied { my $self = shift; my $amount = $self->paid; $amount -= $_->amount foreach ( $self->cust_bill_pay ); + $amount -= $_->amount foreach ( $self->cust_pay_refund ); sprintf("%.2f", $amount ); } diff --git a/FS/FS/cust_pay_refund.pm b/FS/FS/cust_pay_refund.pm new file mode 100644 index 000000000..55a5eb778 --- /dev/null +++ b/FS/FS/cust_pay_refund.pm @@ -0,0 +1,187 @@ +package FS::cust_pay_refund; + +use strict; +use vars qw( @ISA ); #$conf ); +use FS::UID qw( getotaker ); +use FS::Record qw( qsearchs ); # qsearch ); +use FS::cust_main; +use FS::cust_pay; +use FS::cust_refund; + +@ISA = qw( FS::Record ); + +#ask FS::UID to run this stuff for us later +#FS::UID->install_callback( sub { +# $conf = new FS::Conf; +#} ); + +=head1 NAME + +FS::cust_pay_refund - Object methods for cust_pay_refund records + +=head1 SYNOPSIS + + use FS::cust_pay_refund; + + $record = new FS::cust_pay_refund \%hash; + $record = new FS::cust_pay_refund { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::cust_pay_refund object represents application of a refund (see +L<FS::cust_refund>) to an payment (see L<FS::cust_pay>). FS::cust_pay_refund +inherits from FS::Record. The following fields are currently supported: + +=over 4 + +=item payrefundnum - primary key + +=item paynum - credit being applied + +=item refundnum - invoice to which credit is applied (see L<FS::cust_bill>) + +=item amount - amount of the credit applied + +=item _date - specified as a UNIX timestamp; see L<perlfunc/"time">. Also see +L<Time::Local> and L<Date::Parse> for conversion functions. + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new cust_pay_refund. To add the cust_pay_refund to the database, +see L<"insert">. + +=cut + +sub table { 'cust_pay_refund'; } + +=item insert + +Adds this cust_pay_refund to the database. If there is an error, returns the +error, otherwise returns false. + +=cut + +sub insert { + my $self = shift; + my $error = $self->SUPER::insert(@_); + return $error if $error; + + ''; +} + +=item delete + +=cut + +sub delete { + my $self = shift; + return "Can't apply refund to closed payment" + if $self->cust_pay->closed =~ /^Y/i; + return "Can't apply closed refund" + if $self->cust_refund->closed =~ /^Y/i; + $self->SUPER::delete(@_); +} + +=item replace OLD_RECORD + +Application of refunds to payments may not be modified. + +=cut + +sub replace { + return "Can't modify application of a refund to payment!" +} + +=item check + +Checks all fields to make sure this is a valid refund application to a payment. +If there is an error, returns the error, otherwise returns false. Called by +the insert and replace methods. + +=cut + +sub check { + my $self = shift; + + my $error = + $self->ut_numbern('payrefundnum') + || $self->ut_number('paynum') + || $self->ut_number('refundnum') + || $self->ut_numbern('_date') + || $self->ut_money('amount') + ; + return $error if $error; + + return "amount must be > 0" if $self->amount <= 0; + + return "Unknown payment" + unless my $cust_pay = + qsearchs( 'cust_pay', { 'paynum' => $self->paynum } ); + + return "Unknown refund" + unless my $cust_refund = + qsearchs( 'cust_refund', { 'refundnum' => $self->refundnum } ); + + $self->_date(time) unless $self->_date; + + return 'Cannot apply ($'. $self->amount. ') more than'. + ' remaining value of refund ($'. $cust_refund->unapplied. ')' + unless $self->amount <= $cust_refund->unapplied; + + return "Cannot apply more than remaining value of payment" + unless $self->amount <= $cust_pay->unapplied; + + $self->SUPER::check; +} + +=item sub cust_credit + +Returns the credit (see L<FS::cust_credit>) + +=cut + +sub cust_credit { + my $self = shift; + qsearchs( 'cust_credit', { 'crednum' => $self->crednum } ); +} + +=item cust_bill + +Returns the invoice (see L<FS::cust_bill>) + +=cut + +sub cust_bill { + my $self = shift; + qsearchs( 'cust_bill', { 'invnum' => $self->invnum } ); +} + +=back + +=head1 BUGS + +The delete method. + +=head1 SEE ALSO + +L<FS::Record>, L<FS::cust_refund>, L<FS::cust_bill>, L<FS::cust_credit>, +schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/cust_refund.pm b/FS/FS/cust_refund.pm index d60c01061..b9f48db5c 100644 --- a/FS/FS/cust_refund.pm +++ b/FS/FS/cust_refund.pm @@ -3,10 +3,11 @@ package FS::cust_refund; use strict; use vars qw( @ISA ); use Business::CreditCard; -use FS::Record qw( qsearchs dbh ); +use FS::Record qw( qsearch qsearchs dbh ); use FS::UID qw(getotaker); use FS::cust_credit; use FS::cust_credit_refund; +use FS::cust_pay_refund; use FS::cust_main; @ISA = qw( FS::Record ); @@ -78,7 +79,9 @@ Adds this refund to the database. For backwards-compatibility and convenience, if the additional field crednum is defined, an FS::cust_credit_refund record for the full amount of the refund -will be created. In this case, custnum is optional. +will be created. Or (this time for convenience and consistancy), if the +additional field paynum is defined, an FS::cust_pay_refund record for the full +amount of the refund will be created. In both cases, custnum is optional. =cut @@ -103,6 +106,13 @@ sub insert { return "Unknown cust_credit.crednum: ". $self->crednum; }; $self->custnum($cust_credit->custnum); + } elsif ( $self->paynum ) { + my $cust_pay = qsearchs('cust_pay', { 'paynum' => $self->paynum } ) + or do { + $dbh->rollback if $oldAutoCommit; + return "Unknown cust_pay.paynum: ". $self->paynum; + }; + $self->custnum($cust_pay->custnum); } my $error = $self->check; @@ -127,57 +137,20 @@ sub insert { return $error; } #$self->custnum($cust_credit_refund->cust_credit->custnum); - } - - - $dbh->commit or die $dbh->errstr if $oldAutoCommit; - - ''; - -} - -sub upgrade_replace { #1.3.x->1.4.x - my $self = shift; - - local $SIG{HUP} = 'IGNORE'; - local $SIG{INT} = 'IGNORE'; - local $SIG{QUIT} = 'IGNORE'; - local $SIG{TERM} = 'IGNORE'; - local $SIG{TSTP} = 'IGNORE'; - local $SIG{PIPE} = 'IGNORE'; - - my $oldAutoCommit = $FS::UID::AutoCommit; - local $FS::UID::AutoCommit = 0; - my $dbh = dbh; - - my $error = $self->check; - return $error if $error; - - my %new = $self->hash; - my $new = FS::cust_refund->new(\%new); - - if ( $self->crednum ) { - my $cust_credit_refund = new FS::cust_credit_refund { - 'crednum' => $self->crednum, + } elsif ( $self->paynum ) { + my $cust_pay_refund = new FS::cust_pay_refund { + 'paynum' => $self->paynum, 'refundnum' => $self->refundnum, 'amount' => $self->refund, '_date' => $self->_date, }; - $error = $cust_credit_refund->insert; + $error = $cust_pay_refund->insert; if ( $error ) { $dbh->rollback if $oldAutoCommit; return $error; } - $new->custnum($cust_credit_refund->cust_credit->custnum); - } else { - die; } - $error = $new->SUPER::replace($self); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return $error; - } $dbh->commit or die $dbh->errstr if $oldAutoCommit; @@ -263,6 +236,52 @@ sub check { $self->SUPER::check; } +=item cust_credit_refund + +Returns all applications to credits (see L<FS::cust_credit_refund>) for this +refund. + +=cut + +sub cust_credit_refund { + my $self = shift; + sort { $a->_date <=> $b->_date } + qsearch( 'cust_credit_refund', { 'refundnum' => $self->refundnum } ) + ; +} + +=item cust_pay_refund + +Returns all applications to payments (see L<FS::cust_pay_refund>) for this +refund. + +=cut + +sub cust_pay_refund { + my $self = shift; + sort { $a->_date <=> $b->_date } + qsearch( 'cust_pay_refund', { 'refundnum' => $self->refundnum } ) + ; +} + +=item unapplied + +Returns the amount of this refund that is still unapplied; which is +amount minus all credit applications (see L<FS::cust_credit_refund>) and +payment applications (see L<FS::cust_pay_refund>). + +=cut + +sub unapplied { + my $self = shift; + my $amount = $self->refund; + $amount -= $_->amount foreach ( $self->cust_credit_refund ); + $amount -= $_->amount foreach ( $self->cust_pay_refund ); + sprintf("%.2f", $amount ); +} + + + =item payinfo_masked Returns a "masked" payinfo field with all but the last four characters replaced diff --git a/FS/MANIFEST b/FS/MANIFEST index 24fc1d1bc..4e78e7220 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -59,6 +59,7 @@ FS/cust_pay.pm FS/cust_bill_event.pm FS/cust_bill_pay.pm FS/cust_pay_batch.pm +FS/cust_pay_refund.pm FS/cust_pkg.pm FS/cust_refund.pm FS/cust_credit_refund.pm @@ -148,6 +149,7 @@ t/cust_main_county.t t/cust_main_invoice.t t/cust_pay.t t/cust_pay_batch.t +t/cust_pay_refund.t t/cust_pkg.t t/cust_refund.t t/cust_svc.t diff --git a/FS/bin/freeside-setup b/FS/bin/freeside-setup index 522c0a1a2..33b3465e0 100755 --- a/FS/bin/freeside-setup +++ b/FS/bin/freeside-setup @@ -1115,6 +1115,21 @@ sub tables_hash_hack { 'index' => [], }, + 'cust_pay_refund' => { + 'columns' => [ + 'payrefundnum', 'serial', '', '', + 'paynum', 'int', '', '', + 'refundnum', 'int', '', '', + '_date', @date_type, + 'amount', @money_type, + ], + 'primary_key' => 'payrefundnum', + 'unique' => [], + 'index' => [ ['paynum'], ['refundnum'] ], + }, + + + ); %tables; diff --git a/FS/t/cust_pay_refund.t b/FS/t/cust_pay_refund.t new file mode 100644 index 000000000..85d6c2316 --- /dev/null +++ b/FS/t/cust_pay_refund.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::cust_pay_refund; +$loaded=1; +print "ok 1\n"; |