diff options
author | khoff <khoff> | 2003-02-05 23:17:17 +0000 |
---|---|---|
committer | khoff <khoff> | 2003-02-05 23:17:17 +0000 |
commit | 0354f39ed0e74fd2eae1d9da13906625b4f56591 (patch) | |
tree | 730b2ac862f4c47c661d91a91ccb8167a4a0ee8f /httemplate | |
parent | c89aa83639038cc1946fec07a2dda252f64e5144 (diff) |
svc_broadband rewrite
Diffstat (limited to 'httemplate')
-rw-r--r-- | httemplate/browse/addr_block.cgi | 76 | ||||
-rw-r--r-- | httemplate/browse/generic.cgi | 46 | ||||
-rw-r--r-- | httemplate/browse/part_sb_field.cgi | 31 | ||||
-rw-r--r-- | httemplate/browse/router.cgi | 37 | ||||
-rw-r--r-- | httemplate/edit/part_router_field.cgi | 70 | ||||
-rw-r--r-- | httemplate/edit/part_sb_field.cgi | 79 | ||||
-rwxr-xr-x | httemplate/edit/process/addr_block/add.cgi | 20 | ||||
-rwxr-xr-x | httemplate/edit/process/addr_block/allocate.cgi | 25 | ||||
-rwxr-xr-x | httemplate/edit/process/addr_block/deallocate.cgi | 24 | ||||
-rwxr-xr-x | httemplate/edit/process/addr_block/split.cgi | 19 | ||||
-rw-r--r-- | httemplate/edit/process/generic.cgi | 69 | ||||
-rw-r--r-- | httemplate/edit/process/router.cgi | 100 | ||||
-rw-r--r-- | httemplate/edit/process/svc_broadband.cgi | 54 | ||||
-rwxr-xr-x | httemplate/edit/router.cgi | 88 | ||||
-rw-r--r-- | httemplate/edit/svc_broadband.cgi | 251 | ||||
-rw-r--r-- | httemplate/index.html | 14 | ||||
-rw-r--r-- | httemplate/view/svc_broadband.cgi | 62 |
17 files changed, 884 insertions, 181 deletions
diff --git a/httemplate/browse/addr_block.cgi b/httemplate/browse/addr_block.cgi new file mode 100644 index 000000000..06ac556cf --- /dev/null +++ b/httemplate/browse/addr_block.cgi @@ -0,0 +1,76 @@ +<%= header('Address Blocks', menubar('Main Menu' => $p)) %> +<% + +use NetAddr::IP; + +my @addr_block = qsearch('addr_block', {}); +my @router = qsearch('router', {}); +my $block; +my $p2 = popurl(2); +my $path = $p2 . "edit/process/addr_block"; + +%> + +<% if ($cgi->param('error')) { %> + <FONT SIZE="+1" COLOR="#ff0000">Error: <%=$cgi->param('error')%></FONT> + <BR><BR> +<% } %> + +<%=table()%> + +<% foreach $block (sort {$a->NetAddr cmp $b->NetAddr} @addr_block) { %> + <TR> + <TD><%=$block->NetAddr%></TD> + <% if (my $router = $block->router) { %> + <% if (scalar($block->svc_broadband) == 0) { %> + <TD> + <%=$router->routername%> + </TD> + <TD> + <FORM ACTION="<%=$path%>/deallocate.cgi" METHOD="POST"> + <INPUT TYPE="hidden" NAME="blocknum" VALUE="<%=$block->blocknum%>"> + <INPUT TYPE="submit" NAME="submit" VALUE="Deallocate"> + </FORM> + </TD> + <% } else { %> + <TD COLSPAN="2"> + <%=$router->routername%> + </TD> + <% } %> + <% } else { %> + <TD> + <FORM ACTION="<%=$path%>/allocate.cgi" METHOD="POST"> + <INPUT TYPE="hidden" NAME="blocknum" VALUE="<%=$block->blocknum%>"> + <SELECT NAME="routernum" SIZE="1"> + <% foreach (@router) { %> + <OPTION VALUE="<%=$_->routernum %>"><%=$_->routername%></OPTION> + <% } %> + </SELECT> + <INPUT TYPE="submit" NAME="submit" VALUE="Allocate"> + </FORM> + </TD> + <TD> + <FORM ACTION="<%=$path%>/split.cgi" METHOD="POST"> + <INPUT TYPE="hidden" NAME="blocknum" VALUE="<%=$block->blocknum%>"> + <INPUT TYPE="submit" NAME="submit" VALUE="Split"> + </FORM> + </TD> + </TR> +<% } + } %> + <TR><TD COLSPAN="3"><BR></TD></TR> + <TR> + <FORM ACTION="<%=$path%>/add.cgi" METHOD="POST"> + <TD>Gateway/Netmask</TD> + <TD> + <INPUT TYPE="text" NAME="ip_gateway" SIZE="15">/<INPUT TYPE="text" NAME="ip_netmask" SIZE="2"> + </TD> + <TD> + <INPUT TYPE="submit" NAME="submit" VALUE="Add"> + </TD> + </FORM> + </TR> +</TABLE> +</BODY> +</HTML> + diff --git a/httemplate/browse/generic.cgi b/httemplate/browse/generic.cgi new file mode 100644 index 000000000..9ac0f2391 --- /dev/null +++ b/httemplate/browse/generic.cgi @@ -0,0 +1,46 @@ +<% + +use FS::Record qw(qsearch dbdef); +use DBIx::DBSchema; +use DBIx::DBSchema::Table; + +my $error; +my $p2 = popurl(2); +my ($table) = $cgi->keywords; +my $dbdef = dbdef or die "Cannot fetch dbdef!"; +my $dbdef_table = $dbdef->table($table) or die "Cannot fetch schema for $table"; + +my $pkey = $dbdef_table->primary_key or die "Cannot fetch pkey for $table"; +print header("Browse $table", menubar('Main Menu' => $p)); + +my @rec = qsearch($table, {}); +my @col = $dbdef_table->columns; + +if ($cgi->param('error')) { %> + <FONT SIZE="+1" COLOR="#ff0000">Error: <%=$cgi->param('error')%></FONT> + <BR><BR> +<% } +%> +<A HREF="<%=$p2%>edit/<%=$table%>.cgi"><I>Add a new <%=$table%></I></A><BR><BR> + +<%=table()%> +<TH> +<% foreach (grep { $_ ne $pkey } @col) { + %><TD><%=$_%></TD> + <% } %> +</TH> +<% foreach $rec (sort {$a->getfield($pkey) cmp $b->getfield($pkey) } @rec) { + %> + <TR> + <TD> + <A HREF="<%=$p2%>edit/<%=$table%>.cgi?<%=$rec->getfield($pkey)%>"> + <%=$rec->getfield($pkey)%></A> </TD> <% + foreach $col (grep { $_ ne $pkey } @col) { %> + <TD><%=$rec->getfield($col)%></TD> <% } %> + </A> + </TR> +<% } %> +</TABLE> +</BODY> +</HTML> + diff --git a/httemplate/browse/part_sb_field.cgi b/httemplate/browse/part_sb_field.cgi new file mode 100644 index 000000000..4c9641e86 --- /dev/null +++ b/httemplate/browse/part_sb_field.cgi @@ -0,0 +1,31 @@ +<%= header('svc_broadband extended fields', menubar('Main Menu' => $p)) %> +<% + +my @psf = qsearch('part_sb_field', {}); +my $block; +my $p2 = popurl(2); + +%> + +<% if ($cgi->param('error')) { %> + <FONT SIZE="+1" COLOR="#ff0000">Error: <%=$cgi->param('error')%></FONT> + <BR><BR> +<% } %> + +<A HREF="<%=$p2%>edit/part_sb_field.cgi"><I>Add a new field</I></A><BR><BR> + +<%=table()%> +<TH><TD>Field name</TD><TD>Service type</TD></TH> +<% foreach $psf (sort {$a->name cmp $b->name} @psf) { %> + <TR> + <TD></TD> + <TD> + <A HREF="<%=$p2%>edit/part_sb_field.cgi?<%=$psf->sbfieldpart%>"> + <%=$psf->name%></A></TD> + <TD><%=$psf->part_svc->svc%></TD> + </TR> +<% } %> +</TABLE> +</BODY> +</HTML> + diff --git a/httemplate/browse/router.cgi b/httemplate/browse/router.cgi new file mode 100644 index 000000000..8864936d9 --- /dev/null +++ b/httemplate/browse/router.cgi @@ -0,0 +1,37 @@ +<%= header('Routers', menubar('Main Menu' => $p)) %> +<% + +my @router = qsearch('router', {}); +my $p2 = popurl(2); + +%> + +<% if ($cgi->param('error')) { %> + <FONT SIZE="+1" COLOR="#ff0000">Error: <%=$cgi->param('error')%></FONT> + <BR><BR> +<% } %> + +<A HREF="<%=$p2%>edit/router.cgi"><I>Add a new router</I></A><BR><BR> + +<%=table()%> +<!-- <TH><TD>Field name</TD><TD>Field value</TD></TH> --> +<% foreach $router (sort {$a->routernum <=> $b->routernum} @router) { %> + <TR> +<!-- <TD ROWSPAN="<%=scalar($router->router_field) + 2%>"> --> + <TD> + <A HREF="<%=$p2%>edit/router.cgi?<%=$router->routernum%>"><%=$router->routername%></A> + </TD> + <!-- + <% foreach (sort { $a->part_router_field->name cmp $b->part_router_field->name } $router->router_field ) { %> + <TR> + <TD BGCOLOR="#cccccc" ALIGN="right"><%=$_->part_router_field->name%></TD> + <TD BGCOLOR="#ffffff"><%=$_->value%></TD> + </TR> + <% } %> + --> + </TR> +<% } %> +</TABLE> +</BODY> +</HTML> + diff --git a/httemplate/edit/part_router_field.cgi b/httemplate/edit/part_router_field.cgi new file mode 100644 index 000000000..c3e99be2c --- /dev/null +++ b/httemplate/edit/part_router_field.cgi @@ -0,0 +1,70 @@ +<!-- mason kludge --> +<% +my ($routerfieldpart, $part_router_field); + +if ( $cgi->param('error') ) { + $part_router_field = new FS::part_router_field ( { + map { $_, scalar($cgi->param($_)) } fields('part_router_field')}); + $routerfieldpart = $part_router_field->routerfieldpart; +} else { + my($query) = $cgi->keywords; + if ( $query =~ /^(\d+)$/ ) { #editing + $routerfieldpart=$1; + $part_router_field=qsearchs('part_router_field', + {'routerfieldpart' => $routerfieldpart}) + or die "Unknown routerfieldpart!"; + + } else { #adding + $part_router_field = new FS::part_router_field({}); + } +} +my $action = $part_router_field->routerfieldpart ? 'Edit' : 'Add'; + +my $p1 = popurl(1); +print header("$action Router Extended Field Definition", ''); + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), + "</FONT>" + if $cgi->param('error'); +%> +<FORM ACTION="<%=$p1%>process/generic.cgi" METHOD=POST> + +<INPUT TYPE="hidden" NAME="table" VALUE="part_router_field"> +<INPUT TYPE="hidden" NAME="redirect_ok" + VALUE="<%=$p1%>part_router_field.cgi"> +<INPUT TYPE="hidden" NAME="routerfieldpart" VALUE="<%= + $routerfieldpart%>"> +Field #<B><%=$routerfieldpart or "(NEW)"%></B><BR><BR> + +<%=ntable("#cccccc",2)%> + <TR> + <TD ALIGN="right">Name</TD> + <TD><INPUT TYPE="text" NAME="name" MAXLENGTH=15 VALUE="<%= + $part_router_field->name%>"></TD> + </TR> + <TR> + <TD ALIGN="right">Length</TD> + <TD><INPUT TYPE="text" NAME="length" MAXLENGTH=4 VALUE="<%= + $part_router_field->length%>"></TD> + </TR> + <TR> + <TD ALIGN="right">check_block</TD> + <TD><TEXTAREA COLS="20" ROWS="4" NAME="check_block"><%= + $part_router_field->check_block%></TEXTAREA></TD> + </TR> + <TR> + <TD ALIGN="right">list_source</TD> + <TD><TEXTAREA COLS="20" ROWS="4" NAME="list_source"><%= + $part_router_field->list_source%></TEXTAREA></TD> + </TR> +</TABLE><BR><INPUT TYPE="submit" VALUE="Submit"> + +</FORM> + +<BR><BR> +<FONT SIZE=-2>If you don't understand what <I>check_block</I> and +<I>list_source</I> mean, <B>LEAVE THEM BLANK</B>. We mean it.</FONT> + + +</BODY> +</HTML> diff --git a/httemplate/edit/part_sb_field.cgi b/httemplate/edit/part_sb_field.cgi new file mode 100644 index 000000000..9e0cc9e4f --- /dev/null +++ b/httemplate/edit/part_sb_field.cgi @@ -0,0 +1,79 @@ +<!-- mason kludge --> +<% +my ($sbfieldpart, $part_sb_field); + +if ( $cgi->param('error') ) { + $part_sb_field = new FS::part_sb_field ( { + map { $_, scalar($cgi->param($_)) } fields('part_sb_field')}); + $sbfieldpart = $part_sb_field->sbfieldpart; +} else { + my($query) = $cgi->keywords; + if ( $query =~ /^(\d+)$/ ) { #editing + $sbfieldpart=$1; + $part_sb_field=qsearchs('part_sb_field', + {'sbfieldpart' => $sbfieldpart}) + or die "Unknown sbfieldpart!"; + + } else { #adding + $part_sb_field = new FS::part_sb_field({}); + } +} +my $action = $part_sb_field->sbfieldpart ? 'Edit' : 'Add'; + +my $p1 = popurl(1); +print header("$action svc_broadband Extended Field Definition", ''); + +print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), + "</FONT>" + if $cgi->param('error'); +%> +<FORM ACTION="<%=$p1%>process/generic.cgi" METHOD="POST"> + +<INPUT TYPE="hidden" NAME="table" VALUE="part_sb_field"> +<INPUT TYPE="hidden" NAME="redirect_ok" + VALUE="<%=popurl(2)%>browse/part_sb_field.cgi"> +<INPUT TYPE="hidden" NAME="sbfieldpart" VALUE="<%= + $sbfieldpart%>"> +Field #<B><%=$sbfieldpart or "(NEW)"%></B><BR><BR> + +<%=ntable("#cccccc",2)%> + <TR> + <TD ALIGN="right">Name</TD> + <TD><INPUT TYPE="text" NAME="name" MAXLENGTH=15 VALUE="<%= + $part_sb_field->name%>"></TD> + </TR> + <TR> + <TD ALIGN="right">Length</TD> + <TD><INPUT TYPE="text" NAME="length" MAXLENGTH=4 VALUE="<%= + $part_sb_field->length%>"></TD> + </TR> + <TR> + <TD ALIGN="right">Service</TD> + <TD><SELECT SIZE=1 NAME="svcpart"><% + foreach my $part_svc (qsearch('part_svc', {svcdb => 'svc_broadband'})) { + %><OPTION VALUE="<%=$part_svc->svcpart%>"<%= + ($part_svc->svcpart == $part_sb_field->svcpart) ? ' SELECTED' : ''%>"> + <%=$part_svc->svc%> + <% } %> + </SELECT></TD> + <TR> + <TD ALIGN="right">check_block</TD> + <TD><TEXTAREA COLS="20" ROWS="4" NAME="check_block"><%= + $part_sb_field->check_block%></TEXTAREA></TD> + </TR> + <TR> + <TD ALIGN="right">list_source</TD> + <TD><TEXTAREA COLS="20" ROWS="4" NAME="list_source"><%= + $part_sb_field->list_source%></TEXTAREA></TD> + </TR> +</TABLE><BR><INPUT TYPE="submit" VALUE="Submit"> + +</FORM> + +<BR><BR> +<FONT SIZE=-2>If you don't understand what <I>check_block</I> and +<I>list_source</I> mean, <B>LEAVE THEM BLANK</B>. We mean it.</FONT> + + +</BODY> +</HTML> diff --git a/httemplate/edit/process/addr_block/add.cgi b/httemplate/edit/process/addr_block/add.cgi new file mode 100755 index 000000000..34d799ccd --- /dev/null +++ b/httemplate/edit/process/addr_block/add.cgi @@ -0,0 +1,20 @@ +<% + +my $error = ''; +my $ip_gateway = $cgi->param('ip_gateway'); +my $ip_netmask = $cgi->param('ip_netmask'); + +my $new = new FS::addr_block { + ip_gateway => $ip_gateway, + ip_netmask => $ip_netmask, + routernum => 0 }; + +$error = $new->insert; + +if ( $error ) { + $cgi->param('error', $error); + print $cgi->redirect(popurl(4). "browse/addr_block.cgi?". $cgi->query_string ); +} else { + print $cgi->redirect(popurl(4). "browse/addr_block.cgi"); +} +%> diff --git a/httemplate/edit/process/addr_block/allocate.cgi b/httemplate/edit/process/addr_block/allocate.cgi new file mode 100755 index 000000000..85b0d7a7a --- /dev/null +++ b/httemplate/edit/process/addr_block/allocate.cgi @@ -0,0 +1,25 @@ +<% +my $error = ''; +my $blocknum = $cgi->param('blocknum'); +my $routernum = $cgi->param('routernum'); + +my $addr_block = qsearchs('addr_block', { blocknum => $blocknum }); +my $router = qsearchs('router', { routernum => $routernum }); + +if($addr_block) { + if ($router) { + $error = $addr_block->allocate($router); + } else { + $error = "Cannot find router with routernum $routernum"; + } +} else { + $error = "Cannot find block with blocknum $blocknum"; +} + +if ( $error ) { + $cgi->param('error', $error); + print $cgi->redirect(popurl(4). "browse/addr_block.cgi?" . $cgi->query_string); +} else { + print $cgi->redirect(popurl(4). "browse/addr_block.cgi"); +} +%> diff --git a/httemplate/edit/process/addr_block/deallocate.cgi b/httemplate/edit/process/addr_block/deallocate.cgi new file mode 100755 index 000000000..cfb7ed04d --- /dev/null +++ b/httemplate/edit/process/addr_block/deallocate.cgi @@ -0,0 +1,24 @@ +<% +my $error = ''; +my $blocknum = $cgi->param('blocknum'); + +my $addr_block = qsearchs('addr_block', { blocknum => $blocknum }); + +if($addr_block) { + my $router = $addr_block->router; + if ($router) { + $error = $addr_block->deallocate($router); + } else { + $error = "Block is not allocated to a router"; + } +} else { + $error = "Cannot find block with blocknum $blocknum"; +} + +if ( $error ) { + $cgi->param('error', $error); + print $cgi->redirect(popurl(4). "browse/addr_block.cgi?" . $cgi->query_string); +} else { + print $cgi->redirect(popurl(4). "browse/addr_block.cgi"); +} +%> diff --git a/httemplate/edit/process/addr_block/split.cgi b/httemplate/edit/process/addr_block/split.cgi new file mode 100755 index 000000000..bb6d4ba3e --- /dev/null +++ b/httemplate/edit/process/addr_block/split.cgi @@ -0,0 +1,19 @@ +<% +my $error = ''; +my $blocknum = $cgi->param('blocknum'); +my $addr_block = qsearchs('addr_block', { blocknum => $blocknum }); + +if ( $addr_block) { + $error = $addr_block->split_block; +} else { + $error = "Unknown blocknum: $blocknum"; +} + + +if ( $error ) { + $cgi->param('error', $error); + print $cgi->redirect(popurl(4). "browse/addr_block.cgi?". $cgi->query_string ); +} else { + print $cgi->redirect(popurl(4). "browse/addr_block.cgi"); +} +%> diff --git a/httemplate/edit/process/generic.cgi b/httemplate/edit/process/generic.cgi new file mode 100644 index 000000000..751987f7a --- /dev/null +++ b/httemplate/edit/process/generic.cgi @@ -0,0 +1,69 @@ +<% + +# Welcome to generic.cgi. +# +# This script provides a generic edit/process/ backend for simple table +# editing. All it knows how to do is take the values entered into +# the script and insert them into the table specified by $cgi->param('table'). +# If there's an existing record with the same primary key, it will be +# replaced. (Deletion will be added in the future.) +# +# Special cgi params for this script: +# table: the name of the table to be edited. The script will die horribly +# if it can't find the table. +# redirect_ok: URL to be displayed after a successful edit. The value of +# the record's primary key will be passed as a keyword. +# Defaults to (freeside root)/view/$table.cgi. +# redirect_error: URL to be displayed if there's an error. The original +# query string, plus the error message, will be passed. +# Defaults to $cgi->referer() (i.e. go back where you +# came from). + + +use FS::Record qw(qsearchs dbdef); +use DBIx::DBSchema; +use DBIx::DBSchema::Table; + + +my $error; +my $p2 = popurl(2); +my $table = $cgi->param('table'); +my $dbdef = dbdef or die "Cannot fetch dbdef!"; + +my $dbdef_table = $dbdef->table($table) or die "Cannot fetch schema for $table"; + +my $pkey = $dbdef_table->primary_key or die "Cannot fetch pkey for $table"; +my $pkey_val = $cgi->param($pkey); + + +#warn "new FS::Record ( $table, (hashref) )"; +my $new = FS::Record::new ( "FS::$table", { + map { $_, scalar($cgi->param($_)) } fields($table) +} ); + +#warn 'created $new of class '.ref($new); + +if($pkey_val and (my $old = qsearchs($table, { $pkey, $pkey_val} ))) { + # edit + $error = $new->replace($old); +} else { + #add + $error = $new->insert; + $pkey_val = $new->getfield($pkey); + # New records usually don't have their primary keys set until after + # they've been checked/inserted, so grab the new $pkey_val so we can + # redirect to it. +} + +my $redirect_ok = (($cgi->param('redirect_ok')) ? + $cgi->param('redirect_ok') : $p2."view/$table.cgi"); +my $redirect_error = (($cgi->param('redirect_error')) ? + $cgi->param('redirect_error') : $cgi->referer()); + +if($error) { + $cgi->param('error', $error); + print $cgi->redirect($redirect_error . '?' . $cgi->query_string); +} else { + print $cgi->redirect($redirect_ok . '?' .$pkey_val); +} +%> diff --git a/httemplate/edit/process/router.cgi b/httemplate/edit/process/router.cgi new file mode 100644 index 000000000..c0cb884f0 --- /dev/null +++ b/httemplate/edit/process/router.cgi @@ -0,0 +1,100 @@ +<% + +use FS::UID qw(dbh); + +my $dbh = dbh; +local $FS::UID::AutoCommit=0; + +sub check { + my $error = shift; + if($error) { + $cgi->param('error', $error); + print $cgi->redirect(popurl(3) . "edit/router.cgi?". $cgi->query_string); + $dbh->rollback; + exit; + } +} + +my $error = ''; +my $routernum = $cgi->param('routernum'); +my $routername = $cgi->param('routername'); +my $old = qsearchs('router', { routernum => $routernum }); +my @old_rf; +my @old_psr; + +my $new = new FS::router { + routernum => $routernum, + routername => $routername, + svcnum => 0 + }; + +if($old) { + if($old->routername ne $new->routername) { + $error = $new->replace($old); + } #else do nothing +} else { + $error = $new->insert; +} + +check($error); + +if ($old) { + @old_psr = $old->part_svc_router; + foreach $psr (@old_psr) { + if($cgi->param('svcpart_'.$psr->svcpart) eq 'ON') { + # do nothing + } else { + $error = $psr->delete; + } + } + check($error); + @old_rf = $old->router_field; + foreach $rf (@old_rf) { + if(my $new_val = $cgi->param('rf_'.$rf->routerfieldpart)) { + if($new_val ne $rf->value) { + my $new_rf = new FS::router_field + { routernum => $routernum, + value => $new_val, + routerfieldpart => $rf->routerfieldpart }; + $error = $new_rf->replace($rf); + } #else do nothing + } else { + $error = $rf->delete; + } + check($error); + } +} + +foreach($cgi->param) { + if($cgi->param($_) eq 'ON' and /^svcpart_(\d+)$/) { + my $svcpart = $1; + if(grep {$_->svcpart == $svcpart} @old_psr) { + # do nothing + } else { + my $new_psr = new FS::part_svc_router { svcpart => $svcpart, + routernum => $routernum }; + $error = $new_psr->insert; + } + check($error); + } elsif($cgi->param($_) ne '' and /^rf_(\d+)$/) { + my $part = $1; + if(my @x = grep {$_->routerfieldpart == $part} @old_rf) { + # already handled all of these + } else { + my $new_rf = new FS::router_field + { routernum => $routernum, + value => $cgi->param('rf_'.$part), + routerfieldpart => $part }; + $error = $new_rf->insert; + check($error); + } + } +} + + + +# Yay, everything worked! +$dbh->commit or die $dbh->errstr; +print $cgi->redirect(popurl(3). "edit/router.cgi?$routernum"); + +%> diff --git a/httemplate/edit/process/svc_broadband.cgi b/httemplate/edit/process/svc_broadband.cgi index fd7ba20d5..ab8b9f9d8 100644 --- a/httemplate/edit/process/svc_broadband.cgi +++ b/httemplate/edit/process/svc_broadband.cgi @@ -1,12 +1,19 @@ <% +# If it's stupid but it works, it's not stupid. +# -- U.S. Army + +local $FS::UID::AutoCommit = 0; +my $dbh = FS::UID::dbh; + $cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!"; my $svcnum = $1; -my $old; +my $old; my @old_sbf; if ( $svcnum ) { $old = qsearchs('svc_broadband', { 'svcnum' => $svcnum } ) or die "fatal: can't find broadband service (svcnum $svcnum)!"; + @old_sbf = $old->sb_field; } else { $old = ''; } @@ -17,14 +24,6 @@ my $new = new FS::svc_broadband ( { } ( fields('svc_broadband'), qw( pkgnum svcpart ) ) } ); -unless ( $new->ip_addr ) { - $new->ip_addr(join('.', (map $cgi->param('ip_addr_'.$_), (a..d)))); -} - -unless ( $new->mac_addr) { - $new->mac_addr(join(':', (map $cgi->param('mac_addr_'.$_), (a..f)))); -} - my $error; if ( $svcnum ) { $error = $new->replace($old); @@ -33,12 +32,47 @@ if ( $svcnum ) { $svcnum = $new->svcnum; } +unless ($error) { + my $sb_field; + + foreach ($cgi->param) { + #warn "\$cgi->param $_: " . $cgi->param($_); + if(/^sbf_(\d+)/) { + my $part = $1; + #warn "\$part $part"; + $sb_field = new FS::sb_field + { svcnum => $svcnum, + value => $cgi->param($_), + sbfieldpart => $part }; + if (my @x = grep { $_->sbfieldpart eq $part } @old_sbf) { + #if (my $old_sb_field = (grep { $_->sbfieldpart eq $part} @old_Sbf)[0]) { + #warn "array: " . scalar(@x); + if (length($sb_field->value) && ($sb_field->value ne $x[0]->value)) { + #warn "replacing " . $x[0]->value . " with " . $sb_field->value; + $error = $sb_field->replace($x[0]); + #$error = $sb_field->replace($old_sb_field); + } elsif (length($sb_field->value) == 0) { + #warn "delete"; + $error = $x[0]->delete; + } + } else { + if (length($sb_field->value) > 0) { + #warn "insert"; + $error = $sb_field->insert; + } + # else do nothing + } + } + } +} + if ( $error ) { $cgi->param('error', $error); $cgi->param('ip_addr', $new->ip_addr); - $cgi->param('mac_addr', $new->mac_addr); + $dbh->rollback; print $cgi->redirect(popurl(2). "svc_broadband.cgi?". $cgi->query_string ); } else { + $dbh->commit or die $dbh->errstr; print $cgi->redirect(popurl(3). "view/svc_broadband.cgi?" . $svcnum ); } diff --git a/httemplate/edit/router.cgi b/httemplate/edit/router.cgi new file mode 100755 index 000000000..d2279ff00 --- /dev/null +++ b/httemplate/edit/router.cgi @@ -0,0 +1,88 @@ +<HTML><BODY> + +<% + +my $router; +if ( $cgi->keywords ) { + my($query) = $cgi->keywords; + $query =~ /^(\d+)$/; + $router = qsearchs('router', { routernum => $1 }) + or print $cgi->redirect(popurl(2)."browse/router.cgi") ; +} else { + $router = new FS::router ( { + map { $_, scalar($cgi->param($_)) } fields('router') + } ); +} + +my $routernum = $router->routernum; +my $action = $routernum ? 'Edit' : 'Add'; +my $hashref = $router->hashref; + +print header("$action Router", menubar( + 'Main Menu' => "$p", + 'View all routers' => "${p}browse/router.cgi", +)); + +if($cgi->param('error')) { +%> <FONT SIZE="+1" COLOR="#ff0000">Error: <%=$cgi->param('error')%></FONT> +<% } %> + +<FORM ACTION="<%=popurl(1)%>process/router.cgi" METHOD=POST> + <INPUT TYPE="hidden" NAME="routernum" VALUE="<%=$routernum%>"> + Router #<%=$routernum or "(NEW)"%> + +<BR><BR>Name <INPUT TYPE="text" NAME="routername" SIZE=32 VALUE="<%=$hashref->{routername}%>"> +<%=table() %> + +<% +# I know, I know. Massive false laziness with edit/svc_broadband.cgi. But +# Kristian won't let me generalize the custom field mechanism to every table in +# the database, so this is what we get. <snarl> +# -- MW + +my @part_router_field = qsearch('part_router_field', { }); +my %rf = map { $_->part_router_field->name, $_->value } $router->router_field; +foreach (sort { $a->name cmp $b->name } @part_router_field) { + %> + <TR> + <TD ALIGN="right"><%=$_->name%></TD> + <TD><% + if(my @opts = $_->list_values) { + %> <SELECT NAME="rf_<%=$_->routerfieldpart%>" SIZE="1"> + <% + foreach $opt (@opts) { + %> <OPTION VALUE="<%=$opt%>"<%=($opt eq $rf{$_->name}) + ? ' SELECTED' : ''%>> + <%=$opt%> + </OPTION> + <% } %> + </SELECT> + <% } else { %> + <INPUT NAME="rf_<%=$_->routerfieldpart%>" + VALUE="<%=$rf{$_->name}%>" + <%=$_->length ? 'SIZE="'.$_->length.'"' : ''%>> + <% } %></TD> + </TR> +<% } %> +</TABLE> + + + +<BR><BR>Select the service types available on this router<BR> +<% + +foreach my $part_svc ( qsearch('part_svc', { svcdb => 'svc_broadband', + disabled => '' }) ) { + %> + <BR> + <INPUT TYPE="checkbox" NAME="svcpart_<%=$part_svc->svcpart%>"<%= + qsearchs('part_svc_router', { svcpart => $part_svc->svcpart, + routernum => $routernum } ) ? 'CHECKED' : ''%> VALUE="ON"> + <A HREF="<%=${p}%>edit/part_svc.cgi?<%=$part_svc->svcpart%>"> + <%=$part_svc->svcpart%>: <%=$part_svc->svc%></A> + <% } %> + + <BR><BR><INPUT TYPE="submit" VALUE="Apply changes"> + </FORM> +</BODY></HTML> + diff --git a/httemplate/edit/svc_broadband.cgi b/httemplate/edit/svc_broadband.cgi index d8a1f7a2a..f017d7a6e 100644 --- a/httemplate/edit/svc_broadband.cgi +++ b/httemplate/edit/svc_broadband.cgi @@ -1,6 +1,13 @@ <!-- mason kludge --> <% +# If it's stupid but it works, it's still stupid. +# -Kristian + + +use HTML::Widgets::SelectLayers; +use Tie::IxHash; + my( $svcnum, $pkgnum, $svcpart, $part_svc, $svc_broadband ); if ( $cgi->param('error') ) { $svc_broadband = new FS::svc_broadband ( { @@ -38,6 +45,8 @@ if ( $cgi->param('error') ) { $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart}); die "No part_svc entry!" unless $part_svc; + $svc_broadband->setfield('svcpart', $svcpart); + $svcnum=''; #set fixed and default fields from part_svc @@ -53,12 +62,9 @@ if ( $cgi->param('error') ) { } my $action = $svc_broadband->svcnum ? 'Edit' : 'Add'; -my @ac_list; - if ($pkgnum) { - unless ($svc_broadband->actypenum) {die "actypenum must be set fixed";}; - @ac_list = qsearch('ac', { actypenum => $svc_broadband->getfield('actypenum') }); + #Nothing? } elsif ( $action eq 'Edit' ) { @@ -68,152 +74,111 @@ if ($pkgnum) { die "\$action eq Add, but \$pkgnum is null!\n"; } - my $p1 = popurl(1); -print header("Broadband Service $action", ''); - -print qq!<FONT SIZE="+1" COLOR="#ff0000">Error: !, $cgi->param('error'), - "</FONT>" - if $cgi->param('error'); - -print qq!<FORM ACTION="${p1}process/svc_broadband.cgi" METHOD=POST>!; - -#display - - - -#svcnum -print qq!<INPUT TYPE="hidden" NAME="svcnum" VALUE="$svcnum">!; -print qq!Service #<B>!, $svcnum ? $svcnum : "(NEW)", "</B><BR><BR>"; - -#pkgnum -print qq!<INPUT TYPE="hidden" NAME="pkgnum" VALUE="$pkgnum">!; - -#svcpart -print qq!<INPUT TYPE="hidden" NAME="svcpart" VALUE="$svcpart">!; - -#actypenum -print '<INPUT TYPE="hidden" NAME="actypenum" VALUE="' . - $svc_broadband->actypenum . '">'; - - -print &ntable("#cccccc",2) . qq!<TR><TD ALIGN="right">AC</TD><TD>!; - -#acnum -if (( $part_svc->part_svc_column('acnum')->columnflag eq 'F' ) or - ( !$pkgnum )) { - - my $ac = qsearchs('ac', { acnum => $svc_broadband->acnum }); - my ($acnum, $acname) = ($ac->acnum, $ac->acname); - - print qq!<INPUT TYPE="hidden" NAME="acnum" VALUE="${acnum}">! . - qq!${acnum}: ${acname}</TD></TR>!; - -} else { - - my @ac_list = qsearch('ac', { actypenum => $svc_broadband->actypenum }); - print qq!<SELECT NAME="acnum" SIZE="1"><OPTION VALUE=""></OPTION>!; - - foreach ( @ac_list ) { - my ($acnum, $acname) = ($_->acnum, $_->acname); - print qq!<OPTION VALUE="${acnum}"! . - ($acnum == $svc_broadband->acnum ? ' SELECTED>' : '>') . - qq!${acname}</OPTION>!; - } - print '</TD></TR>'; - -} - -#speed_up & speed_down -my ($speed_up, $speed_down) = ($svc_broadband->speed_up, - $svc_broadband->speed_down); -print '<TR><TD ALIGN="right">Download speed</TD><TD>'; -if ( $part_svc->part_svc_column('speed_down')->columnflag eq 'F' ) { - print qq!<INPUT TYPE="hidden" NAME="speed_down" VALUE="${speed_down}">! . - qq!${speed_down}Kbps</TD></TR>!; -} else { - print qq!<INPUT TYPE="text" NAME="speed_down" SIZE=5 VALUE="${speed_down}">! . - qq!Kbps</TD></TR>!; -} - -print '<TR><TD ALIGN="right">Upload speed</TD><TD>'; -if ( $part_svc->part_svc_column('speed_up')->columnflag eq 'F' ) { - print qq!<INPUT TYPE="hidden" NAME="speed_up" VALUE="${speed_up}">! . - qq!${speed_up}Kbps</TD></TR>!; -} else { - print qq!<INPUT TYPE="text" NAME="speed_up" SIZE=5 VALUE="${speed_up}">! . - qq!Kbps</TD></TR>!; -} +my ($ip_addr, $speed_up, $speed_down, $blocknum) = + ($svc_broadband->ip_addr, + $svc_broadband->speed_up, + $svc_broadband->speed_down, + $svc_broadband->blocknum); -#ip_addr & ip_netmask -#We're assuming that ip_netmask is fixed if ip_addr is fixed. -#If it isn't, well, <shudder> what the heck are you doing!?!? - -my ($ip_addr, $ip_netmask) = ($svc_broadband->ip_addr, - $svc_broadband->ip_netmask); - -print '<TR><TD ALIGN="right">IP address/Mask</TD><TD>'; -if ( $part_svc->part_svc_column('ip_addr')->columnflag eq 'F' ) { - print qq!<INPUT TYPE="hidden" NAME="ip_addr" VALUE="${ip_addr}">! . - qq!<INPUT TYPE="hidden" NAME="ip_netmask" VALUE="${ip_netmask}">! . - qq!${ip_addr}/${ip_netmask}</TD></TR>!; -} else { - $ip_addr =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/; - print <<END; - <INPUT TYPE="text" NAME="ip_addr_a" SIZE="3" MAXLENGTH="3" VALUE="${1}">. - <INPUT TYPE="text" NAME="ip_addr_b" SIZE="3" MAXLENGTH="3" VALUE="${2}">. - <INPUT TYPE="text" NAME="ip_addr_c" SIZE="3" MAXLENGTH="3" VALUE="${3}">. - <INPUT TYPE="text" NAME="ip_addr_d" SIZE="3" MAXLENGTH="3" VALUE="${4}">/ - <INPUT TYPE="text" NAME="ip_netmask" SIZE="2" MAXLENGTH="2" VALUE="${ip_netmask}"> -</TD></TR> -<TR><TD COLSPAN="2" WIDTH="300"> -<P><SMALL>Leave the IP address and netmask blank for automatic assignment of a /32 address. Specifing the netmask and not the address will force assignment of a larger block.</SMALL></P> -</TD></TR> -END -} - -#mac_addr -my $mac_addr = $svc_broadband->mac_addr; - -unless (( $part_svc->part_svc_column('mac_addr')->columnflag eq 'F' ) and - ( $mac_addr eq '' )) { - print '<TR><TD ALIGN="right">MAC Address</TD><TD>'; - if ( $part_svc->part_svc_column('mac_addr')->columnflag eq 'F' ) { #Why? - print qq!<INPUT TYPE="hidden" NAME="mac_addr" VALUE="${mac_addr}">! . - qq!${mac_addr}</TD></TR>!; - } else { - #Ewwww - $mac_addr =~ /^([a-f0-9]{2}):([a-f0-9]{2}):([a-f0-9]{2}):([a-f0-9]{2}):([a-f0-9]{2}):([a-f0-9]{2})$/i; - print <<END; - <INPUT TYPE="text" NAME="mac_addr_a" SIZE="2" MACLENGTH="2" VALUE="${1}">: - <INPUT TYPE="text" NAME="mac_addr_b" SIZE="2" MACLENGTH="2" VALUE="${2}">: - <INPUT TYPE="text" NAME="mac_addr_c" SIZE="2" MACLENGTH="2" VALUE="${3}">: - <INPUT TYPE="text" NAME="mac_addr_d" SIZE="2" MACLENGTH="2" VALUE="${4}">: - <INPUT TYPE="text" NAME="mac_addr_e" SIZE="2" MACLENGTH="2" VALUE="${5}">: - <INPUT TYPE="text" NAME="mac_addr_f" SIZE="2" MACLENGTH="2" VALUE="${6}"> -</TD></TR> -END +%> +<%=header("Broadband Service $action", '')%> + +<% if ($cgi->param('error')) { %> +<FONT SIZE="+1" COLOR="#ff0000">Error: <%=$cgi->param('error')%></FONT><BR> +<% } %> + +Service #<B><%=$svcnum ? $svcnum : "(NEW)"%></B><BR><BR> + +<FORM ACTION="<%=${p1}%>process/svc_broadband.cgi" METHOD=POST> + <INPUT TYPE="hidden" NAME="svcnum" VALUE="<%=$svcnum%>"> + <INPUT TYPE="hidden" NAME="pkgnum" VALUE="<%=$pkgnum%>"> + <INPUT TYPE="hidden" NAME="svcpart" VALUE="<%=$svcpart%>"> + <INPUT TYPE="hidden" NAME="ip_addr" VALUE="<%=$ip_addr%>"> + + <%=&ntable("#cccccc",2)%> + + <TR> + <TD ALIGN="right">Download speed</TD> + <TD BGCOLOR="#ffffff"> +<% if ( $part_svc->part_svc_column('speed_down')->columnflag eq 'F' ) { %> + <INPUT TYPE="hidden" NAME="speed_down" VALUE="<%=$speed_down%>"><%=$speed_down%>Kbps +<% } else { %> + <INPUT TYPE="text" NAME="speed_down" SIZE=5 VALUE="<%=$speed_down%>">Kbps +<% } %> + </TD> + </TR> + <TR> + <TD ALIGN="right">Upload speed</TD> + <TD BGCOLOR="#ffffff"> +<% if ( $part_svc->part_svc_column('speed_up')->columnflag eq 'F' ) { %> + <INPUT TYPE="hidden" NAME="speed_up" VALUE="<%=$speed_up%>"><%=$speed_up%>Kbps +<% } else { %> + <INPUT TYPE="text" NAME="speed_up" SIZE=5 VALUE="<%=$speed_up%>">Kbps +<% } %> + </TD> + </TR> +<% if ($action eq 'Add') { %> + <TR> + <TD ALIGN="right">Router/Block</TD> + <TD BGCOLOR="#ffffff"> + <SELECT NAME="blocknum"> +<% + foreach my $router ($svc_broadband->allowed_routers) { + foreach my $addr_block ($router->addr_block) { +%> + <OPTION VALUE="<%=$addr_block->blocknum%>"<%=($addr_block->blocknum eq $blocknum) ? ' SELECTED' : ''%>> + <%=$router->routername%>:<%=$addr_block->ip_gateway%>/<%=$addr_block->ip_netmask%></OPTION> +<% + } } -} - -#location -my $location = $svc_broadband->location; +%> + </SELECT> + </TD> + </TR> +<% } else { %> -print '<TR><TD VALIGN="top" ALIGN="right">Location</TD><TD BGCOLOR="#e8e8e8">'; -if ( $part_svc->part_svc_column('location')->columnflag eq 'F' ) { - print qq!<PRE>${location}</PRE></TD></TR>!; -} else { - print qq!<TEXTAREA ROWS="4" COLS="30" NAME="location">${location}</TEXTAREA>!; -} + <TR> + <TD ALIGN="right">Router/Block</TD> + <TD BGCOLOR="#ffffff"> + <%=$svc_broadband->addr_block->router->routername%>:<%=$svc_broadband->addr_block->NetAddr%> + <INPUT TYPE="hidden" NAME="blocknum" VALUE="<%=$svc_broadband->blocknum%>"> + </TD> + </TR> -print '</TABLE><BR><INPUT TYPE="submit" VALUE="Submit">'; +<% } %> -print <<END; +<% - </FORM> - </BODY> + my @part_sb_field = qsearch('part_sb_field', { svcpart => $svcpart }); + my $sbf_hashref = $svc_broadband->sb_field_hashref($svcpart); + foreach (sort { $a->name cmp $b->name } @part_sb_field) { + %> + <TR> + <TD ALIGN="right"><%=$_->name%></TD> + <TD><% + if(my @opts = $_->list_values) { + %> + <SELECT NAME="sbf_<%=$_->sbfieldpart%>" SIZE=1> <% + foreach $opt (@opts) { %> + <OPTION VALUE="<%=$opt%>"<%= + ($opt eq $sbf_hashref->{$_->name}) ? ' SELECTED' : ''%>> + <%=$opt%></OPTION><% + } %></SELECT> + <% } else { %> + <INPUT NAME="sbf_<%=$_->sbfieldpart%>" + VALUE="<%=$sbf_hashref->{$_->name}%>" + <%=$_->length ? 'SIZE="'.$_->length.'"' : ''%>> + <% } %> + </TD> + </TR> +<% } %> + </TABLE> + <BR> + <INPUT TYPE="submit" NAME="submit" VALUE="Submit"> +</FORM> +</BODY> </HTML> -END -%> + diff --git a/httemplate/index.html b/httemplate/index.html index e8c3681b4..d13649b07 100644 --- a/httemplate/index.html +++ b/httemplate/index.html @@ -194,12 +194,16 @@ into counties and assign different tax rates to each. <LI><A HREF="browse/svc_acct_pop.cgi">View/Edit Access Numbers</A> - Points of Presence - <LI><A HREF="browse/ac_type.cgi">View/Edit AC Types</A> - - Broadband service access concentrator types. - <LI><A HREF="browse/ac.cgi">View/Edit AC</A> - - Broadband service access concentrators. <LI><A HREF="browse/part_bill_event.cgi">View/Edit invoice events</A> - Actions for overdue invoices - <LI><A HREF="browse/msgcat.cgi">View/Edit message catalog</A> - Change error messages and other customizable labels. + <LI><A HREF="browse/msgcat.cgi">View/Edit message catalog</A> - Change error messages and other customizable labels. + <LI><A HREF="browse/part_sb_field.cgi">View/Edit custom svc_broadband fields</A> + - Custom broadband service fields for site-specific export/informational data. + <LI><A HREF="browse/generic.cgi?part_router_field">View/Edit custom router fields</A> + - Custom router fields for site-specific export data. + <LI><A HREF="browse/router.cgi">View/Edit routers</A> + - Broadband access routers + <LI><A HREF="browse/addr_block.cgi">View/Edit address blocks</A> + - Manage address blocks and block assignments to broadband routers. </ul> <BR> </TD></TR> diff --git a/httemplate/view/svc_broadband.cgi b/httemplate/view/svc_broadband.cgi index 156edfaec..164b5b22c 100644 --- a/httemplate/view/svc_broadband.cgi +++ b/httemplate/view/svc_broadband.cgi @@ -20,28 +20,26 @@ if ($pkgnum) { } #eofalse -my $ac = qsearchs('ac', { acnum => $svc_broadband->getfield('acnum') }); +my $router = $svc_broadband->addr_block->router; + +if (not $router) { die "Could not lookup router for svc_broadband (svcnum $svcnum)" }; my ( - $acname, - $acnum, + $routername, + $routernum, $speed_down, $speed_up, - $ip_addr, - $ip_netmask, - $mac_addr, - $location + $ip_addr ) = ( - $ac->getfield('acname'), - $ac->getfield('acnum'), + $router->getfield('routername'), + $router->getfield('routernum'), $svc_broadband->getfield('speed_down'), $svc_broadband->getfield('speed_up'), - $svc_broadband->getfield('ip_addr'), - $svc_broadband->getfield('ip_netmask'), - $svc_broadband->getfield('mac_addr'), - $svc_broadband->getfield('location') + $svc_broadband->getfield('ip_addr') ); + + print header('Broadband Service View', menubar( ( ( $custnum ) ? ( "View this package (#$pkgnum)" => "${p}view/cust_pkg.cgi?$pkgnum", @@ -56,20 +54,38 @@ print header('Broadband Service View', menubar( ntable("#cccccc"). '<TR><TD>'. ntable("#cccccc",2). qq!<TR><TD ALIGN="right">Service number</TD>!. qq!<TD BGCOLOR="#ffffff">$svcnum</TD></TR>!. - qq!<TR><TD ALIGN="right">AC</TD>!. - qq!<TD BGCOLOR="#ffffff">$acnum: $acname</TD></TR>!. + qq!<TR><TD ALIGN="right">Router</TD>!. + qq!<TD BGCOLOR="#ffffff">$routernum: $routername</TD></TR>!. qq!<TR><TD ALIGN="right">Download Speed</TD>!. qq!<TD BGCOLOR="#ffffff">$speed_down</TD></TR>!. qq!<TR><TD ALIGN="right">Upload Speed</TD>!. qq!<TD BGCOLOR="#ffffff">$speed_up</TD></TR>!. - qq!<TR><TD ALIGN="right">IP Address/Mask</TD>!. - qq!<TD BGCOLOR="#ffffff">$ip_addr/$ip_netmask</TD></TR>!. - qq!<TR><TD ALIGN="right">MAC Address</TD>!. - qq!<TD BGCOLOR="#ffffff">$mac_addr</TD></TR>!. - qq!<TR><TD ALIGN="right" VALIGN="TOP">Location</TD>!. - qq!<TD BGCOLOR="#ffffff"><PRE>$location</PRE></TD></TR>!. - '</TABLE></TD></TR></TABLE>'. - '<BR>'. joblisting({'svcnum'=>$svcnum}, 1). + qq!<TR><TD ALIGN="right">IP Address</TD>!. + qq!<TD BGCOLOR="#ffffff">$ip_addr</TD></TR>!. + '</TD></TR><TR ROWSPAN="1"><TD></TD></TR>'; + + +# foreach my $sb_field +# ( qsearch('sb_field', { svcnum => $svcnum }) ) { +# my $part_sb_field = qsearchs('part_sb_field', +# { sbfieldpart => $sb_field->sbfieldpart }); +# print q!<TR><TD ALIGN="right">! . $part_sb_field->name . +# q!</TD><TD BGCOLOR="#ffffff">! . $sb_field->value . +# q!</TD></TR>!; +# } +# print '</TABLE>'; + + + my $sb_field = $svc_broadband->sb_field_hashref; + foreach (sort { $a cmp $b } keys(%{$sb_field})) { + print q!<TR><TD ALIGN="right">! . $_ . + q!</TD><TD BGCOLOR="#ffffff">! . $sb_field->{$_} . + q!</TD></TR>!; + } + print '</TABLE>'; + + +print '<BR>'. joblisting({'svcnum'=>$svcnum}, 1). '</BODY></HTML>' ; %> |