1 package FS::part_export::cust_location_http;
4 use base qw( FS::part_export::http );
5 use vars qw( %options %info );
7 my @location_fields = qw(
30 tie %options, 'Tie::IxHash',
31 'method' => { label =>'Method',
33 #options =>[qw(POST GET)],
36 'location_url' => { label => 'Location URL' },
37 'package_url' => { label => 'Package URL' },
38 'ssl_no_verify' => { label => 'Skip SSL certificate validation',
41 'include_fields' => { 'label' => 'Include fields',
44 'options' => [ @location_fields ] },
45 'location_data' => { 'label' => 'Location data',
46 'type' => 'textarea' },
47 'package_data' => { 'label' => 'Package data',
48 'type' => 'textarea' },
50 label => 'Success Regexp',
56 'svc' => [qw( cust_location )],
57 'desc' => 'Send an HTTP or HTTPS GET or POST request, for customer locations',
58 'options' => \%options,
61 Send an HTTP or HTTPS GET or POST to the specified URLs on customer location
62 creation/update (action 'location') and package location assignment/change (action 'package').
63 Leave a URL blank to skip that action.
64 Always sends locationnum, action, and fields specified in the export options.
65 Action 'package' also sends pkgnum and change_pkgnum (the previous pkgnum,
66 because location changes usually instigate a pkgnum change.)
67 Simple field values can be selected in 'Include fields', and more complex
68 values can be specified in the data field options as perl code using vars
69 $cust_location, $cust_main and (where relevant) $cust_pkg.
70 Action 'location' only sends on update if a specified field changed.
71 Note that scheduled future package changes are currently sent when the change is scheduled
72 (this may not be the case in future versions of this export.)
73 For HTTPS support, <a href="http://search.cpan.org/dist/Crypt-SSLeay">Crypt::SSLeay</a>
74 or <a href="http://search.cpan.org/dist/IO-Socket-SSL">IO::Socket::SSL</a> is required.
78 # we don't do anything on deletion because we generally don't delete locations
80 # we don't send blank custnum/prospectnum because we do a lot of inserting/replacing
81 # with blank values and then immediately overwriting, but that unfortunately
82 # makes it difficult to indicate if this is the first time we've sent the location
83 # to the customer--hence we don't distinguish insert from update in the cgi vars
85 # gets invoked by FS::part_export::http _export_insert
87 my( $self, $action, $cust_location ) = @_;
89 # redundant--cust_location exports don't get invoked by cust_location->delete,
90 # or by any status trigger, but just to be clear, since http export has other actions...
91 return '' unless $action eq 'insert';
93 $self->_http_queue_standard(
94 'action' => 'location',
95 (map { $_ => $cust_location->get($_) } ('locationnum', $self->_include_fields)),
96 $self->_eval_replace('location_data',$cust_location,$cust_location->cust_main),
101 sub _export_replace {
102 my( $self, $new, $old ) = @_;
106 # even if they don't want custnum/prospectnum exported,
107 # inserts that lack custnum/prospectnum don't trigger exports,
108 # so we might not have previously reported these
109 $changed = 1 if $new->custnum && !$old->custnum;
110 $changed = 1 if $new->prospectnum && !$old->prospectnum;
112 foreach my $field ($self->_include_fields) {
114 next if $new->get($field) eq $old->get($field);
115 next if ($field =~ /latitude|longitude/) and $new->get($field) == $old->get($field);
121 %old_eval = $self->_eval_replace('location_data', $old, $old->cust_main),
124 my %eval = $self->_eval_replace('location_data', $new, $new->cust_main);
126 foreach my $key (keys %eval) {
128 next if $eval{$key} eq $old_eval{$key};
132 return '' unless $changed;
134 $self->_http_queue_standard(
135 'action' => 'location',
136 (map { $_ => $new->get($_) } ('locationnum', $self->_include_fields)),
141 # not to be confused with export_pkg_change, which is for svcs
142 sub export_pkg_location {
143 my ($self, $cust_pkg) = @_;
145 return '' unless $cust_pkg->locationnum;
147 my $cust_location = $cust_pkg->cust_location;
149 $self->_http_queue_standard(
150 'action' => 'package',
151 (map { $_ => $cust_pkg->get($_) } ('pkgnum', 'change_pkgnum', 'locationnum')),
152 (map { $_ => $cust_location->get($_) } $self->_include_fields),
153 $self->_eval_replace('package_data',$cust_location,$cust_pkg->cust_main,$cust_pkg),
157 sub _http_queue_standard {
161 if ($opts{'action'} eq 'location') {
162 $url = $self->option('location_url');
163 return '' unless $url;
164 } elsif ($opts{'action'} eq 'package') {
165 $url = $self->option('package_url');
166 return '' unless $url;
168 return "Bad action ".$opts{'action'};
170 $self->http_queue( '',
171 ( $self->option('ssl_no_verify') ? 'ssl_no_verify' : '' ),
172 $self->option('method'),
174 $self->option('success_regexp'),
179 sub _include_fields {
181 split( /\s+/, $self->option('include_fields') );
185 my ($self,$option,$cust_location,$cust_main,$cust_pkg) = @_;
188 /^\s*(\S+)\s+(.*)$/ or /()()/;
189 my( $field, $value_expression ) = ( $1, $2 );
190 my $value = eval $value_expression;
193 } split(/\n/, $self->option($option) );