From: jeff Date: Sat, 28 Jun 2008 19:25:24 +0000 (+0000) Subject: agent virtualize address blocks and routers X-Git-Tag: root_of_webpay_support~526 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=a1871d3d13c1dafa93b956762c0d23728d261da7 agent virtualize address blocks and routers --- diff --git a/FS/FS/AccessRight.pm b/FS/FS/AccessRight.pm index 5621a97c5..4e6eaafe2 100644 --- a/FS/FS/AccessRight.pm +++ b/FS/FS/AccessRight.pm @@ -238,6 +238,9 @@ tie my %rights, 'Tie::IxHash', 'Edit billing events', { rightname=>'Edit global billing events', global=>1 }, + { rightname=>'Engineering configuration' }, + { rightname=>'Engineering global configuration', global=>1 }, + { rightname=>'Configuration', global=>1 }, #most of the rest of the configuraiton is not agent-virtualized ], diff --git a/FS/FS/addr_block.pm b/FS/FS/addr_block.pm index 208684b3e..5815f1abd 100755 --- a/FS/FS/addr_block.pm +++ b/FS/FS/addr_block.pm @@ -7,6 +7,7 @@ use FS::router; use FS::svc_broadband; use FS::Conf; use NetAddr::IP; +use Carp qw( carp ); @ISA = qw( FS::Record ); @@ -47,6 +48,8 @@ block is assigned. =item ip_netmask - the netmask of the block, expressed as an integer. +=item agentnum - optional agent number (see L) + =back =head1 METHODS @@ -84,6 +87,28 @@ sub delete { Replaces OLD_RECORD with this one in the database. If there is an error, returns the error, otherwise returns false. +At present it's not possible to reallocate a block to a different router +except by deallocating it first, which requires that none of its addresses +be assigned. This is probably as it should be. + +sub replace_check { + my ( $new, $old ) = ( shift, shift ); + + unless($new->routernum == $old->routernum) { + my @svc = $self->svc_broadband; + if (@svc) { + return 'Block has assigned addresses: '. + join ', ', map {$_->ip_addr} @svc; + } + + return 'Block is already allocated' + if($new->routernum && $old->routernum); + + } + + ''; +} + =item check Checks all fields to make sure this is a valid record. If there is an error, @@ -99,6 +124,7 @@ sub check { $self->ut_number('routernum') || $self->ut_ip('ip_gateway') || $self->ut_number('ip_netmask') + || $self->ut_agentnum_acl('agentnum', 'Engineering global configuration') ; return $error if $error; @@ -202,7 +228,7 @@ my @used = } -=item allocate +=item allocate -- deprecated Allocates this address block to a router. Takes an FS::router object as an argument. @@ -215,25 +241,18 @@ be assigned. This is probably as it should be. sub allocate { my ($self, $router) = @_; - - return 'Block is already allocated' - if($self->router); + carp "deallocate deprecated -- use replace"; return 'Block must be allocated to a router' unless(ref $router eq 'FS::router'); - my @svc = $self->svc_broadband; - if (@svc) { - return 'Block has assigned addresses: '. join ', ', map {$_->ip_addr} @svc; - } - my $new = new FS::addr_block {$self->hash}; $new->routernum($router->routernum); return $new->replace($self); } -=item deallocate +=item deallocate -- deprecated Deallocates the block (i.e. sets the routernum to 0). If any addresses in the block are assigned to services, it fails. @@ -241,13 +260,9 @@ block are assigned to services, it fails. =cut sub deallocate { + carp "deallocate deprecated -- use replace"; my $self = shift; - my @svc = $self->svc_broadband; - if (@svc) { - return 'Block has assigned addresses: '. join ', ', map {$_->ip_addr} @svc; - } - my $new = new FS::addr_block {$self->hash}; $new->routernum(0); return $new->replace($self); @@ -328,6 +343,29 @@ sub split_block { To be implemented. +=item agent + +Returns the agent (see L) for this address block, if one exists. + +=cut + +sub agent { + qsearchs('agent', { 'agentnum' => shift->agentnum } ); +} + +=item label + +Returns text including the router name, gateway ip, and netmask for this +block. + +=cut + +sub label { + my $self = shift; + my $router = $self->router; + ($router ? $router->routername : '(unallocated)'). ':'. $self->NetAddr; +} + =back =head1 BUGS diff --git a/FS/FS/router.pm b/FS/FS/router.pm index 88ba99032..bfc553087 100755 --- a/FS/FS/router.pm +++ b/FS/FS/router.pm @@ -5,7 +5,7 @@ use vars qw( @ISA ); use FS::Record qw( qsearchs qsearch ); use FS::addr_block; -@ISA = qw( FS::Record ); +@ISA = qw( FS::Record FS::m2m_Common ); =head1 NAME @@ -82,7 +82,9 @@ sub check { my $error = $self->ut_numbern('routernum') - || $self->ut_text('routername'); + || $self->ut_text('routername') + || $self->ut_agentnum_acl('agentnum', 'Engineering global configuration') + ; return $error if $error; $self->SUPER::check; @@ -125,6 +127,16 @@ sub part_svc { $self->part_svc_router; } +=item agent + +Returns the agent associated with this router, if any. + +=cut + +sub agent { + qsearchs('agent', { 'agentnum' => shift->agentnum }); +} + =back =head1 BUGS diff --git a/FS/FS/svc_broadband.pm b/FS/FS/svc_broadband.pm index d1235246e..fa904370b 100755 --- a/FS/FS/svc_broadband.pm +++ b/FS/FS/svc_broadband.pm @@ -220,6 +220,24 @@ sub check { if($self->speed_up < 0) { return 'speed_up must be positive'; } if($self->speed_down < 0) { return 'speed_down must be positive'; } + my $cust_svc = $self->svcnum + ? qsearchs('cust_svc', { 'svcnum' => $self->svcnum } ) + : ''; + my $cust_pkg; + if ($cust_svc) { + $cust_pkg = $cust_svc->cust_pkg; + }else{ + $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $self->pkgnum } ); + return "Invalid pkgnum" unless $cust_pkg; + } + + if ($cust_pkg) { + my $addr_agentnum = $self->addr_block->agentnum; + if ($addr_agentnum && $addr_agentnum != $cust_pkg->cust_main->agentnum) { + return "Address block does not service this customer"; + } + } + if (not($self->ip_addr) or $self->ip_addr eq '0.0.0.0') { my $next_addr = $self->addr_block->next_free_addr; if ($next_addr) { @@ -290,6 +308,9 @@ sub allowed_routers { The business with sb_field has been 'fixed', in a manner of speaking. +allowed_routers isn't agent virtualized because part_svc isn't agent +virtualized + =head1 SEE ALSO FS::svc_Common, FS::Record, FS::addr_block, diff --git a/httemplate/browse/addr_block.cgi b/httemplate/browse/addr_block.cgi index d597ee17e..917f94c96 100644 --- a/httemplate/browse/addr_block.cgi +++ b/httemplate/browse/addr_block.cgi @@ -2,13 +2,13 @@ 'title' => 'Address Blocks', 'name' => 'address block', 'html_init' => $html_init, - 'html_form' => $html_form, + 'html_foot' => $html_foot, 'query' => { 'table' => 'addr_block', 'hashref' => {}, 'extra_sql' => $extra_sql, 'order_by' => $order_by, }, - 'count_query' => "SELECT count(*) from addr_block $extra_sql", + 'count_query' => "SELECT count(*) from addr_block $count_sql", 'header' => [ 'Address Block', 'Router', 'Action(s)', @@ -42,17 +42,26 @@ 'border-right:none;', 'border-left:none;', ], + 'agent_virt' => 1, + 'agent_null_right' => 'Engineering global configuration', + 'agent_pos' => 1, ) %> <%init> die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + unless $FS::CurrentUser::CurrentUser->access_right('Engineering configuration') + || $FS::CurrentUser::CurrentUser->access_right('Engineering global configuration'); my $p2 = popurl(2); my $path = $p2 . "edit/process/addr_block"; -my $extra_sql = " "; +my $extra_sql = ""; + +my $count_sql = "WHERE ". $FS::CurrentUser::CurrentUser->agentnums_sql( + 'null_right' => 'Engineering global configuration', +); + my $order_by = "ORDER BY "; $order_by .= "inet(ip_gateway), " if driver_name =~ /^Pg/i; $order_by .= "inet_aton(ip_gateway), " if driver_name =~ /^mysql/i; @@ -74,10 +83,16 @@ my $confirm = sub { "javascript:addr_block_areyousure('$path/$verb.cgi?blocknum=$num', '$verb')"; }; -my $html_form = qq( +my $html_foot = qq(
Gateway/Netmask: / +); +$html_foot .= include( '/elements/select-agent.html', + 'agent_virt' => 1, + 'agent_null_right' => 'Engineering global configuration', + ); +$html_foot .= qq(
); diff --git a/httemplate/browse/router.cgi b/httemplate/browse/router.cgi index 9d856f67c..9f7167329 100644 --- a/httemplate/browse/router.cgi +++ b/httemplate/browse/router.cgi @@ -6,7 +6,7 @@ 'hashref' => {}, 'extra_sql' => $extra_sql, }, - 'count_query' => "SELECT count(*) from router $extra_sql", + 'count_query' => "SELECT count(*) from router $count_sql", 'header' => [ 'Router name', 'Address block(s)', ], @@ -19,12 +19,16 @@ 'links' => [ [ "${p2}edit/router.cgi?", 'routernum' ], '', ], + 'agent_virt' => 1, + 'agent_null_right'=> "Engineering global configuration", + 'agent_pos' => 1, ) %> <%init> die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + unless $FS::CurrentUser::CurrentUser->access_right('Engineering configuration') + || $FS::CurrentUser::CurrentUser->access_right('Engineering global configuration'); my $p2 = popurl(2); my $extra_sql = ''; @@ -40,4 +44,9 @@ if ($cgi->param('hidecustomerrouters') eq '1') { push @menubar, 'Hide customer routers', $cgi->self_url(); } +my $count_sql = $extra_sql. ( $extra_sql =~ /WHERE/ ? ' AND' : 'WHERE' ). + $FS::CurrentUser::CurrentUser->agentnums_sql( + 'null_right' => 'Engineering global configuration', + ); + diff --git a/httemplate/browse/svc_acct_pop.cgi b/httemplate/browse/svc_acct_pop.cgi index 44bc651cf..4e493717a 100755 --- a/httemplate/browse/svc_acct_pop.cgi +++ b/httemplate/browse/svc_acct_pop.cgi @@ -27,8 +27,11 @@ %> <%init> +my $curuser = $FS::CurrentUser::CurrentUser; + die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + unless $curuser->access_right('Engineering configuration') + || $curuser->access_right('Engineering global configuration'); my $html_init = qq! Add new Access Number diff --git a/httemplate/edit/allocate.html b/httemplate/edit/allocate.html index 29c16ae6a..0f05fcc7d 100644 --- a/httemplate/edit/allocate.html +++ b/httemplate/edit/allocate.html @@ -12,15 +12,22 @@ 'table' => 'router', 'name_col' => 'routername', 'disable_empty' => 1, + 'agent_virt' => 1, + 'agent_null_right' => + 'Engineering global configuration', }, ], 'post_url' => "process/addr_block/allocate.cgi", 'popup' => 1, + 'agent_virt' => 1, + 'agent_null_right' => 'Engineering global configuration', ) %> <%init> +my $curuser = $FS::CurrentUser::CurrentUser; die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + unless $curuser->access_right('Engineering configuration') + || $curuser->access_right('Engineering global configuration'); diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html index 86eb2b3c7..47b246477 100644 --- a/httemplate/edit/elements/edit.html +++ b/httemplate/edit/elements/edit.html @@ -108,8 +108,8 @@ Example: #run before display to return a different value 'value_callback' => sub { my( $columname, $value ) = @_; }, - #XXX describe - 'field_callback' => sub { }, + #run before display to manipulate element of the 'fields' arrayref + 'field_callback' => sub { my( $cgi, $object, $field_hashref ) = @_; }, 'viewall_dir' => '', #'search' or 'browse', defaults to 'search' @@ -179,7 +179,7 @@ Example: % @$fields % ) { % -% &{ $opt{'field_callback'} }( $f ) +% my $trash = &{ $opt{'field_callback'} }( $cgi, $object, $f ) % if $opt{'field_callback'}; % % my $field = $f->{'field'}; @@ -227,10 +227,18 @@ Example: % 'disabled' => $f->{'disabled'}, % ); % -% #select-table +% #select-table, checkboxes-table % $include_common{$_} = $f->{$_} % foreach grep exists($f->{$_}), qw( table name_col ); % +% #checkboxes-table +% $include_common{$_} = $f->{$_} +% foreach grep exists($f->{$_}), qw( target_table link_table ); +% +% #*-table +% $include_common{$_} = $f->{$_} +% foreach grep exists($f->{$_}), qw( hashref agent_virt agent_null_right ); +% % if ( $type eq 'tablebreak-tr-title' ) { % $include_common{'table_id'} = 'TableNumber'. $tablenum++ % } diff --git a/httemplate/edit/elements/svc_Common.html b/httemplate/edit/elements/svc_Common.html index 72abcba1f..b6737c14a 100644 --- a/httemplate/edit/elements/svc_Common.html +++ b/httemplate/edit/elements/svc_Common.html @@ -13,7 +13,7 @@ % $pkgnum = $1; % $cgi->param('svcpart') =~ /^(\d+)$/ or die 'unparsable svcpart'; % $svcpart = $1; -% $cgi->delete_all(); #so edit.html treats this correctly as new?? +% #$cgi->delete_all(); #so edit.html treats this correctly as new?? % } % <% include( 'edit.html', @@ -63,7 +63,7 @@ }, 'field_callback' => sub { - my $f = shift; + my ($cgi, $object, $f) = @_; my $columndef = $part_svc->part_svc_column($f->{'field'}); my $flag = $columndef->columnflag; if ( $flag eq 'F' ) { @@ -72,6 +72,23 @@ } }, + 'html_init' => sub { + my $cust_main; + if ( $pkgnum ) { + my $cust_pkg = qsearchs('cust_pkg', {'pkgnum' => $pkgnum}); + $cust_main = $cust_pkg->cust_main if $cust_pkg; + } + $cust_main + ? include( '/elements/small_custview.html', + $cust_main, + '', + 1, + popurl(2). "view/cust_main.cgi" + ). '
' + : ''; + + }, + 'html_table_bottom' => sub { my $svc_x = shift; my $html = ''; diff --git a/httemplate/edit/process/addr_block/add.cgi b/httemplate/edit/process/addr_block/add.cgi index e9f9b9736..4321f946a 100755 --- a/httemplate/edit/process/addr_block/add.cgi +++ b/httemplate/edit/process/addr_block/add.cgi @@ -1,28 +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"); -%} -% +<% include( '../elements/process.html', + 'table' => 'addr_block', + 'redirect' => popurl(4). 'browse/addr_block.cgi?dummy=', + 'error_redirect' => popurl(4). 'browse/addr_block.cgi?', + 'agent_virt' => 1, + 'agent_null_right' => 'Engineering global configuration', + ) +%> <%init> -my $conf = new FS::Conf; +my $curuser = $FS::CurrentUser::CurrentUser; die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + unless $curuser->access_right('Engineering configuration') + || $curuser->access_right('Engineering global configuration'); + +$cgi->param('routernum', 0) # in FS::addr_block::check instead? + unless $cgi->param('routernum'); diff --git a/httemplate/edit/process/addr_block/allocate.cgi b/httemplate/edit/process/addr_block/allocate.cgi index d1bd73f1f..f377d8155 100755 --- a/httemplate/edit/process/addr_block/allocate.cgi +++ b/httemplate/edit/process/addr_block/allocate.cgi @@ -8,7 +8,9 @@ <%init> my $conf = new FS::Conf; +my $curuser = $FS::CurrentUser::CurrentUser; die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + unless $curuser->access_right('Engineering configuration') + || $curuser->access_right('Engineering global configuration'); diff --git a/httemplate/edit/process/addr_block/deallocate.cgi b/httemplate/edit/process/addr_block/deallocate.cgi index 95e1b7e4d..91184b33e 100755 --- a/httemplate/edit/process/addr_block/deallocate.cgi +++ b/httemplate/edit/process/addr_block/deallocate.cgi @@ -1,32 +1,20 @@ -% -%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"); -%} -% - +<% include( '../elements/process.html', + 'table' => 'addr_block', + 'copy_on_empty' => [ grep { $_ ne 'routernum' } + fields 'addr_block' ], + 'redirect' => popurl(4). 'browse/addr_block.cgi?', + 'error_redirect' => popurl(4). 'browse/addr_block.cgi?', + 'agent_virt' => 1, + 'agent_null_right' => 'Engineering global configuration', + ) +%> <%init> my $conf = new FS::Conf; +my $curuser = $FS::CurrentUser::CurrentUser; die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + unless $curuser->access_right('Engineering configuration') + || $curuser->access_right('Engineering global configuration'); +$cgi->param('routernum', 0); # just to be explicit about what we are doing diff --git a/httemplate/edit/process/addr_block/split.cgi b/httemplate/edit/process/addr_block/split.cgi index b3a33b18a..eb55d008e 100755 --- a/httemplate/edit/process/addr_block/split.cgi +++ b/httemplate/edit/process/addr_block/split.cgi @@ -1,27 +1,27 @@ -% -%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"); -%} -% - +<% $cgi->redirect(popurl(4). "browse/addr_block.cgi?". $cgi->query_string ) %> <%init> -my $conf = new FS::Conf; +my $curuser = $FS::CurrentUser::CurrentUser; + die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + unless $curuser->access_right('Engineering configuration') + || $curuser->access_right('Engineering global configuration'); + +my $error = ''; +$cgi->param('blocknum') =~ /^(\d+)$/ or die "invalid blocknum"; +my $blocknum = $1; + +my $addr_block = qsearchs({ 'table' => 'addr_block', + 'hashref' => { blocknum => $blocknum }, + 'extra_sql' => ' AND '. $curuser->agentnums_sql( + 'null_right' => 'Engineering global configuration' + ), + }) + or $error = "Unknown blocknum: $blocknum"; + +$error ||= $addr_block->split_block; + +$cgi->param('error', $error) + if $error; diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html index 6f271ee29..de0304a94 100644 --- a/httemplate/edit/process/elements/process.html +++ b/httemplate/edit/process/elements/process.html @@ -33,7 +33,8 @@ Example: 'clear_on_error' => [ 'form_field1', 'form_field2', ... ], - #pass an arrayref of hashrefs for multiple m2ms or m2names + #pass an arrayref of hashrefs for multiple m2ms or m2names + #be certain you incorporate m2m_Common if you see error: param 'process_m2m' => { 'link_table' => 'link_table_name', 'target_table' => 'target_table_name', @@ -176,6 +177,13 @@ my %hash = my $new = $class->new( \%hash ); +if ($old && exists($opt{'copy_on_empty'})) { + foreach my $field (@{$opt{'copy_on_empty'}}) { + $new->set($field, $old->get($field)) + unless scalar($cgi->param($field)); + } +} + if ( $opt{'agent_virt'} ) { die "illegal agentnum" unless $curuser->agentnums_href->{$new->agentnum} @@ -184,13 +192,6 @@ if ( $opt{'agent_virt'} ) { && $curuser->access_right($opt{'agent_null_right'}); } -if ($old && exists($opt{'copy_on_empty'})) { - foreach my $field (@{$opt{'copy_on_empty'}}) { - $new->set($field, $old->get($field)) - unless scalar($cgi->param($field)); - } -} - $error ||= $new->check; my @args = (); diff --git a/httemplate/edit/process/router.cgi b/httemplate/edit/process/router.cgi index 7e0baf782..6e717d19c 100644 --- a/httemplate/edit/process/router.cgi +++ b/httemplate/edit/process/router.cgi @@ -1,70 +1,20 @@ -%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_psr; -% -%my $new = new FS::router { -% map { -% ($_, scalar($cgi->param($_))); -% } fields('router') -%}; -% -%if($old) { -% $error = $new->replace($old); -%} else { -% $error = $new->insert; -% $routernum = $new->routernum; -%} -% -%check($error); -% -%if ($old) { -% @old_psr = $old->part_svc_router; -% foreach my $psr (@old_psr) { -% if($cgi->param('svcpart_'.$psr->svcpart) eq 'ON') { -% # do nothing -% } else { -% $error = $psr->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); -% } -%} -% -% -%# Yay, everything worked! -%dbh->commit or die dbh->errstr; -%print $cgi->redirect(popurl(3). "browse/router.cgi"); -% +<% include('elements/process.html', + 'table' => 'router', + 'viewall_dir' => 'browse', + 'viewall_ext' => 'cgi', + 'edit_ext' => 'cgi', + 'process_m2m' => { 'link_table' => 'part_svc_router', + 'target_table' => 'part_svc', + }, + 'agent_virt' => 1, + 'agent_null_right' => 'Engineering global configuration', + ) +%> <%init> +my $curuser = $FS::CurrentUser::CurrentUser; die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + unless $curuser->access_right('Engineering configuration') + || $curuser->access_right('Engineering global configuration'); diff --git a/httemplate/edit/process/svc_acct_pop.cgi b/httemplate/edit/process/svc_acct_pop.cgi index 75b89c88f..522e94948 100755 --- a/httemplate/edit/process/svc_acct_pop.cgi +++ b/httemplate/edit/process/svc_acct_pop.cgi @@ -6,8 +6,11 @@ %} <%init> +my $curuser = $FS::CurrentUser::CurrentUser; + die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + unless $curuser->access_right('Engineering configuration') + || $curuser->access_right('Engineering global configuration'); my $popnum = $cgi->param('popnum'); diff --git a/httemplate/edit/process/svc_broadband.cgi b/httemplate/edit/process/svc_broadband.cgi index 8600da349..d5c9820bb 100644 --- a/httemplate/edit/process/svc_broadband.cgi +++ b/httemplate/edit/process/svc_broadband.cgi @@ -1,38 +1,8 @@ -%if ( $error ) { -% $cgi->param('error', $error); -% $cgi->param('ip_addr', $new->ip_addr); -<% $cgi->redirect(popurl(2). "svc_broadband.cgi?". $cgi->query_string ) %> -%} else { -<% $cgi->redirect(popurl(3). "view/svc_broadband.cgi?" . $svcnum ) %> -%} +<% include('elements/svc_Common.html', 'table' => 'svc_broadband') %> <%init> +my $curuser = $FS::CurrentUser::CurrentUser; die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? - -$cgi->param('svcnum') =~ /^(\d*)$/ or die "Illegal svcnum!"; -my $svcnum = $1; - -my $old; -if ( $svcnum ) { - $old = qsearchs('svc_broadband', { 'svcnum' => $svcnum } ) - or die "fatal: can't find broadband service (svcnum $svcnum)!"; -} else { - $old = ''; -} - -my $new = new FS::svc_broadband ( { - map { - ($_, scalar($cgi->param($_))); - } ( fields('svc_broadband'), qw( pkgnum svcpart ) ) -} ); - -my $error; -if ( $svcnum ) { - $error = $new->replace($old); -} else { - $error = $new->insert; - $svcnum = $new->svcnum; -} + unless $curuser->access_right('Provision customer service'); #something else more specific? diff --git a/httemplate/edit/router.cgi b/httemplate/edit/router.cgi index c08e54449..180dcb7a7 100755 --- a/httemplate/edit/router.cgi +++ b/httemplate/edit/router.cgi @@ -1,78 +1,44 @@ -<% include('/elements/header.html', "$action Router", menubar( - 'View all routers' => "${p}browse/router.cgi", - )) +<% include('elements/edit.html', + 'post_url' => popurl(1).'process/router.cgi', + 'name' => 'router', + 'table' => 'router', + 'viewall_url' => "${p}browse/router.cgi", + 'labels' => { 'routernum' => 'Router', + 'routername' => 'Name', + 'svc_part' => 'Service', + }, + 'fields' => [ + { 'field'=>'routername', 'type'=>'text', 'size'=>32 }, + { 'field'=>'agentnum', 'type'=>'select-agent' }, + ], + 'error_callback' => $callback, + 'edit_callback' => $callback, + 'new_callback' => $callback, + ) %> - -<% include('/elements/error.html') %> - -
- - - - - - Router #<%$routernum or "(NEW)"%> - -

Name - -

-Custom fields: -
-<%table() %> -% -%foreach my $field ($router->virtual_fields) { -% print $router->pvf($field)->widget('HTML', 'edit', -% $router->getfield($field)); -%} -% - - -% -%unless ($router->svcnum) { -% - -

Select the service types available on this router
-% -% -% foreach my $part_svc ( qsearch('part_svc', { svcdb => 'svc_broadband', -% disabled => '' }) ) { -% - -
- $part_svc->svcpart, - routernum => $routernum } ) ? ' CHECKED' : ''%> VALUE="ON"> - - <%$part_svc->svcpart%>: <%$part_svc->svc%> -% } -% } - - -

-
- -<% include('/elements/footer.html') %> - <%init> -die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); +my $curuser = $FS::CurrentUser::CurrentUser; -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 $p3 = popurl(3); +die "access denied" + unless $curuser->access_right('Engineering configuration') + || $curuser->access_right('Engineering global configuration'); + +my $callback = sub { + my ($cgi, $object, $fields) = (shift, shift, shift); + unless ($object->svcnum) { + push @{$fields}, + { 'type' => 'tablebreak-tr-title', + 'value' => 'Select the service types available on this router', + }, + { 'field' => 'svc_part', + 'type' => 'checkboxes-table', + 'target_table' => 'part_svc', + 'link_table' => 'part_svc_router', + 'name_col' => 'svc', + 'hashref' => { 'svcdb' => 'svc_broadband', 'disabled' => '' }, + }; + } +}; diff --git a/httemplate/edit/svc_acct_pop.cgi b/httemplate/edit/svc_acct_pop.cgi index 3c16a1f95..b0ae1c381 100755 --- a/httemplate/edit/svc_acct_pop.cgi +++ b/httemplate/edit/svc_acct_pop.cgi @@ -27,8 +27,11 @@ Local access_right('Configuration'); + unless $curuser->access_right('Engineering configuration') + || $curuser->access_right('Engineering global configuration'); my $svc_acct_pop; if ( $cgi->param('error') ) { diff --git a/httemplate/edit/svc_broadband.cgi b/httemplate/edit/svc_broadband.cgi index c2fb58dda..25fb009ac 100644 --- a/httemplate/edit/svc_broadband.cgi +++ b/httemplate/edit/svc_broadband.cgi @@ -1,167 +1,26 @@ -<% include('/elements/header.html', "Broadband Service $action") %> - -<% include('/elements/error.html') %> - -Service #<%$svcnum ? $svcnum : "(NEW)"%>

- -
- - - - - <%&ntable("#cccccc",2)%> - - Description - -% if ( $part_svc->part_svc_column('description')->columnflag eq 'F' ) { - - <%$description%> -% } else { - - -% } - - - - - IP Address - -% if ( $part_svc->part_svc_column('ip_addr')->columnflag eq 'F' ) { - - <%$ip_addr%> -% } else { - - -% } - - - - - Download speed - -% if ( $part_svc->part_svc_column('speed_down')->columnflag eq 'F' ) { - - <%$speed_down%>Kbps -% } else { - - Kbps -% } - - - - - Upload speed - -% if ( $part_svc->part_svc_column('speed_up')->columnflag eq 'F' ) { - - <%$speed_up%>Kbps -% } else { - - Kbps -% } - - - -% if ($action eq 'Add') { - - - Router/Block - - - - -% } else { - - - - Router/Block - - <%$svc_broadband->addr_block->router->routername%>:<%$svc_broadband->addr_block->NetAddr%> - - - -% } - - MAC Address - - - - - - Latitude - - - - - - Longitude - - - - - - Altitude - - - - - - VLAN Profile - -% if ( $part_svc->part_svc_column('vlan_profile')->columnflag eq 'F' ) { - - <%$vlan_profile%> -% } else { - - -% } - - - - - Authentication Key - -% if ( $part_svc->part_svc_column('auth_key')->columnflag eq 'F' ) { - - <%$auth_key%> -% } else { - - -% } - - - -% -%foreach my $field ($svc_broadband->virtual_fields) { -% if ( $part_svc->part_svc_column($field)->columnflag ne 'F' && -% $part_svc->part_svc_column($field)->columnflag ne 'X') { -% print $svc_broadband->pvf($field)->widget('HTML', 'edit', -% $svc_broadband->getfield($field)); -% } -%} - - -
- -
- -<% include('/elements/footer.html') %> - +<% include('elements/svc_Common.html', + 'post_url' => popurl(1). 'process/svc_broadband.cgi', + 'name' => 'broadband service', + 'table' => 'svc_broadband', + 'labels' => { 'svcnum' => 'Service #', + 'description' => 'Description', + 'ip_addr' => 'IP address', + 'speed_down' => 'Download speed', + 'speed_up' => 'Upload speed', + 'blocknum' => 'Router/Block', + 'block_disp' => 'Router/Block', + 'mac_addr' => 'MAC address', + 'latitude' => 'Latitude', + 'longitude' => 'Longitude', + 'altitude' => 'Altitude', + 'vlan_profile' => 'VLAN profile', + 'authkey' => 'Authentication key', + }, + 'fields' => \@fields, + 'field_callback' => $callback, + 'dummy' => $cgi->query_string, + ) +%> <%init> die "access denied" @@ -170,85 +29,58 @@ die "access denied" # 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 ( { - map { $_, scalar($cgi->param($_)) } fields('svc_broadband'), qw(svcpart) - } ); - $svcnum = $svc_broadband->svcnum; - $pkgnum = $cgi->param('pkgnum'); - $svcpart = $svc_broadband->svcpart; - $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart}); - die "No part_svc entry!" unless $part_svc; - -} elsif ( $cgi->param('pkgnum') && $cgi->param('svcpart') ) { #adding - - $cgi->param('pkgnum') =~ /^(\d+)$/ or die 'unparsable pkgnum'; - $pkgnum = $1; - $cgi->param('svcpart') =~ /^(\d+)$/ or die 'unparsable svcpart'; - $svcpart = $1; - - $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart}); - die "No part_svc entry!" unless $part_svc; - - $svc_broadband = new FS::svc_broadband({ svcpart => $svcpart }); - - $svcnum=''; +my @fields = ( + qw( description ip_addr speed_down speed_up blocknum ), + { field=>'block_label', type=>'fixed' }, + qw( mac_addr latitude longitude altitude vlan_profile authkey ) +); - $svc_broadband->set_default_and_fixed; +my $callback = sub { + my ($cgi, $object, $fieldref) = @_; -} else { #editing + my $svcpart = $object->svcnum ? $object->cust_svc->svcpart + : $cgi->param('svcpart'); - my($query) = $cgi->keywords; - $query =~ /^(\d+)$/ or die "unparsable svcnum"; - $svcnum=$1; - $svc_broadband=qsearchs('svc_broadband',{'svcnum'=>$svcnum}) - or die "Unknown (svc_broadband) svcnum!"; - - my($cust_svc)=qsearchs('cust_svc',{'svcnum'=>$svcnum}) - or die "Unknown (cust_svc) svcnum!"; - - $pkgnum=$cust_svc->pkgnum; - $svcpart=$cust_svc->svcpart; - - $part_svc=qsearchs('part_svc',{'svcpart'=>$svcpart}); + my $part_svc = qsearchs( 'part_svc', { svcpart => $svcpart } ); die "No part_svc entry!" unless $part_svc; -} -my $action = $svc_broadband->svcnum ? 'Edit' : 'Add'; - -if ($pkgnum) { - - #Nothing? - -} elsif ( $action eq 'Edit' ) { - - #Nothing? - -} else { - die "\$action eq Add, but \$pkgnum is null!\n"; -} - -my $p1 = popurl(1); - -my ($ip_addr, $speed_up, $speed_down, $blocknum, $mac_addr, - $latitude, $longitude, $altitude, $vlan_profile, $auth_key, - $description) = - ($svc_broadband->ip_addr, - $svc_broadband->speed_up, - $svc_broadband->speed_down, - $svc_broadband->blocknum, - $svc_broadband->mac_addr, - $svc_broadband->latitude, - $svc_broadband->longitude, - $svc_broadband->altitude, - $svc_broadband->vlan_profile, - $svc_broadband->auth_key, - $svc_broadband->description, - ); + my $columndef = $part_svc->part_svc_column($fieldref->{'field'}); + if ($columndef->columnflag eq 'F') { + $fieldref->{'type'} = 'fixed'; + $fieldref->{'value'} = $columndef->columnvalue; + } + + if ($object->svcnum) { + + $fieldref->{type} = 'hidden' + if $fieldref->{field} eq 'blocknum'; + + $fieldref->{value} = $object->addr_block->label + if $fieldref->{field} eq 'block_label'; + + } else { + + $fieldref->{type} = 'hidden' if $fieldref->{field} eq 'block_label'; + + if ($fieldref->{field} eq 'blocknum') { + my $cust_pkg = qsearchs( 'cust_pkg', {pkgnum => $cgi->param('pkgnum')} ); + die "No cust_pkg entry!" unless $cust_pkg; + + $object->svcpart($part_svc->svcpart); + my @addr_block = + grep { ! $_->agentnum + || $cust_pkg->cust_main->agentnum == $_->agentnum + && $FS::CurrentUser::CurrentUser->agentnum($_->agentnum) + } + map { $_->addr_block } $object->allowed_routers; + my @options = map { $_->blocknum } @addr_block; + my %option_labels = map { ( $_->blocknum => $_->label ) } @addr_block; + $fieldref->{type} = 'select'; + $fieldref->{options} = \@options; + $fieldref->{labels} = \%option_labels; + } + + } +}; diff --git a/httemplate/elements/checkboxes-table.html b/httemplate/elements/checkboxes-table.html index cdfa58eca..b6b04d111 100644 --- a/httemplate/elements/checkboxes-table.html +++ b/httemplate/elements/checkboxes-table.html @@ -28,9 +28,9 @@ % my $target_pkey = dbdef->table($opt{'target_table'})->primary_key; % % my( $source_pkey, $sourcenum, $source_obj ); -% if ( $opt{'source_obj'} ) { +% if ( $opt{'source_obj'} || $opt{'object'} ) { % -% $source_obj = $opt{'source_obj'}; +% $source_obj = $opt{'source_obj'} || $opt{'object'}; % #$source_table = $source_obj->dbdef_table->table; % $source_pkey = $source_obj->dbdef_table->primary_key; % $sourcenum = $source_obj->$source_pkey(); @@ -48,11 +48,17 @@ % % my $extra_sql = ''; % +% if ( $opt{'agent_virt'} ) { +% $extra_sql .= ' AND' . $FS::CurrentUser::CurrentUser->agentnums_sql( +% 'null_right' => $opt{'agent_null_right'} +% ); +% } +% % if ( $opt{'disable-able'} ) { % $hashref->{'disabled'} = ''; % % $extra_sql .= ( $sourcenum && $source_pkey ) -% ? "OR $source_pkey = $sourcenum" +% ? " OR $source_pkey = $sourcenum" % : ''; % } % diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html index 9ace19ea3..5a947ea88 100644 --- a/httemplate/elements/menu.html +++ b/httemplate/elements/menu.html @@ -334,7 +334,7 @@ $config_menu{'Resellers'} = [ \%config_agent, '' ] $config_menu{'Billing'} = [ \%config_billing, '' ] if $curuser->access_right('Edit billing events') || $curuser->access_right('Edit global billing events'); -if ( $curuser->access_right('Configuration') ) { +if ( $curuser->access_right('Engineering configuration') ) { $config_menu{'Dialup'} = [ \%config_dialup, '' ]; $config_menu{'Fixed (username-less) broadband'} = [ \%config_broadband, '' ]; diff --git a/httemplate/elements/select-agent.html b/httemplate/elements/select-agent.html index 54069a5cb..d8ab50080 100644 --- a/httemplate/elements/select-agent.html +++ b/httemplate/elements/select-agent.html @@ -4,9 +4,8 @@ 'value' => $agentnum || '', 'empty_label' => 'all', 'hashref' => { 'disabled' => '' }, - 'extra_sql' => ' AND '. - $FS::CurrentUser::CurrentUser->agentnums_sql. - ' ORDER BY agent', + 'order_by' => ' ORDER BY agent', + 'disable_empty' => $disable_empty, %opt, ) %> @@ -18,4 +17,13 @@ my $agentnum = $opt{'curr_value'} || $opt{'value'}; $opt{'records'} = delete $opt{'agents'} if $opt{'agents'}; +my $curuser = $FS::CurrentUser::CurrentUser; +my $disable_empty = 1; +if ( $opt{'agent_null_right'} && + $curuser->access_right($opt{'agent_null_right'}) + ) +{ + $disable_empty--; +} + diff --git a/httemplate/elements/select-table.html b/httemplate/elements/select-table.html index 7339f362c..d24c9abe4 100644 --- a/httemplate/elements/select-table.html +++ b/httemplate/elements/select-table.html @@ -92,14 +92,25 @@ my $name_col = $opt{'name_col'}; my $value = $opt{'curr_value'} || $opt{'value'}; $value = [ split(/\s*,\s*/, $value) ] if $opt{'multiple'} && $value =~ /,/; +my $extra_sql = $opt{'extra_sql'} || ''; +my $hashref = $opt{'hashref'} || {}; + +if ( $opt{'agent_virt'} ) { + $extra_sql .= + ( $extra_sql =~ /WHERE/i || scalar(keys %$hashref ) ? ' AND ' : ' WHERE ' ). + $FS::CurrentUser::CurrentUser->agentnums_sql( + 'null_right' => $opt{'agent_null_right'} + ); +} + my @records = (); if ( $opt{'records'} ) { @records = @{ $opt{'records'} }; } else { @records = qsearch( { 'table' => $opt{'table'}, - 'hashref' => ( $opt{'hashref'} || {} ), - 'extra_sql' => ( $opt{'extra_sql'} || '' ), + 'hashref' => $hashref, + 'extra_sql' => $extra_sql, 'order_by' => ( $opt{'order_by'} || "ORDER BY $name_col" ), }); } @@ -113,7 +124,7 @@ unless ( ! $value $opt{hashref}->{$key} = $value; my $record = qsearchs( { 'table' => $opt{table}, - 'hashref' => $opt{hashref}, + 'hashref' => $hashref, 'extra_sql' => ( $opt{extra_sql} || '' ), }); push @records, $record if $record; diff --git a/httemplate/elements/tr-checkboxes-table.html b/httemplate/elements/tr-checkboxes-table.html new file mode 100644 index 000000000..0099427be --- /dev/null +++ b/httemplate/elements/tr-checkboxes-table.html @@ -0,0 +1,20 @@ +% unless ( $opt{'js_only'} ) { + + <% include('tr-td-label.html', @_ ) %> + + > +% } + + <% include( '/elements/checkboxes-table.html', %opt ) %> + +% unless ( $opt{'js_only'} ) { + + +% } +<%init> + +my( %opt ) = @_; + +my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : ''; + +