X-Git-Url: http://git.freeside.biz/gitweb/?a=blobdiff_plain;f=FS%2FFS%2Fcust_main%2FImport_Charges.pm;h=3d2031d45b1351fada216b60b445e0ff48e10c1a;hb=38f5c59a6a3b92881c0f60bc8dccc9acd0feef41;hp=312a6060ba14293fbd5550122682f290bfb1241e;hpb=c4e26585cdbd2cd086ed813a02b963ffccfebc55;p=freeside.git diff --git a/FS/FS/cust_main/Import_Charges.pm b/FS/FS/cust_main/Import_Charges.pm index 312a6060b..3d2031d45 100644 --- a/FS/FS/cust_main/Import_Charges.pm +++ b/FS/FS/cust_main/Import_Charges.pm @@ -4,11 +4,52 @@ package FS::cust_main::Import_Charges; # subroutine for misc/process/cust_main-import_charges.cgi use strict; -use Text::CSV_XS; use FS::UID qw( dbh ); use FS::CurrentUser; use FS::Record qw( qsearchs ); use FS::cust_main; +use FS::Conf; + +my $DEBUG = ''; + +my %import_charges_info; +foreach my $INC ( @INC ) { + warn "globbing $INC/FS/cust_main/import_charges/[a-z]*.pm\n" if $DEBUG; + foreach my $file ( glob("$INC/FS/cust_main/import_charges/[a-z]*.pm") ) { + warn "attempting to load import charges format info from $file\n" if $DEBUG; + $file =~ /\/(\w+)\.pm$/ or do { + warn "unrecognized file in $INC/FS/cust_main/import_charges/: $file\n"; + next; + }; + my $mod = $1; + my $info = eval "use FS::cust_main::import_charges::$mod; ". + "\\%FS::cust_main::import_charges::$mod\::info;"; + if ( $@ ) { + die "error using FS::cust_main::import_charges::$mod (skipping): $@\n" if $@; + next; + } + unless ( keys %$info ) { + warn "no %info hash found in FS::cust_main::import_charges::$mod, skipping\n"; + next; + } + warn "got import charges format info from FS::cust_main::import_charges::$mod: $info\n" if $DEBUG; + if ( exists($info->{'disabled'}) && $info->{'disabled'} ) { + warn "skipping disabled import charges format FS::cust_main::import_charges::$mod" if $DEBUG; + next; + } + $import_charges_info{$mod} = $info; + } +} + +tie my %import_formats, 'Tie::IxHash', + map { $_ => $import_charges_info{$_}->{'name'} } + sort { $import_charges_info{$a}->{'weight'} <=> $import_charges_info{$b}->{'weight'} } + grep { exists($import_charges_info{$_}->{'fields'}) } + keys %import_charges_info; + +sub import_formats { + %import_formats; +} =head1 NAME @@ -39,24 +80,69 @@ Batch customer charging. =cut sub batch_charge { + my $job = shift; my $param = shift; #warn join('-',keys %$param); - my $fh = $param->{filehandle}; my $agentnum = $param->{agentnum}; my $format = $param->{format}; + my $files = $param->{'uploaded_files'} + or die "No files provided.\n"; + + my (%files) = map { /^(\w+):([\.\w]+)$/ ? ($1,$2):() } split /,/, $files; + + my $dir = '%%%FREESIDE_CACHE%%%/cache.'. $FS::UID::datasrc. '/'; + my $filename = $dir. $files{'file'}; + + my $type; + if ( $filename =~ /\.(\w+)$/i ) { + $type = lc($1); + } else { + #or error out??? + warn "can't parse file type from filename $filename; defaulting to CSV"; + $type = 'csv'; + } + my $extra_sql = ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql; my @fields; - if ( $format eq 'simple' ) { - @fields = qw( custnum agent_custid amount pkg ); + my %charges; + + if ( $import_charges_info{$format} ) { + @fields = @{$import_charges_info{$format}->{'fields'}}; + %charges = %{$import_charges_info{$format}->{'charges'}}; } else { die "unknown format $format"; } - my $csv = new Text::CSV_XS; - #warn $csv; - #warn $fh; + my $count; + my $parser; + my @buffer = (); + + if ( $type eq 'csv' ) { + + eval "use Text::CSV_XS;"; + eval "use File::Slurp qw( slurp );"; + die $@ if $@; + + $parser = new Text::CSV_XS; + + @buffer = split(/\r?\n/, slurp($filename) ); + $count = scalar(@buffer); + + } elsif ( $type eq 'xls' ) { + eval "use Spreadsheet::ParseExcel;"; + die $@ if $@; + + my $excel = Spreadsheet::ParseExcel::Workbook->new->Parse($filename); + $parser = $excel->{Worksheet}[0]; #first sheet + + $count = $parser->{MaxRow} || $parser->{MinRow}; + $count++; + + } else { + die "Unknown file type $type\n"; + } my $imported = 0; #my $columns; @@ -71,17 +157,36 @@ sub batch_charge { my $oldAutoCommit = $FS::UID::AutoCommit; local $FS::UID::AutoCommit = 0; my $dbh = dbh; - - #while ( $columns = $csv->getline($fh) ) { + my $line; - while ( defined($line=<$fh>) ) { + my $row = 0; + my %data = (); + my( $last, $min_sec ) = ( time, 5 ); #progressbar foo + while (1) { + my @columns = (); - $csv->parse($line) or do { - $dbh->rollback if $oldAutoCommit; - return "can't parse: ". $csv->error_input(); - }; + if ( $type eq 'csv' ) { + + last unless scalar(@buffer); + $line = shift(@buffer); + + $parser->parse($line) or do { + $dbh->rollback if $oldAutoCommit; + return "can't parse: ". $parser->error_input(); + }; + @columns = $parser->fields(); + + } elsif ( $type eq 'xls' ) { + last if $row > ($parser->{MaxRow} || $parser->{MinRow}) + || ! $parser->{Cells}[$row]; + + my @row = @{ $parser->{Cells}[$row] }; + @columns = map $_->{Val}, @row; + + } else { + die "Unknown file type $type\n"; + } - my @columns = $csv->fields(); #warn join('-',@columns); my %row = (); @@ -94,14 +199,26 @@ sub batch_charge { return "can't specify custnum with agent_custid $row{agent_custid}"; } + my $id; my %hash = (); + if ( $row{agent_custid} && $agentnum ) { + $id = $row{agent_custid}; + $data{$id}{cust} = { + 'agent_custid' => $row{agent_custid}, + 'agentnum' => $agentnum, + }; %hash = ( 'agent_custid' => $row{agent_custid}, 'agentnum' => $agentnum, ); } if ( $row{custnum} ) { + $id = $row{custnum}; + $data{$id}{cust} = { + 'custnum' => $row{custnum}, + 'testnum' => 'test', + }; %hash = ( 'custnum' => $row{custnum} ); } @@ -110,40 +227,65 @@ sub batch_charge { return "can't find customer without custnum or agent_custid and agentnum"; } - my $cust_main = qsearchs('cust_main', { %hash } ); + ## add new pkg data or upate existing by adding new amount for custnum + $data{$id}{pkg}{$row{pkg}} = $data{$id}{pkg}{$row{pkg}} ? $data{$id}{pkg}{$row{pkg}} + $row{'amount'} : $row{'amount'}; + + $row++; + + if ( $job && time - $min_sec > $last ) { #progress bar + $job->update_statustext( int(100 * $row / $count) ); + $last = time; + } + + } + + ### run through data hash to post all charges. + foreach my $k (keys %data) { + my %pkg_hash = %{$data{$k}{pkg}}; + my %cust_hash = %{$data{$k}{cust}}; + + my $cust_main = qsearchs('cust_main', { %cust_hash } ); unless ( $cust_main ) { $dbh->rollback if $oldAutoCommit; - my $custnum = $row{custnum} || $row{agent_custid}; + my $custnum = $cust_hash{custnum} || $cust_hash{agent_custid}; return "unknown custnum $custnum"; } - if ( $row{'amount'} > 0 ) { - my $error = $cust_main->charge($row{'amount'}, $row{'pkg'}); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return $error; - } - $imported++; - } elsif ( $row{'amount'} < 0 ) { - my $error = $cust_main->credit( sprintf( "%.2f", 0-$row{'amount'} ), - $row{'pkg'} ); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return $error; - } - $imported++; - } else { + foreach my $pkg_key (keys %pkg_hash) { + my $pkg = $pkg_key; + my $amount = $pkg_hash{$pkg_key}; + + if (%charges) { next unless $charges{$pkg}; } + + if ( $amount > 0 ) { + my $error = $cust_main->charge($amount, $pkg); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + $imported++; + } elsif ( $amount < 0 ) { + my $error = $cust_main->credit( sprintf( "%.2f", 0-$amount ), $pkg ); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return $error; + } + $imported++; + } else { #hmm? + } } } $dbh->commit or die $dbh->errstr if $oldAutoCommit; + unlink $filename; + return "Empty file!" unless $imported; ''; #no error } -1; +1; \ No newline at end of file