package FS::part_export::ikano;
+use strict;
+use warnings;
use vars qw(@ISA %info %loopType $me);
use Tie::IxHash;
use Date::Format qw( time2str );
# current assumptions of what won't change (from their side):
# vendor_order_id, vendor_qual_id, vendor_order_type, pushed, monitored,
# last_pull, address (from qual), contact info, ProductCustomId
- my($self, $svc_dsl) = (shift, shift);
+ my($self, $svc_dsl, $threshold) = (shift, shift, shift);
$self->loadmod;
my $result = $self->valid_order($svc_dsl,'pull');
return $result unless $result eq '';
+
+ my $now = time;
+ if($now - $svc_dsl->last_pull < $threshold) {
+ warn "$me skipping pull since threshold not reached (svcnum="
+ . $svc_dsl->svcnum . ",now=$now,threshold=$threshold,last_pull="
+ . $svc_dsl->last_pull .")" if $self->option('debug');
+ return '';
+ }
$result = $self->ikano_command('ORDERSTATUS',
{ OrderId => $svc_dsl->vendor_order_id } );
'username' => 'Username',
'password' => 'Password' );
+ my($fsf, $ikanof);
while (($fsf, $ikanof) = each %justUpdate) {
$svc_dsl->$fsf($result->{$ikanof})
if $result->{$ikanof} ne $svc_dsl->$fsf;
my @ostatics = split(',',$ostatics);
# more horrible search/sync code below...
my $staticsChanged = 0;
- foreach $istatic ( @istatics ) { # they have, we don't
+ foreach my $istatic ( @istatics ) { # they have, we don't
unless ( grep($_ eq $istatic, @ostatics) ) {
push @ostatics, $istatic;
$staticsChanged = 1;
my @tnotes = defined $tnotes ? @$tnotes : ();
my @inotes = (); # all Ikano OrderNotes as FS::dsl_note objects
my $notesChanged = 0;
- foreach $tnote ( @tnotes ) {
+ foreach my $tnote ( @tnotes ) {
my $inote = $self->ikano2fsnote($tnote,$svc_dsl->svcnum);
return 'Cannot parse note' unless ref($inote);
push @inotes, $inote;
# assume notes we already have don't change & no notes added from our side
# so using the horrible code below just find what we're missing and add it
my $error;
- foreach $inote ( @inotes ) {
+ foreach my $inote ( @inotes ) {
my $found = 0;
- foreach $onote ( @onotes ) {
+ foreach my $onote ( @onotes ) {
if($onote->date == $inote->date && $onote->note eq $inote->note) {
$found = 1;
last;
$by = "Ikano" if $n->{'CompanyStaffId'} == -1 && $n->{'StaffId'} != -1;
$by = "Us" if $n->{'StaffId'} == -1 && $n->{'CompanyStaffId'} != -1;
- $fsnote = new FS::dsl_note( {
+ new FS::dsl_note( {
'svcnum' => $svcnum,
- 'by' => $by,
+ 'user' => $by,
'priority' => $n->{'HighPriority'} eq 'false' ? 'N' : 'H',
- 'date' => int(str2time($n->{'Date'})),
+ '_date' => int(str2time($n->{'Date'})),
'note' => $n->{'Text'},
} );
}
sub qual {
+ my($self,$qual) = (shift,shift);
+# address always required for Ikano qual, TN optional (assume dry if not given)
+
+ my %location_hash = $qual->location;
+ return 'No address provided' unless %location_hash;
+ my $svctn = $qual->phonenum;
+
+ my $result = $self->ikano_command('PREQUAL',
+ { AddressLine1 => $location_hash{address1},
+ AddressUnitType => $location_hash{location_type},
+ AddressUnitValue => $location_hash{location_number},
+ AddressCity => $location_hash{city},
+ AddressState => $location_hash{state},
+ ZipCode => $location_hash{zip},
+ Country => $location_hash{country},
+ LocationType => $location_hash{location_kind},
+ PhoneNumber => length($svctn) > 1 ? $svctn : "STANDALONE",
+ RequestClientIP => '127.0.0.1',
+ CheckNetworks => $self->option('check_networks'),
+ } );
+ return 'Invalid prequal response' unless defined $result->{'PrequalId'};
+
+ my $qoptions = {};
+ # lame data structure traversal...
+ # don't spend much time here, just get TermsId and ProductCustomId
+ my $networks = $result->{'Network'};
+ my @networks = defined $networks ? @$networks : ();
+ my $netcount = 0;
+ foreach my $network ( @networks ) {
+ my $productgroups = $network->{'ProductGroup'};
+ my @productgroups = defined $productgroups ? @$productgroups : ();
+ my $pgcount = 0;
+ foreach my $productgroup ( @productgroups ) {
+ my $prefix = "ikano_Network_$netcount"."_ProductGroup_$pgcount"."_";
+ $qoptions->{$prefix."TermsId"} = $productgroup->{'TermsId'};
+ my $products = $network->{'Product'};
+ my @products = defined $products ? @$products : ();
+ my $prodcount = 0;
+ foreach my $product ( @products ) {
+ $qoptions->{$prefix."Product_$prodcount"."_ProductCustomId"} = $product->{'ProductCustomId'};
+ $prodcount++;
+ }
+ $pgcount++;
+ }
+ $netcount++;
+ }
+
+ { 'vendor_qual_id' => $result->{'PrequalId'},
+ 'status' => scalar(@networks) ? 'Q' : 'D',
+ 'options' => $qoptions,
+ };
+}
+
+sub qual_html {
'';
}
my @notes = $svc_dsl->notes;
my $html = '<TABLE border="1" cellspacing="2" cellpadding="2" id="dsl_notes">
<TR><TH>Date</TH><TH>By</TH><TH>Priority</TH><TH>Note</TH></TR>';
- foreach $note ( @notes ) {
+ foreach my $note ( @notes ) {
$html .= "<TR>
<TD>".time2str("$date_format %H:%M",$note->date)."</TD>
<TD>".$note->by."</TD>
# common to all order types/status/loop_type
my $error = !($svc_dsl->desired_due_date
- && grep($_ eq $svc_dsl->vendor_order_type, @Net::Ikano::orderType)
+ && grep($_ eq $svc_dsl->vendor_order_type, Net::Ikano->orderTypes)
&& $svc_dsl->first
&& $svc_dsl->last
&& defined $svc_dsl->loop_type
my $qual = qsearchs( 'qual', { 'vendor_qual_id' => $vendor_qual_id });
return '' unless $qual;
my %qual_options = $qual->options;
+ my( $optionname, $optionvalue );
while (($optionname, $optionvalue) = each %qual_options) {
if ( $optionname =~ /^ikano_Network_(\d+)_ProductGroup_(\d+)_Product_(\d+)_ProductCustomId$/
&& $optionvalue eq $ProductCustomId ) {
$svc_dsl->vendor_order_status($result->{'Status'});
$svc_dsl->username($result->{'Username'});
local $FS::svc_Common::noexport_hack = 1;
- local $FS::UID::AutoCommit = 0;
$result = $svc_dsl->replace;
- return 'Error setting DSL fields' if $result;
+ return "Error setting DSL fields: $result" if $result;
'';
}
my $result = $self->ikano_command('CANCEL',
{ OrderId => $svc_dsl->vendor_order_id, } );
return $result unless ref($result); # scalar (string) is an error
-
- return $self->dsl_pull($svc_dsl);
+ return 'Unable to cancel order' unless $result->{'Order'};
+ $result = $result->{'Order'};
+ return 'Invalid cancellation response'
+ unless $result->{'Status'} eq 'CANCELLED'
+ && $result->{'OrderId'} eq $svc_dsl->vendor_order_id;
+
+ # we're supposed to do a pull, but it will break everything, so don't
+ # this is very wrong...
}
else {
return "Cannot cancel a NEW order unless it's in NEW or PENDING status";