From: ivan Date: Mon, 25 Jan 2010 22:17:14 +0000 (+0000) Subject: linking DIDs and users to PBXes, RT#7051 X-Git-Tag: root_of_svc_elec_features~515 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=9ad4f8407cc106ef5815e65bce2ee873cd0896c2 linking DIDs and users to PBXes, RT#7051 --- diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index 0ffc5bd42..8d35c689b 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -1586,14 +1586,15 @@ sub tables_hashref { 'downbytes_threshold', 'bigint', 'NULL', '', '', '', 'totalbytes','bigint', 'NULL', '', '', '', 'totalbytes_threshold', 'bigint', 'NULL', '', '', '', - 'domsvc', 'int', '', '', '', '', + 'domsvc', 'int', '', '', '', '', + 'pbxsvc', 'int', 'NULL', '', '', '', 'last_login', @date_type, '', '', 'last_logout', @date_type, '', '', ], 'primary_key' => 'svcnum', #'unique' => [ [ 'username', 'domsvc' ] ], 'unique' => [], - 'index' => [ ['username'], ['domsvc'] ], + 'index' => [ ['username'], ['domsvc'], ['pbxsvc'] ], }, 'acct_rt_transaction' => { @@ -2514,10 +2515,11 @@ sub tables_hashref { 'pin', 'varchar', 'NULL', $char_d, '', '', 'sip_password', 'varchar', 'NULL', $char_d, '', '', 'phone_name', 'varchar', 'NULL', $char_d, '', '', + 'pbxsvc', 'int', 'NULL', '', '', '', ], 'primary_key' => 'svcnum', 'unique' => [], - 'index' => [ [ 'countrycode', 'phonenum' ] ], + 'index' => [ [ 'countrycode', 'phonenum' ], ['pbxsvc'] ], }, 'phone_device' => { diff --git a/FS/FS/svc_Common.pm b/FS/FS/svc_Common.pm index a67504a5b..9b2cf7bc4 100644 --- a/FS/FS/svc_Common.pm +++ b/FS/FS/svc_Common.pm @@ -586,6 +586,105 @@ sub part_svc { } +=item svc_pbx + +Returns the FS::svc_pbx record for this service, if any (see L). + +Only makes sense if the service has a pbxsvc field (currently, svc_phone and +svc_acct). + +=cut + +# XXX FS::h_svc_{acct,phone} could have a history-aware svc_pbx override + +sub svc_pbx { + my $self = shift; + return '' unless $self->pbxsvc; + qsearchs( 'svc_pbx', { 'svcnum' => $self->pbxsvc } ); +} + +=item pbx_title + +Returns the title of the FS::svc_pbx record associated with this service, if +any. + +Only makes sense if the service has a pbxsvc field (currently, svc_phone and +svc_acct). + +=cut + +sub pbx_title { + my $self = shift; + my $svc_pbx = $self->svc_pbx or return ''; + $svc_pbx->title; +} + +=item pbx_select_hash %OPTIONS + +Can be called as an object method or a class method. + +Returns a hash SVCNUM => TITLE ... representing the PBXes this customer +that may be associated with this service. + +Currently available options are: I I + +Only makes sense if the service has a pbxsvc field (currently, svc_phone and +svc_acct). + +=cut + +#false laziness w/svc_acct::domain_select_hash +sub pbx_select_hash { + my ($self, %options) = @_; + my %pbxes = (); + my $part_svc; + my $cust_pkg; + + if (ref($self)) { + $part_svc = $self->part_svc; + $cust_pkg = $self->cust_svc->cust_pkg + if $self->cust_svc; + } + + $part_svc = qsearchs('part_svc', { 'svcpart' => $options{svcpart} }) + if $options{'svcpart'}; + + $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $options{pkgnum} }) + if $options{'pkgnum'}; + + if ($part_svc && ( $part_svc->part_svc_column('pbxsvc')->columnflag eq 'S' + || $part_svc->part_svc_column('pbxsvc')->columnflag eq 'F')) { + %pbxes = map { $_->svcnum => $_->title } + map { qsearchs('svc_pbx', { 'svcnum' => $_ }) } + split(',', $part_svc->part_svc_column('pbxsvc')->columnvalue); + } elsif ($cust_pkg) { # && !$conf->exists('svc_acct-alldomains') ) { + %pbxes = map { $_->svcnum => $_->title } + map { qsearchs('svc_pbx', { 'svcnum' => $_->svcnum }) } + map { qsearch('cust_svc', { 'pkgnum' => $_->pkgnum } ) } + qsearch('cust_pkg', { 'custnum' => $cust_pkg->custnum }); + } else { + #XXX agent-virt + warn "hi"; + %pbxes = map { $_->svcnum => $_->title } qsearch('svc_pbx', {} ); + warn %pbxes; + } + + if ($part_svc && $part_svc->part_svc_column('pbxsvc')->columnflag eq 'D') { + my $svc_pbx = qsearchs('svc_pbx', + { 'svcnum' => $part_svc->part_svc_column('pbxsvc')->columnvalue } ); + if ( $svc_pbx ) { + $pbxes{$svc_pbx->svcnum} = $svc_pbx->title; + } else { + warn "unknown svc_pbx.svcnum for part_svc_column pbxsvc: ". + $part_svc->part_svc_column('pbxsvc')->columnvalue; + + } + } + + (%pbxes); + +} + =item set_auto_inventory Sets any fields which auto-populate from inventory (see L). diff --git a/FS/FS/svc_acct.pm b/FS/FS/svc_acct.pm index e5fd5822f..ca33aa858 100644 --- a/FS/FS/svc_acct.pm +++ b/FS/FS/svc_acct.pm @@ -38,6 +38,7 @@ use FS::part_svc; use FS::svc_acct_pop; use FS::cust_main_invoice; use FS::svc_domain; +use FS::svc_pbx; use FS::raddb; use FS::queue; use FS::radius_usergroup; @@ -161,45 +162,71 @@ FS::svc_Common. The following fields are currently supported: =over 4 -=item svcnum - primary key (assigned automatcially for new accounts) +=item svcnum + +Primary key (assigned automatcially for new accounts) =item username -=item _password - generated if blank +=item _password + +generated if blank + +=item _password_encoding + +plain, crypt, ldap (or empty for autodetection) -=item _password_encoding - plain, crypt, ldap (or empty for autodetection) +=item sec_phrase -=item sec_phrase - security phrase +security phrase -=item popnum - Point of presence (see L) +=item popnum + +Point of presence (see L) =item uid =item gid -=item finger - GECOS +=item finger + +GECOS + +=item dir -=item dir - set automatically if blank (and uid is not) +set automatically if blank (and uid is not) =item shell -=item quota - (unimplementd) +=item quota -=item slipip - IP address +=item slipip -=item seconds - +IP address + +=item seconds + +=item upbytes + +=item downbyte + +=item totalbytes + +=item domsvc -=item upbytes - +svcnum from svc_domain -=item downbytes - +=item pbxsvc -=item totalbytes - +Optional svcnum from svc_pbx -=item domsvc - svcnum from svc_domain +=item radius_I -=item radius_I - I (reply) +I (reply) -=item rc_I - I (check) +=item rc_I + +I (check) =back @@ -275,6 +302,20 @@ sub table_info { disable_inventory => 1, }, + 'domsvc' => { + label => 'Domain', + type => 'select', + select_table => 'svc_domain', + select_key => 'svcnum', + select_label => 'domain', + disable_inventory => 1, + + }, + 'pbxsvc' => { label => 'PBX', + type => 'select-svc_pbx.html', + disable_inventory => 1, + disable_select => 1, #UI wonky, pry works otherwise + }, 'usergroup' => { label => 'RADIUS groups', type => 'radius_usergroup_selector', @@ -1011,7 +1052,8 @@ sub check { my $error = $self->ut_numbern('svcnum') #|| $self->ut_number('domsvc') - || $self->ut_foreign_key('domsvc', 'svc_domain', 'svcnum' ) + || $self->ut_foreign_key( 'domsvc', 'svc_domain', 'svcnum' ) + || $self->ut_foreign_keyn('pbxsvc', 'svc_pbx', 'svcnum' ) || $self->ut_textn('sec_phrase') || $self->ut_snumbern('seconds') || $self->ut_snumbern('upbytes') diff --git a/FS/FS/svc_pbx.pm b/FS/FS/svc_pbx.pm index f4ecc049b..49509b5ef 100644 --- a/FS/FS/svc_pbx.pm +++ b/FS/FS/svc_pbx.pm @@ -37,7 +37,21 @@ FS::svc_Common. The following fields are currently supported: =over 4 -=item field - description +=item svcnum + +Primary key (assigned automatcially for new accounts) + +=item id + +(Unique?) number of external record + +=item title + +PBX name + +=item max_extensions + +Maximum number of extensions =back diff --git a/FS/FS/svc_phone.pm b/FS/FS/svc_phone.pm index 88582d393..071b8073c 100644 --- a/FS/FS/svc_phone.pm +++ b/FS/FS/svc_phone.pm @@ -8,6 +8,7 @@ use FS::Msgcat qw(gettext); use FS::svc_Common; use FS::part_svc; use FS::phone_device; +use FS::svc_pbx; @ISA = qw( FS::svc_Common ); @@ -67,6 +68,10 @@ Voicemail PIN =item phone_name +=item pbxsvc + +Optional svcnum from svc_pbx + =back =head1 METHODS @@ -104,6 +109,11 @@ sub table_info { }, 'sip_password' => 'SIP password', 'phone_name' => 'Name', + 'pbxsvc' => { label => 'PBX', + type => 'select-svc_pbx.html', + disable_inventory => 1, + disable_select => 1, #UI wonky, pry works otherwise + }, }, }; } @@ -258,6 +268,7 @@ sub check { || $self->ut_anything('sip_password') || $self->ut_numbern('pin') || $self->ut_textn('phone_name') + || $self->ut_foreign_keyn('pbxsvc', 'svc_pbx', 'svcnum' ) ; return $error if $error; diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html index 43b7afe11..4fe32c15d 100644 --- a/httemplate/edit/elements/edit.html +++ b/httemplate/edit/elements/edit.html @@ -40,6 +40,10 @@ Example: 'disabled' => 0, 'onchange' => 'javascript_function', + 'include_opt_callback' => sub { #my $ = @_; + ( 'option' => 'value', ); + }, + 'm2name_table' => 'table_name', 'm2name_namecol' => 'name_column', #OR# @@ -294,6 +298,10 @@ Example: % $include_common{'colspan'} = $f->{colspan} if $f->{colspan}; % } % +% if ( $f->{include_opt_callback} ) { +% %include_common = ( %include_common, &{ $f->{include_opt_callback} } ); +% } +% % my $layer_prefix_on = ''; % % my $include_sub = sub { diff --git a/httemplate/edit/elements/svc_Common.html b/httemplate/edit/elements/svc_Common.html index ef04bd04a..31d4739bf 100644 --- a/httemplate/edit/elements/svc_Common.html +++ b/httemplate/edit/elements/svc_Common.html @@ -54,6 +54,7 @@ 'field_callback' => sub { my ($cgi, $object, $f) = @_; + my $columndef = $part_svc->part_svc_column($f->{'field'}); my $flag = $columndef->columnflag; if ( $flag eq 'F' ) { @@ -62,6 +63,15 @@ : 'hidden'; $f->{'value'} = $columndef->columnvalue; } + + if ( $f->{'type'} eq 'select-svc_pbx' ) { + $f->{'include_opt_callback'} = + sub { ( 'pkgnum' => $pkgnum, + 'svcpart' => $svcpart, + ); + }; + } + }, 'html_init' => sub { diff --git a/httemplate/edit/part_svc.cgi b/httemplate/edit/part_svc.cgi index 20bc27780..d74e0f20d 100755 --- a/httemplate/edit/part_svc.cgi +++ b/httemplate/edit/part_svc.cgi @@ -289,6 +289,14 @@ that field. % } #endif % $html .= ''; % +% } elsif ( $def->{type} eq 'select-svc_pbx.html' ) { +% +% $html .= include('/elements/select-svc_pbx.html', +% 'element_name' => "${layer}__${field}", +% 'element_etc' => $disabled, +% 'multiple' => ($flag eq 'S'), +% ); +% % } elsif ( $def->{type} eq 'radius_usergroup_selector' ) { % % #XXX disable the RADIUS usergroup selector? ugh it sure does need @@ -304,7 +312,7 @@ that field. % % } else { % -% $html .= 'unknown type'. $def->{type}; +% $html .= 'unknown type '. $def->{type}; % % } % diff --git a/httemplate/edit/svc_acct.cgi b/httemplate/edit/svc_acct.cgi index afbd002c1..2845c8301 100755 --- a/httemplate/edit/svc_acct.cgi +++ b/httemplate/edit/svc_acct.cgi @@ -122,7 +122,14 @@ Service # <% $svcnum ? "$svcnum" : " (NEW)" %>
% } -% + +<% include('/elements/tr-select-svc_pbx.html', + 'curr_value' => $svc_acct->pbxsvc, + 'part_svc' => $part_svc, + 'cust_pkg' => $cust_pkg, + ) +%> + %#pop %my $popnum = $svc_acct->popnum || 0; %if ( $part_svc->part_svc_column('popnum')->columnflag eq 'F' ) { diff --git a/httemplate/edit/svc_phone.cgi b/httemplate/edit/svc_phone.cgi index d7629ab6f..55ee890f4 100644 --- a/httemplate/edit/svc_phone.cgi +++ b/httemplate/edit/svc_phone.cgi @@ -6,6 +6,10 @@ type => 'select-did', label => 'Phone number', }, + { field => 'pbxsvc', + type => 'select-svc_pbx', + label => 'PBX', + }, 'sip_password', 'pin', 'phone_name', @@ -16,6 +20,7 @@ 'sip_password' => 'SIP password', 'pin' => 'Voicemail PIN', 'phone_name' => 'Name', + 'pbxsvc' => 'PBX', }, ) %> diff --git a/httemplate/elements/select-svc_pbx.html b/httemplate/elements/select-svc_pbx.html new file mode 100644 index 000000000..19bce96ca --- /dev/null +++ b/httemplate/elements/select-svc_pbx.html @@ -0,0 +1,57 @@ + +<%init> + +# false laziness w/select-svc_acct-domain.html + +my %opt = @_; + +my $pbxsvc = $opt{'curr_value'}; +my $part_svc = $opt{'part_svc'} + || qsearchs('part_svc', { 'svcpart' => $opt{'svcpart'} }); +my $svcpart = $part_svc ? $part_svc->svcpart : ''; + +#optional +my $cust_pkg = $opt{'cust_pkg'}; +$cust_pkg ||= qsearchs('cust_pkg', { 'pkgnum' => $opt{'pkgnum'} }) + if $opt{'pkgnum'}; + +my $pkgnum = $cust_pkg ? $cust_pkg->pkgnum : ''; + +my %svc_pbx = (); + +if ( $pbxsvc ) { + my $svc_pbx = qsearchs('svc_pbx', { 'svcnum' => $pbxsvc } ); + if ( $svc_pbx ) { + $svc_pbx{$svc_pbx->svcnum} = $svc_pbx; + } else { + warn "unknown svc_pbx.svcnum for svc_acct.pbxsvc: $pbxsvc"; + } +} + +%svc_pbx = ( + %svc_pbx, + FS::svc_Common->pbx_select_hash( 'svcpart' => $svcpart, + 'pkgnum' => $pkgnum, + ) +); + diff --git a/httemplate/elements/tr-select-svc_pbx.html b/httemplate/elements/tr-select-svc_pbx.html new file mode 100644 index 000000000..b02bd65c3 --- /dev/null +++ b/httemplate/elements/tr-select-svc_pbx.html @@ -0,0 +1,60 @@ +%if ( $columnflag eq 'F' || !keys(%svc_pbx) ) { + +% } else { + + + <% $opt{'label'} || 'PBX' %> + + <% include('/elements/select-svc_pbx.html', + 'curr_value' => $pbxsvc, + 'part_svc' => $part_svc, + 'cust_pkg' => $cust_pkg, + ) + %> + + +% } +<%init> + +# false laziness w/tr-select-svc_acct-domain.html + +my %opt = @_; + +my $pbxsvc = $opt{'curr_value'}; + +#required +my $part_svc = $opt{'part_svc'} + || qsearchs('part_svc', { 'svcpart' => $opt{'svcpart'} }); +my $svcpart = + $part_svc ? $part_svc->svcpart : ''; +my $columnflag = + $part_svc ? $part_svc->part_svc_column('pbxsvc')->columnflag : ''; + +#optional +my $cust_pkg = $opt{'cust_pkg'}; +$cust_pkg ||= qsearchs('cust_pkg', { 'pkgnum' => $opt{'pkgnum'} }) + if $opt{'pkgnum'}; + +# false laziness w/select-svc_pbx.html + +my $pkgnum = $cust_pkg ? $cust_pkg->pkgnum : ''; + +my %svc_pbx = (); + +if ( $pbxsvc ) { + my $svc_pbx = qsearchs('svc_pbx', { 'svcnum' => $pbxsvc } ); + if ( $svc_pbx ) { + $svc_pbx{$svc_pbx->svcnum} = $svc_pbx; + } else { + warn "unknown svc_pbx.svcnum for svc_acct.pbxsvc: $pbxsvc"; + } +} + +%svc_pbx = ( + %svc_pbx, + FS::svc_Common->pbx_select_hash( 'svcpart' => $svcpart, + 'pkgnum' => $pkgnum, + ) +); + + diff --git a/httemplate/view/svc_acct.cgi b/httemplate/view/svc_acct.cgi index 44a2aa611..7e94df16d 100755 --- a/httemplate/view/svc_acct.cgi +++ b/httemplate/view/svc_acct.cgi @@ -157,6 +157,13 @@ Service #<% $svcnum %> <% $domain %> +% if ( $svc_acct->pbxsvc ) { + + PBX + <% $svc_acct->pbx_title %> + +%} + Password diff --git a/httemplate/view/svc_phone.cgi b/httemplate/view/svc_phone.cgi index c5fce62d9..59ee2d516 100644 --- a/httemplate/view/svc_phone.cgi +++ b/httemplate/view/svc_phone.cgi @@ -3,6 +3,7 @@ 'fields' => [qw( countrycode phonenum + pbx_title sip_password pin phone_name @@ -10,6 +11,7 @@ 'labels' => { 'countrycode' => 'Country code', 'phonenum' => 'Phone number', + 'pbx_title' => 'PBX', 'sip_password' => 'SIP password', 'pin' => 'PIN', 'phone_name' => 'Name',