X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=FS%2FFS%2Fsvc_broadband.pm;h=b808527a198ddf8b4749646f39fd9dd981bc63db;hp=45f6c360168b88e6c9fbdbeb67d5c186daa14334;hb=4b5d4c82766ef1869d03df63fa1e2f0dd050cb6a;hpb=0354f39ed0e74fd2eae1d9da13906625b4f56591 diff --git a/FS/FS/svc_broadband.pm b/FS/FS/svc_broadband.pm index 45f6c3601..b808527a1 100755 --- a/FS/FS/svc_broadband.pm +++ b/FS/FS/svc_broadband.pm @@ -85,9 +85,62 @@ points to. You can ask the object for a copy with the I method. =cut +sub table_info { + { + 'name' => 'Broadband', + 'name_plural' => 'Broadband services', + 'longname_plural' => 'Fixed (username-less) broadband services', + 'display_weight' => 50, + 'cancel_weight' => 70, + 'fields' => { + 'description' => 'Descriptive label for this particular device.', + 'speed_down' => 'Maximum download speed for this service in Kbps. 0 denotes unlimited.', + 'speed_up' => 'Maximum upload speed for this service in Kbps. 0 denotes unlimited.', + 'ip_addr' => 'IP address. Leave blank for automatic assignment.', + 'blocknum' => { 'label' => 'Address block', + 'type' => 'select', + 'select_table' => 'addr_block', + 'select_key' => 'blocknum', + 'select_label' => 'cidr', + 'disable_inventory' => 1, + }, + }, + }; +} + sub table { 'svc_broadband'; } -=item insert +=item search_sql STRING + +Class method which returns an SQL fragment to search for the given string. + +=cut + +sub search_sql { + my( $class, $string ) = @_; + if ( $string =~ /^(\d{1,3}\.){3}\d{1,3}$/ ) { + $class->search_sql_field('ip_addr', $string ); + }elsif ( $string =~ /^([a-fA-F0-9]{12})$/ ) { + $class->search_sql_field('mac_addr', uc($string)); + }elsif ( $string =~ /^(([a-fA-F0-9]{1,2}:){5}([a-fA-F0-9]{1,2}))$/ ) { + $class->search_sql_field('mac_addr', uc("$2$3$4$5$6$7") ); + } else { + '1 = 0'; #false + } +} + +=item label + +Returns the IP address. + +=cut + +sub label { + my $self = shift; + $self->ip_addr; +} + +=item insert [ , OPTION => VALUE ... ] Adds this record to the database. If there is an error, returns the error, otherwise returns false. @@ -95,6 +148,12 @@ otherwise returns false. The additional fields pkgnum and svcpart (see FS::cust_svc) should be defined. An FS::cust_svc record will be created and inserted. +Currently available options are: I + +If I is set (to a scalar jobnum or an array reference of +jobnums), all provisioning jobs will have a dependancy on the supplied +jobnum(s) (they will not run until the specific job(s) complete(s)). + =cut # Standard FS::svc_Common::insert @@ -116,50 +175,6 @@ returns the error, otherwise returns false. # Standard FS::svc_Common::replace -=item sb_field - -Returns a list of FS::sb_field objects assigned to this object. - -=cut - -sub sb_field { - my $self = shift; - - return qsearch( 'sb_field', { svcnum => $self->svcnum } ); -} - -=item sb_field_hashref - -Returns a hashref of the FS::sb_field key/value pairs for this object. - -Deprecated. Please don't use it. - -=cut - -# Kristian wrote this, but don't hold it against him. He was under a powerful -# distracting influence whom he evidently found much more interesting than -# svc_broadband.pm. I can't say I blame him. - -sub sb_field_hashref { - my $self = shift; - my $svcpart = shift; - - if ((not $svcpart) && ($self->cust_svc)) { - $svcpart = $self->cust_svc->svcpart; - } - - my $hashref = {}; - - map { - my $sb_field = qsearchs('sb_field', { sbfieldpart => $_->sbfieldpart, - svcnum => $self->svcnum }); - $hashref->{$_->getfield('name')} = $sb_field ? $sb_field->getfield('value') : ''; - } qsearch('part_sb_field', { svcpart => $svcpart }); - - return $hashref; - -} - =item suspend Called by the suspend method of FS::cust_pkg (see FS::cust_pkg). @@ -188,23 +203,70 @@ sub check { my $error = $self->ut_numbern('svcnum') - || $self->ut_foreign_key('blocknum', 'addr_block', 'blocknum') + || $self->ut_numbern('blocknum') + || $self->ut_textn('description') || $self->ut_number('speed_up') || $self->ut_number('speed_down') || $self->ut_ipn('ip_addr') + || $self->ut_hexn('mac_addr') + || $self->ut_hexn('auth_key') + || $self->ut_coordn('latitude', -90, 90) + || $self->ut_coordn('longitude', -180, 180) + || $self->ut_sfloatn('altitude') + || $self->ut_textn('vlan_profile') ; return $error if $error; 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 ($self->blocknum) { + $error = $self->ut_foreign_key('blocknum', 'addr_block', 'blocknum'); + return $error if $error; + } + + if ($cust_pkg && $self->blocknum) { + 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') { - $self->ip_addr($self->addr_block->next_free_addr->addr); - if (not $self->ip_addr) { + return "Must supply either address or block" + unless $self->blocknum; + my $next_addr = $self->addr_block->next_free_addr; + if ($next_addr) { + $self->ip_addr($next_addr->addr); + } else { return "No free addresses in addr_block (blocknum: ".$self->blocknum.")"; } } + if (not($self->blocknum)) { + return "Must supply either address or block" + unless ($self->ip_addr and $self->ip_addr ne '0.0.0.0'); + my @block = grep { $_->NetAddr->contains($self->NetAddr) } + map { $_->addr_block } + $self->allowed_routers; + if (scalar(@block)) { + $self->blocknum($block[0]->blocknum); + }else{ + return "Address not with available block."; + } + } + # This should catch errors in the ip_addr. If it doesn't, # they'll almost certainly not map into the block anyway. my $self_addr = $self->NetAddr; #netmask is /32 @@ -223,8 +285,7 @@ sub check { return 'Router '.$router->routernum.' cannot provide svcpart '.$self->svcpart; } - - ''; #no error + $self->SUPER::check; } =item NetAddr @@ -236,7 +297,7 @@ is /32. sub NetAddr { my $self = shift; - return new NetAddr::IP ($self->ip_addr); + new NetAddr::IP ($self->ip_addr); } =item addr_block @@ -247,8 +308,7 @@ Returns the FS::addr_block record (i.e. the address block) for this broadband se sub addr_block { my $self = shift; - - return qsearchs('addr_block', { blocknum => $self->blocknum }); + qsearchs('addr_block', { blocknum => $self->blocknum }); } =back @@ -261,25 +321,19 @@ Returns a list of allowed FS::router objects. sub allowed_routers { my $self = shift; - - return map { $_->router } qsearch('part_svc_router', { svcpart => $self->svcpart }); + map { $_->router } qsearch('part_svc_router', { svcpart => $self->svcpart }); } =head1 BUGS -I think there's one place in the code where we actually use sb_field_hashref. -That's a bug in itself. +The business with sb_field has been 'fixed', in a manner of speaking. -The real problem with it is that we're still grappling with the question of how -tightly xfields should be integrated with real fields. There are a few -different directions we could go with it--we I override several -functions in Record so that xfields behave almost exactly like real fields (can -be set with setfield(), appear in fields() and hash(), used as criteria in -qsearch(), etc.). +allowed_routers isn't agent virtualized because part_svc isn't agent +virtualized =head1 SEE ALSO -FS::svc_Common, FS::Record, FS::addr_block, FS::sb_field, +FS::svc_Common, FS::Record, FS::addr_block, FS::part_svc, schema.html from the base documentation. =cut