From: Jonathan Prykop Date: Mon, 18 Apr 2016 19:33:02 +0000 (-0500) Subject: RT#29296: API stuff: Add new locations [package location export] X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=9e069687732191fedeaed8ade62e4db2886429c0 RT#29296: API stuff: Add new locations [package location export] --- diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index 24d105683..745315816 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -5306,7 +5306,7 @@ and customer address. Include units.', my @part_export = map { qsearch( 'part_export', {exporttype => $_ } ) } keys %{FS::part_export::export_info('cust_main')}; - map { $_->exportnum => $_->exporttype.' to '.$_->machine } @part_export; + map { $_->exportnum => $_->exportname } @part_export; }, 'option_sub' => sub { require FS::Record; @@ -5315,7 +5315,7 @@ and customer address. Include units.', 'part_export', { 'exportnum' => shift } ); $part_export - ? $part_export->exporttype.' to '.$part_export->machine + ? $part_export->exportname : ''; }, }, @@ -5324,7 +5324,7 @@ and customer address. Include units.', { 'key' => 'cust_location-exports', 'section' => '', - 'description' => 'Export(s) to call on cust_location insert, modification and deletion.', + 'description' => 'Export(s) to call on cust_location insert or modification', 'type' => 'select-sub', 'multiple' => 1, 'options_sub' => sub { diff --git a/FS/FS/cust_location.pm b/FS/FS/cust_location.pm index 2b8a5c88d..3588cee97 100644 --- a/FS/FS/cust_location.pm +++ b/FS/FS/cust_location.pm @@ -249,20 +249,22 @@ sub insert { # cust_location exports #my $export_args = $options{'export_args'} || []; - my @part_export = - map qsearch( 'part_export', {exportnum=>$_} ), - $conf->config('cust_location-exports'); #, $agentnum - - foreach my $part_export ( @part_export ) { - my $error = $part_export->export_insert($self); #, @$export_args); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "exporting to ". $part_export->exporttype. - " (transaction rolled back): $error"; + # don't export custnum_pending cases, let follow-up replace handle that + if ($self->custnum || $self->prospectnum) { + my @part_export = + map qsearch( 'part_export', {exportnum=>$_} ), + $conf->config('cust_location-exports'); #, $agentnum + + foreach my $part_export ( @part_export ) { + my $error = $part_export->export_insert($self); #, @$export_args); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "exporting to ". $part_export->exporttype. + " (transaction rolled back): $error"; + } } } - $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; } @@ -311,20 +313,22 @@ sub replace { # cust_location exports #my $export_args = $options{'export_args'} || []; - my @part_export = - map qsearch( 'part_export', {exportnum=>$_} ), - $conf->config('cust_location-exports'); #, $agentnum - - foreach my $part_export ( @part_export ) { - my $error = $part_export->export_replace($self, $old); #, @$export_args); - if ( $error ) { - $dbh->rollback if $oldAutoCommit; - return "exporting to ". $part_export->exporttype. - " (transaction rolled back): $error"; + # don't export custnum_pending cases, let follow-up replace handle that + if ($self->custnum || $self->prospectnum) { + my @part_export = + map qsearch( 'part_export', {exportnum=>$_} ), + $conf->config('cust_location-exports'); #, $agentnum + + foreach my $part_export ( @part_export ) { + my $error = $part_export->export_replace($self, $old); #, @$export_args); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "exporting to ". $part_export->exporttype. + " (transaction rolled back): $error"; + } } } - $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; } diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index 074a58c9b..1cc82357e 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -442,6 +442,21 @@ sub insert { my $conf = new FS::Conf; + if ($self->locationnum) { + my @part_export = + map qsearch( 'part_export', {exportnum=>$_} ), + $conf->config('cust_location-exports'); #, $agentnum + + foreach my $part_export ( @part_export ) { + my $error = $part_export->export_pkg_location($self); #, @$export_args); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "exporting to ". $part_export->exporttype. + " (transaction rolled back): $error"; + } + } + } + if ( ! $import && $conf->config('ticket_system') && $options{ticket_subject} ) { #this init stuff is still inefficient, but at least its limited to @@ -696,6 +711,24 @@ sub replace { } } + # also run exports if removing locationnum? + # doesn't seem to happen, and we don't export blank locationnum on insert... + if ($new->locationnum and ($new->locationnum != $old->locationnum)) { + my $conf = new FS::Conf; + my @part_export = + map qsearch( 'part_export', {exportnum=>$_} ), + $conf->config('cust_location-exports'); #, $agentnum + + foreach my $part_export ( @part_export ) { + my $error = $part_export->export_pkg_location($new); #, @$export_args); + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "exporting to ". $part_export->exporttype. + " (transaction rolled back): $error"; + } + } + } + $dbh->commit or die $dbh->errstr if $oldAutoCommit; ''; diff --git a/FS/FS/part_export/cust_location_http.pm b/FS/FS/part_export/cust_location_http.pm index 460080c74..e2830db74 100644 --- a/FS/FS/part_export/cust_location_http.pm +++ b/FS/FS/part_export/cust_location_http.pm @@ -4,27 +4,9 @@ use strict; use base qw( FS::part_export::http ); use vars qw( %options %info ); -my @location_fields = qw( - custnum - address1 - address2 - city - state - zip - country - locationname - county - latitude - longitude - prospectnum - location_type - location_number - location_kind - geocode - district - censusyear - incorporated -); +use FS::cust_main::Location; + +my @location_fields = ( qw( custnum prospectnum ), FS::cust_main::Location->location_fields ); tie %options, 'Tie::IxHash', 'method' => { label =>'Method', @@ -32,10 +14,11 @@ tie %options, 'Tie::IxHash', #options =>[qw(POST GET)], options =>[qw(POST)], default =>'POST' }, - 'url' => { label => 'URL', default => 'http://', }, - 'ssl_no_verify' => { label => 'Skip SSL certificate validation', - type => 'checkbox', - }, + 'location_url' => { label => 'Location URL' }, + 'package_url' => { label => 'Package URL' }, + 'ssl_no_verify' => { label => 'Skip SSL certificate validation', + type => 'checkbox', + }, 'include_fields' => { 'label' => 'Include fields', 'type' => 'select', 'multiple' => 1, @@ -52,45 +35,39 @@ tie %options, 'Tie::IxHash', 'options' => \%options, 'no_machine' => 1, 'notes' => <<'END', -Send an HTTP or HTTPS GET or POST to the specified URL on customer location insert -or replace. Always sends cgi fields action ('insert' or 'replace') and locationnum, -as well as any fields specified below. Only sends on replace if one of the -specified fields changed. +Send an HTTP or HTTPS GET or POST to the specified URLs on customer location +creation/update (action 'location') and package location assignment/change (action 'package'). +Always sends locationnum, action and any fields specified in the 'Include fields' +export option. Action 'package' also sends pkgnum and old_pkgnum (because location +changes usually instigate a pkgnum change.) Action 'location' only sends on replace +if one of the specified fields changed. Leave a URL blank to skip that action. For HTTPS support, Crypt::SSLeay or IO::Socket::SSL is required. END ); -sub http_queue_standard { - my $self = shift; - $self->http_queue( '', - ( $self->option('ssl_no_verify') ? 'ssl_no_verify' : '' ), - $self->option('method'), - $self->option('url'), - $self->option('success_regexp'), - @_ - ); -} - -sub _include_fields { - my $self = shift; - split( /\s+/, $self->option('include_fields') ); -} +# we don't do anything on deletion because we generally don't delete locations +# +# we don't send blank custnum/prospectnum because we do a lot of inserting/replacing +# with blank values and then immediately overwriting, but that unfortunately +# makes it difficult to indicate if this is the first time we've sent the location +# to the customer--hence we don't distinguish creation from update in the cgi vars +# gets invoked by FS::part_export::http _export_insert sub _export_command { my( $self, $action, $cust_location ) = ( shift, shift, shift ); + # redundant--cust_location exports don't get invoked by cust_location->delete, + # or by any status trigger, but just to be clear, since http export has other actions... return '' unless $action eq 'insert'; - $self->http_queue_standard( - 'action' => $action, + $self->_http_queue_standard( + 'action' => 'location', map { $_ => $cust_location->get($_) } ('locationnum', $self->_include_fields) ); } -# currently, only custnum can change (when converting prospect to customer) -# but using more generic logic for ease of adding other changeable fields sub _export_replace { my( $self, $new, $old ) = ( shift, shift, shift ); @@ -99,13 +76,56 @@ sub _export_replace { next if $new->get($field) eq $old->get($field); next if ($field =~ /latitude|longitude/) and $new->get($field) == $old->get($field); $changed = 1; + last; } return '' unless $changed; - $self->http_queue_standard( - 'action' => 'replace', + $self->_http_queue_standard( + 'action' => 'location', map { $_ => $new->get($_) } ('locationnum', $self->_include_fields) ); } +# not to be confused with export_pkg_change, which is for svcs +sub export_pkg_location { + my( $self, $cust_pkg ) = ( shift, shift, shift ); + + return '' unless $cust_pkg->locationnum; + + my $cust_location = $cust_pkg->cust_location; + + $self->_http_queue_standard( + 'action' => 'package', + (map { $_ => $cust_pkg->get($_) } ('pkgnum', 'change_pkgnum', 'locationnum')), + (map { $_ => $cust_location->get($_) } $self->_include_fields), + ); +} + +sub _http_queue_standard { + my $self = shift; + my %opts = @_; + my $url; + if ($opts{'action'} eq 'location') { + $url = $self->option('location_url'); + return '' unless $url; + } elsif ($opts{'action'} eq 'package') { + $url = $self->option('package_url'); + return '' unless $url; + } else { + return "Bad action ".$opts{'action'}; + } + $self->http_queue( '', + ( $self->option('ssl_no_verify') ? 'ssl_no_verify' : '' ), + $self->option('method'), + $url, + $self->option('success_regexp'), + %opts + ); +} + +sub _include_fields { + my $self = shift; + split( /\s+/, $self->option('include_fields') ); +} + 1;