diff options
| author | Mark Wells <mark@freeside.biz> | 2012-09-29 16:36:46 -0700 |
|---|---|---|
| committer | Mark Wells <mark@freeside.biz> | 2012-09-29 16:36:46 -0700 |
| commit | 33beebf4cb42eba3e1dd868ad5e0af102de961da (patch) | |
| tree | 860712543dcc74ff2402a4ed8d73e8cd553e62d4 /httemplate/elements | |
| parent | 7ac86daf67b0a95153b736d5811f9050363f6553 (diff) | |
update address standardization for cust_location changes
Diffstat (limited to 'httemplate/elements')
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 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 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> !; -#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; |
