},
{
+ 'key' => 'svc_phone-domain',
+ 'section' => '',
+ 'description' => 'Track an optional domain association with each phone service.',
+ 'type' => 'checkbox',
+ },
+
+ {
'key' => 'default_phone_countrycode',
'section' => '',
'description' => 'Default countrcode',
'sip_password', 'varchar', 'NULL', $char_d, '', '',
'phone_name', 'varchar', 'NULL', $char_d, '', '',
'pbxsvc', 'int', 'NULL', '', '', '',
+ 'domsvc', 'int', 'NULL', '', '', '',
],
'primary_key' => 'svcnum',
'unique' => [],
- 'index' => [ [ 'countrycode', 'phonenum' ], ['pbxsvc'] ],
+ 'index' => [ [ 'countrycode', 'phonenum' ], ['pbxsvc'], ['domsvc'] ],
},
'phone_device' => {
$ns;
}
+sub ns_domain {
+ my($self, $svc_phone) = (shift, shift);
+ $svc_phone->domain || $self->option('domain');
+}
+
sub ns_subscriber {
my($self, $svc_phone) = (shift, shift);
- my $domain = $self->option('domain');
+ my $domain = $self->ns_domain($svc_phone);
my $phonenum = $svc_phone->phonenum;
"/domains_config/$domain/subscriber_config/$phonenum";
sub ns_devicename {
my( $self, $svc_phone ) = (shift, shift);
- my $domain = $self->option('domain');
+ my $domain = $self->ns_domain($svc_phone);
#my $countrycode = $svc_phone->countrycode;
my $phonenum = $svc_phone->phonenum;
sub ns_create_or_update {
my($self, $svc_phone, $dial_policy) = (shift, shift, shift);
- my $domain = $self->option('domain');
+ my $domain = $self->ns_domain($svc_phone);
#my $countrycode = $svc_phone->countrycode;
my $phonenum = $svc_phone->phonenum;
sub export_device_insert {
my( $self, $svc_phone, $phone_device ) = (shift, shift, shift);
- #my $domain = $self->option('domain');
+ my $domain = $self->ns_domain($svc_phone);
my $countrycode = $svc_phone->countrycode;
my $phonenum = $svc_phone->phonenum;
#'notes' =>
'server' => 'SiPbx',
- 'domain' => $self->option('domain'),
+ 'domain' => $domain,
'brand' => $phone_device->part_device->devicename,
--- /dev/null
+package FS::svc_Domain_Mixin;
+
+use strict;
+use FS::Conf;
+use FS::Record qw(qsearch qsearchs);
+use FS::part_svc;
+use FS::cust_pkg;
+use FS::cust_svc;
+use FS::svc_domain;
+
+=head1 NAME
+
+FS::svc_Domain_Mixin - Mixin class for svc_classes with a domsvc field
+
+=head1 SYNOPSIS
+
+package FS::svc_table;
+use base qw( FS::svc_Domain_Mixin FS::svc_Common );
+
+=head1 DESCRIPTION
+
+This is a mixin class for svc_ classes that contain a domsvc field linking to
+a domain (see L<FS::svc_domain>).
+
+=head1 METHODS
+
+=over 4
+
+=item domain [ END_TIMESTAMP [ START_TIMESTAMP ] ]
+
+Returns the domain associated with this account.
+
+END_TIMESTAMP and START_TIMESTAMP can optionally be passed when dealing with
+history records.
+
+=cut
+
+sub domain {
+ my $self = shift;
+ #die "svc_acct.domsvc is null for svcnum ". $self->svcnum unless $self->domsvc;
+ return '' unless $self->domsvc;
+ my $svc_domain = $self->svc_domain(@_)
+ or die "no svc_domain.svcnum for domsvc ". $self->domsvc;
+ $svc_domain->domain;
+}
+
+=item svc_domain
+
+Returns the FS::svc_domain record for this account's domain (see
+L<FS::svc_domain>).
+
+=cut
+
+# FS::h_svc_acct has a history-aware svc_domain override
+
+sub svc_domain {
+ my $self = shift;
+ $self->{'_domsvc'}
+ ? $self->{'_domsvc'}
+ : qsearchs( 'svc_domain', { 'svcnum' => $self->domsvc } );
+}
+
+=item domain_select_hash %OPTIONS
+
+Object or class method.
+
+Returns a hash SVCNUM => DOMAIN ... representing the domains this customer
+may at present purchase.
+
+Currently available options are: I<pkgnum> and I<svcpart>.
+
+=cut
+
+sub domain_select_hash {
+ my ($self, %options) = @_;
+ my %domains = ();
+
+ my $conf = new FS::Conf;
+
+ 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('domsvc')->columnflag eq 'S'
+ || $part_svc->part_svc_column('domsvc')->columnflag eq 'F')) {
+ %domains = map { $_->svcnum => $_->domain }
+ map { qsearchs('svc_domain', { 'svcnum' => $_ }) }
+ split(',', $part_svc->part_svc_column('domsvc')->columnvalue);
+ }elsif ($cust_pkg && !$conf->exists('svc_acct-alldomains') ) {
+ %domains = map { $_->svcnum => $_->domain }
+ map { qsearchs('svc_domain', { 'svcnum' => $_->svcnum }) }
+ map { qsearch('cust_svc', { 'pkgnum' => $_->pkgnum } ) }
+ qsearch('cust_pkg', { 'custnum' => $cust_pkg->custnum });
+ }else{
+ %domains = map { $_->svcnum => $_->domain } qsearch('svc_domain', {} );
+ }
+
+ if ($part_svc && $part_svc->part_svc_column('domsvc')->columnflag eq 'D') {
+ my $svc_domain = qsearchs('svc_domain',
+ { 'svcnum' => $part_svc->part_svc_column('domsvc')->columnvalue } );
+ if ( $svc_domain ) {
+ $domains{$svc_domain->svcnum} = $svc_domain->domain;
+ }else{
+ warn "unknown svc_domain.svcnum for part_svc_column domsvc: ".
+ $part_svc->part_svc_column('domsvc')->columnvalue;
+
+ }
+ }
+
+ (%domains);
+}
+
+=back
+
+=head1 BUGS
+
+=head1 SEE ALSO
+
+L<FS::svc_Common>, L<FS::Record>
+
+=cut
+
+1;
package FS::svc_acct;
use strict;
-use vars qw( @ISA $DEBUG $me $conf $skip_fuzzyfiles
+use base qw( FS::svc_Domain_Mixin FS::svc_Common );
+use vars qw( $DEBUG $me $conf $skip_fuzzyfiles
$dir_prefix @shells $usernamemin
$usernamemax $passwordmin $passwordmax
$username_ampersand $username_letter $username_letterfirst
use FS::UI::bytecount;
use FS::UI::Web;
use FS::part_pkg;
-use FS::svc_Common;
-use FS::cust_svc;
use FS::part_svc;
use FS::svc_acct_pop;
use FS::cust_main_invoice;
use FS::svc_www;
use FS::cdr;
-@ISA = qw( FS::svc_Common );
-
$DEBUG = 0;
$me = '[FS::svc_acct]';
select_key => 'svcnum',
select_label => 'domain',
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',
$svc_domain->domain;
}
-=item svc_domain
-
-Returns the FS::svc_domain record for this account's domain (see
-L<FS::svc_domain>).
-
-=cut
-
-# FS::h_svc_acct has a history-aware svc_domain override
-
-sub svc_domain {
- my $self = shift;
- $self->{'_domsvc'}
- ? $self->{'_domsvc'}
- : qsearchs( 'svc_domain', { 'svcnum' => $self->domsvc } );
-}
-
=item cust_svc
Returns the FS::cust_svc record for this account (see L<FS::cust_svc>).
=cut
-=item domain_select_hash %OPTIONS
-
-Returns a hash SVCNUM => DOMAIN ... representing the domains this customer
-may at present purchase.
-
-Currently available options are: I<pkgnum> I<svcpart>
-
-=cut
-
-sub domain_select_hash {
- my ($self, %options) = @_;
- my %domains = ();
- 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('domsvc')->columnflag eq 'S'
- || $part_svc->part_svc_column('domsvc')->columnflag eq 'F')) {
- %domains = map { $_->svcnum => $_->domain }
- map { qsearchs('svc_domain', { 'svcnum' => $_ }) }
- split(',', $part_svc->part_svc_column('domsvc')->columnvalue);
- }elsif ($cust_pkg && !$conf->exists('svc_acct-alldomains') ) {
- %domains = map { $_->svcnum => $_->domain }
- map { qsearchs('svc_domain', { 'svcnum' => $_->svcnum }) }
- map { qsearch('cust_svc', { 'pkgnum' => $_->pkgnum } ) }
- qsearch('cust_pkg', { 'custnum' => $cust_pkg->custnum });
- }else{
- %domains = map { $_->svcnum => $_->domain } qsearch('svc_domain', {} );
- }
-
- if ($part_svc && $part_svc->part_svc_column('domsvc')->columnflag eq 'D') {
- my $svc_domain = qsearchs('svc_domain',
- { 'svcnum' => $part_svc->part_svc_column('domsvc')->columnvalue } );
- if ( $svc_domain ) {
- $domains{$svc_domain->svcnum} = $svc_domain->domain;
- }else{
- warn "unknown svc_domain.svcnum for part_svc_column domsvc: ".
- $part_svc->part_svc_column('domsvc')->columnvalue;
-
- }
- }
-
- (%domains);
-}
-
1;
-
package FS::svc_phone;
use strict;
-use vars qw( @ISA @pw_set $conf );
+use base qw( FS::svc_Domain_Mixin FS::svc_Common );
+use vars qw( @pw_set $conf );
use FS::Conf;
use FS::Record qw( qsearch qsearchs dbh );
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 );
+use FS::svc_domain;
#avoid l 1 and o O 0
@pw_set = ( 'a'..'k', 'm','n', 'p-z', 'A'..'N', 'P'..'Z' , '2'..'9' );
disable_inventory => 1,
disable_select => 1, #UI wonky, pry works otherwise
},
+ 'domsvc' => {
+ label => 'Domain',
+ type => 'select',
+ select_table => 'svc_domain',
+ select_key => 'svcnum',
+ select_label => 'domain',
+ disable_inventory => 1,
+ },
},
};
}
my $self = shift;
my $phonenum = $self->phonenum; #XXX format it better
my $label = $phonenum;
+ $label .= '@'.$self->domain if $self->domsvc;
$label .= ' ('.$self->phone_name.')' if $self->phone_name;
$label;
}
|| $self->ut_anything('sip_password')
|| $self->ut_numbern('pin')
|| $self->ut_textn('phone_name')
- || $self->ut_foreign_keyn('pbxsvc', 'svc_pbx', 'svcnum' )
+ || $self->ut_foreign_keyn('pbxsvc', 'svc_pbx', 'svcnum' )
+ || $self->ut_foreign_keyn('domsvc', 'svc_domain', 'svcnum' )
;
return $error if $error;
t/cust_credit_bill_pkg.t
FS/registrar.pm
t/registrar.t
+FS/svc_Domain_Mixin.pm
+t/svc_Domain_Mixin.t
FS/svc_External_Common.pm
t/svc_External_Common.t
FS/svc_Parent_Mixin.pm
--- /dev/null
+BEGIN { $| = 1; print "1..1\n" }
+END {print "not ok 1\n" unless $loaded;}
+use FS::svc_Domain_Mixin;
+$loaded=1;
+print "ok 1\n";
$f->{'disable_empty'} = $object->svcnum ? 1 : 0,
}
- if ( $f->{'type'} eq 'select-svc_pbx' ) {
+ if ( $f->{'type'} eq 'select-svc_pbx'
+ || $f->{'type'} eq 'select-svc-domain'
+ )
+ {
$f->{'include_opt_callback'} =
sub { ( 'pkgnum' => $pkgnum,
'svcpart' => $svcpart,
<% include( 'elements/svc_Common.html',
'name' => 'Phone number',
'table' => 'svc_phone',
- 'fields' => [ 'countrycode',
- { field => 'phonenum',
- type => 'select-did',
- label => 'Phone number',
- },
- { field => 'pbxsvc',
- type => 'select-svc_pbx',
- label => 'PBX',
- },
- 'sip_password',
- 'pin',
- 'phone_name',
- ],
+ 'fields' => \@fields,
'labels' => {
'countrycode' => 'Country code',
'phonenum' => 'Phone number',
+ 'domsvc' => 'Domain',
'sip_password' => 'SIP password',
'pin' => 'Voicemail PIN',
'phone_name' => 'Name',
die "access denied"
unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+my $conf = new FS::Conf;
+
+my @fields = ( 'countrycode',
+ { field => 'phonenum',
+ type => 'select-did',
+ label => 'Phone number',
+ },
+ );
+
+push @fields, { field => 'domsvc',
+ type => 'select-svc-domain',
+ label => 'Domain',
+ }
+ if $conf->exists('svc_phone-domain');
+
+push @fields, { field => 'pbxsvc',
+ type => 'select-svc_pbx',
+ label => 'PBX',
+ },
+ 'sip_password',
+ 'pin',
+ 'phone_name',
+;
+
</%init>
--- /dev/null
+<SELECT NAME="domsvc" SIZE=1>
+% foreach my $svcnum (
+% sort { $svc_domain{$a} cmp $svc_domain{$b} }
+% keys %svc_domain
+% ) {
+
+ <OPTION VALUE="<% $svcnum %>"
+ <% ($svcnum == $domsvc) ? ' SELECTED' : '' %>
+ ><% $svc_domain{$svcnum} %>
+
+% }
+
+</SELECT>
+<%init>
+
+my %opt = @_;
+
+my %svc_domain = ();
+my $domsvc;
+
+my $domsvc = $opt{'curr_value'};
+my $part_svc = $opt{'part_svc'}
+ || qsearchs('part_svc', { 'svcpart' => $opt{'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_domain = ();
+
+if ( $domsvc ) {
+ my $svc_domain = qsearchs('svc_domain', { 'svcnum' => $domsvc } );
+ if ( $svc_domain ) {
+ $svc_domain{$svc_domain->svcnum} = $svc_domain;
+ } else {
+ warn "unknown svc_domain.svcnum for svc_acct.domsvc: $domsvc";
+ }
+}
+
+%svc_domain = (
+ %svc_domain,
+ FS::svc_Domain_Mixin->domain_select_hash( 'svcpart' => $part_svc->svcpart,
+ 'pkgnum' => $pkgnum,
+ )
+);
+
+</%init>
--- /dev/null
+%if ( $columnflag eq 'F' ) {
+ <INPUT TYPE="hidden" NAME="domsvc" VALUE="<% $domsvc %>">
+% } else {
+
+ <TR>
+ <TD ALIGN="right"><% $opt{'label'} || 'Domain' %></TD>
+ <TD>
+ <% include('/elements/select-svc-domain.html',
+ 'curr_value' => $domsvc,
+ 'part_svc' => $part_svc,
+ 'cust_pkg' => $cust_pkg,
+ )
+ %>
+ </TD>
+ </TR>
+% }
+<%init>
+
+my %opt = @_;
+
+my $domsvc = $opt{'curr_value'};
+
+#required
+my $part_svc = $opt{'part_svc'}
+ || qsearchs('part_svc', { 'svcpart' => $opt{'svcpart'} });
+
+my $columnflag = $part_svc->part_svc_column('domsvc')->columnflag;
+
+#optional
+my $cust_pkg = $opt{'cust_pkg'};
+$cust_pkg ||= qsearchs('cust_pkg', { 'pkgnum' => $opt{'pkgnum'} })
+ if $opt{'pkgnum'};
+
+</%init>
<% include('elements/svc_Common.html',
'table' => 'svc_phone',
- 'fields' => [qw(
- countrycode
- phonenum
- pbx_title
- sip_password
- pin
- phone_name
- )],
+ 'fields' => \@fields,
'labels' => {
'countrycode' => 'Country code',
'phonenum' => 'Phone number',
+ 'domain' => 'Domain',
'pbx_title' => 'PBX',
'sip_password' => 'SIP password',
'pin' => 'PIN',
%>
<%init>
+my $conf = new FS::Conf;
+
+my @fields = qw( countrycode phonenum );
+push @fields, 'domain' if $conf->exists('svc_phone-domain');
+push @fields, qw( pbx_title sip_password pin phone_name );
+
my $html_foot = sub {
my $svc_phone = shift;