From cfe85e45bcba97089988b4dc22a895aec687f2c3 Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 6 Jul 2004 13:26:21 +0000 Subject: [PATCH] add cust_pay_void table and payment voiding web ui part one --- FS/FS.pm | 2 + FS/FS/cust_pay.pm | 54 ++++++++++- FS/FS/cust_pay_void.pm | 196 ++++++++++++++++++++++++++++++++++++++ FS/bin/freeside-setup | 20 ++++ FS/t/cust_pay_void.t | 5 + README.1.5.0pre1 | 17 ---- README.1.5.0pre6 | 18 +++- httemplate/docs/schema.html | 14 +++ httemplate/docs/upgrade10.html | 18 +++- httemplate/misc/void-cust_pay.cgi | 16 ++++ 10 files changed, 336 insertions(+), 24 deletions(-) create mode 100644 FS/FS/cust_pay_void.pm create mode 100644 FS/t/cust_pay_void.t delete mode 100644 README.1.5.0pre1 create mode 100755 httemplate/misc/void-cust_pay.cgi diff --git a/FS/FS.pm b/FS/FS.pm index 67cb1f837..7c002fe3f 100644 --- a/FS/FS.pm +++ b/FS/FS.pm @@ -116,6 +116,8 @@ L - Completed invoice event class L - Payment class +L - Payment application class L - Credit class diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm index 799ceab51..3317a32bd 100644 --- a/FS/FS/cust_pay.pm +++ b/FS/FS/cust_pay.pm @@ -5,13 +5,13 @@ use vars qw( @ISA $conf $unsuspendauto ); use Date::Format; use Business::CreditCard; use Text::Template; -use FS::UID qw( dbh ); -use FS::Record qw( dbh qsearch qsearchs dbh ); +use FS::Record qw( dbh qsearch qsearchs ); use FS::Misc qw(send_email); use FS::cust_bill; use FS::cust_bill_pay; use FS::cust_pay_refund; use FS::cust_main; +use FS::cust_pay_void; @ISA = qw( FS::Record ); @@ -207,10 +207,54 @@ sub insert { } +=item void [ REASON ] + +Voids this payment: deletes the payment and all associated applications and +adds a record of the voided payment to the FS::cust_pay_void table. + +=cut + +sub void { + 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 $cust_pay_void = new FS::cust_pay_void ( { + map { $_ => $self->get($_) } $self->fields + } ); + $cust_pay_void->reason(shift) if scalar(@_); + my $error = $cust_pay_void->insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + $error = $self->delete; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + + ''; + +} + =item delete Deletes this payment and all associated applications (see L), -unless the closed flag is set. +unless the closed flag is set. In most cases, you want to use the void +method instead to leave a record of the deleted payment. =cut @@ -229,8 +273,8 @@ sub delete { local $FS::UID::AutoCommit = 0; my $dbh = dbh; - foreach my $cust_bill_pay ( $self->cust_bill_pay ) { - my $error = $cust_bill_pay->delete; + foreach my $app ( $self->cust_bill_pay, $self->cust_pay_refund ) { + my $error = $app->delete; if ( $error ) { $dbh->rollback if $oldAutoCommit; return $error; diff --git a/FS/FS/cust_pay_void.pm b/FS/FS/cust_pay_void.pm new file mode 100644 index 000000000..7267929c8 --- /dev/null +++ b/FS/FS/cust_pay_void.pm @@ -0,0 +1,196 @@ +package FS::cust_pay_void; +use strict; +use vars qw( @ISA ); +use Business::CreditCard; +use FS::UID qw(getotaker); +use FS::Record qw(qsearchs); # dbh qsearch ); +#use FS::cust_bill; +#use FS::cust_bill_pay; +#use FS::cust_pay_refund; +#use FS::cust_main; + +@ISA = qw( FS::Record ); + +=head1 NAME + +FS::cust_pay_void - Object methods for cust_pay_void objects + +=head1 SYNOPSIS + + use FS::cust_pay_void; + + $record = new FS::cust_pay_void \%hash; + $record = new FS::cust_pay_void { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::cust_pay_void object represents a voided payment. The following fields +are currently supported: + +=over 4 + +=item paynum - primary key (assigned automatically for new payments) + +=item custnum - customer (see L) + +=item paid - Amount of this payment + +=item _date - specified as a UNIX timestamp; see L. Also see +L and L for conversion functions. + +=item payby - `CARD' (credit cards), `CHEK' (electronic check/ACH), +`LECB' (phone bill billing), `BILL' (billing), or `COMP' (free) + +=item payinfo - card number, check #, or comp issuer (4-8 lowercase alphanumerics; think username), respectively + +=item paybatch - text field for tracking card processing + +=item closed - books closed flag, empty or `Y' + +=item void_date + +=item reason + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new payment. To add the payment to the databse, see L<"insert">. + +=cut + +sub table { 'cust_pay_void'; } + +=item insert + +Adds this voided payment to the database. + +=item delete + +Currently unimplemented. + +=cut + +sub delete { + return "Can't delete voided payments!"; +} + +=item replace OLD_RECORD + +Currently unimplemented. + +=cut + +sub replace { + return "Can't modify voided payments!"; +} + +=item check + +Checks all fields to make sure this is a valid voided payment. If there is an +error, returns the error, otherwise returns false. Called by the insert +method. + +=cut + +sub check { + my $self = shift; + + my $error = + $self->ut_numbern('paynum') + || $self->ut_numbern('custnum') + || $self->ut_money('paid') + || $self->ut_number('_date') + || $self->ut_textn('paybatch') + || $self->ut_enum('closed', [ '', 'Y' ]) + || $self->ut_numbern('void_date') + || $self->ut_textn('reason') + ; + return $error if $error; + + return "paid must be > 0 " if $self->paid <= 0; + + return "unknown cust_main.custnum: ". $self->custnum + unless $self->invnum + || qsearchs( 'cust_main', { 'custnum' => $self->custnum } ); + + $self->void_date(time) unless $self->void_date; + + $self->payby =~ /^(CARD|CHEK|LECB|BILL|COMP)$/ or return "Illegal payby"; + $self->payby($1); + + #false laziness with cust_refund::check + if ( $self->payby eq 'CARD' ) { + my $payinfo = $self->payinfo; + $payinfo =~ s/\D//g; + $self->payinfo($payinfo); + if ( $self->payinfo ) { + $self->payinfo =~ /^(\d{13,16})$/ + or return "Illegal (mistyped?) credit card number (payinfo)"; + $self->payinfo($1); + validate($self->payinfo) or return "Illegal credit card number"; + return "Unknown card type" if cardtype($self->payinfo) eq "Unknown"; + } else { + $self->payinfo('N/A'); + } + + } else { + $error = $self->ut_textn('payinfo'); + return $error if $error; + } + + $self->otaker(getotaker); + + $self->SUPER::check; +} + +=item cust_main + +Returns the parent customer object (see L). + +=cut + +sub cust_main { + my $self = shift; + qsearchs( 'cust_main', { 'custnum' => $self->custnum } ); +} + +=item payinfo_masked + +Returns a "masked" payinfo field with all but the last four characters replaced +by 'x'es. Useful for displaying credit cards. + +=cut + +sub payinfo_masked { + my $self = shift; + my $payinfo = $self->payinfo; + 'x'x(length($payinfo)-4). substr($payinfo,(length($payinfo)-4)); +} + +=back + +=head1 BUGS + +Delete and replace methods. + +=head1 SEE ALSO + +L, L, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/bin/freeside-setup b/FS/bin/freeside-setup index 33b3465e0..119b09d5d 100755 --- a/FS/bin/freeside-setup +++ b/FS/bin/freeside-setup @@ -552,6 +552,26 @@ sub tables_hash_hack { 'index' => [ [ 'custnum' ], [ 'paybatch' ], [ 'payby' ], [ '_date' ] ], }, + 'cust_pay_void' => { + 'columns' => [ + 'paynum', 'int', '', '', + 'custnum', 'int', '', '', + 'paid', @money_type, + '_date', @date_type, + 'payby', 'char', '', 4, # CARD/BILL/COMP, should be index into + # payment type table. + 'payinfo', 'varchar', 'NULL', $char_d, #see cust_main above + 'paybatch', 'varchar', 'NULL', $char_d, #for auditing purposes. + 'closed', 'char', 'NULL', 1, + 'void_date', @date_type, + 'reason', 'varchar', 'NULL', $char_d, + 'otaker', 'varchar', '', 32, + ], + 'primary_key' => 'paynum', + 'unique' => [], + 'index' => [ [ 'custnum' ] ], + }, + 'cust_bill_pay' => { 'columns' => [ 'billpaynum', 'serial', '', '', diff --git a/FS/t/cust_pay_void.t b/FS/t/cust_pay_void.t new file mode 100644 index 000000000..dca9becd1 --- /dev/null +++ b/FS/t/cust_pay_void.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::cust_pay_void; +$loaded=1; +print "ok 1\n"; diff --git a/README.1.5.0pre1 b/README.1.5.0pre1 deleted file mode 100644 index 0de86bce0..000000000 --- a/README.1.5.0pre1 +++ /dev/null @@ -1,17 +0,0 @@ -preliminary upgrade instructions - -schema changes: - *** get svc_broadband changes from pc-intouch - *** otaker changes s/8/32 all otkaer fields - *** optional: sequence changes - *** add column cust_main_county.taxname - *** add column cust_bill_pkg.itemdesc - *** drop index cust_bill_pkg1 - *** add index part_pkg1 and part_svc1 - -install DBIx::DBSchema 0.21 -install NetAddr::IP - -Run dbdef-create -something about history tables -Restart apache and freeside-queued diff --git a/README.1.5.0pre6 b/README.1.5.0pre6 index ba9129fab..bd5e39b94 100644 --- a/README.1.5.0pre6 +++ b/README.1.5.0pre6 @@ -9,7 +9,23 @@ CREATE TABLE cust_pay_refund ( CREATE INDEX cust_pay_refund1 ON cust_pay_refund(paynum); CREATE INDEX cust_pay_refund2 ON cust_pay_refund(refundnum); +CREATE TABLE cust_pay_void ( + paynum int NOT NULL, + custnum int NOT NULL, + paid decimal(10,2) NOT NULL, + _date int, + payby char(4) NOT NULL, + payinfo varchar(80), + paybatch varchar(80), + closed char(1), + void_date int, + reason varchar(80), + otaker varchar(32) NOT NULL, + PRIMARY KEY (paynum) +); +CREATE INDEX cust_pay_void1 ON cust_pay_void(custnum); + dbdef-create username -create-history-tables username cust_pay_refund +create-history-tables username cust_pay_refund cust_pay_void dbdef-create username diff --git a/httemplate/docs/schema.html b/httemplate/docs/schema.html index 8a27e0118..8dee8ad9e 100644 --- a/httemplate/docs/schema.html +++ b/httemplate/docs/schema.html @@ -176,6 +176,20 @@
  • paybatch - text field for tracking card processor batches
  • closed - books closed flag, empty or `Y' +
  • cust_pay_void - Voided payments. +
      +
    • paynum - primary key +
    • custnum - customer +
    • paid - amount +
    • _date +
    • payby - CARD, CHEK, LECB, BILL, or COMP +
    • payinfo - card number, P.O.#, or comp issuer +
    • paybatch - text field for tracking card processor batches +
    • closed - books closed flag, empty or `Y' +
    • void_date +
    • reason +
    • otaker - order taker +
  • cust_bill_pay - Applicaton of a payment to a specific invoice.
    • billpaynum diff --git a/httemplate/docs/upgrade10.html b/httemplate/docs/upgrade10.html index 1d099646f..8922d198f 100644 --- a/httemplate/docs/upgrade10.html +++ b/httemplate/docs/upgrade10.html @@ -162,6 +162,22 @@ CREATE TABLE cust_pay_refund ( CREATE INDEX cust_pay_refund1 ON cust_pay_refund(paynum); CREATE INDEX cust_pay_refund2 ON cust_pay_refund(refundnum); +CREATE TABLE cust_pay_void ( + paynum int NOT NULL, + custnum int NOT NULL, + paid decimal(10,2) NOT NULL, + _date int, + payby char(4) NOT NULL, + payinfo varchar(80), + paybatch varchar(80), + closed char(1), + void_date int, + reason varchar(80), + otaker varchar(32) NOT NULL, + PRIMARY KEY (paynum) +); +CREATE INDEX cust_pay_void1 ON cust_pay_void(custnum); + DROP INDEX cust_bill_pkg1; ALTER TABLE cust_bill_pkg ADD itemdesc varchar(80) NULL; @@ -228,7 +244,7 @@ optionally: mandatory again: dbdef-create username -create-history-tables username cust_bill_pkg_detail router part_svc_router addr_block svc_broadband acct_snarf svc_external +create-history-tables username cust_bill_pkg_detail router part_svc_router addr_block svc_broadband acct_snarf svc_external cust_pay_refund cust_pay_void dbdef-create username apache - fix sections to include .html also diff --git a/httemplate/misc/void-cust_pay.cgi b/httemplate/misc/void-cust_pay.cgi new file mode 100755 index 000000000..4eec60892 --- /dev/null +++ b/httemplate/misc/void-cust_pay.cgi @@ -0,0 +1,16 @@ +<% + +#untaint paynum +my($query) = $cgi->keywords; +$query =~ /^(\d+)$/ || die "Illegal paynum"; +my $paynum = $1; + +my $cust_pay = qsearchs('cust_pay',{'paynum'=>$paynum}); +my $custnum = $cust_pay->custnum; + +my $error = $cust_pay->void; +eidiot($error) if $error; + +print $cgi->redirect($p. "view/cust_main.cgi?". $custnum); + +%> -- 2.11.0