summaryrefslogtreecommitdiff
path: root/httemplate/elements
diff options
context:
space:
mode:
authorMark Wells <mark@freeside.biz>2012-09-29 16:36:46 -0700
committerMark Wells <mark@freeside.biz>2012-09-29 16:36:46 -0700
commit33beebf4cb42eba3e1dd868ad5e0af102de961da (patch)
tree860712543dcc74ff2402a4ed8d73e8cd553e62d4 /httemplate/elements
parent7ac86daf67b0a95153b736d5811f9050363f6553 (diff)
update address standardization for cust_location changes
Diffstat (limited to 'httemplate/elements')
-rw-r--r--httemplate/elements/coord-links.html12
-rw-r--r--httemplate/elements/customer-table.html105
-rw-r--r--httemplate/elements/dashboard-toplist.html103
-rw-r--r--httemplate/elements/form-create_ticket.html38
-rw-r--r--httemplate/elements/freeside.css20
-rw-r--r--httemplate/elements/header.html6
-rw-r--r--httemplate/elements/init_overlib.html11
-rw-r--r--httemplate/elements/location.html109
-rw-r--r--httemplate/elements/menu.html134
-rw-r--r--httemplate/elements/order_pkg_link.html26
-rw-r--r--httemplate/elements/popup_link-cust_main.html23
-rw-r--r--httemplate/elements/progress-init.html6
-rw-r--r--httemplate/elements/searchbar-ticket.html2
-rw-r--r--httemplate/elements/select-cust-part_pkg.html6
-rw-r--r--httemplate/elements/select-cust_pkg-status.html2
-rw-r--r--httemplate/elements/select-part_svc_class.html22
-rw-r--r--httemplate/elements/select-rt-customfield.html3
-rw-r--r--httemplate/elements/select-table.html46
-rw-r--r--httemplate/elements/standardize_locations.js5
-rw-r--r--httemplate/elements/table-tickets.html159
-rw-r--r--httemplate/elements/tr-amount_fee.html100
-rw-r--r--httemplate/elements/tr-cust_svc.html2
-rw-r--r--httemplate/elements/tr-fixed-cust_main.html15
-rw-r--r--httemplate/elements/tr-fixed-date.html13
-rw-r--r--httemplate/elements/tr-fixed-prospect_main.html15
-rw-r--r--httemplate/elements/tr-fixed.html16
-rw-r--r--httemplate/elements/tr-select-agent.html19
-rw-r--r--httemplate/elements/tr-select-cust-part_pkg.html27
-rw-r--r--httemplate/elements/tr-select-cust_location.html63
-rw-r--r--httemplate/elements/tr-select-discount.html26
-rw-r--r--httemplate/elements/tr-select-part_referral.html8
-rw-r--r--httemplate/elements/tr-select-part_svc_class.html27
-rwxr-xr-xhttemplate/elements/tr-select-reason.html57
-rw-r--r--httemplate/elements/tr-select-voip_class.html24
-rw-r--r--httemplate/elements/tr-svc_export_machine.html37
-rw-r--r--httemplate/elements/xmenu.css2
-rw-r--r--httemplate/elements/xmenu.top.css2
37 files changed, 1045 insertions, 246 deletions
diff --git a/httemplate/elements/coord-links.html b/httemplate/elements/coord-links.html
index 3fd3ff696..02a224a00 100644
--- a/httemplate/elements/coord-links.html
+++ b/httemplate/elements/coord-links.html
@@ -3,7 +3,7 @@
<& /elements/popup_link.html,
'action' => $p. 'view/map.html?'. $query,
'label' => mt('map'),
- 'actionlabel' => $name,
+ 'actionlabel' => $js_name,
'width' => 763,
'height' => 575,
#'color'
@@ -12,8 +12,8 @@
% if ( $origin ) {
<& /elements/popup_link.html,
'action' => $p. "view/directions.html?origin=$origin;". $query,
- 'label' => mt('dir'),
- 'actionlabel' => $name,
+ 'label' => mt('directions'),
+ 'actionlabel' => $js_name,
'width' => 763,
'height' => 575,
&>
@@ -29,6 +29,12 @@ my $query = 'name='. uri_escape_utf8($name).
';lat='. $latitude.
';lon='. $longitude;
+my $js_name = $name;
+$js_name =~ s/[<>"]/ /g;
+$m->interp->apply_escapes($js_name, 'js_string');
+$js_name =~ s/^'//;
+$js_name =~ s/'$//;
+
my $origin;
#for directions link
if ( $agentnum =~ /^\d+$/ ) {
diff --git a/httemplate/elements/customer-table.html b/httemplate/elements/customer-table.html
index a517ece2a..75e682d92 100644
--- a/httemplate/elements/customer-table.html
+++ b/httemplate/elements/customer-table.html
@@ -41,6 +41,8 @@ Example:
<SCRIPT TYPE="text/javascript">
+ var num_open_invoices = new Array;
+
function clearhint_invnum() {
if ( this.value == 'Not found' || this.value == 'Multiple' ) {
@@ -90,7 +92,7 @@ Example:
customer_select.style.display = 'none';
return false;
- } else if ( customerArray.length == 5 ) {
+ } else if ( customerArray.length == 6 ) {
custnum_obj.value = customerArray[0];
custnum_obj.style.color = '#000000';
@@ -99,6 +101,7 @@ Example:
update_balance_text(searchrow, customerArray[2]);
update_status_text( searchrow, customerArray[3]);
update_status_color(searchrow, '#'+customerArray[4]);
+ update_num_open(searchrow, customerArray[5]);
customer.style.display = '';
customer_select.style.display = 'none';
@@ -140,6 +143,7 @@ Example:
update_balance_text(searchrow, '');
update_status_text(searchrow, '');
update_status_color(searchrow, '#000000');
+ update_num_open(searchrow, 0);
function search_invnum_update(customers) {
@@ -175,15 +179,16 @@ Example:
if ( ( <% $opt{prefix} %>rownum - searchrow ) == 1 ) {
<% $opt{prefix} %>addRow();
}
- var customer = document.getElementById('customer'+searchrow);
- customer.value = 'searching...';
- customer.disabled = true;
- customer.style.color = '#000000';
- customer.style.backgroundColor = '#dddddd';
+
+ var customer_obj = document.getElementById('customer'+searchrow);
+ customer_obj.value = 'searching...';
+ customer_obj.disabled = true;
+ customer_obj.style.color = '#000000';
+ customer_obj.style.backgroundColor = '#dddddd';
var customer_select = document.getElementById('cust_select'+searchrow);
- customer.style.display = '';
+ customer_obj.style.display = '';
customer_select.style.display = 'none';
var invnum = document.getElementById('invnum'+searchrow);
@@ -192,15 +197,48 @@ Example:
update_balance_text(searchrow, '');
update_status_text( searchrow, '');
update_status_color(searchrow, '#000000');
+ update_num_open(searchrow, 0);
function search_custnum_update(customers) {
- var customerArray = eval('(' + customers + ')') || [];
- update_customer(searchrow, customerArray);
+ var customerArrayArray = eval('(' + customers + ')') || [];
+
+ if ( customerArrayArray.length == 0 ) {
+
+ update_customer(searchrow, []);
+
+ } else if ( customerArrayArray.length == 1 ) {
+ update_customer(searchrow, customerArrayArray[0]);
% if ( $opt{custnum_update_callback} ) {
- <% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>')
+ <% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>')
% }
+
+ } else {
+
+ custnum_obj.value = 'Multiple'; // or something
+ custnum_obj.style.color = '#ff0000';
+
+ //blank the current list
+ customer_select.options.length = 0;
+
+ opt(customer_select, '', 'Multiple customers match "' + custnum + '" - select one', '#ff0000');
+ //add the multiple customers
+ for ( var s = 0; s < customerArrayArray.length; s++ ) {
+ opt(customer_select,
+ JSON.stringify(customerArrayArray[s]),
+ customerArrayArray[s][1],
+ '#000000');
+ }
+
+ opt(customer_select, 'cancel', '(Edit search string)', '#000000');
+
+ customer_obj.style.display = 'none';
+
+ customer_select.style.display = '';
+
+ }
+
}
custnum_search(custnum, search_custnum_update );
@@ -243,9 +281,13 @@ Example:
custnum_obj.disabled = false;
custnum_obj.style.backgroundColor = '#ffffff';
- if ( customerArrayArray.length == 1 ) {
+ if ( customerArrayArray.length == 0 ) {
+
+ update_customer(searchrow, []);
+
+ } else if ( customerArrayArray.length == 1 ) {
- update_customer(customerArrayArray[1]);
+ update_customer(searchrow, customerArrayArray[0]);
% if ( $opt{custnum_update_callback} ) {
<% $opt{custnum_update_callback} %>(searchrow, '<% $opt{prefix} %>')
% }
@@ -337,6 +379,9 @@ Example:
document.getElementById('balance'+rownum+'_text').innerHTML = newval;
}
+ function update_num_open(rownum, newval) {
+ num_open_invoices[rownum] = newval;
+ }
</SCRIPT>
@@ -356,7 +401,7 @@ Example:
% my $row = 0;
% for ( $row = 0; exists($param->{"custnum$row"}); $row++ ) {
- <TR>
+ <TR id="row<%$row%>" rownum="<%$row%>">
<TD>
<INPUT TYPE = "text"
NAME = "invnum<% $row %>"
@@ -458,19 +503,24 @@ Example:
% my $color = $opt{color}->[$col];
% my $font = $color ? qq(<FONT COLOR="$color">) : '';
% my $onchange = '';
-% if ( $opt{footer}->[$col] eq '_TOTAL' ) {
+% if ( $opt{onchange}->[$col] ) {
+% $onchange = 'onchange="'.$opt{onchange}->[$col].'"';
+% }
+% elsif ( $opt{footer}->[$col] eq '_TOTAL' ) {
% $total[$col] += $value;
% $onchange = $opt{prefix}. "calc_total$col();";
% $onchange = qq(onchange="$onchange" onkeyup="$onchange");
% }
<TD ALIGN="<% $align %>">
-% if (! $types->[$col] || $types->[$col] eq 'text') {
- <INPUT TYPE = "text"
+% my $type = $types->[$col] || 'text';
+% if ($type eq 'text' or $type eq 'checkbox') {
+ <INPUT TYPE = "<% $type %>"
NAME = "<% $name %>"
ID = "<% $name %>"
SIZE = "<% $size %>"
STYLE = "text-align: <% $align %>;"
VALUE = "<% $value %>"
+ rownum = "<% $row %>"
<% $onchange %>
>
% } elsif ($types->[$col] eq 'immutable') {
@@ -485,7 +535,7 @@ Example:
</TR>
% }
-<TR>
+<TR id="row_total">
<TH COLSPAN=5 ID="<% $opt{'prefix'} %>_TOTAL_TOTAL">
Total <% $row ? $row-1 : 0 %>
<% PL($opt{name_singular} || 'customer', ( $row ? $row-1 : 0 ) ) %>
@@ -559,7 +609,8 @@ Example:
var table = document.getElementById('<% $opt{prefix} %>OneTrueTable');
var tablebody = table.getElementsByTagName('tbody').item(0);
- var row = table.insertRow(rownum+1);
+ var row = table.insertRow(table.rows.length - 1);
+ row.setAttribute('id', 'row'+rownum);
var invnum_cell = document.createElement('TD');
@@ -676,7 +727,7 @@ Example:
% } else {
% $value = $param->{"$field$row"};
% }
- var my_text = document.createTextNode('<% $value %>');
+ var my_text = document.createTextNode(<% $value |js_string %>);
my_cell.appendChild(my_text);
% }
@@ -686,10 +737,17 @@ Example:
my_input.setAttribute('id', '<% $name %>'+<% $opt{prefix} %>rownum);
my_input.style.textAlign = '<% $align{ $opt{align}->[$col] || 'l' } %>';
my_input.setAttribute('size', <% $sizes->[$col] || 10 %>);
-% if ($types->[$col] eq 'immutable') {
+ my_input.setAttribute('rownum', <% $opt{prefix} %>rownum);
+% if ( $types->[$col] eq 'immutable' ) {
my_input.setAttribute('type', 'hidden');
% }
-% if ( $opt{footer}->[$col] eq '_TOTAL' ) {
+% elsif ( $types->[$col] eq 'checkbox' ) {
+ my_input.setAttribute('type', 'checkbox');
+% }
+% if ( $opt{onchange}->[$col] ) {
+ my_input.onchange = <% $opt{onchange}->[$col] %>;
+% }
+% elsif ( $opt{footer}->[$col] eq '_TOTAL' ) {
my_input.onchange = <% $opt{prefix} %>calc_total<%$col%>;
my_input.onkeyup = <% $opt{prefix} %>calc_total<%$col%>;
% }
@@ -713,6 +771,11 @@ Example:
+ ' <% PL($opt{name_singular} || 'customer') %>';
}
+% if ( $opt{add_row_callback} ) {
+ <% $opt{add_row_callback} %>(<% $opt{prefix} %>rownum,
+ '<% $opt{prefix} %>');
+% }
+
<% $opt{prefix} %>rownum++;
}
diff --git a/httemplate/elements/dashboard-toplist.html b/httemplate/elements/dashboard-toplist.html
index 72f596f4a..c6362e0c9 100644
--- a/httemplate/elements/dashboard-toplist.html
+++ b/httemplate/elements/dashboard-toplist.html
@@ -32,18 +32,21 @@
</FONT>
</TD>
-% foreach my $priority ( @custom_priorities, '' ) {
-% my $num =
-% FS::TicketSystem->num_customer_tickets($custnum,$priority);
-% my $ahref = '';
-% $ahref= '<A HREF="'.
-% FS::TicketSystem->href_customer_tickets($custnum,$priority).
-% '">'
-% if $num;
-
+% foreach my $priority ( @custom_priorities ) {
<TD CLASS="grid" BGCOLOR="<% $bgcolor %>" ALIGN="right">
- <% $ahref.$num %></A>
- </TD>
+% my $num = $num_tickets_by_priority{$priority}->{$custnum};
+% if ( $num ) {
+ <A HREF="<%
+ FS::TicketSystem->href_customer_tickets($custnum,$priority)
+ %>"><% $num %></A>
+% if ( $priority &&
+% exists($num_tickets_by_priority{''}{$custnum}) ) {
+% # decrement the customer's total by the number in
+% # this priority bin
+% $num_tickets_by_priority{''}{$custnum} -= $num;
+% }
+% }
+ </TD>
% }
</TR>
@@ -77,7 +80,7 @@
<TH CLASS="grid" BGCOLOR="#cccccc"><% $line %></TH>
<TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Lint') |h %></TH>
<TH CLASS="grid" BGCOLOR="#cccccc"></TH>
-% foreach my $priority ( @custom_priorities, '' ) {
+% foreach my $priority ( @custom_priorities ) {
<TH CLASS="grid" BGCOLOR="#cccccc">
<% $priority || '<i>(none)</i>'%>
</TH>
@@ -105,11 +108,83 @@ my $conf = new FS::Conf;
#false laziness w/httemplate/search/cust_main.cgi... care if
# custom_priority_field becomes anything but a local hack...
+
my @custom_priorities = ();
-if ( $conf->config('ticket_system-custom_priority_field')
+my $custom_priority_field = $conf->config('ticket_system-custom_priority_field');
+if ( $custom_priority_field
&& @{[ $conf->config('ticket_system-custom_priority_field-values') ]} ) {
@custom_priorities =
$conf->config('ticket_system-custom_priority_field-values');
}
-
+push @custom_priorities, '';
+
+my %num_tickets_by_priority = map { $_ => {} } @custom_priorities;
+# "optimization" (i.e. "terrible hack") to avoid constructing
+# (@custom_priorities) x (cust_main) queries with a bazillion
+# joins each just to count tickets
+if ( $FS::TicketSystem::system eq 'RT_Internal'
+ and $conf->config('dashboard-toplist') )
+{
+ my $text = (driver_name =~ /^Pg/) ? 'text' : 'char';
+ # The RT API does not play nicely with aggregate queries,
+ # so we're going to go around it.
+ my $sql;
+ # optimization to keep this from taking a million years
+ my $cust_tickets =
+ "SELECT custnum, Tickets.Id, Tickets.Queue
+ FROM cust_main
+ JOIN Links ON (
+ Links.Target = 'freeside://freeside/cust_main/' || CAST(cust_main.custnum AS $text)
+ AND Links.Base LIKE '%rt://%/ticket/%'
+ AND Links.Type = 'MemberOf'
+ ) JOIN Tickets ON (Links.LocalBase = Tickets.Id)
+ UNION
+ SELECT custnum, Tickets.Id, Tickets.Queue
+ FROM cust_pkg JOIN cust_svc USING (pkgnum)
+ JOIN Links ON (
+ Links.Target = 'freeside://freeside/cust_svc/' || CAST(cust_svc.svcnum AS $text)
+ AND Links.Base LIKE '%rt://%/ticket/%'
+ AND Links.Type = 'MemberOf'
+ ) JOIN Tickets ON (Links.LocalBase = Tickets.Id)
+ ";
+
+ if ( $custom_priority_field ) {
+ $sql =
+ "SELECT cust_tickets.custnum AS custnum,
+ ObjectCustomFieldValues.Content as priority,
+ COUNT(DISTINCT cust_tickets.Id) AS num_tickets
+ FROM ($cust_tickets) AS cust_tickets
+ LEFT JOIN ObjectCustomFields ON (
+ ObjectCustomFields.ObjectId = '0' OR
+ ObjectCustomFields.ObjectId = cust_tickets.Queue
+ )
+ LEFT JOIN CustomFields ON (
+ ObjectCustomFields.CustomField = CustomFields.Id AND
+ CustomFields.Name = '$custom_priority_field'
+ )
+ LEFT JOIN ObjectCustomFieldValues ON (
+ ObjectCustomFieldValues.CustomField = CustomFields.Id AND
+ ObjectCustomFieldValues.ObjectType = 'RT::Ticket' AND
+ ObjectCustomFieldValues.Disabled = '0' AND
+ ObjectCustomFieldValues.ObjectId = cust_tickets.Id
+ )
+ GROUP BY cust_tickets.custnum, ObjectCustomFieldValues.Content";
+ #warn $sql."\n";
+ } else { # no custom_priority_field
+ $sql =
+ "SELECT cust_tickets.custnum,
+ '' as priority,
+ COUNT(DISTINCT cust_tickets.Id) AS num_tickets
+ FROM ($cust_tickets) AS cust_tickets
+ GROUP BY cust_tickets.custnum";
+ }
+ my $sth = dbh->prepare($sql) or die dbh->errstr;
+ $sth->execute or die $sth->errstr;
+ while ( my $row = $sth->fetchrow_hashref ) {
+ #warn to_json($row)."\n";
+ $num_tickets_by_priority{ $row->{priority} }->{ $row->{custnum} } =
+ $row->{num_tickets};
+ }
+}
+#warn Dumper \%num_tickets_by_priority;
</%init>
diff --git a/httemplate/elements/form-create_ticket.html b/httemplate/elements/form-create_ticket.html
new file mode 100644
index 000000000..362e82397
--- /dev/null
+++ b/httemplate/elements/form-create_ticket.html
@@ -0,0 +1,38 @@
+<FORM METHOD="GET" NAME="CreateTicketForm" STYLE="display:inline">
+<SCRIPT TYPE="text/javascript">
+function updateTicketLink() {
+ var link = document.getElementById('CreateTicketLink');
+ var selector = document.getElementById('Queue')
+ link.href = "<% $new_base.'?'.
+ join(';', map(
+ { ($_ eq 'Queue') ? () : "$_=$new_param{$_}"}
+ keys %new_param),'Queue=') %>" + selector.options[selector.selectedIndex].value;
+}
+</SCRIPT>
+<A NAME="tickets"><FONT CLASS="fsinnerbox-title">Tickets</FONT></A>
+<A id="CreateTicketLink" HREF="<% $new_link %>"><% mt('Create new ticket') |h %></A>
+ <% mt('in queue') |h %>
+%# fetch list of queues in which the user can create tickets
+% my %queues = FS::TicketSystem->queues('', 'CreateTicket');
+% if( $conf->exists('ticket_system-force_default_queueid') ) {
+<B><% $queues{$new_param{'Queue'}} %></B>
+<INPUT TYPE="hidden" NAME="Queue" VALUE="<% $new_param{'Queue'} %>">
+% }
+% else {
+<SELECT NAME="Queue" id="Queue" onchange="updateTicketLink()">
+% foreach my $queueid ( sort { $queues{$a} cmp $queues{$b} } keys %queues ) {
+ <OPTION VALUE="<% $queueid %>"
+ <% $queueid == $new_param{'Queue'} ? 'SELECTED' : '' %>
+ ><% $queues{$queueid} |h %>
+% }
+</SELECT>
+<SCRIPT DEFER TYPE="text/javascript">updateTicketLink();</SCRIPT>
+% }
+</FORM>
+<%init>
+my %opt = @_;
+my $conf = new FS::Conf;
+my $object = $opt{'object'}; # must be a cust_main, cust_svc, or svc_...
+my ($new_base, %new_param) = FS::TicketSystem->href_params_new_ticket($object);
+my $new_link = FS::TicketSystem->href_new_ticket($object);
+</%init>
diff --git a/httemplate/elements/freeside.css b/httemplate/elements/freeside.css
index c291e1e33..82eb9b562 100644
--- a/httemplate/elements/freeside.css
+++ b/httemplate/elements/freeside.css
@@ -108,8 +108,8 @@ a.fstab {
-moz-border-radius-topright:8px;
-webkit-border-radius-topleft:8px;
-webkit-border-radius-topright:8px;
- border-radius-topleft:8px;
- border-radius-topright:8px;
+ border-top-left-radius:8px;
+ border-top-right-radius:8px;
/*font-weight:bold;*/
/*padding-left:12px;
padding-right:12px;*/
@@ -141,8 +141,8 @@ a.fstabselected {
-moz-border-radius-topright:8px;
-webkit-border-radius-topleft:8px;
-webkit-border-radius-topright:8px;
- border-radius-topleft:8px;
- border-radius-topright:8px;
+ border-top-left-radius:8px;
+ border-top-right-radius:8px;
/*font-weight:bold;*/
/*padding-left:12px;
padding-right:12px;*/
@@ -175,8 +175,8 @@ div.fstabcontainer {
-moz-border-radius-bottomright:8px;
-webkit-border-radius-bottomleft:8px;
-webkit-border-radius-bottomright:8px;
- border-radius-bottomleft:8px;
- border-radius-bottomright:8px;
+ border-bottom-left-radius:8px;
+ border-bottom-right-radius:8px;
-moz-box-shadow: #666666 1px 1px 2px;
-webkit-box-shadow: #666666 1px 1px 2px;
box-shadow: #666666 1px 1px 2px;
@@ -206,8 +206,8 @@ div.fstabcontainer {
-moz-border-radius-bottomright:8px;
-webkit-border-radius-bottomleft:8px;
-webkit-border-radius-bottomright:8px;
- border-radius-bottomleft:8px;
- border-radius-bottomright:8px;
+ border-bottom-left-radius:8px;
+ border-bottom-right-radius:8px;
-moz-box-shadow: #666666 1px 1px 2px;
-webkit-box-shadow: #666666 1px 1px 2px;
box-shadow: #666666 1px 1px 2px;
@@ -238,8 +238,8 @@ div.fstabcontainer {
-moz-border-radius-topright:8px;
-webkit-border-radius-topleft:8px;
-webkit-border-radius-topright:8px;
- border-radius-topleft:8px;
- border-radius-topright:8px;
+ border-top-left-radius:8px;
+ border-top-right-radius:8px;
-moz-box-shadow: 1px 0px 1px #999999;
-webkit-box-shadow: 1px 0px 1px #999999;
box-shadow: 1px 0px 1px #999999;
diff --git a/httemplate/elements/header.html b/httemplate/elements/header.html
index d0ab3055d..c6ad3c387 100644
--- a/httemplate/elements/header.html
+++ b/httemplate/elements/header.html
@@ -42,6 +42,12 @@ Example:
<% include('init_overlib.html') |n %>
<% include('rs_init_object.html') |n %>
<% include('logout.html') |n %>
+% my $timeout = $conf->config('logout-timeout');
+% if ( $timeout && $timeout =~ /^\s*\d+\s*$/ ) {
+ <script type="text/javascript">
+ setTimeout('logout()', <% 60000 * $timeout %>);
+ </script>
+% }
<% $head |n %>
diff --git a/httemplate/elements/init_overlib.html b/httemplate/elements/init_overlib.html
index d27ca3bda..986adec40 100644
--- a/httemplate/elements/init_overlib.html
+++ b/httemplate/elements/init_overlib.html
@@ -1,9 +1,16 @@
% for my $file (@files) {
<SCRIPT TYPE="text/javascript" SRC="<%$fsurl%>elements/<%$file%>.js"></SCRIPT>
% }
+<%shared>
+my $initialized = 0; #won't work if component is "preloaded"... so don't do that
+</%shared>
<%init>
-my @files = map "overlibmws$_", ( '', qw( _iframe _draggable _crossframe ) );
-push @files, map { "${_}contentmws" } qw( iframe ajax );
+my @files = ();
+if ( ! $initialized ) {
+ push @files, map "overlibmws$_", ( '', qw( _iframe _draggable _crossframe ) );
+ push @files, map { "${_}contentmws" } qw( iframe ajax );
+ $initialized++;
+}
</%init>
diff --git a/httemplate/elements/location.html b/httemplate/elements/location.html
index f3640510a..4df218b43 100644
--- a/httemplate/elements/location.html
+++ b/httemplate/elements/location.html
@@ -3,16 +3,18 @@
Example:
include( '/elements/location.html',
- 'object' => $cust_main, # or $cust_location
- 'prefix' => $pre, #only for cust_main objects
+ 'object' => $cust_location
+ 'prefix' => $pre, # prefixed to form field names
'onchange' => $javascript,
- 'disabled' => $disabled,
- 'same_checked' => $same_checked,
'geocode' => $geocode, #passed through
'censustract' => $censustract, #passed through
'no_asterisks' => 0, #set true to disable the red asterisks next
#to required fields
'address1_label' => 'Address', #label for address
+ 'enable_coords' => 1, #show latitude/longitude fields
+ 'enable_district' => 1, #show tax district field
+ 'enable_censustract' => 1, #show censustract field
+
)
</%doc>
@@ -40,12 +42,12 @@ Example:
% }
<TR>
- <<%$th%> ALIGN="right"><%$r%><% $opt{'address1_label'} || emt('Address') %></<%$th%>>
+ <<%$th%> STYLE="width:16ex" ALIGN="right"><%$r%><% $opt{'address1_label'} || emt('Address') %></<%$th%>>
<TD COLSPAN=7>
<INPUT TYPE = "text"
NAME = "<%$pre%>address1"
ID = "<%$pre%>address1"
- VALUE = "<% $object->get($pre.'address1') |h %>"
+ VALUE = "<% $object->get('address1') |h %>"
SIZE = 54
onChange = "<% $onchange %>"
<% $disabled %>
@@ -62,7 +64,7 @@ Example:
<INPUT TYPE = "text"
NAME = "<%$pre%>address2"
ID = "<%$pre%>address2"
- VALUE = "<% $object->get($pre.'address2') |h %>"
+ VALUE = "<% $object->get('address2') |h %>"
SIZE = 54
onChange = "<% $onchange %>"
<% $disabled %>
@@ -75,7 +77,7 @@ Example:
<INPUT TYPE = "hidden"
NAME = "<%$pre%>address2"
- VALUE = "<% $object->get($pre.'address2') |h %>"
+ VALUE = "<% $object->get('address2') |h %>"
>
<TR>
@@ -83,7 +85,7 @@ Example:
<TD COLSPAN=7>
% my $location_type = scalar($cgi->param('location_type'))
-% || $object->get($pre.'location_type');
+% || $object->get('location_type');
% #my $location_number = scalar($cgi->param('location_number'))
% # || $object->get($pre.'location_number');
%
@@ -130,7 +132,7 @@ Example:
<INPUT TYPE="text"
NAME = "location_number"
ID = "location_number"
- VALUE = "<% scalar($cgi->param('location_number')) || $object->get($pre.'location_number') |h %>"
+ VALUE = "<% scalar($cgi->param('location_number')) || $object->get('location_number') |h %>"
SIZE = "5"
<% $disabled || ($location_type ? '' : 'DISABLED') %>
<% $style %>
@@ -161,7 +163,7 @@ Example:
<INPUT TYPE = "text"
NAME = "<%$pre%>zip"
ID = "<%$pre%>zip"
- VALUE = "<% $object->get($pre.'zip') |h %>"
+ VALUE = "<% $object->get('zip') |h %>"
SIZE = 11
onChange = "<% $onchange %>"
<% $disabled %>
@@ -175,13 +177,14 @@ Example:
<TD COLSPAN=6><% include('/elements/select-country.html', %select_hash ) %></TD>
</TR>
+% if ( $opt{enable_coords} ) {
<TR>
<TD ALIGN="right"><% mt('Latitude') |h %></TH>
<TD COLSPAN=7>
<INPUT TYPE = "text"
NAME = "<%$pre%>latitude"
ID = "<%$pre%>latitude"
- VALUE = "<% $object->get($pre.'latitude') |h %>"
+ VALUE = "<% $object->get('latitude') |h %>"
<% $disabled %>
<% $style %>
>
@@ -189,37 +192,48 @@ Example:
<INPUT TYPE = "text"
NAME = "<%$pre%>longitude"
ID = "<%$pre%>longitude"
- VALUE = "<% $object->get($pre.'longitude') |h %>"
+ VALUE = "<% $object->get('longitude') |h %>"
<% $disabled %>
<% $style %>
>
</TD>
</TR>
-<INPUT TYPE="hidden" NAME="<%$pre%>coord_auto" VALUE="<% $object->get($pre.'coord_auto') %>">
-
-% if ( !$pre ) {
- <INPUT TYPE="hidden" NAME="geocode" VALUE="<% $opt{geocode} %>">
% } else {
-% if ( $pre eq 'ship_' && $conf->exists('cust_main-require_censustract') ) {
- <TR><<%$th%> ALIGN="right">Census tract<BR>(automatic)</<%$th%>>
- <TD>
- <INPUT TYPE="text" NAME="enter_censustract" VALUE="<% $opt{censustract} %>">
- <INPUT TYPE="hidden" NAME="censusyear" VALUE="<% $object->get('censusyear') %>">
- <INPUT TYPE="hidden" NAME="censustract" VALUE="">
- </TD>
- </TR>
+% foreach (qw(latitude longitude)) {
+<INPUT TYPE="hidden" NAME="<% $_ %>" VALUE="<% $object->get($_) |h%>">
+% }
+% }
+<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 %>">
+% if ( $opt{enable_censustract} ) {
+<TR>
+ <TD ALIGN="right">Census&nbsp;tract</TD>
+ <TD COLSPAN=8>
+ <INPUT TYPE="text" SIZE=15
+ NAME="<%$pre%>enter_censustract"
+ VALUE="<% $object->censustract %>">
+ <% '(automatic)' %>
+ </TD>
+</TR>
+% }
+% if ( $conf->config('tax_district_method') ) {
+% if ( $opt{enable_district} ) {
+ <TR>
+ <TD ALIGN="right">Tax&nbsp;district</TD>
+ <TD COLSPAN=8>
+ <INPUT TYPE="text" SIZE=15
+ NAME="<%$pre%>district"
+ VALUE="<% $object->district %>">
+ <% '(automatic)' %>
+ </TD>
+ </TR>
% } else {
- <INPUT TYPE="hidden" NAME="censustract" VALUE="<% $opt{censustract} %>">
-% }
-% if ( $conf->config('tax_district_method') or $object->get('district') ) {
- <TR>
- <<%$th%> ALIGN="right">Tax district<BR>(automatic)</<%$th%>>
- <TD>
- <INPUT TYPE="text" NAME="district" VALUE="<%$object->get('district')%>">
- </TD>
- </TR>
+ <INPUT TYPE="hidden" NAME="<%$pre%>district" VALUE="<% $object->district %>">
% }
-% }
+% }
%# For address standardization:
%# keep a clean copy of the address so we know if we need
@@ -244,16 +258,13 @@ my $conf = new FS::Conf;
my $r = $opt{'no_asterisks'} ? '' : qq!<font color="#ff0000">*</font>&nbsp;!;
-#false laziness with ship state
my $countrydefault = $conf->config('countrydefault') || 'US';
-$object->set($pre.'country', $countrydefault )
- unless $object->get($pre.'country');
-
-my $statedefault = $conf->config('statedefault')
+my $statedefault = $conf->config('statedefault')
|| ($countrydefault eq 'US' ? 'CA' : '');
-$object->set($pre.'state', $statedefault )
- unless $object->get($pre.'state')
- || $object->get($pre.'country') ne $countrydefault;
+$object ||= FS::cust_location->new({
+ 'country' => $countrydefault,
+ 'state' => $statedefault,
+});
my $alt_err = ($opt{'alt_format'} && !$disabled) ? $object->alternize : '';
@@ -266,8 +277,8 @@ push @address2_label_style, 'visibility:hidden'
|| ! $conf->exists('cust_main-require_address2')
|| ( !$pre && !$opt{'same_checked'} );
-my @counties = counties( $object->get($pre.'state'),
- $object->get($pre.'country'),
+my @counties = counties( $object->get('state'),
+ $object->get('country'),
);
my @county_style = ();
push @county_style, 'display:none' # 'visibility:hidden'
@@ -287,10 +298,10 @@ my $county_style =
: '';
my %select_hash = (
- 'city' => $object->get($pre.'city'),
- 'county' => $object->get($pre.'county'),
- 'state' => $object->get($pre.'state'),
- 'country' => $object->get($pre.'country'),
+ 'city' => $object->get('city'),
+ 'county' => $object->get('county'),
+ 'state' => $object->get('state'),
+ 'country' => $object->get('country'),
'prefix' => $pre,
'onchange' => $onchange,
'disabled' => $disabled,
diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html
index b1cbebf34..b2141e991 100644
--- a/httemplate/elements/menu.html
+++ b/httemplate/elements/menu.html
@@ -94,6 +94,11 @@ tie my %report_prospects, 'Tie::IxHash',
'Advanced prospect reports' => [ $fsurl. 'search/report_prospect_main.html', '' ],
;
+tie my %report_quotations, 'Tie::IxHash',
+ 'List quotations' => [ $fsurl. 'search/quotation.html', '' ],
+ 'Advanced quotation reports' => [ $fsurl. 'search/report_quotation.html', '' ],
+;
+
tie my %report_customers_lists, 'Tie::IxHash',
'by customer number' => [ $fsurl. 'search/cust_main.cgi?browse=custnum', '' ],
'by last name' => [ $fsurl. 'search/cust_main.cgi?browse=last', '' ],
@@ -110,8 +115,7 @@ $report_customers{'List customers'} = [ \%report_customers_lists, 'List customer
$report_customers{'Zip code distribution'} = [ $fsurl. 'search/report_cust_main-zip.html', 'Zip codes by number of customers' ];
$report_customers{'Customer signup report'} = [ $fsurl. 'graph/report_cust_signup.html', 'New customer signups by date' ],
$report_customers{'Advanced customer reports'} = [ $fsurl. 'search/report_cust_main.html', 'by status, signup date, agent, etc.' ]
- if $curuser->access_right('List customers')
- && $curuser->access_right('List packages');
+ if $curuser->access_right('Advanced customer search');
tie my %report_invoices_open, 'Tie::IxHash',
'All open invoices' => [ $fsurl.'search/cust_bill.html?OPEN_date', 'All invoices with an unpaid balance' ],
@@ -201,10 +205,10 @@ foreach my $svcdb ( FS::part_svc->svc_tables() ) {
];
}
- if ( $svcdb =~ /^svc_(acct|broadband|hardware)$/ ) {
$report_svc{"Advanced $lcsname reports"} =
- [ $fsurl."search/report_$svcdb.html", '' ];
- }
+ [ $fsurl."search/report_$svcdb.html", '' ]
+ if $svcdb =~ /^svc_(acct|broadband|hardware)$/
+ && $curuser->access_right("Services: $name: Advanced search");
if ( $svcdb eq 'svc_phone' ) {
@@ -221,7 +225,8 @@ foreach my $svcdb ( FS::part_svc->svc_tables() ) {
}
- $report_services{$name} = [ \%report_svc, $longname ];
+ $report_services{$name} = [ \%report_svc, $longname ]
+ if $curuser->access_right("Services: $name");
}
@@ -253,14 +258,19 @@ tie my %report_inventory, 'Tie::IxHash',
'Inventory activity' => [ $fsurl.'search/report_h_inventory_item.html', '' ],
;
-tie my %report_rating, 'Tie::IxHash',
- 'RADIUS sessions' => [ $fsurl.'search/sqlradius.html', '' ],
- 'Call Detail Records (CDRs)' => [ $fsurl.'search/report_cdr.html', '' ],
- 'Unrateable CDRs' => [ $fsurl.'search/cdr.html?freesidestatus=failed'.
- ';cdrbatchnum=_ALL_' ],
- 'Time worked' => [ $fsurl.'search/report_rt_transaction.html', '' ],
- 'Time worked summary' => [ $fsurl.'search/report_rt_ticket.html', '' ],
-;
+tie my %report_rating, 'Tie::IxHash';
+$report_rating{'RADIUS sessions'} = [ $fsurl.'search/sqlradius.html', '' ]
+ if $curuser->access_right("Usage: RADIUS sessions");
+$report_rating{'RADIUS data usage'} = [ $fsurl.'search/report_sqlradius_usage.html', '' ]
+ if $curuser->access_right("Usage: RADIUS sessions");
+$report_rating{'Call Detail Records (CDRs)'} = [ $fsurl.'search/report_cdr.html', '' ]
+ if $curuser->access_right("Usage: Call Detail Records (CDRs)");
+$report_rating{'Unrateable CDRs'} = [ $fsurl.'search/cdr.html?freesidestatus=failed;cdrbatchnum=_ALL_' ]
+ if $curuser->access_right("Usage: Unrateable CDRs");
+if ( $curuser->access_right("Usage: Time worked") ) {
+ $report_rating{'Time worked'} = [ $fsurl.'search/report_rt_transaction.html', '' ];
+ $report_rating{'Time worked summary'} = [ $fsurl.'search/report_rt_ticket.html', '' ];
+}
tie my %report_ticketing_statistics, 'Tie::IxHash',
'Tickets per day per Queue' => [ $fsurl.'rt/RTx/Statistics/CallsQueueDay', 'View the number of tickets created, resolved or deleted in a specific Queue, over the requested period of days' ],
@@ -272,13 +282,14 @@ tie my %report_ticketing_statistics, 'Tie::IxHash',
;
tie my %report_ticketing, 'Tie::IxHash',
- 'Resolved by owner' => [ $fsurl.'rt/Tools/Reports/ResolvedByOwner.html', '' ],
- 'Resolved in date range' => [ $fsurl.'rt/Tools/Reports/ResolvedByDates.html', '' ],
- 'Created in date range' => [ $fsurl.'rt/Tools/Reports/CreatedByDates.html', '' ],
- 'separator' => '',
+# fix TimeToResolve extension? or redo in a more modern way?
+# 'Resolved by owner' => [ $fsurl.'rt/Tools/Reports/ResolvedByOwner.html', '' ],
+# 'Resolved in date range' => [ $fsurl.'rt/Tools/Reports/ResolvedByDates.html', '' ],
+# 'Created in date range' => [ $fsurl.'rt/Tools/Reports/CreatedByDates.html', '' ],
+# 'separator' => '',
'Statistics' => [ \%report_ticketing_statistics, '' ],
'separator2' => '',
- 'Advanced ticket reports' => [ $fsurl.'rt/Search/Build.html', 'List tickets by any criteria' ],
+ 'Advanced ticket reports' => [ $fsurl.'rt/Search/Build.html?NewQuery=1', 'List tickets by any criteria' ],
;
tie my %report_bill_event, 'Tie::IxHash',
@@ -310,6 +321,7 @@ if($curuser->access_right('Financial reports')) {
'Daily Sales, Credits and Receipts' => [ $fsurl.'graph/report_money_time_daily.html', 'Sales, credits and receipts (broken down by day) summary graph' ],
'Sales Report' => [ $fsurl.'graph/report_cust_bill_pkg.html', 'Sales report and graph (by agent, package class and/or date range)' ],
'Rated Call Sales Report' => [ $fsurl.'graph/report_cust_bill_pkg_detail.html', 'Sales report and graph (by agent, package class, usage class and/or date range)' ],
+ 'Sales With Advertising Source' => [ $fsurl.'search/report_cust_bill_pkg_referral.html' ],
'Employee Commission Report' => [ $fsurl.'search/report_employee_commission.html', '' ],
'Credit Report' => [ $fsurl.'search/report_cust_credit.html', 'Credit report (by employee and/or date range)' ],
'Unapplied Credits' => [ $fsurl.'search/report_cust_credit.html?unapplied=1', 'Unapplied credit report (by type and/or date range)' ],
@@ -337,6 +349,8 @@ if($curuser->access_right('Financial reports')) {
tie my %report_menu, 'Tie::IxHash';
$report_menu{'Prospects'} = [ \%report_prospects, 'Prospect reports' ]
if $curuser->access_right('List prospects');
+$report_menu{'Quotations'} = [ \%report_quotations, 'Quotation reports' ]
+ if $curuser->access_right('List quotations');
$report_menu{'Customers'} = [ \%report_customers, 'Customer reports' ]
if $curuser->access_right('List customers');
$report_menu{'Invoices'} = [ \%report_invoices, 'Invoice reports' ]
@@ -387,10 +401,18 @@ tie my %tools_exporting, 'Tie::IxHash',
'Download database dump' => [ $fsurl. 'misc/dump.cgi', '' ],
;
+tie my %tools_ticketing_articles, 'Tie::IxHash',
+ 'Overview' => [ $fsurl.'rt/Articles/index.html', '' ],
+ 'Search' => [ $fsurl.'rt/Articles/Article/Search.html', '' ],
+ 'Topics' => [ $fsurl.'rt/Articles/Topics.html', '' ],
+;
+
tie my %tools_ticketing, 'Tie::IxHash',
- 'Offline' => [ $fsurl.'rt/Tools/Offline.html', '' ],
+ 'Articles' => [ \%tools_ticketing_articles, '' ],
'My Day' => [ $fsurl.'rt/Tools/MyDay.html', '' ],
- 'My Approvals' => [ $fsurl.'rt/Approvals/', '' ],
+ 'My Reminders' => [ $fsurl.'rt/Tools/MyReminders.html', '' ],
+ 'Offline' => [ $fsurl.'rt/Tools/Offline.html', '' ],
+ 'Approval' => [ $fsurl.'rt/Approvals/', '' ],
;
$tools_ticketing{'Cron Tool'} = [ $fsurl.'rt/Developer/CronTool/', '' ]
if $conf->exists('rt-crontool');
@@ -453,6 +475,7 @@ tie my %config_radius, 'Tie::IxHash',
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' ];
+ $config_export_svc{'Service classes'} = [ $fsurl.'browse/part_svc_class.html', 'Services classes are user-defined, informational types for services' ];
$config_export_svc{'Provisioning exports'} = [ $fsurl.'browse/part_export.cgi', 'Provisioning services to external machines, databases and APIs' ];
}
$config_export_svc{'Dialup'} = [ \%config_dialup, '' ]
@@ -506,6 +529,10 @@ tie my %config_agent, 'Tie::IxHash',
'Agent payment gateways' => [ $fsurl.'browse/payment_gateway.html', 'Credit card and electronic check processors for agent overrides' ];
;
+tie my %config_sales, 'Tie::IxHash',
+ 'Sales' => [ $fsurl.'browse/sales.cgi', 'Sales bring in new business.' ],
+;
+
tie my %config_billing_rates, 'Tie::IxHash',
'Rate plans' => [ $fsurl.'browse/rate.cgi', 'Manage rate plans' ],
'Regions and prefixes' => [ $fsurl.'browse/rate_region.html', 'Manage regions and prefixes' ],
@@ -541,12 +568,44 @@ if ( $curuser->access_right('Configuration') ) {
$config_billing{'Credit reason types'} = [ $fsurl.'browse/reason_type.html?class=R', 'Credit reason types define groups of reasons.' ];
}
+#XXX also to be unified
+tie my %config_ticketing_groups, 'Tie::IxHash',
+ 'Select' => [ $fsurl.'rt/Admin/Groups', '' ],
+ 'Create' => [ $fsurl.'rt/Admin/Groups/Modify.html?Create=1', '' ],
+;
+
+tie my %config_ticketing_queues, 'Tie::IxHash',
+ 'Select' => [ $fsurl.'rt/Admin/Queues', '' ],
+ 'Create' => [ $fsurl.'rt/Admin/Queues/Modify.html?Create=1', '' ],
+;
+
+tie my %config_ticketing_customfields, 'Tie::IxHash',
+ 'Select' => [ $fsurl.'rt/Admin/CustomFields', '' ],
+ 'Create' => [ $fsurl.'rt/Admin/CustomFields/Modify.html?Create=1', '' ],
+;
+
+tie my %config_ticketing_articles_classes, 'Tie::IxHash',
+ 'Select' => [ $fsurl.'rt/Admin/Articles/Classes/', '' ],
+ 'Create' => [ $fsurl.'rt/Admin/Articles/Classes/Modify.html?Create=1', '' ],
+;
+
+tie my %config_ticketing_articles_customfields, 'Tie::IxHash',
+ 'Select' => [ $fsurl.'rt/Admin/CustomFields/index.html?type=RT%3A%3AClass-RT%3A%3AArticle', '' ],
+ 'Create' => [ $fsurl.'rt/Admin/CustomFields/Modify.html?Create=1&LookupType=RT%3A%3AClass-RT%3A%3AArticle', '' ],
+;
+
+tie my %config_ticketing_articles, 'Tie::IxHash',
+ 'Classes' => [ \%config_ticketing_articles_classes, '' ],
+ 'Custom Fields' => [ \%config_ticketing_articles_customfields, '' ],
+;
+
tie my %config_ticketing, 'Tie::IxHash',
- 'Ticketing Users' => [ $fsurl.'rt/Admin/Users', 'View/Edit ticketing users' ], #XXX to be unified
- 'Ticketing Groups' => [ $fsurl.'rt/Admin/Groups', 'View/Edit ticketing groups and group membership' ], #XXX to be unified
- 'Ticketing Queues' => [ $fsurl.'rt/Admin/Queues', 'View/Edit ticketing queues and queue-specific properties' ],
- 'Ticket Custom Fields' => [ $fsurl.'rt/Admin/CustomFields', 'View/Edit ticketing custom fields' ],
- 'Ticketing Global' => [ $fsurl.'rt/Admin/Global', 'View/Edit ticketing configuration applicable to all queues' ],
+ 'Ticketing Users' => [ $fsurl.'rt/Admin/Users', 'Edit ticketing users' ], #XXX to be unified
+ 'Ticketing Groups' => [ \%config_ticketing_groups, 'View/Edit ticketing groups and group membership' ], #XXX to be unified
+ 'Ticketing Queues' => [ \%config_ticketing_queues, 'View/Edit ticketing queues and queue-specific properties' ],
+ 'Ticket Custom Fields' => [ \%config_ticketing_customfields, 'View/Edit ticketing custom fields' ],
+ 'Ticketing Global' => [ $fsurl.'rt/Admin/Global', 'View/Edit ticketing configuration applicable to all queues' ], #XXX the individual items
+ 'Ticketing Articles' => [ \%config_ticketing_articles, '' ],
#"System Configuraiton"? useless, just makes people report errors about missing Module::Versions::Report #'Ticketing Tools' => [ $fsurl.'rt/Admin/Tools', '' ],
;
@@ -556,9 +615,8 @@ tie my %config_nms, 'Tie::IxHash',
tie my %config_misc, 'Tie::IxHash';
$config_misc{'Message templates'} = [ $fsurl.'browse/msg_template.html', 'Templates for customer notices' ]
- if $curuser->access_right('Edit templates')
- || $curuser->access_right('Edit global templates')
- || $curuser->access_right('Configuration');
+ if $curuser->access_right(['View templates', 'View global templates',
+ 'Edit templates', 'Edit global templates', ]);
$config_misc{'Advertising sources'} = [ $fsurl.'browse/part_referral.html', 'Where a customer heard about your service.' ]
if $curuser->access_right('Edit advertising sources')
|| $curuser->access_right('Edit global advertising sources');
@@ -571,6 +629,9 @@ $config_misc{'Inventory classes and inventory'} = [ $fsurl.'browse/inventory_cla
|| $curuser->access_right('Edit global inventory')
|| $curuser->access_right('Configuration');
+$config_misc{'FTP targets'} = [ $fsurl.'browse/ftp_target.html', 'FTP servers for billing and payment processing' ]
+ if $curuser->access_right('Configuration');
+
tie my %config_menu, 'Tie::IxHash';
if ( $curuser->access_right('Configuration' ) ) {
%config_menu = (
@@ -578,6 +639,7 @@ if ( $curuser->access_right('Configuration' ) ) {
'separator' => '', #its a separator!
'Employees' => [ \%config_employees, '' ],
'Resellers' => [ \%config_agent, '' ],
+ 'Sales People' => [ \%config_sales, '' ],
'separator2' => '', #its a separator!
'Customers' => [ \%config_cust, '' ],
#or this? 'Customers and Contacts' => [ \%config_cust, '' ],
@@ -622,18 +684,18 @@ my $doc_link = $conf->config('support-key')
eval "use RT;"
if $conf->config('ticket_system') eq 'RT_Internal';
-tie my %help_menu, 'Tie::IxHash', 'Billing documentation' => [ $doc_link, 'Freeside documentation' ];
-$help_menu{'Ticketing documentation'} = [ 'http://wiki.bestpractical.com/', 'Request Tracker Wiki' ]
- if $conf->config('ticket_system') eq 'RT_Internal';
-$help_menu{'Networking monitoring documentation'} = [ 'http://torrus.org/userguide.pod.html', 'Torrus User Guide' ]
- if $conf->config('network_monitoring_system') eq 'Torrus_Internal';
-$help_menu{'separator'} = '';
-
+tie my %help_menu, 'Tie::IxHash';
my $agentnum = $conf->config('brand-agent');
if ( $agentnum ) {
my $company_name = $conf->config('company_name', $agentnum);
$help_menu{"About $company_name"} = [ "javascript:about_freeside()", '' ];
} else {
+ $help_menu{'Billing documentation'} = [ $doc_link, 'Freeside documentation' ];
+ $help_menu{'Ticketing documentation'} = [ 'http://wiki.bestpractical.com/', 'Request Tracker Wiki' ]
+ if $conf->config('ticket_system') eq 'RT_Internal';
+ $help_menu{'Networking monitoring documentation'} = [ 'http://torrus.org/userguide.pod.html', 'Torrus User Guide' ]
+ if $conf->config('network_monitoring_system') eq 'Torrus_Internal';
+ $help_menu{'separator'} = '';
$help_menu{"About Freeside v$FS::VERSION"} = [ "javascript:about_freeside()", '' ];
$help_menu{"About RT v$RT::VERSION"} = [ 'http://www.bestpractical.com/rt', 'Request Tracker Homepage' ]
if $conf->config('ticket_system') eq 'RT_Internal';
diff --git a/httemplate/elements/order_pkg_link.html b/httemplate/elements/order_pkg_link.html
new file mode 100644
index 000000000..d8aa8fd4e
--- /dev/null
+++ b/httemplate/elements/order_pkg_link.html
@@ -0,0 +1,26 @@
+<& /elements/popup_link-cust_main.html,
+ 'action' => $p. 'misc/order_pkg.html',
+ 'label' => $opt{'label'} || emt('Order new package'),
+ 'actionlabel' => $opt{'actionlabel'} || emt('Order new package'),
+ 'color' => '#333399',
+ 'cust_main' => $opt{cust_main},
+ 'prospect_main' => $opt{prospect_main},
+ 'custnum' => $opt{custnum},
+ 'prospectnum' => $opt{prospectnum},
+ 'closetext' => emt('Close'),
+ 'width' => 960, #763,
+ 'height' => $height,
+ %optional,
+&>
+<%init>
+
+my(%opt) = @_;
+
+my %optional =
+ map { $_ => $opt{$_} }
+ grep $opt{$_},
+ qw( lock_pkgpart lock_locationnum qualnum quotationnum svcpart );
+
+my $height = $opt{'lock_locationnum'} ? 336 : 576;
+
+</%init>
diff --git a/httemplate/elements/popup_link-cust_main.html b/httemplate/elements/popup_link-cust_main.html
index 14137859f..541bb5837 100644
--- a/httemplate/elements/popup_link-cust_main.html
+++ b/httemplate/elements/popup_link-cust_main.html
@@ -22,7 +22,7 @@ Example:
)
</%doc>
-% if ( $params->{'cust_main'} ) {
+% if ( $custnum || $prospectnum ) {
<% include('/elements/popup_link.html', $params ) %>\
% }
<%init>
@@ -34,13 +34,26 @@ if (ref($_[0]) eq 'HASH') {
} else {
$params = { %$params, @_ };
}
+
+my $custnum = $params->{'cust_main'}
+ ? $params->{'cust_main'}->custnum
+ : $params->{'custnum'};
+
+$params->{'action'} .= ( $params->{'action'} =~ /\?/ ? ';' : '?' ).
+ "custnum=$custnum"
+ if $custnum;
+
+#(maybe i should be called popup_link-cust_or_prospect_main.html now)
+my $prospectnum = $params->{'prospect_main'}
+ ? $params->{'prospect_main'}->prospectnum
+ : $params->{'prospectnum'};
-$params->{'action'} .=
- ( $params->{'action'} =~ /\?/ ? ';' : '?' ).
- 'custnum='. $params->{'cust_main'}->custnum;
+$params->{'action'} .= ( $params->{'action'} =~ /\?/ ? ';' : '?' ).
+ "prospectnum=$prospectnum"
+ if $prospectnum;
$params->{'action'} .= ";$_=".$params->{$_}
foreach grep $params->{$_},
- qw( lock_pkgpart lock_locationnum qualnum svcpart );
+ qw( lock_pkgpart lock_locationnum qualnum quotationnum svcpart );
</%init>
diff --git a/httemplate/elements/progress-init.html b/httemplate/elements/progress-init.html
index 2ec248e32..7a282a34c 100644
--- a/httemplate/elements/progress-init.html
+++ b/httemplate/elements/progress-init.html
@@ -54,10 +54,7 @@ sub process_whatever { #class method
)
%>
-% if (!$noinit) {
<& /elements/init_overlib.html &>
-% $noinit = 1;
-% }
<SCRIPT TYPE="text/javascript">
@@ -117,9 +114,6 @@ function <%$key%>myCallback( jobnum ) {
</SCRIPT>
-<%once>
-my $noinit = 0;
-</%once>
<%init>
my( $formname, $fields, $action, $url_or_message, $key ) = @_;
diff --git a/httemplate/elements/searchbar-ticket.html b/httemplate/elements/searchbar-ticket.html
index 774ca9875..30624f7d3 100644
--- a/httemplate/elements/searchbar-ticket.html
+++ b/httemplate/elements/searchbar-ticket.html
@@ -2,7 +2,7 @@
<FORM ACTION="<% FS::TicketSystem->baseurl %>index.html" METHOD="GET" STYLE="margin:0">
<INPUT NAME="q" TYPE="text" VALUE="<% $ticketing_label |n %>" STYLE="width:<% $width %>" onFocus="clearhint_search_ticket(this);" onClick="clearhint_search_ticket(this);" CLASS="fstext"><BR>
- <A HREF="<% FS::TicketSystem->baseurl %>Search/Build.html" CLASS="fslink" STYLE="font-size:11px"><% mt('Advanced') |h %></A>
+ <A HREF="<% FS::TicketSystem->baseurl %>Search/Build.html?NewQuery=1" CLASS="fslink" STYLE="font-size:11px"><% mt('Advanced') |h %></A>
<INPUT TYPE="submit" VALUE="<% mt('Search tickets') |h %>" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:11px">
</FORM>
<% $menu_position eq 'left' ? '<BR>' : '' %>
diff --git a/httemplate/elements/select-cust-part_pkg.html b/httemplate/elements/select-cust-part_pkg.html
index 731beae2a..2d4cd183d 100644
--- a/httemplate/elements/select-cust-part_pkg.html
+++ b/httemplate/elements/select-cust-part_pkg.html
@@ -27,9 +27,9 @@ Example:
my( %opt ) = @_;
-my $cust_main = $opt{'cust_main'}
- or die "cust_main not specified";
+my $cust_or_prospect_main = $opt{'cust_main'} || $opt{'prospect_main'}
+ or die "neither cust_main nor prospect_main specified";
-$opt{'extra_sql'} .= ' AND '. FS::part_pkg->agent_pkgs_sql( $cust_main->agent );
+$opt{'extra_sql'} .= ' AND '. FS::part_pkg->agent_pkgs_sql( $cust_or_prospect_main->agent );
</%init>
diff --git a/httemplate/elements/select-cust_pkg-status.html b/httemplate/elements/select-cust_pkg-status.html
index ec37eaf67..2114c07a1 100644
--- a/httemplate/elements/select-cust_pkg-status.html
+++ b/httemplate/elements/select-cust_pkg-status.html
@@ -3,7 +3,9 @@
<% $onchange %>
>
+% if ( !$opt{'disable_empty'} ) {
<OPTION VALUE="">all
+% }
% foreach my $option ( @{ $opt{'statuses'} } ) {
diff --git a/httemplate/elements/select-part_svc_class.html b/httemplate/elements/select-part_svc_class.html
new file mode 100644
index 000000000..280e3e17d
--- /dev/null
+++ b/httemplate/elements/select-part_svc_class.html
@@ -0,0 +1,22 @@
+<% include( '/elements/select-table.html',
+ 'table' => 'part_svc_class',
+ 'name_col' => 'classname',
+ 'value' => $classnum,
+ 'empty_label' => '(none)',
+ 'hashref' => \%hash,
+ %opt,
+ )
+%>
+<%init>
+
+my %opt = @_;
+my $classnum = $opt{'curr_value'} || $opt{'value'};
+
+my %hash = ();
+$hash{'disabled'} = '' unless $opt{'showdisabled'};
+
+
+$opt{'records'} = delete $opt{'part_svc_class'}
+ if $opt{'part_svc_class'};
+
+</%init>
diff --git a/httemplate/elements/select-rt-customfield.html b/httemplate/elements/select-rt-customfield.html
index 7a45bb14b..85758d585 100644
--- a/httemplate/elements/select-rt-customfield.html
+++ b/httemplate/elements/select-rt-customfield.html
@@ -3,9 +3,6 @@
<OPTION VALUE="<% shift @fields %>"><% shift @fields %></OPTION>
% }
</SELECT>
-<%once>
-RT::Init();
-</%once>
<%init>
my %opt = @_;
my $lookuptype = $opt{lookuptype};
diff --git a/httemplate/elements/select-table.html b/httemplate/elements/select-table.html
index c0dde7414..c0cd7a50b 100644
--- a/httemplate/elements/select-table.html
+++ b/httemplate/elements/select-table.html
@@ -93,10 +93,17 @@ Example:
% )
% {
% my $recvalue = $record->$key();
+% my $selected;
+% if ( $opt{'all_selected'} ) {
+% $selected = 1;
+% } elsif ( $opt{'compare_sub'} && !ref($value) ) {
+% $selected = &{ $opt{'compare_sub'} }( $value, $recvalue );
+% } else {
+% $selected = ( ref($value) && $value->{$recvalue} )
+% || ( $value && $value eq $recvalue ); #not == because of value_col
+% }
<OPTION VALUE="<% $recvalue %>"
- <% $opt{'all_selected'} || ref($value) && $value->{$recvalue} || $value && $value eq $recvalue # not == because of value_col
- ? ' SELECTED' : ''
- %>
+ <% $selected ? ' SELECTED' : '' %>
% foreach my $att ( @{ $opt{'extra_option_attributes'} } ) {
data-<% $att %>="<% $record->$att() |h %>"
% }
@@ -174,24 +181,29 @@ if ( $opt{'records'} ) {
});
}
-unless ( $value < 1 # !$value #ignore negatives too
- or ref($value)
+if ( ref( $value ) eq 'ARRAY' ) {
+ $value = { map { $_ => 1 } @$value };
+}
+
+unless ( !ref($value) && $value < 1 # !$value #ignore negatives too
or ! exists( $opt{hashref}->{disabled} ) #??
- or grep { $value == $_->$key() } @records
+ #or grep { $value == $_->$key() } @records
) {
delete $opt{hashref}->{disabled};
- $opt{hashref}->{$key} = $value;
- my $record = qsearchs( {
- 'table' => $opt{table},
- 'addl_from' => $opt{'addl_from'},
- 'hashref' => $hashref,
- 'extra_sql' => $extra_sql,
- });
- push @records, $record if $record;
-}
-if ( ref( $value ) eq 'ARRAY' ) {
- $value = { map { $_ => 1 } @$value };
+ foreach my $v ( ref($value) ? keys %$value : ($value) ) {
+ next if grep { $v == $_->$key() } @records;
+
+ $opt{hashref}->{$key} = $v;
+ my $record = qsearchs( {
+ 'table' => $opt{table},
+ 'addl_from' => $opt{'addl_from'},
+ 'hashref' => $hashref,
+ 'extra_sql' => $extra_sql,
+ });
+ push @records, $record if $record;
+
+ }
}
my @pre_options = $opt{pre_options} ? @{ $opt{pre_options} } : ();
diff --git a/httemplate/elements/standardize_locations.js b/httemplate/elements/standardize_locations.js
index ee4c5e7f3..f6564a55e 100644
--- a/httemplate/elements/standardize_locations.js
+++ b/httemplate/elements/standardize_locations.js
@@ -7,7 +7,7 @@ function form_address_info() {
'onlyship': 1,
% } else {
% if ( $withfirm ) {
- 'company': cf.elements['<% $main_prefix %>company'].value,
+ 'company', cf.elements['company'].value,
% }
'address1': cf.elements['<% $main_prefix %>address1'].value,
'address2': cf.elements['<% $main_prefix %>address2'].value,
@@ -16,9 +16,6 @@ function form_address_info() {
'zip': cf.elements['<% $main_prefix %>zip'].value,
'country': cf.elements['<% $main_prefix %>country'].value,
% }
-% if ( $withfirm ) {
- 'ship_company': cf.elements['<% $ship_prefix %>company'].value,
-% }
% if ( $withcensus ) {
'ship_censustract': cf.elements['enter_censustract'].value,
% }
diff --git a/httemplate/elements/table-tickets.html b/httemplate/elements/table-tickets.html
new file mode 100644
index 000000000..6d1a45a0d
--- /dev/null
+++ b/httemplate/elements/table-tickets.html
@@ -0,0 +1,159 @@
+<& /elements/form-create_ticket.html, object => $object &>
+ |
+View
+<A HREF="<% $open_link %>"><% mt($openlabel) |h %></A> |
+<A HREF="<% $res_link %>"><% mt('resolved') |h %></A>
+ <BR>
+
+<& /elements/table-grid.html &>
+% my $bgcolor1 = '#eeeeee';
+% my $bgcolor2 = '#ffffff';
+% my $bgcolor = '';
+
+<TR>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('#') |h %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Subject') |h %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Status') |h %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Queue') |h %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Owner') |h %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Due') |h %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Estimated Time') |h %></TH>
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Priority') |h %></TH>
+% if ( $ss_priority ) {
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Customer Priority') |h %></TH>
+% }
+% if ( $object->isa('FS::cust_main') ) {
+ <TH CLASS="grid" BGCOLOR="#cccccc"><% mt('Service') |h %></TH>
+% }
+</TR>
+
+% foreach my $ticket ( @tickets ) {
+% my $href = FS::TicketSystem->href_ticket($ticket->{id});
+% if ( $bgcolor eq $bgcolor1 ) {
+% $bgcolor = $bgcolor2;
+% } else {
+% $bgcolor = $bgcolor1;
+% }
+
+ <TR>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <A HREF=<%$href%>><% $ticket->{id} %></A>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <A HREF=<%$href%>><% $ticket->{subject} %></A>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $ticket->{status} %>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $ticket->{queue} %>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $ticket->{owner} %>
+ </TD>
+
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $date_formatter->($ticket->{due}) %>
+ </TD>
+
+ <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $ticket->{timeestimated} %>
+ </TD>
+
+ <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $ticket->{content}
+ ? $ticket->{content}.' ('.$ticket->{priority}.')'
+ : $ticket->{priority}
+ %>
+ </TD>
+
+% if ( $ss_priority ) {
+ <TD ALIGN="right" CLASS="grid" BGCOLOR="<% $bgcolor %>">
+ <% $ticket->{"CF.{$ss_priority}"} %>
+ </TD>
+% }
+% if ( $object->isa('FS::cust_main') ) {
+ <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><FONT SIZE=-1><B>
+% foreach (@{ $ticket->{svcnums} }) {
+% my $cust_svc = FS::cust_svc->by_key($_) or next;
+ <% FS::UI::Web::svc_label_link($m, $cust_svc->part_svc, $cust_svc) %>
+ <BR>
+% }
+ </B></FONT></TD>
+% }
+
+ </TR>
+
+% }
+
+</TABLE>
+
+<%init>
+use Date::Parse qw(str2time);
+use Date::Format qw(time2str);
+
+my %opt = @_;
+my $conf = new FS::Conf;
+
+my $object = $opt{'object'};
+$object = $object->cust_svc if $object->isa('FS::svc_Common');
+my( @tickets ) = $object->tickets;
+
+my ($openlabel, $open_link, $res_link, $thing);
+$openlabel = join('/', FS::TicketSystem->statuses );
+
+# not the nicest way to do this--FS::has_tickets_Common?
+if ( $object->isa('FS::cust_main') ) {
+ $thing = 'customer';
+ $open_link = FS::TicketSystem->href_customer_tickets($object->custnum);
+
+ $res_link = FS::TicketSystem->href_customer_tickets(
+ $object->custnum,
+ { 'statuses' => [ 'resolved' ] }
+ );
+}
+elsif ( $object->isa('FS::cust_svc') ) {
+ $thing = 'service';
+ $open_link = FS::TicketSystem->href_service_tickets($object->svcnum);
+
+ $res_link = FS::TicketSystem->href_service_tickets(
+ $object->svcnum,
+ { 'statuses' => [ 'resolved' ] }
+ );
+}
+
+my $ss_priority = FS::TicketSystem->selfservice_priority;
+if ( $ss_priority ) {
+ my $dir = $conf->exists('ticket_system-priority_reverse') ? -1 : 1;
+ use sort 'stable';
+ # sort in the following way:
+ @tickets = sort {
+ # within a severity level...
+ ( $a->{'content'} eq $b->{'content'} ) ? (
+ # no-priority tickets sort last
+ (
+ ($a->{'_selfservice_priority'} eq '') <=>
+ ($b->{'_selfservice_priority'} eq '')
+ ) ||
+ # otherwise obey ticket_system-priority_reverse
+ ( $dir *
+ ($b->{'_selfservice_priority'} <=> $a->{'_selfservice_priority'})
+ )
+ ) : 0; # but don't rearrange between severity levels
+ } @tickets;
+}
+
+my $format = $conf->config('date_format') || '%Y-%m-%d';
+
+my $date_formatter = sub {
+ my $time = str2time($_[0], 'GMT');
+ # exclude times within 24 hours of zero
+ ($time > 86400) ? time2str($format, $time) : '';
+};
+
+</%init>
diff --git a/httemplate/elements/tr-amount_fee.html b/httemplate/elements/tr-amount_fee.html
new file mode 100644
index 000000000..12488521a
--- /dev/null
+++ b/httemplate/elements/tr-amount_fee.html
@@ -0,0 +1,100 @@
+ <TR>
+ <TH ALIGN="right"><% mt('Payment amount') |h %></TH>
+ <TD COLSPAN=7>
+ <TABLE><TR><TD BGCOLOR="#ffffff">
+ <% $money_char %><INPUT NAME = "amount"
+ ID = "amount"
+ TYPE = "text"
+ VALUE = "<% $amount %>"
+ SIZE = 8
+ STYLE = "text-align:right;"
+% if ( $fee ) {
+ onChange = "amount_changed(this)"
+ onKeyDown = "amount_changed(this)"
+ onKeyUp = "amount_changed(this)"
+ onKeyPress = "amount_changed(this)"
+% }
+ >
+ </TD><TD BGCOLOR="#cccccc">
+% if ( $fee ) {
+ <INPUT TYPE="hidden" NAME="fee_pkgpart" VALUE="<% $fee_pkg->pkgpart %>">
+ <INPUT TYPE="hidden" NAME="fee" VALUE="<% $fee_display eq 'add' ? $fee : '' %>">
+ <B><FONT SIZE='+1'><% $fee_op %></FONT>
+ <% $money_char . $fee %>
+ </B>
+ <% $fee_pkg->pkg |h %>
+ <B><FONT SIZE='+1'>=</FONT></B>
+ </TD><TD ID="ajax_total_cell" BGCOLOR="#dddddd" STYLE="border:1px solid blue">
+ <FONT SIZE="+1"><% length($amount) ? $money_char. sprintf('%.2f', ($fee_display eq 'add') ? $amount + $fee : $amount - $fee ) : '' %> <% $fee_display eq 'add' ? 'TOTAL' : 'AVAILABLE' %></FONT>
+
+% }
+ </TD></TR></TABLE>
+ </TD>
+ </TR>
+
+% if ( $fee ) {
+
+ <SCRIPT TYPE="text/javascript">
+
+ function amount_changed(what) {
+
+
+ var total = '';
+ if ( what.value.length ) {
+ total = parseFloat(what.value) <% $fee_op %> <% $fee %>;
+ /* total = Math.round(total*100)/100; */
+ total = '<% $money_char %>' + total.toFixed(2);
+ }
+
+ var total_cell = document.getElementById('ajax_total_cell');
+ total_cell.innerHTML = '<FONT SIZE="+1">' + total + ' <% $fee_display eq 'add' ? 'TOTAL' : 'AVAILABLE' %></FONT>';
+
+ }
+
+ </SCRIPT>
+
+% }
+
+<%init>
+
+my %opt = @_;
+
+my $conf = new FS::Conf;
+my $money_char = $conf->config('money_char') || '$';
+
+my $fee = '';
+my $fee_pkg = '';
+my $fee_display = '';
+my $fee_op = '';
+
+if ( $opt{'process-pkgpart'}
+ and ! $opt{'process-skip_first'} || $opt{'num_payments'}
+ )
+{
+
+ $fee_display = $opt{'process-display'} || 'add';
+ $fee_op = $fee_display eq 'add' ? '+' : '-';
+
+ $fee_pkg =
+ qsearchs('part_pkg', { pkgpart=>$opt{'process-pkgpart'} } );
+
+ #well ->unit_setup or ->calc_setup both call for a $cust_pkg
+ # (though ->unit_setup doesn't use it...)
+ $fee = $fee_pkg->option('setup_fee')
+ if $fee_pkg; #in case.. better than dying with a perl traceback
+
+}
+
+my $amount = $opt{'amount'};
+if ( $amount > 0 ) {
+ $amount += $fee
+ if $fee && $fee_display eq 'subtract';
+
+ #&{ $opt{post_fee_callback} }( \$amount ) if $opt{post_fee_callback};
+ $amount += $amount * $opt{'surcharge_percentage'}/100
+ if $opt{'surcharge_percentage'} > 0;
+
+ $amount = sprintf("%.2f", $amount);
+}
+
+</%init>
diff --git a/httemplate/elements/tr-cust_svc.html b/httemplate/elements/tr-cust_svc.html
index ca5de86b4..1ca22f6d4 100644
--- a/httemplate/elements/tr-cust_svc.html
+++ b/httemplate/elements/tr-cust_svc.html
@@ -24,7 +24,7 @@ Usage:
<TD ALIGN="right" VALIGN="top"><%
FS::UI::Web::svc_link($m, $part_svc, $cust_svc)
%></TD>
- <TD STYLE="padding-bottom:0px"><B><%
+ <TD STYLE="padding-bottom:0px"><B><% $cust_svc->agent_svcid ? $cust_svc->agent_svcid.': ' : '' %><%
FS::UI::Web::svc_label_link($m, $part_svc, $cust_svc)
%></B></TD>
<TD ALIGN="right"><% FS::UI::Web::svc_export_links($m, $part_svc, $cust_svc) %>
diff --git a/httemplate/elements/tr-fixed-cust_main.html b/httemplate/elements/tr-fixed-cust_main.html
new file mode 100644
index 000000000..00bcb66d8
--- /dev/null
+++ b/httemplate/elements/tr-fixed-cust_main.html
@@ -0,0 +1,15 @@
+% if ( $cust_main ) {
+ <% include('tr-fixed.html', %opt ) %>
+% }
+<%init>
+
+my %opt = @_;
+
+my $value = $opt{'curr_value'} || $opt{'value'};
+
+my $cust_main = $value ? qsearchs('cust_main', {custnum=>$value} )
+ : '';
+
+$opt{'formatted_value'} = $cust_main->name if $cust_main;
+
+</%init>
diff --git a/httemplate/elements/tr-fixed-date.html b/httemplate/elements/tr-fixed-date.html
new file mode 100644
index 000000000..716e5ceb8
--- /dev/null
+++ b/httemplate/elements/tr-fixed-date.html
@@ -0,0 +1,13 @@
+<% include('tr-fixed.html', %opt ) %>
+<%init>
+
+my %opt = @_;
+
+my $value = $opt{'curr_value'} || $opt{'value'};
+
+my $conf = new FS::Conf;
+my $date_format = $conf->config('date_format') || '%m/%d/%Y';
+
+$opt{'formatted_value'} = time2str($date_format, $value);
+
+</%init>
diff --git a/httemplate/elements/tr-fixed-prospect_main.html b/httemplate/elements/tr-fixed-prospect_main.html
new file mode 100644
index 000000000..8da0ffb84
--- /dev/null
+++ b/httemplate/elements/tr-fixed-prospect_main.html
@@ -0,0 +1,15 @@
+% if ( $prospect_main ) {
+ <% include('tr-fixed.html', %opt ) %>
+% }
+<%init>
+
+my %opt = @_;
+
+my $value = $opt{'curr_value'} || $opt{'value'};
+
+my $prospect_main = $value ? qsearchs('prospect_main', {prospectnum=>$value} )
+ : '';
+
+$opt{'formatted_value'} = $prospect_main->name if $prospect_main;
+
+</%init>
diff --git a/httemplate/elements/tr-fixed.html b/httemplate/elements/tr-fixed.html
index f358343dd..dd07d90b6 100644
--- a/httemplate/elements/tr-fixed.html
+++ b/httemplate/elements/tr-fixed.html
@@ -13,13 +13,15 @@ my %opt = @_;
my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
my $value = $opt{'formatted_value'} || $opt{'curr_value'} || $opt{'value'};
-#compatibility with select-table and friends
-if ( $opt{'multiple'} ) {
- $value = [ split(/\s*,\s*/, $value) ] if !ref $value;
- $value = join('<BR>', map {encode_entities($_)} @$value);
-}
-else {
- $value = encode_entities($value)
+
+unless ( $opt{'noescape'} ) {
+ #compatibility with select-table and friends
+ if ( $opt{'multiple'} ) {
+ $value = [ split(/\s*,\s*/, $value) ] if !ref $value;
+ $value = join('<BR>', map {encode_entities($_)} @$value);
+ } else {
+ $value = encode_entities($value)
+ }
}
</%init>
diff --git a/httemplate/elements/tr-select-agent.html b/httemplate/elements/tr-select-agent.html
index ce03c40f5..321bd6b32 100644
--- a/httemplate/elements/tr-select-agent.html
+++ b/httemplate/elements/tr-select-agent.html
@@ -22,7 +22,7 @@ Example:
);
</%doc>
-% if ( scalar(@agents) == 1 ) {
+% if ( scalar(@agents) == 1 || $opt{'fixed'} ) {
<INPUT TYPE = "hidden"
NAME = "<% $opt{'field'} || 'agentnum' %>"
@@ -30,9 +30,20 @@ Example:
VALUE = "<% $agents[0]->agentnum %>"
>
-%# YUCK. empty row so we don't throw g_row in edit.html off :/
- <TR>
- </TR>
+% if ( scalar(@agents) != 1 ) {
+ <TR>
+ <TD ALIGN="right"><% $opt{'label'} || emt('Agent') %></TD>
+ <TD BGCOLOR="#dddddd" <% $colspan %>>
+% my $agent = qsearchs('agent', { 'agentnum' => $agentnum });
+ <% $agent ? $agent->agent : '(all)' |h %>
+ </TD>
+ </TR>
+
+% } else { # YUCK. empty row so we don't throw g_row in edit.html off :/
+ <TR>
+ </TR>
+% }
+%
% } else {
<TR>
diff --git a/httemplate/elements/tr-select-cust-part_pkg.html b/httemplate/elements/tr-select-cust-part_pkg.html
index 767d23264..848ab0a4b 100644
--- a/httemplate/elements/tr-select-cust-part_pkg.html
+++ b/httemplate/elements/tr-select-cust-part_pkg.html
@@ -51,8 +51,11 @@
}
- get_part_pkg( <% $cust_main->custnum %>, classnum, update_part_pkg );
-
+ get_part_pkg( <% $cust_main ? $cust_main->custnum : '0' %>,
+ <% $prospect_main ? $prospect_main->prospectnum : '0' %>,
+ classnum,
+ update_part_pkg
+ );
}
</SCRIPT>
@@ -74,10 +77,11 @@
<TH ALIGN="right"><% mt('Package') |h %></TH>
<TD COLSPAN=7>
<& /elements/select-cust-part_pkg.html,
- 'curr_value' => $opt{'curr_value'}, #$pkgpart
- 'classnum' => $opt{'classnum'},
- 'cust_main' => $opt{'cust_main'}, #$cust_main
- 'onchange' => 'pkg_changed',
+ 'curr_value' => $opt{'curr_value'}, #$pkgpart
+ 'classnum' => $opt{'classnum'},
+ 'cust_main' => $opt{'cust_main'}, #$cust_main
+ 'prospect_main' => $opt{'prospect_main'}, #$prospect_main
+ 'onchange' => 'pkg_changed',
&>
</TD>
</TR>
@@ -91,8 +95,13 @@ my %opt = @_;
my $pre_label = $opt{'pre_label'} || '';
$pre_label .= ' ' if length($pre_label) && $pre_label =~ /\S$/;
-my $cust_main = $opt{'cust_main'}
- or die "cust_main not specified";
+my $cust_main = $opt{'cust_main'};
+my $prospect_main = $opt{'prospect_main'};
+
+die "neither cust_main nor prospect_main specified"
+ unless $cust_main || $prospect_main;
+
+my $agent = $cust_main ? $cust_main->agent : $prospect_main->agent;
#"normal" part_pkg agent virtualization (agentnum or type)
my @part_pkg = qsearch({
@@ -101,7 +110,7 @@ my @part_pkg = qsearch({
'hashref' => { 'disabled' => '' },
'extra_sql' =>
' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql( 'null'=>1 ).
- ' AND '. FS::part_pkg->agent_pkgs_sql( $opt{'cust_main'}->agent ),
+ ' AND '. FS::part_pkg->agent_pkgs_sql( $agent ),
});
my @pkg_class =
diff --git a/httemplate/elements/tr-select-cust_location.html b/httemplate/elements/tr-select-cust_location.html
index 801152e9f..b472cc5a7 100644
--- a/httemplate/elements/tr-select-cust_location.html
+++ b/httemplate/elements/tr-select-cust_location.html
@@ -11,7 +11,6 @@ Example:
#optional
'empty_label' => '(default service address)',
- 'disable_empty' => 0, #1 to disable
)
</%doc>
@@ -52,12 +51,13 @@ Example:
var ftype = what.form.<%$_%>.tagName;
if( ftype != 'SELECT') what.form.<%$_%>.style.backgroundColor = '#ffffff';
% }
-
- if ( what.form.location_type &&
- what.form.location_type.options[what.form.location_type.selectedIndex].value ) {
- what.form.location_number.disabled = false;
- what.form.location_number.style.backgroundColor = '#ffffff';
- }
+% if ( $opt{'alt_format'} ) {
+ if ( what.form.location_type &&
+ what.form.location_type.options[what.form.location_type.selectedIndex].value ) {
+ what.form.location_number.disabled = false;
+ what.form.location_number.style.backgroundColor = '#ffffff';
+ }
+% }
}
function locationnum_changed(what) {
@@ -102,25 +102,8 @@ Example:
return;
}
- if ( locationnum == 0 ) { //(default service address)
-% if ( $cust_main ) {
- what.form.address1.value = <% $cust_main->get($prefix.'address1') |js_string %>;
- what.form.address2.value = <% $cust_main->get($prefix.'address2') |js_string %>;
- what.form.city.value = <% $cust_main->get($prefix.'city') |js_string %>;
- what.form.zip.value = <% $cust_main->get($prefix.'zip') |js_string %>;
-
- changeSelect(what.form.country, <% $cust_main->get($prefix.'country') | js_string %> );
-
- country_changed( what.form.country,
- fix_state_factory( <% $cust_main->get($prefix.'state') | js_string %>,
- <% $cust_main->get($prefix.'county') | js_string %>
- )
- );
-% }
-
- } else {
- get_location( locationnum, update_location );
- }
+%# default service address is now just another location
+ get_location( locationnum, update_location );
% if ( $editable ) {
if ( locationnum == 0 ) {
@@ -204,14 +187,16 @@ Example:
ID = "locationnum"
onChange = "locationnum_changed(this);"
>
-% if ( !$prospect_main && !$opt{'disable_empty'} ) {
- <OPTION VALUE=""><% $opt{'empty_label'} || '(default service address)' |h %>
+% if ( $cust_main ) {
+ <OPTION VALUE="<% $cust_main->ship_locationnum %>"><% $opt{'empty_label'} || '(default service address)' |h %>
% }
% if ( $opt{'is_optional'} ) {
<OPTION VALUE="-2" <% $locationnum == -2 ? 'SELECTED' : ''%>><% $opt{'optional_label'} || '(not required)' |h %>
% }
%
% foreach my $loc ( @cust_location ) {
+% # don't show the ship_location redundantly
+% next if $cust_main && $cust_main->ship_locationnum == $loc->locationnum;
<OPTION VALUE="<% $loc->locationnum %>"
<% $locationnum == $loc->locationnum ? 'SELECTED' : '' %>
><% $loc->line |h %>
@@ -232,9 +217,12 @@ Example:
'no_asterisks' => 1,
'no_bold' => $opt{'no_bold'},
'alt_format' => $opt{'alt_format'},
+ 'enable_coords'=> 1,
)
%>
-
+<SCRIPT TYPE="text/javascript">
+ locationnum_changed(document.getElementById('locationnum'));
+</SCRIPT>
<%init>
my $conf = new FS::Conf;
@@ -247,8 +235,7 @@ my $cgi = $opt{'cgi'};
my $cust_pkg = $opt{'cust_pkg'};
my $cust_main = $opt{'cust_main'};
my $prospect_main = $opt{'prospect_main'};
-
-my $prefix = ($cust_main && length($cust_main->ship_last)) ? 'ship_' : '';
+die "cust_main or prospect_main required" unless $cust_main or $prospect_main;
my $locationnum = '';
if ( $cgi->param('error') ) {
@@ -260,9 +247,9 @@ if ( $cgi->param('error') ) {
} elsif ($prospect_main) {
my @cust_location = $prospect_main->cust_location;
$locationnum = $cust_location[0]->locationnum if scalar(@cust_location)==1;
- } else { #?
+ } else { #$cust_main
$cgi->param('locationnum') =~ /^(\-?\d*)$/ or die "illegal locationnum";
- $locationnum = $1;
+ $locationnum = $1 || $cust_main->ship_locationnum;
}
}
@@ -278,7 +265,7 @@ if ( $opt{'alt_format'} ) {
push @location_fields, qw( location_type location_number location_kind );
}
-my $cust_location;
+my $cust_location; #the one that shows by default in the location edit space
if ( $locationnum && $locationnum > 0 ) {
$cust_location = qsearchs('cust_location', { 'locationnum' => $locationnum } )
or die "unknown locationnum";
@@ -291,7 +278,7 @@ if ( $locationnum && $locationnum > 0 ) {
$cust_location->$_( $pkg_location->$_ ) foreach @location_fields;
$opt{'empty_label'} ||= 'package address: '.$pkg_location->line;
} elsif ( $cust_main ) {
- $cust_location->$_( $cust_main->get($prefix.$_) ) foreach @location_fields;
+ $cust_location = $cust_main->ship_location; #I think
}
}
@@ -304,7 +291,7 @@ my $location_sort = sub {
or lc($a->address2) cmp lc($b->address2)
};
-my @cust_location = ();
+my @cust_location;
push @cust_location, $cust_main->cust_location if $cust_main;
push @cust_location, $prospect_main->cust_location if $prospect_main;
push @cust_location, $cust_location
@@ -314,14 +301,14 @@ push @cust_location, $cust_location
@cust_location = sort $location_sort grep !$_->disabled, @cust_location;
$cust_location = $cust_location[0]
- if ( $prospect_main || $opt{'disable_empty'} )
+ if ( $prospect_main )
&& !$opt{'is_optional'}
&& @cust_location;
my $disabled =
( $locationnum < 0
|| ( $editable && $locationnum )
- || ( ( $prospect_main || $opt{'disable_empty'} )
+ || ( $prospect_main
&& !$opt{'is_optional'} && !@cust_location && $addnew
)
)
diff --git a/httemplate/elements/tr-select-discount.html b/httemplate/elements/tr-select-discount.html
index 30a60ec85..ee862519f 100644
--- a/httemplate/elements/tr-select-discount.html
+++ b/httemplate/elements/tr-select-discount.html
@@ -6,7 +6,7 @@
% } else {
<TR>
- <TD ALIGN="right" WIDTH="176"><% $opt{'label'} || '<B>'.emt('Discount').'</B>' %></TD>
+ <TD ALIGN="right" WIDTH="275"><% $opt{'label'} || '<B>'.emt('Discount').'</B>' %></TD>
<TD <% $colspan %>>
<% include( '/elements/select-discount.html',
'curr_value' => $discountnum,
@@ -74,6 +74,16 @@
)
%>
+%# <% include( '/elements/tr-checkbox.html',
+%# 'label' => '<B>Apply discount to add-on packages</B>',
+%# 'field' => $name.'_linked',
+%# 'id' => $name.'_linked',
+%# 'curr_value' => scalar($cgi->param($name.'_linked')),
+%# 'value' => 'Y',
+%# 'colspan' => $opt{'colspan'},
+%# )
+%# %>
+
<SCRIPT TYPE="text/javascript">
% my $ge = 'document.getElementById';
@@ -136,6 +146,10 @@
<% $ge %>('<% $name %>_percent_label0').style.visibility = 'hidden';
<% $ge %>('<% $name %>_percent_input0').style.display = 'none';
<% $ge %>('<% $name %>_percent_input0').style.visibility = 'hidden';
+// <% $ge %>('<% $name %>_linked_label0').style.display = 'none';
+// <% $ge %>('<% $name %>_linked_label0').style.visibility = 'hidden';
+// <% $ge %>('<% $name %>_linked').style.display = 'none';
+// <% $ge %>('<% $name %>_linked').style.visibility = 'hidden';
} else if ( <% $name %>__type == 'Amount' ) {
<% $ge %>('<% $name %>_amount_label0').style.display = '';
<% $ge %>('<% $name %>_amount_label0').style.visibility = '';
@@ -145,6 +159,11 @@
<% $ge %>('<% $name %>_percent_label0').style.visibility = 'hidden';
<% $ge %>('<% $name %>_percent_input0').style.display = 'none';
<% $ge %>('<% $name %>_percent_input0').style.visibility = 'hidden';
+ <% $ge %>('<% $name %>_percent_input0').style.visibility = 'hidden';
+// <% $ge %>('<% $name %>_linked_label0').style.display = 'none';
+// <% $ge %>('<% $name %>_linked_label0').style.visibility = 'hidden';
+// <% $ge %>('<% $name %>_linked').style.display = 'none';
+// <% $ge %>('<% $name %>_linked').style.visibility = 'hidden';
} else if ( <% $name %>__type == 'Percentage' ) {
<% $ge %>('<% $name %>_amount_label0').style.display = 'none';
<% $ge %>('<% $name %>_amount_label0').style.visibility = 'hidden';
@@ -154,6 +173,11 @@
<% $ge %>('<% $name %>_percent_label0').style.visibility = '';
<% $ge %>('<% $name %>_percent_input0').style.display = '';
<% $ge %>('<% $name %>_percent_input0').style.visibility = '';
+ <% $ge %>('<% $name %>_percent_input0').style.visibility = '';
+// <% $ge %>('<% $name %>_linked_label0').style.display = '';
+// <% $ge %>('<% $name %>_linked_label0').style.visibility = '';
+// <% $ge %>('<% $name %>_linked').style.display = '';
+// <% $ge %>('<% $name %>_linked').style.visibility = '';
}
}
diff --git a/httemplate/elements/tr-select-part_referral.html b/httemplate/elements/tr-select-part_referral.html
index 765aa8400..5041f7f73 100644
--- a/httemplate/elements/tr-select-part_referral.html
+++ b/httemplate/elements/tr-select-part_referral.html
@@ -14,13 +14,7 @@
<INPUT TYPE="hidden" NAME="<% $opt{'element_name'} || $opt{'field'} || 'refnum' %>" VALUE="<% $opt{'part_referrals'}->[0]->refnum %>">
% } else {
-
- <TR>
-% if ( $opt{'label'} ) {
- <TD ALIGN="right"><% $opt{'label'} %></TD>
-% } else {
- <TH ALIGN="right"><%$r%><% mt('Advertising source') |h %></TH>
-% }
+ <& /elements/tr-td-label.html, label => 'Advertising source', %opt &>
<TD COLSPAN="<% $colspan %>">
<& /elements/select-part_referral.html,
'curr_value' => $refnum,
diff --git a/httemplate/elements/tr-select-part_svc_class.html b/httemplate/elements/tr-select-part_svc_class.html
new file mode 100644
index 000000000..2f4b09381
--- /dev/null
+++ b/httemplate/elements/tr-select-part_svc_class.html
@@ -0,0 +1,27 @@
+% if ( scalar(@{ $opt{'part_svc_class'} }) == 0 ) {
+
+ <INPUT TYPE="hidden" NAME="<% $opt{'element_name'} || $opt{'field'} || 'classnum' %>" VALUE="">
+
+% } else {
+
+ <TR>
+ <TD ALIGN="right"><% $opt{'label'} || 'Service class' %></TD>
+ <TD>
+ <% include( '/elements/select-part_svc_class.html',
+ 'curr_value' => $classnum,
+ %opt
+ )
+ %>
+ </TD>
+ </TR>
+
+% }
+
+<%init>
+
+my %opt = @_;
+my $classnum = $opt{'curr_value'} || $opt{'value'};
+
+$opt{'part_svc_class'} ||= [ qsearch( 'part_svc_class', { disabled=>'' } ) ];
+
+</%init>
diff --git a/httemplate/elements/tr-select-reason.html b/httemplate/elements/tr-select-reason.html
index 5a79d68ef..c1df10b94 100755
--- a/httemplate/elements/tr-select-reason.html
+++ b/httemplate/elements/tr-select-reason.html
@@ -32,8 +32,15 @@ Example:
<SCRIPT TYPE="text/javascript">
function sh_add<% $func_suffix %>()
{
+ var hints = <% encode_json(\@hints) %>;
+ var select_reason = document.getElementById('<% $id %>');
- if (document.getElementById('<% $id %>').selectedIndex == 0){
+% if ( $class eq 'S' ) {
+ document.getElementById('<% $id %>_hint').innerHTML =
+ hints[select_reason.selectedIndex];
+% }
+
+ if (select_reason.selectedIndex == 0){
<% $controlledbutton ? $controlledbutton.'.disabled = true;' : ';' %>
}else{
<% $controlledbutton ? $controlledbutton.'.disabled = false;' : ';' %>
@@ -41,8 +48,8 @@ Example:
%if ($curuser->access_right($add_access_right)){
- if (document.getElementById('<% $id %>').selectedIndex ==
- (document.getElementById('<% $id %>').length - 1)) {
+ 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';
@@ -113,6 +120,13 @@ Example:
</TR>
% }
+% if ( $class eq 'S' ) {
+<TR>
+ <TD COLSPAN=2 ALIGN="center" id="<% $id %>_hint">
+ </TD>
+</TR>
+% }
+
<TR>
<TD ALIGN="right">
<P id="new<% $id %>Label" style="display:<% $display %>"><% mt('New Reason') |h %></P>
@@ -184,6 +198,43 @@ my @reasons = qsearch({
order_by => 'ORDER BY reason_type.type ASC, reason.reason ASC',
});
+my @hints;
+if ( $class eq 'S' ) {
+ my $conf = FS::Conf->new;
+ @hints = ( '' );
+ foreach my $reason (@reasons) {
+ if ( $reason->unsuspend_pkgpart ) {
+ my $part_pkg = FS::part_pkg->by_key($reason->unsuspend_pkgpart);
+ if ( $part_pkg ) {
+ if ( $part_pkg->option('setup_fee',1) > 0 and
+ $part_pkg->option('recur_fee',1) == 0 ) {
+ # the usual case
+ push @hints,
+ mt('A [_1] unsuspension fee will apply.',
+ ($conf->config('money_char') || '$') .
+ sprintf('%.2f', $part_pkg->option('setup_fee'))
+ );
+ } else {
+ # oddball cases--not really supported
+ push @hints,
+ mt('An unsuspension package will apply: [_1]',
+ $part_pkg->price_info
+ );
+ }
+ } else { #no $part_pkg
+ push @hints,
+ '<FONT COLOR="#ff0000">Unsuspend pkg #'.$reason->unsuspend_pkgpart.
+ ' not found.</FONT>';
+ }
+ } else { #no unsuspend_pkgpart
+ push @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-voip_class.html b/httemplate/elements/tr-select-voip_class.html
new file mode 100644
index 000000000..dcc1487cc
--- /dev/null
+++ b/httemplate/elements/tr-select-voip_class.html
@@ -0,0 +1,24 @@
+<& tr-td-label.html, label => 'Category', @_ &>
+<TD>
+<SELECT NAME="<% $opt{'field'} %>">
+% while(@options) {
+% my $value = shift @options;
+% my $selected = ($value eq $opt{'curr_value'}) ? 'SELECTED' : '';
+ <OPTION VALUE="<% $value %>" <% $selected %>><% shift @options %></OPTION>
+% }
+</SELECT>
+</TD></TR>
+<%init>
+my %opt = (
+ field => 'fcc_voip_class',
+ label => 'Category',
+ @_
+);
+my @options = (
+ '' => '',
+ 1 => 'VoIP without Broadband',
+ 2 => 'VoIP with Broadband',
+ 3 => 'Wholesale VoIP'
+);
+
+</%init>
diff --git a/httemplate/elements/tr-svc_export_machine.html b/httemplate/elements/tr-svc_export_machine.html
new file mode 100644
index 000000000..92b6ac1d7
--- /dev/null
+++ b/httemplate/elements/tr-svc_export_machine.html
@@ -0,0 +1,37 @@
+% foreach my $part_export (@part_export) {
+% my $label = ( $part_export->exportname
+% ? $part_export->exportname
+% : $part_export->label
+% ).
+% ' hostname';
+%
+% my $element = 'exportnum'. $part_export->exportnum. 'machinenum';
+% my $machinenum = $opt{cgi}->param($element);
+% if ( ! $machinenum && $opt{svc}->svcnum ) {
+% my $svc_export_machine = qsearchs('svc_export_machine', {
+% 'svcnum' => $opt{svc}->svcnum,
+% 'exportnum' => $part_export->exportnum,
+% });
+% $machinenum = $svc_export_machine->machinenum if $svc_export_machine;
+% }
+
+ <& /elements/tr-select-table.html,
+ 'label' => $label,
+ 'element_name' => 'exportnum'. $part_export->exportnum. 'machinenum',
+ 'table' => 'part_export_machine',
+ 'name_col' => 'machine',
+ 'hashref' => { 'exportnum' => $part_export->exportnum,
+ 'disabled' => '',
+ },
+ 'curr_value' => $machinenum,
+ 'empty_label' => 'Select export hostname',
+ &>
+% }
+<%init>
+
+my %opt = @_;
+
+my @part_export = grep { $_->machine eq '_SVC_MACHINE' }
+ $opt{part_svc}->part_export;
+
+</%init>
diff --git a/httemplate/elements/xmenu.css b/httemplate/elements/xmenu.css
index 73699b6f9..e6a39f675 100644
--- a/httemplate/elements/xmenu.css
+++ b/httemplate/elements/xmenu.css
@@ -20,7 +20,7 @@
.webfx-menu {
position: absolute;
- z-index: 100;
+ z-index: 9999;
visibility: hidden;
border: 1px solid #7e0079;
-moz-border-radius: 4px;
diff --git a/httemplate/elements/xmenu.top.css b/httemplate/elements/xmenu.top.css
index ff0d6f684..7a42254e4 100644
--- a/httemplate/elements/xmenu.top.css
+++ b/httemplate/elements/xmenu.top.css
@@ -20,7 +20,7 @@
.webfx-menu {
position: absolute;
- z-index: 100;
+ z-index: 9999;
visibility: hidden;
border: 1px solid #7e0079;
-moz-border-radius: 4px;