-tr-select-cust_location.html and elements/location.html: optionally support alternat...
authorlevinse <levinse>
Mon, 6 Dec 2010 06:36:02 +0000 (06:36 +0000)
committerlevinse <levinse>
Mon, 6 Dec 2010 06:36:02 +0000 (06:36 +0000)
optional address
-nearly finished qualifications, RT7111

FS/FS/part_export/ikano.pm
FS/FS/qual.pm
httemplate/edit/process/qual.cgi [new file with mode: 0644]
httemplate/elements/location.html
httemplate/elements/tr-select-cust_location.html
httemplate/misc/qual.html [new file with mode: 0644]
httemplate/view/cust_main/packages.html
httemplate/view/cust_main/qual_link.html [new file with mode: 0644]
httemplate/view/qual.cgi [new file with mode: 0644]

index bae683a..d371582 100644 (file)
@@ -278,6 +278,7 @@ sub qual {
        RequestClientIP => '127.0.0.1',
        CheckNetworks => $self->option('check_networks'),
       } ); 
+    return $result unless ref($result); # error case
     return 'Invalid prequal response' unless defined $result->{'PrequalId'};
 
     my $qoptions = {};
@@ -293,7 +294,7 @@ sub qual {
        foreach my $productgroup ( @productgroups ) {
            my $prefix = "ikano_Network_$netcount"."_ProductGroup_$pgcount"."_";
            $qoptions->{$prefix."TermsId"} = $productgroup->{'TermsId'};
-           my $products = $network->{'Product'};
+           my $products = $productgroup->{'Product'};
            my @products = defined $products ? @$products : ();
            my $prodcount = 0;
            foreach my $product ( @products ) {
@@ -312,7 +313,29 @@ sub qual {
 }
 
 sub qual_html {
-    '';
+    my($self,$qual) = (shift,shift);
+    
+    my %qual_options = $qual->options;
+    my @externalids = ();
+    my( $optionname, $optionvalue );
+    while (($optionname, $optionvalue) = each %qual_options) {
+       push @externalids, $optionvalue 
+           if ( $optionname =~ /^ikano_Network_(\d+)_ProductGroup_(\d+)_Product_(\d+)_ProductCustomId$/
+               && $optionvalue ne '' );
+    }
+
+    my $list = "<B>Qualifying Packages:</B><UL>";
+    my @part_pkgs = qsearch( 'part_pkg', { 'disabled' => '' } );
+    foreach my $part_pkg ( @part_pkgs ) {
+       my $externalid = $part_pkg->option('externalid',1);
+       if ( $externalid ) {
+           $list .= "<LI>".$part_pkg->pkgpart.": ".$part_pkg->pkg." - "
+               .$part_pkg->comment."</LI>" 
+             if grep( $_ eq $externalid, @externalids );
+       }
+    }
+    $list .= "</UL>";
+    $list;
 }
 
 sub notes_html { 
index 553de13..4859b77 100644 (file)
@@ -143,8 +143,31 @@ sub location {
     '';
 }
 
+sub cust_or_prospect {
+    my $self = shift;
+    if ( $self->locationnum ) {
+       my $l = qsearchs( 'cust_location', 
+                   { 'locationnum' => $self->locationnum });
+       return qsearchs('cust_main',{ 'custnum' => $l->custnum })
+           if $l->custnum;
+       return qsearchs('prospect_main',{ 'prospectnum' => $l->prospectnum })
+           if $l->prospectnum;
+    }
+    return qsearchs('cust_main', { 'custnum' => $self->custnum }) 
+       if $self->custnum;
+    return qsearchs('prospect_main', { 'prospectnum' => $self->prospectnum })
+       if $self->prospectnum;
+}
+
 sub status_long {
-    
+    my $self = shift;
+    my $s = {
+       'Q' => 'Qualified',
+       'D' => 'Does not Qualify',
+       'N' => 'New',
+    };
+    return $s->{$self->status} if defined $s->{$self->status};
+    return 'Unknown';
 }
 
 =back
diff --git a/httemplate/edit/process/qual.cgi b/httemplate/edit/process/qual.cgi
new file mode 100644 (file)
index 0000000..78e8770
--- /dev/null
@@ -0,0 +1,115 @@
+%if ($error) {
+%  $cgi->param('error', $error);
+%  $dbh->rollback if $oldAutoCommit;
+<% $cgi->redirect(popurl(3). 'misc/qual.html?'. $cgi->query_string ) %>
+%} else {
+%  $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+<% header('Qualification entered') %>
+  <SCRIPT TYPE="text/javascript">
+    window.top.location = '<% popurl(3). "view/qual.cgi?qualnum=$qualnum" %>';
+  </SCRIPT>
+
+  </BODY></HTML>
+%}
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+  unless $curuser->access_right('Order customer package'); # XXX: fix me
+
+$cgi->param('custnum') =~ /^(\d+)$/
+  or die 'illegal custnum '. $cgi->param('custnum');
+my $custnum = $1;
+my $cust_main = qsearchs({
+  'table'     => 'cust_main',
+  'hashref'   => { 'custnum' => $custnum },
+  'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+die 'unknown custnum' unless $cust_main;
+
+$cgi->param('exportnum') =~ /^(\d+)$/ or die 'illegal exportnum';
+my $exportnum = $1;
+
+$cgi->param('phonenum') =~ /^(\d*)$/ or die 'illegal phonenum';
+my $phonenum = $1;
+
+$cgi->param('locationnum') =~ /^(\-?\d*)$/
+  or die 'illegal locationnum '. $cgi->param('locationnum');
+my $locationnum = $1;
+
+my $oldAutoCommit = $FS::UID::AutoCommit;
+local $FS::UID::AutoCommit = 0;
+my $dbh = dbh;
+my $error = '';
+my $cust_location;
+if ( $locationnum == -1 ) { # adding a new one
+  my %location_hash = map { $_ => scalar($cgi->param($_)) }
+       qw( custnum address1 address2 city county state zip country geocode );
+  $location_hash{location_type} = $cgi->param('location_type') 
+    if $cgi->param('location_type');
+  $location_hash{location_number} = $cgi->param('location_number') 
+    if $cgi->param('location_number');
+  $location_hash{location_kind} = $cgi->param('location_kind') 
+    if $cgi->param('location_kind');
+  $cust_location = new FS::cust_location ( { %location_hash } );
+  $error = $cust_location->insert;
+  die "Unable to insert cust_location: $error" if $error;
+}
+elsif ( $locationnum eq '' ) { # default service location
+  $cust_location = new FS::cust_location ( {
+       $cust_main->location_hash,
+       custnum => $custnum,
+  } );
+}
+elsif ( $locationnum != -2 ) { # -2 = address not required for qual
+  $cust_location = qsearchs('cust_location', { 'locationnum' => $locationnum })
+    or die 'Invalid locationnum'; 
+}
+
+my $export;
+if ( $exportnum > 0 ) {
+ $export = qsearchs( 'part_export', { 'exportnum' => $exportnum } )
+    or die 'Invalid exportnum';
+}
+
+die "Nothing to qualify - neither TN nor address specified" 
+    unless ( defined $cust_location || $phonenum ne '' );
+
+my $qual;
+if ( $locationnum != -2 && $cust_location->locationnum > 0 ) {
+    $qual = new FS::qual( { locationnum => $cust_location->locationnum } );
+}
+else { # a cust_main default service address *OR* address not required
+    $qual = new FS::qual( { custnum => $custnum } );
+}
+$qual->phonenum($phonenum) if $phonenum ne '';
+$qual->status('N');
+
+if ( $export ) {
+    $qual->exportnum($export->exportnum);
+    my $qres = $export->qual($qual);
+    $error = "Qualification error: $qres" unless ref($qres);
+    unless ( $error ) {
+       $qual->status($qres->{'status'}) if $qres->{'status'};
+       $qual->vendor_qual_id($qres->{'vendor_qual_id'}) 
+           if $qres->{'vendor_qual_id'};
+       $error = $qual->insert($qres->{'options'}) if ref($qres->{'options'});
+    }
+}
+
+unless ( $error || $qual->qualnum ) {
+    $error = $qual->insert;
+}
+
+my $qualnum;
+unless ( $error ) {
+    if($qual->qualnum) {
+       $qualnum = $qual->qualnum;
+    }
+    else {
+       $error = "Unable to save qualification";
+    }
+}
+
+</%init>
index 0d2fa38..b5f7640 100644 (file)
@@ -31,21 +31,60 @@ Example:
     >
   </TD>
 </TR>
+<TR>
+      <TD ALIGN="right"><FONT ID="<% $pre %>address2_required" color="#ff0000" <% $address2_label_style %>>*</FONT>&nbsp;<FONT ID="<% $pre %>address2_label" <% $address2_label_style %>><B>Unit&nbsp;#</B></FONT></TD>
+      <TD COLSPAN=7>
+       <INPUT TYPE     = "text"
+              NAME     = "<%$pre%>address2"
+              ID       = "<%$pre%>address2"
+              VALUE    = "<% $object->get($pre.'address2') |h %>"
+              SIZE     = 54
+              onChange = "<% $onchange %>"
+              <% $disabled %>
+              <% $style %>
+       >
+      </TD>
+</TR>
 
+
+% if ( $opt{'alt_format'} ) { 
 <TR>
-  <TD ALIGN="right"><FONT ID="<% $pre %>address2_required" color="#ff0000" <% $address2_label_style %>>*</FONT>&nbsp;<FONT ID="<% $pre %>address2_label" <% $address2_label_style %>><B>Unit&nbsp;#</B></FONT></TD>
-  <TD COLSPAN=7>
-    <INPUT TYPE     = "text"
-           NAME     = "<%$pre%>address2"
-           ID       = "<%$pre%>address2"
-           VALUE    = "<% $object->get($pre.'address2') |h %>"
-           SIZE     = 54
-           onChange = "<% $onchange %>"
-           <% $disabled %>
-           <% $style %>
-    >
-  </TD>
+    <<%$th%> ALIGN="right">Location Type</<%$th%>>
+    <TD><INPUT         TYPE="text" 
+               NAME="location_type" 
+               ID="location_type"
+               VALUE="<% $object->get('location_type') |h %>"
+               SIZE="10"
+              <% $disabled %>
+              <% $style %>
+       >
+    </TD>
+    <TD></TD>
+    <<%$th%> ALIGN="right">Number</<%$th%>>
+    <TD><INPUT TYPE="text" 
+               NAME="location_number"
+               ID="location_number"
+               VALUE="<% $object->get('location_number') |h %>"
+               SIZE="5"
+              <% $disabled %>
+              <% $style %>
+       >
+    </TD>
+    <<%$th%> ALIGN="right">Kind</<%$th%>>
+    <TD>
+    <% include('/elements/select.html',
+             'cgi'       => $cgi,
+            'field'    => 'location_kind',
+            'disabled' => $disabled,
+            'style' => $style, 
+            'options'  => \@location_kind_options,
+            'labels'   => $location_kind_labels,
+            'curr_value' => $cgi->param('location_kind'),
+         )
+    %>
+    </TD>
 </TR>
+% } 
 
 <TR>
   <<%$th%> ALIGN="right"><%$r%>City</<%$th%>>
@@ -155,4 +194,7 @@ my %select_hash = (
 
 my $th = $opt{'no_bold'} ? 'TD' : 'TH';
 
+my @location_kind_options = ( '', 'R', 'B' );
+my $location_kind_labels = { '' => '', 'R' => 'Residential', 'B' => 'Business' };
+
 </%init>
index f2b267a..78252ba 100644 (file)
@@ -25,18 +25,26 @@ Example:
 
   function locationnum_changed(what) {
     var locationnum = what.options[what.selectedIndex].value;
+    if ( locationnum == -2 ) {
+%         for (@location_fields, 'city_select') { 
+            what.form.<%$_%>.disabled = true;
+           var ftype = what.form.<%$_%>.tagName;
+           if( ftype == 'SELECT') changeSelect(what.form.<%$_%>, '');
+           else what.form.<%$_%>.value = '';
+            what.form.<%$_%>.style.backgroundColor = '#dddddd';
+%         } 
+       return;
+    }
+    
     if ( locationnum == -1 ) {
 
 %     for (@location_fields, 'city_select') { 
         what.form.<%$_%>.disabled = false;
         what.form.<%$_%>.style.backgroundColor = '#ffffff';
+       var ftype = what.form.<%$_%>.tagName;
+       if( ftype == 'INPUT' ) what.form.<%$_%>.value = '';
 %     } 
 
-      what.form.address1.value = '';
-      what.form.address2.value = '';
-      what.form.city.value = '';
-      what.form.zip.value = '';
-
       changeSelect(what.form.country, <% $countrydefault |js_string %>);
 
       country_changed( what.form.country,
@@ -147,6 +155,9 @@ Example:
   <TD COLSPAN=7>
     <SELECT NAME="locationnum" onChange="locationnum_changed(this);">
       <OPTION VALUE=""><% $opt{'empty_label'} || '(default service address)' |h %>
+% if ( $opt{'is_optional'} ) {
+    <OPTION VALUE="-2" <% $locationnum == -2 ? 'SELECTED' : ''%>><% $opt{'optional_label'} || '(not required)' |h %>
+% }
 %     my @locations = $cust_main ? $cust_main->cust_location : ();
 %     push @locations, $cust_location
 %       if !$cust_main && $cust_location && $cust_location->locationnum>0;
@@ -170,14 +181,10 @@ Example:
              'disabled'     => $disabled,
              'no_asterisks' => 1,
              'no_bold'      => $opt{'no_bold'},
+            'alt_format'   => $opt{'alt_format'},
           )
 %>
 
-<%once>
-
-my @location_fields = qw( address1 address2 city county state zip country );
-
-</%once>
 <%init>
 
 my $conf = new FS::Conf;
@@ -206,8 +213,13 @@ if ( length($opt{'curr_value'}) ) {
 my $editable = $cust_main ? 0 : 1; #could use explicit control
 my $addnew = $cust_main ? 1 : ( $locationnum>0 ? 0 : 1 );
 
+my @location_fields = qw( address1 address2 city county state zip country );
+if ( $opt{'alt_format'} ) {
+    push @location_fields, qw( location_type location_number location_kind );
+}
+
 my $cust_location;
-if ( $locationnum && $locationnum != -1 ) {
+if ( $locationnum && $locationnum > 0 ) {
   $cust_location = qsearchs('cust_location', { 'locationnum' => $locationnum } )
     or die "unknown locationnum";
 } else {
@@ -230,7 +242,7 @@ my $location_sort = sub {
   or lc($a->address2) cmp lc($b->address2)
 };
 
-my $disabled = ( $locationnum == -1 || ($editable && $locationnum) )
+my $disabled = ( $locationnum < 0 || ($editable && $locationnum) )
                  ? ''
                  : 'DISABLED';
 
diff --git a/httemplate/misc/qual.html b/httemplate/misc/qual.html
new file mode 100644 (file)
index 0000000..7796342
--- /dev/null
@@ -0,0 +1,81 @@
+<% include('/elements/header-popup.html', 'Service Qualification' ) %>
+
+<% include('/elements/error.html') %>
+
+<FORM NAME="QualForm" ACTION="<% $p %>edit/process/qual.cgi" METHOD="POST">
+
+<INPUT TYPE="hidden" NAME="custnum" VALUE="<% $cust_main->custnum %>">
+
+<% ntable("#cccccc", 2) %>
+
+<% include('/elements/tr-td-label.html',
+             'cgi'       => $cgi,
+            'label'    => 'Qualify using',
+            'cell_style' => 'font-weight: bold',
+            'id' => 'exportnum',
+         )
+%>
+<TD>
+<% include('/elements/select.html',
+             'cgi'       => $cgi,
+            'field'    => 'exportnum',
+            'options'  => \@export_options,
+            'labels'   => $export_labels,
+            'curr_value' => $cgi->param('exportnum'),
+         )
+%>
+</TD>
+</TR>
+
+<% include('/elements/tr-input-text.html',
+             'cgi'       => $cgi,
+            'label'    => 'Service Telephone Number',
+            'field'    => 'phonenum',
+            'size'     => '12',
+            'value'    => $cgi->param('phonenum'),
+          )
+%>
+
+<% include('/elements/tr-select-cust_location.html',
+             'cgi'       => $cgi,
+             'cust_main' => $cust_main,
+            'alt_format' => 1, # XXX: use a config option
+            'is_optional' => 1,
+            'no_bold' => 1,
+          )
+%>
+</TABLE>
+
+<BR>
+<INPUT type="submit" VALUE="Qualify" onClick = "this.disabled=true;">
+
+</FORM>
+</BODY>
+</HTML>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+  unless $curuser->access_right('Order customer package'); # XXX: fix this
+
+my $conf = new FS::Conf;
+my $date_format = $conf->config('date_format') || '%m/%d/%Y';
+
+$cgi->param('custnum') =~ /^(\d+)$/ or die "no custnum";
+my $custnum = $1;
+my $cust_main = qsearchs({
+  'table'     => 'cust_main',
+  'hashref'   => { 'custnum' => $custnum },
+  'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+});
+
+my @exports = grep { $_->can('qual') } qsearch( 'part_export', {} );
+my @export_options = ( 0 );
+my $export_labels = { '0' => '(manual)' };
+foreach my $export ( @exports ) {
+    push @export_options, $export->exportnum;
+    $export_labels->{$export->exportnum} = $export->exportname;
+}
+
+</%init>
index 660d0ef..04c47aa 100755 (executable)
@@ -1,4 +1,9 @@
 % my $s = 0;
+
+% # XXX: add qual access right
+  <% $s++ ? ' | ' : '' %>
+  <% include('qual_link.html', $cust_main) %>
+
 % if ( $curuser->access_right('Order customer package') ) { 
   <% $s++ ? ' | ' : '' %>
   <% include('order_pkg_link.html', $cust_main) %>
diff --git a/httemplate/view/cust_main/qual_link.html b/httemplate/view/cust_main/qual_link.html
new file mode 100644 (file)
index 0000000..077142c
--- /dev/null
@@ -0,0 +1,16 @@
+<% include( '/elements/popup_link-cust_main.html',
+              'action'      => $p. 'misc/qual.html',
+              'label'       => 'Service&nbsp;Qualification',
+              'actionlabel' => 'Service Qualification',
+              'color'       => '#333399',
+              'cust_main'   => $cust_main,
+              'closetext'   => 'Close',
+              'width'       => 763,
+              'height'      => 436,
+          )
+%>
+<%init>
+
+my($cust_main) = @_;
+
+</%init>
diff --git a/httemplate/view/qual.cgi b/httemplate/view/qual.cgi
new file mode 100644 (file)
index 0000000..f967269
--- /dev/null
@@ -0,0 +1,65 @@
+<% include("/elements/header.html","View Qualification") %>
+
+% if ( $cust_or_prospect->custnum ) {
+
+  <% include( '/elements/small_custview.html', $cust_or_prospect->custnum, '', 1,
+     "${p}view/cust_main.cgi") %>
+  <BR>
+
+% }
+
+<B>Qualification #<% $qual->qualnum %></B>
+<% ntable("#cccccc", 2) %>
+<% include('elements/tr.html', label => 'Status', value => $qual->status_long ) %>
+<% include('elements/tr.html', label => 'Service Telephone Number', value => $qual->phonenum ) %>
+<% include('elements/tr.html', label => 'Address', value => $location_line ) %>
+% if ( $location_kind ) {
+<% include('elements/tr.html', label => 'Location Kind', value => $location_kind ) %>
+% } if ( $export ) { 
+<% include('elements/tr.html', label => 'Qualified using', value => $export->exportname ) %>
+<% include('elements/tr.html', label => 'Vendor Qualification #', value => $qual->vendor_qual_id ) %>
+% } 
+</TABLE>
+<BR><BR>
+
+% if ( $export ) {
+<% $export->qual_html($qual) %>
+% }
+
+<%init>
+
+# XXX: add access right for quals?
+
+my $qualnum;
+if ( $cgi->param('qualnum') ) {
+  $cgi->param('qualnum') =~ /^(\d+)$/ or die "unparsable qualnum";
+  $qualnum = $1;
+} else {
+  my($query) = $cgi->keywords;
+  $query =~ /^(\d+)$/ or die "no qualnum";
+  $qualnum = $1;
+}
+
+my $qual = qsearchs('qual', { qualnum => $qualnum }) or die "invalid qualnum";
+my $location_line = '';
+my %location_hash = $qual->location;
+my $cust_location;
+if ( %location_hash ) {
+    $cust_location = new FS::cust_location(\%location_hash);
+    $location_line = $cust_location->location_label;
+}
+# XXX: geocode_Mixin location_label doesn't currently have the new cust_location fields - add them
+
+my $location_kind;
+$location_kind = "Residential" if $cust_location->location_kind eq 'R';
+$location_kind = "Business" if $cust_location->location_kind eq 'B';
+
+my $cust_or_prospect = $qual->cust_or_prospect;
+
+my $export;
+if ( $qual->exportnum ) {
+    $export = qsearchs('part_export', { exportnum => $qual->exportnum } )
+               or die 'invalid exportnum';
+}
+
+</%init>