diff options
author | Ivan Kohler <ivan@freeside.biz> | 2014-12-04 10:37:16 -0800 |
---|---|---|
committer | Ivan Kohler <ivan@freeside.biz> | 2014-12-04 10:37:16 -0800 |
commit | 8dd41f364aaba88969dfd0908feb22709025e7f6 (patch) | |
tree | 471cb3796019d873da648413d88ca70a657414ed /httemplate | |
parent | a2df4ef9575be1ae2f1f5b9089f121316f796bac (diff) | |
parent | bf50a8356a7344b4f75c7bc7f952019b98867f26 (diff) |
Merge branch 'master' of git.freeside.biz:/home/git/freeside
Diffstat (limited to 'httemplate')
53 files changed, 962 insertions, 451 deletions
diff --git a/httemplate/browse/circuit_provider.html b/httemplate/browse/circuit_provider.html new file mode 100644 index 000000000..12f653251 --- /dev/null +++ b/httemplate/browse/circuit_provider.html @@ -0,0 +1,11 @@ +<& elements/browse-simple.html, + 'table' => 'circuit_provider', + 'title' => 'Circuit providers', + 'menubar' => [ 'Circuit types' => 'circuit_type.html', + 'Circuit terminations' => 'circuit_termination.html' + ], + 'name_singular' => 'provider', + 'name_header' => 'Provider name', + 'name_col' => 'provider', + 'acl' => 'Configuration', +&> diff --git a/httemplate/browse/circuit_termination.html b/httemplate/browse/circuit_termination.html new file mode 100644 index 000000000..830ccf7fb --- /dev/null +++ b/httemplate/browse/circuit_termination.html @@ -0,0 +1,11 @@ +<& elements/browse-simple.html, + 'table' => 'circuit_termination', + 'title' => 'Circuit terminations', + 'menubar' => [ 'Circuit types' => 'circuit_type.html', + 'Circuit providers' => 'circuit_provider.html' + ], + 'name_singular' => 'termination type', + 'name_header' => 'Termination type', + 'name_col' => 'termination', + 'acl' => 'Configuration', +&> diff --git a/httemplate/browse/circuit_type.html b/httemplate/browse/circuit_type.html new file mode 100644 index 000000000..a145d54d9 --- /dev/null +++ b/httemplate/browse/circuit_type.html @@ -0,0 +1,11 @@ +<& elements/browse-simple.html, + 'table' => 'circuit_type', + 'title' => 'Circuit types', + 'menubar' => [ 'Circuit providers' => 'circuit_provider.html', + 'Circuit terminations' => 'circuit_termination.html' + ], + 'name_singular' => 'circuit type', + 'name_header' => 'Circuit type', + 'name_col' => 'typename', + 'acl' => 'Configuration', +&> diff --git a/httemplate/browse/elements/browse-simple.html b/httemplate/browse/elements/browse-simple.html new file mode 100644 index 000000000..cfa27e882 --- /dev/null +++ b/httemplate/browse/elements/browse-simple.html @@ -0,0 +1,57 @@ +<& browse.html, + 'query' => { 'table' => $table }, + 'count_query' => "SELECT COUNT(*) FROM $table", + 'header' => [ '#', $opt{name_header} ], + 'fields' => [ $table_key, $opt{name_col} ], + 'links' => [ '', '' ], + 'link_onclicks' => [ '', $sub_edit_popup ], + 'disableable' => 1, + 'disabled_statuspos' => 2, + 'html_init' => $html_init, + %opt, +&> +<%doc> +A simple wrapper around search/elements/search.html for browsing/editing +tables that only have a primary key, a 'disabled' field, and one other column +which is the object's name or description. Usage: + +<& browse-simple.html, + # required + 'table' => 'mytable', + 'title' => 'My Things', + 'name_singular' => 'thing', + 'name_col' => 'thingname', + 'name_header' => 'Thing name' + 'acl' => 'Configure things', +&> + +</%doc> +<%init> +my %opt = @_; + +my $table = delete $opt{table}; +my $name_singular = $opt{name_singular}; + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right($opt{acl}); + +my $table_key = dbdef->table($table)->primary_key; +my $sub_edit_popup = sub { + my $pkey = $_[0]->get($table_key); + include('/elements/popup_link_onclick.html', + 'action' => $p."edit/$table.html?$pkey", + 'actionlabel' => "Edit $name_singular", + 'width' => 350, + 'height' => 220, + ); +}; + +my $html_init = include('/elements/popup_link.html', + 'action' => $p."edit/$table.html?", + 'actionlabel' => "Add $name_singular", + 'width' => 350, + 'height' => 220, + 'label' => "Add a new $name_singular", +) . '<BR>'; + +</%init> diff --git a/httemplate/browse/part_pkg-fcc.html b/httemplate/browse/part_pkg-fcc.html index e3fd97ccf..bdfb99a59 100755 --- a/httemplate/browse/part_pkg-fcc.html +++ b/httemplate/browse/part_pkg-fcc.html @@ -180,9 +180,11 @@ if ( $cgi->param('redirect') ) { my $html_init = include('/elements/init_overlib.html') . include('/elements/input-fcc_options.html', js_only => 1) . - include('.style'); + include('.style') . + include('.script'); -my $html_form = qq!<FORM ACTION="${p}edit/process/bulk-part_pkg-fcc.html" METHOD="POST"> +my $html_form = qq!<FORM ACTION="${p}edit/process/bulk-part_pkg-fcc.html" METHOD="POST" NAME="bulk-part_pkg-fcc"> + <INPUT TYPE="hidden" NAME="jump"> ( show class: !. include('/elements/select-pkg_class.html', #'curr_value' => $classnum, @@ -193,20 +195,13 @@ my $html_form = qq!<FORM ACTION="${p}edit/process/bulk-part_pkg-fcc.html" METHOD 'disable_empty' => 1, ). ' ) - <BR><BR>' . - qq!<SCRIPT TYPE="text/javascript"> - function filter_change() { - window.location = '! . $cgi->self_url . qq!?classnum=' - + document.getElementById('classnum').value; - } - </SCRIPT>!; + <BR><BR>'; + # restore this only after creating $html_form $cgi->param('classnum', $classnum) if length($classnum); -my $html_foot = qq! - <INPUT TYPE="submit" VALUE="Save changes"> - </FORM>!; +my $html_foot = '</FORM>'; my @menubar = ( 'Package definitions' => $p.'browse/part_pkg.cgi' ); @@ -224,3 +219,17 @@ my @menubar = } </style> </%def> +<%def .script> +<script type="text/javascript"> + function finish_edit_fcc(id) { + cClick(); + document.forms['bulk-part_pkg-fcc']['jump'].value = id; + document.forms['bulk-part_pkg-fcc'].submit(); //immediately save/refresh + } + + function filter_change() { + window.location = '! . $cgi->self_url . qq!?classnum=' + + document.getElementById('classnum').value; + } +</script> +</%def> diff --git a/httemplate/docs/part_svc-table.html b/httemplate/docs/part_svc-table.html index 8d3711d23..5e8d9e5d1 100644 --- a/httemplate/docs/part_svc-table.html +++ b/httemplate/docs/part_svc-table.html @@ -23,6 +23,7 @@ <LI><B>svc_broadband</B>: Wireless broadband <LI><B>svc_cable</B>: Cable <LI><B>svc_dish</B>: DISH Network + <LI><B>svc_circuit</B>: Phone circuits other than DSL </UL> </TD> <TD VALIGN="top"> diff --git a/httemplate/edit/circuit_provider.html b/httemplate/edit/circuit_provider.html new file mode 100644 index 000000000..6c8dcedac --- /dev/null +++ b/httemplate/edit/circuit_provider.html @@ -0,0 +1,21 @@ +<& elements/edit.html, + 'popup' => 1, + 'table' => 'circuit_provider', + 'name_singular' => 'provider', + 'labels' => \%labels, + 'fields' => \@fields, +&> +<%init> +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my @fields = ( + 'provider', + { field => 'disabled', type => 'checkbox', value => 'Y' } +); +my %labels = ( + 'providernum' => '', + 'provider' => 'Provider name', + 'disabled' => 'Disabled' +); +</%init> diff --git a/httemplate/edit/circuit_termination.html b/httemplate/edit/circuit_termination.html new file mode 100644 index 000000000..0317bced5 --- /dev/null +++ b/httemplate/edit/circuit_termination.html @@ -0,0 +1,21 @@ +<& elements/edit.html, + 'popup' => 1, + 'table' => 'circuit_termination', + 'name_singular' => 'termination type', + 'labels' => \%labels, + 'fields' => \@fields, +&> +<%init> +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my @fields = ( + 'termination', + { field => 'disabled', type => 'checkbox', value => 'Y' } +); +my %labels = ( + 'termnum' => '', + 'termination' => 'Termination type', + 'disabled' => 'Disabled' +); +</%init> diff --git a/httemplate/edit/circuit_type.html b/httemplate/edit/circuit_type.html new file mode 100644 index 000000000..897758897 --- /dev/null +++ b/httemplate/edit/circuit_type.html @@ -0,0 +1,21 @@ +<& elements/edit.html, + 'popup' => 1, + 'table' => 'circuit_type', + 'name_singular' => 'circuit type', + 'labels' => \%labels, + 'fields' => \@fields, +&> +<%init> +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +my @fields = ( + 'typename', + { field => 'disabled', type => 'checkbox', value => 'Y' } +); +my %labels = ( + 'typenum' => '', + 'typename' => 'Circuit type', + 'disabled' => 'Disabled' +); +</%init> diff --git a/httemplate/edit/credit-cust_bill_pkg.html b/httemplate/edit/credit-cust_bill_pkg.html index 40faddc46..85f794317 100644 --- a/httemplate/edit/credit-cust_bill_pkg.html +++ b/httemplate/edit/credit-cust_bill_pkg.html @@ -80,9 +80,9 @@ <& /elements/tr-select-reason.html, 'field' => 'reasonnum', 'reason_class' => 'R', - #XXX reconcile both this and show_taxes wanteding to enable this + #XXX reconcile both this and show_taxes wanting to enable this 'id' => 'select_reason', - 'control_button' => "document.getElementById('credit_button')", + 'control_button' => 'credit_button', 'cgi' => $cgi, &> diff --git a/httemplate/edit/cust_credit.cgi b/httemplate/edit/cust_credit.cgi index a3565f125..29801efef 100755 --- a/httemplate/edit/cust_credit.cgi +++ b/httemplate/edit/cust_credit.cgi @@ -24,7 +24,7 @@ <& /elements/tr-select-reason.html, 'field' => 'reasonnum', 'reason_class' => 'R', - 'control_button' => "document.getElementById('confirm_credit_button')", + 'control_button' => 'confirm_credit_button', 'cgi' => $cgi, &> diff --git a/httemplate/edit/cust_main/bottomfixup.js b/httemplate/edit/cust_main/bottomfixup.js index 5a8835f53..6a9deb92a 100644 --- a/httemplate/edit/cust_main/bottomfixup.js +++ b/httemplate/edit/cust_main/bottomfixup.js @@ -100,14 +100,13 @@ function copyelement(from, to) { //alert(from + " (" + from.type + "): " + to.name + " => " + to.value); } -% # the value in pre+'censustract' is the confirmed censustract; if it's set, -% # and the user hasn't changed it manually, skip this +% # the value in pre+'censustract' is the confirmed censustract (either from +% # the previous saved record, or from address standardization (if the backend +% # supports it), or from an aborted previous submit. only need to reconfirm +% # if it's empty. function confirm_censustract(pre) { var cf = document.CustomerForm; - if ( cf.elements[pre+'censustract'].value == '' || - cf.elements[pre+'enter_censustract'].value != - cf.elements[pre+'censustract'].value ) - { + if ( cf.elements[pre+'censustract'].value == '' ) { var address_info = form_address_info(); address_info[pre+'latitude'] = cf.elements[pre+'latitude'].value; address_info[pre+'longitude'] = cf.elements[pre+'longitude'].value; @@ -116,10 +115,13 @@ function confirm_censustract(pre) { '<%$p%>/misc/confirm-censustract.html', 'q=' + encodeURIComponent(JSON.stringify(address_info)), function() { - overlib( OLresponseAJAX, CAPTION, 'Confirm censustract', STICKY, - AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, - 576, HEIGHT, 268, BGCOLOR, '#333399', CGCOLOR, '#333399', - TEXTSIZE, 3 ); + if ( OLresponseAJAX ) { + overlib( OLresponseAJAX, CAPTION, 'Confirm censustract', STICKY, + AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, + 576, HEIGHT, 268, BGCOLOR, '#333399', CGCOLOR, '#333399', + TEXTSIZE, 3 ); + } else + submit_continue(); }, 0); } else submit_continue(); diff --git a/httemplate/edit/elements/part_svc_column.html b/httemplate/edit/elements/part_svc_column.html index 64901a80f..6dcb602fe 100644 --- a/httemplate/edit/elements/part_svc_column.html +++ b/httemplate/edit/elements/part_svc_column.html @@ -249,7 +249,10 @@ that field. </TR> % } % # special case: services with attached routers (false laziness...) -% if ( $svcdb eq 'svc_acct' or $svcdb eq 'svc_broadband' or $svcdb eq 'svc_dsl' ) { +% if ( $svcdb eq 'svc_acct' +% or $svcdb eq 'svc_broadband' +% or $svcdb eq 'svc_dsl' +% or $svcdb eq 'svc_circuit' ) { % push @fields, 'has_router'; <TR> <TD COLSPAN=3 ALIGN="right"> diff --git a/httemplate/edit/elements/svc_Common.html b/httemplate/edit/elements/svc_Common.html index fc29327ae..97b630f76 100644 --- a/httemplate/edit/elements/svc_Common.html +++ b/httemplate/edit/elements/svc_Common.html @@ -103,10 +103,42 @@ my $flag = $columndef->columnflag; if ( $flag eq 'F' ) { #fixed - $f->{'type'} = length($columndef->columnvalue) - ? 'fixed' - : 'hidden'; $f->{'value'} = $columndef->columnvalue; + if (length($columndef->columnvalue)) { + + if ( $f->{'type'} =~ /^select-?(.*)/ ) { + # try to display this in a user-friendly manner + if ( $f->{'table'} ) { # find matching records + $f->{'value_col'} ||= + dbdef->table($f->{'table'})->primary_key; + + my @values = split(',', $f->{'value'}); + my @recs; + foreach (@values) { + push @recs, qsearchs( $f->{'table'}, + { $f->{'value_col'} => $_ } + ); + } + if ( @recs ) { + my $method = $f->{'name_col'}; + if ( $f->{'multiple'} ) { + $f->{'formatted_value'} = [ + map { $_->method } @recs + ]; + } else { # there shouldn't be more than one... + $f->{'formatted_value'} = $recs[0]->$method; + } + } # if not, then just let tr-fixed display the + # values as-is + + } # other select types probably don't matter + } # if it's a select + + $f->{'type'} = 'fixed'; + + } else { # fixed, null + $f->{'type'} = 'hidden'; + } } elsif ( $flag eq 'A' ) { #auto assign from inventory $f->{'type'} = 'hidden'; @@ -127,16 +159,14 @@ }; } elsif ( $flag eq 'S' #selectable choice - && $f->{type} !~ /^select-svc(-domain|_pbx)$/ ) { + && $f->{type} !~ /^select-svc/ ) { $f->{type} = 'select'; $f->{options} = [ split( /\s*,\s*/, $columndef->columnvalue) ]; - } + } # shouldn't this be enforced for all 'S' fields? - if ( $f->{'type'} eq 'select-svc_pbx' - || $f->{'type'} eq 'select-svc-domain' - ) + if ( $f->{'type'} =~ /^select-svc/ ) { $f->{'include_opt_callback'} = sub { ( 'pkgnum' => $pkgnum, diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi index af69f71f9..2ae9df3ec 100755 --- a/httemplate/edit/part_pkg.cgi +++ b/httemplate/edit/part_pkg.cgi @@ -895,6 +895,11 @@ my $javascript = <<'END'; } } + function finish_edit_fcc(id) { + cClick(); + show_fcc_options(id); // refresh the display + } + END my $warning = diff --git a/httemplate/edit/process/bulk-part_pkg-fcc.html b/httemplate/edit/process/bulk-part_pkg-fcc.html index 4a0fb2a22..8ef330829 100644 --- a/httemplate/edit/process/bulk-part_pkg-fcc.html +++ b/httemplate/edit/process/bulk-part_pkg-fcc.html @@ -17,7 +17,7 @@ % } <% $cgi->redirect($fsurl.'browse/part_pkg-fcc.html?redirect='.$session) %> % } else { -<% $cgi->redirect($fsurl.'browse/part_pkg-fcc.html?classnum='.$classnum) %> +<% $cgi->redirect($fsurl.'browse/part_pkg-fcc.html?classnum='.$classnum.$jump) %> % } <%init> my $curuser = $FS::CurrentUser::CurrentUser; @@ -40,4 +40,8 @@ foreach my $param ($cgi->param) { my $classnum = $cgi->param('classnum'); +my $jump = ''; +if ( $cgi->param('jump') =~ /^pkgpart(\d+)$/ ) { + $jump = '#'.$1; +} </%init> diff --git a/httemplate/edit/process/circuit_provider.html b/httemplate/edit/process/circuit_provider.html new file mode 100644 index 000000000..0a91a178d --- /dev/null +++ b/httemplate/edit/process/circuit_provider.html @@ -0,0 +1,11 @@ +<& elements/process.html, + 'table' => 'circuit_provider', + 'viewall_dir' => 'browse', + 'popup_reload' => 'Updating', +&> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/circuit_termination.html b/httemplate/edit/process/circuit_termination.html new file mode 100644 index 000000000..94d29c05c --- /dev/null +++ b/httemplate/edit/process/circuit_termination.html @@ -0,0 +1,11 @@ +<& elements/process.html, + 'table' => 'circuit_termination', + 'viewall_dir' => 'browse', + 'popup_reload' => 'Updating', +&> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/circuit_type.html b/httemplate/edit/process/circuit_type.html new file mode 100644 index 000000000..58f461e2c --- /dev/null +++ b/httemplate/edit/process/circuit_type.html @@ -0,0 +1,11 @@ +<& elements/process.html, + 'table' => 'circuit_type', + 'viewall_dir' => 'browse', + 'popup_reload' => 'Updating', +&> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Configuration'); + +</%init> diff --git a/httemplate/edit/process/credit-cust_bill_pkg.html b/httemplate/edit/process/credit-cust_bill_pkg.html index 8e66368d4..75900bde5 100644 --- a/httemplate/edit/process/credit-cust_bill_pkg.html +++ b/httemplate/edit/process/credit-cust_bill_pkg.html @@ -27,19 +27,35 @@ foreach my $billpkgnum_setuprecur (@billpkgnum_setuprecurs) { push @amounts, $amount; } -my $error = FS::cust_credit->credit_lineitems( +my $reasonnum = $cgi->param('reasonnum'); +$reasonnum =~ /^(-?\d+)$/ or die "Illegal reasonnum"; +$reasonnum = $1; + +my $error; +if ($reasonnum == -1) { + my $new_reason = FS::reason->new({ + map { $_ => scalar( $cgi->param("select_reason_new_$_") ) } + qw( reason_type reason ) + }); + $error = $new_reason->insert; + $reasonnum = $new_reason->reasonnum; +} + +if ( !$reasonnum ) { + $error ||= 'Reason required' +} + +$error ||= FS::cust_credit->credit_lineitems( #the lineitems to credit 'billpkgnums' => \@billpkgnums, 'setuprecurs' => \@setuprecurs, 'amounts' => \@amounts, 'apply' => ( $cgi->param('apply') eq 'yes' ), + 'reasonnum' => $reasonnum, - #the credit - 'newreasonnum' => scalar($cgi->param('newreasonnum')), - 'newreasonnum_type' => scalar($cgi->param('newreasonnumT')), map { $_ => scalar($cgi->param($_)) } #fields('cust_credit') - qw( custnum _date amount reason reasonnum addlinfo ), #pkgnum eventnum + qw( custnum _date amount addlinfo ), #pkgnum eventnum ); </%init> diff --git a/httemplate/edit/process/cust_credit.cgi b/httemplate/edit/process/cust_credit.cgi index 245f31af7..e442d7fa6 100755 --- a/httemplate/edit/process/cust_credit.cgi +++ b/httemplate/edit/process/cust_credit.cgi @@ -1,5 +1,4 @@ %if ( $error ) { -% $cgi->param('reasonnum', $reasonnum); % $cgi->param('error', $error); % $dbh->rollback if $oldAutoCommit; % @@ -37,19 +36,11 @@ my $oldAutoCommit = $FS::UID::AutoCommit; local $FS::UID::AutoCommit = 0; my $dbh = dbh; -my $error = ''; -if ($reasonnum == -1) { - - $error = 'Enter a new reason (or select an existing one)' - unless $cgi->param('newreasonnum') !~ /^\s*$/; - my $reason = new FS::reason { - 'reason_type' => scalar($cgi->param('newreasonnumT')), - 'reason' => scalar($cgi->param('newreasonnum')), - }; - $error ||= $reason->insert; - $cgi->param('reasonnum', $reason->reasonnum) - unless $error; +my ($reasonnum, $error) = $m->comp('/misc/process/elements/reason'); +if (!$reasonnum) { + $error ||= 'Reason required' } +$cgi->param('reasonnum', $reasonnum) unless $error; unless ($error) { my $new = new FS::cust_credit ( { diff --git a/httemplate/edit/process/elements/svc_Common.html b/httemplate/edit/process/elements/svc_Common.html index 55ecc5f79..ca336a126 100644 --- a/httemplate/edit/process/elements/svc_Common.html +++ b/httemplate/edit/process/elements/svc_Common.html @@ -29,7 +29,7 @@ my $args_callback = sub { map { $_ => $cgi->param("router_$_") } qw( routernum routername blocknum ) }); - if (length($router->routername) == 0) { + if ($router->blocknum and length($router->routername) == 0) { #sensible default $router->set('routername', $svc->label); } diff --git a/httemplate/edit/process/part_event.html b/httemplate/edit/process/part_event.html index 481439d53..bac69241c 100644 --- a/httemplate/edit/process/part_event.html +++ b/httemplate/edit/process/part_event.html @@ -62,12 +62,17 @@ my $value = join(',', $cgi->param( "$prefix$option" ) ); if ( $option eq 'reasonnum' && $value == -1 ) { - $value = { - 'typenum' => scalar( $cgi->param( "new$prefix${option}T" ) ), - 'reason' => scalar( $cgi->param( "new$prefix${option}" ) ), - }; + my $reason_prefix = $object->action . '_' . $option . '_new_'; + my $new_reason = FS::reason->new; + foreach ( qw( reason_type reason unsuspend pkgpart + unsuspend_hold unused_credit ) ) { + $new_reason->set($_, $cgi->param("$reason_prefix$_")); + } + warn Dumper $new_reason; + my $error = $new_reason->insert; + die "error creating reason: $error" if $error; + $value = $new_reason->reasonnum; } - ( $option => $value ); } @{ $object->option_fields_listref }; diff --git a/httemplate/edit/process/svc_circuit.html b/httemplate/edit/process/svc_circuit.html new file mode 100644 index 000000000..d28f91329 --- /dev/null +++ b/httemplate/edit/process/svc_circuit.html @@ -0,0 +1,11 @@ +<& elements/svc_Common.html, + table => 'svc_circuit', + edit_ext => 'html', + redirect => popurl(3)."view/svc_circuit.html?", +&> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + +</%init> diff --git a/httemplate/edit/svc_circuit.cgi b/httemplate/edit/svc_circuit.cgi new file mode 100644 index 000000000..3f9bad5b1 --- /dev/null +++ b/httemplate/edit/svc_circuit.cgi @@ -0,0 +1,54 @@ +<& elements/svc_Common.html, + 'table' => 'svc_circuit', + 'fields' => \@fields, +&> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific? + +my $conf = new FS::Conf; +my $date_format = $conf->config('date_format') || '%m/%d/%Y'; + +my @fields = ( + { field => 'providernum', + type => 'select-table', + table => 'circuit_provider', + name_col => 'provider', + disable_empty => 1, + }, + { field => 'typenum', + type => 'select-table', + table => 'circuit_type', + name_col => 'typename', + disable_empty => 1, + }, + { field => 'termnum', + type => 'select-table', + table => 'circuit_termination', + name_col => 'termination', + disable_empty => 1, + }, + { field => 'circuit_id', + size => 40, + }, + { field => 'desired_due_date', + type => 'input-date-field', + }, + { field => 'due_date', + type => 'input-date-field', + }, + 'vendor_order_id', + 'vendor_qual_id', + 'vendor_order_status', + 'endpoint_ip_addr', + { field => 'endpoint_mac_addr', + type => 'input-mac_addr', + }, +); + +# needed: a new_callback to migrate vendor quals over to circuits + +#my ($svc_new_callback, $svc_edit_callback, $svc_error_callback); + +</%init> diff --git a/httemplate/edit/svc_phone.cgi b/httemplate/edit/svc_phone.cgi index f8582057e..f9c0d4005 100644 --- a/httemplate/edit/svc_phone.cgi +++ b/httemplate/edit/svc_phone.cgi @@ -2,17 +2,12 @@ 'table' => 'svc_phone', 'fields' => [], 'begin_callback' => $begin_callback, - 'svc_new_callback' => sub { - my( $cgi, $svc_x, $part_svc, $cust_pkg, $fields, $opt ) = @_; - $svc_x->locationnum($cust_pkg->locationnum) if $cust_pkg; - }, - 'svc_edit_callback' => sub { - my( $cgi, $svc_x, $part_svc, $cust_pkg, $fields, $opt) = @_; - my $conf = new FS::Conf; - $svc_x->sip_password('*HIDDEN*') unless $conf->exists('showpasswords'); - }, + 'svc_new_callback' => $svc_callback, + 'svc_edit_callback' => $svc_callback, + 'svc_error_callback' => $svc_callback, &> <%init> +my $conf = new FS::Conf; my $begin_callback = sub { my( $cgi, $fields, $opt ) = @_; @@ -25,8 +20,6 @@ my $begin_callback = sub { die "access denied" unless $FS::CurrentUser::CurrentUser->access_right($right); - my $conf = new FS::Conf; - push @$fields, 'countrycode', { field => 'phonenum', @@ -149,7 +142,26 @@ my $begin_callback = sub { } -}; +}; # begin_callback +# svc_edit_callback / svc_new_callback +my $svc_callback = sub { + my ($cgi, $svc_x, $part_svc, $cust_pkg, $fields, $opt) = @_; + push @$fields, { + field => 'circuit_svcnum', + type => 'select-svc_circuit', + cust_pkg => $cust_pkg, + part_svc => $part_svc, + }; + + if ( $cust_pkg and not $svc_x->svcnum ) { + # new service, default to package location + $svc_x->set('locationnum', $cust_pkg->locationnum); + } + + if ( not $conf->exists('showpasswords') and $svc_x->svcnum ) { + $svc_x->sip_password('*HIDDEN*'); + } +}; </%init> diff --git a/httemplate/elements/input-fcc_options.html b/httemplate/elements/input-fcc_options.html index fb2500fa5..064c647fc 100644 --- a/httemplate/elements/input-fcc_options.html +++ b/httemplate/elements/input-fcc_options.html @@ -80,7 +80,8 @@ function show_fcc_options(id) { } } // is_phone if ( curr_values['is_voip'] ) { - out += '<li><strong>VoIP</strong> telephone service</li>'; + out += '<li><strong>VoIP</strong> telephone service over <strong>' + + media + '</strong></li>'; out += '<li><strong>' + curr_values['voip_sessions'] + '</strong> sessions allowed</li>'; if ( curr_values['voip_lastmile'] ) { diff --git a/httemplate/elements/location.html b/httemplate/elements/location.html index 5cdc424a7..214a7d5f2 100644 --- a/httemplate/elements/location.html +++ b/httemplate/elements/location.html @@ -59,12 +59,7 @@ Example: </TR> % } else { - - <INPUT TYPE = "hidden" - NAME = "<%$pre%>locationname" - ID = "<%$pre%>locationname" - VALUE = "<% $object->get('locationname') |h %>" - > + <& hidden.html, field => $pre.'locationname', value => $object->get('locationname') &> % } @@ -102,10 +97,7 @@ Example: % } else { # alternate format - <INPUT TYPE = "hidden" - NAME = "<%$pre%>address2" - VALUE = "<% $object->get('address2') |h %>" - > +<& hidden.html, field => $pre.'address2', value => $object->get('address2') &> <TR> <<%$th%> ALIGN="right">Unit type and #</<%$th%>> @@ -227,14 +219,14 @@ Example: </TR> % } else { % foreach (qw(latitude longitude)) { -<INPUT TYPE="hidden" NAME="<% $_ %>" ID="<% $_ %>" VALUE="<% $object->get($_) |h%>"> +<& hidden.html, field => $pre.$_, value => $object->get($_) &> % } % } -<INPUT TYPE="hidden" NAME="<%$pre%>coord_auto" VALUE="<% $object->coord_auto %>"> - -<INPUT TYPE="hidden" NAME="<%$pre%>geocode" VALUE="<% $object->geocode %>"> -<INPUT TYPE="hidden" NAME="<%$pre%>censustract" VALUE="<% $object->censustract %>"> -<INPUT TYPE="hidden" NAME="<%$pre%>censusyear" VALUE="<% $object->censusyear %>"> +% +% foreach (qw(coord_auto geocode censustract censusyear)) { + <& hidden.html, field => $pre.$_, value => $object->get($_) &> +% } +% % if ( $opt{enable_censustract} ) { <TR> <TD ALIGN="right">Census tract</TD> @@ -259,7 +251,7 @@ Example: </TD> </TR> % } else { - <INPUT TYPE="hidden" ID="<%$pre%>" NAME="<%$pre%>district" VALUE="<% $object->district %>"> + <& hidden.html, field => $pre.'district', value => $object->get('district') &> % } %# For address standardization: @@ -267,11 +259,11 @@ Example: %# to re-standardize % foreach (qw(address1 city state country zip latitude % longitude censustract district addr_clean) ) { -<INPUT TYPE="hidden" NAME="old_<%$pre.$_%>" ID="old_<%$pre.$_%>" VALUE="<% $object->get($_) |h%>"> +<& hidden.html, field => 'old_'.$pre.$_, value => $object->get($_) &> % } %# Placeholders -<INPUT TYPE="hidden" NAME="<%$pre%>cachenum" VALUE=""> -<INPUT TYPE="hidden" NAME="<%$pre%>addr_clean" VALUE=""> +<& hidden.html, field => $pre.'cachenum', value => '' &> +<& hidden.html, field => $pre.'addr_clean', value => '' &> <SCRIPT TYPE="text/javascript"> <&| /elements/onload.js &> @@ -306,6 +298,26 @@ Example: el.attachEvent('onchange', clear_coords); } } + function clear_censustract() { + // if the user manually edits the census tract, clear the 'hard' census + // tract field so that we can re-verify and present a confirmation popup + + // get the ID of the hidden censustract field + var censustract_id = this.id.replace('enter_', ''); + var el = document.getElementById(censustract_id); + if (el) { + el.value = ''; + } + } + var el = document.getElementById('<%$pre%>enter_censustract'); + if (el) { + if ( el.addEventListener ) { + el.addEventListener('change', clear_censustract); + } else if ( el.attachEvent ) { + el.attachEvent('onchange', clear_censustract); + } + } + </&> </SCRIPT> diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html index 3236bc14b..03ce20185 100644 --- a/httemplate/elements/menu.html +++ b/httemplate/elements/menu.html @@ -564,6 +564,12 @@ tie my %config_conferencing, 'Tie::IxHash', 'Quality levels' => [ $fsurl.'browse/conferencing_quality.html', '' ], ; +tie my %config_circuit, 'Tie::IxHash', + 'Circuit types' => [ $fsurl.'browse/circuit_type.html', '' ], + 'Circuit providers' => [ $fsurl.'browse/circuit_provider.html', '' ], + 'Termination types' => [ $fsurl.'browse/circuit_termination.html', '' ], +; + tie my %config_export_svc, 'Tie::IxHash', (); if ( $curuser->access_right('Configuration') ) { $config_export_svc{'Service definitions'} = [ $fsurl.'browse/part_svc.cgi', 'Services are items you offer to your customers' ]; @@ -584,6 +590,8 @@ $config_export_svc{'Conferencing'} = [ \%config_conferencing, '' ] if $curuser->access_right('Configuration'); $config_export_svc{'Alarm'} = [ \%config_alarm, '' ] if $curuser->access_right(['Alarm configuration', 'Alarm global configuration']); +$config_export_svc{'Circuits'} = [ \%config_circuit, '' ] + if $curuser->access_right('Configuration'); $config_export_svc{'Hardware types'} = [ $fsurl.'browse/hardware_class.html', 'Set up hardware type catalog' ] if $curuser->access_right('Configuration'); diff --git a/httemplate/elements/standardize_locations.js b/httemplate/elements/standardize_locations.js index 817a2e357..ff7183b26 100644 --- a/httemplate/elements/standardize_locations.js +++ b/httemplate/elements/standardize_locations.js @@ -279,10 +279,7 @@ function setselect(el, value) { function confirm_censustract() { % if ( FS::Conf->new->exists('cust_main-require_censustract') ) { var form = document.<% $formname %>; - // this is the existing/confirmed censustract, not the manually entered one - if ( form.elements['censustract'].value == '' || - form.elements['censustract'].value != - form.elements['enter_censustract'].value ) { + if ( form.elements['censustract'].value == '' ) { var address_info = form_address_info(); address_info['latitude'] = form.elements['latitude'].value; address_info['longitude'] = form.elements['longitude'].value; @@ -290,10 +287,15 @@ function confirm_censustract() { '<%$p%>/misc/confirm-censustract.html', 'q=' + encodeURIComponent(JSON.stringify(address_info)), function() { - overlib( OLresponseAJAX, CAPTION, 'Confirm censustract', STICKY, - AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, - 576, HEIGHT, 268, BGCOLOR, '#333399', CGCOLOR, '#333399', - TEXTSIZE, 3 ); + if ( OLresponseAJAX ) { + overlib( OLresponseAJAX, CAPTION, 'Confirm censustract', STICKY, + AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, + 576, HEIGHT, 268, BGCOLOR, '#333399', CGCOLOR, '#333399', + TEXTSIZE, 3 ); + } else { + // no response + <% $post_censustract %>; + } }, 0); } else { diff --git a/httemplate/elements/tr-censustract.html b/httemplate/elements/tr-censustract.html index bd014f11b..7a4b34943 100644 --- a/httemplate/elements/tr-censustract.html +++ b/httemplate/elements/tr-censustract.html @@ -1,4 +1,4 @@ -% if ($censustract) { +% if ($location->country eq 'US' and $censustract) { <TR> <TD ALIGN="right"><% mt('Census tract') |h %></TD> <TD COLSPAN=5> diff --git a/httemplate/elements/tr-input-fcc_options.html b/httemplate/elements/tr-input-fcc_options.html index 87117ef1e..1f63588ad 100644 --- a/httemplate/elements/tr-input-fcc_options.html +++ b/httemplate/elements/tr-input-fcc_options.html @@ -7,96 +7,9 @@ </STYLE> <TR> <TH COLSPAN=2> - <& hidden.html, 'id' => $id, @_ &> -%# <& input-text.html, 'id' => $id, @_ &> # XXX debugging - <UL ID="<%$id%>_display_fcc_options" CLASS="fcc_options"> - </UL> - <BUTTON TYPE="button" onclick="edit_fcc_options()"> - Edit - </BUTTON> -% # show some kind of useful summary of the FCC options here + <& input-fcc_options.html, 'id' => $id, @_ &> </TH> </TR> -<SCRIPT TYPE="text/javascript"> -function edit_fcc_options() { - <& popup_link_onclick.html, - 'action' => $fsurl.'misc/part_pkg_fcc_options.html?id=' . $id, - 'actionlabel' => 'FCC Form 477 options', - 'width' => 760, - 'height' => 600, - &> -} -var technology_labels = <% encode_json(FS::part_pkg_fcc_option->technology_labels) %>; -function show_fcc_options() { - var curr_values = JSON.parse(document.getElementById('<% $id %>').value); - // hardcoded for the same reasons as misc/part_pkg_fcc_options - var out = ''; - var tech = curr_values['technology']; - if ( tech ) { - if (technology_labels[tech]) { - tech = technology_labels[tech]; - } else { - tech = 'Technology '+tech; // unknown? - } - } - var media = curr_values['media'] || 'unknown media'; - media = media.toLowerCase(); - if ( curr_values['is_consumer'] ) { - out += '<li><strong>Consumer-grade</strong></li>>'; - } else { - out += '<li><strong>Business-grade</strong></li>'; - } - if ( curr_values['is_broadband'] ) { - out += '<li>Broadband via <strong>' + tech + '</strong>' - + '<li><strong>' + curr_values['broadband_downstream'] - + 'Mbps </strong> down / ' - + '<strong>' + curr_values['broadband_upstream'] - + 'Mbps </strong> up</li>'; - } - if ( curr_values['is_phone'] ) { - if ( curr_values['phone_wholesale'] ) { - out += '<li>Wholesale telephone</li>'; - if ( curr_values['phone_vges'] ) { - out += '<li><strong>' + curr_values['phone_vges'] + '</strong>' - + ' switched voice-grade lines</li>'; - } - if ( curr_values['phone_circuits'] ) { - out += '<li><strong>' + curr_values['phone_circuits'] + '</strong>' - + ' unswitched circuits</li>'; - } - } else { - // enduser service - out += '<li>Local telephone over <strong>' + media + '</strong></li>' - + '<li><strong>' + curr_values['phone_lines'] - + '</strong> voice-grade lines</li>'; - if ( curr_values['phone_localloop'] == 'resale' ) { - out += '<li><strong>Resold</strong> from another carrier</li>>'; - } else if ( curr_values['phone_localloop'] == 'leased' ) { - out += '<li>Using <strong>leased circuits</strong> from another carrier</li>'; - } else if ( curr_values['phone_localloop'] == 'owned' ) { - out += '<li>Using <strong>our own circuits</strong></li>'; - } - if ( curr_values['phone_longdistance'] ) { - out += '<li>Includes <strong>long-distance service</strong></li>'; - } - } - } // is_phone - if ( curr_values['is_voip'] ) { - out += '<li><strong>VoIP</strong> telephone service</li>'; - if ( curr_values['voip_ott'] ) { - out += '<li>Using a <strong>separate</strong> last-mile connection</li>'; - } else { - out += '<li><strong>Including</strong> last-mile connection</li>'; - } - } // is_voip - - var out_ul = document.getElementById('<% $id %>_display_fcc_options'); - out_ul.innerHTML = out; -} -<&| onload.js &> - show_fcc_options(); -</&> -</SCRIPT> <%init> my %opt = @_; my $id = $opt{id} || $opt{field}; diff --git a/httemplate/elements/tr-select-reason.html b/httemplate/elements/tr-select-reason.html index b7a715b42..0df7c058a 100755 --- a/httemplate/elements/tr-select-reason.html +++ b/httemplate/elements/tr-select-reason.html @@ -29,109 +29,119 @@ Example: </%doc> +% # note style improvements. +% # - no more conditionally included code here +% # - callers are not expected to pass javascript fragments +% # - no redundant checking of ACLs or parameters +% # - form fields are grouped for easy management +% # - use the standard select-table widget instead of ad hoc crap <SCRIPT TYPE="text/javascript"> - function sh_add<% $func_suffix %>() - { - var hints = <% encode_json(\@hints) %>; + function <% $id %>_changed() { + var hints = <% encode_json(\%all_hints) %>; var select_reason = document.getElementById('<% $id %>'); -% if ( $class eq 'S' ) { document.getElementById('<% $id %>_hint').innerHTML = - hints[select_reason.selectedIndex]; -% } + hints[select_reason.value] || ''; - if (select_reason.selectedIndex == 0){ - <% $controlledbutton ? $controlledbutton.'.disabled = true;' : ';' %> - }else{ - <% $controlledbutton ? $controlledbutton.'.disabled = false;' : ';' %> + // toggle submit button state + var submit_button = document.getElementById(<% $opt{control_button} |js_string %>); + if (submit_button) { + submit_button.disabled = ( select_reason.value == 0 ); } -%if ($curuser->access_right($add_access_right)){ - - if (select_reason.selectedIndex == - (select_reason.length - 1)) { - document.getElementById('new<% $id %>').disabled = false; - document.getElementById('new<% $id %>').style.display = 'inline'; - document.getElementById('new<% $id %>Label').style.display = 'inline'; - document.getElementById('new<% $id %>T').disabled = false; - document.getElementById('new<% $id %>T').style.display = 'inline'; - document.getElementById('new<% $id %>TLabel').style.display = 'inline'; + // toggle visibility of 'new reason' fields + var new_fields = document.getElementById('<% $id %>_new_fields'); + if ( select_reason.value == -1 ) { + new_fields.disabled = false; + new_fields.style.display = ''; } else { - document.getElementById('new<% $id %>').disabled = true; - document.getElementById('new<% $id %>').style.display = 'none'; - document.getElementById('new<% $id %>Label').style.display = 'none'; - document.getElementById('new<% $id %>T').disabled = true; - document.getElementById('new<% $id %>T').style.display = 'none'; - document.getElementById('new<% $id %>TLabel').style.display = 'none'; + new_fields.disabled = true; + new_fields.style.display = 'none'; } -%} - } + <&| onload.js &> <% $id %>_changed(); </&> </SCRIPT> -<TR> - <TD ALIGN="right"><% mt('Reason') |h %></TD> - <TD> - <SELECT id="<% $id %>" name="<% $name %>" onFocus="sh_add<% $func_suffix %>()" onChange="sh_add<% $func_suffix %>()"> - <OPTION VALUE="" <% ($init_reason eq '') ? 'SELECTED' : '' %>><% mt('Select Reason...') |h %></OPTION> -% foreach my $reason (@reasons) { - <OPTION VALUE="<% $reason->reasonnum %>" <% ($init_reason == $reason->reasonnum) ? 'SELECTED' : '' %>><% $reason->reasontype->type %> : <% $reason->reason %></OPTION> -% } -% if ($curuser->access_right($add_access_right)) { - <OPTION VALUE="-1" <% ($init_reason == -1) ? 'SELECTED' : '' %>><% mt('Add new reason') |h %></OPTION> -% } -% - </SELECT> - </TD> -</TR> - -% my @types = qsearch( 'reason_type', { 'class' => $class } ); -% if (scalar(@types) < 1) { # we should never reach this -<TR> - <TD ALIGN="right"> - <P><% mt('No reason types. Please add some.') |h %></P> - </TD> -</TR> -% }elsif (scalar(@types) == 1) { -<TR> - <TD ALIGN="right"> - <P id="new<% $name %>TLabel" style="display:<% $display %>"><% mt('Reason Type') |h %></P> - </TD> - <TD> - <P id="new<% $name %>T" disabled="<% $disabled %>" style="display:<% $display %>"><% $types[0]->type %> - <INPUT type="hidden" name="new<% $name %>T" value="<% $types[0]->typenum %>"> - </TD> -</TR> - -% }else{ - -<TR> - <TD ALIGN="right"> - <P id="new<% $id %>TLabel" style="display:<% $display %>"><% mt('Reason Type') |h %></P> - </TD> - <TD> - <SELECT id="new<% $id %>T" name="new<% $name %>T" "<% $disabled %>" style="display:<% $display %>"> -% for my $type (@types) { - <OPTION VALUE="<% $type->typenum %>" <% ($init_type == $type->typenum) ? 'SELECTED' : '' %>><% $type->type %></OPTION> -% } - </SELECT> - </TD> -</TR> -% } +%# sadly can't just use add_inline here, as we have non-text fields +<& tr-select-table.html, + 'label' => 'Reason', + 'field' => $name, + 'id' => $id, + 'table' => 'reason', + 'records' => \@reasons, + 'label_callback' => sub { my $reason = shift; + $reason->type . ' : ' . $reason->reason }, + 'disable_empty' => 1, + 'pre_options' => [ 0 => 'Select reason...' ], + 'post_options' => [ -1 => 'Add new reason' ], + 'curr_value' => $init_reason, + 'onchange' => $id.'_changed()', +&> + +% # "add new reason" fields +% # should be a <fieldset>, but that doesn't fit well into the table + +<TR id="<% $id %>_new_fields"> + <TD COLSPAN=2> + <TABLE CLASS="inv" STYLE="text-align: left"> + + <& tr-input-text.html, + label => 'New reason', + field => $id.'_new_reason' + &> + +% my @types = qsearch( 'reason_type', { 'class' => $class } ); +% if (scalar(@types) < 1) { # we should never reach this + <TR> + <TD ALIGN="right"> + <P><% mt('No reason types. Please add some.') |h %></P> + </TD> + </TR> +% } elsif (scalar(@types) == 1) { + <& tr-fixed.html, + label => 'Reason type', + field => $id.'_new_reason_type', + curr_value => $types[0]->typenum, + formatted_value => $types[0]->type, + &> +% } else { # more than one type, the normal case + <& tr-select-table.html, + label => 'Reason type', + field => $id.'_new_reason_type', + table => 'reason_type', + name_col => 'type', + hashref => { 'class' => $class }, + disable_empty => 1, + &> +% } # scalar(@types) % if ( $class eq 'S' ) { -<TR> - <TD COLSPAN=2 ALIGN="center" id="<% $id %>_hint"> - </TD> -</TR> + <& tr-checkbox.html, + label => 'Credit the unused portion of service when suspending', + field => $id.'_new_unused_credit', + value => 'Y' + &> + <& tr-select-part_pkg.html, + label => 'Charge this fee when unsuspending', + field => $id.'_new_unsuspend_pkgpart', + hashref => { disabled => '', freq => '0' }, + empty_label => 'none', + &> + <& tr-checkbox.html, + label => 'Hold unsuspension fee until the next bill', + field => $id.'_new_unsuspend_hold', + value => 'Y', + &> % } + </table> + </td> +</tr> +% # container for hints <TR> - <TD ALIGN="right"> - <P id="new<% $id %>Label" style="display:<% $display %>"><% mt('New Reason') |h %></P> + <TD COLSPAN=2 ALIGN="center" id="<% $id %>_hint" style="font-size:small"> </TD> - <TD><INPUT id="new<% $id %>" name="new<% $name %>" type="text" value="<% $init_newreason |h %>" "<% $disabled %>" style="display:<% $display %>"></TD> </TR> <%init> @@ -148,11 +158,8 @@ if ( $opt{'cgi'} ) { $init_reason = $opt{'curr_value'}; } -my $controlledbutton = $opt{'control_button'}; - -( my $func_suffix = $name ) =~ s/\./_/g; - -my $id = $opt{'id'} || $func_suffix; +my $id = $opt{'id'} || $name; +$id =~ s/\./_/g; # for edit/part_event my $add_access_right; if ($class eq 'C') { @@ -167,41 +174,21 @@ if ($class eq 'C') { die "illegal class: $class"; } -my( $display, $disabled ) = ( 'none', 'DISABLED' ); -my( $init_type, $init_newreason ) = ( '', '' ); -if ($init_reason == -1 || ref($init_reason) ) { - - $display = 'inline'; - $disabled = ''; - - if ( ref($init_reason) ) { - $init_type = $init_reason->{'typenum'}; - $init_newreason = $init_reason->{'reason'}; - $init_reason = -1; - } elsif ( $opt{'cgi'} ) { - $init_type = $opt{'cgi'}->param( "new${name}T" ); - $init_newreason = $opt{'cgi'}->param( "new$name" ); - } - -} - -my $extra_sql = - "WHERE class = '$class' and (disabled = '' OR disabled is NULL)"; - my @reasons = qsearch({ - table => 'reason', - hashref => {}, - extra_sql => $extra_sql, - addl_from => 'LEFT JOIN reason_type '. - ' ON reason_type.typenum = reason.reason_type', - order_by => 'ORDER BY reason_type.type ASC, reason.reason ASC', + 'table' => 'reason', + 'addl_from' => ' LEFT JOIN reason_type'. + ' ON (reason.reason_type = reason_type.typenum)', + 'hashref' => { disabled => '' }, + 'extra_sql' => " AND reason_type.class = '$class'", + 'order_by' => ' ORDER BY type, reason', }); -my @hints; +my %all_hints; if ( $class eq 'S' ) { my $conf = FS::Conf->new; - @hints = ( '' ); + %all_hints = ( 0 => '', -1 => '' ); foreach my $reason (@reasons) { + my @hints; if ( $reason->unsuspend_pkgpart ) { my $part_pkg = FS::part_pkg->by_key($reason->unsuspend_pkgpart); if ( $part_pkg ) { @@ -225,15 +212,13 @@ if ( $class eq 'S' ) { '<FONT COLOR="#ff0000">Unsuspend pkg #'.$reason->unsuspend_pkgpart. ' not found.</FONT>'; } - } else { #no unsuspend_pkgpart - push @hints, ''; } + if ( $reason->unused_credit ) { + push @hints, mt('The customer will be credited for unused time.'); + } + $all_hints{ $reason->reasonnum } = join('<BR>', @hints); } - push @hints, ''; # for the "new reason" case - @hints = map {'<FONT SIZE="-1">'.$_.'</FONT>'} @hints; } - my $curuser = $FS::CurrentUser::CurrentUser; - </%init> diff --git a/httemplate/elements/tr-select-svc_circuit.html b/httemplate/elements/tr-select-svc_circuit.html new file mode 100644 index 000000000..fb55501c5 --- /dev/null +++ b/httemplate/elements/tr-select-svc_circuit.html @@ -0,0 +1,41 @@ +% if ( $columnflag eq 'F' ) { # no good reason for this, but support it anyway + <INPUT TYPE="hidden" NAME="circuit_svcnum" VALUE="<% $circuit_svcnum %>"> +% } else { + <& tr-select-table.html, + 'table' => 'svc_circuit', + 'name_col' => 'circuit_id', + 'empty_label' => ' ', + %select_hash, + %opt + &> +% } +<%init> + +my %opt = @_; + +my $circuit_svcnum; +if ( $opt{'curr_value'} =~ /^(\d+)$/ ) { + $circuit_svcnum = $1; +} + +# generally not the svcpart of the circuit service (or any circuit service) +my $part_svc = $opt{'part_svc'} + || qsearchs('part_svc', { 'svcpart' => $opt{'svcpart'} }); + +my $columnflag = $part_svc->part_svc_column('circuit_svcnum')->columnflag; + +my $cust_pkg = $opt{'cust_pkg'}; +my $custnum; +$custnum = $cust_pkg->custnum if $cust_pkg; + +my %select_hash; +if ( $custnum =~ /^(\d+)$/ ) { + %select_hash = ( + 'addl_from' => ' LEFT JOIN cust_svc USING (svcnum)' . + ' LEFT JOIN cust_pkg USING (pkgnum)', + 'extra_sql' => " WHERE cust_pkg.custnum = $custnum". + " OR svcnum = $circuit_svcnum", + ); +} + +</%init> diff --git a/httemplate/misc/cancel_cust.html b/httemplate/misc/cancel_cust.html index ebf111935..85367026c 100644 --- a/httemplate/misc/cancel_cust.html +++ b/httemplate/misc/cancel_cust.html @@ -48,7 +48,7 @@ toggle(false); 'field' => 'reasonnum', 'reason_class' => 'C', 'cgi' => $cgi, - 'control_button' => "document.getElementById('confirm_cancel_cust_button')", + 'control_button' => 'confirm_cancel_cust_button', &> </TABLE> diff --git a/httemplate/misc/cancel_pkg.html b/httemplate/misc/cancel_pkg.html index e2734e97d..c80b2b278 100755 --- a/httemplate/misc/cancel_pkg.html +++ b/httemplate/misc/cancel_pkg.html @@ -6,9 +6,9 @@ <INPUT TYPE="hidden" NAME="pkgnum" VALUE="<% $pkgnum %>"> <INPUT TYPE="hidden" NAME="method" VALUE="<% $method %>"> -<BR><BR> +<BR> <% emt(ucfirst($method)." [_1]", $part_pkg->pkg_comment(cust_pkg=>$cust_pkg) ) %> -<% ntable("#cccccc", 2) %> +<table style="background-color: #cccccc; border-spacing: 2; width: 100%"> % my $date_init = 0; % if ($method eq 'expire' || $method eq 'adjourn' || $method eq 'resume') { @@ -58,7 +58,7 @@ field => 'reasonnum', reason_class => $class, curr_value => $reasonnum, - control_button => "document.getElementById('confirm_cancel_pkg_button')", + control_button => "confirm_cancel_pkg_button", &> % } diff --git a/httemplate/misc/confirm-censustract.html b/httemplate/misc/confirm-censustract.html index 880cade3a..024bc17c4 100644 --- a/httemplate/misc/confirm-censustract.html +++ b/httemplate/misc/confirm-censustract.html @@ -1,3 +1,10 @@ +% if ( !$error and !$new_tract ) { +% # then set_censustract returned nothing +% # because it's not relevant for this address +% # so output nothing (forces confirm_censustract() to continue) +% $m->clear_buffer; +% $m->abort; +% } <CENTER><BR><B> % if ( $error ) { Census tract error diff --git a/httemplate/misc/cust_main-cancel.cgi b/httemplate/misc/cust_main-cancel.cgi index 2ae9f1021..a78a8b3dc 100755 --- a/httemplate/misc/cust_main-cancel.cgi +++ b/httemplate/misc/cust_main-cancel.cgi @@ -22,51 +22,43 @@ if ( $cgi->param('custnum') =~ /^(\d+)$/ ) { $custnum = $1; } -#false laziness w/process/cancel_pkg.html -#untaint reasonnum -my $reasonnum = $cgi->param('reasonnum'); -$reasonnum =~ /^(-?\d+)$/ || die "Illegal reasonnum"; -$reasonnum = $1; - -if ($reasonnum == -1) { - $reasonnum = { - 'typenum' => scalar( $cgi->param('newreasonnumT') ), - 'reason' => scalar( $cgi->param('newreasonnum' ) ), - }; +#untaint reasonnum / create new reason +my ($reasonnum, $error) = $m->comp('process/elements/reason'); +if (!$reasonnum) { + $error ||= 'Reason required' } -#eslaf - my $cust_main = qsearchs( { 'table' => 'cust_main', 'hashref' => { 'custnum' => $custnum }, 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql, } ); -my @errors; -if($cgi->param('now_or_later')) { +if ( $error ) { + # do nothing +} elsif ( $cgi->param('now_or_later') ) { $expire = parse_datetime($expire); if($expire) { #warn "setting expire dates on custnum#$custnum\n"; my @pkgs = $cust_main->ncancelled_pkgs; - @errors = grep {$_} map { $_->cancel( + my @errors = grep {$_} map { $_->cancel( 'reason' => $reasonnum, 'date' => $expire, ) } @pkgs; + $error = join(' / ', @errors); } else { - @errors = ("error parsing expire date: ".$cgi->param('expire')); + $error = ("error parsing expire date: ".$cgi->param('expire')); } } else { warn "cancelling $cust_main"; - @errors = $cust_main->cancel( + $error = $cust_main->cancel( 'ban' => $ban, 'reason' => $reasonnum, ); } -my $error = join(' / ', @errors) if scalar(@errors); if ( $error ) { $cgi->param('error', $error); diff --git a/httemplate/misc/cust_main-suspend.cgi b/httemplate/misc/cust_main-suspend.cgi index 61851364e..7a501d61a 100755 --- a/httemplate/misc/cust_main-suspend.cgi +++ b/httemplate/misc/cust_main-suspend.cgi @@ -22,50 +22,39 @@ if ( $cgi->param('custnum') =~ /^(\d+)$/ ) { $custnum = $1; } -#false laziness w/process/cancel_pkg.html - -#untaint reasonnum -my $reasonnum = $cgi->param('reasonnum'); -$reasonnum =~ /^(-?\d+)$/ || die "Illegal reasonnum"; -$reasonnum = $1; - -if ($reasonnum == -1) { - $reasonnum = { - 'typenum' => scalar( $cgi->param('newreasonnumT') ), - 'reason' => scalar( $cgi->param('newreasonnum' ) ), - }; +#untaint reasonnum / create new reason +my ($reasonnum, $error) = $m->comp('process/elements/reason'); +if (!$reasonnum) { + $error ||= 'Reason required'; } -#eslaf - my $cust_main = qsearchs( { 'table' => 'cust_main', 'hashref' => { 'custnum' => $custnum }, 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql, } ); -my @errors; -if($cgi->param('now_or_later')) { +if ( $error ) { + # do nothing +} elsif ( $cgi->param('now_or_later') ) { $adjourn = parse_datetime($adjourn); if($adjourn) { #warn "setting adjourn dates on custnum#$custnum\n"; my @pkgs = $cust_main->unsuspended_pkgs; - @errors = grep {$_} map { $_->suspend( + my @errors = grep {$_} map { $_->suspend( 'reason' => $reasonnum, 'date' => $adjourn, ) } @pkgs; + $error = join(' / ', @errors); + } else { + $error = ("error parsing adjourn date: ".$cgi->param('adjourn')); } - else { - @errors = ("error parsing adjourn date: ".$cgi->param('adjourn')); - } -} -else { +} else { warn "suspending $cust_main"; - @errors = $cust_main->suspend( + $error = $cust_main->suspend( 'reason' => $reasonnum, ); } -my $error = join(' / ', @errors) if scalar(@errors); if ( $error ) { $cgi->param('error', $error); diff --git a/httemplate/misc/part_pkg_fcc_options.html b/httemplate/misc/part_pkg_fcc_options.html index 27b45e003..0db4e2503 100644 --- a/httemplate/misc/part_pkg_fcc_options.html +++ b/httemplate/misc/part_pkg_fcc_options.html @@ -156,8 +156,7 @@ function save_changes() { } parent_input.value = JSON.stringify(data); // update the display - parent.show_fcc_options(parent_input.id); - parent.cClick(); //overlib + parent.finish_edit_fcc(parent_input.id); } function enable_fieldset(fieldset_id) { diff --git a/httemplate/misc/process/cancel_pkg.html b/httemplate/misc/process/cancel_pkg.html index a106b845a..47ceca23b 100755 --- a/httemplate/misc/process/cancel_pkg.html +++ b/httemplate/misc/process/cancel_pkg.html @@ -65,17 +65,12 @@ if ( $method eq 'suspend' ) { #or 'adjourn' my $cust_pkg = qsearchs( 'cust_pkg', {'pkgnum'=>$pkgnum} ); -#untaint reasonnum -my $reasonnum = $cgi->param('reasonnum'); -if ( $method !~ /^(unsuspend|uncancel)$/ ) { - $reasonnum =~ /^(-?\d+)$/ or die "Illegal reasonnum"; - $reasonnum = $1; - - if ($reasonnum == -1) { - $reasonnum = { - 'typenum' => scalar( $cgi->param('newreasonnumT') ), - 'reason' => scalar( $cgi->param('newreasonnum' ) ), - }; +#untaint reasonnum, and set up new reason if appropriate +my ($reasonnum, $error); +if ($method ne 'resume' and $method ne 'uncancel') { + ($reasonnum, $error) = $m->comp('elements/reason'); + if (!$reasonnum) { + $error ||= 'Reason required'; } } @@ -87,7 +82,7 @@ my $bill = my $svc_fatal = ( $cgi->param('svc_not_fatal') ne 'Y' ); -my $error = $cust_pkg->$method( 'reason' => $reasonnum, +$error ||= $cust_pkg->$method( 'reason' => $reasonnum, 'date' => $date, 'resume_date' => $resume_date, 'last_bill' => $last_bill, diff --git a/httemplate/misc/process/elements/reason b/httemplate/misc/process/elements/reason new file mode 100644 index 000000000..ae92a7528 --- /dev/null +++ b/httemplate/misc/process/elements/reason @@ -0,0 +1,17 @@ +<%init> +#untaint reasonnum, and set up new reason if appropriate +my $reasonnum = $cgi->param('reasonnum'); +$reasonnum =~ /^(-?\d+)$/ or die "Illegal reasonnum"; +$reasonnum = $1; + +my $error; +if ($reasonnum == -1) { + my $new_reason = FS::reason->new({ + map { $_ => scalar( $cgi->param("reasonnum_new_$_") ) } + qw( reason_type reason unsuspend_pkgpart unsuspend_hold unused_credit ) + }); # not sanitizing them here, but check() will do it + $error = $new_reason->insert; + $reasonnum = $new_reason->reasonnum; +} +return ($reasonnum, $error); +</%init> diff --git a/httemplate/misc/suspend_cust.html b/httemplate/misc/suspend_cust.html index 8eedd0a57..83d974300 100644 --- a/httemplate/misc/suspend_cust.html +++ b/httemplate/misc/suspend_cust.html @@ -40,7 +40,7 @@ toggle(false); 'field' => 'reasonnum', 'reason_class' => 'S', 'cgi' => $cgi, - 'control_button' => "document.getElementById('confirm_suspend_cust_button')", + 'control_button' => 'confirm_suspend_cust_button', &> </TABLE> diff --git a/httemplate/misc/xmlhttp-address_standardize.html b/httemplate/misc/xmlhttp-address_standardize.html index 618265364..d0255a02a 100644 --- a/httemplate/misc/xmlhttp-address_standardize.html +++ b/httemplate/misc/xmlhttp-address_standardize.html @@ -43,6 +43,10 @@ foreach my $pre ( @prefixes ) { last if !$all_same; } + $all_same = 0 if ( length( $old{$pre.'censustract'} ) > 0 && + length( $new{$pre.'censustract'} ) > 0 && + $old{$pre.'censustract'} ne $new{$pre.'censustract'} ); + $all_same = 0 if $new{$pre.'error'}; } diff --git a/httemplate/search/477.html b/httemplate/search/477.html index 244bfa1df..ff2ac8638 100644 --- a/httemplate/search/477.html +++ b/httemplate/search/477.html @@ -212,7 +212,7 @@ my $part_titles = FS::Report::FCC_477->parts; </%def> <%def .header_voip> <TR CLASS="head"> - <TD ROWSPAN=2>State</TD> + <TD ROWSPAN=3>State</TD> <TD COLSPAN=2>VoIP OTT</TD> <TD COLSPAN=8>VoIP Non-OTT</TD> </TR> diff --git a/httemplate/search/svc_circuit.cgi b/httemplate/search/svc_circuit.cgi new file mode 100755 index 000000000..c14c55fdc --- /dev/null +++ b/httemplate/search/svc_circuit.cgi @@ -0,0 +1,65 @@ +<& elements/svc_Common.html, + 'title' => 'Circuit Search Results', + 'name' => 'circuit services', + 'query' => $query, + 'count_query' => $query->{'count_query'}, + 'redirect' => [ popurl(2). "view/svc_circuit.html?", 'svcnum' ], + 'header' => [ '#', + 'Provider', + 'Type', + 'Termination', + 'Circuit ID', + 'IP Address', + FS::UI::Web::cust_header($cgi->param('cust_fields')), + ], + 'fields' => [ 'svcnum', + 'provider', + 'typename', + 'termination', + 'circuit_id', + 'ip_addr', + \&FS::UI::Web::cust_fields, + ], + 'links' => [ $link, + '', + '', + '', + $link, + $link, + FS::UI::Web::cust_links($cgi->param('cust_fields')), + ], + 'align' => 'rlllll'. FS::UI::Web::cust_aligns(), + 'color' => [ + ('') x 6, + FS::UI::Web::cust_colors(), + ], + 'style' => [ + ('') x 6, + FS::UI::Web::cust_styles(), + ], + +&> +<%init> + +die "access denied" unless + $FS::CurrentUser::CurrentUser->access_right('List services'); + +my $conf = new FS::Conf; + +my %search_hash; +if ( $cgi->param('magic') eq 'unlinked' ) { + %search_hash = ( 'unlinked' => 1 ); +} else { + foreach (qw( custnum agentnum svcpart cust_fields )) { + $search_hash{$_} = $cgi->param($_) if $cgi->param($_); + } + foreach (qw(pkgpart routernum towernum sectornum)) { + $search_hash{$_} = [ $cgi->param($_) ] if $cgi->param($_); + } +} + +my $query = FS::svc_circuit->search(\%search_hash); + +my $link = [ $p.'view/svc_circuit.html?', 'svcnum' ]; + +</%init> diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi index 4880ac3dc..833b6d08c 100755 --- a/httemplate/view/cust_main.cgi +++ b/httemplate/view/cust_main.cgi @@ -60,8 +60,8 @@ function areyousure(href, message) { 'actionlabel' => emt('Confirm Suspension'), 'color' => '#ff9900', 'cust_main' => $cust_main, - 'width' => 616, #make room for reasons - 'height' => 366, + 'width' => 768, #make room for reasons + 'height' => 450, } &> | % } @@ -91,7 +91,7 @@ function areyousure(href, message) { 'color' => '#ff0000', 'cust_main' => $cust_main, 'width' => 616, #make room for reasons - 'height' => 366, + 'height' => 410, } &> | % } diff --git a/httemplate/view/cust_main/locations.html b/httemplate/view/cust_main/locations.html index fdbbc396b..336c1aa98 100755 --- a/httemplate/view/cust_main/locations.html +++ b/httemplate/view/cust_main/locations.html @@ -35,16 +35,18 @@ table.location { <TH COLSPAN=5> <DIV CLASS="<% $loc->disabled ? 'loclabel disabled' : 'loclabel' %>"> <% $loc->location_label %> -% if ( $loc->censustract ) { - <BR> - <FONT SIZE=-1> - <% $loc->censustract %> (<% $loc->censusyear %> census) - </FONT> -% } elsif ( $conf->exists('cust_main-require_censustract') ) { - <BR> - <FONT SIZE=-1 COLOR="#ee3300"> - <% emt('Census tract unknown') %> - </FONT> +% if ( $loc->country eq 'US' ) { # only U.S. census tracts for now +% if ( $loc->censustract ) { + <BR> + <FONT SIZE=-1> + <% $loc->censustract %> (<% $loc->censusyear %> census) + </FONT> +% } elsif ( $conf->exists('cust_main-require_censustract') ) { + <BR> + <FONT SIZE=-1 COLOR="#ee3300"> + <% emt('Census tract unknown') %> + </FONT> +% } % } </DIV> <DIV STYLE="display: inline; float:right;"> diff --git a/httemplate/view/cust_main/packages/location.html b/httemplate/view/cust_main/packages/location.html index c5ef10ee4..99d91e514 100644 --- a/httemplate/view/cust_main/packages/location.html +++ b/httemplate/view/cust_main/packages/location.html @@ -30,16 +30,18 @@ &> </FONT> % } -% if ( $loc->censustract ) { - <BR> - <FONT SIZE=-1> - <% $loc->censustract %> (<% $loc->censusyear %> census) - </FONT> -% } elsif ( $opt{'cust_main-require_censustract'} ) { - <BR> - <FONT SIZE=-1 COLOR="#ee3300"> - <% emt('Census tract unknown') %> - </FONT> +% if ( $loc->country eq 'US' ) { +% if ( $loc->censustract ) { + <BR> + <FONT SIZE=-1> + <% $loc->censustract %> (<% $loc->censusyear %> census) + </FONT> +% } elsif ( $opt{'cust_main-require_censustract'} ) { + <BR> + <FONT SIZE=-1 COLOR="#ee3300"> + <% emt('Census tract unknown') %> + </FONT> +% } % } % if ( $default ) { diff --git a/httemplate/view/cust_main/packages/status.html b/httemplate/view/cust_main/packages/status.html index accdb4588..f760d6fcc 100644 --- a/httemplate/view/cust_main/packages/status.html +++ b/httemplate/view/cust_main/packages/status.html @@ -582,6 +582,7 @@ sub pkg_suspend_link { 'actionlabel' => emt('Suspend'), 'color' => '#FF9900', 'cust_pkg' => shift, + 'height' => 420, ) } @@ -592,6 +593,7 @@ sub pkg_adjourn_link { 'actionlabel' => emt('Adjourn'), 'color' => '#CC6600', 'cust_pkg' => shift, + 'height' => 445, ) } diff --git a/httemplate/view/elements/svc_Common.html b/httemplate/view/elements/svc_Common.html index b12d2ddcd..6c5c90201 100644 --- a/httemplate/view/elements/svc_Common.html +++ b/httemplate/view/elements/svc_Common.html @@ -32,6 +32,15 @@ function areyousure(href) { window.location.href = href; } </SCRIPT> +<STYLE> + td.content { + background-color: #ffffff; + } + .error { + color: #ff0000; + font-weight: bold; + } +</STYLE> % if ( $custnum ) { @@ -67,61 +76,20 @@ function areyousure(href) { <% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %> -% my @inventory_items = $svc_x->inventory_item; % foreach my $f ( @$fields ) { -% -% my($field, $type, $value); -% if ( ref($f) ) { -% $field = $f->{'field'}; -% $type = $f->{'type'} || 'text'; -% if ( $f->{'value_callback'} ) { -% my $hack_strict_refs = \&{ $f->{'value_callback'} }; -% $value = &$hack_strict_refs($svc_x); -% } else { -% $value = encode_entities($svc_x->$field); -% } -% } else { -% $field = $f; -% $type = 'text'; -% $value = encode_entities($svc_x->$field); -% } -% -% my $columndef = $part_svc->part_svc_column($field); -% if ( $columndef->columnflag =~ /^[MA]$/ && $columndef->columnvalue =~ /,/ ) -% { -% # inventory-select field with multiple classes -% # show the class name to disambiguate -% my ($item) = grep { $_->svc_field eq $field } @inventory_items; -% my $class = qsearchs('inventory_class', { classnum => $item->classnum }); -% $value .= ' <i>('. $class->classname . ')</i>' if $class; -% } -% unless ($columndef->columnflag eq 'F' && !length($columndef->columnvalue)) { - +% my ($field, $label, $value) = &{ $format_field }($f); +% next if !$field; <TR> <TD ALIGN="right"> - <% ( $opt{labels} && exists $opt{labels}->{$field} ) - ? $opt{labels}->{$field} - : $field - %> + <% $label %> </TD> -% $value = time2str($date_format,$value) -% if $type eq 'date' && $value; -% $value = time2str("$date_format %H:%M",$value) -% if $type eq 'datetime' && $value; -% $value = $value eq 'Y' ? emt('Yes') : emt('No') -% if $type eq 'checkbox'; -% $value .= ' ('. (Net::MAC::Vendor::lookup($value))->[0]. ')' -% if $type =~ /mac_addr$/ && $value =~ /\w/i; -% #eventually more options for <SELECT>, etc. fields - - <TD BGCOLOR="#ffffff"><% $value %><TD> - + <TD CLASS="content"> + <% $value %> + </TD> </TR> -% } -% -% } +% } % foreach (sort { $a cmp $b } $svc_x->virtual_fields) { <% $svc_x->pvf($_)->widget('HTML', 'view', $svc_x->getfield($_)) %> @@ -193,7 +161,7 @@ my $svc_x = qsearchs({ my $cust_svc = $svc_x->cust_svc; my ($label, $value, $svcdb, $part_svc ); -my $labels = $opt{labels}; #not -> here +my $labels = $opt{labels} || {}; if ( $cust_svc ) { ($label, $value, $svcdb) = $cust_svc->label; @@ -227,7 +195,10 @@ if ($pkgnum) { # attached routers if ( my $router = qsearchs('router', { svcnum => $svc_x->svcnum }) ) { - push @$fields, qw(router_routername router_block); + push @$fields, + 'router_routername', + 'router_block'; + $labels->{'router_routername'} = 'Attached router'; $labels->{'router_block'} = 'Attached address block'; $svc_x->set('router_routername', $router->routername); @@ -235,10 +206,100 @@ if ( my $router = qsearchs('router', { svcnum => $svc_x->svcnum }) ) { if ( $block ) { $svc_x->set('router_block', $block->cidr); } else { - $svc_x->set('router_block', '<i>(none)</i>'); + $svc_x->set('router_block', '(none)'); } } +my @inventory_items = $svc_x->inventory_item; + +my $format_field = sub { + my $f = shift; + my($field, $type, $value); + if ( ref($f) ) { + $field = $f->{'field'}; + $type = $f->{'type'} || 'text'; + } else { + $field = $f; + $type = 'text'; + } + + my $columndef = $part_svc->part_svc_column($field); + # skip fields that are fixed and empty + if ( $columndef->columnflag eq 'F' + and length($columndef->columnvalue) == 0 ) { + return; + } + + # things that override the column value: value_callback, select + if ( ref($f) and $f->{'value_callback'} ) { + + my $hack_strict_refs = \&{ $f->{'value_callback'} }; + $value = &$hack_strict_refs($svc_x); + + } elsif ( $type eq 'select-table' ) { + # imitates the /elements/select-table interface + $value = $svc_x->$field; + + my $value_col = $f->{'value_col'} || + dbdef->table($f->{'table'})->primary_key; + my $name_col = $f->{'name_col'} or die 'name_col required'; + # we don't yet support multiple-valued fields here + my $obj = qsearchs($f->{'table'}, { $value_col => $value }); + if ( $obj ) { + $value = $obj->$name_col; # can be any method of the object + } else { + # show the raw value, but mark it as an error + $value = '<SPAN CLASS="error">' . $f->{'table'} . ' ' . + encode_entities($value) . '</SPAN>'; + } + + } else { + $value = encode_entities($svc_x->$field); + } + + # inventory-select field with multiple classes + # show the class name to disambiguate + if ( $columndef->columnflag =~ /^[MA]$/ && $columndef->columnvalue =~ /,/ ) + { + my ($item) = grep { $_->svc_field eq $field } @inventory_items; + my $class = qsearchs('inventory_class', { classnum => $item->classnum }); + $value .= ' <i>('. $class->classname . ')</i>' if $class; + } + + # formatting tweaks + if ( $type eq 'date' and $value ) { + $value = time2str($date_format,$value) + } elsif ( $type eq 'datetime' and $value ) { + $value = time2str("$date_format %H:%M",$value) + } elsif ( $type eq 'checkbox' ) { + $value = $value eq 'Y' ? emt('Yes') : emt('No'); + } elsif ( $type eq 'mac_addr' and $value =~ /\w/) { + $value .= ' ('. (Net::MAC::Vendor::lookup($value))->[0]. ')' + } + + # 'link' option + my $href; + if ( ref($f) and exists $f->{'link'} ) { + my $link = $f->{'link'}; + if ( ref($link) eq 'CODE' ) { + $link = &{$link}($svc_x); + } + if ( ref($link) eq 'ARRAY' ) { + my ($base, $method) = @$link; + $href = $base . $svc_x->$method(); + } elsif ( !ref($link) ) { + $href = $link; + } + + if ( $href ) { + $value = qq!<A HREF="$href">$value</A>!; + } + } + + my $label = $opt{labels}->{$field} || $field; + return ($field, $label, $value); +}; + &{ $opt{'svc_callback'} }( $cgi, $svc_x, $part_svc, $cust_pkg, $fields, \%opt ) if $opt{'svc_callback'}; </%init> diff --git a/httemplate/view/svc_circuit.html b/httemplate/view/svc_circuit.html new file mode 100644 index 000000000..c8d5d23ee --- /dev/null +++ b/httemplate/view/svc_circuit.html @@ -0,0 +1,80 @@ +<& elements/svc_Common.html, + 'table' => 'svc_circuit', + 'labels' => \%labels, + 'fields' => \@fields, + 'html_foot' => sub { $self->call_method('.foot', @_) }, +&> +<%method .foot> +% my $svc_circuit = shift; +% my $link = [ 'svc_phone.cgi?', 'svcnum' ]; +% if ( FS::svc_phone->count('circuit_svcnum = '.$svc_circuit->svcnum) ) { +<& /search/elements/search.html, + + 'title' => 'Provisioned phone services', + 'name_singular' => 'phone number', + 'query' => { 'table' => 'svc_phone', + 'hashref' => { 'circuit_svcnum' => $svc_circuit->svcnum }, + 'addl_from' => ' LEFT JOIN cust_svc USING (svcnum)'. + ' LEFT JOIN part_svc USING (svcpart)', + 'select' => 'svc_phone.*, part_svc.*', + }, + 'count_query' => 'SELECT COUNT(*) FROM svc_phone WHERE circuit_svcnum = '. + $svc_circuit->svcnum, + 'header' => [ '#', 'Service', 'Phone number', ], + 'fields' => [ 'svcnum', 'svc', 'phonenum' ], + 'links' => [ $link, $link, $link ], + 'align' => 'rlr', + + 'html_form' => '<SPAN CLASS="fsinnerbox-title">Phone services</SPAN>', + 'nohtmlheader' => 1, + 'disable_total' => 1, + 'disable_maxselect' => 1, + 'really_disable_download' => 1, +&> + <BR> +% } +</%method> +<%init> + +my @fields = ( + 'circuit_id', + { field => 'providernum', + type => 'select-table', + table => 'circuit_provider', + name_col => 'provider', + }, + { field => 'typenum', + type => 'select-table', + table => 'circuit_type', + name_col => 'typename', + }, + { field => 'termnum', + type => 'select-table', + table => 'circuit_termination', + name_col => 'termination', + }, + qw( vendor_qual_id vendor_order_id vendor_order_type vendor_order_status + desired_due_date due_date + endpoint_ip_addr + ), + { field => 'endpoint_mac_addr', type => 'mac_addr' }, +); + + +my %labels = ( + circuit_id => 'Circuit ID', + providernum => 'Provider', + typenum => 'Circuit type', + termnum => 'Termination', + vendor_qual_id => 'Qualification ID', + vendor_order_id => 'Order ID', + vendor_order_type => 'Order type', + vendor_order_status => 'Order status', + desired_due_date => 'Desired due date', + due_date => 'Due date', + endpoint_ip_addr => 'Endpoint IP address', + endpoint_mac_addr => 'MAC address', +); + +my $self = $m->request_comp; +</%init> diff --git a/httemplate/view/svc_phone.cgi b/httemplate/view/svc_phone.cgi index 2a2ef243b..1c0fb39c5 100644 --- a/httemplate/view/svc_phone.cgi +++ b/httemplate/view/svc_phone.cgi @@ -1,7 +1,7 @@ <& elements/svc_Common.html, 'table' => 'svc_phone', 'fields' => \@fields, - 'labels' => \%labels, + 'labels' => \%labels, 'html_foot' => $html_foot, &> <%init> @@ -53,6 +53,11 @@ if ( $conf->exists('svc_phone-lnp') ) { ; } +$labels{circuit_label} = mt('Circuit'); +push @fields, { field => 'circuit_label', + link => [ $p.'view/svc_circuit.html?', 'circuit_svcnum' ] + }; + my $html_foot = sub { my $svc_phone = shift; |