summaryrefslogtreecommitdiff
path: root/httemplate
diff options
context:
space:
mode:
authormark <mark>2011-04-01 02:52:24 +0000
committermark <mark>2011-04-01 02:52:24 +0000
commitb65b8096089410001dfbcd35f9a56f9405b9f5f1 (patch)
treedf16b0422007bd876bc969bdff857d8a510b0aca /httemplate
parent19b0c403fbf697a1de92f12abc8a2104daca07bc (diff)
svc_hardware and svc_dish, #11454
Diffstat (limited to 'httemplate')
-rw-r--r--httemplate/browse/hardware_class.html44
-rw-r--r--httemplate/browse/hardware_status.html24
-rwxr-xr-xhttemplate/browse/part_svc.cgi19
-rw-r--r--httemplate/edit/elements/edit.html4
-rw-r--r--httemplate/edit/elements/svc_Common.html6
-rw-r--r--httemplate/edit/hardware_class.html16
-rw-r--r--httemplate/edit/hardware_status.html16
-rw-r--r--httemplate/edit/hardware_type.html28
-rwxr-xr-xhttemplate/edit/part_svc.cgi32
-rw-r--r--httemplate/edit/process/elements/process.html6
-rw-r--r--httemplate/edit/process/hardware_class.html11
-rw-r--r--httemplate/edit/process/hardware_status.html11
-rw-r--r--httemplate/edit/process/hardware_type.html11
-rw-r--r--httemplate/edit/process/svc_dish.html10
-rw-r--r--httemplate/edit/process/svc_hardware.html10
-rw-r--r--httemplate/edit/svc_dish.cgi33
-rw-r--r--httemplate/edit/svc_hardware.cgi55
-rw-r--r--httemplate/elements/menu.html5
-rw-r--r--httemplate/elements/select-hardware_class.html10
-rw-r--r--httemplate/elements/select-hardware_type.html14
-rw-r--r--httemplate/elements/tr-cust_svc.html78
-rw-r--r--httemplate/elements/tr-cust_svc_cancel.html24
-rw-r--r--httemplate/elements/tr-select-hardware_type.html10
-rwxr-xr-xhttemplate/search/report_svc_hardware.html71
-rwxr-xr-xhttemplate/search/svc_dish.cgi99
-rw-r--r--httemplate/search/svc_hardware.cgi106
-rw-r--r--httemplate/view/cust_main/packages/services.html83
-rw-r--r--httemplate/view/elements/svc_Common.html5
-rw-r--r--httemplate/view/elements/svc_edit_link.html24
-rwxr-xr-xhttemplate/view/svc_acct.cgi6
-rw-r--r--httemplate/view/svc_broadband.cgi2
-rw-r--r--httemplate/view/svc_dish.cgi16
-rw-r--r--httemplate/view/svc_hardware.cgi24
-rw-r--r--httemplate/view/svc_phone.cgi2
34 files changed, 822 insertions, 93 deletions
diff --git a/httemplate/browse/hardware_class.html b/httemplate/browse/hardware_class.html
new file mode 100644
index 000000000..aef0fa39e
--- /dev/null
+++ b/httemplate/browse/hardware_class.html
@@ -0,0 +1,44 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Hardware Classes and Types',
+ 'name' => 'hardware classes',
+ 'menubar' => $menubar,
+ 'query' => { 'table' => 'hardware_class' },
+ 'count_query' => 'SELECT COUNT(*) FROM hardware_class',
+ 'header' => [ '#', 'Hardware class', '', 'Device types' ],
+ 'fields' => [ 'classnum',
+ 'classname',
+ '',
+ $types_sub,
+ ],
+ 'links' => [ $class_link,
+ $class_link,
+ '',
+ '',
+ ],
+ )
+%>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Configuration');
+
+my $menubar =
+ [ 'Hardware statuses' => $p.'browse/hardware_status.html',
+ 'Add a hardware class' => $p.'edit/hardware_class.html',
+ 'Add a device type', => $p.'edit/hardware_type.html', ];
+
+my $types_sub = sub {
+ my $hardware_class = shift;
+ my @rows = map {
+ my $type_link = $p.'edit/hardware_type.html?'.$_->typenum;
+ [ { 'data' => $_->model, 'link' => $type_link }, ]
+ } $hardware_class->hardware_type;
+
+ \@rows;
+};
+
+my $class_link = [ "${p}edit/hardware_class.html?", 'classnum' ];
+
+</%init>
diff --git a/httemplate/browse/hardware_status.html b/httemplate/browse/hardware_status.html
new file mode 100644
index 000000000..9695ed399
--- /dev/null
+++ b/httemplate/browse/hardware_status.html
@@ -0,0 +1,24 @@
+<% include( 'elements/browse.html',
+ 'title' => 'Hardware Statuses',
+ 'name' => 'hardware statuses',
+ 'menubar' => $menubar,
+ 'query' => { 'table' => 'hardware_status', },
+ 'count_query' => 'SELECT COUNT(*) FROM hardware_status',
+ 'header' => [ '#', 'Status' ],
+ 'fields' => [ 'statusnum', 'label' ],
+ 'links' => [ $link, $link ],
+ )
+%>
+<%init>
+
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+die "access denied"
+ unless $curuser->access_right('Configuration');
+
+my $menubar = [ 'Hardware classes' => $p.'browse/hardware_class.html',
+ 'Add a status' => $p.'edit/hardware_status.html' ];
+
+my $link = [ "${p}edit/hardware_status.html?", 'statusnum' ];
+
+</%init>
diff --git a/httemplate/browse/part_svc.cgi b/httemplate/browse/part_svc.cgi
index 82b1150cc..4549e44dd 100755
--- a/httemplate/browse/part_svc.cgi
+++ b/httemplate/browse/part_svc.cgi
@@ -169,14 +169,14 @@ function part_export_areyousure(href) {
<TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
% my $value = &$formatter($part_svc->part_svc_column($field)->columnvalue);
-% if ( $flag =~ /^[MA]$/ ) {
-% $inventory_class{$value}
-% ||= qsearchs('inventory_class', { 'classnum' => $value } );
-%
-
- <% $inventory_class{$value}
- ? $inventory_class{$value}->classname
- : "WARNING: inventory_class.classnum $value not found" %>
+% if ( $flag =~ /^[MAH]$/ ) {
+% my $select_table = ($flag eq 'H') ? 'hardware_class' : 'inventory_class';
+% $select_class{$value} ||=
+% qsearchs($select_table, { 'classnum' => $value } );
+%
+ <% $select_class{$value}
+ ? $select_class{$value}->classname
+ : "WARNING: $select_table.classnum $value not found" %>
% } else {
<% $value %>
@@ -208,6 +208,7 @@ my %flag = (
'M' => 'Manual selected from inventory',
#'A' => 'Automatically fill in from inventory',
'A' => 'Automatically filled in from inventory',
+ 'H' => 'Selected from hardware class',
'X' => 'Excluded',
);
@@ -232,6 +233,6 @@ if ( $cgi->param('orderby') eq 'active' ) {
@part_svc = sort { lc($a->svc) cmp lc($b->svc) } @part_svc;
}
-my %inventory_class = ();
+my %select_class = ();
</%init>
diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html
index 1ed75c3ef..295ad8567 100644
--- a/httemplate/edit/elements/edit.html
+++ b/httemplate/edit/elements/edit.html
@@ -260,6 +260,10 @@ Example:
% 'maxlength' => $f->{'maxlength'},
% 'postfix' => $f->{'postfix'},
%
+% #textarea
+% 'rows' => $f->{'rows'},
+% 'cols' => $f->{'cols'},
+%
% #checkbox, title, fixed, hidden
% #& deprecated weird value hashref used only by reason.html
% 'value' => $f->{'value'},
diff --git a/httemplate/edit/elements/svc_Common.html b/httemplate/edit/elements/svc_Common.html
index aa7699555..0955d49c6 100644
--- a/httemplate/edit/elements/svc_Common.html
+++ b/httemplate/edit/elements/svc_Common.html
@@ -104,6 +104,12 @@
if $object->svcnum;
$f->{'extra_sql'} .= ' ) ';
$f->{'disable_empty'} = $object->svcnum ? 1 : 0,
+ } elsif ( $flag eq 'H' ) {
+ $f->{'type'} = 'select-hardware_type';
+ $f->{'hashref'} = {
+ 'classnum'=>$columndef->columnvalue
+ };
+ $f->{'empty_label'} = 'Select hardware type';
}
if ( $f->{'type'} eq 'select-svc_pbx'
diff --git a/httemplate/edit/hardware_class.html b/httemplate/edit/hardware_class.html
new file mode 100644
index 000000000..8760dd86c
--- /dev/null
+++ b/httemplate/edit/hardware_class.html
@@ -0,0 +1,16 @@
+<% include( 'elements/edit.html',
+ 'name' => 'Hardware Class',
+ 'table' => 'hardware_class',
+ 'labels' => {
+ 'classnum' => 'Class number',
+ 'classname' => 'Class name',
+ },
+ 'viewall_dir' => 'browse',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/hardware_status.html b/httemplate/edit/hardware_status.html
new file mode 100644
index 000000000..ee5f25db8
--- /dev/null
+++ b/httemplate/edit/hardware_status.html
@@ -0,0 +1,16 @@
+<% include( 'elements/edit.html',
+ 'name' => 'Hardware Status',
+ 'table' => 'hardware_status',
+ 'labels' => {
+ 'statusnum' => 'Status number',
+ 'label' => 'Description' ,
+ },
+ 'viewall_dir' => 'browse',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/hardware_type.html b/httemplate/edit/hardware_type.html
new file mode 100644
index 000000000..09a272402
--- /dev/null
+++ b/httemplate/edit/hardware_type.html
@@ -0,0 +1,28 @@
+<% include( 'elements/edit.html',
+ 'name' => 'Device Type',
+ 'table' => 'hardware_type',
+ 'fields' => \@fields,
+ 'labels' => {
+ 'typenum' => 'Type number',
+ 'model' => 'Device model',
+ 'classnum' => 'Hardware class',
+ },
+ 'viewall_url' => $p.'browse/hardware_class.html',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+my @fields = (
+ { field => 'classnum',
+ type => 'select-table',
+ table => 'hardware_class',
+ disable_empty => 1,
+ name_col => 'classname',
+ },
+ 'model',
+);
+
+</%init>
diff --git a/httemplate/edit/part_svc.cgi b/httemplate/edit/part_svc.cgi
index d608657dc..97e2d9694 100755
--- a/httemplate/edit/part_svc.cgi
+++ b/httemplate/edit/part_svc.cgi
@@ -9,7 +9,8 @@
Service Part #<% $part_svc->svcpart ? $part_svc->svcpart : "(NEW)" %>
<BR><BR>
Service <INPUT TYPE="text" NAME="svc" VALUE="<% $hashref->{svc} %>"><BR>
-Disable new orders <INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->{disabled} eq 'Y' ? ' CHECKED' : '' %>><BR>
+<INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->{disabled} eq 'Y' ? ' CHECKED' : '' %>>&nbsp;Disable new orders<BR>
+<INPUT TYPE="checkbox" NAME="preserve" VALUE="Y"<% $hashref->{'preserve'} eq 'Y' ? ' CHECKED' : '' %>>&nbsp;Preserve this service on package cancellation<BR>
<INPUT TYPE="hidden" NAME="svcpart" VALUE="<% $hashref->{svcpart} %>">
<BR>
@@ -56,6 +57,9 @@ Disable new orders <INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->
% 'A' => { 'desc' => 'Automatically fill in from inventory',
% 'condition' => $inv_sub,
% },
+% 'H' => { 'desc' => 'Select from hardware class',
+% 'condition' => sub { $_[0]->{type} ne 'select-hardware' },
+% },
% 'X' => { 'desc' => 'Excluded',
% 'condition' =>
% sub { ! $vfields{$_[1]}->{$_[2]} },
@@ -76,7 +80,7 @@ Disable new orders <INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->
% #'form_action' => 'process/part_svc.cgi',
% 'form_action' => 'part_svc.cgi', #self
% 'form_text' => [ qw( svc svcpart ) ],
-% 'form_checkbox' => [ 'disabled' ],
+% 'form_checkbox' => [ 'disabled', 'preserve' ],
% 'layer_callback' => sub {
% my $layer = shift;
%
@@ -90,7 +94,7 @@ Disable new orders <INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->
% my @part_export =
% map { qsearch( 'part_export', {exporttype => $_ } ) }
% keys %{FS::part_export::export_info($layer)};
-% $html .= '<BR><BR>'. table().
+% $html .= '<BR><BR>'. include('/elements/table.html') .
% "<TR><TH COLSPAN=$columns>Exports</TH></TR><TR>";
% foreach my $part_export ( @part_export ) {
% $communigate++ if $part_export->exporttype =~ /^communigate/;
@@ -179,7 +183,7 @@ Disable new orders <INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->
% foreach my $f ( keys %flag ) {
%
% # need to template-ize more httemplate/edit/svc_* first
-% next if $f eq 'M' and $layer !~ /^svc_(broadband|external|phone)$/;
+% next if $f eq 'M' and $layer !~ /^svc_(broadband|external|phone|dish)$/;
%
% #here is where the SUB from above is called, to skip some choices
% next if $flag{$f}->{condition}
@@ -218,7 +222,8 @@ Disable new orders <INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->
% " what.form.${layer}__${field}_classnum.style.backgroundColor = '#ffffff';".
% " what.form.${layer}__${field}_classnum.style.display = 'none';".
% " }".
-% ' } else if ( f == "M" || f == "A" ) { //enable, inventory',
+% ' } else if ( f == "M" || f == "A" || f == "H" ) { '.
+% '//enable, inventory',
% " what.form.${layer}__${field}.disabled = false;".
% " what.form.${layer}__${field}.style.backgroundColor = '#ffffff';".
% " what.form.${layer}__${field}.style.display = 'none';".
@@ -238,10 +243,10 @@ Disable new orders <INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->
%
% my $disabled = $flag ? ''
% : 'DISABLED STYLE="background-color: #dddddd"';
+% my $nodisplay = ' STYLE="display:none"';
%
% if ( !$def->{type} || $def->{type} eq 'text' ) {
%
-% my $nodisplay = ' STYLE="display:none"';
% my $is_inv = ( $flag =~ /^[MA]$/ );
%
% $html .=
@@ -343,6 +348,16 @@ Disable new orders <INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->
% #doesn't work#'element_etc' => $disabled,
% );
%
+% } elsif ( $def->{type} eq 'select-hardware' ) {
+%
+% $html .= qq!<INPUT TYPE="text" NAME="${layer}__${field}" $disabled>!;
+% $html .= include('/elements/select-hardware_class.html',
+% 'curr_value' => $value,
+% 'element_name' => "${layer}__${field}_classnum",
+% 'element_etc' => $flag ne 'H' && $nodisplay,
+% 'empty_label' => 'Select hardware class',
+% );
+%
% } elsif ( $def->{type} eq 'disabled' ) {
%
% $html .=
@@ -372,7 +387,8 @@ Disable new orders <INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<% $hashref->
%
% $html .= include('/elements/progress-init.html',
% $layer, #form name
-% [ qw(svc svcpart disabled exportnum), @fields ],
+% [ qw(svc svcpart disabled preserve exportnum),
+% @fields ],
% 'process/part_svc.cgi',
% $p.'browse/part_svc.cgi',
% $layer,
@@ -452,6 +468,7 @@ my $svcdb_info = '
<TD VALIGN="top">
<UL STYLE="margin:0">
<LI><B>svc_acct</B>: Accounts - anything with a username (mailbox, shell, RADIUS, etc.)
+ <LI><B>svc_hardware</B>: Equipment supplied to customers
<LI><B>svc_external</B>: Externally-tracked service
</UL>
</TD>
@@ -459,6 +476,7 @@ my $svcdb_info = '
<UL STYLE="margin:0">
<LI><B>svc_dsl</B>: DSL
<LI><B>svc_broadband</B>: Wireless broadband
+ <LI><B>svc_dish</B>: DISH Network
</UL>
</TD>
<TD VALIGN="top">
diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html
index 53419cde0..107b3f298 100644
--- a/httemplate/edit/process/elements/process.html
+++ b/httemplate/edit/process/elements/process.html
@@ -133,9 +133,11 @@ Example:
% } else {
%
% my $ext = $opt{'viewall_ext'} || 'html';
+% my $viewall_dir = $opt{'viewall_dir'} || 'search';
+% my $viewall_url = $opt{'viewall_url'} || ($viewall_dir . "/$table.$ext");
%
-<% $cgi->redirect( popurl(3). ($opt{viewall_dir}||'search'). "/$table.$ext" ) %>
-%
+%#<% $cgi->redirect( popurl(3). ($opt{viewall_dir}||'search'). "/$table.$ext" ) %>
+<% $cgi->redirect( popurl(3) . $viewall_url ) %>
% }
%
%}
diff --git a/httemplate/edit/process/hardware_class.html b/httemplate/edit/process/hardware_class.html
new file mode 100644
index 000000000..64bc72efe
--- /dev/null
+++ b/httemplate/edit/process/hardware_class.html
@@ -0,0 +1,11 @@
+<% include( 'elements/process.html',
+ 'table' => 'hardware_class',
+ 'viewall_dir' => 'browse',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/hardware_status.html b/httemplate/edit/process/hardware_status.html
new file mode 100644
index 000000000..61f02e215
--- /dev/null
+++ b/httemplate/edit/process/hardware_status.html
@@ -0,0 +1,11 @@
+<% include( 'elements/process.html',
+ 'table' => 'hardware_status',
+ 'viewall_dir' => 'browse',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/hardware_type.html b/httemplate/edit/process/hardware_type.html
new file mode 100644
index 000000000..52787011c
--- /dev/null
+++ b/httemplate/edit/process/hardware_type.html
@@ -0,0 +1,11 @@
+<% include( 'elements/process.html',
+ 'table' => 'hardware_type',
+ 'viewall_url' => 'browse/hardware_class.html',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+</%init>
diff --git a/httemplate/edit/process/svc_dish.html b/httemplate/edit/process/svc_dish.html
new file mode 100644
index 000000000..6c8851e77
--- /dev/null
+++ b/httemplate/edit/process/svc_dish.html
@@ -0,0 +1,10 @@
+<% include( 'elements/svc_Common.html',
+ 'table' => 'svc_dish',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+</%init>
diff --git a/httemplate/edit/process/svc_hardware.html b/httemplate/edit/process/svc_hardware.html
new file mode 100644
index 000000000..5abf16c4b
--- /dev/null
+++ b/httemplate/edit/process/svc_hardware.html
@@ -0,0 +1,10 @@
+<% include( 'elements/svc_Common.html',
+ 'table' => 'svc_hardware',
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Provision customer service'); #something else more specific?
+
+</%init>
diff --git a/httemplate/edit/svc_dish.cgi b/httemplate/edit/svc_dish.cgi
new file mode 100644
index 000000000..77a223933
--- /dev/null
+++ b/httemplate/edit/svc_dish.cgi
@@ -0,0 +1,33 @@
+<% include( 'elements/svc_Common.html',
+ 'table' => 'svc_dish',
+ 'html_foot' => $html_foot,
+ '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 $html_foot = sub { };
+
+my @fields = (
+ {
+ field => 'acctnum',
+ type => 'text',
+ label => 'DISH Account #',
+ },
+ {
+ field => 'note',
+ type => 'textarea',
+ rows => 4,
+ cols => 30,
+ label => 'Installation notes',
+ },
+
+);
+
+</%init>
diff --git a/httemplate/edit/svc_hardware.cgi b/httemplate/edit/svc_hardware.cgi
new file mode 100644
index 000000000..e6cb22bcb
--- /dev/null
+++ b/httemplate/edit/svc_hardware.cgi
@@ -0,0 +1,55 @@
+<% include( 'elements/svc_Common.html',
+ 'table' => 'svc_hardware',
+ 'html_foot' => $html_foot,
+ '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 $html_foot = sub { };
+
+my @fields = (
+ {
+ field => 'typenum',
+ type => 'select-hardware_type',
+ },
+ {
+ field => 'serial',
+ type => 'text',
+ label => 'Device serial #',
+ },
+ {
+ field => 'hw_addr',
+ type => 'text',
+ label => 'Hardware address',
+ },
+ {
+ field => 'ip_addr',
+ type => 'text',
+ label => 'IP address',
+ },
+ {
+ field => 'statusnum',
+ type => 'select-table',
+ table => 'hardware_status',
+ label => 'Service status',
+ name_col => 'label',
+ disable_empty => 1,
+ },
+ {
+ field => 'note',
+ type => 'textarea',
+ rows => 4,
+ cols => 30,
+ label => 'Installation notes',
+ },
+
+);
+
+</%init>
diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html
index a70abe475..f558777b5 100644
--- a/httemplate/elements/menu.html
+++ b/httemplate/elements/menu.html
@@ -191,7 +191,7 @@ foreach my $svcdb ( FS::part_svc->svc_tables() ) {
];
}
- if ( $svcdb eq 'svc_acct' || $svcdb eq 'svc_broadband' ) {
+ if ( $svcdb =~ /^svc_(acct|broadband|hardware)$/ ) {
$report_svc{"Advanced $lcsname reports"} =
[ $fsurl."search/report_$svcdb.html", '' ];
}
@@ -532,6 +532,9 @@ $config_misc{'Inventory classes and inventory'} = [ $fsurl.'browse/inventory_cla
|| $curuser->access_right('Edit global inventory')
|| $curuser->access_right('Configuration');
+$config_misc{'Hardware types'} = [ $fsurl.'browse/hardware_class.html', 'Set up hardware type catalog' ]
+ if $curuser->access_right('Configuration');
+
tie my %config_menu, 'Tie::IxHash';
if ( $curuser->access_right('Configuration' ) ) {
%config_menu = (
diff --git a/httemplate/elements/select-hardware_class.html b/httemplate/elements/select-hardware_class.html
new file mode 100644
index 000000000..692b3c9fd
--- /dev/null
+++ b/httemplate/elements/select-hardware_class.html
@@ -0,0 +1,10 @@
+<% include( '/elements/select-table.html',
+ 'table' => 'hardware_class',
+ 'name_col' => 'classname',
+ 'hashref' => { 'disabled' => '' },
+ %opt,
+ )
+%>
+<%init>
+my %opt = @_;
+</%init>
diff --git a/httemplate/elements/select-hardware_type.html b/httemplate/elements/select-hardware_type.html
new file mode 100644
index 000000000..ae07798fc
--- /dev/null
+++ b/httemplate/elements/select-hardware_type.html
@@ -0,0 +1,14 @@
+<% include( '/elements/select-table.html',
+ 'table' => 'hardware_type',
+ 'name_col' => 'model',
+ 'hashref' => $hashref,
+ %opt,
+ )
+%>
+<%init>
+my %opt = @_;
+my $classnum = delete $opt{'classnum'};
+my $hashref = $opt{'hashref'} || {};
+$hashref->{'classnum'} = $classnum if $classnum;
+
+</%init>
diff --git a/httemplate/elements/tr-cust_svc.html b/httemplate/elements/tr-cust_svc.html
new file mode 100644
index 000000000..e792ff350
--- /dev/null
+++ b/httemplate/elements/tr-cust_svc.html
@@ -0,0 +1,78 @@
+<%doc>
+tr-cust_svc - Short display of a customer service for use in view/cust_main.
+
+Formerly part of view/cust_main/packages/services.html, moved here for
+cleanliness.
+</%doc>
+<TR>
+ <TD ALIGN="right" VALIGN="top"><%
+FS::UI::Web::svc_link($m, $part_svc, $cust_svc)
+%></TD>
+ <TD STYLE="padding-bottom:0px"><B><%
+FS::UI::Web::svc_label_link($m, $part_svc, $cust_svc)
+%></B></TD>
+</TR>
+% if ( $cust_svc->overlimit ) {
+<TR>
+ <TD ALIGN="right" COLSPAN="3" VALIGN="top"
+ STYLE="padding-bottom:1px; padding-top:0px">
+ <FONT SIZE="-2" COLOR="#FFD000">Overlimit: <%
+time2str('%b %o %Y' . $opt{'cust_pkg-display_times'} ? ' %l:%M %P' : '',
+$cust_svc->overlimit )
+ %></FONT>
+ </TD>
+</TR>
+% }
+<TR>
+% # first column: recharge link
+ <TD ALIGN="right" VALIGN="top" STYLE="padding-bottom:5px; padding-top:0px">
+% if ( $curuser->access_right('Recharge customer service')
+% && $part_svc->svcdb eq 'svc_acct'
+% && ( $svc_x->seconds ne ''
+% || $svc_x->upbytes ne ''
+% || $svc_x->downbytes ne ''
+% || $svc_x->totalbytes ne ''
+% )
+% ) {
+ <FONT SIZE="-2">(&nbsp;<% svc_recharge_link($cust_svc)%>&nbsp;)</FONT>
+% }
+ </TD>
+% # second column: all other action links
+ <TD ALIGN="right" VALIGN="top" STYLE="padding-bottom:5px; padding-top:0px">
+% if ( $part_svc->svcdb eq 'svc_broadband' ) {
+ <FONT SIZE="-1" STYLE="float:left">(&nbsp;<%
+ include('/elements/popup_link-ping.html',
+ 'ip' => $svc_x->ip_addr
+ ) %>&nbsp;)</FONT>
+% my $manage_link = $opt{'svc_broadband-manage_link'};
+% if ( $manage_link ) {
+ <FONT SIZE="-1" STYLE="float:left">(&nbsp;<A HREF="<%
+ eval(qq("$manage_link"))
+ %>">Manage Device</A>&nbsp;)</FONT>
+% }
+% } #svc_broadband
+% if ( $curuser->access_right('Unprovision customer service') ) {
+ <FONT SIZE="-2">(&nbsp;<% $svc_unprovision_link %>&nbsp;)</FONT>
+% }
+% if ( $part_svc->svcdb eq 'svc_pbx' && $opt{'maestro-status_test'} ) {
+ <FONT SIZE="-2">(&nbsp;<A HREF="<%$p%>misc/maestro-customer_status-test.html?<% $cust_pkg->custnum.'+'.$cust_svc->svcnum %>">Test maestro status</A>&nbsp;)
+ </FONT>
+% }
+ </TD>
+</TR>
+
+<%init>
+my %opt = @_;
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $cust_svc = $opt{'cust_svc'};
+my $part_svc = $opt{'part_svc'} || $cust_svc->part_svc;
+my $cust_pkg = $opt{'cust_pkg'} || $cust_svc->cust_pkg;
+my $svc_x = $cust_svc->svc_x;
+
+my $svc_unprovision_link =
+ qq!<A HREF="javascript:areyousure('${p}misc/unprovision.cgi?! .
+ $cust_svc->svcnum .
+ qq!', 'Permanently unprovision and delete this service?')">Unprovision</A>!;
+
+</%init>
diff --git a/httemplate/elements/tr-cust_svc_cancel.html b/httemplate/elements/tr-cust_svc_cancel.html
new file mode 100644
index 000000000..e7fa47a92
--- /dev/null
+++ b/httemplate/elements/tr-cust_svc_cancel.html
@@ -0,0 +1,24 @@
+<%doc>
+tr-cust_svc_cancel - Short display of a canceled customer service
+for use in view/cust_main.
+</%doc>
+<TR STYLE="color:#cccccc;">
+ <TD ALIGN="right" VALIGN="top"><%
+FS::UI::Web::svc_link($m, $part_svc, $cust_svc)
+%></TD>
+ <TD STYLE="padding-bottom:0px;"><B><%
+FS::UI::Web::svc_label_link($m, $part_svc, $cust_svc)
+%></B></TD>
+</TR>
+%# no action links, the service is canceled
+
+<%init>
+my %opt = @_;
+my $curuser = $FS::CurrentUser::CurrentUser;
+
+my $cust_svc = $opt{'cust_svc'};
+my $part_svc = $opt{'part_svc'} || $cust_svc->part_svc;
+my $cust_pkg = $opt{'cust_pkg'} || $cust_svc->cust_pkg;
+my $svc_x = $cust_svc->svc_x;
+
+</%init>
diff --git a/httemplate/elements/tr-select-hardware_type.html b/httemplate/elements/tr-select-hardware_type.html
new file mode 100644
index 000000000..c3066417b
--- /dev/null
+++ b/httemplate/elements/tr-select-hardware_type.html
@@ -0,0 +1,10 @@
+<TR>
+ <TD ALIGN="right"><% $opt{'label'} || 'Device type: ' %></TD>
+ <TD><% include('select-hardware_type.html', %opt) %></TD>
+</TR>
+
+<%init>
+
+my %opt = @_;
+
+</%init>
diff --git a/httemplate/search/report_svc_hardware.html b/httemplate/search/report_svc_hardware.html
new file mode 100755
index 000000000..4a763b0b4
--- /dev/null
+++ b/httemplate/search/report_svc_hardware.html
@@ -0,0 +1,71 @@
+<% include('/elements/header.html', $title ) %>
+
+<FORM ACTION="svc_hardware.cgi" METHOD="GET">
+
+ <TABLE BGCOLOR="#cccccc" CELLSPACING=0>
+ <TR>
+ <TH CLASS="background" COLSPAN=2 ALIGN="left"><FONT SIZE="+1">Search options</FONT></TH>
+ </TR>
+
+ <TR><TD>
+ <% include('/elements/selectlayers.html',
+ 'field' => 'classnum',
+ 'label' => '',
+ 'options' => \@classnums,
+ 'labels' => \%class_labels,
+ 'layer_callback' => \&layer_callback,
+ 'html_between' => '</TD><TD>',
+ ) %>
+ </TD></TR>
+
+ <% include('/elements/tr-input-text.html',
+ 'field' => 'serial',
+ 'label' => 'Serial #',
+ ) %>
+ <% include('/elements/tr-input-text.html',
+ 'field' => 'hw_addr',
+ 'label' => 'Hardware address',
+ ) %>
+ <% include('/elements/tr-input-text.html',
+ 'field' => 'ip_addr',
+ 'label' => 'IP address',
+ ) %>
+ <% include('/elements/tr-select-table.html',
+ 'field' => 'statusnum',
+ 'label' => 'Service status',
+ 'table' => 'hardware_status',
+ 'name_col' => 'label',
+ 'empty_label' => 'any',
+ ) %>
+
+ </TABLE>
+
+<BR>
+<INPUT TYPE="submit" VALUE="Search">
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List packages'); #?
+
+my $title = 'Hardware Service Report';
+
+my @classes = qsearch('hardware_class', {});
+my @classnums = ('', map { $_->classnum } @classes);
+my %class_labels = ('' => 'Select hardware class',
+ map { $_->classnum => $_->classname } @classes);
+
+sub layer_callback {
+ my $classnum = shift or return '';
+ include('/elements/select-hardware_type.html',
+ 'field' => 'classnum'.$classnum.'typenum',
+ 'classnum' => $classnum,
+ 'empty_label' => 'any',
+ );
+}
+
+</%init>
+
diff --git a/httemplate/search/svc_dish.cgi b/httemplate/search/svc_dish.cgi
new file mode 100755
index 000000000..94da03537
--- /dev/null
+++ b/httemplate/search/svc_dish.cgi
@@ -0,0 +1,99 @@
+<% include( 'elements/search.html',
+ 'title' => 'Dish Network Search Results',
+ 'name' => 'services',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'redirect' => $link,
+ 'header' => [ '#',
+ 'Service',
+ 'Account #',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [ 'svcnum',
+ 'svc',
+ 'acctnum',
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'links' => [ $link,
+ $link,
+ $link,
+ ( map { $_ ne 'Cust. Status' ? $link_cust : '' }
+ FS::UI::Web::cust_header()
+ ),
+ ],
+ 'align' => 'rll'. FS::UI::Web::cust_aligns(),
+ 'color' => [
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_colors(),
+ ],
+ 'style' => [
+ '',
+ '',
+ '',
+ FS::UI::Web::cust_styles(),
+ ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List services');
+
+#my $conf = new FS::Conf;
+
+my $orderby = 'ORDER BY svcnum';
+my @extra_sql = ();
+if ( $cgi->param('magic') =~ /^(all|unlinked)$/ ) {
+
+ push @extra_sql, 'pkgnum IS NULL'
+ if $cgi->param('magic') eq 'unlinked';
+
+ if ( $cgi->param('sortby') =~ /^(\w+)$/ ) {
+ my $sortby = $1;
+ $orderby = "ORDER BY $sortby";
+ }
+} elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) {
+ push @extra_sql, "svcpart = $1";
+}
+
+my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '.
+ ' LEFT JOIN part_svc USING ( svcpart ) '.
+ ' LEFT JOIN cust_pkg USING ( pkgnum ) '.
+ ' LEFT JOIN cust_main USING ( custnum ) ';
+
+#here is the agent virtualization
+push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null_right' => 'View/link unlinked services'
+ );
+
+my $extra_sql =
+ scalar(@extra_sql)
+ ? ' WHERE '. join(' AND ', @extra_sql )
+ : '';
+
+
+my $count_query = "SELECT COUNT(*) FROM svc_dish $addl_from $extra_sql";
+my $sql_query = {
+ 'table' => 'svc_dish',
+ 'hashref' => {},
+ 'select' => join(', ',
+ 'svc_dish.*',
+ 'part_svc.svc',
+ 'cust_main.custnum',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'extra_sql' => $extra_sql,
+ 'order_by' => $orderby,
+ 'addl_from' => $addl_from,
+};
+
+my $link = [ "${p}view/svc_dish.cgi?", 'svcnum', ];
+
+my $link_cust = sub {
+ my $svc_x = shift;
+ $svc_x->custnum ? [ "${p}view/cust_main.cgi?", 'custnum' ] : '';
+};
+
+</%init>
diff --git a/httemplate/search/svc_hardware.cgi b/httemplate/search/svc_hardware.cgi
new file mode 100644
index 000000000..ffbb9f3b6
--- /dev/null
+++ b/httemplate/search/svc_hardware.cgi
@@ -0,0 +1,106 @@
+<% include('elements/search.html',
+ 'title' => 'Hardware service search results',
+ 'name' => 'installations',
+ 'query' => $sql_query,
+ 'count_query' => $count_query,
+ 'redirect' => $link_svc,
+ 'header' => [ '#',
+ 'Service',
+ 'Device type',
+ 'Serial #',
+ 'Hardware addr.',
+ 'IP addr.',
+ FS::UI::Web::cust_header(),
+ ],
+ 'fields' => [ 'svcnum',
+ 'svc',
+ 'model',
+ 'serial',
+ 'hw_addr',
+ 'ip_addr',
+ \&FS::UI::Web::cust_fields,
+ ],
+ 'links' => [ ($link_svc) x 6,
+ ( map { $_ ne 'Cust. Status' ?
+ $link_cust : '' }
+ FS::UI::Web::cust_header() )
+ ],
+ 'align' => 'rllll' . FS::UI::Web::cust_aligns(),
+ 'color' => [ ('') x 4, FS::UI::Web::cust_colors() ],
+ 'style' => [ ('') x 4, FS::UI::Web::cust_styles() ],
+ )
+%>
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('List services');
+
+
+my $addl_from = '
+ LEFT JOIN cust_svc USING ( svcnum )
+ LEFT JOIN part_svc USING ( svcpart )
+ LEFT JOIN cust_pkg USING ( pkgnum )
+ LEFT JOIN cust_main USING ( custnum )
+ LEFT JOIN hardware_type USING ( typenum )';
+
+my @extra_sql;
+push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql(
+ 'null_right' => 'View/link unlinked services'
+ );
+
+if ( $cgi->param('magic') =~ /^(unlinked)$/ ) {
+ push @extra_sql, 'pkgnum IS NULL';
+}
+
+if ( lc($cgi->param('serial')) =~ /^(\w+)$/ ) {
+ push @extra_sql, "LOWER(serial) LIKE '%$1%'";
+}
+
+if ( $cgi->param('hw_addr') =~ /^(\S+)$/ ) {
+ my $hw_addr = uc($1);
+ $hw_addr =~ s/\W//g;
+ push @extra_sql, "hw_addr LIKE '%$hw_addr%'";
+}
+
+my $ip = NetAddr::IP->new($cgi->param('ip_addr'));
+if ( $ip ) {
+ push @extra_sql, "ip_addr = '".lc($ip->addr)."'";
+}
+
+if ( $cgi->param('statusnum') =~ /^(\d+)$/ ) {
+ push @extra_sql, "statusnum = $1";
+}
+
+if ( $cgi->param('classnum') =~ /^(\d+)$/ ) {
+ push @extra_sql, "hardware_type.classnum = $1";
+ if ( $cgi->param('classnum'.$1.'typenum') =~ /^(\d+)$/ ) {
+ push @extra_sql, "svc_hardware.typenum = $1";
+ }
+}
+
+my ($orderby) = $cgi->param('orderby') =~ /^(\w+( ASC| DESC)?)$/i;
+$orderby ||= 'svcnum';
+
+my $extra_sql = '';
+$extra_sql = ' WHERE '.join(' AND ', @extra_sql) if @extra_sql;
+
+my $sql_query = {
+ 'table' => 'svc_hardware',
+ 'select' => join(', ',
+ 'svc_hardware.*',
+ 'part_svc.svc',
+ 'cust_main.custnum',
+ 'hardware_type.model',
+ FS::UI::Web::cust_sql_fields(),
+ ),
+ 'hashref' => {},
+ 'extra_sql' => $extra_sql,
+ 'order_by' => "ORDER BY $orderby",
+ 'addl_from' => $addl_from,
+};
+
+my $count_query = "SELECT COUNT(*) FROM svc_hardware $addl_from $extra_sql";
+my $link_svc = [ $p.'view/svc_hardware.cgi?', 'svcnum' ];
+my $link_cust = [ $p.'view/cust_main.cgi?', 'custnum' ];
+
+</%init>
diff --git a/httemplate/view/cust_main/packages/services.html b/httemplate/view/cust_main/packages/services.html
index 512efccc4..1e636ad4e 100644
--- a/httemplate/view/cust_main/packages/services.html
+++ b/httemplate/view/cust_main/packages/services.html
@@ -10,7 +10,6 @@ function clearhint_search_cust_svc(obj, str) {
}
</SCRIPT>
-% #foreach my $svcpart (sort {$a->{svcpart} <=> $b->{svcpart}} @{$pkg->{svcparts}}) {
% foreach my $part_svc ( $cust_pkg->part_svc ) {
% if ( $opt{'cust_pkg-large_pkg_size'} > 0 and
@@ -36,66 +35,26 @@ function clearhint_search_cust_svc(obj, str) {
</TD>
</TR>
% }
-% else {
+% else { # don't summarize
% foreach my $cust_svc ( @{ $part_svc->cust_pkg_svc } ) {
-
- <TR>
- <TD ALIGN="right" VALIGN="top"><% FS::UI::Web::svc_link($m, $part_svc, $cust_svc) %></TD>
- <TD STYLE="padding-bottom:0px"><B><% FS::UI::Web::svc_label_link($m, $part_svc, $cust_svc) %></B></TD>
- <TD><% FS::UI::Web::svc_export_links($m, $part_svc, $cust_svc) %></TD>
- </TR>
-
- <TR>
- <TD ALIGN="right" COLSPAN="3" VALIGN="top" STYLE="padding-bottom:1px;padding-top:0px"><FONT SIZE="-2" COLOR="#FFD000">
-
- <% $cust_svc->overlimit ? "Overlimit: ". time2str('%b %o %Y' . ($opt{'cust_pkg-display_times'} ? ' %l:%M %P' : ''), $cust_svc->overlimit) : '' %>
- </FONT></TD>
- </TR>
-
- <TR>
- <TD ALIGN="right" VALIGN="top" STYLE="padding-bottom:5px;padding-top:0px"><FONT SIZE="-2">
-
-% if ( $curuser->access_right('Recharge customer service')
-% && $part_svc->svcdb eq 'svc_acct'
-% && ( $cust_svc->svc_x->seconds ne ''
-% || $cust_svc->svc_x->upbytes ne ''
-% || $cust_svc->svc_x->downbytes ne ''
-% || $cust_svc->svc_x->totalbytes ne ''
-% )
-% ) {
- (&nbsp;<%svc_recharge_link($cust_svc)%>&nbsp;)
-% }
- </FONT></TD>
-
- <TD ALIGN="right" VALIGN="top" STYLE="padding-bottom:5px;padding-top:0px">
-
-% my $ip_addr = $cust_svc->svc_x->ip_addr;
-
-% if ( $part_svc->svcdb eq 'svc_broadband' ) {
- <FONT SIZE="-1" STYLE="float:left">(&nbsp;<% include('/elements/popup_link-ping.html', 'ip'=> $ip_addr ) %>&nbsp;)</FONT>
-
-% }
-
-% my $manage_link = $opt{'svc_broadband-manage_link'};
-% if ( $manage_link && $part_svc->svcdb eq 'svc_broadband' ) {
-% my $svc_manage_link = eval(qq("$manage_link"));
- <FONT SIZE="-1" STYLE="float:left">(&nbsp;<A HREF="<% $svc_manage_link %>">Manage Device</A>&nbsp;)</FONT>
-
-% }
-
-% if ( $curuser->access_right('Unprovision customer service') ) {
- <FONT SIZE="-2">(&nbsp;<%svc_unprovision_link($cust_svc)%>&nbsp;)</FONT>
-% }
-
-% if ( $part_svc->svcdb eq 'svc_pbx' && $opt{'maestro-status_test'} ){
- <FONT SIZE="-2">(&nbsp;<A HREF="<% $p %>misc/maestro-customer_status-test.html?<% $cust_pkg->custnum.'+'.$cust_svc->svcnum %>">Test maestro status</A>&nbsp;)</FONT>
-% }
-
- </TD>
- </TR>
+% if ( $cust_pkg->getfield('cancel') > 0 ) {
+ <% include('/elements/tr-cust_svc_cancel.html',
+ %opt,
+ 'part_svc' => $part_svc,
+ 'cust_svc' => $cust_svc,
+ 'cust_pkg' => $cust_pkg,
+ ) %>
+% }
+% else {
+ <% include('/elements/tr-cust_svc.html',
+ %opt,
+ 'part_svc' => $part_svc,
+ 'cust_svc' => $cust_svc,
+ 'cust_pkg' => $cust_pkg,
+ ) %>
+% } #if cancel > 0
% } #foreach $cust_svc
-% }
-
+% } #if summarizing
% if ( ! $cust_pkg->get('cancel')
% && $curuser->access_right('Provision customer service')
% && $part_svc->num_avail
@@ -160,12 +119,6 @@ sub svc_provision_link {
$link;
}
-sub svc_unprovision_link {
- my $cust_svc = shift or return '';
- qq!<A HREF="javascript:areyousure('${p}misc/unprovision.cgi?!. $cust_svc->svcnum.
- qq!', 'Permanently unprovision and delete this service?')">Unprovision</A>!;
-}
-
my %hints = (
svc_acct => '(user or email)',
svc_domain => '(domain)',
diff --git a/httemplate/view/elements/svc_Common.html b/httemplate/view/elements/svc_Common.html
index de49b50d2..7a7539da2 100644
--- a/httemplate/view/elements/svc_Common.html
+++ b/httemplate/view/elements/svc_Common.html
@@ -51,10 +51,7 @@ function areyousure(href) {
Service #<B><% $svcnum %></B>
% my $url = $opt{'edit_url'} || $p. 'edit/'. $opt{'table'}. '.cgi?';
-| <A HREF="<%$url%><%$svcnum%>">Edit this <% $label %></A>
-
-| <A HREF="javascript:areyousure('<%$p.'misc/unprovision.cgi?'.$svcnum%>')">
-Unprovision this Service</A>
+| <% include('/view/elements/svc_edit_link.html', 'svc' => $svc_x) %>
<BR>
<% ntable("#cccccc") %><TR><TD><% ntable("#cccccc",2) %>
diff --git a/httemplate/view/elements/svc_edit_link.html b/httemplate/view/elements/svc_edit_link.html
new file mode 100644
index 000000000..a85d38077
--- /dev/null
+++ b/httemplate/view/elements/svc_edit_link.html
@@ -0,0 +1,24 @@
+% if ( $cancel_date ) {
+<I>Canceled <% time2str('%b %o %Y', $cancel_date) %></I>
+% } else {
+<SCRIPT>
+function areyousure_delete() {
+ if (confirm("Permanently delete this service?") == true)
+ window.location.href = '<% $cancel_url %>';
+}
+</SCRIPT>
+<A HREF="<% $edit_url %>">Edit this <% $label %></A> |
+<A HREF="javascript:areyousure_delete()">
+Unprovision this Service</A>
+% }
+<%init>
+my %opt = @_;
+my $svc_x = $opt{'svc'} or die "'svc' required";
+my $svcdb = $opt{'table'} || $svc_x->table;
+my $edit_url = $opt{'edit_url'} ||
+ $p . 'edit/' . $svcdb . '.cgi?' . $svc_x->svcnum;
+my $cancel_url = $p . 'misc/unprovision.cgi?' . $svc_x->svcnum;
+my $cust_svc = $svc_x->cust_svc; # always exists
+my $cancel_date = $cust_svc->pkg_cancel_date;
+my ($label) = $cust_svc->label;
+</%init>
diff --git a/httemplate/view/svc_acct.cgi b/httemplate/view/svc_acct.cgi
index 4e82569fc..291298d1e 100755
--- a/httemplate/view/svc_acct.cgi
+++ b/httemplate/view/svc_acct.cgi
@@ -38,8 +38,8 @@
%>
Service #<B><% $svcnum %></B>
-| <A HREF="<%$p%>edit/svc_acct.cgi?<%$svcnum%>">Edit this service</A>
-
+|
+<% include('/view/elements/svc_edit_link.html', 'svc' => $svc_acct) %>
<% include( 'svc_acct/change_svc.html',
'part_svc' => \@part_svc,
%gopt,
@@ -105,7 +105,7 @@ my $svc_acct = qsearchs({
die "Unknown svcnum" unless $svc_acct;
#false laziness w/all svc_*.cgi
-my $cust_svc = qsearchs( 'cust_svc' , { 'svcnum' => $svcnum } );
+my $cust_svc = $svc_acct->cust_svc;
my $pkgnum = $cust_svc->getfield('pkgnum');
my($cust_pkg, $custnum);
if ($pkgnum) {
diff --git a/httemplate/view/svc_broadband.cgi b/httemplate/view/svc_broadband.cgi
index 12e5f0f5d..2c44293ec 100644
--- a/httemplate/view/svc_broadband.cgi
+++ b/httemplate/view/svc_broadband.cgi
@@ -10,7 +10,7 @@
<% include('/elements/init_overlib.html') %>
-<A HREF="<%$p%>edit/svc_broadband.cgi?<%$svcnum%>">Edit this information</A>
+<% include('/view/elements/svc_edit_link.html', $svc_acct) %>
<BR>
<%ntable("#cccccc")%>
<TR>
diff --git a/httemplate/view/svc_dish.cgi b/httemplate/view/svc_dish.cgi
new file mode 100644
index 000000000..d4aa8bfdf
--- /dev/null
+++ b/httemplate/view/svc_dish.cgi
@@ -0,0 +1,16 @@
+<% include('elements/svc_Common.html',
+ 'table' => 'svc_dish',
+ 'labels' => \%labels,
+ 'fields' => \@fields,
+ )
+%>
+<%init>
+
+my $fields = FS::svc_dish->table_info->{'fields'};
+my %labels = map { $_ => ( ref($fields->{$_})
+ ? $fields->{$_}{'label'}
+ : $fields->{$_}
+ );
+ } keys %$fields;
+my @fields = qw( acctnum note );
+</%init>
diff --git a/httemplate/view/svc_hardware.cgi b/httemplate/view/svc_hardware.cgi
new file mode 100644
index 000000000..9cea341d7
--- /dev/null
+++ b/httemplate/view/svc_hardware.cgi
@@ -0,0 +1,24 @@
+<% include('elements/svc_Common.html',
+ 'table' => 'svc_hardware',
+ 'labels' => \%labels,
+ 'fields' => \@fields,
+ )
+%>
+<%init>
+
+my $fields = FS::svc_hardware->table_info->{'fields'};
+my %labels = map { $_ => ( ref($fields->{$_})
+ ? $fields->{$_}{'label'}
+ : $fields->{$_}
+ );
+ } keys %$fields;
+my $model = { field => 'typenum',
+ type => 'text',
+ value => sub { $_[0]->hardware_type->model }
+ };
+my $status = { field => 'statusnum',
+ type => 'text',
+ value => sub { $_[0]->status_label }
+ };
+my @fields = ($model, qw( serial hw_addr ip_addr ), $status, 'note' );
+</%init>
diff --git a/httemplate/view/svc_phone.cgi b/httemplate/view/svc_phone.cgi
index e4dc335ca..4a850c21c 100644
--- a/httemplate/view/svc_phone.cgi
+++ b/httemplate/view/svc_phone.cgi
@@ -137,7 +137,7 @@ my $html_foot = sub {
#src & charged party as per voip_cdr.pm
my $search;
my $cust_pkg = $svc_phone->cust_svc->cust_pkg;
- if ( $cust_pkg && $cust_pkg->part_pkg->option('disable_src') ) {
+ if ( $cust_pkg && $cust_pkg->part_pkg->option('disable_src',1) ) {
$search = "charged_party=$number";
} else {
$search = "charged_party_or_src=$number";