From 0b4247f88f8a290a7bbbdebe93404baef2d1e29d Mon Sep 17 00:00:00 2001 From: jeff Date: Fri, 25 Jan 2008 18:29:04 +0000 Subject: [PATCH] simple payment CSV import --- FS/FS/cust_pay.pm | 146 ++++++++++++++++++++++++++++ httemplate/elements/menu.html | 2 + httemplate/misc/cust_pay-import.cgi | 62 ++++++++++++ httemplate/misc/process/cust_pay-import.cgi | 21 ++++ 4 files changed, 231 insertions(+) create mode 100644 httemplate/misc/cust_pay-import.cgi create mode 100644 httemplate/misc/process/cust_pay-import.cgi diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm index f969460a9..2b2e9442a 100644 --- a/FS/FS/cust_pay.pm +++ b/FS/FS/cust_pay.pm @@ -650,6 +650,152 @@ sub unapplied_sql { =back +=head1 SUBROUTINES + +=over 4 + +=item batch_import HASHREF + +Inserts new payments. + +=cut + +sub batch_import { + my $param = shift; + + my $fh = $param->{filehandle}; + my $agentnum = $param->{agentnum}; + my $format = $param->{'format'}; + my $paybatch = $param->{'paybatch'}; + + # here is the agent virtualization + my $extra_sql = ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql; + + my @fields; + my $payby; + if ( $format eq 'simple' ) { + @fields = qw( custnum agent_custid paid payinfo ); + $payby = 'BILL'; + } elsif ( $format eq 'extended' ) { + die "unimplemented\n"; + @fields = qw( ); + $payby = 'BILL'; + } else { + die "unknown format $format"; + } + + eval "use Text::CSV_XS;"; + die $@ if $@; + + my $csv = new Text::CSV_XS; + + my $imported = 0; + + 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 $line; + while ( defined($line=<$fh>) ) { + + $csv->parse($line) or do { + $dbh->rollback if $oldAutoCommit; + return "can't parse: ". $csv->error_input(); + }; + + my @columns = $csv->fields(); + + my %cust_pay = ( + payby => $payby, + paybatch => $paybatch, + ); + + my $cust_main; + foreach my $field ( @fields ) { + + if ( $field eq 'agent_custid' + && $agentnum + && $columns[0] =~ /\S+/ ) + { + + my $agent_custid = $columns[0]; + my %hash = ( 'agent_custid' => $agent_custid, + 'agentnum' => $agentnum, + ); + + if ( $cust_pay{'custnum'} !~ /^\s*$/ ) { + $dbh->rollback if $oldAutoCommit; + return "can't specify custnum with agent_custid $agent_custid"; + } + + $cust_main = qsearchs({ + 'table' => 'cust_main', + 'hashref' => \%hash, + 'extra_sql' => $extra_sql, + }); + + unless ( $cust_main ) { + $dbh->rollback if $oldAutoCommit; + return "can't find customer with agent_custid $agent_custid"; + } + + $field = 'custnum'; + $columns[0] = $cust_main->custnum; + } + + $cust_pay{$field} = shift @columns; + } + + my $cust_pay = new FS::cust_pay( \%cust_pay ); + my $error = $cust_pay->insert; + + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "can't insert payment for $line: $error"; + } + + if ( $format eq 'simple' ) { + # include agentnum for less surprise? + $cust_main = qsearchs({ + 'table' => 'cust_main', + 'hashref' => { 'custnum' => $cust_pay->custnum }, + 'extra_sql' => $extra_sql, + }) + unless $cust_main; + + unless ( $cust_main ) { + $dbh->rollback if $oldAutoCommit; + return "can't find customer to which payments apply at line: $line"; + } + + $error = $cust_main->apply_payments_and_credits; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "can't apply payments to customer for $line: $error"; + } + + } + + $imported++; + } + + $dbh->commit or die $dbh->errstr if $oldAutoCommit; + + return "Empty file!" unless $imported; + + ''; #no error + +} + +=back + =head1 BUGS Delete and replace methods. diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html index 8d56adcc3..f43fca1bb 100644 --- a/httemplate/elements/menu.html +++ b/httemplate/elements/menu.html @@ -216,6 +216,8 @@ $report_menu{'Financial'} = [ \%report_financial, 'Financial reports' ] tie my %tools_importing, 'Tie::IxHash', 'Import customers from CSV file' => [ $fsurl.'misc/cust_main-import.cgi', '' ], + 'Import payments from CSV file' => [ $fsurl.'misc/cust_pay-import.cgi', '' ], + 'Import customer comments from CSV file' => [ $fsurl.'misc/cust_main_note-import.html', '' ], 'Import one-time charges from CSV file' => [ $fsurl.'misc/cust_main-import_charges.cgi', '' ], 'Import Call Detail Records (CDRs) from CSV file' => [ $fsurl.'misc/cdr-import.html', '' ], diff --git a/httemplate/misc/cust_pay-import.cgi b/httemplate/misc/cust_pay-import.cgi new file mode 100644 index 000000000..849a25bea --- /dev/null +++ b/httemplate/misc/cust_pay-import.cgi @@ -0,0 +1,62 @@ +<% include("/elements/header.html",'Batch Payment Import') %> + +Import a CSV file containing customer payments. +

+ +
+ +<% &ntable("#cccccc", 2) %> + +<% include('/elements/tr-select-agent.html', + #'curr_value' => '', #$agentnum, + 'label' => "Agent", + 'empty_label' => 'Select agent', + ) +%> + + + Format + + + + + + + CSV filename + + + + + + + +
+ +
+ +Simple file format is CSV, with the following field order: custnum, agent_custid, amount, checknum +

+ + + +Field information: + + + +
+ +<% include('/elements/footer.html') %> diff --git a/httemplate/misc/process/cust_pay-import.cgi b/httemplate/misc/process/cust_pay-import.cgi new file mode 100644 index 000000000..d4ff226ec --- /dev/null +++ b/httemplate/misc/process/cust_pay-import.cgi @@ -0,0 +1,21 @@ +<% $cgi->redirect(popurl(3). "search/cust_pay.cgi?magic=paybatch;paybatch=$paybatch") %> +<%init> + +my $fh = $cgi->upload('csvfile'); + +# webbatch? I suppose +my $paybatch = time2str('webbatch-%Y/%m/%d-%T'. "-$$-". rand() * 2**32, time); + +my $error = defined($fh) + ? FS::cust_pay::batch_import( { + 'filehandle' => $fh, + 'agentnum' => scalar($cgi->param('agentnum')), + 'format' => scalar($cgi->param('format')), + 'paybatch' => $paybatch, + } ) + : 'No file'; + +errorpage($error) + if ( $error ); + + -- 2.11.0