diff options
author | Christopher Burger <burgerc@freeside.biz> | 2017-09-07 08:49:34 -0400 |
---|---|---|
committer | Christopher Burger <burgerc@freeside.biz> | 2017-09-08 13:15:07 -0400 |
commit | 321a2e69b5ab89ebf3e2d6b711b2a21126b28ff8 (patch) | |
tree | fd6944343bc802573b0a0cef4ff4e6bb750041ef /FS | |
parent | d2d82863f354790d1eb3ee1d3b193d2e423ae8d0 (diff) |
RT# 77167 - Added the ability to import a list of contacts
Conflicts:
httemplate/elements/menu.html
Diffstat (limited to 'FS')
-rw-r--r-- | FS/FS/Mason.pm | 1 | ||||
-rw-r--r-- | FS/FS/contact/Import.pm | 161 | ||||
-rw-r--r-- | FS/FS/contact_import.pm | 164 |
3 files changed, 326 insertions, 0 deletions
diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm index 60e377953..f50192c13 100644 --- a/FS/FS/Mason.pm +++ b/FS/FS/Mason.pm @@ -266,6 +266,7 @@ if ( -e $addl_handler_use_file ) { use FS::cust_category; use FS::prospect_main; use FS::contact; + use FS::contact::Import; use FS::phone_type; use FS::svc_pbx; use FS::discount; diff --git a/FS/FS/contact/Import.pm b/FS/FS/contact/Import.pm new file mode 100644 index 000000000..26bdcfa6e --- /dev/null +++ b/FS/FS/contact/Import.pm @@ -0,0 +1,161 @@ +package FS::contact::Import; + +use strict; +use vars qw( $DEBUG ); #$conf ); +use Data::Dumper; +use FS::Misc::DateTime qw( parse_datetime ); +use FS::Record qw( qsearchs ); +use FS::contact; +use FS::cust_main; + +$DEBUG = 0; + +=head1 NAME + +FS::contact::Import - Batch contact importing + +=head1 SYNOPSIS + + use FS::contact::Import; + + #import + FS::contact::Import::batch_import( { + file => $file, #filename + type => $type, #csv or xls + format => $format, #default + agentnum => $agentnum, + job => $job, #optional job queue job, for progressbar updates + pkgbatch => $pkgbatch, #optional batch unique identifier + } ); + die $error if $error; + + #ajax helper + use FS::UI::Web::JSRPC; + my $server = + new FS::UI::Web::JSRPC 'FS::contact::Import::process_batch_import', $cgi; + print $server->process; + +=head1 DESCRIPTION + +Batch contact importing. + +=head1 SUBROUTINES + +=item process_batch_import + +Load a batch import as a queued JSRPC job + +=cut + +sub process_batch_import { + my $job = shift; + my $param = shift; + warn Dumper($param) if $DEBUG; + + 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 $dir = '/usr/local/etc/freeside/cache.'. $FS::UID::datasrc. '/'; + my $file = $dir. $files{'file'}; + + my $type; + if ( $file =~ /\.(\w+)$/i ) { + $type = lc($1); + } else { + #or error out??? + warn "can't parse file type from filename $file; defaulting to CSV"; + $type = 'csv'; + } + + my $error = + FS::contact::Import::batch_import( { + job => $job, + file => $file, + type => $type, + agentnum => $param->{'agentnum'}, + 'format' => $param->{'format'}, + } ); + + unlink $file; + + die "$error\n" if $error; + +} + +=item batch_import + +=cut + +my %formatfields = ( + 'default' => [ qw( custnum last first title comment selfservice_access emailaddress phonetypenum1 phonetypenum3 phonetypenum2 ) ], +); + +sub _formatfields { + \%formatfields; +} + +## not tested but maybe allow 2nd format to attach location in the future +my %import_options = ( + 'table' => 'contact', + + 'preinsert_callback' => sub { + my($record, $param) = @_; + my @location_params = grep /^location\./, keys %$param; + if (@location_params) { + my $cust_location = FS::cust_location->new({ + 'custnum' => $record->custnum, + }); + foreach my $p (@location_params) { + $p =~ /^location.(\w+)$/; + $cust_location->set($1, $param->{$p}); + } + + my $error = $cust_location->find_or_insert; # this avoids duplicates + return "error creating location: $error" if $error; + $record->set('locationnum', $cust_location->locationnum); + } + ''; + }, + +); + +sub _import_options { + \%import_options; +} + +sub batch_import { + my $opt = shift; + + my $iopt = _import_options; + $opt->{$_} = $iopt->{$_} foreach keys %$iopt; + + my $format = delete $opt->{'format'}; + + my $formatfields = _formatfields(); + die "unknown format $format" unless $formatfields->{$format}; + + my @fields; + foreach my $field ( @{ $formatfields->{$format} } ) { + push @fields, $field; + } + + $opt->{'fields'} = \@fields; + + FS::Record::batch_import( $opt ); + +} + +=head1 BUGS + +Not enough documentation. + +=head1 SEE ALSO + +L<FS::contact> + +=cut + +1;
\ No newline at end of file diff --git a/FS/FS/contact_import.pm b/FS/FS/contact_import.pm new file mode 100644 index 000000000..599132bc7 --- /dev/null +++ b/FS/FS/contact_import.pm @@ -0,0 +1,164 @@ +package FS::contact_import; + +use strict; +use vars qw( $DEBUG ); #$conf ); +use Storable qw(thaw); +use Data::Dumper; +use MIME::Base64; +use FS::Misc::DateTime qw( parse_datetime ); +use FS::Record qw( qsearchs ); +use FS::contact; +use FS::cust_main; + +$DEBUG = 0; + +=head1 NAME + +FS::contact_import - Batch contact importing + +=head1 SYNOPSIS + + use FS::contact_import; + + #import + FS::contact_import::batch_import( { + file => $file, #filename + type => $type, #csv or xls + format => $format, #default + agentnum => $agentnum, + job => $job, #optional job queue job, for progressbar updates + pkgbatch => $pkgbatch, #optional batch unique identifier + } ); + die $error if $error; + + #ajax helper + use FS::UI::Web::JSRPC; + my $server = + new FS::UI::Web::JSRPC 'FS::contact_import::process_batch_import', $cgi; + print $server->process; + +=head1 DESCRIPTION + +Batch contact importing. + +=head1 SUBROUTINES + +=item process_batch_import + +Load a batch import as a queued JSRPC job + +=cut + +sub process_batch_import { + my $job = shift; + #my $param = shift; + my $param = thaw(decode_base64(shift)); + warn Dumper($param) if $DEBUG; + + 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 $file = $dir. $files{'file'}; + + my $type; + if ( $file =~ /\.(\w+)$/i ) { + $type = lc($1); + } else { + #or error out??? + warn "can't parse file type from filename $file; defaulting to CSV"; + $type = 'csv'; + } + + my $error = + FS::contact_import::batch_import( { + job => $job, + file => $file, + type => $type, + agentnum => $param->{'agentnum'}, + 'format' => $param->{'format'}, + } ); + + unlink $file; + + die "$error\n" if $error; + +} + +=item batch_import + +=cut + +my %formatfields = ( + 'default' => [ qw( custnum last first title comment selfservice_access emailaddress phonetypenum1 phonetypenum3 phonetypenum2 ) ], +); + +sub _formatfields { + \%formatfields; +} + +## not tested but maybe allow 2nd format to attach location in the future +my %import_options = ( + 'table' => 'contact', + + 'preinsert_callback' => sub { + my($record, $param) = @_; + my @location_params = grep /^location\./, keys %$param; + if (@location_params) { + my $cust_location = FS::cust_location->new({ + 'custnum' => $record->custnum, + }); + foreach my $p (@location_params) { + $p =~ /^location.(\w+)$/; + $cust_location->set($1, $param->{$p}); + } + + my $error = $cust_location->find_or_insert; # this avoids duplicates + return "error creating location: $error" if $error; + $record->set('locationnum', $cust_location->locationnum); + } + ''; + }, + +); + +sub _import_options { + \%import_options; +} + +sub batch_import { + my $opt = shift; + + my $iopt = _import_options; + $opt->{$_} = $iopt->{$_} foreach keys %$iopt; + + my $format = delete $opt->{'format'}; + + my $formatfields = _formatfields(); + die "unknown format $format" unless $formatfields->{$format}; + + my @fields; + foreach my $field ( @{ $formatfields->{$format} } ) { + push @fields, $field; + } + + $opt->{'fields'} = \@fields; + + FS::Record::batch_import( $opt ); + +} + +=head1 BUGS + +Not enough documentation. + +=head1 SEE ALSO + +L<FS::contact> + +=cut + +1;
\ No newline at end of file |