diff options
Diffstat (limited to 'httemplate')
97 files changed, 2981 insertions, 1567 deletions
diff --git a/httemplate/autohandler b/httemplate/autohandler index ad0ab8ba6..a017eccb7 100644 --- a/httemplate/autohandler +++ b/httemplate/autohandler @@ -9,15 +9,18 @@ if ( UNIVERSAL::can(dbh, 'sprintProfile') ) { if ( lc($r->content_type) eq 'text/html' ) { - # barely worth it, just in case someone tries to use profiling on a - # non-RT install - eval "use Text::Wrapper;"; - die $@ if $@; + ## barely worth it, just in case someone tries to use profiling on a + ## non-RT install + #eval "use Text::Wrapper;"; + #die $@ if $@; my $wrapper = new Text::Wrapper( columns => 80 ); - + my $text = dbh->sprintProfile(); + #my $text = $wrapper->wrap( dbh->sprintProfile() ); + $text =~ s/^/ /mg; + $profile = '<PRE>'. - encode_entities( $wrapper->wrap( dbh->sprintProfile() ) ). + encode_entities( $text ). #"\n\n". &sprintAutoProfile(). '</PRE>'; "\n\n". '</PRE>'; } diff --git a/httemplate/browse/access_group.html b/httemplate/browse/access_group.html index 6ba89ea81..9ebb2b882 100644 --- a/httemplate/browse/access_group.html +++ b/httemplate/browse/access_group.html @@ -4,6 +4,45 @@ my $html_init = "Internal access groups control access to the back-office interface.<BR><BR>". qq!<A HREF="${p}edit/access_group.html"><I>Add an internal access group</I></A><BR><BR>!; +#false laziness w/access_user.html & agent_type.cgi +my $agents_sub = sub { + my $access_group = shift; + + [ map { + my $access_groupagent = $_; + my $agent = $access_groupagent->agent; + [ + { + 'data' => $agent->agent, + 'align' => 'left', + 'link' => $p. 'edit/agent.cgi?'. $agent->agentnum, + }, + ]; + } + grep { $_->agent } #? + $access_group->access_groupagent, + + ]; + +}; + +my $rights_sub = sub { + my $access_group = shift; + + [ map { my $access_right = $_; + [ + { + 'data' => $access_right->rightname, + 'align' => 'left', + }, + ]; + } + $access_group->access_rights, + + ]; + +}; + my $count_query = 'SELECT COUNT(*) FROM access_group'; my $link = [ $p.'edit/access_group.html?', 'groupnum' ]; @@ -22,12 +61,18 @@ my $link = [ $p.'edit/access_group.html?', 'groupnum' ]; 'count_query' => $count_query, 'header' => [ '#', 'Group name', + 'Agents', + 'Rights', ], 'fields' => [ 'groupnum', 'groupname', + $agents_sub, + $rights_sub, ], 'links' => [ $link, $link, + '', + '', ], ) %> diff --git a/httemplate/browse/access_user.html b/httemplate/browse/access_user.html index 38d5430b1..5b787977d 100644 --- a/httemplate/browse/access_user.html +++ b/httemplate/browse/access_user.html @@ -4,7 +4,15 @@ my $html_init = "Internal users have access to the back-office interface. Typically, this is your employees and contractors, but in a VISP setup, you can also add accounts for your reseller's employees. It is <B>highly recommended</B> to add a <B>separate account for each person</B> rather than using role accounts.<BR><BR>". qq!<A HREF="${p}edit/access_user.html"><I>Add an internal user</I></A><BR><BR>!; -#false laziness w/agent_type.cgi +#false laziness w/part_pkg.cgi +my %search = (); +my $search = ''; +unless ( $cgi->param('showdisabled') ) { + %search = ( 'disabled' => '' ); + $search = "( disabled = '' OR disabled IS NULL )"; +} + +#false laziness w/access_group.html & agent_type.cgi my $groups_sub = sub { my $access_user = shift; @@ -28,36 +36,63 @@ my $groups_sub = sub { }; +my $posttotal; +if ( $cgi->param('showdisabled') ) { + $cgi->param('showdisabled', 0); + $posttotal = '( <a href="'. $cgi->self_url. '">hide disabled users</a> )'; + $cgi->param('showdisabled', 1); +} else { + $cgi->param('showdisabled', 1); + $posttotal = '( <a href="'. $cgi->self_url. '">show disabled users</a> )'; + $cgi->param('showdisabled', 0); +} + my $count_query = 'SELECT COUNT(*) FROM access_user'; +$count_query .= " WHERE $search" + if $search; my $link = [ $p.'edit/access_user.html?', 'usernum' ]; +my @header = ( '#', 'Username' ); +my @fields = ( 'usernum', 'username' ); +my $align = 'rl'; +my @links = ( $link, $link ); +my @style = ( '', '' ); + +#false laziness w/part_pkg.cgi +#unless ( $cgi->param('showdisabled') ) { #its been reversed already +if ( $cgi->param('showdisabled') ) { #its been reversed already + push @header, 'Status'; + push @fields, sub { shift->disabled + ? '<FONT COLOR="#FF0000">DISABLED</FONT>' + : '<FONT COLOR="#00CC00">Active</FONT>' + }; + push @links, ''; + $align .= 'c'; + push @style, 'b'; +} + +push @header, 'Full name', 'Groups'; +push @fields, 'name', $groups_sub; +push @links, $link, ''; +$align .= 'll'; + %><%= include( 'elements/browse.html', - 'title' => 'Internal Users', - 'menubar' => [ #'Main menu' => $p, - 'Internal access groups' => $p.'browse/access_group.html', - ], - 'html_init' => $html_init, - 'name' => 'internal users', - 'query' => { 'table' => 'access_user', - 'hashref' => {}, - 'extra_sql' => 'ORDER BY last, first', - }, - 'count_query' => $count_query, - 'header' => [ '#', - 'Username', - 'Full name', - 'Groups' - ], - 'fields' => [ 'usernum', - 'username', - 'name', # sub { shift->name }, - $groups_sub, - ], - 'links' => [ $link, - $link, - $link, - '' - ], + 'title' => 'Internal Users', + 'menubar' => [ #'Main menu' => $p, + 'Internal access groups' => $p.'browse/access_group.html', + ], + 'html_init' => $html_init, + 'html_posttotal' => $posttotal, + 'name' => 'internal users', + 'query' => { 'table' => 'access_user', + 'hashref' => \%search, + 'extra_sql' => 'ORDER BY last, first', + }, + 'count_query' => $count_query, + 'header' => \@header, + 'fields' => \@fields, + 'links' => \@links, + 'style' => \@style, ) %> diff --git a/httemplate/browse/agent.cgi b/httemplate/browse/agent.cgi index 17cc8bd40..f5157d9b7 100755 --- a/httemplate/browse/agent.cgi +++ b/httemplate/browse/agent.cgi @@ -29,21 +29,27 @@ full offerings (via their type).<BR><BR> %> <% } %> -<%= table() %> +<%= include('/elements/table-grid.html') %> + +<% my $bgcolor1 = '#eeeeee'; + my $bgcolor2 = '#ffffff'; + my $bgcolor = ''; +%> + <TR> - <TH COLSPAN=<%= ( $cgi->param('showdisabled') || !dbdef->table('agent')->column('disabled') ) ? 2 : 3 %>>Agent</TH> - <TH>Type</TH> - <TH>Customers</TH> - <TH><FONT SIZE=-1>Customer<BR>packages</FONT></TH> - <TH>Reports</TH> - <TH>Registration codes</TH> - <TH>Prepaid cards</TH> + <TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=<%= ( $cgi->param('showdisabled') || !dbdef->table('agent')->column('disabled') ) ? 2 : 3 %>>Agent</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Type</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Customers</TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Customer<BR>packages</FONT></TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Reports</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Registration codes</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Prepaid cards</TH> <% if ( $conf->config('ticket_system') ) { %> - <TH>Ticketing</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Ticketing</TH> <% } %> - <TH><FONT SIZE=-1>Payment Gateway Overrides</FONT></TH> - <TH><FONT SIZE=-1>Freq.</FONT></TH> - <TH><FONT SIZE=-1>Prog.</FONT></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Payment Gateway Overrides</FONT></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Freq.</FONT></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Prog.</FONT></TH> </TR> <% # <TH><FONT SIZE=-1>Agent #</FONT></TH> @@ -58,107 +64,157 @@ foreach my $agent ( sort { 'agentnum='. $agent->agentnum; my $cust_pkg_link = $p. 'search/cust_pkg.cgi?agentnum='. $agent->agentnum; + + if ( $bgcolor eq $bgcolor1 ) { + $bgcolor = $bgcolor2; + } else { + $bgcolor = $bgcolor1; + } %> <TR> - <TD><A HREF="<%=$p%>edit/agent.cgi?<%= $agent->agentnum %>"> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"><A HREF="<%=$p%>edit/agent.cgi?<%= $agent->agentnum %>"> <%= $agent->agentnum %></A></TD> <% if ( dbdef->table('agent')->column('disabled') && !$cgi->param('showdisabled') ) { %> - <TD><%= $agent->disabled ? 'DISABLED' : '' %></TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"><%= $agent->disabled ? 'DISABLED' : '' %></TD> <% } %> - <TD><A HREF="<%=$p%>edit/agent.cgi?<%= $agent->agentnum %>"> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"><A HREF="<%=$p%>edit/agent.cgi?<%= $agent->agentnum %>"> <%= $agent->agent %></A></TD> - <TD><A HREF="<%=$p%>edit/agent_type.cgi?<%= $agent->typenum %>"><%= $agent->agent_type->atype %></A></TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"><A HREF="<%=$p%>edit/agent_type.cgi?<%= $agent->typenum %>"><%= $agent->agent_type->atype %></A></TD> + + <TD CLASS="inv" BGCOLOR="<%= $bgcolor %>"> + <TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0> - <TD> - <TABLE CELLSPACING=0 CELLPADDING=0> <TR> <TH ALIGN="right" WIDTH="40%"> - <%= my $num_prospect = $agent->num_prospect_cust_main %> + <FONT COLOR="#7e0079"> + <%= my $num_prospect = $agent->num_prospect_cust_main %> + </FONT> </TH> + <TD> <% if ( $num_prospect ) { %> <A HREF="<%= $cust_main_link %>&prospect=1"><% } %>prospects<% if ($num_prospect ) { %></A><% } %> <TD> </TR> + + <TR> + <TH ALIGN="right" WIDTH="40%"> + <FONT COLOR="#0000CC"> + <%= my $num_inactive = $agent->num_inactive_cust_main %> + </FONT> + </TH> + + <TD> + <% if ( $num_inactive ) { %> + <A HREF="<%= $cust_main_link %>&inactive=1"><% } %>inactive<% if ( $num_inactive ) { %></A><% } %> + </TD> + </TR> + <TR> <TH ALIGN="right" WIDTH="40%"> <FONT COLOR="#00CC00"> <%= my $num_active = $agent->num_active_cust_main %> </FONT> </TH> + <TD> <% if ( $num_active ) { %> <A HREF="<%= $cust_main_link %>&active=1"><% } %>active<% if ( $num_active ) { %></A><% } %> </TD> </TR> + <TR> <TH ALIGN="right" WIDTH="40%"> <FONT COLOR="#FF9900"> <%= my $num_susp = $agent->num_susp_cust_main %> </FONT> </TH> + <TD> <% if ( $num_susp ) { %> <A HREF="<%= $cust_main_link %>&suspended=1"><% } %>suspended<% if ( $num_susp ) { %></A><% } %> </TD> </TR> + <TR> <TH ALIGN="right" WIDTH="40%"> <FONT COLOR="#FF0000"> <%= my $num_cancel = $agent->num_cancel_cust_main %> </FONT> </TH> + <TD> <% if ( $num_cancel ) { %> <A HREF="<%= $cust_main_link %>&showcancelledcustomers=1&cancelled=1"><% } %>cancelled<% if ( $num_cancel ) { %></A><% } %> </TD> </TR> + </TABLE> </TD> - <TD> - <TABLE CELLSPACING=0 CELLPADDING=0> + <TD CLASS="inv" BGCOLOR="<%= $bgcolor %>" VALIGN="bottom"> + <TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0> + + <TR> + <TH ALIGN="right" WIDTH="40%"> + <FONT COLOR="#0000CC"> + <%= my $num_inactive_pkg = $agent->num_inactive_cust_pkg %> + </FONT> + </TH> + + <TD> + <% if ( $num_inactive_pkg ) { %> + <A HREF="<%= $cust_pkg_link %>&magic=inactive"><% } %>inactive<% if ( $num_inactive_pkg ) { %></A><% } %> + </TD> + </TR> + <TR> <TH ALIGN="right" WIDTH="40%"> <FONT COLOR="#00CC00"> <%= my $num_active_pkg = $agent->num_active_cust_pkg %> </FONT> </TH> + <TD> <% if ( $num_active_pkg ) { %> <A HREF="<%= $cust_pkg_link %>&magic=active"><% } %>active<% if ( $num_active_pkg ) { %></A><% } %> </TD> </TR> + <TR> <TH ALIGN="right" WIDTH="40%"> <FONT COLOR="#FF9900"> <%= my $num_susp_pkg = $agent->num_susp_cust_pkg %> </FONT> + </TH> <TD> <% if ( $num_susp_pkg ) { %> <A HREF="<%= $cust_pkg_link %>&magic=suspended"><% } %>suspended<% if ( $num_susp_pkg ) { %></A><% } %> </TD> </TR> + <TR> <TH ALIGN="right" WIDTH="40%"> <FONT COLOR="#FF0000"> <%= my $num_cancel_pkg = $agent->num_cancel_cust_pkg %> </FONT> </TH> + <TD> <% if ( $num_cancel_pkg ) { %> <A HREF="<%= $cust_pkg_link %>&magic=cancelled"><% } %>cancelled<% if ( $num_cancel_pkg ) { %></A><% } %> </TD> </TR> + </TABLE> </TD> - <TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"> <A HREF="<%= $p %>search/report_cust_pay.html?agentnum=<%= $agent->agentnum %>">Payments</A> <BR><A HREF="<%= $p %>search/report_cust_credit.html?agentnum=<%= $agent->agentnum %>">Credits</A> <BR><A HREF="<%= $p %>search/report_receivables.cgi?agentnum=<%= $agent->agentnum %>">A/R Aging</A> @@ -166,14 +222,14 @@ foreach my $agent ( sort { </TD> - <TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"> <%= my $num_reg_code = $agent->num_reg_code %> <% if ( $num_reg_code ) { %> <A HREF="<%=$p%>search/reg_code.html?agentnum=<%= $agent->agentnum %>"><% } %>Unused<% if ( $num_reg_code ) { %></A><% } %> <BR><A HREF="<%=$p%>edit/reg_code.cgi?agentnum=<%= $agent->agentnum %>">Generate codes</A> </TD> - <TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"> <%= my $num_prepay_credit = $agent->num_prepay_credit %> <% if ( $num_prepay_credit ) { %> <A HREF="<%=$p%>search/prepay_credit.html?agentnum=<%= $agent->agentnum %>"><% } %>Unused<% if ( $num_prepay_credit ) { %></A><% } %> @@ -182,7 +238,7 @@ foreach my $agent ( sort { <% if ( $conf->config('ticket_system') ) { %> - <TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"> <% if ( $agent->ticketing_queueid ) { %> Queue: <%= $agent->ticketing_queueid %>: <%= $agent->ticketing_queue %><BR> <% } %> @@ -190,7 +246,7 @@ foreach my $agent ( sort { <% } %> - <TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"> <TABLE CELLSPACING=0 CELLPADDING=0> <% foreach my $override ( # sort { } want taxclass-full stuff first? and default cards (empty cardtype) @@ -214,8 +270,10 @@ foreach my $agent ( sort { </TABLE> </TD> - <TD><%= $agent->freq %></TD> - <TD><%= $agent->prog %></TD> +<!-- + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"><%= $agent->freq %></TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"><%= $agent->prog %></TD> +--> </TR> diff --git a/httemplate/browse/agent_type.cgi b/httemplate/browse/agent_type.cgi index a5ffb1048..ceffce3d4 100755 --- a/httemplate/browse/agent_type.cgi +++ b/httemplate/browse/agent_type.cgi @@ -13,21 +13,18 @@ my $packages_sub = sub { [ map { my $type_pkgs = $_; - my $part_pkg = $type_pkgs->part_pkg; + #my $part_pkg = $type_pkgs->part_pkg; [ { - 'data' => $part_pkg->pkg. ' - '. $part_pkg->comment, + #'data' => $part_pkg->pkg. ' - '. $part_pkg->comment, + 'data' => $type_pkgs->pkg. ' - '. $type_pkgs->comment, 'align' => 'left', 'link' => $p. 'edit/part_pkg.cgi?'. $type_pkgs->pkgpart, }, ]; } - #sort { - # } - grep { - $_->part_pkg and ! $_->part_pkg->disabled - } - $agent_type->type_pkgs #XXX the method should order itself by something + + $agent_type->type_pkgs_enabled ]; }; diff --git a/httemplate/browse/cust_pay_batch.cgi b/httemplate/browse/cust_pay_batch.cgi index 6ee983ab4..c7f0afe76 100755 --- a/httemplate/browse/cust_pay_batch.cgi +++ b/httemplate/browse/cust_pay_batch.cgi @@ -15,7 +15,7 @@ Filename <INPUT TYPE="file" NAME="batch_results"><BR> Format <SELECT NAME="format"> <OPTION VALUE="">Default batch mode</OPTION> <OPTION VALUE="csv-td_canada_trust-merchant_pc_batch">CSV results from TD Canada Trust Merchant PC Batch</OPTION> -<OPTION VALUE="BoM">Bank of Montreal ECA results</OPTION> +<OPTION VALUE="BoM">Bank of Montreal ECA batch</OPTION> </SELECT><BR> <INPUT TYPE="submit" VALUE="Upload"></FORM> <BR> diff --git a/httemplate/browse/inventory_class.html b/httemplate/browse/inventory_class.html index 6da3c9e3c..4a15bf7d4 100644 --- a/httemplate/browse/inventory_class.html +++ b/httemplate/browse/inventory_class.html @@ -8,7 +8,7 @@ tie my %labels, 'Tie::IxHash', my %link = ( 'num_avail' => ';avail=1', - 'num_used' => ';avail=1', + 'num_used' => ';used=1', 'num_total' => '', ); diff --git a/httemplate/browse/part_pkg.cgi b/httemplate/browse/part_pkg.cgi index 41d86358c..a5e212d17 100755 --- a/httemplate/browse/part_pkg.cgi +++ b/httemplate/browse/part_pkg.cgi @@ -1,5 +1,6 @@ <% +#false laziness w/access_user.html my %search = (); my $search = ''; unless ( $cgi->param('showdisabled') ) { @@ -53,11 +54,14 @@ my $posttotal; if ( $cgi->param('showdisabled') ) { $cgi->param('showdisabled', 0); $posttotal = '( <a href="'. $cgi->self_url. '">hide disabled packages</a> )'; + $cgi->param('showdisabled', 1); } else { $cgi->param('showdisabled', 1); $posttotal = '( <a href="'. $cgi->self_url. '">show disabled packages</a> )'; + $cgi->param('showdisabled', 0); } + # ------ my $link = [ $p.'edit/part_pkg.cgi?', 'pkgpart' ]; @@ -68,7 +72,9 @@ my $align = 'rll'; my @links = ( $link, $link, '' ); my @style = ( '', '', '' ); -unless ( $cgi->param('showdisabled') ) { #its been reversed already +#false laziness w/access_user.html +#unless ( $cgi->param('showdisabled') ) { #its been reversed already +if ( $cgi->param('showdisabled') ) { #its been reversed already push @header, 'Status'; push @fields, sub { shift->disabled ? '<FONT COLOR="#FF0000">DISABLED</FONT>' diff --git a/httemplate/browse/part_referral.cgi b/httemplate/browse/part_referral.html index 238ddace7..c50a406ed 100755 --- a/httemplate/browse/part_referral.cgi +++ b/httemplate/browse/part_referral.html @@ -1,11 +1,9 @@ -<!-- mason kludge --> -<%= include("/elements/header.html","Advertising source Listing", menubar( - 'Main Menu' => $p, -# 'Add new referral' => "../edit/part_referral.cgi", -)) %> +<%= include("/elements/header.html","Advertising source Listing" ) %> + Where a customer heard about your service. Tracked for informational purposes. <BR><BR> -<A HREF="<%= $p %>edit/part_referral.cgi"><I>Add a new advertising source</I></A> + +<A HREF="<%= $p %>edit/part_referral.html"><I>Add a new advertising source</I></A> <BR><BR> <% @@ -34,36 +32,71 @@ Where a customer heard about your service. Tracked for informational purposes. 'Total' => 86400, # 60sec * 60min * 24hrs ); + my $curuser = $FS::CurrentUser::CurrentUser; + my $statement = "SELECT COUNT(*) FROM h_cust_main WHERE history_action = 'insert' AND refnum = ? AND history_date >= ? AND history_date < ? - "; + AND ". $curuser->agentnums_sql; my $sth = dbh->prepare($statement) or die dbh->errstr; + + my $show_agentnums = scalar($curuser->agentnums); + +%> + +<%= include('/elements/table-grid.html') %> + +<% my $bgcolor1 = '#eeeeee'; + my $bgcolor2 = '#ffffff'; + my $bgcolor = ''; %> -<%= table() %> <TR> - <TH COLSPAN=2 ROWSPAN=2>Advertising source</TH> - <TH COLSPAN=<%= scalar(keys %after) %>>Customers</TH> + <TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=2 ROWSPAN=2>Advertising source</TH> + <% if ( $show_agentnums ) { %> + <TH CLASS="grid" BGCOLOR="#cccccc" ROWSPAN=2>Agent</TH> + <% } %> + <TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=<%= scalar(keys %after) %>>Customers</TH> </TR> <% for my $period ( keys %after ) { %> - <TH><FONT SIZE=-1><%= $period %></FONT></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1><%= $period %></FONT></TH> <% } %> </TR> <% -foreach my $part_referral ( sort { - $a->getfield('refnum') <=> $b->getfield('refnum') -} qsearch('part_referral',{}) ) { +foreach my $part_referral ( FS::part_referral->all_part_referral(1) ) { + + if ( $bgcolor eq $bgcolor1 ) { + $bgcolor = $bgcolor2; + } else { + $bgcolor = $bgcolor1; + } + + $a = 0; + %> <TR> - <TD><A HREF="<%= $p %>edit/part_referral.cgi?<%= $part_referral->refnum %>"> - <%= $part_referral->refnum %></A></TD> - <TD><A HREF="<%= $p %>edit/part_referral.cgi?<%= $part_referral->refnum %>"> - <%= $part_referral->referral %></A></TD> + + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"> + <% if ( $part_referral->agentnum || $curuser->access_right('Edit global advertising sources') ) { + $a++; + %> + <A HREF="<%= $p %>edit/part_referral.html?<%= $part_referral->refnum %>"> + <% } %> + <%= $part_referral->refnum %><%= $a ? '</A>' : '' %></TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"> + <% if ( $a ) { %> + <A HREF="<%= $p %>edit/part_referral.html?<%= $part_referral->refnum %>"> + <% } %> + <%= $part_referral->referral %><%= $a ? '</A>' : '' %></TD> + + <% if ( $show_agentnums ) { %> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"><%= $part_referral->agentnum ? $part_referral->agent->agent : '(global)' %></TD> + <% } %> + <% for my $period ( keys %after ) { $sth->execute( $part_referral->refnum, $today-$after{$period}, @@ -71,7 +104,7 @@ foreach my $part_referral ( sort { ) or die $sth->errstr; my $number = $sth->fetchrow_arrayref->[0]; %> - <TD ALIGN="right"><%= $number %></TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>" ALIGN="right"><%= $number %></TD> <% } %> </TR> <% } %> @@ -82,14 +115,14 @@ foreach my $part_referral ( sort { or die dbh->errstr; %> <TR> - <TH COLSPAN=2>Total</TH> + <TD BGCOLOR="#dddddd" ALIGN="center" COLSPAN=3><B>Total</B></TD> <% for my $period ( keys %after ) { $sth->execute( $today-$after{$period}, $today+$before{$period}, ) or die $sth->errstr; my $number = $sth->fetchrow_arrayref->[0]; %> - <TD ALIGN="right"><%= $number %></TD> + <TD BGCOLOR="#dddddd" ALIGN="right"><B><%= $number %><B></TD> <% } %> </TR> </TABLE> diff --git a/httemplate/browse/part_svc.cgi b/httemplate/browse/part_svc.cgi index eef2676c0..805bd88b9 100755 --- a/httemplate/browse/part_svc.cgi +++ b/httemplate/browse/part_svc.cgi @@ -1,9 +1,15 @@ <% +#code duplication w/ edit/part_svc.cgi, should move this hash to part_svc.pm my %flag = ( - 'D' => 'Default', - 'F' => 'Fixed', '' => '', + 'D' => 'Default', + 'F' => 'Fixed (unchangeable)', + #'M' => 'Manual selection from inventory', + 'M' => 'Manual selected from inventory', + #'A' => 'Automatically fill in from inventory', + 'A' => 'Automatically filled in from inventory', + 'X' => 'Excluded', ); my %search; @@ -27,6 +33,8 @@ if ( $cgi->param('orderby') eq 'active' ) { @part_svc = sort { lc($a->svc) cmp lc($b->svc) } @part_svc; } +my %inventory_class = (); + %> <%= include("/elements/header.html",'Service Definition Listing', menubar( 'Main Menu' => $p) ) %> @@ -125,7 +133,21 @@ map { qsearchs('part_export', { exportnum => $_->exportnum } ) } qsearch('export <%= $n1 %> <TD><%= $field %></TD> <TD><%= $flag{$flag} %></TD> - <TD><%= $part_svc->part_svc_column($field)->columnvalue%></TD> + + <TD> + <% my $value = $part_svc->part_svc_column($field)->columnvalue; + if ( $flag =~ /^[MA]$/ ) { + $inventory_class{$value} + ||= qsearchs('inventory_class', { 'classnum' => $value } ); + %> + <%= $inventory_class{$value} + ? $inventory_class{$value}->classname + : "WARNING: inventory_class.classnum $value not found" %> + <% } else { %> + <%= $value %> + <% } %> + </TD> + <% $n1="</TR><TR>"; } diff --git a/httemplate/config/config.cgi b/httemplate/config/config.cgi index 21f79a9dc..cf228dba5 100644 --- a/httemplate/config/config.cgi +++ b/httemplate/config/config.cgi @@ -55,25 +55,65 @@ function SafeOnsubmit() { #warn $i->key unless defined($type); %> <% if ( $type eq '' ) { %> - <font color="#ff0000">no type</font> + + <font color="#ff0000">no type</font> + <% } elsif ( $type eq 'textarea' ) { %> - <textarea name="<%= $i->key. $n %>" rows=5><%= "\n". join("\n", $conf->config($i->key) ) %></textarea> + + <textarea name="<%= $i->key. $n %>" rows=5><%= "\n". join("\n", $conf->config($i->key) ) %></textarea> + <% } elsif ( $type eq 'checkbox' ) { %> - <input name="<%= $i->key. $n %>" type="checkbox" value="1"<%= $conf->exists($i->key) ? ' CHECKED' : '' %>> + + <input name="<%= $i->key. $n %>" type="checkbox" value="1"<%= $conf->exists($i->key) ? ' CHECKED' : '' %>> + <% } elsif ( $type eq 'text' ) { %> - <input name="<%= $i->key. $n %>" type="<%= $type %>" value="<%= $conf->exists($i->key) ? $conf->config($i->key) : '' %>"> + + <input name="<%= $i->key. $n %>" type="<%= $type %>" value="<%= $conf->exists($i->key) ? $conf->config($i->key) : '' %>"> + <% } elsif ( $type eq 'select' || $type eq 'selectmultiple' ) { %> - <select name="<%= $i->key. $n %>" <%= $type eq 'selectmultiple' ? 'MULTIPLE' : '' %>> - <% my %saw; - foreach my $value ( "", @{$i->select_enum} ) { - local($^W)=0; next if $saw{$value}++; %> - <option value="<%= $value %>"<%= $value eq $conf->config($i->key) || ( $type eq 'selectmultiple' && grep { $_ eq $value } $conf->config($i->key) ) ? ' SELECTED' : '' %>><%= $value %> - <% } %> - <% if ( $conf->exists($i->key) && $conf->config($i->key) && ! grep { $conf->config($i->key) eq $_ } @{$i->select_enum}) { %> - <option value=<%= $conf->config($i->key) %> SELECTED><%= $conf->config($i->key) %> + + <select name="<%= $i->key. $n %>" <%= $type eq 'selectmultiple' ? 'MULTIPLE' : '' %>> + <% + my %hash = (); + if ( $i->select_enum ) { + tie %hash, 'Tie::IxHash', + '' => '', map { $_ => $_ } @{ $i->select_enum }; + } elsif ( $i->select_hash ) { + if ( ref($i->select_hash) eq 'ARRAY' ) { + tie %hash, 'Tie::IxHash', + '' => '', @{ $i->select_hash }; + } else { + tie %hash, 'Tie::IxHash', + '' => '', %{ $i->select_hash }; + } + } else { + %hash = ( '' => 'WARNING: neither select_enum nor select_hash specified in Conf.pm for configuration option "'. $i->key. '"' ); + } + + my %saw = (); + foreach my $value ( keys %hash ) { + local($^W)=0; next if $saw{$value}++; + my $label = $hash{$value}; + %> + + <option value="<%= $value %>"<%= $value eq $conf->config($i->key) || ( $type eq 'selectmultiple' && grep { $_ eq $value } $conf->config($i->key) ) ? ' SELECTED' : '' %>><%= $label %> + + <% } %> + + <% my $curvalue = $conf->config($i->key); + if ( $conf->exists($i->key) && $curvalue + && ! $hash{$curvalue} + ) { + %> + + <option value="<%= $conf->config($i->key) %>" SELECTED><%= exists( $hash{ $conf->config($i->key) } ) ? $hash{ $conf->config($i->key) } : $conf->config($i->key) %> + <% } %> + </select> + <% } elsif ( $type eq 'select-sub' ) { %> + <select name="<%= $i->key. $n %>"> <option value=""> <% my %options = &{$i->options_sub}; @@ -88,7 +128,9 @@ function SafeOnsubmit() { <option value=<%= $conf->config($i->key) %> SELECTED><%= $conf->config($i->key) %>: <%= &{ $i->option_sub }( $conf->config($i->key) ) %> <% } %> </select> - <% } elsif ( $type eq 'editlist' ) { %> + + <% } elsif ( $type eq 'editlist' ) { %> + <script> function doremove<%= $i->key. $n %>() { fromObject = document.OneTrueForm.<%= $i->key. $n %>; @@ -167,9 +209,13 @@ function SafeOnsubmit() { <% } %> <td><input type="button" value="add" onClick="doadd<%= $i->key. $n %>(this.form)"></td> </tr></table> + <% } else { %> + <font color="#ff0000">unknown type <%= $type %></font> + <% } %> + <% $n++; } %> </td> <td><a name="<%= $i->key %>"> diff --git a/httemplate/docs/index.html b/httemplate/docs/index.html index bec62e34a..d7b464346 100644 --- a/httemplate/docs/index.html +++ b/httemplate/docs/index.html @@ -6,11 +6,9 @@ <img src="overview-new.png"> <h3>Installation and upgrades</h3> <ul> - <li><a href="install.html">New Installation</a> - <li><a href="install-rt.html">Installing integrated RT ticketing</a> - <li><a href="upgrade9.html">Upgrading from 1.4.0 to 1.4.1</a> - <li><a href="upgrade-1.4.2.html">Upgrading from 1.4.1 to 1.4.2</a> - <li><a href="upgrade10.html">Upgrading from 1.4.1 (or 1.4.2) to 1.5.8</a> + <li><a href="http://www.sisd.com/mediawiki/index.php/Freeside:1.7:Documentation:Installation">New Installation</a> + <li><a href="http://www.sisd.com/mediawiki/index.php/Freeside:1.7:Documentation:RT_Installation">Installing integrated RT ticketing</a> + <li><a href="http://www.sisd.com/mediawiki/index.php/Freeside:1.7:Documentation:Upgrading">Upgrading from 1.5.8 or 1.6.X</a> </ul> <h3>Configuration and setup</h3> <ul> diff --git a/httemplate/docs/install-rt.html b/httemplate/docs/install-rt.html deleted file mode 100644 index da0941a09..000000000 --- a/httemplate/docs/install-rt.html +++ /dev/null @@ -1,78 +0,0 @@ -<head> - <title>Installing integrated RT ticketing</title> -</head> -<body> -<h1>Installing integrated RT ticketing</h1> - -<p><i>Integrated ticketing is an new feature and these instructions are preliminary. Documentation contributions are welcome.</i> - -<p><i>There is also support for running this integration against an external RT installation, but it is not (yet) documented.</i> - -<p>Perl minimum version 5.8.3 is required. HTML::Mason is required. - -<p>Install the following perl modules: - <ul> - <li><a href="http://search.cpan.org/search?dist=Apache-Session">Apache::Session</a> - <li><a href="http://search.cpan.org/search?dist=HTML-Tree">HTML::TreeBuilder (HTML-Tree)</a> - <li><a href="http://search.cpan.org/search?dist=HTML-Format">HTML::FormatText (HTML-Format)</a> - <li><a href="http://search.cpan.org/search?dist=Test-Inline">Test::Inline</a> - <li><a href="http://search.cpan.org/search?dist=Class-ReturnValue">Class::ReturnValue</a> - <li><a href="http://search.cpan.org/search?dist=DBIx-SearchBuilder">DBIx::SearchBuilder</a> - <li><a href="http://search.cpan.org/search?dist=Log-Dispatch">Log::Dispatch</a> - <li><a href="http://search.cpan.org/search?dist=Locale-Maketext-Lexicon">Locale::Maketext::Lexicon</a> - <li><a href="http://search.cpan.org/search?dist=Locale-Maketext-Fuzzy">Locale::Maketext::Fuzzy</a> - <li><a href="http://search.cpan.org/search?dist=Text-Wrapper">Text::Wrapper</a> - <li><a href="http://search.cpan.org/search?dist=Time-modules">Time::ParseDate (Time-modules)</a> - <li><a href="http://search.cpan.org/search?dist=TermReadKey">Term::ReadKey (TermReadKey)</a> - <li><a href="http://search.cpan.org/search?dist=Text-Autoformat">Text::Autoformat</a> - <li><a href="http://search.cpan.org/search?dist=Text-Quoted">Text::Quoted</a> - <li><a href="http://search.cpan.org/search?dist=Regexp-Common">Regexp::Common</a> - <li><a href="http://search.cpan.org/search?dist=HTML-Scrubber">HTML::Scrubber</a> - <li><a href="http://search.cpan.org/search?dist=Tree-Simple">Tree::Simple</a> - </ul> - -<p>Create a new Unix group called 'rt' - -<p>Edit the top-level Makefile, set RT_ENABLED to 1 and set the RT_DOMAIN, RT_TIMEZONE, and FREESIDE_URL variables. - -<p><pre>make configure-rt -make create-rt -make install-rt -</pre> - -<p>Add the following to your httpd.conf: -<pre> -# replace /var/www/freeside with your freeside document root -<DirectoryMatch "^/var/www/freeside/rt/.*NoAuth"> -<Limit GET POST> -allow from all -Satisfy any -SetHandler perl-script -PerlHandler HTML::Mason -</Limit> -</DirectoryMatch> -# replace /var/www/freeside with your freeside document root -<DirectoryMatch "^/var/www/freeside/rt/.*NoAuth/images"> -SetHandler None -</DirectoryMatch> -# replace /var/www/freeside with your freeside document root -<Directory /var/www/freeside/rt/Ticket/Attachment> -SetHandler perl-script -PerlHandler HTML::Mason -</Directory> -</pre> - -<p>Set the <b>ticket_system</b> configuration value to <b>RT_Internal</b>. You may also wish to set <b>ticket_system-default_queueid</b> once you have RT configured. - -<p>Bootstrap RT's permissions: - <ul> - <li>Click on "Ticketing Main" on the Freeside main menu to auto-create an RT login for your username - <li>Run <code>freeside-adduser -h /usr/local/etc/freeside/htpasswd root</code> and set a (temporary) password - <li>Log into your Freeside installation as the "root" user you just created, by closing your browser or using <code>https://root@yourmachone/freeside/</code> syntax. - <li>Click on "Ticketing Main" on the Freeside main menu. Click on "Configuration", then "Global", and then "User Rights". Grant the "SuperUser" right to your RT login. - <li>Remove the temporary "root" user from /usr/local/etc/freeside/mapsecrets and /usr/local/etc/freeside/htpasswd - </ul> - -<p>Follow the <A HREF="http://wiki.bestpractical.com/">regular RT documentation</A> to configure RT, setup the mailgate, etc. - -</body> diff --git a/httemplate/docs/install.html b/httemplate/docs/install.html deleted file mode 100644 index 78172e8e4..000000000 --- a/httemplate/docs/install.html +++ /dev/null @@ -1,173 +0,0 @@ -<head> - <title>Installation</title> -</head> -<body> -<h1>Installation</h1> -<i>Note: Install Freeside on a firewalled, private server, not a public (web, RADIUS, etc.) server.</i><br><br> -Before installing, you need: -<ul> - <li><a href="http://www.perl.com/">Perl</a>, minimum version 5.005_03. (5.8.3 for the integrated RT ticketing) - <li><a href="http://www.apache.org">Apache</a> (<a href="http://www.modssl.org/">mod_ssl</a> or <a href="http://www.apache-ssl.org">Apache-SSL</a> highly recommended) - <li><a href="http://perl.apache.org/">mod_perl</a> (if compiling your own mod_perl, make sure you set the <a href="http://perl.apache.org/guide/install.html#EVERYTHING">EVERYTHING</a>=1 compile-time option) - <li><a href="http://www.openssh.com/">SSH</a> (<a href="http://www.openssh.com//">OpenSSH</a> is recommended. SSH Communications Security <a href="http://www.ssh.com/products/ssh/download.cfm">commercial SSH version 3</a> has been reported incompatible with Freeside.) - <li><a href="http://rsync.samba.org/">rsync</a> - <li>Optional, enables typeset invoices: teTeX and Ghostscript (included with most distributions). - <li>A <b>transactional</b> database engine <a href="http://search.cpan.org/search?mode=module&query=DBD%3A%3A">supported</a> by Perl's <a href="http://dbi.perl.org">DBI</a>. - <ul> - <li><a href="http://www.postgresql.org/">PostgreSQL</a> is recommended (v7.2 or later, 7.4 or later recommended). - <li> <a href="http://www.mysql.com/">MySQL</a> is <b>not currently supported</b>. <FONT SIZE="-1"><i>Developers intersted in maintaining MySQL support are welcome to ask on the -devel mailing list; many things work, but MySQL support needs a maintainer to update it for recent (and future) changes.</i></FONT> - <!-- <li><a href="http://www.mysql.com/">MySQL</a> <b>MINIMUM VERSION 4.1</b> is untested but may work. Versions before 4.1 do not support standard SQL subqueries and are <b>NOT SUPPORTED</b>. -<!-- <li>MySQL has been reported to work. - MySQL's default <a href="http://www.mysql.com/doc/M/y/MyISAM.html">MyISAM</a> and <a href="http://www.mysql.com/doc/I/S/ISAM.html">ISAM</a> table types are not supported. You <b>must</b> use one of the new <a href="http://www.mysql.com/doc/T/a/Table_types.html">transaction-safe table types</a> such as <a href="http://www.mysql.com/doc/I/n/InnoDB.html">InnoDB</a>. Set it as the default table type using the <code>--default-table-type=InnoDB</code> <a href="http://www.mysql.com/documentation/mysql/bychapter/manual_MySQL_Database_Administration.html#Command-line_options">mysqld command-line option</a> or by setting <code>default-table-type=InnoDB</code> in the <a href="http://www.mysql.com/documentation/mysql/bychapter/manual_MySQL_Database_Administration.html#Option_files">my.cnf option file</a>. ---> - </ul> - <i>Note: the above only applies to the database used by the Freeside software itself. Freeside can integrate with RADIUS and other servers running MySQL <!--(any version)--> or any other DBI-supported database.</i> - <li>Perl modules (<a href="http://search.cpan.org/~andk/CPAN/lib/CPAN.pm">CPAN</a> will query, download and build perl modules automatically) - <ul> -<!-- <li><a href="http://search.cpan.org/dist/Array-PrintCols">Array-PrintCols</a> - <li><a href="http://search.cpan.org/dist/Term-Query">Term-Query</a> (make test broken; install manually) --> - <li><a href="http://search.cpan.org/dist/MIME-Base64">MIME-Base64</a> - <li><a href="http://search.cpan.org/dist/Digest-MD5">Digest-MD5</a> -<!-- <li><a href="http://search.cpan.org/dist/MD5">MD5</a> --> - <li><a href="http://search.cpan.org/dist/URI">URI</a> - <li><a href="http://search.cpan.org/dist/HTML-Tagset">HTML-Tagset</a> - <li><a href="http://search.cpan.org/dist/HTML-Parser">HTML-Parser</a> - <li><a href="http://search.cpan.org/dist/libnet">libnet</a> - <li><a href="http://search.cpan.org/dist/Locale-Codes">Locale-Codes</a> - <li><a href="http://search.cpan.org/dist/Net-Whois-Raw">Net-Whois-Raw</a> - <li><a href="http://search.cpan.org/dist/libwww-perl">libwww-perl</a> - <li><a href="http://search.cpan.org/dist/Business-CreditCard">Business-CreditCard</a> -<!-- <li><a href="http://search.cpan.org/dist/Data-ShowTable">Data-ShowTable</a> --> - <li><a href="http://search.cpan.org/dist/MailTools">MailTools</a> - <li><a href="http://search.cpan.org/dist/TimeDate">TimeDate</a> - <li><a href="http://search.cpan.org/dist/DateManip">DateManip</a> - <li><a href="http://search.cpan.org/dist/File-CounterFile">File-CounterFile</a> - <li><a href="http://search.cpan.org/dist/FreezeThaw">FreezeThaw</a> - <li><a href="http://search.cpan.org/dist/String-Approx">String-Approx</a> - <li><a href="http://search.cpan.org/dist/Text-Template">Text-Template</a> - <li><a href="http://search.cpan.org/dist/DBI">DBI</a> - <li><a href="http://search.cpan.org/search?mode=module&query=DBD">DBD for your database engine</a> (<a href="http://search.cpan.org/dist/DBD-Pg">DBD::Pg</a> for PostgreSQL<!--, <a href="http://search.cpan.org/search?dist=DBD-mysql">DBD::mysql</a> for MySQL-->) -<!-- <li><a href="http://search.cpan.org/dist/DBIx-DataSource">DBIx-DataSource</a> --> - <li><a href="http://search.cpan.org/dist/DBIx-DBSchema">DBIx-DBSchema</a> - <li><a href="http://search.cpan.org/dist/Net-SSH">Net-SSH</a> - <li><a href="http://search.cpan.org/dist/String-ShellQuote">String-ShellQuote</a> - <li><a href="http://search.cpan.org/dist/Net-SCP">Net-SCP</a> - <li><a href="http://www.masonhq.com/">HTML::Mason</a> - <li><a href="http://search.cpan.org/dist/Tie-IxHash">Tie-IxHash</a> - <li><a href="http://search.cpan.org/dist/Time-Duration">Time-Duration</a> - <li><a href="http://search.cpan.org/dist/HTML-Widgets-SelectLayers">HTML-Widgets-SelectLayers</a> - <li><a href="http://search.cpan.org/dist/Storable">Storable</a> - <li><a href="http://search.cpan.org/dist/Cache-Cache">Cache::Cache</a> - <li><a href="http://search.cpan.org/dist/NetAddr-IP">NetAddr-IP</a> - <li><a href="http://search.cpan.org/dist/Chart">Chart</a> - <li><a href="http://search.cpan.org/dist/Crypt-PasswdMD5">Crypt::PasswdMD5</a> - <li><a href="http://search.cpan.org/dist/Locale-SubCountry">Locale::SubCountry</a> - <li><a href="http://search.cpan.org/dist/Frontier-RPC">Frontier::RPC</a> - <li><a href="http://search.cpan.org/dist/Text-CSV_XS">Text::CSV_XS</a> - <li><a href="http://search.cpan.org/dist/Spreadsheet-WriteExcel">Spreadsheet::WriteExcel</a> - <li><a href="http://search.cpan.org/dist/IO-stringy">IO-stringy (IO::Scalar)</a> - <li><a href="http://search.cpan.org/dist/Frontier-RPC">Frontier::RPC (Frontier::RPC2)</a> - <li><a href="http://search.cpan.org/dist/MIME-tools">MIME::Entity (MIME-tools)</a> - <li><a href="http://search.cpan.org/dist/IPC-Run3">IPC::Run3</a> - <li><a href="http://search.cpan.org/dist/Term-ReadKey">Term::ReadKey</a> -<!-- <li><a href="http://search.cpan.org/dist/Crypt-YAPassGen">Crypt::YAPassGen</a> --> - <li><a href="http://search.cpan.org/dist/JSON">JSON</a> - <li><a href="http://search.cpan.org/search?mode=module&query=MIME::Entity">Fax::Hylafax::Client</a> <i>(Required if using FAX invoice destinations)</i> - <li><a href="http://search.cpan.org/dist/ApacheDBI">Apache::DBI</a> <i>(optional but recommended for better webinterface performance)</i> - </ul> -</ul> -Install the Freeside distribution: -<ul> - <li>Add the user and group `freeside' to your system. - <li>Allow the freeside user full access to the freeside database. - <ul> - <li> with <a href="http://www.postgresql.org/users-lounge/docs/7.1/postgres/user-manag.html#DATABASE-USERS">PostgreSQL</a>: - <pre> -$ su postgres (pgsql on some distributions) -$ createuser -P freeside -Enter password for user "freeside": -Enter it again: -Shall the new user be allowed to create databases? (y/n) y -Shall the new user be allowed to create more new users? (y/n) n -CREATE USER</pre> - <li> with <a href="http://www.mysql.com/documentation/mysql/bychapter/manual_MySQL_Database_Administration.html#User_Account_Management">MySQL</a>: - <pre> -$ mysqladmin -u root password '<i>set_a_root_database_password</i>' -$ mysql -u root -p -mysql> GRANT SELECT,INSERT,UPDATE,DELETE,INDEX,ALTER,CREATE,DROP on freeside.* TO freeside@localhost IDENTIFIED BY '<i>set_a_freeside_database_password</i>';</pre> - </ul> -<!-- <li>Unpack the tarball: <pre>gunzip -c fs-x.y.z.tar.gz | tar xvf -</pre>--> - <li>Edit the top-level Makefile: - <ul> - <li>Set <tt>DATASOURCE</tt> to your <a href="http://search.cpan.org/doc/TIMB/DBI-1.28/DBI.pm">DBI data source</a>, for example, <tt>DBI:Pg:dbname=freeside</tt> for PostgresSQL or <tt>DBI:mysql:freeside</tt> for MySQL. See the <a href="http://search.cpan.org/doc/TIMB/DBI-1.28/DBI.pm">DBI manpage</a> and the <a href="http://search.cpan.org/search?mode=module&query=DBD%3A%3A">manpage for your DBD</a> for the exact syntax of your DBI data source. - <li>Set <tt>DB_PASSWORD</tt> to the freeside database user's password. - </ul> - <li>Add the freeside database to your database engine: - <ul> - <li>with Postgres: - <pre> -$ su freeside -$ createdb -E sql_ascii freeside</pre> - <li>with MySQL: - <pre> -$ mysqladmin -u freeside -p create freeside </pre> - </ul> - <li>Build and install the Perl modules: - <pre> -$ make perl-modules -$ su -# make install-perl-modules</pre> - <li>Create the necessary configuration files:<pre> -$ su -# make create-config -</pre> - <li>Run a <b>separate</b> iteration of Apache[-SSL] with mod_perl enabled <b>as the freeside user</b>. - <li>Edit the <tt>Makefile</tt> and set <tt>TEMPLATE</tt> to <tt>asp</tt> or <tt>mason</tt>. Also set <tt>FREESIDE_DOCUMENT_ROOT</tt>. - <li>Run <tt> make install-docs</tt>. -<li>Configure Apache: -<font size="-1"><pre> -PerlModule HTML::Mason -# your freeside docuemnt root -<Directory /var/www/freeside> -<Files ~ (\.cgi|\.html)> -AddHandler perl-script .cgi .html -PerlHandler HTML::Mason -</Files> -<Perl> -require "/usr/local/etc/freeside/handler.pl"; -</Perl> -</Directory> -</pre></font> -<li>Restrict access to this web interface - see the <a href="http://httpd.apache.org/docs/misc/FAQ.html#user-authentication">Apache documentation on user authentication</a>. For example, to configure user authentication with <a href="http://httpd.apache.org/docs/mod/mod_auth.html">mod_auth</a> (flat files), add something like the following to your Apache httpd.conf file, adjusting for your actual paths: -<pre> -#your freeside document root -<Directory /var/www/freeside> -AuthName Freeside -AuthType Basic -AuthUserFile /usr/local/etc/freeside/htpasswd -require valid-user -</Directory> -</pre> - <li>Create one or more Freeside users (your internal sales/tech folks, not customer accounts). These users are setup using using Apache authentication, not UNIX user accounts. For example, using <a href="http://httpd.apache.org/docs/mod/mod_auth.html">mod_auth</a> (flat files): - <ul> - <li>First user:<font size="-1"> -<pre>$ su -# <a href="man/bin/freeside-adduser.html">freeside-adduser</a> -c -h /usr/local/etc/freeside/htpasswd <i>username</i></pre></font> - <li>Additional users:<font size="-1"> -<pre>$ su -# <a href="man/bin/freeside-adduser.html">freeside-adduser</a> -h /usr/local/etc/freeside/htpasswd <i>username</i></pre></font> - </ul> - <i>(using other auth types, add each user to your <a href="http://httpd.apache.org/docs/misc/FAQ.html#user-authentication">Apache authentication</a> and then run: <tt>freeside-adduser <b>username</b></tt>)</i> - <li>Create the Freeside system users: -<pre>$ su -# <a href="man/bin/freeside-adduser.html">freeside-adduser</a> fs_queue -# <a href="man/bin/freeside-adduser.html">freeside-adduser</a> fs_selfservice</pre> - <li>As the freeside UNIX user, run <tt>freeside-setup -d <b>domain.name</b> <b>username</b></tt> to create the database tables and initial data, passing the username of a Freeside user you created above: -<pre> -$ su freeside -$ freeside-setup -d </b>example.com</b> <b>username</b> -</pre> - <li><tt>freeside-queued</tt> was installed with the Perl modules. Start it now and ensure that is run upon system startup (Do this manually, or edit the top-level Makefile, replacing INIT_FILE with the appropriate location on your systemand QUEUED_USER with the username of a Freeside user you created above, and run <tt>make install-init</tt>) - <li>Now proceed to the initial <a href="admin.html">administration</a> of your installation. -</ul> -</body> diff --git a/httemplate/docs/trouble.html b/httemplate/docs/trouble.html deleted file mode 100755 index fce743928..000000000 --- a/httemplate/docs/trouble.html +++ /dev/null @@ -1,26 +0,0 @@ -<head> - <title>Troubleshooting</title> -</head> -<body> - <h1>Troubleshooting</h1> - <ul> - <li>When troubleshooting the web interface, helpful information is often in your web server's error log. - <li>If bin/svc_acct.import fails with an "Out of memory!" error using MySQL, upgrede MySQL and recompile the Perl DBD. There was a memory leak in some older versions of MySQL. - <li>If you get tons of errors in your web server's error log like this: -<pre> -Ambiguous use of value => resolved to "value" => -at /usr/lib/perl5/site_perl/File/CounterFile.pm line 132. -</pre> - This clutters up your log files but is otherwise harmless. Upgrade to the latest File::CounterFile. - <li>If you get errors like this: -<pre> -UID.pm: Can't open /var/spool/freeside/conf/secrets: Permission denied -at <i>/your/path</i>/site_perl/FS/UID.pm line 26. -BEGIN failed--compilation aborted at -<i>/your/path</i>/edit/process/part_svc.cgi line 15. -</pre> - Then the scripts are not running as the freeside freeside user. See -the <a href="install.html">New Installation</a> section of the documentation. - <li>If you receive `can not connect to server' errors using MySQL on a system that doesn't support native threading, you may need to specify the full hostname in your DBI datasource. See the <a href="http://www.mysql.com/Manual_chapter/manual_Problems.html#Can_not_connect_to_server">MySQL documentation</a>, DBI manpage and the DBD::mysql manpage for details. - </ul> -</body> diff --git a/httemplate/docs/upgrade-1.4.2.html b/httemplate/docs/upgrade-1.4.2.html deleted file mode 100644 index a24661142..000000000 --- a/httemplate/docs/upgrade-1.4.2.html +++ /dev/null @@ -1,27 +0,0 @@ -<head> - <title>Upgrading to 1.4.2</title> -</head> -<body> -<h1>Upgrading to 1.4.2 from 1.4.1</h1> -<ul> - <li>If migrating from less than 1.4.1, see these <a href="upgrade9.html">instructions</a> first. - <li>Back up your data and current Freeside installation. - <li>Install <a href="http://search.cpan.org/search?dist=Locale-SubCountry">Locale::SubCountry</a> - <li>Install <a href="http://search.cpan.org/search?dist=IPC-ShareLite">IPC::ShareLite</a> - <li>Install <a href="http://search.cpan.org/search?dist=HTML-Widgets-SelectLayers">HTML::Widgets::SelectLayers</a> 0.04. - <li>Install <a href="http://search.cpan.org/search?dist=DBIx-DBSchema">DBIx::DBSchema</a> 0.23. - <li>Install <a href="http://search.cpan.org/search?dist=DBD-Pg">DBD::Pg</a> 1.32. - <li>Install <a href="http://search.cpan.org/search?dist=Cache-Cache">Cache::Cache</a>. - <li>Install <a href="http://search.cpan.org/search?dist=Net-SSH">Net::SSH</a> 0.08. - <li>Install <a href="http://search.cpan.org/search?dist=Crypt-PasswdMD5">Crypt::PasswdMD5</a> - <li>Install <a href="http://search.cpan.org/search?dist=Net-Whois-Raw">Net::Whois::Raw</a> - <li>CGI.pm minimum version 2.47 is required. You will probably need to install a current CGI.pm from CPAN if you are using Perl 5.005 or earlier. - <li>File::Temp minimum version 0.14 is required. You will probably need to install a currrent File::Temp from CPAN if you are using Perl 5.6 or earlier. - <li>If using Apache::ASP, add <code>PerlSetVar RequestBinaryRead Off</code> to your Apache configuration and make sure you are using Apache::ASP minimum version 2.55. - <li>Run <code>make aspdocs</code> or <code>make masondocs</code>. - <li>Copy <code>aspdocs/</code> or <code>masondocs/</code> to your web server's document space. - <li>Run <code>make install-perl-modules</code>. - <li>The signup server and password server are deprecated in 1.4.2. Their functionality has been incorperated into the self-service server. Edit or reinstall your init script, and set the "signup_server-default_agentnum" and "signup_server-default_refnum" configuration options. The FS::SignupClient interface is still available as a compatibility wrapper, so you should be able to continue to use your current signup.cgi. - <li>Optional: To use typeset invoices, install tetex and ghostscript, and copy conf/invoice_latex, conf/invoice_latexnotes, and conf/invoice_latexfooter to /usr/local/etc/freeside/conf.<datasrc>/ - <li>Restart Apache and freeside-queued. -</body> diff --git a/httemplate/docs/upgrade10.html b/httemplate/docs/upgrade10.html deleted file mode 100644 index 2a4b0d975..000000000 --- a/httemplate/docs/upgrade10.html +++ /dev/null @@ -1,115 +0,0 @@ -<head> - <title>Upgrading to 1.5.8</title> -</head> -<body> -<h1>Upgrading to 1.5.8 from 1.4.1 or 1.4.2</h1 - -<table bgcolor="#dddddd"> -<tr><td> -<i><b>Note:</b> Version numbering has been simplified. 1.5.7 and 1.5.8 are the -versions following 1.5.0pre6. They are still development versions - releases -with odd numbered middle parts (NN in x.NN.x) are development versions, like -Perl or Linux. -</td></tr> -</table> -<br> - -<ul> - <li>If migrating from 1.5.0pre6, see README.1.5.7 instead - <li>If migrating from 1.5.7, see README.1.5.8 instead - <li> install DBD::Pg 1.32, 1.41 or later (not 1.40) (or, if you're using a Perl version before 5.6, you could try installing DBD::Pg 1.22 with <a href="http://420.am/~ivan/DBD-Pg-1.22-fixvercmp.patch">this patch</a> and commenting out the "use DBD::Pg 1.32" at the top of DBIx/DBSchema/DBD/Pg.pm) - <li> install DBIx::DBSchema 0.27 (or later) (if you are running Pg version 7.2.x or earlier, install at least DBIx::DBSchema 0.29) - <li> install Net::SSH 0.08 or later - <li> install HTML::Widgets::SelectLayers 0.05 or later - <li> install Business::CreditCard 0.28 or later - - <li>If using Apache::ASP, add PerlSetVar RequestBinaryRead Off and PerlSetVar IncludesDir /your/freeside/document/root/ to your Apache configuration and make sure you are using Apache::ASP minimum version 2.55. - <ul> - <li>In httpd.conf, change <Files ~ \.cgi> to <Files ~ (\.cgi|\.html)> - <li>In httpd.conf, change <b>AddHandler perl-script .cgi</b> or <b>SetHandler perl-script</b> to <b>AddHandler perl-script .cgi .html</b> - </ul> - <li>install NetAddr::IP, Chart::Base, Locale::SubCountry, Text::CSV_XS, -Spreadsheet::WriteExcel, IO-stringy (IO::Scalar), Frontier::RPC -(Frontier::RPC2), MIME::Entity (MIME-tools), IPC::Run3, Net::Whois::Raw, -JSON, Term::ReadKey and Color::Scheme -<!-- and Crypt::YAPassGen--> - - <li>Apply the following changes to your database: -<pre> -INSERT INTO msgcat ( msgnum, msgcode, locale, msg ) VALUES ( 20, 'svc_external-id', 'en_US', 'External ID' ); -INSERT INTO msgcat ( msgnum, msgcode, locale, msg ) VALUES ( 21, 'svc_external-title', 'en_US', 'Title' ); - -DROP INDEX cust_bill_pkg1; -</pre> - - <li>On recent Pg versions: -<pre> -ALTER TABLE cust_main ALTER COLUMN payinfo varchar(512) NULL; -ALTER TABLE h_cust_main ALTER COLUMN payinfo varchar(512) NULL; -ALTER TABLE cust_pay_batch ADD COLUMN batchnum int NOT NULL; -ALTER TABLE cust_pay_batch ALTER COLUMN batchnum SET NOT NULL; -ALTER TABLE cust_pay_batch ADD COLUMN payinfo varchar(512) NULL; -UPDATE cust_pay_batch SET payinfo = cardnum; -ALTER TABLE cust_pay_batch DROP COLUMN cardnum; -ALTER TABLE h_cust_pay_batch ADD COLUMN payinfo varchar(512) NULL; -UPDATE h_cust_pay_batch SET payinfo = cardnum; -ALTER TABLE h_cust_pay_batch DROP COLUMN cardnum; -</pre> -On older Pg versions that don't support altering columns directly, you will need to dump the database, edit the schema definitions in the dump file, and reload. - - <li>On recent Pg versions: -<pre> -ALTER TABLE svc_forward ALTER COLUMN srcsvc DROP NOT NULL; -ALTER TABLE h_svc_forward ALTER COLUMN srcsvc DROP NOT NULL; -ALTER TABLE svc_forward ALTER COLUMN dstsvc DROP NOT NULL; -ALTER TABLE h_svc_forward ALTER COLUMN dstsvc DROP NOT NULL; -ALTER TABLE cust_main ALTER COLUMN zip DROP NOT NULL; -ALTER TABLE h_cust_main ALTER COLUMN zip DROP NOT NULL; -</pre> -Or on Pg versions that don't support DROP NOT NULL (tested on 7.1 and 7.2 so far): -<pre> -UPDATE pg_attribute SET attnotnull = FALSE WHERE ( attname = 'srcsvc' OR attname = 'dstsvc' ) AND ( attrelid = ( SELECT oid FROM pg_class WHERE relname = 'svc_forward' ) OR attrelid = ( SELECT oid FROM pg_class WHERE relname = 'h_svc_forward' ) ); -UPDATE pg_attribute SET attnotnull = FALSE WHERE ( attname = 'zip' ) AND ( attrelid = ( SELECT oid FROM pg_class WHERE relname = 'cust_main' ) OR attrelid = ( SELECT oid FROM pg_class WHERE relname = 'h_cust_main' ) ); -</pre> - - <li> If you created your database with a version before 1.4.2, dump database, edit the following, then reload: - <ul> - <li>cust_main and h_cust_main: increase otaker from 8 to 32 - <li>cust_main and h_cust_main: change ss from char(11) to varchar(11) ( "character(11)" to "character varying(11)" ) - <li>cust_credit and h_cust_credit: increase otaker from 8 to 32 - <li>cust_pkg and h_cust_pkg: increase otaker from 8 to 32 - <li>cust_refund and h_cust_refund: increase otaker from 8 to 32 - <li>domain_record and h_domain_record: increase reczone from 80 to 255 - <li>domain_record and h_domain_record: change rectype from char to varchar ( "character(5)" to "character varying(5)" ) - <li>domain_record and h_domain_record: increase recdata from 80 to 255 - </ul> - -<li>make install-perl-modules to install the new libraries and CLI utilities -<li>run "freeside-upgrade username" to create the remaining new tables and columns - -<li>optionally: -<pre> -CREATE INDEX cust_main4 ON cust_main ( daytime ); -CREATE INDEX cust_main5 ON cust_main ( night ); -CREATE INDEX cust_main6 ON cust_main ( fax ); -CREATE INDEX cust_main7 ON cust_main ( refnum ); -CREATE INDEX cust_main8 ON cust_main ( county ); -CREATE INDEX cust_main9 ON cust_main ( state ); -CREATE INDEX cust_main10 ON cust_main ( country ); -CREATE INDEX cust_main11 ON cust_main ( ship_last ); -CREATE INDEX cust_main12 ON cust_main ( ship_company ); -CREATE INDEX cust_main13 ON cust_main ( ship_daytime ); -CREATE INDEX cust_main14 ON cust_main ( ship_night ); -CREATE INDEX cust_main15 ON cust_main ( ship_fax ); -CREATE INDEX agent2 ON agent ( disabled ); -CREATE INDEX part_bill_event2 ON part_bill_event ( disabled ); -CREATE INDEX cust_pay4 ON cust_pay (_date); -CREATE INDEX part_referral1 ON part_referral ( disabled ); -CREATE INDEX part_pkg2 ON part_pkg ( promo_code ); -CREATE INDEX h_part_pkg2 ON h_part_pkg ( promo_code ); -</pre> - -</ul> - -</body> -</html> diff --git a/httemplate/docs/upgrade9.html b/httemplate/docs/upgrade9.html deleted file mode 100644 index 6a8fd965d..000000000 --- a/httemplate/docs/upgrade9.html +++ /dev/null @@ -1,28 +0,0 @@ -<head> - <title>Upgrading to 1.4.1</title> -</head> -<body> -<h1>Upgrading to 1.4.1 from 1.4.0</h1> -<ul> - <li>If migrating from less than 1.4.0, see these <a href="upgrade8.html">instructions</a> first. - <li>Back up your data and current Freeside installation. - <li>Run <code>make aspdocs</code> or <code>make masondocs</code>. - <li>Copy <code>aspdocs/</code> or <code>masondocs/</code> to your web server's document space. - <li>Run <code>make install-perl-modules</code>. - <li>Install <a href="http://search.cpan.org/search?dist=Net-SSH">Net::SSH</a> minimum version 0.07 - <li>Apply the following changes to your database: -<pre> -INSERT INTO msgcat ( msgnum, msgcode, locale, msg ) VALUES ( 18, 'daytime', 'en_US', 'Day Phone' ); -INSERT INTO msgcat ( msgnum, msgcode, locale, msg ) VALUES ( 19, 'night', 'en_US', 'Night Phone' ); -</pre> - <li>Optionally, apply the following changes to your database (performance improvements): -<pre> -CREATE INDEX part_pkg1 ON part_pkg ( disabled ); -CREATE INDEX part_svc1 ON part_svc ( disabled ); -CREATE INDEX cust_bill2 ON cust_bill ( _date ); -</pre> - <li>If you want to use ACH (electronic checks), you will need to make changes to your database. The easiest way to make these changes is to dump your database (with pg_dump), change the payinfo field in the cust_pay, cust_refund, h_cust_pay and h_cust_refund tables from varchar(16) to varchar(80), reload the database from the dump. - <li>If you will be doing bind exports you should make additional changes to your database. Follow the directions above to dump the database and change the reczone and recdata fields in the domain_record and h_domain_record tables from varchar(80) to varchar(255). - <li>If you made changes to your db schema from a dump as listed above run dbdef-create. - <li>Restart Apache and freeside-queued. -</body> diff --git a/httemplate/edit/access_group.html b/httemplate/edit/access_group.html index 11b8df7bc..d7f7667f4 100644 --- a/httemplate/edit/access_group.html +++ b/httemplate/edit/access_group.html @@ -5,6 +5,42 @@ 'groupnum' => 'Group number', 'groupname' => 'Group name', }, + 'viewall_dir' => 'browse', + + 'html_bottom' => + sub { + my $access_group = shift; + + "<BR>Group virtualized to customers of agents:<BR>". + ntable("#cccccc",2). + '<TR><TD>'. + include( '/elements/checkboxes-table.html', + 'source_obj' => $access_group, + 'link_table' => 'access_groupagent', + 'target_table' => 'agent', + 'name_col' => 'agent', + 'target_link' => $p.'edit/agent.cgi?', + 'disable-able' => 1, + ). + '</TR></TD></TABLE>'. + + "<BR>Group rights:<BR>". + ntable("#cccccc",2). + '<TR><TD>'. + include( '/elements/checkboxes-table-name.html', + 'source_obj' => $access_group, + 'link_table' => 'access_right', + 'link_static' => { 'righttype' => + 'FS::access_group', + }, + 'num_col' => 'rightobjnum', + 'name_col' => 'rightname', + 'names_list' => [ FS::AccessRight->rights() ], + ). + '</TR></TD></TABLE>' + + ; + }, ) %> diff --git a/httemplate/edit/access_user.html b/httemplate/edit/access_user.html index 2b19dbf7b..fb2a97196 100644 --- a/httemplate/edit/access_user.html +++ b/httemplate/edit/access_user.html @@ -6,6 +6,7 @@ { field=>'_password', type=>'password' }, 'last', 'first', + { field=>'disabled', type=>'checkbox', value=>'Y' }, ], 'labels' => { 'usernum' => 'User number', @@ -13,6 +14,7 @@ '_password' => 'Password', 'last' => 'Last name', 'first' => 'First name', + 'disabled' => 'Disable employee', }, 'viewall_dir' => 'browse', 'html_bottom' => diff --git a/httemplate/edit/cust_credit.cgi b/httemplate/edit/cust_credit.cgi index 946b1087b..8de627d20 100755 --- a/httemplate/edit/cust_credit.cgi +++ b/httemplate/edit/cust_credit.cgi @@ -24,9 +24,7 @@ my $otaker = getotaker; my $p1 = popurl(1); -%> - -<%= header("Post Credit", '') %> +%><%= include('/elements/header-popup.html', 'Enter Credit') %> <% if ( $cgi->param('error') ) { %> <FONT SIZE="+1" COLOR="#ff0000">Error: <%= $cgi->param('error') %></FONT> @@ -74,7 +72,7 @@ Credit </TABLE> <BR> -<CENTER><INPUT TYPE="submit" VALUE="Post credit"></CENTER> +<CENTER><INPUT TYPE="submit" VALUE="Enter credit"></CENTER> </FORM> </BODY> </HTML> diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi index bb2a8618e..c3d1804bc 100755 --- a/httemplate/edit/cust_main.cgi +++ b/httemplate/edit/cust_main.cgi @@ -64,7 +64,11 @@ if ( $cgi->param('error') ) { @invoicing_list = (); } $cgi->delete_all(); + my $action = $custnum ? 'Edit' : 'Add'; +$action .= ": ". $cust_main->name if $custnum; + +my $r = qq!<font color="#ff0000">*</font> !; %> @@ -77,38 +81,29 @@ my $action = $custnum ? 'Edit' : 'Add'; ) %> <% if ( $error ) { %> -<FONT SIZE="+1" COLOR="#ff0000">Error: <%= $error %></FONT> +<FONT SIZE="+1" COLOR="#ff0000">Error: <%= $error %></FONT><BR><BR> <% } %> <FORM NAME="topform" STYLE="margin-bottom: 0"> <INPUT TYPE="hidden" NAME="custnum" VALUE="<%= $custnum %>"> -Customer # <%= $custnum ? "<B>$custnum</B>" : " (NEW)" %> - -<!-- agent --> - -<% +<% if ( $custnum ) { %> + Customer #<B><%= $custnum %></B> - + <B><FONT COLOR="<%= $cust_main->statuscolor %>"> + <%= ucfirst($cust_main->status) %> + </FONT></B> + <BR><BR> +<% } %> -my $r = qq!<font color="#ff0000">*</font> !; +<%= &ntable("#cccccc") %> -my %agent_search = dbdef->table('agent')->column('disabled') - ? ( 'disabled' => '' ) : (); -my @agents = qsearch( 'agent', \%agent_search ); -#die "No agents created!" unless @agents; -eidiot "You have not created any agents (or all agents are disabled). You must create at least one agent before adding a customer. Go to ". popurl(2). "browse/agent.cgi and create one or more agents." unless @agents; -my $agentnum = $cust_main->agentnum || $agents[0]->agentnum; #default to first +<!-- agent --> +<%= include('/elements/tr-select-agent.html', $cust_main->agentnum, + 'label' => "<B>${r}Agent</B>", + 'empty_label' => 'Select agent', + ) %> -<% if ( scalar(@agents) == 1 ) { %> - <INPUT TYPE="hidden" NAME="agentnum" VALUE="<%= $agentnum %>"> -<% } else { %> - <BR><BR><%=$r%>Agent <SELECT NAME="agentnum" SIZE="1"> - <% foreach my $agent (sort { $a->agent cmp $b->agent; } @agents) { %> - <OPTION VALUE="<%= $agent->agentnum %>"<%= " SELECTED"x($agent->agentnum==$agentnum) %>><%= $agent->agent %> - <% } %> - </SELECT> -<% } %> - <!-- referral (advertising source) --> <% @@ -118,28 +113,9 @@ if ( $custnum && ! $conf->exists('editreferrals') ) { <INPUT TYPE="hidden" NAME="refnum" VALUE="<%= $refnum %>"> -<% - } else { - - my(@referrals) = qsearch('part_referral',{}); - if ( scalar(@referrals) == 0 ) { - eidiot "You have not created any advertising sources. You must create at least one advertising source before adding a customer. Go to ". popurl(2). "browse/part_referral.cgi and create one or more advertising sources."; - } elsif ( scalar(@referrals) == 1 ) { - $refnum ||= $referrals[0]->refnum; -%> - - <INPUT TYPE="hidden" NAME="refnum" VALUE="<%= $refnum %>"> - <% } else { %> - <BR><BR><%=$r%>Advertising source - <SELECT NAME="refnum" SIZE="1"> - <%= $refnum ? '' : '<OPTION VALUE="">' %> - <% foreach my $referral (sort { $a->refnum <=> $b->refnum } @referrals) { %> - <OPTION VALUE="<%= $referral->refnum %>" <%= $referral->refnum == $refnum ? 'SELECTED' : '' %>><%= $referral->refnum %>: <%= $referral->referral %> - <% } %> - </SELECT> -<% } %> + <%= include('/elements/tr-select-part_referral.html') %> <% } %> @@ -153,14 +129,26 @@ if ( $cust_main->referral_custnum ) { %> - <BR><BR>Referring Customer: - <A HREF="<%= popurl(1) %>/cust_main.cgi?<%= $cust_main->referral_custnum %>"><%= $cust_main->referral_custnum %>: <%= $referring_cust_main->name %></A> + <TR> + <TD ALIGN="right">Referring customer</TD> + <TD> + <A HREF="<%= popurl(1) %>/cust_main.cgi?<%= $cust_main->referral_custnum %>"><%= $cust_main->referral_custnum %>: <%= $referring_cust_main->name %></A> + </TD> + </TR> <INPUT TYPE="hidden" NAME="referral_custnum" VALUE="<%= $cust_main->referral_custnum %>"> <% } elsif ( ! $conf->exists('disable_customer_referrals') ) { %> - <BR><BR>Referring customer number: - <INPUT TYPE="text" NAME="referral_custnum" VALUE=""> + <TR> + <TD ALIGN="right">Referring customer</TD> + <TD> + <!-- <INPUT TYPE="text" NAME="referral_custnum" VALUE=""> --> + <%= include('/elements/search-cust_main.html', + 'field_name' => 'referral_custnum', + ) + %> + </TD> + </TR> <% } else { %> @@ -168,6 +156,8 @@ if ( $cust_main->referral_custnum <% } %> +</TABLE> + <!-- contact info --> <BR><BR> @@ -377,10 +367,10 @@ unless ( $custnum ) { #false laziness, copied from FS::cust_pkg::order my $pkgpart; + my @agents = $FS::CurrentUser::CurrentUser->agents; if ( scalar(@agents) == 1 ) { # $pkgpart->{PKGPART} is true iff $custnum may purchase PKGPART - my($agent)=qsearchs('agent',{'agentnum'=> $agentnum }); - $pkgpart = $agent->pkgpart_hashref; + $pkgpart = $agents[0]->pkgpart_hashref; } else { #can't know (agent not chosen), so, allow all my %typenum; diff --git a/httemplate/edit/cust_pay.cgi b/httemplate/edit/cust_pay.cgi index a03a245eb..e7734c1fc 100755 --- a/httemplate/edit/cust_pay.cgi +++ b/httemplate/edit/cust_pay.cgi @@ -9,22 +9,20 @@ my %payby = ( 'MCRD' => 'Manual credit card', ); -my($link, $linknum, $paid, $payby, $payinfo, $quickpay, $_date); +my($link, $linknum, $paid, $payby, $payinfo, $_date); if ( $cgi->param('error') ) { $link = $cgi->param('link'); $linknum = $cgi->param('linknum'); $paid = $cgi->param('paid'); $payby = $cgi->param('payby'); $payinfo = $cgi->param('payinfo'); - $quickpay = $cgi->param('quickpay'); $_date = $cgi->param('_date') ? str2time($cgi->param('_date')) : time; } elsif ( $cgi->param('custnum') =~ /^(\d+)$/ ) { - $link = 'custnum'; + $link = $cgi->param('popup') ? 'popup' : 'custnum'; $linknum = $1; $paid = ''; $payby = $cgi->param('payby') || 'BILL'; $payinfo = ''; - $quickpay = $cgi->param('quickpay'); $_date = time; } elsif ( $cgi->param('invnum') =~ /^(\d+)$/ ) { $link = 'invnum'; @@ -32,7 +30,6 @@ if ( $cgi->param('error') ) { $paid = ''; $payby = $cgi->param('payby') || 'BILL'; $payinfo = ""; - $quickpay = ''; $_date = time; } else { die "illegal query ". $cgi->keywords; @@ -43,9 +40,15 @@ my $paybatch = "webui-$_date-$$-". rand() * 2**32; my $title = 'Post '. $payby{$payby}. ' payment'; $title .= " against Invoice #$linknum" if $link eq 'invnum'; -%> +if ( $link eq 'popup' ) { + +%><%= include('/elements/header-popup.html', $title ) %> + +<% } else { %> -<%= include("/elements/header.html",$title, '') %> +<%= include("/elements/header.html", $title, '') %> + +<% } %> <% if ( $cgi->param('error') ) { %> <FONT SIZE="+1" COLOR="#ff0000">Error: <%= $cgi->param('error') %></FONT> @@ -60,7 +63,6 @@ $title .= " against Invoice #$linknum" if $link eq 'invnum'; <FORM ACTION="<%= popurl(1) %>process/cust_pay.cgi" METHOD=POST> <INPUT TYPE="hidden" NAME="link" VALUE="<%= $link %>"> <INPUT TYPE="hidden" NAME="linknum" VALUE="<%= $linknum %>"> -<INPUT TYPE="hidden" NAME="quickpay" VALUE="<%= $quickpay %>"> <% my $money_char = $conf->config('money_char') || '$'; @@ -74,7 +76,9 @@ if ( $link eq 'invnum' ) { } %> +<% unless ( $link eq 'popup' ) { %> <%= small_custview($custnum, $conf->config('countrydefault')) %> +<% } %> <INPUT TYPE="hidden" NAME="payby" VALUE="<%= $payby %>"> diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html index 120c03a3c..c40a00492 100644 --- a/httemplate/edit/elements/edit.html +++ b/httemplate/edit/elements/edit.html @@ -9,13 +9,38 @@ # 'column' => 'Label', # } # - # listref - each item is a literal column name (or method) or (notyet) coderef + # listref - each item is a literal column name (or method) or hashref + # or (notyet) coderef # if not specified all columns (except for the primary key) will be editable # 'fields' => [ + # 'columname', + # { 'field' => 'another_columname', + # 'type' => 'text', #text, fixed, hidden, checkbox + # #eventually more for <SELECT>, etc. + # 'value' => 'Y', #only for checkbox + # }, # ] # # 'menubar' => '', #menubar arrayref # + # #run when re-displaying with an error + # 'error_callback' => sub { my( $cgi, $object ) = @_; }, + # + # #run when editing + # 'edit_callback' => sub { my( $cgi, $object ) = @_; }, + # + # # returns a hashref for the new object + # 'new_hashref_callback' + # + # #run when adding + # 'new_callback' => sub { my( $cgi, $object ) = @_; }, + # + # #XXX describe + # 'field_callback' => sub { }, + # + # #string or coderef of additional HTML to add before </TABLE> + # 'html_table_bottom' => '', + # # 'viewall_dir' => '', #'search' or 'browse', defaults to 'search' # # 'html_bottom' => '', #string @@ -43,15 +68,30 @@ map { $_ => scalar($cgi->param($_)) } fields($table) }); + &{$opt{'error_callback'}}($cgi, $object) + if $opt{'error_callback'}; + } elsif ( $cgi->keywords ) { #editing my( $query ) = $cgi->keywords; $query =~ /^(\d+)$/; $object = qsearchs( $table, { $pkey => $1 } ); + warn "$table $pkey => $1" + if $opt{'debug'}; + + &{$opt{'edit_callback'}}($cgi, $object) + if $opt{'edit_callback'}; } else { #adding - $object = $class->new( {} ); + my $hashref = $opt{'new_hashref_callback'} + ? &{$opt{'new_hashref_callback'}} + : {}; + + $object = $class->new( $hashref ); + + &{$opt{'new_callback'}}($cgi, $object) + if $opt{'new_callback'}; } @@ -91,16 +131,15 @@ <%= ntable("#cccccc",2) %> -<% foreach my $f ( @$fields ) { +<% foreach my $f ( map { ref($_) ? $_ : {'field'=>$_} } + @$fields + ) { + + &{ $opt{'field_callback'} }( $f ) + if $opt{'field_callback'}; - my( $field, $type); - if ( ref($f) ) { - $field = $f->{'field'}, - $type = $f->{'type'} || 'text', - } else { - $field = $f; - $type = 'text'; - } + my $field = $f->{'field'}; + my $type = $f->{'type'} ||= 'text'; %> @@ -113,18 +152,34 @@ %> </TD> - <% - #eventually more options for <SELECT>, etc. fields - %> + <% if ( $type eq 'fixed' ) { %> + + <TD BGCOLOR="#dddddd"><%= $f->{'value'} %></TD> + <INPUT TYPE="hidden" NAME="<%= $field %>" VALUE="<%= $f->{'value'} %>"> + + <% } elsif ( $type eq 'checkbox' ) { %> + + <TD> + <INPUT TYPE="checkbox" NAME="<%= $field %>" VALUE="<%= $f->{'value'} %>" <%= $object->$field() eq $f->{'value'} ? ' CHECKED' : '' %>> + </TD> - <TD> - <INPUT TYPE="<%= $type %>" NAME="<%= $field %>" VALUE="<%= $object->$field() %>"> - <TD> + <% } else { %> + + <TD> + <INPUT TYPE="<%= $type %>" NAME="<%= $field %>" VALUE="<%= $object->$field() %>"> + <TD> + + <% } %> </TR> <% } %> +<%= ref( $opt{'html_table_bottom'} ) + ? &{ $opt{'html_table_bottom'} }( $object ) + : $opt{'html_table_bottom'} +%> + </TABLE> <%= ref( $opt{'html_bottom'} ) diff --git a/httemplate/edit/elements/svc_Common.html b/httemplate/edit/elements/svc_Common.html new file mode 100644 index 000000000..c113ad645 --- /dev/null +++ b/httemplate/edit/elements/svc_Common.html @@ -0,0 +1,98 @@ +<% + + my %opt = @_; + + #my( $svcnum, $pkgnum, $svcpart, $part_svc ); + my( $pkgnum, $svcpart, $part_svc ); + + #get & untaint pkgnum & svcpart + my($query) = $cgi->keywords; #they're not proper cgi params + if ( $query =~ /^pkgnum(\d+)-svcpart(\d+)$/ ) { + $pkgnum = $1; + $svcpart = $2; + $cgi->delete_all(); #so the standard edit.html treats this correctly as new + } + +%><%= include( 'edit.html', + + 'menubar' => [], + + 'error_callback' => sub { + my( $cgi, $svc_x ) = @_; + #$svcnum = $svc_x->svcnum; + $pkgnum = $cgi->param('pkgnum'); + $svcpart = $cgi->param('svcpart'); + + $part_svc = qsearchs( 'part_svc', { svcpart=>$svcpart }); + die "No part_svc entry!" unless $part_svc; + }, + + 'edit_callback' => sub { + my( $cgi, $svc_x ) = @_; + #$svcnum = $svc_x->svcnum; + my $cust_svc = $svc_x->cust_svc + or die "Unknown (cust_svc) svcnum!"; + + $pkgnum = $cust_svc->pkgnum; + $svcpart = $cust_svc->svcpart; + + $part_svc = qsearchs ('part_svc', { svcpart=>$svcpart }); + die "No part_svc entry!" unless $part_svc; + }, + + 'new_hash_callback' => sub { + #my( $cgi, $svc_x ) = @_; + + { svcpart => $svcpart }; + + }, + + 'new_callback' => sub { + my( $cgi, $svc_x ) = @_;; + + $part_svc = qsearchs( 'part_svc', { svcpart=>$svcpart }); + die "No part_svc entry!" unless $part_svc; + + #$svcnum=''; + + $svc_x->set_default_and_fixed; + + }, + + 'field_callback' => sub { + my $f = shift; + my $columndef = $part_svc->part_svc_column($f->{'field'}); + my $flag = $columndef->columnflag; + if ( $flag eq 'F' ) { + $f->{'type'} = 'fixed'; + $f->{'value'} = $columndef->columnvalue; + } + }, + + 'html_table_bottom' => sub { + my $svc_x = shift; + my $html = ''; + foreach my $field ($svc_x->virtual_fields) { + if ($part_svc->part_svc_column($field)->columnflag ne 'F'){ + # If the flag is X, it won't even show up + # in $svc_acct->virtual_fields. + $html .= + $svc_x->pvf($field)->widget( 'HTML', + 'edit', + $svc_x->getfield($field) + ); + } + } + $html; + }, + + 'html_bottom' => sub { + qq!<INPUT TYPE="hidden" NAME="pkgnum" VALUE="$pkgnum">!. + qq!<INPUT TYPE="hidden" NAME="svcpart" VALUE="$svcpart">!; + }, + + 'debug' => 1, + + %opt #pass through/override params + ) +%> diff --git a/httemplate/edit/part_bill_event.cgi b/httemplate/edit/part_bill_event.cgi index 57eedbc71..32a3f2df0 100755 --- a/httemplate/edit/part_bill_event.cgi +++ b/httemplate/edit/part_bill_event.cgi @@ -139,13 +139,21 @@ my $money_char = $conf->config('money_char') || '$'; tie my %events, 'Tie::IxHash', 'fee' => { - 'name' => 'Late fee', + 'name' => 'Late fee (flat)', 'code' => '$cust_main->charge( %%%charge%%%, \'%%%reason%%%\' );', 'html' => 'Amount <INPUT TYPE="text" SIZE="7" NAME="charge" VALUE="%%%charge%%%">'. '<BR>Reason <INPUT TYPE="text" NAME="reason" VALUE="%%%reason%%%">', 'weight' => 10, }, + 'fee_percent' => { + 'name' => 'Late fee (percentage)', + 'code' => '$cust_main->charge( sprintf(\'%.2f\', $cust_bill->owed * %%%percent%%% / 100 ), \'%%%reason%%%\' );', + 'html' => + 'Percent <INPUT TYPE="text" SIZE="2" NAME="percent" VALUE="%%%percent%%%">%'. + '<BR>Reason <INPUT TYPE="text" NAME="reason" VALUE="%%%reason%%%">', + 'weight' => 10, + }, 'suspend' => { 'name' => 'Suspend', 'code' => '$cust_main->suspend();', diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi index 462d5161f..b085d2260 100755 --- a/httemplate/edit/part_pkg.cgi +++ b/httemplate/edit/part_pkg.cgi @@ -237,7 +237,7 @@ if ( dbdef->table('pkg_svc')->column('primary_svc') ) { push @form_radio, 'pkg_svc_primary'; } -tie my %freq, 'Tie::IxHash', %FS::part_pkg::freq; +tie my %freq, 'Tie::IxHash', %{FS::part_pkg->freqs_href()}; if ( $part_pkg->dbdef_table->column('freq')->type =~ /(int)/i ) { delete $freq{$_} foreach grep { ! /^\d+$/ } keys %freq; } diff --git a/httemplate/edit/part_referral.cgi b/httemplate/edit/part_referral.cgi deleted file mode 100755 index dce1e6394..000000000 --- a/httemplate/edit/part_referral.cgi +++ /dev/null @@ -1,44 +0,0 @@ -<% - -my $part_referral; -if ( $cgi->param('error') ) { - $part_referral = new FS::part_referral ( { - map { $_, scalar($cgi->param($_)) } fields('part_referral') - } ); -} elsif ( $cgi->keywords ) { - my($query) = $cgi->keywords; - $query =~ /^(\d+)$/; - $part_referral = qsearchs( 'part_referral', { 'refnum' => $1 } ); -} else { #adding - $part_referral = new FS::part_referral {}; -} -my $action = $part_referral->refnum ? 'Edit' : 'Add'; -my $hashref = $part_referral->hashref; - -my $p1 = popurl(1); - -%><%= include('/elements/header.html', "$action Advertising source", menubar( - 'Main Menu' => popurl(2), - 'View all advertising sources' => popurl(2). "browse/part_referral.cgi", -)) %> - -<% if ( $cgi->param('error') ) { %> - <FONT SIZE="+1" COLOR="#ff0000">Error: <%= $cgi->param('error') %></FONT> -<% } %> - -<FORM ACTION="<%= $p1 %>process/part_referral.cgi" METHOD=POST> - -<INPUT TYPE="hidden" NAME="refnum" VALUE="<%= $hashref->{refnum} %>"> - -<% -#print "Referral #", $hashref->{refnum} ? $hashref->{refnum} : "(NEW)"; -%> - -Advertising source <INPUT TYPE="text" NAME="referral" SIZE=32 VALUE="<%= $hashref->{referral} %>"> - -<BR> -<INPUT TYPE="submit" VALUE="<%= $hashref->{refnum} ? "Apply changes" : "Add advertising source" %>"> - -</FORM> - -<%= include('/elements/footer.html') %> diff --git a/httemplate/edit/part_referral.html b/httemplate/edit/part_referral.html new file mode 100755 index 000000000..ec0f32f58 --- /dev/null +++ b/httemplate/edit/part_referral.html @@ -0,0 +1,9 @@ +<%= include( 'elements/edit.html', + 'name' => 'Advertising source', + 'table' => 'part_referral', + 'fields' => [ 'referral' ], + 'labels' => { 'referral' => 'Advertising source' }, + 'viewall_dir' => 'browse', + 'html_table_bottom' => include('/elements/tr-select-agent.html'), + ) +%> diff --git a/httemplate/edit/part_svc.cgi b/httemplate/edit/part_svc.cgi index c5fff25e0..489a2339c 100755 --- a/httemplate/edit/part_svc.cgi +++ b/httemplate/edit/part_svc.cgi @@ -38,32 +38,30 @@ Service <INPUT TYPE="text" NAME="svc" VALUE="<%= $hashref->{svc} %>"><BR> Disable new orders <INPUT TYPE="checkbox" NAME="disabled" VALUE="Y"<%= $hashref->{disabled} eq 'Y' ? ' CHECKED' : '' %>><BR> <INPUT TYPE="hidden" NAME="svcpart" VALUE="<%= $hashref->{svcpart} %>"> <BR> -Services are items you offer to your customers. -<UL><LI>svc_acct - Shell accounts, POP mailboxes, SLIP/PPP and ISDN accounts +Service definitions are the templates for items you offer to your customers. +<UL><LI>svc_acct - Accounts - anything with a username (Mailboxes, PPP accounts, shell accounts, RADIUS entries for broadband, etc.) <LI>svc_domain - Domains <LI>svc_forward - mail forwarding <LI>svc_www - Virtual domain website - <LI>svc_broadband - Broadband/High-speed Internet service + <LI>svc_broadband - Broadband/High-speed Internet service (always-on) + <LI>svc_phone - Customer phone numbers <LI>svc_external - Externally-tracked service <!-- <LI>svc_charge - One-time charges (Partially unimplemented) <LI>svc_wo - Work orders (Partially unimplemented) --> </UL> For the selected table, you can give fields default or fixed (unchangable) -values. For example, a SLIP/PPP account may have a default (or perhaps fixed) -<B>slipip</B> of <B>0.0.0.0</B>, while a POP mailbox will probably have a fixed -blank <B>slipip</B> as well as a fixed shell something like <B>/bin/true</B> or -<B>/usr/bin/passwd</B>. +values, or select an inventory class to manually or automatically fill in +that field. <BR><BR> <% -my %vfields; - #these might belong somewhere else for other user interfaces #pry need to eventually create stuff that's shared amount UIs my $conf = new FS::Conf; my %defs = ( + 'svc_acct' => { 'dir' => 'Home directory', 'uid' => 'UID (set to fixed and blank for no UIDs)', @@ -77,38 +75,55 @@ my %defs = ( select_label => 'city', }, 'username' => { - desc => 'Username', - type => 'disabled', + desc => 'Username', + type => 'text', + disable_default => 1, + disable_fixed => 1, + }, + 'quota' => { + desc => '', + type => 'text', + disable_inventory => 1, }, - 'quota' => '', '_password' => 'Password', 'gid' => 'GID (when blank, defaults to UID)', 'shell' => { - desc =>'Shell (all service definitions should have a default or fixed shell that is present in the <b>shells</b> configuration file, set to blank for no shell tracking)', + #desc =>'Shell (all service definitions should have a default or fixed shell that is present in the <b>shells</b> configuration file, set to blank for no shell tracking)', + desc =>'Shell ( set to blank for no shell tracking)', type =>'select', select_list => [ $conf->config('shells') ], + disable_inventory => 1, }, - 'finger' => 'GECOS', + 'finger' => 'Real name (GECOS)', 'domsvc' => { desc =>'svcnum from svc_domain', type =>'select', select_table => 'svc_domain', select_key => 'svcnum', select_label => 'domain', + disable_inventory => 1, }, 'usergroup' => { desc =>'RADIUS groups', type =>'radius_usergroup_selector', + disable_inventory => 1, + }, + 'seconds' => { desc => '', + type => 'text', + disable_inventory => 1, }, }, + 'svc_domain' => { 'domain' => 'Domain', }, + 'svc_forward' => { 'srcsvc' => 'service from which mail is to be forwarded', 'dstsvc' => 'service to which mail is to be forwarded', 'dst' => 'someone@another.domain.com to use when dstsvc is 0', }, + # 'svc_charge' => { # 'amount' => 'amount', # }, @@ -116,22 +131,39 @@ my %defs = ( # 'worker' => 'Worker', # '_date' => 'Date', # }, + 'svc_www' => { #'recnum' => '', #'usersvc' => '', }, + 'svc_broadband' => { 'speed_down' => 'Maximum download speed for this service in Kbps. 0 denotes unlimited.', 'speed_up' => 'Maximum upload speed for this service in Kbps. 0 denotes unlimited.', 'ip_addr' => 'IP address. Leave blank for automatic assignment.', 'blocknum' => 'Address block.', }, + + 'svc_phone' => { + 'countrycode' => { desc => 'Country code', + type => 'text', + disable_inventory => 1, + }, + 'phonenum' => 'Phone number', + 'pin' => { desc => 'Personal Identification Number', + type => 'text', + disable_inventory => 1, + }, + }, + 'svc_external' => { #'id' => '', #'title' => '', }, + ); + my %vfields; foreach my $svcdb (grep dbdef->table($_), keys %defs ) { my $self = "FS::$svcdb"->new; $vfields{$svcdb} = {}; @@ -149,10 +181,42 @@ my %defs = ( warn "\$vfields{$svcdb}->{$field} = $pvf"; } #next $field } #next $svcdb + + #code duplication w/ edit/part_svc.cgi, should move this hash to part_svc.pm + # and generalize the subs + # condition sub is tested to see whether to disable display of this choice + # params: ( $def, $layer, $field ) (see SUB below) + my $inv_sub = sub { + ref($_[0]) && ( $_[0]->{disable_inventory} + || $_[0]->{'type'} ne 'text' ) + }; + tie my %flag, 'Tie::IxHash', + '' => { 'desc' => 'No default', }, + 'D' => { 'desc' => 'Default', + 'condition' => + sub { ref($_[0]) && $_[0]->{disable_default} }, + }, + 'F' => { 'desc' => 'Fixed (unchangeable)', + 'condition' => + sub { ref($_[0]) && $_[0]->{disable_fixed} }, + }, +# need to template-ize httemplate/edit/svc_* first +# 'M' => { 'desc' => 'Manual selection from inventory', +# 'condition' => $inv_sub, +# }, + 'A' => { 'desc' => 'Automatically fill in from inventory', + 'condition' => $inv_sub, + }, + 'X' => { 'desc' => 'Excluded', + 'condition' => + sub { ! $vfields{$_[1]}->{$_[2]} }, + + }, + ; my @dbs = $hashref->{svcdb} ? ( $hashref->{svcdb} ) - : qw( svc_acct svc_domain svc_forward svc_www svc_broadband svc_external ); + : qw( svc_acct svc_domain svc_forward svc_www svc_broadband svc_phone svc_external ); tie my %svcdb, 'Tie::IxHash', map { $_=>$_ } grep dbdef->table($_), @dbs; my $widget = new HTML::Widgets::SelectLayers( @@ -174,8 +238,8 @@ my %defs = ( my @part_export = map { qsearch( 'part_export', {exporttype => $_ } ) } keys %{FS::part_export::export_info($layer)}; - $html .= '<BR><BR>'. table(). - table(). "<TR><TH COLSPAN=$columns>Exports</TH></TR><TR>"; + $html .= '<BR><BR>'. table(). + "<TR><TH COLSPAN=$columns>Exports</TH></TR><TR>"; foreach my $part_export ( @part_export ) { $html .= '<TD><INPUT TYPE="checkbox"'. ' NAME="exportnum'. $part_export->exportnum. '" VALUE="1" '; @@ -191,75 +255,176 @@ my %defs = ( } $html .= '</TR></TABLE><BR><BR>'; - $html .= table(). "<TH>Field</TH><TH COLSPAN=2>Modifier</TH>"; + $html .= include('/elements/table-grid.html', 'cellpadding' => 4 ). + '<TR>'. + '<TH CLASS="grid" BGCOLOR="#cccccc">Field</TH>'. + '<TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=2>Modifier</TH>'. + '</TR>'; + + my $bgcolor1 = '#eeeeee'; + my $bgcolor2 = '#ffffff'; + my $bgcolor; + #yucky kludge my @fields = defined( dbdef->table($layer) ) ? grep { $_ ne 'svcnum' } fields($layer) : (); push @fields, 'usergroup' if $layer eq 'svc_acct'; #kludge $part_svc->svcpart($clone) if $clone; #haha, undone below + + foreach my $field (@fields) { + my $part_svc_column = $part_svc->part_svc_column($field); my $value = $part_svc_column->columnvalue; my $flag = $part_svc_column->columnflag; my $def = $defs{$layer}{$field}; my $desc = ref($def) ? $def->{desc} : $def; + + if ( $bgcolor eq $bgcolor1 ) { + $bgcolor = $bgcolor2; + } else { + $bgcolor = $bgcolor1; + } - $html .= "<TR><TD>$field"; + $html .= qq!<TR><TD CLASS="grid" BGCOLOR="$bgcolor" ALIGN="right">!. + $field; $html .= "- <FONT SIZE=-1>$desc</FONT>" if $desc; $html .= "</TD>"; $flag = '' if ref($def) && $def->{type} eq 'disabled'; - $html .= - qq!<TD><INPUT TYPE="radio" NAME="${layer}__${field}_flag" VALUE=""!. - ' CHECKED'x($flag eq ''). ">Off</TD>". - '<TD>'; - unless ( ref($def) && $def->{type} eq 'disabled' ) { - $html .= - qq!<INPUT TYPE="radio" NAME="${layer}__${field}_flag" VALUE="D"!. - ' CHECKED'x($flag eq 'D'). ">Default ". - qq!<INPUT TYPE="radio" NAME="${layer}__${field}_flag" VALUE="F"!. - ' CHECKED'x($flag eq 'F'). ">Fixed "; - $html .= '<BR>'; - } - if ( ref($def) ) { - if ( $def->{type} eq 'select' ) { - $html .= qq!<SELECT NAME="${layer}__${field}">!; - $html .= '<OPTION> </OPTION>' unless $value; - if ( $def->{select_table} ) { - foreach my $record ( qsearch( $def->{select_table}, {} ) ) { - my $rvalue = $record->getfield($def->{select_key}); - $html .= qq!<OPTION VALUE="$rvalue"!. - ( $rvalue==$value ? ' SELECTED>' : '>' ). - $record->getfield($def->{select_label}). '</OPTION>'; - } #next $record - } else { # select_list - foreach my $item ( @{$def->{select_list}} ) { - $html .= qq!<OPTION VALUE="$item"!. - ( $item eq $value ? ' SELECTED>' : '>' ). - $item. '</OPTION>'; - } #next $item - } #endif - $html .= '</SELECT>'; - } elsif ( $def->{type} eq 'radius_usergroup_selector' ) { - $html .= FS::svc_acct::radius_usergroup_selector( - [ split(',', $value) ], "${layer}__${field}" ); - } elsif ( $def->{type} eq 'disabled' ) { - $html .= - qq!<INPUT TYPE="hidden" NAME="${layer}__${field}" VALUE="">!; - } else { - $html .= '<font color="#ff0000">unknown type'. $def->{type}; - } + + $html .= qq!<TD CLASS="grid" BGCOLOR="$bgcolor">!; + + if ( ref($def) && $def->{type} eq 'disabled' ) { + + $html .= 'No default'; + } else { - $html .= - qq!<INPUT TYPE="text" NAME="${layer}__${field}" VALUE="$value">!; + + $html .= qq!<SELECT NAME="${layer}__${field}_flag"!. + qq! onChange="${layer}__${field}_flag_changed(this)">!; + + foreach my $f ( keys %flag ) { + + #here is where the SUB from above is called, to skip some choices + next if $flag{$f}->{condition} + && &{ $flag{$f}->{condition} }( $def, $layer, $field ); + + $html .= qq!<OPTION VALUE="$f"!. + ' SELECTED'x($flag eq $f ). + '>'. $flag{$f}->{desc}; + + } + + $html .= '</SELECT>'; + + $html .= join("\n", + '<SCRIPT>', + " function ${layer}__${field}_flag_changed(what) {", + ' var f = what.options[what.selectedIndex].value;', + ' if ( f == "" || f == "X" ) { //disable', + " what.form.${layer}__${field}.disabled = true;". + " what.form.${layer}__${field}.style.backgroundColor = '#dddddd';". + " if ( what.form.${layer}__${field}_classnum ) {". + " what.form.${layer}__${field}_classnum.disabled = true;". + " what.form.${layer}__${field}_classnum.style.backgroundColor = '#dddddd';". + " }". + ' } else if ( f == "D" || f == "F" ) { //enable, text box', + " what.form.${layer}__${field}.disabled = false;". + " what.form.${layer}__${field}.style.backgroundColor = '#ffffff';". + " what.form.${layer}__${field}.style.display = '';". + " if ( what.form.${layer}__${field}_classnum ) {". + " what.form.${layer}__${field}_classnum.disabled = false;". + " what.form.${layer}__${field}_classnum.style.backgroundColor = '#ffffff';". + " what.form.${layer}__${field}_classnum.style.display = 'none';". + " }". + ' } else if ( f == "M" || f == "A" ) { //enable, inventory', + " what.form.${layer}__${field}.disabled = false;". + " what.form.${layer}__${field}.style.backgroundColor = '#ffffff';". + " what.form.${layer}__${field}.style.display = 'none';". + " if ( what.form.${layer}__${field}_classnum ) {". + " what.form.${layer}__${field}_classnum.disabled = false;". + " what.form.${layer}__${field}_classnum.style.backgroundColor = '#ffffff';". + " what.form.${layer}__${field}_classnum.style.display = '';". + " }". + ' }', + ' }', + '</SCRIPT>', + ); + } - if($vfields{$layer}->{$field}) { - $html .= qq!<BR><INPUT TYPE="radio" NAME="${layer}__${field}_flag" VALUE="X"!. - ' CHECKED'x($flag eq 'X'). ">Excluded "; + $html .= qq!</TD><TD CLASS="grid" BGCOLOR="$bgcolor">!; + + my $disabled = $flag ? '' + : 'DISABLED STYLE="background-color: #dddddd"'; + + if ( ! ref($def) || $def->{type} eq 'text' ) { + + my $nodisplay = ' STYLE="display:none"'; + my $is_inv = ( $flag =~ /^[MA]$/ ); + + $html .= + qq!<INPUT TYPE="text" NAME="${layer}__${field}" VALUE="$value" !. + $disabled. + ( $is_inv ? $nodisplay : $disabled ). + '>'; + + $html .= include('/elements/select-table.html', + 'element_name' => "${layer}__${field}_classnum", + 'element_etc' => ( $is_inv + ? $disabled + : $nodisplay + ), + 'table' => 'inventory_class', + 'name_col' => 'classname', + 'value' => $value, + 'empty_label' => 'Select inventory class', + ); + + } elsif ( $def->{type} eq 'select' ) { + + $html .= qq!<SELECT NAME="${layer}__${field}" $disabled>!; + $html .= '<OPTION> </OPTION>' unless $value; + if ( $def->{select_table} ) { + foreach my $record ( qsearch( $def->{select_table}, {} ) ) { + my $rvalue = $record->getfield($def->{select_key}); + $html .= qq!<OPTION VALUE="$rvalue"!. + ( $rvalue==$value ? ' SELECTED>' : '>' ). + $record->getfield($def->{select_label}). '</OPTION>'; + } #next $record + } else { # select_list + foreach my $item ( @{$def->{select_list}} ) { + $html .= qq!<OPTION VALUE="$item"!. + ( $item eq $value ? ' SELECTED>' : '>' ). + $item. '</OPTION>'; + } #next $item + } #endif + $html .= '</SELECT>'; + + } elsif ( $def->{type} eq 'radius_usergroup_selector' ) { + + #XXX disable the RADIUS usergroup selector? ugh it sure does need + #an overhaul, people have dum group problems because of it + + $html .= FS::svc_acct::radius_usergroup_selector( + [ split(',', $value) ], "${layer}__${field}" ); + + } elsif ( $def->{type} eq 'disabled' ) { + + $html .= + qq!<INPUT TYPE="hidden" NAME="${layer}__${field}" VALUE="">!; + + } else { + + $html .= '<font color="#ff0000">unknown type'. $def->{type}; + } + $html .= "</TD></TR>\n"; - } + + } #foreach my $field (@fields) { + $part_svc->svcpart('') if $clone; #undone $html .= "</TABLE>"; diff --git a/httemplate/edit/process/access_group.html b/httemplate/edit/process/access_group.html index e8c6d07b1..9bb9d1dda 100644 --- a/httemplate/edit/process/access_group.html +++ b/httemplate/edit/process/access_group.html @@ -1,5 +1,15 @@ <%= include( 'elements/process.html', 'table' => 'access_group', 'viewall_dir' => 'browse', + 'process_m2m' => { 'link_table' => 'access_groupagent', + 'target_table' => 'agent', + }, + 'process_m2name' => { + 'link_table' => 'access_right', + 'link_static' => { 'righttype' => 'FS::access_group', }, + 'num_col' => 'rightobjnum', + 'name_col' => 'rightname', + 'names_list' => [ FS::AccessRight->rights() ], + }, ) %> diff --git a/httemplate/edit/process/cust_main.cgi b/httemplate/edit/process/cust_main.cgi index 09a42544c..4ba30c435 100755 --- a/httemplate/edit/process/cust_main.cgi +++ b/httemplate/edit/process/cust_main.cgi @@ -103,8 +103,6 @@ if ( $new->custnum eq '' ) { 'popnum' => $cgi->param('popnum'), } ); - my $y = $svc_acct->setdefault; # arguably should be in new method - $error ||= $y unless ref($y); #and just in case you were silly $svc_acct->svcpart($svcpart); $svc_acct->username($cgi->param('username')); diff --git a/httemplate/edit/process/cust_pay.cgi b/httemplate/edit/process/cust_pay.cgi index 87d6011e7..cecccb59e 100755 --- a/httemplate/edit/process/cust_pay.cgi +++ b/httemplate/edit/process/cust_pay.cgi @@ -4,15 +4,16 @@ $cgi->param('linknum') =~ /^(\d+)$/ or die "Illegal linknum: ". $cgi->param('linknum'); my $linknum = $1; -$cgi->param('link') =~ /^(custnum|invnum)$/ +$cgi->param('link') =~ /^(custnum|invnum|popup)$/ or die "Illegal link: ". $cgi->param('link'); -my $link = $1; +my $field = my $link = $1; +$field = 'custnum' if $field eq 'popup'; my $_date = str2time($cgi->param('_date')); my $new = new FS::cust_pay ( { - $link => $linknum, - _date => $_date, + $field => $linknum, + _date => $_date, map { $_, scalar($cgi->param($_)); } qw(paid payby payinfo paybatch) @@ -24,19 +25,30 @@ my $error = $new->insert; if ($error) { $cgi->param('error', $error); print $cgi->redirect(popurl(2). 'cust_pay.cgi?'. $cgi->query_string ); -} elsif ( $link eq 'invnum' ) { +} elsif ( $field eq 'invnum' ) { print $cgi->redirect(popurl(3). "view/cust_bill.cgi?$linknum"); -} elsif ( $link eq 'custnum' ) { +} elsif ( $field eq 'custnum' ) { if ( $cgi->param('apply') eq 'yes' ) { my $cust_main = qsearchs('cust_main', { 'custnum' => $linknum }) or die "unknown custnum $linknum"; $cust_main->apply_payments; } - if ( $cgi->param('quickpay') eq 'yes' ) { - print $cgi->redirect(popurl(3). "search/cust_main-quickpay.html"); - } else { + if ( $link eq 'popup' ) { + + %><%= header('Payment entered') %> + <SCRIPT TYPE="text/javascript"> + window.top.location.reload(); + </SCRIPT> + + </BODY></HTML> + <% + + } elsif ( $link eq 'custnum' ) { print $cgi->redirect(popurl(3). "view/cust_main.cgi?$linknum"); + } else { + die "unknown link $link"; } + } %> diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html index 59ad35ee4..7cae78bfc 100644 --- a/httemplate/edit/process/elements/process.html +++ b/httemplate/edit/process/elements/process.html @@ -5,6 +5,7 @@ ### ##req ## + # # 'table' => # # #? 'primary_key' => #required when the dbdef doesn't know...??? @@ -13,10 +14,24 @@ ### ##opt ### + # # 'viewall_dir' => '', #'search' or 'browse', defaults to 'search' + # OR + # 'redirect' => 'view/table.cgi?', # value of primary key is appended + # + # 'edit_ext' => 'html', #defaults to 'html', you might want 'cgi' while the + # #naming is still inconsistent + # # 'process_m2m' => { 'link_table' => 'link_table_name', # 'target_table' => 'target_table_name', - # }. + # }, + # 'process_m2name' => { 'link_table' => 'link_table_name', + # 'link_static' => { 'column' => 'value' }, + # 'num_col' => 'column', #if column name is different in + # #link_table than source_table + # 'name_col' => 'name_column', + # 'names_list' => [ 'list', 'names' ], + # }, my(%opt) = @_; @@ -52,9 +67,20 @@ ); } + if ( !$error && $opt{'process_m2name'} ) { + $error = $new->process_m2name( %{ $opt{'process_m2name'} }, + 'params' => scalar($cgi->Vars), + ); + } + + # XXX print?!?! + if ( $error ) { $cgi->param('error', $error); - print $cgi->redirect(popurl(2). "$table.html?". $cgi->query_string ); + my $edit_ext = $opt{'edit_ext'} || 'html'; + print $cgi->redirect(popurl(2). "$table.$edit_ext?". $cgi->query_string ); + } elsif ( $opt{'redirect'} ) { + print $cgi->redirect( $opt{'redirect'}. $pkeyvalue ); } else { print $cgi->redirect( popurl(3). ( $opt{'viewall_dir'} || 'search' ). diff --git a/httemplate/edit/process/elements/svc_Common.html b/httemplate/edit/process/elements/svc_Common.html new file mode 100644 index 000000000..1f8f8315e --- /dev/null +++ b/httemplate/edit/process/elements/svc_Common.html @@ -0,0 +1,14 @@ +<% + + my %opt = @_; + my $table = $opt{'table'}; + $opt{'fields'} ||= [ fields($table) ]; + push @{ $opt{'fields'} }, qw( pkgnum svcpart ); + +%><%= include( 'process.html', + 'edit_ext' => 'cgi', + 'redirect' => popurl(3)."view/$table.cgi?", + %opt, + ) +%> + diff --git a/httemplate/edit/process/part_referral.cgi b/httemplate/edit/process/part_referral.cgi deleted file mode 100755 index fd2c01506..000000000 --- a/httemplate/edit/process/part_referral.cgi +++ /dev/null @@ -1,28 +0,0 @@ -<% - -my $refnum = $cgi->param('refnum'); - -my $new = new FS::part_referral ( { - map { - $_, scalar($cgi->param($_)); - } fields('part_referral') -} ); - -my $error; -if ( $refnum ) { - my $old = qsearchs( 'part_referral', { 'refnum' =>$ refnum } ); - die "(Old) Record not found!" unless $old; - $error = $new->replace($old); -} else { - $error = $new->insert; -} -$refnum=$new->refnum; - -if ( $error ) { - $cgi->param('error', $error); - print $cgi->redirect(popurl(2). "part_referral.cgi?". $cgi->query_string ); -} else { - print $cgi->redirect(popurl(3). "browse/part_referral.cgi"); -} - -%> diff --git a/httemplate/edit/process/part_referral.html b/httemplate/edit/process/part_referral.html new file mode 100755 index 000000000..0b5d959a0 --- /dev/null +++ b/httemplate/edit/process/part_referral.html @@ -0,0 +1,5 @@ +<%= include( 'elements/process.html', + 'table' => 'part_referral', + 'viewall_dir' => 'browse', + ) +%> diff --git a/httemplate/edit/process/svc_phone.html b/httemplate/edit/process/svc_phone.html new file mode 100644 index 000000000..c1d4b7547 --- /dev/null +++ b/httemplate/edit/process/svc_phone.html @@ -0,0 +1,4 @@ +<%= include( 'elements/svc_Common.html', + 'table' => 'svc_phone', + ) +%> diff --git a/httemplate/edit/svc_acct.cgi b/httemplate/edit/svc_acct.cgi index 1e87c67ad..71b324d99 100755 --- a/httemplate/edit/svc_acct.cgi +++ b/httemplate/edit/svc_acct.cgi @@ -68,18 +68,22 @@ unless ( $svcnum || $cgi->param('error') ) { #adding } } - #set fixed and default fields from part_svc - foreach my $part_svc_column ( - grep { $_->columnflag } $part_svc->all_part_svc_column - ) { - if ( $part_svc_column->columnname eq 'usergroup' ) { - @groups = split(',', $part_svc_column->columnvalue); - } else { - $svc_acct->setfield( $part_svc_column->columnname, - $part_svc_column->columnvalue, - ); - } - } + $svc_acct->set_default_and_fixed( { + #false laziness w/svc-acct::_fieldhandlers + 'usergroup' => sub { + my( $self, $groups ) = @_; + if ( ref($groups) eq 'ARRAY' ) { + @groups = @$groups; + $groups; + } elsif ( length($groups) ) { + @groups = split(/\s*,\s*/, $groups); + [ @groups ]; + } else { + @groups = (); + []; + } + } + } ); } @@ -274,7 +278,7 @@ if ( $part_svc->part_svc_column('popnum')->columnflag eq 'F' ) { <% foreach my $xid (qw( uid gid )) { %> <% - if ( $part_svc->part_svc_column($xid)->columnflag eq 'F' + if ( $part_svc->part_svc_column($xid)->columnflag =~ /^[FA]$/ || ! $conf->exists("svc_acct-edit_$xid") ) { %> @@ -376,7 +380,7 @@ if ( $part_svc->part_svc_column('shell')->columnflag eq 'F' <% } %> -<% if ( $part_svc->part_svc_column('slipip')->columnflag eq 'F' ) { %> +<% if ( $part_svc->part_svc_column('slipip')->columnflag =~ /^[FA]$/ ) { %> <INPUT TYPE="hidden" NAME="slipip" VALUE="<%= $svc_acct->slipip %>"> @@ -396,7 +400,7 @@ foreach my $r ( grep { /^r(adius|[cr])_/ } fields('svc_acct') ) { my $a = $2; %> - <% if ( $part_svc->part_svc_column($r)->columnflag eq 'F' ) { %> + <% if ( $part_svc->part_svc_column($r)->columnflag =~ /^[FA]$/ ) { %> <INPUT TYPE="hidden" NAME="<%= $r %>" VALUE="<%= $svc_acct->getfield($r) %>"> diff --git a/httemplate/edit/svc_broadband.cgi b/httemplate/edit/svc_broadband.cgi index cbd0c2c3a..d66cff690 100644 --- a/httemplate/edit/svc_broadband.cgi +++ b/httemplate/edit/svc_broadband.cgi @@ -47,14 +47,7 @@ if ( $cgi->param('error') ) { $svcnum=''; - #set fixed and default fields from part_svc - foreach my $part_svc_column ( - grep { $_->columnflag } $part_svc->all_part_svc_column - ) { - $svc_broadband->setfield( $part_svc_column->columnname, - $part_svc_column->columnvalue, - ); - } + $svc_broadband->set_default_and_fixed; } } diff --git a/httemplate/edit/svc_domain.cgi b/httemplate/edit/svc_domain.cgi index f47ba0a8f..1156bf0ba 100755 --- a/httemplate/edit/svc_domain.cgi +++ b/httemplate/edit/svc_domain.cgi @@ -44,14 +44,7 @@ if ( $cgi->param('error') ) { $svcnum=''; - #set fixed and default fields from part_svc - foreach my $part_svc_column ( - grep { $_->columnflag } $part_svc->all_part_svc_column - ) { - $svc_domain->setfield( $part_svc_column->columnname, - $part_svc_column->columnvalue, - ); - } + $svc_domain->set_default_and_fixed; } diff --git a/httemplate/edit/svc_external.cgi b/httemplate/edit/svc_external.cgi index bcfc85e3f..38b3ce1a4 100644 --- a/httemplate/edit/svc_external.cgi +++ b/httemplate/edit/svc_external.cgi @@ -40,14 +40,7 @@ if ( $cgi->param('error') ) { $svcnum=''; - #set fixed and default fields from part_svc - foreach my $part_svc_column ( - grep { $_->columnflag } $part_svc->all_part_svc_column - ) { - $svc_external->setfield( $part_svc_column->columnname, - $part_svc_column->columnvalue, - ); - } + $svc_external->set_default_and_fixed; } } diff --git a/httemplate/edit/svc_forward.cgi b/httemplate/edit/svc_forward.cgi index c1b90a9bd..c32fbd7c1 100755 --- a/httemplate/edit/svc_forward.cgi +++ b/httemplate/edit/svc_forward.cgi @@ -44,14 +44,7 @@ if ( $cgi->param('error') ) { $svcnum=''; - #set fixed and default fields from part_svc - foreach my $part_svc_column ( - grep { $_->columnflag } $part_svc->all_part_svc_column - ) { - $svc_forward->setfield( $part_svc_column->columnname, - $part_svc_column->columnvalue, - ); - } + $svc_forward->set_default_and_fixed; } } diff --git a/httemplate/edit/svc_phone.cgi b/httemplate/edit/svc_phone.cgi new file mode 100644 index 000000000..77b4975a1 --- /dev/null +++ b/httemplate/edit/svc_phone.cgi @@ -0,0 +1,11 @@ +<%= include( 'elements/svc_Common.html', + 'name' => 'Phone number', + 'table' => 'svc_phone', + 'fields' => [qw( countrycode phonenum )], #pin + 'labels' => { + 'countrycode' => 'Country code', + 'phonenum' => 'Phone number', + 'pin' => 'PIN', + }, + ) +%> diff --git a/httemplate/edit/svc_www.cgi b/httemplate/edit/svc_www.cgi index 3cb752850..280346bb4 100644 --- a/httemplate/edit/svc_www.cgi +++ b/httemplate/edit/svc_www.cgi @@ -42,14 +42,7 @@ if ( $cgi->param('error') ) { $svcnum=''; - #set fixed and default fields from part_svc - foreach my $part_svc_column ( - grep { $_->columnflag } $part_svc->all_part_svc_column - ) { - $svc_www->setfield( $part_svc_column->columnname, - $part_svc_column->columnvalue, - ); - } + $svc_www->set_default_and_fixed; } } diff --git a/httemplate/elements/checkboxes-table-name.html b/httemplate/elements/checkboxes-table-name.html new file mode 100644 index 000000000..8e9dd29d2 --- /dev/null +++ b/httemplate/elements/checkboxes-table-name.html @@ -0,0 +1,85 @@ +<% + + ## + # required + ## + # 'link_table' => 'table_name', + # + # 'name_col' => 'name_column', + # #or + # 'name_callback' => sub { }, + # + # 'names_list' => [ 'value', 'other value' ], + # + ## + # recommended (required?) + ## + # 'source_obj' => $obj, + # #or? + # #'source_table' => 'table_name', + # #'sourcenum' => '4', #current value of primary key in source_table + # # # (none is okay, just pass it if you have it) + ## + # optional + ## + # 'num_col' => 'col_name' #if column name is different in link_table than + # #source_table + # 'link_static' => { 'column' => 'value' }, + + my( %opt ) = @_; + + my( $source_pkey, $sourcenum, $source_obj ); + if ( $opt{'source_obj'} ) { + + $source_obj = $opt{'source_obj'}; + #$source_table = $source_obj->dbdef_table->table; + $source_pkey = $source_obj->dbdef_table->primary_key; + $sourcenum = $source_obj->$source_pkey(); + + } else { + + #$source_obj? + $source_pkey = $opt{'source_table'} + ? dbdef->table($opt{'source_table'})->primary_key + : ''; + $sourcenum = $opt{'sourcenum'}; + } + + $source_pkey = $opt{'num_col'} || $source_pkey; + + my $link_static = $opt{'link_static'} || {}; + +%> + +<% foreach my $name ( @{ $opt{'names_list'} } ) { + + my $checked; + if ( $cgi->param('error') ) { + + $checked = $cgi->param($opt{'link_table'}. ".$name" ) + ? 'CHECKED' + : ''; + + } else { + + $checked = + qsearchs( $opt{'link_table'}, { + $source_pkey => $sourcenum, + $opt{'name_col'} => $name, + %$link_static, + } ) + ? 'CHECKED' + : '' + + } + +%> + + <INPUT TYPE="checkbox" NAME="<%= $opt{'link_table'}. ".$name" %>" <%= $checked %> VALUE="ON"> + + <%= $name %> + + <BR> + +<% } %> + diff --git a/httemplate/elements/checkboxes-table.html b/httemplate/elements/checkboxes-table.html index d26ebef35..16376fa3d 100644 --- a/httemplate/elements/checkboxes-table.html +++ b/httemplate/elements/checkboxes-table.html @@ -68,16 +68,28 @@ ) { my $targetnum = $target_obj->$target_pkey(); + + my $checked; + if ( $cgi->param('error') ) { + + $checked = $cgi->param($target_pkey.$targetnum) + ? 'CHECKED' + : ''; + + } else { + + $checked = qsearchs( $opt{'link_table'}, { + $source_pkey => $sourcenum, + $target_pkey => $targetnum, + } ) + ? 'CHECKED' + : '' + + } + %> - <INPUT TYPE="checkbox" NAME="<%= $target_pkey. $targetnum %>" <%= - qsearchs( $opt{'link_table'}, { - $source_pkey => $sourcenum, - $target_pkey => $targetnum, - }) - ? 'CHECKED ' - : '' - %> VALUE="ON"> + <INPUT TYPE="checkbox" NAME="<%= $target_pkey. $targetnum %>" <%= $checked %> VALUE="ON"> <% if ( $opt{'target_link'} ) { %> diff --git a/httemplate/elements/header-popup.html b/httemplate/elements/header-popup.html new file mode 100644 index 000000000..73377abfe --- /dev/null +++ b/httemplate/elements/header-popup.html @@ -0,0 +1,22 @@ +<% + my($title, $menubar) = ( shift, shift ); #$menubar is unused here though + my $etc = @_ ? shift : ''; #$etc is for things like onLoad= etc. + my $head = @_ ? shift : ''; #$head is for things that go in the <HEAD> section + my $conf = new FS::Conf; +%> +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> +<HTML> + <HEAD> + <TITLE> + <%= $title %> + </TITLE> + <META HTTP-Equiv="Cache-Control" Content="no-cache"> + <META HTTP-Equiv="Pragma" Content="no-cache"> + <META HTTP-Equiv="Expires" Content="0"> + <%= $head %> + </HEAD> + <BODY BGCOLOR="#e8e8e8" <%= $etc %>> + <FONT SIZE=6> + <CENTER><%= $title %></CENTER> + </FONT> + <BR><!--<BR>--> diff --git a/httemplate/elements/header.html b/httemplate/elements/header.html index 3aa81be3b..ea8c418c3 100644 --- a/httemplate/elements/header.html +++ b/httemplate/elements/header.html @@ -3,6 +3,7 @@ my $etc = @_ ? shift : ''; #$etc is for things like onLoad= etc. my $head = @_ ? shift : ''; #$head is for things that go in the <HEAD> section my $conf = new FS::Conf; + %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <HTML> @@ -18,17 +19,22 @@ <SCRIPT TYPE="text/javascript"> function clearhint_search_cust (what) { - if ( what.value = '(cust #, name or company)' ) + if ( what.value == '(cust #, name, company or phone)' ) + what.value = ''; + } + + function clearhint_search_invoice (what) { + if ( what.value == '(inv #)' ) what.value = ''; } function clearhint_search_svc (what) { - if ( what.value = '(user, user@domain or domain)' ) + if ( what.value == '(user, user@domain or domain)' ) what.value = ''; } function clearhint_search_ticket (what) { - if ( what.value = '(ticket # or subject string)' ) + if ( what.value == '(ticket # or subject string)' ) what.value = ''; } </SCRIPT> @@ -39,13 +45,11 @@ <BODY BACKGROUND="<%=$fsurl%>images/background-cheat.png" <%= $etc %> STYLE="margin-top:0; margin-bottom:0; margin-left:0; margin-right:0"> <table width="100%" CELLPADDING=0 CELLSPACING=0 STYLE="padding-left:0; padding-right:4"> <tr> - <td rowspan=2 BGCOLOR="#ffffff"> - <IMG BORDER=0 ALT="freeside" SRC="<%=$fsurl%>images/small-logo.png"> - </td> + <td rowspan=2 BGCOLOR="#ffffff"><IMG BORDER=0 ALT="freeside" SRC="<%=$fsurl%>images/small-logo.png"></td> <td align=left rowspan=2 BGCOLOR="#ffffff"> <!-- valign="top" --> <font size=6><%= $conf->config('company_name') || 'ExampleCo' %></font> </td> - <td align=right valign=top BGCOLOR="#ffffff">Logged in as <b><%= getotaker %> </b><br><FONT SIZE="-2"><a href="<%=$fsurl%>pref/XXXwritethis">Preferences</a> <BR><BR></FONT> + <td align=right valign=top BGCOLOR="#ffffff"><FONT SIZE="-1">Logged in as <b><%= getotaker %> </b><br></FONT><FONT SIZE="-2"><a href="<%=$fsurl%>pref/XXXwritethis">Preferences</a> <BR></FONT> </td> </tr> <tr> @@ -77,34 +81,88 @@ </tr> </table> - <TABLE WIDTH="100%" CELLSPACING=0 CELLPADDING=4> +<style type="text/css"> +input.fsblackbutton { + background-color:#333333; + color: #ffffff; + border:1px solid; + border-top-color:#cccccc; + border-left-color:#cccccc; + border-right-color:#aaaaaa; + border-bottom-color:#aaaaaa; + font-weight:bold; + padding-left:12px; + padding-right:12px; + overflow:visible; + filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff333333',EndColorStr='#ff666666') +} + +input.fsblackbuttonselected { + background-color:#7e0079; + color: #ffffff; + border:1px solid; + border-top-color:#cccccc; + border-left-color:#cccccc; + border-right-color:#aaaaaa; + border-bottom-color:#aaaaaa; + font-weight:bold; + padding-left:12px; + padding-right:12px; + overflow:visible; + filter:progid:DXImageTransform.Microsoft.Gradient(GradientType=0,StartColorStr='#ff330033',EndColorStr='#ff7e0079') +} +</style> + + <TABLE WIDTH="100%" CELLSPACING=0 CELLPADDING=0> <TR> - <TD COLSPAN=4 WIDTH="100%" STYLE="padding:0"><IMG BORDER=0 ALT="" SRC="<%=$fsurl%>images/black-gradient.png" HEIGHT="13" WIDTH="100%"></TD> + <TD COLSPAN=5 WIDTH="100%" STYLE="padding:0"><IMG BORDER=0 ALT="" SRC="<%=$fsurl%>images/black-gradient.png" HEIGHT="13" WIDTH="100%"></TD> </TR> + <TR> - <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right" WIDTH="15%"> + + <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right"> <FORM ACTION="<%=$fsurl%>edit/cust_main.cgi" METHOD="GET" STYLE="margin:0"> - <INPUT TYPE="submit" VALUE="New customer"> + <INPUT TYPE="submit" VALUE="New customer" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="vertical-align:bottom"> </FORM> </TD> + <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right"> <FORM ACTION="<%=$fsurl%>search/cust_main.cgi" METHOD="GET" STYLE="margin:0"> - <INPUT NAME="search_cust" TYPE="text" VALUE="(cust #, name or company)" SIZE="22" onFocus="clearhint_search_cust(this);" onClick="clearhint_search_cust(this);" STYLE="text-align:right"> - <INPUT TYPE="submit" VALUE="Search customers"> + <INPUT NAME="search_cust" TYPE="text" VALUE="(cust #, name, company or phone)" SIZE="28" onFocus="clearhint_search_cust(this);" onClick="clearhint_search_cust(this);" STYLE="vertical-align:bottom;text-align:right"><BR> + <A HREF="<%=$fsurl%>search/cust_main.html" STYLE="color: #000000; font-size: 70%">Advanced</A> + <INPUT TYPE="submit" VALUE="Search customers" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%"> </FORM> </TD> + + <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right"> + <% if ( $FS::CurrentUser::CurrentUser->access_right('View invoices') ) { %> + <FORM ACTION="<%=$fsurl%>search/cust_bill.html" METHOD="GET" STYLE="margin:0;display:inline"> + <INPUT NAME="invnum" TYPE="text" VALUE="(inv #)" SIZE="4" onFocus="clearhint_search_invoice(this);" onClick="clearhint_search_invoice(this);" STYLE="vertical-align:bottom;text-align:right;margin-bottom:1px"> + <% if ( $FS::CurrentUser::CurrentUser->access_right('List invoices') ) { %> + <A HREF="<%=$fsurl%>search/report_cust_bill.html" STYLE="color: #ffffff; font-size: 70%">Advanced</A> + <% } %> + <BR> + <INPUT TYPE="submit" VALUE="Search invoices" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%"> + </FORM> + <% } %> + </TD> + <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right"> <FORM ACTION="<%=$fsurl%>search/svc_Smart.html" METHOD="GET" STYLE="margin:0"> - <INPUT NAME="search_svc" TYPE="text" VALUE="(user, user@domain or domain)" SIZE="26" onFocus="clearhint_search_svc(this);" onClick="clearhint_search_svc(this);" STYLE="text-align:right"> - <INPUT TYPE="submit" VALUE="Search services"> + <INPUT NAME="search_svc" TYPE="text" VALUE="(user, user@domain or domain)" SIZE="26" onFocus="clearhint_search_svc(this);" onClick="clearhint_search_svc(this);" STYLE="vertical-align:bottom;text-align:right"><BR> + <A HREF="<%=$fsurl%>search/svc_Smarter.html" STYLE="color: #000000; font-size: 70%">Advanced</A> + <INPUT TYPE="submit" VALUE="Search services"CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%"> </FORM> </TD> - <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right"> + + <TD COLSPAN=1 BGCOLOR="#000000" ALIGN="right" STYLE="padding-right:4px"> <FORM ACTION="<%=$fsurl%>rt/index.html" METHOD="GET" STYLE="margin:0"> - <INPUT NAME="q" TYPE="text" VALUE="(ticket # or subject string)" onFocus="clearhint_search_ticket(this);" onClick="clearhint_search_ticket(this);" STYLE="text-align:right"> - <INPUT TYPE="submit" VALUE="Search tickets"> + <INPUT NAME="q" TYPE="text" VALUE="(ticket # or subject string)" onFocus="clearhint_search_ticket(this);" onClick="clearhint_search_ticket(this);" STYLE="vertical-align:bottom;text-align:right"><BR> + <A HREF="<%=$fsurl%>rt/Search/Build.html" STYLE="color: #ffffff; font-size: 70%">Advanced</A> + <INPUT TYPE="submit" VALUE="Search tickets" CLASS="fsblackbutton" onMouseOver="this.className='fsblackbuttonselected'; return true;" onMouseOut="this.className='fsblackbutton'; return true;" STYLE="font-size:70%;padding-left:2px;padding-right:2px"> </FORM> </TD> + </TR> </TABLE> <TABLE WIDTH="100%" HEIGHT="100%" CELLSPACING=0 CELLPADDING=4> diff --git a/httemplate/elements/iframecontentmws.js b/httemplate/elements/iframecontentmws.js new file mode 100644 index 000000000..c80998957 --- /dev/null +++ b/httemplate/elements/iframecontentmws.js @@ -0,0 +1,20 @@ +/*
+ iframecontentmws.js - Foteos Macrides
+ Initial: October 10, 2004 - Last Revised: May 9, 2005
+ Simple script for using an HTML file as iframe content in overlibmws popups.
+ Include WRAP and TEXTPADDING,0 in the overlib call to ensure that the width
+ arg is respected (unless the CAPTION plus CLOSETEXT widths add up to more than
+ the width arg, in which case you should increase the width arg). The name arg
+ should be a unique string for each popup with iframe content in the document.
+ The frameborder arg should be 1 (browser default if omitted) or 0.
+
+ See http://www.macridesweb.com/oltest/IFRAME.html for demonstration.
+*/
+
+function OLiframeContent(src, width, height, name, frameborder) {
+ return ('<iframe src="'+src+'" width="'+width+'" height="'+height+'"'
+ +(name!=null?' name="'+name+'" id="'+name+'"':'')
+ +(frameborder!=null?' frameborder="'+frameborder+'"':'')
+ +' scrolling="auto">'
+ +'<div>[iframe not supported]</div></iframe>');
+}
diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html index c09fcee8c..a5b41aefd 100644 --- a/httemplate/elements/menu.html +++ b/httemplate/elements/menu.html @@ -3,6 +3,8 @@ my $conf = new FS::Conf; my $fsurl = $opt{'freeside_baseurl'}; + my $curuser = $FS::CurrentUser::CurrentUser; + #Active tickets not assigned to a customer tie my %report_customers_lists, 'Tie::IxHash', @@ -40,52 +42,68 @@ tie my %report_services_acct, 'Tie::IxHash', 'All accounts by username' => [ $fsurl.'search/svc_acct.cgi?username', '' ], 'All accounts by UID' => [ $fsurl.'search/svc_acct.cgi?uid', '' ], - 'Unlinked accounts' => [ $fsurl.'search/svc_acct.cgi?UN_uid', 'Pre-Freeside accounts without a customer record' ], ; + $report_services_acct{'Unlinked accounts'} = [ $fsurl.'search/svc_acct.cgi?UN_uid', 'Pre-Freeside accounts without a customer record' ] + if $curuser->access_right('View/link unlinked services'); tie my %report_services_domain, 'Tie::IxHash', 'All domains' => [ $fsurl.'search/svc_domain.cgi?domain', '' ], - 'Unlinked domains' => [ $fsurl.'search/svc_domain.cgi?UN_domain', 'Pre-Freeside domains without a customer record' ], ; + $report_services_domain{'Unlinked domains'} = [ $fsurl.'search/svc_domain.cgi?UN_domain', 'Pre-Freeside domains without a customer record' ] + if $curuser->access_right('View/link unlinked services'); tie my %report_services_forward, 'Tie::IxHash', 'All mail forwards' => [ $fsurl.'search/svc_forward.cgi?svcnum', '' ], - 'Unlinked mail forwards' => [ $fsurl.'search/svc_forward.cgi?UN_svcnum', 'Pre-Freeside mail forwards without a customer record' ], ; + $report_services_forward{'Unlinked mail forwards'} = [ $fsurl.'search/svc_forward.cgi?UN_svcnum', 'Pre-Freeside mail forwards without a customer record' ] + if $curuser->access_right('View/link unlinked services'); tie my %report_services_www, 'Tie::IxHash', 'All virtual hosts' => [ $fsurl.'search/svc_www.cgi?svcnum', '' ], - 'Unlinked virtual hosts' => [ $fsurl.'search/svc_www.cgi?UN_svcnum', 'Pre-Freeside virtual hosts without a customer record' ], ; + $report_services_www{'Unlinked virtual hosts'} = [ $fsurl.'search/svc_www.cgi?UN_svcnum', 'Pre-Freeside virtual hosts without a customer record' ] + if $curuser->access_right('View/link unlinked services'); tie my %report_services_broadband, 'Tie::IxHash', 'All broadband services' => [ $fsurl.'search/svc_broadband.cgi?svcnum', '' ], #'Unlinked domain' => [ $fsurl.'search/svc_acct.cgi?UN_uid', 'Pre-Freeside domains without a customer record' ], ; + tie my %report_services_phone, 'Tie::IxHash', + 'All phone numbers' => [ $fsurl.'search/svc_phone.cgi?svcnum', '' ], + ; + tie my %report_services_external, 'Tie::IxHash', 'All external services' => [ $fsurl.'search/svc_external.cgi?id', '' ], - 'Unlinked external services' => [ $fsurl.'search/svc_external.cgi?UN_id', 'Pre-Freeside domains without a customer record' ], ; + $report_services_external{'Unlinked external services'} = [ $fsurl.'search/svc_external.cgi?UN_id', 'Pre-Freeside domains without a customer record' ] + if $curuser->access_right('View/link unlinked services'); - tie my %report_services, 'Tie::IxHash', - 'Service definitions' => [ $fsurl.'browse/part_svc.cgi?orderby=active', 'Service definitions by number of active packages' ], - 'separator' => '', - 'Accounts' => [ \%report_services_acct, 'Access accounts and mailboxes' ], - 'Domains' => [ \%report_services_domain, 'Domains', ], - 'Mail forwards' => [ \%report_services_forward, 'Mail forwards', ], - 'Virtual hosts' => [ \%report_services_www, 'Virtual hosting', ], - 'Broadband services' => [ \%report_services_broadband, 'Fixed (username-less) broadband services', ], - 'External services' => [ \%report_services_external, 'External services', ], - ; + tie my %report_services, 'Tie::IxHash'; + if ( $curuser->access_right('Configuration') ) { + $report_services{'Service definitions'} = [ $fsurl.'browse/part_svc.cgi?orderby=active', 'Service definitions by number of active packages' ]; + $report_services{'separator'} = ''; + } + $report_services{'Accounts'} = [ \%report_services_acct, 'Access accounts and mailboxes' ]; + $report_services{'Domains'} = [ \%report_services_domain, 'Domains', ]; + $report_services{'Mail forwards'} = [ \%report_services_forward, 'Mail forwards', ]; + $report_services{'Virtual hosts'} = [ \%report_services_www, 'Virtual hosting', ]; + $report_services{'Broadband services'} = [ \%report_services_broadband, 'Fixed (username-less) broadband services', ]; + $report_services{'Phone numbers'} = [ \%report_services_phone, 'Telephone numbers', ]; + $report_services{'External services'} = [ \%report_services_external, 'External services', ]; + + tie my %report_packages, 'Tie::IxHash'; + if ( $curuser->access_right('Configuration') ) { + $report_packages{'Package definitions'} = [ $fsurl.'browse/part_pkg.cgi?active=1', 'Package definitions by number of active packages' ]; + $report_packages{'separator'} = ''; + } + $report_packages{'All customer packages'} = [ $fsurl.'search/cust_pkg.cgi?pkgnum', 'List all customer packages', ]; + $report_packages{'Suspended customer packages'} = [ $fsurl.'search/cust_pkg.cgi?magic=suspended', 'List suspended packages' ]; + $report_packages{'Customer packages with unconfigured services'} = [ $fsurl.'search/cust_pkg.cgi?APKG_pkgnum', 'List packages which have provisionable services' ]; + $report_packages{'Advanced package reports'} = [ $fsurl.'search/report_cust_pkg.html', 'by agent, date range, status, package definition' ]; - tie my %report_packages, 'Tie::IxHash', - 'Package definitions' => [ $fsurl.'browse/part_pkg.cgi?active=1', 'Package definitions by number of active packages' ], - 'separator' => '', - 'All customer packages' => [ $fsurl.'search/cust_pkg.cgi?pkgnum', 'List all customer packages', ], - 'Suspended customer packages' => [ $fsurl.'search/cust_pkg.cgi?magic=suspended', 'List suspended packages' ], - 'Customer packages with unconfigured services' => [ $fsurl.'search/cust_pkg.cgi?APKG_pkgnum', 'List packages which have provisionable services' ], - 'By next bill date' => [ $fsurl.'search/cust_pkg_report.cgi', 'Search packages by next bill date' ], + tie my %report_rating, 'Tie::IxHash', + 'Call Detail Records (CDRs)' => [ $fsurl.'search/report_cdr.html', '' ], ; tie my %report_financial, 'Tie::IxHash', @@ -98,17 +116,24 @@ 'Sales Tax Liability' => [ $fsurl.'search/report_tax.html', 'Sales tax liability report' ], ; - tie my %report_menu, 'Tie::IxHash', - 'Customers' => [ \%report_customers, 'Customer reports' ], - 'Invoices' => [ \%report_invoices, 'Invoice reports' ], - 'Packages' => [ \%report_packages, 'Package reports' ], - 'Services' => [ \%report_services, 'Services reports' ], - 'Financial' => [ \%report_financial, 'Financial reports' ], - ; + tie my %report_menu, 'Tie::IxHash'; + $report_menu{'Customers'} = [ \%report_customers, 'Customer reports' ] + if $curuser->access_right('List customers'); + $report_menu{'Invoices'} = [ \%report_invoices, 'Invoice reports' ] + if $curuser->access_right('List invoices'); + $report_menu{'Packages'} = [ \%report_packages, 'Package reports' ] + if $curuser->access_right('List packages'); + $report_menu{'Services'} = [ \%report_services, 'Services reports' ] + if $curuser->access_right('List services'); + $report_menu{'Rating data'} = [ \%report_rating, 'Rating reports' ] + if $curuser->access_right('List rating data'); + $report_menu{'Financial'} = [ \%report_financial, 'Financial reports' ] + if $curuser->access_right('Financial reports'); tie my %tools_importing, 'Tie::IxHash', 'Import customers from CSV file' => [ $fsurl.'misc/cust_main-import.cgi', '' ], 'Import one-time charges from CSV file' => [ $fsurl.'misc/cust_main-import_charges.cgi', '' ], + 'Import Call Detail Records (CDRs) from CSV file' => [ $fsurl.'misc/cdr-import.html', '' ], ; tie my %tools_exporting, 'Tie::IxHash', @@ -120,12 +145,15 @@ # <!-- or <A HREF="browse/nas-sqlradius.cgi">RADIUS</A> # <BR> --> - tie my %tools_menu, 'Tie::IxHash', - 'Quick payment entry' => [ $fsurl.'misc/batch-cust_pay.html', 'Enter multiple payments in a batch' ], - 'Job Queue' => [ $fsurl.'search/queue.html', 'View pending job queue' ], - 'Importing' => [ \%tools_importing, 'Import tools' ], - 'Exporting' => [ \%tools_exporting, 'Export tools' ], - ; + tie my %tools_menu, 'Tie::IxHash', (); + $tools_menu{'Quick payment entry'} = [ $fsurl.'misc/batch-cust_pay.html', 'Enter multiple payments in a batch' ] + if $curuser->access_right('Post payment batch'); + $tools_menu{'Job Queue'} = [ $fsurl.'search/queue.html', 'View pending job queue' ] + if $curuser->access_right('Job queue'); + $tools_menu{'Importing'} = [ \%tools_importing, 'Import tools' ] + if $curuser->access_right('Import'); + $tools_menu{'Exporting'} = [ \%tools_exporting, 'Export tools' ] + if $curuser->access_right('Export'); tie my %config_employees, 'Tie::IxHash', 'View/Edit employees' => [ $fsurl.'browse/access_user.html', 'Setup internal users' ], @@ -161,26 +189,36 @@ 'View/Edit address blocks' => [ $fsurl.'browse/addr_block.cgi', 'Manage address blocks and block assignments to broadband routers' ], ; - tie my %config_misc, 'Tie::IxHash', - 'View/Edit advertising sources' => [ $fsurl.'browse/part_referral.cgi', 'Where a customer heard about your service. Tracked for informational purposes' ], - 'View/Edit virtual fields' => [ $fsurl.'browse/part_virtual_field.cgi', 'Locally defined fields', ], - 'View/Edit message catalog' => [ $fsurl.'browse/msgcat.cgi', 'Change error messages and other customizable labels' ], - 'View/Edit inventory classes and inventory' => [ $fsurl.'browse/inventory_class.html', 'Setup inventory classes and stock inventory' ], - ; + tie my %config_misc, 'Tie::IxHash'; + $config_misc{'View/Edit advertising sources'} = [ $fsurl.'browse/part_referral.html', 'Where a customer heard about your service. Tracked for informational purposes' ] + if $curuser->access_right('Configuration') + || $curuser->access_right('Edit advertising sources') + || $curuser->access_right('Edit global advertising sources'); + if ( $curuser->access_right('Configuration') ) { + $config_misc{'View/Edit virtual fields'} = [ $fsurl.'browse/part_virtual_field.cgi', 'Locally defined fields', ]; + $config_misc{'View/Edit message catalog'} = [ $fsurl.'browse/msgcat.cgi', 'Change error messages and other customizable labels' ]; + $config_misc{'View/Edit inventory classes and inventory'} = [ $fsurl.'browse/inventory_class.html', 'Setup inventory classes and stock inventory' ]; + } - tie my %config_menu, 'Tie::IxHash', - 'Settings' => [ $fsurl.'config/config-view.cgi', '' ], - 'separator' => '', #its a separator! - 'Employees' => [ \%config_employees, '' ], - 'Provisioning, services and packages' - => [ \%config_export_svc_pkg, '' ], - 'Resellers' => [ \%config_agent, '' ], - 'Billing' => [ \%config_billing, '' ], - 'Dialup' => [ \%config_dialup, '' ], - 'Fixed (username-less) broadband' - => [ \%config_broadband, '' ], - 'Miscellaneous' => [ \%config_misc, '' ], - ; + tie my %config_menu, 'Tie::IxHash'; + if ( $curuser->access_right('Configuration' ) ) { + %config_menu = ( + 'Settings' => [ $fsurl.'config/config-view.cgi', '' ], + 'separator' => '', #its a separator! + 'Employees' => [ \%config_employees, '' ], + 'Provisioning, services and packages' + => [ \%config_export_svc_pkg, '' ], + 'Resellers' => [ \%config_agent, '' ], + 'Billing' => [ \%config_billing, '' ], + 'Dialup' => [ \%config_dialup, '' ], + 'Fixed (username-less) broadband' + => [ \%config_broadband, '' ], + ); + } + $config_menu{'Miscellaneous'} = [ \%config_misc, '' ] + if $curuser->access_right('Configuration') + || $curuser->access_right('Edit advertising sources') + || $curuser->access_right('Edit global advertising sources'); tie my %menu, 'Tie::IxHash', 'Billing Main' => [ $fsurl, 'Billing start page', ], @@ -191,10 +229,15 @@ ), 'Ticketing start page', ], - 'Reports' => [ \%report_menu, 'Lists, reporting and graphing' ], - 'Tools' => [ \%tools_menu, 'Tools' ], - 'Configuration' => [ \%config_menu, 'Configuraiton and setup' ], ; + $menu{'Reports'} = [ \%report_menu, 'Lists, reporting and graphing' ] + if keys %report_menu; + $menu{'Tools'} = [ \%tools_menu, 'Tools' ] + if keys %tools_menu; + $menu{'Configuration'} = [ \%config_menu, 'Configuraiton and setup' ] + if $curuser->access_right('Configuration') + || $curuser->access_right('Edit advertising sources') + || $curuser->access_right('Edit global advertising sources'); use vars qw($gmenunum); $gmenunum = 0; @@ -264,7 +307,7 @@ if ( ref($url_or_submenu) ) { - warn $item; + #warn $item; my( $subhtml, $submenuname ) = submenu($url_or_submenu, $item); diff --git a/httemplate/elements/overlibmws.js b/httemplate/elements/overlibmws.js index fba1105b5..5ef50d68f 100644 --- a/httemplate/elements/overlibmws.js +++ b/httemplate/elements/overlibmws.js @@ -1,7 +1,7 @@ /*
Do not remove or change this notice.
overlibmws.js core module - Copyright Foteos Macrides 2002-2005. All rights reserved.
- Initial: August 18, 2002 - Last Revised: February 10, 2005
+ Initial: August 18, 2002 - Last Revised: May 30, 2006
This module is subject to the same terms of usage as for Erik Bosrup's overLIB,
though only a minority of the code and API now correspond with Erik's version.
See the overlibmws Change History and Command Reference via:
@@ -14,30 +14,30 @@ */
// PRE-INIT -- Ignore these lines, configuration is below.
-var OLloaded=0,pmCnt=1,pMtr=new Array(),OLv,OLudf,OLrefXY;
-var OLpct=new Array("83%","67%","83%","100%","117%","150%","200%","267%");
-var OLbubblePI=0,OLcrossframePI=0,OLdebugPI=0,OLdraggablePI=0,OLexclusivePI=0,OLfilterPI=0;
-var OLfunctionPI=0,OLhidePI=0,OLiframePI=0,OLovertwoPI=0,OLscrollPI=0,OLshadowPI=0;
+var OLloaded=0,pmCnt=1,pMtr=new Array(),OLcmdLine=new Array(),OLrunTime=new Array(),OLv,OLudf,
+OLpct=new Array("83%","67%","83%","100%","117%","150%","200%","267%"),OLrefXY,
+OLbubblePI=0,OLcrossframePI=0,OLdebugPI=0,OLdraggablePI=0,OLexclusivePI=0,OLfilterPI=0,
+OLfunctionPI=0,OLhidePI=0,OLiframePI=0,OLovertwoPI=0,OLscrollPI=0,OLshadowPI=0,OLprintPI=0;
if(typeof OLgateOK=='undefined')var OLgateOK=1;
-OLregCmds(
- 'inarray,caparray,caption,sticky,nofollow,background,noclose,mouseoff,offdelay,right,left,'
-+'center,offsetx,offsety,fgcolor,bgcolor,cgcolor,textcolor,capcolor,closecolor,width,wrap,'
-+'wrapmax,height,border,base,status,autostatus,autostatuscap,snapx,snapy,fixx,fixy,relx,rely,'
-+'midx,midy,ref,refc,refp,refx,refy,fgbackground,bgbackground,cgbackground,padx,pady,fullhtml,'
-+'below,above,vcenter,capicon,textfont,captionfont,closefont,textsize,captionsize,closesize,'
-+'timeout,delay,hauto,vauto,nojustx,nojusty,closetext,closeclick,closetitle,fgclass,bgclass,'
-+'cgclass,capbelow,textpadding,textfontclass,captionpadding,captionfontclass,closefontclass,'
-+'label,donothing');
-
+var OLp1or2c='inarray,caparray,caption,closetext,right,left,center,autostatuscap,padx,pady,'
++'below,above,vcenter,donothing',OLp1or2co='nofollow,background,offsetx,offsety,fgcolor,'
++'bgcolor,cgcolor,textcolor,capcolor,width,wrap,wrapmax,height,border,base,status,autostatus,'
++'snapx,snapy,fixx,fixy,relx,rely,midx,midy,ref,refc,refp,refx,refy,fgbackground,bgbackground,'
++'cgbackground,fullhtml,capicon,textfont,captionfont,textsize,captionsize,timeout,delay,hauto,'
++'vauto,nojustx,nojusty,fgclass,bgclass,cgclass,capbelow,textpadding,textfontclass,'
++'captionpadding,captionfontclass,sticky,noclose,mouseoff,offdelay,closecolor,closefont,'
++'closesize,closeclick,closetitle,closefontclass,decode',OLp1or2o='text,cap,close,hpos,vpos,'
++'padxl,padxr,padyt,padyb',OLp1co='label',OLp1or2=OLp1or2co+','+OLp1or2o,OLp1=OLp1co+','+'frame';
+OLregCmds(OLp1or2c+','+OLp1or2co+','+OLp1co);
function OLud(v){return eval('typeof ol_'+v+'=="undefined"')?1:0;}
-// DEFAULT CONFIGURATION -- See overlibConfig.txt for descriptions.
-if(OLud('fgcolor'))var ol_fgcolor="#CCCCFF";
+// DEFAULT CONFIGURATION -- See overlibConfig.txt for descriptions
+if(OLud('fgcolor'))var ol_fgcolor="#ccccff";
if(OLud('bgcolor'))var ol_bgcolor="#333399";
if(OLud('cgcolor'))var ol_cgcolor="#333399";
if(OLud('textcolor'))var ol_textcolor="#000000";
-if(OLud('capcolor'))var ol_capcolor="#FFFFFF";
-if(OLud('closecolor'))var ol_closecolor="#EEEEFF";
+if(OLud('capcolor'))var ol_capcolor="#ffffff";
+if(OLud('closecolor'))var ol_closecolor="#eeeeff";
if(OLud('textfont'))var ol_textfont="Verdana,Arial,Helvetica";
if(OLud('captionfont'))var ol_captionfont="Verdana,Arial,Helvetica";
if(OLud('closefont'))var ol_closefont="Verdana,Arial,Helvetica";
@@ -106,43 +106,41 @@ if(OLud('vauto'))var ol_vauto=0; if(OLud('nojustx'))var ol_nojustx=0;
if(OLud('nojusty'))var ol_nojusty=0;
if(OLud('label'))var ol_label="";
+if(OLud('decode'))var ol_decode=0;
// ARRAY CONFIGURATION - See overlibConfig.txt for descriptions.
if(OLud('texts'))var ol_texts=new Array("Text 0","Text 1");
if(OLud('caps'))var ol_caps=new Array("Caption 0","Caption 1");
// END CONFIGURATION -- Don't change anything below, all configuration is above.
// INIT -- Runtime variables.
-var o3_text="",o3_cap="",o3_sticky=0,o3_nofollow=0,o3_background="",o3_noclose=0,o3_mouseoff=0;
-var o3_offdelay=300,o3_hpos=RIGHT,o3_offsetx=10,o3_offsety=10,o3_fgcolor="",o3_bgcolor="";
-var o3_cgcolor="",o3_textcolor="",o3_capcolor="",o3_closecolor="",o3_width=200,o3_wrap=0;
-var o3_wrapmax=0,o3_height= -1,o3_border=1,o3_base=0,o3_status="",o3_autostatus=0,o3_snapx=0;
-var o3_snapy=0,o3_fixx= -1,o3_fixy= -1,o3_relx=null,o3_rely=null,o3_midx=null,o3_midy=null;
-var o3_ref="",o3_refc='UL',o3_refp='UL',o3_refx=0,o3_refy=0,o3_fgbackground="";
-var o3_bgbackground="",o3_cgbackground="",o3_padxl=0,o3_padxr=0,o3_padyt=0,o3_padyb=0;
-var o3_fullhtml=0,o3_vpos=BELOW,o3_capicon="",o3_textfont="Verdana,Arial,Helvetica";
-var o3_captionfont="Verdana,Arial,Helvetica",o3_closefont="Verdana,Arial,Helvetica";
-var o3_textsize=1,o3_captionsize=1,o3_closesize=1,o3_frame=self,o3_timeout=0,o3_delay=0;
-var o3_hauto=0,o3_vauto=0,o3_nojustx=0,o3_nojusty=0,o3_close="Close",o3_closeclick=0;
-var o3_closetitle="",o3_fgclass="",o3_bgclass="",o3_cgclass="",o3_textpadding=2;
-var o3_textfontclass="",o3_captionpadding=2,o3_captionfontclass="",o3_closefontclass="";
-var o3_capbelow=0,o3_label="",CSSOFF=DONOTHING,CSSCLASS=DONOTHING;
-var OLx=0,OLy=0,OLshowingsticky=0,OLallowmove=0,OLremovecounter=0;
-var OLdelayid=0,OLtimerid=0,OLshowid=0,OLndt=0;
-var over=null,OLfnRef="",OLhover=0;
-var OLua=navigator.userAgent.toLowerCase();
-var OLns4=(navigator.appName=='Netscape'&&parseInt(navigator.appVersion)==4);
-var OLns6=(document.getElementById)?1:0;
-var OLie4=(document.all)?1:0;
-var OLgek=(OLv=OLua.match(/gecko\/(\d{8})/i))?parseInt(OLv[1]):0;
-var OLmac=(OLua.indexOf('mac')>=0)?1:0;
-var OLsaf=(OLua.indexOf('safari')>=0)?1:0;
-var OLkon=(OLua.indexOf('konqueror')>=0)?1:0;
-var OLkht=(OLsaf||OLkon)?1:0;
-var OLopr=(OLua.indexOf('opera')>=0)?1:0;
-var OLop7=(OLopr&&document.createTextNode)?1:0;
+var o3_text="",o3_cap="",o3_sticky=0,o3_nofollow=0,o3_background="",o3_noclose=0,o3_mouseoff=0,
+o3_offdelay=300,o3_hpos=RIGHT,o3_offsetx=10,o3_offsety=10,o3_fgcolor="",o3_bgcolor="",
+o3_cgcolor="",o3_textcolor="",o3_capcolor="",o3_closecolor="",o3_width=200,o3_wrap=0,
+o3_wrapmax=0,o3_height= -1,o3_border=1,o3_base=0,o3_status="",o3_autostatus=0,o3_snapx=0,
+o3_snapy=0,o3_fixx= -1,o3_fixy= -1,o3_relx=null,o3_rely=null,o3_midx=null,o3_midy=null,o3_ref="",
+o3_refc='UL',o3_refp='UL',o3_refx=0,o3_refy=0,o3_fgbackground="",o3_bgbackground="",
+o3_cgbackground="",o3_padxl=0,o3_padxr=0,o3_padyt=0,o3_padyb=0,o3_fullhtml=0,o3_vpos=BELOW,
+o3_capicon="",o3_textfont="Verdana,Arial,Helvetica",o3_captionfont="",o3_closefont="",
+o3_textsize=1,o3_captionsize=1,o3_closesize=1,o3_frame=self,o3_timeout=0,o3_delay=0,o3_hauto=0,
+o3_vauto=0,o3_nojustx=0,o3_nojusty=0,o3_close="",o3_closeclick=0,o3_closetitle="",o3_fgclass="",
+o3_bgclass="",o3_cgclass="",o3_textpadding=2,o3_textfontclass="",o3_captionpadding=2,
+o3_captionfontclass="",o3_closefontclass="",o3_capbelow=0,o3_label="",o3_decode=0,
+CSSOFF=DONOTHING,CSSCLASS=DONOTHING,OLdelayid=0,OLtimerid=0,OLshowid=0,OLndt=0,over=null,
+OLfnRef="",OLhover=0,OLx=0,OLy=0,OLshowingsticky=0,OLallowmove=0,OLcC=null,
+OLua=navigator.userAgent.toLowerCase(),
+OLns4=(navigator.appName=='Netscape'&&parseInt(navigator.appVersion)==4),
+OLns6=(document.getElementById)?1:0,
+OLie4=(document.all)?1:0,
+OLgek=(OLv=OLua.match(/gecko\/(\d{8})/i))?parseInt(OLv[1]):0,
+OLmac=(OLua.indexOf('mac')>=0)?1:0,
+OLsaf=(OLua.indexOf('safari')>=0)?1:0,
+OLkon=(OLua.indexOf('konqueror')>=0)?1:0,
+OLkht=(OLsaf||OLkon)?1:0,
+OLopr=(OLua.indexOf('opera')>=0)?1:0,
+OLop7=(OLopr&&document.createTextNode)?1:0;
if(OLopr){OLns4=OLns6=0;if(!OLop7)OLie4=0;}
-var OLieM=((OLie4&&OLmac)&&!(OLkht||OLopr))?1:0;
-var OLie5=0,OLie55=0;if(OLie4&&!OLop7){
+var OLieM=((OLie4&&OLmac)&&!(OLkht||OLopr))?1:0,
+OLie5=0,OLie55=0;if(OLie4&&!OLop7){
if((OLv=OLua.match(/msie (\d\.\d+)\.*/i))&&(OLv=parseFloat(OLv[1]))>=5.0){
OLie5=1;OLns6=0;if(OLv>=5.5)OLie55=1;}if(OLns6)OLie4=0;}
if(OLns4)window.onresize=function(){location.reload();}
@@ -156,14 +154,16 @@ else{overlib=nd=cClick=OLpageDefaults=no_overlib;} // Loads defaults then args into runtime variables.
function overlib(){
if(!(OLloaded&&OLgateOK))return;
-if((OLexclusivePI)&&OLisExclusive(overlib.arguments))return true;
+if((OLexclusivePI)&&OLisExclusive(arguments))return true;
if(OLchkMh)OLmh();
if(OLndt&&!OLtimerid)OLndt=0;if(over)cClick();
-OLloadP1or2();OLload('close,closeclick,closetitle,noclose,mouseoff,offdelay,sticky,'
-+'closecolor,closefont,closesize,closefontclass,frame,label');OLfnRef="";OLhover=0;
+OLload(OLp1or2);OLload(OLp1);
+OLfnRef="";OLhover=0;
OLsetRunTimeVar();
-OLparseTokens('o3_',overlib.arguments);
+OLparseTokens('o3_',arguments);
if(!(over=OLmkLyr()))return false;
+if(o3_decode)OLdecode();
+if(OLprintPI)OLchkPrint();
if(OLbubblePI)OLchkForBubbleEffect();
if(OLdebugPI)OLsetDebugCanShow();
if(OLshadowPI)OLinitShadow();
@@ -172,7 +172,7 @@ if(OLfilterPI)OLinitFilterLyr(); if(OLexclusivePI&&o3_exclusive&&o3_exclusivestatus!="")o3_status=o3_exclusivestatus;
else if(o3_autostatus==2&&o3_cap!="")o3_status=o3_cap;
else if(o3_autostatus==1&&o3_text!="")o3_status=o3_text;
-if(o3_delay==0){return OLmain();
+if(!o3_delay){return OLmain();
}else{OLdelayid=setTimeout("OLmain()",o3_delay);
if(o3_status!=""){self.status=o3_status;return true;}
else if(!(OLop7&&event&&event.type=='mouseover'))return false;}
@@ -180,25 +180,24 @@ else if(!(OLop7&&event&&event.type=='mouseover'))return false;} // Clears popups if appropriate
function nd(time){
-if(!(OLloaded&&OLgateOK))return;
-if((OLexclusivePI)&&OLisExclusive())return true;
+if(OLloaded&&OLgateOK){if(!((OLexclusivePI)&&OLisExclusive())){
if(time&&over&&!o3_delay){if(OLtimerid>0)clearTimeout(OLtimerid);
OLtimerid=(OLhover&&o3_frame==self&&!OLcursorOff())?0:
-setTimeout("cClick()",(o3_timeout=OLndt=time));
-}else{if(OLremovecounter>=1)OLshowingsticky=0;if(!OLshowingsticky){
-OLallowmove=0;if(over)OLhideObject(over);}else{OLremovecounter++;}}
-return true;
+setTimeout("cClick()",(o3_timeout=OLndt=time));}else{
+if(!OLshowingsticky){OLallowmove=0;if(over)OLhideObject(over);}}}}
+return false;
}
// Close function for stickies
function cClick(){
-if(OLloaded&&OLgateOK){OLhover=0;if(over)OLhideObject(over);OLshowingsticky=0;}
+if(OLloaded&&OLgateOK){OLhover=0;if(over){
+if(OLovertwoPI&&over==over2)cClick2();OLhideObject(over);OLshowingsticky=0;}}
return false;
}
// Sets page-specific defaults.
function OLpageDefaults(){
-OLparseTokens('ol_',OLpageDefaults.arguments);
+OLparseTokens('ol_',arguments);
}
// For unsupported browsers.
@@ -210,24 +209,14 @@ function no_overlib(){return false;} function OLmain(){
o3_delay=0;
if(o3_frame==self){if(o3_noclose)OLoptMOUSEOFF(0);else if(o3_mouseoff)OLoptMOUSEOFF(1);}
-OLdoLyr();
-OLallowmove=0;if(o3_timeout>0){
+if(o3_sticky)OLshowingsticky=1;OLdoLyr();OLallowmove=0;if(o3_timeout>0){
if(OLtimerid>0)clearTimeout(OLtimerid);OLtimerid=setTimeout("cClick()",o3_timeout);}
if(o3_ref){OLrefXY=OLgetRefXY(o3_ref);if(OLrefXY[0]==null){o3_ref="";o3_midx=0;o3_midy=0;}}
-OLdisp(o3_status);
-if(OLdraggablePI)OLcheckDrag();
+OLdisp(o3_status);if(OLdraggablePI)OLcheckDrag();
if(o3_status!="")return true;else if(!(OLop7&&event&&event.type=='mouseover'))return false;
}
-// Loads defaults for primaries or secondaries
-function OLloadP1or2(){
-OLload('text,cap,capbelow,textpadding,captionpadding,border,base,status,autostatus,nofollow,'
-+'width,wrap,wrapmax,height,hpos,vpos,offsetx,offsety,snapx,snapy,relx,rely,midx,midy,ref,'
-+'refc,refp,refx,refy,fixx,fixy,nojustx,nojusty,hauto,vauto,timeout,delay,fgcolor,bgcolor,'
-+'cgcolor,textcolor,capcolor,textfont,captionfont,textsize,captionsize,fgbackground,'
-+'bgbackground,cgbackground,capicon,background,padxl,padxr,padyt,padyb,fullhtml,fgclass,'
-+'bgclass,cgclass,textfontclass,captionfontclass');
-}
+// Loads o3_ variables
function OLload(c){var i,m=c.split(',');for(i=0;i<m.length;i++)eval('o3_'+m[i]+'=ol_'+m[i]);}
// Chooses LGF
@@ -258,8 +247,7 @@ if(o3_bgcolor!='')o3_bgcolor=' bgcolor="'+o3_bgcolor+'"'; if(o3_cgcolor!='')o3_cgcolor=' bgcolor="'+o3_cgcolor+'"';
if(o3_height>0)o3_height=' height="'+o3_height+'"';else o3_height='';}
if(!OLns4)OLrepositionTo(over,(OLns6?20:0),0);var lyrHtml=OLdoLGF();
-if(o3_sticky){if(OLtimerid>0){clearTimeout(OLtimerid);OLtimerid=0;}
-OLshowingsticky=1;OLremovecounter=0;}
+if(o3_sticky&&OLtimerid>0){clearTimeout(OLtimerid);OLtimerid=0;}
if(o3_wrap&&!o3_fullhtml){OLlayerWrite(lyrHtml);
o3_width=(OLns4?over.clip.width:over.offsetWidth);
if(OLns4&&o3_wrapmax<1)o3_wrapmax=o3_frame.innerWidth-40;
@@ -279,19 +267,19 @@ OLsetBackground('');return t; // Makes table with caption and optional close link
function OLcontentCaption(txt,title,close){
-var closing='',closeevent='onmouseover',caption,t;
-if(o3_closeclick==1)closeevent=(o3_closetitle?'title="'+o3_closetitle+'" ':'')+'onclick';
+var closing=(OLprintPI?OLprintCapLGF():''),closeevent='onmouseover',caption,t,
+cC='javascript:return '+OLfnRef+(OLovertwoPI&&over==over2?'cClick2();':'cClick();');
+if(o3_closeclick)closeevent=(o3_closetitle?'title="'+o3_closetitle+'" ':'')+'onclick';
if(o3_capicon!='')o3_capicon='<img src="'+o3_capicon+'" /> ';
-if(close!=''){closing='<td align="right"><a href="javascript:return '+OLfnRef+'cClick();" '
-+closeevent+'="return '+OLfnRef+'cClick();"'+(o3_closefontclass?' class="'+o3_closefontclass
-+'">':'>'+OLlgfUtil(0,'','span',o3_closecolor,o3_closefont,o3_closesize))+close
-+(o3_closefontclass?'':OLlgfUtil(1,'','span'))+'</a></td>';}
+if(close){closing+='<td align="right"><a href="'+cC+'" '
++closeevent+'="'+cC+'"'+(o3_closefontclass?' class="'+o3_closefontclass
++'">':'>'+OLlgfUtil(0,0,'','span',o3_closecolor,o3_closefont,o3_closesize))+close
++(o3_closefontclass?'':OLlgfUtil(1,0,'','span'))+'</a></td>';}
caption='<table'+OLwd(0)+' border="0" cellpadding="'+o3_captionpadding+'" cellspacing="0"'
+(o3_cgclass?' class="'+o3_cgclass+'"':o3_cgcolor+o3_cgbackground)+'><tr><td'+OLwd(0)
+(o3_cgclass?' class="'+o3_cgclass+'">':'>')+(o3_captionfontclass?'<div class="'
-+o3_captionfontclass+'">':'<strong>'
-+OLlgfUtil(0,'','div',o3_capcolor,o3_captionfont,o3_captionsize))+o3_capicon+title
-+OLlgfUtil(1,'','div')+(o3_captionfontclass?'':'</strong>')+'</td>'+closing+'</tr></table>';
++o3_captionfontclass+'">':OLlgfUtil(0,1,'','div',o3_capcolor,o3_captionfont,
+o3_captionsize))+o3_capicon+title+OLlgfUtil(1,1,'','div')+'</td>'+closing+'</tr></table>';
t=OLbgLGF()+(o3_capbelow?OLfgLGF(txt)+caption:caption+OLfgLGF(txt))+OLbaseLGF();
OLsetBackground('');return t;
}
@@ -302,8 +290,8 @@ var t;if(hasfullhtml){t=txt;}else{t='<table'+OLwd(1) +' border="0" cellpadding="0" cellspacing="0" '+'height="'+o3_height
+'"><tr><td colspan="3" height="'+o3_padyt+'"></td></tr><tr><td width="'
+o3_padxl+'"></td><td valign="top"'+OLwd(2)+'>'
-+OLlgfUtil(0,o3_textfontclass,'div',o3_textcolor,o3_textfont,o3_textsize)+txt+
-OLlgfUtil(1,'','div')+'</td><td width="'+o3_padxr+'"></td></tr><tr><td colspan="3" height="'
++OLlgfUtil(0,0,o3_textfontclass,'div',o3_textcolor,o3_textfont,o3_textsize)+txt+
+OLlgfUtil(1,0,'','div')+'</td><td width="'+o3_padxr+'"></td></tr><tr><td colspan="3" height="'
+o3_padyb+'"></td></tr></table>';}
OLsetBackground(image);return t;
}
@@ -317,14 +305,15 @@ function OLfgLGF(t){ return '<table'+OLwd(0)+o3_height+' border="0" cellpadding="'+o3_textpadding
+'" cellspacing="0"'+(o3_fgclass?' class="'+o3_fgclass+'"':o3_fgcolor+o3_fgbackground)
+'><tr><td valign="top"'+(o3_fgclass?' class="'+o3_fgclass+'"':'')+'>'
-+OLlgfUtil(0,o3_textfontclass,'div',o3_textcolor,o3_textfont,o3_textsize)+t
-+OLlgfUtil(1,'','div')+'</td></tr></table>';
++OLlgfUtil(0,0,o3_textfontclass,'div',o3_textcolor,o3_textfont,o3_textsize)+t
++(OLprintPI?OLprintFgLGF():'')+OLlgfUtil(1,0,'','div')+'</td></tr></table>';
}
-function OLlgfUtil(end,tfc,ele,col,fac,siz){
-if(end)return ('</'+(OLns4?'font':ele)+'>');else return (tfc?'<div class="'+tfc+'">':
-('<'+(OLns4?'font color="'+col+'" face="'+OLquoteMultiNameFonts(fac)+'" size="'+siz:ele
-+' style="color:'+col+';font-family:'+OLquoteMultiNameFonts(fac)+';font-size:'+siz+';'
-+(ele=='span'?'text-decoration:underline;':''))+'">'));
+function OLlgfUtil(end,stg,tfc,ele,col,fac,siz){
+if(end)return ('</'+(OLns4?'font'+(stg?'></strong':''):ele)+'>');else return (tfc?'<div '
++'class="' +tfc +'">':('<'+(OLns4?(stg?'strong><':'')+'font color="'+col+'" face="'
++OLquoteMultiNameFonts(fac)+'" size="'+siz:ele+' style="color:'+col
++(stg?';font-weight:bold':'')+';font-family:'+OLquoteMultiNameFonts(fac)+';font-size:'
++siz+';'+(ele=='span'?'text-decoration:underline;':''))+'">'));
}
function OLquoteMultiNameFonts(f){
var i,v,pM=f.split(',');
@@ -354,34 +343,33 @@ else{if(OLns6)over.style.width=o3_width+'px';over.style.backgroundImage='url('+i */
// Displays layer
function OLdisp(s){
-if(OLallowmove==0){if(OLshadowPI)OLdispShadow();if(OLiframePI)OLdispIfs();OLplaceLayer();
+if(!OLallowmove){if(OLshadowPI)OLdispShadow();if(OLiframePI)OLdispIfs();OLplaceLayer();
if(OLndt)OLshowObject(over);else OLshowid=setTimeout("OLshowObject(over)",1);
OLallowmove=(o3_sticky||o3_nofollow)?0:1;}OLndt=0;if(s!="")self.status=s;
}
// Decides placement of layer.
function OLplaceLayer(){
-var snp,X,Y,pgLeft,pgTop,pWd=o3_width,pHt,iWd=100,iHt=100,SB=0,LM=0,CX=0,TM=0,BM=0,CY=0;
-var o=OLfd(),nsb=(OLgek>=20010505&&!o3_frame.scrollbars.visible)?1:0;
+var snp,X,Y,pgLeft,pgTop,pWd=o3_width,pHt,iWd=100,iHt=100,SB=0,LM=0,CX=0,TM=0,BM=0,CY=0,
+o=OLfd(),nsb=(OLgek>=20010505&&!o3_frame.scrollbars.visible)?1:0;
if(!OLkht&&o&&o.clientWidth)iWd=o.clientWidth;
else if(o3_frame.innerWidth){SB=Math.ceil(1.4*(o3_frame.outerWidth-o3_frame.innerWidth));
if(SB>20)SB=20;iWd=o3_frame.innerWidth;}
pgLeft=(OLie4)?o.scrollLeft:o3_frame.pageXOffset;
-if(OLie55&&OLfilterPI&&o3_filtershadow)SB=CX=5;else
+if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow)SB=CX=5;else
if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowx){SB+=((o3_shadowx>0)?o3_shadowx:0);
LM=((o3_shadowx<0)?Math.abs(o3_shadowx):0);CX=Math.abs(o3_shadowx);}
if(o3_ref!=""||o3_fixx> -1||o3_relx!=null||o3_midx!=null){
-if(o3_ref!=""){
-X=OLrefXY[0];if(OLie55&&OLfilterPI&&o3_filtershadow){if(o3_refp=='UR'||o3_refp=='LR')X -= 5;}
-else if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowx){
-if(o3_shadowx<0&&(o3_refp=='UL'||o3_refp=='LL'))X += o3_shadowx;
-else if(o3_shadowx>0&&(o3_refp=='UR'||o3_refp=='LR'))X -= o3_shadowx;}
+if(o3_ref!=""){X=OLrefXY[0];if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow){
+if(o3_refp=='UR'||o3_refp=='LR')X-=5;}
+else if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowx){
+if(o3_shadowx<0&&(o3_refp=='UL'||o3_refp=='LL'))X-=o3_shadowx;else
+if(o3_shadowx>0&&(o3_refp=='UR'||o3_refp=='LR'))X-=o3_shadowx;}
}else{if(o3_midx!=null){
X=parseInt(pgLeft+((iWd-pWd-SB-LM)/2)+o3_midx);
}else{if(o3_relx!=null){
if(o3_relx>=0)X=pgLeft+o3_relx+LM;else X=pgLeft+o3_relx+iWd-pWd-SB;
-}else{
-X=o3_fixx+LM;}}}
+}else{X=o3_fixx+LM;}}}
}else{
if(o3_hauto){
if(o3_hpos==LEFT&&OLx-pgLeft<iWd/2&&OLx-pWd-o3_offsetx<pgLeft+LM)o3_hpos=RIGHT;else
@@ -398,13 +386,12 @@ if(!OLkht&&!nsb&&o&&o.clientHeight)iHt=o.clientHeight; else if(o3_frame.innerHeight)iHt=o3_frame.innerHeight;
if(OLbubblePI&&o3_bubble)pHt=OLbubbleHt;else pHt=OLns4?over.clip.height:over.offsetHeight;
if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowy){TM=(o3_shadowy<0)?Math.abs(o3_shadowy):0;
-if(OLie55&&OLfilterPI&&o3_filtershadow)BM=CY=5;else
+if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow)BM=CY=5;else
BM=(o3_shadowy>0)?o3_shadowy:0;CY=Math.abs(o3_shadowy);}
if(o3_ref!=""||o3_fixy> -1||o3_rely!=null||o3_midy!=null){
-if(o3_ref!=""){
-Y=OLrefXY[1];if(OLie55&&OLfilterPI&&o3_filtershadow){if(o3_refp=='LL'||o3_refp=='LR')Y -= 5;}
-else if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowy){
-if(o3_shadowy<0&&(o3_refp=='UL'||o3_refp=='UR'))Y+=o3_shadowy;else
+if(o3_ref!=""){Y=OLrefXY[1];if(OLie55&&OLfilterPI&&o3_filter&&o3_filtershadow){
+if(o3_refp=='LL'||o3_refp=='LR')Y-=5;}else if((OLshadowPI)&&bkdrop&&o3_shadow&&o3_shadowy){
+if(o3_shadowy<0&&(o3_refp=='UL'||o3_refp=='UR'))Y-=o3_shadowy;else
if(o3_shadowy>0&&(o3_refp=='LL'||o3_refp=='LR'))Y-=o3_shadowy;}
}else{if(o3_midy!=null){
Y=parseInt(pgTop+((iHt-pHt-CY)/2)+o3_midy);
@@ -434,54 +421,56 @@ return (!OLop7&&fdc&&fdc!='BackCompat'&&fdd&&fdd.clientWidth)?fd.documentElement }
// Gets location of REFerence object
-function OLgetRefXY(r){
-var mn=r,mr=OLgetRef(mn),o,of,rXY;
-if(!mr)return [null,null];
-o=mr;rXY=[o3_refx,o3_refy];
-if(OLns4){if(typeof mr.length!='undefined'&&mr.length>1){
-o=mr[0];rXY[0]+=mr[0].x+mr[1].pageX;rXY[1]+=mr[0].y+mr[1].pageY;
-}else{if((mr.toString().indexOf('Image')!= -1)||(mr.toString().indexOf('Anchor')!= -1)){
-rXY[0]+=mr.x;rXY[1]+=mr.y;}else{rXY[0]+=mr.pageX;rXY[1]+=mr.pageY;}}
-}else{rXY[0]+=OLpageLoc(mr,'Left');rXY[1]+=OLpageLoc(mr,'Top');}
-of=OLgetRefOffsets(o);rXY[0]+=of[0];rXY[1]+=of[1];
+function OLgetRefXY(r,d){
+var o=OLgetRef(r,d),ob=o,rXY=[o3_refx,o3_refy],of;
+if(!o)return [null,null];
+if(OLns4){if(typeof o.length!='undefined'&&o.length>1){
+ob=o[0];rXY[0]+=o[0].x+o[1].pageX;rXY[1]+=o[0].y+o[1].pageY;
+}else{if((o.toString().indexOf('Image')!= -1)||(o.toString().indexOf('Anchor')!= -1)){
+rXY[0]+=o.x;rXY[1]+=o.y;}else{rXY[0]+=o.pageX;rXY[1]+=o.pageY;}}
+}else{rXY[0]+=OLpageLoc(o,'Left');rXY[1]+=OLpageLoc(o,'Top');}
+of=OLgetRefOffsets(ob);rXY[0]+=of[0];rXY[1]+=of[1];
return rXY;
}
-function OLgetRef(l){var r=OLgetRefById(l);return (r)?r:OLgetRefByName(l);}
+function OLgetRef(l,d){var r=OLgetRefById(l,d);return (r)?r:OLgetRefByName(l,d);}
// Seeks REFerence by id
function OLgetRefById(l,d){
-var r="",j;l=(l||'overDiv');d=(d||o3_frame.document);
-if(OLie4&&d.all){return d.all[l];}else if(d.getElementById){return d.getElementById(l);
-}else if(d.layers&&d.layers.length>0){if(d.layers[l])return d.layers[l];
+l=(l||'overDiv');d=(d||o3_frame.document);var j,r;
+if(OLie4&&d.all)return d.all[l];if(d.getElementById)return d.getElementById(l);
+if(d.layers&&d.layers.length>0){if(d.layers[l])return d.layers[l];
for(j=0;j<d.layers.length;j++){r=OLgetRefById(l,d.layers[j].document);if(r)return r;}}
return null;
}
-// Seeks REFerence by name (for img and a)
+// Seeks REFerence by name
function OLgetRefByName(l,d){
-var r=null,j;d=(d||o3_frame.document);
-if(typeof d.images[l]!='undefined'&&d.images[l]){return d.images[l];
-}else if(typeof d.anchors[l]!='undefined'&&d.anchors[l]){return d.anchors[l];
-}else if(d.layers&&d.layers.length>0){
-for(j=0;j<d.layers.length;j++){r=OLgetRefByName(l,d.layers[j].document);
-if(r&&r.length>0)return r;else if(r)return [r,d.layers[j]];}}
+d=(d||o3_frame.document);var j,r,v=OLie4?d.all.tags('iframe'):
+OLns6?d.getElementsByTagName('iframe'):null;
+if(typeof d.images!='undefined'&&d.images[l])return d.images[l];
+if(typeof d.anchors!='undefined'&&d.anchors[l])return d.anchors[l];
+if(v)for(j=0;j<v.length;j++)if(v[j].name==l)return v[j];
+if(d.layers&&d.layers.length>0)for(j=0;j<d.layers.length;j++){
+r=OLgetRefByName(l,d.layers[j].document);
+if(r&&r.length>0)return r;else if(r)return [r,d.layers[j]];}
return null;
}
// Gets layer vs REFerence offsets
function OLgetRefOffsets(o){
-var mc=o3_refc.toUpperCase(),mp=o3_refp.toUpperCase(),mW=0,mH=0,pW=0,pH=0,off=[0,0];
+var c=o3_refc.toUpperCase(),p=o3_refp.toUpperCase(),W=0,H=0,pW=0,pH=0,of=[0,0];
pW=(OLbubblePI&&o3_bubble)?o3_width:OLns4?over.clip.width:over.offsetWidth;
pH=(OLbubblePI&&o3_bubble)?OLbubbleHt:OLns4?over.clip.height:over.offsetHeight;
-if((!OLop7)&&o.toString().indexOf('Image')!= -1){mW=o.width;mH=o.height;
-}else if((!OLop7)&&o.toString().indexOf('Anchor')!= -1){mc=o3_refc='UL';}else{
-mW=(OLns4)?o.clip.width:o.offsetWidth;mH=(OLns4)?o.clip.height:o.offsetHeight;}
-if(mc=='UL'){off=(mp=='UR')?[-pW,0]:(mp=='LL')?[0,-pH]:(mp=='LR')?[-pW,-pH]:[0,0];
-}else if(mc=='UR'){off=(mp=='UR')?[mW-pW,0]:(mp=='LL')?[mW,-pH]:(mp=='LR')?[mW-pW,-pH]:[mW,0];
-}else if(mc=='LL'){off=(mp=='UR')?[-pW,mH]:(mp=='LL')?[0,mH-pH]:(mp=='LR')?[-pW,mH-pH]:[0,mH];
-}else if(mc=='LR'){off=(mp=='UR')?[mW-pW,mH]:(mp=='LL')?[mW,mH-pH]:(mp=='LR')?[mW-pW,mH-pH]:
-[mW,mH];}
-return off;
+if((!OLop7)&&o.toString().indexOf('Image')!= -1){W=o.width;H=o.height;
+}else if((!OLop7)&&o.toString().indexOf('Anchor')!= -1){c=o3_refc='UL';}else{
+W=(OLns4)?o.clip.width:o.offsetWidth;H=(OLns4)?o.clip.height:o.offsetHeight;}
+if((OLns4||(OLns6&&OLgek))&&o.border){W+=2*parseInt(o.border);H+=2*parseInt(o.border);}
+if(c=='UL'){of=(p=='UR')?[-pW,0]:(p=='LL')?[0,-pH]:(p=='LR')?[-pW,-pH]:[0,0];
+}else if(c=='UR'){of=(p=='UR')?[W-pW,0]:(p=='LL')?[W,-pH]:(p=='LR')?[W-pW,-pH]:[W,0];
+}else if(c=='LL'){of=(p=='UR')?[-pW,H]:(p=='LL')?[0,H-pH]:(p=='LR')?[-pW,H-pH]:[0,H];
+}else if(c=='LR'){of=(p=='UR')?[W-pW,H]:(p=='LL')?[W,H-pH]:(p=='LR')?[W-pW,H-pH]:
+[W,H];}
+return of;
}
// Gets x or y location of object
@@ -494,11 +483,13 @@ return l; // Moves layer
function OLmouseMove(e){
var e=(e||event);
+OLcC=(OLovertwoPI&&over2&&over==over2?cClick2:cClick);
OLx=(e.pageX||e.clientX+OLfd().scrollLeft);OLy=(e.pageY||e.clientY+OLfd().scrollTop);
-if((OLallowmove&&over)&&(o3_frame==self||over==OLgetRefById())){
+if((OLallowmove&&over)&&(o3_frame==self||over==OLgetRefById()
+||(OLovertwoPI&&over2==over&&over==OLgetRefById('overDiv2')))){
OLplaceLayer();if(OLhidePI)OLhideUtil(0,1,1,0,0,0);}
-if(OLhover&&over&&o3_frame==self&&OLcursorOff())if(o3_offdelay<1)cClick();else
-{if(OLtimerid>0)clearTimeout(OLtimerid);OLtimerid=setTimeout("cClick()",o3_offdelay);}
+if(OLhover&&over&&o3_frame==self&&OLcursorOff())if(o3_offdelay<1)OLcC();else
+{if(OLtimerid>0)clearTimeout(OLtimerid);OLtimerid=setTimeout("OLcC()",o3_offdelay);}
}
// Capture mouse and chain other scripts.
@@ -515,12 +506,12 @@ OLdw.onmousemove=mh;if(OLns4)OLdw.captureEvents(Event.MOUSEMOVE); PARSING
*/
function OLparseTokens(pf,ar){
-var i,v,md= -1,par=(pf!='ol_'),e=eval,p=OLpar,q=OLparQuo,t=OLtoggle;OLudf=(par&&!ar.length?1:0);
+var i,v,md= -1,par=(pf!='ol_'),p=OLpar,q=OLparQuo,t=OLtoggle;OLudf=(par&&!ar.length?1:0);
for(i=0;i< ar.length;i++){if(md<0){if(typeof ar[i]=='number'){OLudf=(par?1:0);i--;}
else{switch(pf){case 'ol_':ol_text=ar[i];break;default:o3_text=ar[i];}}md=0;
}else{
-if(ar[i]==INARRAY){OLudf=0;e(pf+'text=ol_texts['+ar[++i]+']');continue;}
-if(ar[i]==CAPARRAY){e(pf+'cap=ol_caps['+ar[++i]+']');continue;}
+if(ar[i]==INARRAY){OLudf=0;eval(pf+'text=ol_texts['+ar[++i]+']');continue;}
+if(ar[i]==CAPARRAY){eval(pf+'cap=ol_caps['+ar[++i]+']');continue;}
if(ar[i]==CAPTION){q(ar[++i],pf+'cap');continue;}
if(Math.abs(ar[i])==STICKY){t(ar[i],pf+'sticky');continue;}
if(Math.abs(ar[i])==NOFOLLOW){t(ar[i],pf+'nofollow');continue;}
@@ -545,9 +536,9 @@ if(ar[i]==BORDER){p(ar[++i],pf+'border');continue;} if(ar[i]==BASE){p(ar[++i],pf+'base');continue;}
if(ar[i]==STATUS){q(ar[++i],pf+'status');continue;}
if(Math.abs(ar[i])==AUTOSTATUS){v=pf+'autostatus';
-e(v+'=('+ar[i]+'<0)?('+v+'==2?2:0):('+v+'==1?0:1)');continue;}
+eval(v+'=('+ar[i]+'<0)?('+v+'==2?2:0):('+v+'==1?0:1)');continue;}
if(Math.abs(ar[i])==AUTOSTATUSCAP){v=pf+'autostatus';
-e(v+'=('+ar[i]+'<0)?('+v+'==1?1:0):('+v+'==2?0:2)');continue;}
+eval(v+'=('+ar[i]+'<0)?('+v+'==1?1:0):('+v+'==2?0:2)');continue;}
if(ar[i]==CLOSETEXT){q(ar[++i],pf+'close');continue;}
if(ar[i]==SNAPX){p(ar[++i],pf+'snapx');continue;}
if(ar[i]==SNAPY){p(ar[++i],pf+'snapy');continue;}
@@ -594,6 +585,7 @@ if(ar[i]==CAPTIONFONTCLASS){q(ar[++i],pf+'captionfontclass');continue;} if(ar[i]==CLOSEFONTCLASS){q(ar[++i],pf+'closefontclass');continue;}
if(Math.abs(ar[i])==CAPBELOW){t(ar[i],pf+'capbelow');continue;}
if(ar[i]==LABEL){q(ar[++i],pf+'label');continue;}
+if(Math.abs(ar[i])==DECODE){t(ar[i],pf+'decode');continue;}
if(ar[i]==DONOTHING){continue;}
i=OLparseCmdLine(pf,i,ar);}}
if((OLfunctionPI)&&OLudf&&o3_function)o3_text=o3_function();
@@ -611,6 +603,14 @@ if(OLhasDims(o3_captionsize)){if(OLns4)o3_captionsize="2";}else if(!OLns4){i=parseInt(o3_captionsize);o3_captionsize=(i>0&&i<8)?OLpct[i]:OLpct[0];}
if(OLhasDims(o3_closesize)){if(OLns4)o3_closesize="2";}else
if(!OLns4){i=parseInt(o3_closesize);o3_closesize=(i>0&&i<8)?OLpct[i]:OLpct[0];}
+if(OLprintPI)OLprintDims();
+}
+function OLdecode(){
+var re=/%[0-9A-Fa-f]{2,}/,t=o3_text,c=o3_cap,u=unescape,d=!OLns4&&(!OLgek||OLgek>=20020826)
+&&typeof decodeURIComponent?decodeURIComponent:u;if(typeof(window.TypeError)=='function'){
+if(re.test(t)){eval(new Array('try{','o3_text=d(t);','}catch(e){','o3_text=u(t);',
+'}').join('\n'))};if(c&&re.test(c)){eval(new Array('try{','o3_cap=d(c);','}catch(e){',
+'o3_cap=u(c);','}').join('\n'))}}else{if(re.test(t))o3_text=u(t);if(c&&re.test(c))o3_cap=u(c);}
}
/*
@@ -625,6 +625,7 @@ if(OLns4){over.document.write(t);over.document.close(); domfrag=range.createContextualFragment(t);
while(over.hasChildNodes()){over.removeChild(over.lastChild);}
over.appendChild(domfrag);}
+if(OLprintPI)over.print=o3_print?t:null;
}
// Makes object visible
@@ -661,10 +662,9 @@ if(!c)o3_close=""; over.onmouseover=function(){OLhover=1;if(OLtimerid>0){clearTimeout(OLtimerid);OLtimerid=0;}}
}
function OLcursorOff(){
-if(OLovertwoPI&&over==over2)return false;
-var o=(OLns4?over:over.style),pHt=OLns4?over.clip.height:over.offsetHeight;
-var left=parseInt(o.left),top=parseInt(o.top);
-var right=left+o3_width,bottom=top+((OLbubblePI&&o3_bubble)?OLbubbleHt:pHt);
+var o=(OLns4?over:over.style),pHt=OLns4?over.clip.height:over.offsetHeight,
+left=parseInt(o.left),top=parseInt(o.top),
+right=left+o3_width,bottom=top+((OLbubblePI&&o3_bubble)?OLbubbleHt:pHt);
if(OLx<left||OLx>right||OLy<top||OLy>bottom)return true;
return false;
}
@@ -672,38 +672,26 @@ return false; /*
REGISTRATION
*/
-var OLcmdLine=null,OLrunTime=null;
function OLsetRunTimeVar(){
-if(OLrunTime&&OLrunTime.length)for(var k=0;k<OLrunTime.length;k++)OLrunTime[k]();
+if(OLrunTime.length)for(var k=0;k<OLrunTime.length;k++)OLrunTime[k]();
}
function OLparseCmdLine(pf,i,ar){
-if(OLcmdLine&&OLcmdLine.length){for(var k=0;k<OLcmdLine.length;k++){
+if(OLcmdLine.length){for(var k=0;k<OLcmdLine.length;k++){
var j=OLcmdLine[k](pf,i,ar);if(j>-1){i=j;break;}}}
return i;
}
-function OLisFunc(f){
-var r=1;
-if(typeof f=='object'){for(var i=0;i<f.length;i++){
-if(typeof f[i]=='function')continue;r=0;break;}
-}else if(typeof f!='function')r=0;
-return r;
-}
function OLregCmds(c){
if(typeof c!='string')return;
var pM=c.split(',');pMtr=pMtr.concat(pM);
for(var i=0;i<pM.length;i++)eval(pM[i].toUpperCase()+'='+pmCnt++);
}
function OLregRunTimeFunc(f){
-if(OLisFunc(f)){
-if(!OLrunTime)OLrunTime=new Array();
if(typeof f=='object')OLrunTime=OLrunTime.concat(f);
-else OLrunTime[OLrunTime.length++]=f;}
+else OLrunTime[OLrunTime.length++]=f;
}
function OLregCmdLineFunc(f){
-if(OLisFunc(f)){
-if(!OLcmdLine)OLcmdLine=new Array();
if(typeof f=='object')OLcmdLine=OLcmdLine.concat(f);
-else OLcmdLine[OLcmdLine.length++]=f;}
+else OLcmdLine[OLcmdLine.length++]=f;
}
OLloaded=1;
diff --git a/httemplate/elements/overlibmws_draggable.js b/httemplate/elements/overlibmws_draggable.js index 14e4a6062..0d25f842e 100644 --- a/httemplate/elements/overlibmws_draggable.js +++ b/httemplate/elements/overlibmws_draggable.js @@ -1,7 +1,7 @@ /*
overlibmws_draggable.js plug-in module - Copyright Foteos Macrides 2002=2005
For support of the DRAGGABLE feature.
- Initial: August 24, 2002 - Last Revised: January 12, 2005
+ Initial: August 24, 2002 - Last Revised: March 2, 2006
See the Change History and Command Reference for overlibmws via:
http://www.macridesweb.com/oltest/
@@ -37,7 +37,7 @@ function OLsetDrgCur(d){if(!OLns4)over.style.cursor=(d?'move':'auto');} function OLgrabEl(e){
var e=(e||event);
-var cKy=(OLns4?e.modifiers&Event.ALT_MASK:(!OLop7?e.altKey:e.ctrlKey));o3_dragging=1;
+var cKy=(OLns4?e.modifiers&Event.ALT_MASK:(e.altKey||(OLop7&&e.ctrlKey)));o3_dragging=1;
if(cKy){OLsetDrgCur(0);document.onmouseup=function(){OLsetDrgCur(1);o3_dragging=0;}
return(OLns4?routeEvent(e):true);}
OLx=(e.pageX||e.clientX+OLfd().scrollLeft);OLy=(e.pageY||e.clientY+OLfd().scrollTop);
diff --git a/httemplate/elements/phonenumber.html b/httemplate/elements/phonenumber.html index 1330ca109..6e16ec0ad 100644 --- a/httemplate/elements/phonenumber.html +++ b/httemplate/elements/phonenumber.html @@ -6,13 +6,7 @@ <SCRIPT TYPE="text/javascript" SRC="../elements/overlibmws.js"></SCRIPT> <SCRIPT TYPE="text/javascript" SRC="../elements/overlibmws_iframe.js"></SCRIPT> <SCRIPT TYPE="text/javascript" SRC="../elements/overlibmws_draggable.js"></SCRIPT> -<SCRIPT TYPE="text/javascript"> -function OLiframeContent(src, width, height, name) { - return ('<iframe src="'+src+'" width="'+width+'" height="'+height+'"' - +(name?' name="'+name+'" id="'+name+'"':'')+' scrolling="auto">' - +'<div>[iframe not supported]</div></iframe>'); -} -</SCRIPT> +<SCRIPT TYPE="text/javascript" SRC="../elements/iframecontentmws.js"></SCRIPT> <% if ( length($number) ) { %> <%= $number %> <% if ( $opt{'callable'} && $conf->config('vonage-username') ) { %> diff --git a/httemplate/elements/search-cust_main.html b/httemplate/elements/search-cust_main.html new file mode 100644 index 000000000..ca91b4027 --- /dev/null +++ b/httemplate/elements/search-cust_main.html @@ -0,0 +1,163 @@ +<% + my( %opt ) = @_; + $opt{'field_name'} ||= 'custnum'; + + my $cust_main = ''; + if ( $opt{'value'} ) { + $cust_main = qsearchs( + 'table' => 'cust_main', + 'hashref' => { 'custnum' => $opt{'value'} }, + 'extra_sql' => " AND ". $FS::CurrentUser::CurrentUser->agentnums_sql, + ); + } +%> + +<INPUT TYPE="hidden" NAME="<%= $opt{'field_name'} %>" VALUE="<%= $opt{'value'} %>"> + +<!-- some false laziness w/ misc/batch-cust_pay.html, though not as bad as i'd thought at first... --> + +<INPUT TYPE="text" NAME="<%= $opt{'field_name'} %>_search" ID="<%= $opt{'field_name'} %>_search" SIZE="32" VALUE="<%= $cust_main ? $cust_main->name : '(cust #, name or company)' %>" onFocus="clearhint_<%= $opt{'field_name'} %>_search(this);" onClick="clearhint_<%= $opt{'field_name'} %>_search(this);" onChange="smart_<%= $opt{'field_name'} %>_search(this);"> + +<SELECT NAME="<%= $opt{'field_name'} %>_select" ID="<%= $opt{'field_name'} %>_select" STYLE="color:#ff0000; display:none" onChange="select_<%= $opt{'field_name'} %>(this);"> +</SELECT> + +<%= include('/elements/xmlhttp.html', + 'url' => $p. 'misc/xmlhttp-cust_main-search.cgi', + 'subs' => [ 'smart_search' ], + ) +%> + +<SCRIPT TYPE="text/javascript"> + + function clearhint_<%= $opt{'field_name'} %>_search (what) { + + what.style.color = '#000000'; + + if ( what.value == '(cust #, name or company)' ) + what.value = ''; + + if ( what.value.indexOf('Customer not found: ') == 0 ) + what.value = what.value.substr(20); + + } + + function smart_<%= $opt{'field_name'} %>_search(what) { + + var customer = what.value; + + if ( customer == 'searching...' || customer == '' + || customer.indexOf('Customer not found: ') == 0 ) + return; + + if ( what.getAttribute('magic') == 'nosearch' ) { + what.setAttribute('magic', ''); + return; + } + + //what.value = 'searching...' + what.disabled = true; + what.style.color= '#000000'; + what.style.backgroundColor = '#dddddd'; + + var customer_select = document.getElementById('<%= $opt{'field_name'} %>_select'); + + //alert("search for customer " + customer); + + function <%= $opt{'field_name'} %>_search_update(customers) { + + //alert('customers returned: ' + customers); + + var customerArray = eval('(' + customers + ')'); + + what.disabled = false; + what.style.backgroundColor = '#ffffff'; + + if ( customerArray.length == 0 ) { + + what.form.<%= $opt{'field_name'} %>.value = ''; + + what.value = 'Customer not found: ' + what.value; + what.style.color = '#ff0000'; + + what.style.display = ''; + customer_select.style.display = 'none'; + + } else if ( customerArray.length == 1 ) { + + //alert('one customer found: ' + customerArray[0]); + + what.form.<%= $opt{'field_name'} %>.value = customerArray[0][0]; + what.value = customerArray[0][1]; + + what.style.display = ''; + customer_select.style.display = 'none'; + + } else { + + //alert('multiple customers found, have to create select dropdown'); + + //blank the current list + for ( var i = customer_select.length; i >= 0; i-- ) + customer_select.options[i] = null; + + opt(customer_select, '', 'Multiple customers match "' + customer + '" - select one', '#ff0000'); + + //add the multiple customers + for ( var s = 0; s < customerArray.length; s++ ) + opt(customer_select, customerArray[s][0], customerArray[s][1], '#000000'); + + opt(customer_select, 'cancel', '(Edit search string)', '#000000'); + + what.style.display = 'none'; + customer_select.style.display = ''; + + } + + } + + smart_search( customer, <%= $opt{'field_name'} %>_search_update ); + + + } + + function select_<%= $opt{'field_name'} %> (what) { + + var custnum = what.options[what.selectedIndex].value; + var customer = what.options[what.selectedIndex].text; + + var customer_obj = document.getElementById('<%= $opt{'field_name'} %>_search'); + + if ( custnum == '' ) { + //what.style.color = '#ff0000'; + + } else if ( custnum == 'cancel' ) { + + customer_obj.style.color = '#000000'; + + what.style.display = 'none'; + customer_obj.style.display = ''; + customer_obj.focus(); + + } else { + + what.form.<%= $opt{'field_name'} %>.value = custnum; + + customer_obj.value = customer; + customer_obj.style.color = '#000000'; + + what.style.display = 'none'; + customer_obj.style.display = ''; + + } + + } + + function opt(what,value,text,color) { + var optionName = new Option(text, value, false, false); + optionName.style.color = color; + var length = what.length; + what.options[length] = optionName; + } + +</SCRIPT> + diff --git a/httemplate/elements/select-agent.html b/httemplate/elements/select-agent.html index aa480a54b..009cc6e06 100644 --- a/httemplate/elements/select-agent.html +++ b/httemplate/elements/select-agent.html @@ -1,8 +1,7 @@ <% my( $agentnum, %opt ) = @_; - my %select_opt = (); - $select_opt{'records'} = $opt{'agents'} + $opt{'records'} = delete $opt{'agents'} if $opt{'agents'}; %><%= include( '/elements/select-table.html', @@ -11,6 +10,9 @@ 'value' => $agentnum, 'empty_label' => 'all', 'hashref' => { 'disabled' => '' }, - %select_opt, + 'extra_sql' => ' AND '. + $FS::CurrentUser::CurrentUser->agentnums_sql. + ' ORDER BY agent', + %opt, ) %> diff --git a/httemplate/elements/select-cust-fields.html b/httemplate/elements/select-cust-fields.html new file mode 100644 index 000000000..4d47fbe40 --- /dev/null +++ b/httemplate/elements/select-cust-fields.html @@ -0,0 +1,23 @@ +<% + my( $cust_fields, %opt ) = @_; + + use FS::ConfDefaults; + $opt{'avail_fields'} ||= [ FS::ConfDefaults->cust_fields_avail() ]; + + tie my %hash, 'Tie::IxHash', @{ $opt{'avail_fields'} }; + +%> + +<SELECT NAME="cust_fields"> + + <OPTION VALUE="">(configured default) + + <% + foreach my $value ( keys %hash ) { %> + + <OPTION VALUE="<%= $value %>"><%= $hash{$value} %> + + <% } %> + +</SELECT> + diff --git a/httemplate/elements/select-cust_pkg-status.html b/httemplate/elements/select-cust_pkg-status.html new file mode 100644 index 000000000..5da93fe79 --- /dev/null +++ b/httemplate/elements/select-cust_pkg-status.html @@ -0,0 +1,19 @@ +<% + my( $status, %opt ) = @_; + + $opt{'statuses'} ||= [ FS::cust_pkg->statuses() ]; # { disabled=>'' } ) + +%> + +<SELECT NAME="status"> + + <OPTION VALUE="">all + + <% foreach my $status ( @{ $opt{'statuses'} } ) { %> + + <OPTION VALUE="<%= $status %>"><%= $status %> + + <% } %> + +</SELECT> + diff --git a/httemplate/elements/select-part_referral.html b/httemplate/elements/select-part_referral.html new file mode 100644 index 000000000..deb87bd3b --- /dev/null +++ b/httemplate/elements/select-part_referral.html @@ -0,0 +1,17 @@ +<% + my( $refnum, %opt ) = @_; + + $opt{'records'} = delete $opt{'part_referrals'} + if $opt{'part_referrals'}; + +%><%= include( '/elements/select-table.html', + 'table' => 'part_referral', + 'name_col' => 'referral', + 'value' => $refnum, + 'empty_label' => 'Select advertising source', + 'hashref' => { 'disabled' => '' }, + 'extra_sql' => ' AND '. + FS::part_referral->all_part_referral(1), + %opt, + ) +%> diff --git a/httemplate/elements/select-table.html b/httemplate/elements/select-table.html index 96f0177fb..36eb4e211 100644 --- a/httemplate/elements/select-table.html +++ b/httemplate/elements/select-table.html @@ -8,10 +8,15 @@ # 'value' => 'current_value', # ##opt - # 'empty_label' => '', #better specify it though, the default might change - # 'hashref' => {}, - # 'records' => \@records, #instead of hashref - # 'pre_options' => [ 'value' => 'option' ], #before normal options + # 'empty_label' => '', #better specify it though, the default might change + # 'hashref' => {}, + # 'extra_sql' => '', + # 'records' => \@records, #instead of hashref + # 'pre_options' => [ 'value' => 'option' ], #before normal options + # 'element_name' => '', #HTML element name, defaults to the name of + # # the primary key column + # 'element_etc' => '', #additional attributes (i.e. "DISABLED") for the + # #<SELECT> element my( %opt ) = @_; @@ -25,14 +30,18 @@ if ( $opt{'records'} ) { @records = @{ $opt{'records'} }; } else { - @records = qsearch( $opt{'table'}, ( $opt{'hashref'} || {} ) ); + @records = qsearch( { + 'table' => $opt{'table'}, + 'hashref' => ( $opt{'hashref'} || {} ), + 'extra_sql' => ( $opt{'extra_sql'} || '' ), + }); } my @pre_options = $opt{'pre_options'} ? @{ $opt{'pre_options'} } : (); %> -<SELECT NAME="<%= $key %>"> +<SELECT NAME="<%= $opt{'element_name'} || $key %>" <%= $opt{'element_etc'} %>> <% while ( @pre_options ) { %> <OPTION VALUE="<%= shift(@pre_options) %>"><%= shift(@pre_options) %> diff --git a/httemplate/elements/table-grid.html b/httemplate/elements/table-grid.html index 80611f511..fd1cb9113 100644 --- a/httemplate/elements/table-grid.html +++ b/httemplate/elements/table-grid.html @@ -1,8 +1,20 @@ +<% + my %opt = @_; + $opt{cellspacing} ||= 0; + $opt{cellpadding} ||= 0; + +%> <STYLE TYPE="text/css"> + .grid table { border: solid; empty-cells: show } .grid TH { padding-left: 3px; padding-right: 3px; border: 1px solid #dddddd; border-bottom: dashed 1px black; border-right: none } .grid TD { padding-left: 3px; padding-right: 3px; empty-cells: show; border: 1px solid #cccccc; border-bottom: none; border-right: none } + +.inv table { border: none } +.inv TH { border: none } +.inv TD { border: none } + </STYLE> -<TABLE CLASS="grid" CELLSPACING=0 CELLPADDING=0 BORDER=1 BORDERCOLOR="#000000" STYLE="border: solid 1px black; empty-cells: show"> +<TABLE CLASS="grid" CELLSPACING=<%= $opt{cellspacing} %> CELLPADDING=<%= $opt{cellpadding} %> BORDER=1 BORDERCOLOR="#000000" STYLE="border: solid 1px black; empty-cells: show"> diff --git a/httemplate/elements/tr-select-agent.html b/httemplate/elements/tr-select-agent.html index 2227262b6..6158f6f47 100644 --- a/httemplate/elements/tr-select-agent.html +++ b/httemplate/elements/tr-select-agent.html @@ -3,9 +3,13 @@ my @agents; if ( $opt{'agents'} ) { - @agents = @{ $opt{'agents'} }; + #@agents = @{ $opt{'agents'} }; + #here is the agent virtualization + my $agentnums_href = $FS::CurrentUser::CurrentUser->agentnums_href; + @agents = grep $agentnums_href->{$_->agentnum}, @{ $opt{'agents'} }; + delete $opt{'agents'}; } else { - @agents = qsearch( 'agent', { disabled=>'' } ); + @agents = $FS::CurrentUser::CurrentUser->agents; } %> @@ -17,10 +21,11 @@ <% } else { %> <TR> - <TD ALIGN="right"><%= $opt{'label'} || 'Agent: ' %></TD> + <TD ALIGN="right"><%= $opt{'label'} || 'Agent' %></TD> <TD> <%= include( '/elements/select-agent.html', $agentnum, 'agents' => \@agents, + %opt, ) %> </TD> diff --git a/httemplate/elements/tr-select-cust-fields.html b/httemplate/elements/tr-select-cust-fields.html new file mode 100644 index 000000000..ca37e4276 --- /dev/null +++ b/httemplate/elements/tr-select-cust-fields.html @@ -0,0 +1,14 @@ +<% + my( $cust_fields, %opt ) = @_; + + use FS::ConfDefaults; + $opt{'avail_fields'} ||= [ FS::ConfDefaults->cust_fields_avail() ]; + +%> + +<TR> + <TD ALIGN="right"><%= $opt{'label'} || 'Customer fields' %></TD> + <TD> + <%= include( '/elements/select-cust-fields.html', $cust_fields, %opt ) %> + </TD> +</TR> diff --git a/httemplate/elements/tr-select-cust_pkg-status.html b/httemplate/elements/tr-select-cust_pkg-status.html new file mode 100644 index 000000000..17768517d --- /dev/null +++ b/httemplate/elements/tr-select-cust_pkg-status.html @@ -0,0 +1,13 @@ +<% + my( $status, %opt ) = @_; + + $opt{'statuses'} ||= [ FS::cust_pkg->statuses() ]; # { disabled=>'' } ) + +%> + +<TR> + <TD ALIGN="right"><%= $opt{'label'} || 'Status' %></TD> + <TD> + <%= include( '/elements/select-cust_pkg-status.html', $status, %opt ) %> + </TD> +</TR> diff --git a/httemplate/elements/tr-select-part_referral.html b/httemplate/elements/tr-select-part_referral.html new file mode 100644 index 000000000..0108388bc --- /dev/null +++ b/httemplate/elements/tr-select-part_referral.html @@ -0,0 +1,30 @@ +<% + my( $refnum, %opt ) = @_; + + $opt{'part_referrals'} ||= + [ FS::part_referral->all_part_referral( 1 ) ]; #1: include global + + my $r = qq!<font color="#ff0000">*</font> !; + +%> + +<% if ( scalar( @{$opt{'part_referrals'}} ) == 0 ) { + eidiot "You have not created any advertising sources. You must create at least one advertising source before adding a customer. Go to ". popurl(2). "browse/part_referral.html and create one or more advertising sources."; + } elsif ( scalar( @{$opt{'part_referrals'}} ) == 1 ) { +%> + + <INPUT TYPE="hidden" NAME="refnum" VALUE="<%= $opt{'part_referrals'}->[0]->refnum %>"> + +<% } else { %> + + <TR> + <TH ALIGN="right"><%=$r%>Advertising source</TH> + <TD> + <%= include( '/elements/select-part_referral.html', $refnum, + 'part_referrals' => $opt{'part_referrals'}, + ) + %> + </TD> + </TR> + +<% } %> diff --git a/httemplate/graph/cust_bill_pkg.cgi b/httemplate/graph/cust_bill_pkg.cgi index cb8225516..acd39b025 100644 --- a/httemplate/graph/cust_bill_pkg.cgi +++ b/httemplate/graph/cust_bill_pkg.cgi @@ -18,6 +18,7 @@ if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { } my $title = $sel_agent ? $sel_agent->agent.' ' : ''; +#false lazinessish w/search/cust_pkg.cgi my $classnum = 0; my @pkg_class = (); if ( $cgi->param('classnum') =~ /^(\d*)$/ ) { @@ -34,6 +35,7 @@ if ( $cgi->param('classnum') =~ /^(\d*)$/ ) { push @pkg_class, '(empty class)'; } } +#eslaf my $hue = 0; #my $hue_increment = 170; diff --git a/httemplate/misc/batch-cust_pay.html b/httemplate/misc/batch-cust_pay.html index 41537ee7e..ed093ac08 100644 --- a/httemplate/misc/batch-cust_pay.html +++ b/httemplate/misc/batch-cust_pay.html @@ -264,7 +264,7 @@ customer_input<%= $row %>.onclick = clearhint_customer; customer_input<%= $row %>.onchange = search_customer; </SCRIPT> - <SELECT NAME="cust_select<%= $row %>" ID="cust_select<%= $row %>" rownum="<%= $row %>" STYLE="color:#ff0000; display:none""> + <SELECT NAME="cust_select<%= $row %>" ID="cust_select<%= $row %>" rownum="<%= $row %>" STYLE="color:#ff0000; display:none"> </SELECT> <SCRIPT TYPE="text/javascript"> var customer_select<%= $row %> = document.getElementById("cust_select<%= $row %>"); diff --git a/httemplate/misc/cdr-import.html b/httemplate/misc/cdr-import.html index dc1733249..93de6e43f 100644 --- a/httemplate/misc/cdr-import.html +++ b/httemplate/misc/cdr-import.html @@ -2,8 +2,9 @@ <FORM ACTION="process/cdr-import.html" METHOD="POST" ENCTYPE="multipart/form-data"> Import a CSV file containing Call Detail Records (CDRs).<BR><BR> CDR Format: <SELECT NAME="format"> -<!-- <OPTION VALUE="asterisk">Asterisk</OPTION> --> +<OPTION VALUE="asterisk">Asterisk (untested)</OPTION> <OPTION VALUE="unitel">Unitel/RSLCOM</OPTION> +<OPTION VALUE="ams">AMS</OPTION> </SELECT><BR><BR> Filename: <INPUT TYPE="file" NAME="csvfile"><BR><BR> diff --git a/httemplate/misc/cust_main-import.cgi b/httemplate/misc/cust_main-import.cgi index 484855005..2ad4d95b4 100644 --- a/httemplate/misc/cust_main-import.cgi +++ b/httemplate/misc/cust_main-import.cgi @@ -1,51 +1,65 @@ -<!-- mason kludge --> <%= include("/elements/header.html",'Batch Customer Import') %> + <FORM ACTION="process/cust_main-import.cgi" METHOD="post" ENCTYPE="multipart/form-data"> -Import a CSV file containing customer records.<BR><BR> -Default file format is CSV, with the following field order: <i>cust_pkg.setup, dayphone, first, last, address1, address2, city, state, zip, comments</i><BR><BR> -<% - #false laziness with edit/cust_main.cgi - my @agents = qsearch( 'agent', {} ); - die "No agents created!" unless @agents; - my $agentnum = $agents[0]->agentnum; #default to first +Import a CSV file containing customer records. +<BR><BR> + +<!-- Simple file format is CSV, with the following field order: <i>cust_pkg.setup, dayphone, first, last, address1, address2, city, state, zip, comments</i> +<BR><BR> --> + +Extended file format is CSV, with the following field order: <i>agent_custid, refnum[1], last, first, address1, address2, city, state, zip, country, daytime, night, ship_last, ship_first, ship_address1, ship_address2, ship_city, ship_state, ship_zip, ship_country, payinfo, paycvv, paydate, invoicing_list, pkgpart, username, _password</i> +<BR><BR> - if ( scalar(@agents) == 1 ) { +[1] This field has special treatment upon import: If a string is passed instead +of an integer, the string is searched for and if necessary auto-created in the +target table. +<BR><BR> + +<%= &ntable("#cccccc") %> + +<%= include('/elements/tr-select-agent.html', '', #$agentnum, + 'label' => "<B>Agent</B>", + 'empty_label' => 'Select agent', + ) %> - <INPUT TYPE="hidden" NAME="agentnum" VALUE="<%= $agentnum %>"> -<% } else { %> - <BR><BR>Agent <SELECT NAME="agentnum" SIZE="1"> - <% foreach my $agent (sort { $a->agent cmp $b->agent } @agents) { %> - <OPTION VALUE="<%= $agent->agentnum %>" <%= " SELECTED"x($agent->agentnum==$agentnum) %>><%= $agent->agent %></OPTION> - <% } %> - </SELECT><BR><BR> -<% } %> - -<% - my @referrals = qsearch('part_referral',{}); - die "No advertising sources created!" unless @referrals; - my $refnum = $referrals[0]->refnum; #default to first - - if ( scalar(@referrals) == 1 ) { + +<TR> + <TH ALIGN="right">Format</TH> + <TD> + <SELECT NAME="format"> +<!-- <OPTION VALUE="simple">Simple --> + <OPTION VALUE="extended" SELECTED>Extended + </SELECT> + </TD> +</TR> + +<TR> + <TH ALIGN="right">CSV filename</TH> + <TD><INPUT TYPE="file" NAME="csvfile"></TD> +</TR> + +<% #include('/elements/tr-select-part_referral.html') %> - <INPUT TYPE="hidden" NAME="refnum" VALUE="<%= $refnum %>"> -<% } else { %> - <BR><BR>Advertising source <SELECT NAME="refnum" SIZE="1"> - <% foreach my $referral ( sort { $a->referral <=> $b->referral } @referrals) { %> - <OPTION VALUE="<%= $referral->refnum %>" <%= " SELECTED"x($referral->refnum==$refnum) %>><%= $referral->refnum %>: <%= $referral->referral %></OPTION> - <% } %> - </SELECT><BR><BR> -<% } %> - - First package: <SELECT NAME="pkgpart"><OPTION VALUE="">(none)</OPTION> -<% foreach my $part_pkg ( qsearch('part_pkg',{'disabled'=>'' }) ) { %> - <OPTION VALUE="<%= $part_pkg->pkgpart %>"><%= $part_pkg->pkg. ' - '. $part_pkg->comment %></OPTION> -<% } %> -</SELECT><BR><BR> - - CSV Filename: <INPUT TYPE="file" NAME="csvfile"><BR><BR> - <INPUT TYPE="submit" VALUE="Import"> - </FORM> - </BODY> -<HTML> + +<!-- +<TR> + <TH>First package</TH> + <TD> + <SELECT NAME="pkgpart"><OPTION VALUE="">(none)</OPTION> + <% foreach my $part_pkg ( qsearch('part_pkg',{'disabled'=>'' }) ) { %> + <OPTION VALUE="<%= $part_pkg->pkgpart %>"><%= $part_pkg->pkg. ' - '. $part_pkg->comment %></OPTION> + <% } %> + </SELECT> + </TD> +</TR> +--> + +</TABLE> +<BR><BR> + +<INPUT TYPE="submit" VALUE="Import"> +</FORM> + +<%= include('/elements/footer.html') %> diff --git a/httemplate/misc/process/cust_main-import.cgi b/httemplate/misc/process/cust_main-import.cgi index 371929a5e..aff6b39ef 100644 --- a/httemplate/misc/process/cust_main-import.cgi +++ b/httemplate/misc/process/cust_main-import.cgi @@ -10,8 +10,9 @@ agentnum => scalar($cgi->param('agentnum')), refnum => scalar($cgi->param('refnum')), pkgpart => scalar($cgi->param('pkgpart')), - 'fields' => [qw( cust_pkg.setup dayphone first last address1 address2 - city state zip comments )], + #'fields' => [qw( cust_pkg.setup dayphone first last address1 address2 + # city state zip comments )], + 'format' => scalar($cgi->param('format')), } ) : 'No file'; diff --git a/httemplate/search/cdr.html b/httemplate/search/cdr.html index ec847e41f..e3d6043e8 100644 --- a/httemplate/search/cdr.html +++ b/httemplate/search/cdr.html @@ -11,13 +11,15 @@ if ( $cgi->param('freesidestatus') eq 'NULL' ) { my $title = "Unprocessed $title"; $hashref->{'freesidestatus'} = ''; # Record.pm will take care of it - $count_query .= " AND ( freesidestatus IS NULL OR freesidestatus = '' )"; + #$count_query .= " AND ( freesidestatus IS NULL OR freesidestatus = '' )"; + $count_query .= " WHERE ( freesidestatus IS NULL OR freesidestatus = '' )"; } elsif ( $cgi->param('freesidestatus') =~ /^([\w ]+)$/ ) { my $title = "Processed $title"; $hashref->{'freesidestatus'} = $1; - $count_query .= " AND freesidestatus = '$1'"; + #$count_query .= " AND freesidestatus = '$1'"; + $count_query .= " WHERE freesidestatus = '$1'"; } diff --git a/httemplate/search/cust_bill.html b/httemplate/search/cust_bill.html index 2108653a8..79c05dc42 100755 --- a/httemplate/search/cust_bill.html +++ b/httemplate/search/cust_bill.html @@ -1,4 +1,9 @@ <% + + my $join_cust_main = 'LEFT JOIN cust_main USING ( custnum )'; + #here is the agent virtualization + my $agentnums_sql = $FS::CurrentUser::CurrentUser->agentnums_sql; + my( $count_query, $sql_query ); my( $count_addl ) = ( '' ); my( $distinct ) = ( '' ); @@ -6,11 +11,15 @@ my($agentnum) = ( '' ); my($open, $days) = ( '', '' ); if ( $cgi->param('invnum') =~ /^\s*(FS-)?(\d+)\s*$/ ) { - $count_query = "SELECT COUNT(*) FROM cust_bill WHERE invnum = $2"; + $count_query = + "SELECT COUNT(*) FROM cust_bill $join_cust_main". + " WHERE invnum = $2 AND $agentnums_sql"; #agent virtualization $sql_query = { 'table' => 'cust_bill', + 'addl_from' => $join_cust_main, 'hashref' => { 'invnum' => $2 }, #'select' => '*', + 'extra_sql' => " AND $agentnums_sql", #agent virtualization }; } else { #if ( $cgi->param('begin') || $cgi->param('end') @@ -28,7 +37,7 @@ $begin = str2time($1); push @where, "cust_bill._date >= $begin"; } - if ( $cgi->param('ending') + if ( $cgi->param('ending') && $cgi->param('ending') =~ /^([ 0-9\-\/]{0,10})$/ ) { $end = str2time($1) + 86399; push @where, "cust_bill._date < $end"; @@ -43,6 +52,13 @@ push @where, "cust_bill._date < $end"; } + if ( $cgi->param('invnum_min') =~ /^\s*(\d+)\s*$/ ) { + push @where, "cust_bill.invnum >= $1"; + } + if ( $cgi->param('invnum_max') =~ /^\s*(\d+)\s*$/ ) { + push @where, "cust_bill.invnum <= $1"; + } + if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { $agentnum = $1; push @where, "cust_main.agentnum = $agentnum"; @@ -68,10 +84,10 @@ push @where, "cust_bill._date < ". (time-86400*$days) if $days; } + #here is the agent virtualization + push @where, $agentnums_sql; my $extra_sql = scalar(@where) ? 'WHERE '. join(' AND ', @where) : ''; - my $addl_from = 'left join cust_main using ( custnum )'; - if ( $cgi->param('newest_percust') ) { $distinct = 'DISTINCT ON ( cust_bill.custnum )'; $orderby = 'ORDER BY cust_bill.custnum ASC, cust_bill._date DESC'; @@ -85,11 +101,11 @@ '$%.2f total outstanding balance', ]; } - $count_query .= " FROM cust_bill $addl_from $extra_sql"; + $count_query .= " FROM cust_bill $join_cust_main $extra_sql"; $sql_query = { 'table' => 'cust_bill', - 'addl_from' => $addl_from, + 'addl_from' => $join_cust_main, 'hashref' => {}, 'select' => "$distinct ". join(', ', 'cust_bill.*', diff --git a/httemplate/search/cust_credit.html b/httemplate/search/cust_credit.html index 279d682cd..eb78db5cd 100755 --- a/httemplate/search/cust_credit.html +++ b/httemplate/search/cust_credit.html @@ -36,9 +36,10 @@ push @search, " _date < $1 "; } - my $where = scalar(@search) - ? 'WHERE '. join(' AND ', @search) - : ''; + #here is the agent virtualization + push @search, $FS::CurrentUser::CurrentUser->agentnums_sql; + + my $where = 'WHERE '. join(' AND ', @search); my $count_query = 'SELECT COUNT(*), SUM(amount) '. 'FROM cust_credit LEFT JOIN cust_main USING ( custnum ) '. diff --git a/httemplate/search/cust_main.cgi b/httemplate/search/cust_main.cgi index 733e5dc15..f6841a099 100755 --- a/httemplate/search/cust_main.cgi +++ b/httemplate/search/cust_main.cgi @@ -109,6 +109,7 @@ if ( $cgi->param('browse') push @qual, FS::cust_main->cancel_sql if $cgi->param('cancelled'); push @qual, FS::cust_main->prospect_sql if $cgi->param('prospect'); push @qual, FS::cust_main->active_sql if $cgi->param('active'); + push @qual, FS::cust_main->inactive_sql if $cgi->param('inactive'); push @qual, FS::cust_main->susp_sql if $cgi->param('suspended'); #EWWWWWW @@ -117,6 +118,10 @@ if ( $cgi->param('browse') my $addl_qual = join(' AND ', @qual); + #here is the agent virtualization + $addl_qual .= ( $addl_qual ? ' AND ' : '' ). + $FS::CurrentUser::CurrentUser->agentnums_sql; + if ( $addl_qual ) { $qual .= ' AND ' if $qual; $qual .= $addl_qual; @@ -322,32 +327,43 @@ END print "<BR><BR>". $pager. include('/elements/table-grid.html'). <<END; <TR> - <TH></TH> - <TH>(bill) name</TH> - <TH>company</TH> + <TH CLASS="grid" BGCOLOR="#cccccc"></TH> + <TH CLASS="grid" BGCOLOR="#cccccc">(bill) name</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">company</TH> END if ( defined dbdef->table('cust_main')->column('ship_last') ) { print <<END; - <TH>(service) name</TH> - <TH>company</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">(service) name</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">company</TH> END } foreach my $addl_header ( @addl_headers ) { - print "<TH>$addl_header</TH>"; + print '<TH CLASS="grid" BGCOLOR="#cccccc">'. "$addl_header</TH>"; } print <<END; - <TH>Packages</TH> - <TH COLSPAN=2>Services</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Packages</TH> + <TH CLASS="grid" BGCOLOR="#cccccc" COLSPAN=2>Services</TH> </TR> END + my $bgcolor1 = '#eeeeee'; + my $bgcolor2 = '#ffffff'; + my $bgcolor; + my(%saw,$cust_main); foreach $cust_main ( sort $sortby grep(!$saw{$_->custnum}++, @cust_main) ) { + + if ( $bgcolor eq $bgcolor1 ) { + $bgcolor = $bgcolor2; + } else { + $bgcolor = $bgcolor1; + } + my($custnum,$last,$first,$company)=( $cust_main->custnum, $cust_main->getfield('last'), @@ -377,9 +393,9 @@ END %> <TR> - <TD ROWSPAN=<%= $rowspan || 1 %>><A HREF="<%= $view %>"><FONT SIZE=-1><%= $custnum %></FONT></A></TD> - <TD ROWSPAN=<%= $rowspan || 1 %>><A HREF="<%= $view %>"><FONT SIZE=-1><%= "$last, $first" %></FONT></A></TD> - <TD ROWSPAN=<%= $rowspan || 1 %>><%= $pcompany %></TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>" ROWSPAN=<%= $rowspan || 1 %>><A HREF="<%= $view %>"><FONT SIZE=-1><%= $custnum %></FONT></A></TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>" ROWSPAN=<%= $rowspan || 1 %>><A HREF="<%= $view %>"><FONT SIZE=-1><%= "$last, $first" %></FONT></A></TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>" ROWSPAN=<%= $rowspan || 1 %>><%= $pcompany %></TD> <% if ( defined dbdef->table('cust_main')->column('ship_last') ) { @@ -393,55 +409,85 @@ END : '<FONT SIZE=-1> </FONT>'; %> - <TD ROWSPAN=<%= $rowspan || 1 %>><A HREF="<%= $view %>"><FONT SIZE=-1><%= "$ship_last, $ship_first" %></FONT></A></TD> - <TD ROWSPAN=<%= $rowspan || 1 %>><%= $pship_company %></A></TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>" ROWSPAN=<%= $rowspan || 1 %>><A HREF="<%= $view %>"><FONT SIZE=-1><%= "$ship_last, $ship_first" %></FONT></A></TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>" ROWSPAN=<%= $rowspan || 1 %>><%= $pship_company %></A></TD> <% } foreach my $addl_col ( @addl_cols ) { %> - <TD ROWSPAN=<%= $rowspan || 1 %> ALIGN=right><FONT SIZE=-1> - - <% if ( $addl_col eq 'tickets' ) { - if ( @custom_priorities ) { - print &itable('', 0); - 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; - - print '<TR>'. - " <TD ALIGN=right><FONT SIZE=-1>$ahref$num</A></FONT></TD>". - "<TD ALIGN=left><FONT SIZE=-1>$ahref". - ( $priority || '<i>(none)</i>' ). - "</A></FONT></TD></TR>"; - - } - print '<TR><TD BGCOLOR="#000000" COLSPAN=2></TD></TR>'. - '<TR><TD ALIGN=right><FONT SIZE=-1>'; - } - - my $ahref = ''; - $ahref = '<A HREF="'. - FS::TicketSystem->href_customer_tickets($custnum). - '">' - if $cust_main->get($addl_col); - - print $ahref. $cust_main->get($addl_col). '</A>'; - print "</FONT></TD><TD ALIGN=left>". - "<FONT SIZE=-1>${ahref}Total</A><FONT>". - "</TD></TR></TABLE>" - if @custom_priorities; + <% if ( $addl_col eq 'tickets' ) { %> - } else { - print $cust_main->get($addl_col); + <% if ( @custom_priorities ) { %> + + <TD CLASS="inv" BGCOLOR="<%= $bgcolor %>" ROWSPAN=<%= $rowspan || 1 %> ALIGN=right><FONT SIZE=-1> + + <TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0> + + <% 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; + %> + + <TR> + <TD ALIGN=right> + <FONT SIZE=-1><%= $ahref.$num %></A></FONT> + </TD> + <TD ALIGN=left> + <FONT SIZE=-1><%= $ahref %><%= $priority || '<i>(none)</i>' %></A></FONT> + </TD> + </TR> + + <% } %> + + <TR> + <TH ALIGN=right STYLE="border-top: dashed 1px black"> + <FONT SIZE=-1> + + <% } else { %> + + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>" ROWSPAN=<%= $rowspan || 1 %> ALIGN=right><FONT SIZE=-1> + + <% } %> + + <% + my $ahref = ''; + $ahref = '<A HREF="'. + FS::TicketSystem->href_customer_tickets($custnum). + '">' + if $cust_main->get($addl_col); + %> + + <%= $ahref %><%= $cust_main->get($addl_col) %></A> + + <% if ( @custom_priorities ) { %> + + </FONT></TH> + <TH ALIGN=left STYLE="border-top: dashed 1px black"> + <FONT SIZE=-1><%= ${ahref} %>Total</A><FONT> + </TH> + </TR> + </TABLE> + + <% } %> + + </FONT></TD> + + <% } else { %> + + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>" ROWSPAN=<%= $rowspan || 1 %> ALIGN=right><FONT SIZE=-1> + <%= $cust_main->get($addl_col) %> + </FONT></TD> + +<% } - print "</FONT></TD>"; } my($n1)=''; @@ -457,19 +503,30 @@ END #my(@cust_svc) = qsearch( 'cust_svc', { 'pkgnum' => $_->pkgnum } ); my $rowspan = scalar(@cust_svc) || 1; - print $n1, qq!<TD ROWSPAN=$rowspan><A HREF="$pkgview"><FONT SIZE=-1>$pkg - $comment</FONT></A></TD>!; + print $n1, qq!<TD CLASS="grid" BGCOLOR="$bgcolor" ROWSPAN=$rowspan><A HREF="$pkgview"><FONT SIZE=-1>$pkg - $comment</FONT></A></TD>!; + my($n2)=''; foreach my $cust_svc ( @cust_svc ) { my($label, $value, $svcdb) = $cust_svc->label; my($svcnum) = $cust_svc->svcnum; my($sview) = $p.'view'; - print $n2,qq!<TD><A HREF="$sview/$svcdb.cgi?$svcnum"><FONT SIZE=-1>$label</FONT></A></TD>!, - qq!<TD><A HREF="$sview/$svcdb.cgi?$svcnum"><FONT SIZE=-1>$value</FONT></A></TD>!; + print $n2,qq!<TD CLASS="grid" BGCOLOR="$bgcolor" ><A HREF="$sview/$svcdb.cgi?$svcnum"><FONT SIZE=-1>$label</FONT></A></TD>!, + qq!<TD CLASS="grid" BGCOLOR="$bgcolor" ><A HREF="$sview/$svcdb.cgi?$svcnum"><FONT SIZE=-1>$value</FONT></A></TD>!; $n2="</TR><TR>"; } + + unless ( @cust_svc ) { + print qq!<TD CLASS="grid" BGCOLOR="$bgcolor" COLSPAN=2> </TD>!; + } + #print qq!</TR><TR>\n!; $n1="</TR><TR>"; } + + unless ( @{$all_pkgs{$custnum}} ) { + print qq!<TD CLASS="grid" BGCOLOR="$bgcolor" COLSPAN=3> </TD>!; + } + print "</TR>"; } diff --git a/httemplate/search/cust_pay.cgi b/httemplate/search/cust_pay.cgi index 99ffc3d20..0247b0b0d 100755 --- a/httemplate/search/cust_pay.cgi +++ b/httemplate/search/cust_pay.cgi @@ -96,10 +96,10 @@ die "unknown search magic: ". $cgi->param('magic'); } - my $search = ''; - if ( @search ) { - $search = ' WHERE '. join(' AND ', @search); - } + #here is the agent virtualization + push @search, $FS::CurrentUser::CurrentUser->agentnums_sql; + + my $search = ' WHERE '. join(' AND ', @search); $count_query = "SELECT COUNT(*), SUM(paid) ". "FROM cust_pay LEFT JOIN cust_main USING ( custnum )". @@ -125,14 +125,16 @@ $cgi->param('payby') =~ /^(\w+)$/ or die "illegal payby"; my $payby = $1; - $count_query = "SELECT COUNT(*), SUM(paid) FROM cust_pay ". - "WHERE payinfo = '$payinfo' AND payby = '$payby'"; + $count_query = "SELECT COUNT(*), SUM(paid) FROM cust_pay". + " WHERE payinfo = '$payinfo' AND payby = '$payby'". + " AND ". $FS::CurrentUser::CurrentUser->agentnums_sql; $sql_query = { 'table' => 'cust_pay', 'hashref' => { 'payinfo' => $payinfo, 'payby' => $payby }, - 'extra_sql' => "ORDER BY _date", + 'extra_sql' => $FS::CurrentUser::CurrentUser->agentnums_sql. + " ORDER BY _date", }; } diff --git a/httemplate/search/cust_pkg.cgi b/httemplate/search/cust_pkg.cgi index a2fb89c12..614e9b509 100755 --- a/httemplate/search/cust_pkg.cgi +++ b/httemplate/search/cust_pkg.cgi @@ -1,19 +1,89 @@ <% -my %part_pkg = map { $_->pkgpart => $_ } qsearch('part_pkg', {}); +# my %part_pkg = map { $_->pkgpart => $_ } qsearch('part_pkg', {}); my($query) = $cgi->keywords; -my $orderby; -my @where; -my $cjoin = ''; +my @where = (); + +## +# parse agent +## if ( $cgi->param('agentnum') =~ /^(\d+)$/ and $1 ) { - $cjoin = "LEFT JOIN cust_main USING ( custnum )"; push @where, "agentnum = $1"; } +## +# parse status +## + +if ( $cgi->param('magic') eq 'active' + || $cgi->param('status') eq 'active' ) { + + push @where, FS::cust_pkg->active_sql(); + +} elsif ( $cgi->param('magic') eq 'inactive' + || $cgi->param('status') eq 'inactive' ) { + + push @where, FS::cust_pkg->inactive_sql(); + + +} elsif ( $cgi->param('magic') eq 'suspended' + || $cgi->param('status') eq 'suspended' ) { + + push @where, FS::cust_pkg->suspended_sql(); + +} elsif ( $cgi->param('magic') =~ /^cancell?ed$/ + || $cgi->param('status') =~ /^cancell?ed$/ ) { + + push @where, FS::cust_pkg->cancelled_sql(); + +} elsif ( $cgi->param('status') =~ /^(one-time charge|inactive)$/ ) { + + push @where, FS::cust_pkg->inactive_sql(); + +} + +### +# parse package class +### + +#false lazinessish w/graph/cust_bill_pkg.cgi +my $classnum = 0; +my @pkg_class = (); +if ( exists($cgi->Vars->{'classnum'}) + && $cgi->param('classnum') =~ /^(\d*)$/ + ) +{ + $classnum = $1; + if ( $classnum ) { #a specific class + push @where, "classnum = $classnum"; + + #@pkg_class = ( qsearchs('pkg_class', { 'classnum' => $classnum } ) ); + #die "classnum $classnum not found!" unless $pkg_class[0]; + #$title .= $pkg_class[0]->classname.' '; + + } elsif ( $classnum eq '' ) { #the empty class + + push @where, "classnum IS NULL"; + #$title .= 'Empty class '; + #@pkg_class = ( '(empty class)' ); + } elsif ( $classnum eq '0' ) { + #@pkg_class = qsearch('pkg_class', {} ); # { 'disabled' => '' } ); + #push @pkg_class, '(empty class)'; + } else { + die "illegal classnum"; + } +} +#eslaf + +### +# parse magic, legacy, etc. +### + +my $orderby; if ( $cgi->param('magic') && $cgi->param('magic') eq 'bill' ) { $orderby = 'ORDER BY bill'; @@ -23,40 +93,17 @@ if ( $cgi->param('magic') && $cgi->param('magic') eq 'bill' ) { #"bill <= $ending", "CASE WHEN bill IS NULL THEN 0 ELSE bill END >= $beginning ", "CASE WHEN bill IS NULL THEN 0 ELSE bill END <= $ending", - '( cancel IS NULL OR cancel = 0 )'; + #'( cancel IS NULL OR cancel = 0 )' + ; } else { if ( $cgi->param('magic') && - $cgi->param('magic') =~ /^(active|suspended|cancell?ed)$/ + $cgi->param('magic') =~ /^(active|inactive|suspended|cancell?ed)$/ ) { $orderby = 'ORDER BY pkgnum'; - if ( $cgi->param('magic') eq 'active' ) { - - #push @where, - # '( susp IS NULL OR susp = 0 )', - # '( cancel IS NULL OR cancel = 0)'; - push @where, FS::cust_pkg->active_sql(); - - } elsif ( $cgi->param('magic') eq 'suspended' ) { - - push @where, - 'susp IS NOT NULL', - 'susp != 0', - '( cancel IS NULL OR cancel = 0)'; - - } elsif ( $cgi->param('magic') =~ /^cancell?ed$/ ) { - - push @where, - 'cancel IS NOT NULL', - 'cancel != 0'; - - } else { - die "guru meditation #420"; - } - if ( $cgi->param('pkgpart') =~ /^(\d+)$/ ) { push @where, "pkgpart = $1"; } @@ -84,21 +131,35 @@ if ( $cgi->param('magic') && $cgi->param('magic') eq 'bill' ) { } +## +# setup queries, links, subs, etc. for the search +## + +# here is the agent virtualization +push @where, $FS::CurrentUser::CurrentUser->agentnums_sql; + my $extra_sql = scalar(@where) ? ' WHERE '. join(' AND ', @where) : ''; -my $count_query = "SELECT COUNT(*) FROM cust_pkg $cjoin $extra_sql"; +my $addl_from = 'LEFT JOIN cust_main USING ( custnum ) '. + 'LEFT JOIN part_pkg USING ( pkgpart ) '. + 'LEFT JOIN pkg_class USING ( classnum ) '; + +my $count_query = "SELECT COUNT(*) FROM cust_pkg $addl_from $extra_sql"; my $sql_query = { 'table' => 'cust_pkg', 'hashref' => {}, 'select' => join(', ', 'cust_pkg.*', + ( map "part_pkg.$_", qw( pkg freq ) ), + 'pkg_class.classname', 'cust_main.custnum as cust_main_custnum', - FS::UI::Web::cust_sql_fields(), + FS::UI::Web::cust_sql_fields( + $cgi->param('cust_fields') + ), ), 'extra_sql' => "$extra_sql $orderby", - 'addl_from' => ' LEFT JOIN cust_main USING ( custnum ) ', - #' LEFT JOIN part_pkg USING ( pkgpart ) ' + 'addl_from' => $addl_from, }; my $link = sub { @@ -138,6 +199,10 @@ sub time_or_blank { }; } +### +# and finally, include the search template +### + %><%= include( 'elements/search.html', 'title' => 'Package Search Results', 'name' => 'packages', @@ -146,6 +211,7 @@ sub time_or_blank { #'redirect' => $link, 'header' => [ '#', 'Package', + 'Class', 'Status', 'Freq.', 'Setup', @@ -154,18 +220,25 @@ sub time_or_blank { 'Susp.', 'Expire', 'Cancel', - FS::UI::Web::cust_header(), + FS::UI::Web::cust_header( + $cgi->param('cust_fields') + ), 'Services', ], 'fields' => [ 'pkgnum', - sub { my $part_pkg = $part_pkg{shift->pkgpart}; - $part_pkg->pkg; # ' - '. $part_pkg->comment; + sub { #my $part_pkg = $part_pkg{shift->pkgpart}; + #$part_pkg->pkg; # ' - '. $part_pkg->comment; + $_[0]->pkg; # ' - '. $_[0]->comment; }, + 'classname', sub { ucfirst(shift->status); }, sub { #shift->part_pkg->freq_pretty; - my $part_pkg = $part_pkg{shift->pkgpart}; - $part_pkg->freq_pretty; + + #my $part_pkg = $part_pkg{shift->pkgpart}; + #$part_pkg->freq_pretty; + + FS::part_pkg::freq_pretty(shift); }, #sub { time2str('%b %d %Y', shift->setup); }, @@ -204,6 +277,7 @@ sub time_or_blank { 'color' => [ '', '', + '', sub { shift->statuscolor; }, '', '', @@ -212,12 +286,16 @@ sub time_or_blank { '', '', '', - ( map { '' } FS::UI::Web::cust_header() ), + ( map { '' } + FS::UI::Web::cust_header( + $cgi->param('cust_fields') + ) + ), '', ], - 'style' => [ '', '', 'b' ], - 'size' => [ '', '', '-1', ], - 'align' => 'rlclrrrrrr', + 'style' => [ '', '', '', 'b' ], + 'size' => [ '', '', '', '-1', ], + 'align' => 'rllclrrrrrr', 'links' => [ $link, $link, @@ -229,7 +307,12 @@ sub time_or_blank { '', '', '', - ( map { $clink } FS::UI::Web::cust_header() ), + '', + ( map { $clink } + FS::UI::Web::cust_header( + $cgi->param('cust_fields') + ) + ), '', ], ) diff --git a/httemplate/search/cust_pkg_report.cgi b/httemplate/search/cust_pkg_report.cgi deleted file mode 100755 index d9aada5f4..000000000 --- a/httemplate/search/cust_pkg_report.cgi +++ /dev/null @@ -1,22 +0,0 @@ -<%= include('/elements/header.html', 'Packages' ) %> - -<FORM ACTION="cust_pkg.cgi" METHOD="GET"> -<INPUT TYPE="hidden" NAME="magic" VALUE="bill"> - -Return packages with next bill date: -<BR><BR> - - <TABLE> - <%= include( '/elements/tr-input-beginning_ending.html' ) %> - <%= include( '/elements/tr-select-agent.html', - $cgi->param('agentnum'), - ) - %> - </TABLE> - -<BR> -<INPUT TYPE="submit" VALUE="Get Report"> - -</FORM> - -<%= include('/elements/footer.html') %> diff --git a/httemplate/search/elements/search.html b/httemplate/search/elements/search.html index 6cf574164..3e689eba1 100644 --- a/httemplate/search/elements/search.html +++ b/httemplate/search/elements/search.html @@ -380,8 +380,7 @@ my $tableref = $_; - '<TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0'. - ' STYLE="border:none">'. + '<TABLE CLASS="inv" CELLSPACING=0 CELLPADDING=0>'. join('', map { @@ -393,7 +392,7 @@ my $element = $_; - '<TD STYLE="border:none"'. + '<TD'. ( $element->{'align'} ? ' ALIGN="'. $element->{'align'}. '"' : '' @@ -432,6 +431,8 @@ ) { + my $class = ( $field =~ /^<TABLE/i ) ? 'inv' : 'grid'; + my $align = $aligns ? shift @$aligns : ''; $align = " ALIGN=$align" if $align; @@ -471,7 +472,7 @@ } %> - <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"<%= $align %>><%= $font %><%= $a %><%= $s %><%= $field %><%= $es %><%= $a ? '</A>' : '' %><%= $font ? '</FONT>' : '' %></TD> + <TD CLASS="<%= $class %>" BGCOLOR="<%= $bgcolor %>"<%= $align %>><%= $font %><%= $a %><%= $s %><%= $field %><%= $es %><%= $a ? '</A>' : '' %><%= $font ? '</FONT>' : '' %></TD> <% } %> <% } else { %> <% foreach ( @$row ) { %> diff --git a/httemplate/search/inventory_item.html b/httemplate/search/inventory_item.html index bd74f5619..7049c8841 100644 --- a/httemplate/search/inventory_item.html +++ b/httemplate/search/inventory_item.html @@ -24,7 +24,30 @@ if ( $cgi->param('avail') ) { my $count_query = "SELECT COUNT(*) FROM inventory_item WHERE classnum = $classnum $extra_sql"; +my $link = sub { + my $inventory_item = shift; + if ( $inventory_item->svcnum ) { + [ "${p}view/svc_acct.cgi?", 'svcnum' ]; + } else { + ''; + } +}; +my $link_cust = sub { + my $inventory_item = shift; + if ( $inventory_item->custnum ) { + [ "${p}view/cust_main.cgi?", 'custnum' ]; + } else { + ''; + } +}; + +my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '. + ' LEFT JOIN part_svc USING ( svcpart ) '. + ' LEFT JOIN cust_pkg USING ( pkgnum ) '. + ' LEFT JOIN cust_main USING ( custnum ) '; + %><%= include( 'elements/search.html', + 'title' => $title, #less lame to use Lingua:: something to pluralize @@ -33,19 +56,52 @@ my $count_query = 'query' => { 'table' => 'inventory_item', 'hashref' => { 'classnum' => $classnum }, + 'select' => join(', ', + 'inventory_item.*', + 'cust_main.custnum', + FS::UI::Web::cust_sql_fields(), + ), 'extra_sql' => $extra_sql, + 'addl_from' => $addl_from, }, 'count_query' => $count_query, - # XXX proper full service/customer link ala svc_acct - 'header' => [ '#', $inventory_class->classname, 'svcnum' ], + 'header' => [ + '#', + $inventory_class->classname, + 'Service', + FS::UI::Web::cust_header(), + ], 'fields' => [ 'itemnum', 'item', - 'svcnum', #XXX proper full service customer link ala svc_acct + #'svcnum', #XXX proper full service customer link ala svc_acct # "unallocated" ? "available" ? + sub { + #this could be way more efficient with a mixin + # like cust_main_Mixin that let us all all the methods + # on data we already have... + my $inventory_item = shift; + my $cust_svc = $inventory_item->cust_svc; + if ( $cust_svc ) { + my($label, $value) = $cust_svc->label; + "$label: $value"; + } else { + '(available)'; + } + }, + + \&FS::UI::Web::cust_fields, + + ], + + 'links' => [ + '', + '', + $link, + ( map { $link_cust } FS::UI::Web::cust_header() ), ], ) diff --git a/httemplate/search/report_cdr.html b/httemplate/search/report_cdr.html index 924e28bd7..6febe6c4a 100644 --- a/httemplate/search/report_cdr.html +++ b/httemplate/search/report_cdr.html @@ -4,7 +4,7 @@ Status: <SELECT NAME="freesidestatus"> <OPTION VALUE="">(all) <OPTION VALUE="NULL">unprocessed - <OPTION VALUE="done"">processed + <OPTION VALUE="done">processed </SELECT><BR> <INPUT TYPE="submit" VALUE="Search Call Detail Records"> diff --git a/httemplate/search/report_cust_pkg.html b/httemplate/search/report_cust_pkg.html new file mode 100755 index 000000000..98e91217f --- /dev/null +++ b/httemplate/search/report_cust_pkg.html @@ -0,0 +1,47 @@ +<%= include('/elements/header.html', 'Package Report' ) %> + +<FORM ACTION="cust_pkg.cgi" METHOD="GET"> +<INPUT TYPE="hidden" NAME="magic" VALUE="bill"> + + <TABLE BGCOLOR="#cccccc" CELLSPACING=0> + + <TR> + <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left"><FONT SIZE="+1">Search options</FONT></TH> + </TR> + <%= include( '/elements/tr-select-agent.html', + $cgi->param('agentnum'), + ) + %> + <%= include( '/elements/tr-select-cust_pkg-status.html' ) %> + <%= include( '/elements/tr-select-pkg_class.html', '', + 'pre_options' => [ '0' => 'all' ], + 'empty_label' => '(empty class)', + ) + %> + <% #include( '/elements/tr-selectmultiple-part_pkg.html' ) %> + <TR> + <TD ALIGN="right" VALIGN="center">Next bill date</TD> + <TD> + <TABLE> + <%= include( '/elements/tr-input-beginning_ending.html' ) %> + </TABLE> + </TD> + </TR> + + <TR> + <TH BGCOLOR="#e8e8e8" COLSPAN=2> </TH> + </TR> + + <TR> + <TH BGCOLOR="#e8e8e8" COLSPAN=2 ALIGN="left"><FONT SIZE="+1">Display options</FONT></TH> + </TR> + <%= include( '/elements/tr-select-cust-fields.html' ) %> + + </TABLE> + +<BR> +<INPUT TYPE="submit" VALUE="Get Report"> + +</FORM> + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/report_receivables.cgi b/httemplate/search/report_receivables.cgi index ac94e1a5c..3052ea93c 100755 --- a/httemplate/search/report_receivables.cgi +++ b/httemplate/search/report_receivables.cgi @@ -62,26 +62,19 @@ END my $owed_cols = join(',', map owed( @$_, 'cust'=>1 ), @ranges ); - my $recurring = <<END; - '0' != ( select freq from part_pkg - where cust_pkg.pkgpart = part_pkg.pkgpart ) -END - - my $packages_cols = <<END; + my $select_count_pkgs = FS::cust_main->select_count_pkgs_sql; - ( select count(*) from cust_pkg - where cust_main.custnum = cust_pkg.custnum - and $recurring - and ( cancel = 0 or cancel is null ) - ) as uncancelled_pkgs, - - ( select count(*) from cust_pkg - where cust_main.custnum = cust_pkg.custnum - and $recurring - and ( cancel = 0 or cancel is null ) - and ( susp = 0 or susp is null ) - ) as active_pkgs + my $active_sql = FS::cust_pkg->active_sql; + my $inactive_sql = FS::cust_pkg->inactive_sql; + my $suspended_sql = FS::cust_pkg->inactive_sql; + my $cancelled_sql = FS::cust_pkg->inactive_sql; + my $packages_cols = <<END; + ( $select_count_pkgs ) AS num_pkgs_sql, + ( $select_count_pkgs AND $active_sql ) AS active_pkgs, + ( $select_count_pkgs AND $inactive_sql ) AS inactive_pkgs, + ( $select_count_pkgs AND $suspended_sql ) AS suspended_pkgs, + ( $select_count_pkgs AND $cancelled_sql ) AS cancelled_pkgs END my $where = "where ". owed(0, 0, 'cust'=>1, 'noas'=>1). " > 0"; @@ -92,6 +85,9 @@ END $where .= " AND agentnum = '$agentnum' "; } + #here is the agent virtualization + $where .= ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql; + my $count_sql = "select count(*) from cust_main $where"; my $sql_query = { @@ -116,6 +112,27 @@ END my $clink = [ "${p}view/cust_main.cgi?", 'custnum' ]; + my $status_statuscol = sub { + #conceptual false laziness with cust_main::status... + my $row = shift; + + my $status = 'unknown'; + if ( $row->num_pkgs_sql == 0 ) { + $status = 'prospect'; + } elsif ( $row->active_pkgs > 0 ) { + $status = 'active'; + } elsif ( $row->inactive_pkgs > 0 ) { + $status = 'inactive'; + } elsif ( $row->suspended_pkgs > 0 ) { + $status = 'suspended'; + } elsif ( $row->cancelled_pkgs > 0 ) { + $status = 'cancelled' + } + + ( ucfirst($status), $FS::cust_main::statuscolor{$status} ); + }; + + %><%= include( 'elements/search.html', 'title' => 'Accounts Receivable Aging Summary', 'name' => 'customers', @@ -153,20 +170,7 @@ END ], 'fields' => [ \&FS::UI::Web::cust_fields, - sub { - my $row = shift; - my $status = 'Cancelled'; - my $statuscol = 'FF0000'; - if ( $row->uncancelled_pkgs ) { - $status = 'Suspended'; - $statuscol = 'FF9900'; - if ( $row->active_pkgs ) { - $status = 'Active'; - $statuscol = '00CC00'; - } - } - $status; - }, + sub { ( &{$status_statuscol}(shift) )[0] }, #sub { ucfirst(shift->status) }, sub { sprintf( $money_char.'%.2f', shift->get('owed_0_30') ) }, @@ -199,20 +203,7 @@ END 'b', '', '', '', '', 'b', ], 'color' => [ ( map '', FS::UI::Web::cust_header() ), - sub { - my $row = shift; - my $status = 'Cancelled'; - my $statuscol = 'FF0000'; - if ( $row->uncancelled_pkgs ) { - $status = 'Suspended'; - $statuscol = 'FF9900'; - if ( $row->active_pkgs ) { - $status = 'Active'; - $statuscol = '00CC00'; - } - } - $statuscol; - }, + sub { ( &{$status_statuscol}(shift) )[1] }, #sub { shift->statuscolor; }, '', '', diff --git a/httemplate/search/svc_acct.cgi b/httemplate/search/svc_acct.cgi index b14591958..0f2f3ef45 100755 --- a/httemplate/search/svc_acct.cgi +++ b/httemplate/search/svc_acct.cgi @@ -5,11 +5,9 @@ my $orderby = 'ORDER BY svcnum'; my($query)=$cgi->keywords; $query ||= ''; #to avoid use of unitialized value errors -my $cjoin = ''; my @extra_sql = (); if ( $query =~ /^UN_(.*)$/ ) { $query = $1; - $cjoin = 'LEFT JOIN cust_svc USING ( svcnum )'; push @extra_sql, 'pkgnum IS NULL'; } @@ -24,7 +22,6 @@ if ( $query eq 'svcnum' ) { push @extra_sql, "popnum = $1"; $orderby = "ORDER BY LOWER(username)"; } elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) { - $cjoin ||= 'LEFT JOIN cust_svc USING ( svcnum )'; push @extra_sql, "svcpart = $1"; $orderby = "ORDER BY uid"; #$orderby = "ORDER BY svcnum"; @@ -72,12 +69,20 @@ if ( $query eq 'svcnum' ) { } +my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '. + ' LEFT JOIN part_svc USING ( svcpart ) '. + ' LEFT JOIN cust_pkg USING ( pkgnum ) '. + ' LEFT JOIN cust_main USING ( custnum ) '; + +#here is the agent virtualization +push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql; + my $extra_sql = scalar(@extra_sql) ? ' WHERE '. join(' AND ', @extra_sql ) : ''; -my $count_query = "SELECT COUNT(*) FROM svc_acct $cjoin $extra_sql"; +my $count_query = "SELECT COUNT(*) FROM svc_acct $addl_from $extra_sql"; #if ( keys %svc_acct ) { # $count_query .= ' WHERE '. # join(' AND ', map "$_ = ". dbh->quote($svc_acct{$_}), @@ -90,14 +95,12 @@ my $sql_query = { 'hashref' => {}, # \%svc_acct, 'select' => join(', ', 'svc_acct.*', + 'part_svc.svc', 'cust_main.custnum', FS::UI::Web::cust_sql_fields(), ), 'extra_sql' => "$extra_sql $orderby", - 'addl_from' => ' LEFT JOIN cust_svc USING ( svcnum ) '. - ' LEFT JOIN part_svc USING ( svcpart ) '. - ' LEFT JOIN cust_pkg USING ( pkgnum ) '. - ' LEFT JOIN cust_main USING ( custnum ) ', + 'addl_from' => $addl_from, }; my $link = [ "${p}view/svc_acct.cgi?", 'svcnum' ]; @@ -117,21 +120,21 @@ my $link_cust = sub { 'count_query' => $count_query, 'redirect' => $link, 'header' => [ '#', + 'Service', 'Account', 'UID', - 'Service', FS::UI::Web::cust_header(), ], 'fields' => [ 'svcnum', + 'svc', 'email', 'uid', - 'svc', \&FS::UI::Web::cust_fields, ], 'links' => [ $link, $link, $link, - '', + $link, ( map { $link_cust } FS::UI::Web::cust_header() ), diff --git a/httemplate/search/svc_domain.cgi b/httemplate/search/svc_domain.cgi index b02eea8bd..ecb77792f 100755 --- a/httemplate/search/svc_domain.cgi +++ b/httemplate/search/svc_domain.cgi @@ -6,51 +6,62 @@ my($query)=$cgi->keywords; $query ||= ''; #to avoid use of unitialized value errors my $orderby = 'ORDER BY svcnum'; -my $join = ''; my %svc_domain = (); -my $extra_sql = ''; +my @extra_sql = (); if ( $query eq 'svcnum' ) { #$orderby = 'ORDER BY svcnum'; } elsif ( $query eq 'domain' ) { $orderby = 'ORDER BY domain'; -} elsif ( $query eq 'UN_svcnum' ) { +} elsif ( $query eq 'UN_svcnum' ) { #UN searches need to be acl'ed (and need to + #fix $agentnums_sql #$orderby = 'ORDER BY svcnum'; - $join = 'LEFT JOIN cust_svc USING ( svcnum )'; - $extra_sql = ' WHERE pkgnum IS NULL'; -} elsif ( $query eq 'UN_domain' ) { + push @extra_sql, 'pkgnum IS NULL'; +} elsif ( $query eq 'UN_domain' ) { #UN searches need to be acl'ed (and need to + #fix $agentnums_sql $orderby = 'ORDER BY domain'; - $join = 'LEFT JOIN cust_svc USING ( svcnum )'; - $extra_sql = ' WHERE pkgnum IS NULL'; + push @extra_sql, 'pkgnum IS NULL'; } elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) { #$orderby = 'ORDER BY svcnum'; - $join = 'LEFT JOIN cust_svc USING ( svcnum )'; - $extra_sql = " WHERE svcpart = $1"; + push @extra_sql, "svcpart = $1"; } else { $cgi->param('domain') =~ /^([\w\-\.]+)$/; - $join = ''; $svc_domain{'domain'} = $1; } -my $count_query = "SELECT COUNT(*) FROM svc_domain $join $extra_sql"; +my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '. + ' LEFT JOIN part_svc USING ( svcpart ) '. + ' LEFT JOIN cust_pkg USING ( pkgnum ) '. + ' LEFT JOIN cust_main USING ( custnum ) '; + +#here is the agent virtualization +push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql; + +my $extra_sql = ''; +if ( @extra_sql ) { + $extra_sql = ( keys(%svc_domain) ? ' AND ' : ' WHERE ' ). + join(' AND ', @extra_sql ); +} + +my $count_query = "SELECT COUNT(*) FROM svc_domain $addl_from "; if ( keys %svc_domain ) { $count_query .= ' WHERE '. join(' AND ', map "$_ = ". dbh->quote($svc_domain{$_}), keys %svc_domain ); } +$count_query .= $extra_sql; my $sql_query = { 'table' => 'svc_domain', 'hashref' => \%svc_domain, 'select' => join(', ', 'svc_domain.*', - 'cust_main.custnum', - FS::UI::Web::cust_sql_fields(), + 'part_svc.svc', + 'cust_main.custnum', + FS::UI::Web::cust_sql_fields(), ), 'extra_sql' => "$extra_sql $orderby", - 'addl_from' => 'LEFT JOIN cust_svc USING ( svcnum ) '. - 'LEFT JOIN cust_pkg USING ( pkgnum ) '. - 'LEFT JOIN cust_main USING ( custnum ) ', + 'addl_from' => $addl_from, }; my $link = [ "${p}view/svc_domain.cgi?", 'svcnum' ]; @@ -68,15 +79,18 @@ my $link_cust = sub { 'count_query' => $count_query, 'redirect' => $link, 'header' => [ '#', + 'Service', 'Domain', FS::UI::Web::cust_header(), ], 'fields' => [ 'svcnum', + 'svc', 'domain', \&FS::UI::Web::cust_fields, ], 'links' => [ $link, $link, + $link, ( map { $link_cust } FS::UI::Web::cust_header() ), diff --git a/httemplate/search/svc_forward.cgi b/httemplate/search/svc_forward.cgi index a204e345f..d391a1834 100755 --- a/httemplate/search/svc_forward.cgi +++ b/httemplate/search/svc_forward.cgi @@ -5,14 +5,12 @@ my $conf = new FS::Conf; my($query)=$cgi->keywords; $query ||= ''; #to avoid use of unitialized value errors - my $orderby; -my $cjoin = ''; my @extra_sql = (); -if ( $query =~ /^UN_(.*)$/ ) { +if ( $query =~ /^UN_(.*)$/ ) { #UN searches need to be acl'ed (and need to + #fix $agentnums_sql $query = $1; - $cjoin = 'LEFT JOIN cust_svc USING ( svcnum )'; push @extra_sql, 'pkgnum IS NULL'; } @@ -22,25 +20,31 @@ if ( $query eq 'svcnum' ) { eidiot('unimplemented'); } +my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '. + ' LEFT JOIN part_svc USING ( svcpart ) '. + ' LEFT JOIN cust_pkg USING ( pkgnum ) '. + ' LEFT JOIN cust_main USING ( custnum ) '; + +#here is the agent virtualization +push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql; + my $extra_sql = scalar(@extra_sql) ? ' WHERE '. join(' AND ', @extra_sql ) : ''; -my $count_query = "SELECT COUNT(*) FROM svc_forward $cjoin $extra_sql"; +my $count_query = "SELECT COUNT(*) FROM svc_forward $addl_from $extra_sql"; my $sql_query = { 'table' => 'svc_forward', 'hashref' => {}, 'select' => join(', ', 'svc_forward.*', - 'cust_main.custnum', - FS::UI::Web::cust_sql_fields(), + 'part_svc.svc', + 'cust_main.custnum', + FS::UI::Web::cust_sql_fields(), ), 'extra_sql' => "$extra_sql $orderby", - 'addl_from' => ' LEFT JOIN cust_svc USING ( svcnum ) '. - ' LEFT JOIN part_svc USING ( svcpart ) '. - ' LEFT JOIN cust_pkg USING ( pkgnum ) '. - ' LEFT JOIN cust_main USING ( custnum ) ', + 'addl_from' => $addl_from, }; # <TH>Service #<BR><FONT SIZE=-1>(click to view forward)</FONT></TH> @@ -100,16 +104,19 @@ my $link_cust = sub { 'count_query' => $count_query, 'redirect' => $link, 'header' => [ '#', + 'Service', 'Mail to', 'Forwards to', FS::UI::Web::cust_header(), ], 'fields' => [ 'svcnum', + 'svc', $format_src, $format_dst, \&FS::UI::Web::cust_fields, ], 'links' => [ $link, + $link, $link_src, $link_dst, ( map { $link_cust } diff --git a/httemplate/search/svc_phone.cgi b/httemplate/search/svc_phone.cgi new file mode 100644 index 000000000..a68a13e39 --- /dev/null +++ b/httemplate/search/svc_phone.cgi @@ -0,0 +1,94 @@ +<% + +my $conf = new FS::Conf; + +my($query)=$cgi->keywords; +$query ||= ''; #to avoid use of unitialized value errors + +my $orderby = 'ORDER BY svcnum'; +my %svc_phone = (); +my @extra_sql = (); +if ( $query eq 'svcnum' ) { + #$orderby = 'ORDER BY svcnum'; +} elsif ( $query eq 'phonenum' ) { + $orderby = 'ORDER BY phonenum'; +} elsif ( $cgi->param('svcpart') =~ /^(\d+)$/ ) { + #$orderby = 'ORDER BY svcnum'; + push @extra_sql, "svcpart = $1"; +} else { + $cgi->param('phonenum') =~ /^([\d\- ]+)$/; + ( $svc_phone{'phonenum'} = $1 ) =~ s/\D//g; +} + +my $addl_from = ' LEFT JOIN cust_svc USING ( svcnum ) '. + ' LEFT JOIN part_svc USING ( svcpart ) '. + ' LEFT JOIN cust_pkg USING ( pkgnum ) '. + ' LEFT JOIN cust_main USING ( custnum ) '; + +#here is the agent virtualization +push @extra_sql, $FS::CurrentUser::CurrentUser->agentnums_sql; + +my $extra_sql = ''; +if ( @extra_sql ) { + $extra_sql = ( keys(%svc_phone) ? ' AND ' : ' WHERE ' ). + join(' AND ', @extra_sql ); +} + +my $count_query = "SELECT COUNT(*) FROM svc_phone $addl_from "; +if ( keys %svc_phone ) { + $count_query .= ' WHERE '. + join(' AND ', map "$_ = ". dbh->quote($svc_phone{$_}), + keys %svc_phone + ); +} +$count_query .= $extra_sql; + +my $sql_query = { + 'table' => 'svc_phone', + 'hashref' => \%svc_phone, + 'select' => join(', ', + 'svc_phone.*', + 'part_svc.svc', + 'cust_main.custnum', + FS::UI::Web::cust_sql_fields(), + ), + 'extra_sql' => "$extra_sql $orderby", + 'addl_from' => $addl_from, +}; + +my $link = [ "${p}view/svc_phone.cgi?", 'svcnum' ]; + +#smaller false laziness w/svc_*.cgi here +my $link_cust = sub { + my $svc_x = shift; + $svc_x->custnum ? [ "${p}view/cust_main.cgi?", 'custnum' ] : ''; +}; + +%><%= include( 'elements/search.html', + 'title' => "Phone number search results", + 'name' => 'phone numbers', + 'query' => $sql_query, + 'count_query' => $count_query, + 'redirect' => $link, + 'header' => [ '#', + 'Service', + 'Country code', + 'Phone number', + FS::UI::Web::cust_header(), + ], + 'fields' => [ 'svcnum', + 'svc', + 'countrycode', + 'phonenum', + \&FS::UI::Web::cust_fields, + ], + 'links' => [ $link, + $link, + $link, + $link, + ( map { $link_cust } + FS::UI::Web::cust_header() + ), + ], + ) +%> diff --git a/httemplate/search/svc_www.cgi b/httemplate/search/svc_www.cgi index ae51c61fc..ef4045cf9 100755 --- a/httemplate/search/svc_www.cgi +++ b/httemplate/search/svc_www.cgi @@ -17,6 +17,7 @@ my $sql_query = { 'hashref' => {}, 'select' => join(', ', 'svc_www.*', + 'part_svc.svc', 'cust_main.custnum', FS::UI::Web::cust_sql_fields(), ), @@ -43,11 +44,13 @@ my $link_cust = sub { 'count_query' => $count_query, 'redirect' => $link, 'header' => [ '#', + 'Service', 'Zone', 'User', FS::UI::Web::cust_header(), ], 'fields' => [ 'svcnum', + 'svc', sub { $_[0]->domain_record->zone }, sub { my $svc_www = shift; @@ -59,6 +62,7 @@ my $link_cust = sub { \&FS::UI::Web::cust_fields, ], 'links' => [ $link, + $link, '', $ulink, ( map { $link_cust } diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi index 58f2925d5..8267fea51 100755 --- a/httemplate/view/cust_main.cgi +++ b/httemplate/view/cust_main.cgi @@ -1,23 +1,8 @@ -<!-- mason kludge --> <% my $conf = new FS::Conf; -my %uiview = (); -my %uiadd = (); -foreach my $part_svc ( qsearch('part_svc',{}) ) { - $uiview{$part_svc->svcpart} = $p. "view/". $part_svc->svcdb . ".cgi"; - $uiadd{$part_svc->svcpart}= $p. "edit/". $part_svc->svcdb . ".cgi"; -} - -%> - -<%= include("/elements/header.html","Customer View", - include("/elements/menubar.html", - 'Main Menu' => $p, -)) %> - -<% +my $curuser = $FS::CurrentUser::CurrentUser; die "No customer specified (bad URL)!" unless $cgi->keywords; my($query) = $cgi->keywords; # needs parens with my, ->keywords returns array @@ -26,13 +11,19 @@ my $custnum = $1; my $cust_main = qsearchs('cust_main',{'custnum'=>$custnum}); die "Customer not found!" unless $cust_main; -print qq!<A HREF="${p}edit/cust_main.cgi?$custnum">Edit this customer</A>!; - %> +<%= include("/elements/header.html","Customer View: ". $cust_main->name ) %> + +<% if ( $curuser->access_right('Edit customer') ) { %> + <A HREF="<%= $p %>edit/cust_main.cgi?<%= $custnum %>">Edit this customer</A> | +<% } %> + + <SCRIPT TYPE="text/javascript" SRC="../elements/overlibmws.js"></SCRIPT> <SCRIPT TYPE="text/javascript" SRC="../elements/overlibmws_iframe.js"></SCRIPT> <SCRIPT TYPE="text/javascript" SRC="../elements/overlibmws_draggable.js"></SCRIPT> +<SCRIPT TYPE="text/javascript" SRC="../elements/iframecontentmws.js"></SCRIPT> <SCRIPT TYPE="text/javascript"> function areyousure(href, message) { @@ -60,37 +51,36 @@ var confirm_cancel = '<FORM METHOD="POST" ACTION="<%= $p %>misc/cust_main-cancel </SCRIPT> -<% if ( $cust_main->ncancelled_pkgs ) { %> +<% if ( $curuser->access_right('Cancel customer') + && $cust_main->ncancelled_pkgs + ) { +%> + <A HREF="javascript:void(0);" onClick="overlib(confirm_cancel, CAPTION, 'Confirm cancellation', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, 128, TEXTSIZE, 3, BGCOLOR, '#ff0000', CGCOLOR, '#ff0000' ); return false; ">Cancel this customer</A> | +<% } %> - | <A HREF="javascript:void(0);" onClick="overlib(confirm_cancel, CAPTION, 'Confirm cancellation', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', MIDX, 0, MIDY, 0, DRAGGABLE, WIDTH, 576, HEIGHT, 128, TEXTSIZE, 3, BGCOLOR, '#ff0000', CGCOLOR, '#ff0000' ); return false; ">Cancel this customer</A> +<% if ( $conf->exists('deletecustomers') + && $curuser->access_right('Delete customer') + ) { +%> + <A HREF="<%= $p %>misc/delete-customer.cgi?<%= $custnum%>">Delete this customer</A> | <% } %> -<% - -print qq! | <A HREF="${p}misc/delete-customer.cgi?$custnum">!. - 'Delete this customer</A>' - if $conf->exists('deletecustomers'); -unless ( $conf->exists('disable_customer_referrals') ) { - print qq! | <A HREF="!, popurl(2), - qq!edit/cust_main.cgi?referral_custnum=$custnum">!, - qq!Refer a new customer</A>!; +<% unless ( $conf->exists('disable_customer_referrals') ) { %> + <A HREF="<%= popurl(2) %>edit/cust_main.cgi?referral_custnum=<%= $custnum %>">Refer a new customer</A> | + <A HREF="<%= popurl(2) %>search/cust_main.cgi?referral_custnum=<%= $custnum %>">View this customer's referrals</A> +<% } %> - print qq! | <A HREF="!, popurl(2), - qq!search/cust_main.cgi?referral_custnum=$custnum">!, - qq!View this customer's referrals</A>!; -} -print '<BR><BR>'; +<BR><BR> +<% my $signupurl = $conf->config('signupurl'); if ( $signupurl ) { -print "This customer's signup URL: ". - "<a href=\"$signupurl?ref=$custnum\">$signupurl?ref=$custnum</a><BR><BR>"; -} - %> + This customer's signup URL: <A HREF="<%= $signupurl %>?ref=<%= $custnum %>"><%= $signupurl %>?ref=<%= $custnum %></A><BR><BR> +<% } %> <A NAME="cust_main"></A> <TABLE BORDER=0> @@ -135,5 +125,4 @@ Comments <%= include('cust_main/payment_history.html', $cust_main ) %> <% } %> -</BODY></HTML> - +<%= include('/elements/footer.html') %> diff --git a/httemplate/view/cust_main/billing.html b/httemplate/view/cust_main/billing.html index 895814cc2..191d3092f 100644 --- a/httemplate/view/cust_main/billing.html +++ b/httemplate/view/cust_main/billing.html @@ -1,12 +1,24 @@ <% my( $cust_main ) = @_; my @invoicing_list = $cust_main->invoicing_list; + my $conf = new FS::Conf; + my $money_char = $conf->config('money_char') || '$'; %> Billing information (<A HREF="<%= $p %>misc/bill.cgi?<%= $cust_main->custnum %>">Bill now</A>) <%= ntable("#cccccc") %><TR><TD><%= ntable("#cccccc",2) %> +<% +( my $balance = $cust_main->balance ) + =~ s/^(\-?)(.*)$/<FONT SIZE=+1>$1<\/FONT>$money_char$2/; +%> + +<TR> + <TD ALIGN="right">Balance due</TD> + <TD BGCOLOR="#ffffff"><B><%= $balance %></B></TD> +</TR> + <TR> <TD ALIGN="right">Billing type</TD> <TD BGCOLOR="#ffffff"> @@ -159,7 +171,7 @@ if ( $date =~ /^(\d{4})-(\d{1,2})-\d{1,2}$/ ) { #PostgreSQL date format <%= join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ) || 'no' %> </TD> </TR> -<% my $conf = new FS::Conf; if ( $conf->exists('voip-cust_cdr_spools') ) { %> +<% if ( $conf->exists('voip-cust_cdr_spools') ) { %> <TR> <TD ALIGN="right">Spool CDRs</TD> <TD BGCOLOR="#ffffff"><%= $cust_main->spool_cdr ? 'yes' : 'no' %></TD> diff --git a/httemplate/view/cust_main/contacts.html b/httemplate/view/cust_main/contacts.html index 7aba11813..48371550b 100644 --- a/httemplate/view/cust_main/contacts.html +++ b/httemplate/view/cust_main/contacts.html @@ -114,7 +114,7 @@ Service address </TR> <TR> <TD ALIGN="right">Country</TD> - <TD BGCOLOR="#ffffff"><%= $cust_main->get("${pre}country") %></TD> + <TD BGCOLOR="#ffffff"><%= code2country( $cust_main->get("${pre}country") ) %></TD> </TR> <TR> <TD ALIGN="right"><%= $daytime_label %></TD> diff --git a/httemplate/view/cust_main/misc.html b/httemplate/view/cust_main/misc.html index 69e120573..f06a4fbd2 100644 --- a/httemplate/view/cust_main/misc.html +++ b/httemplate/view/cust_main/misc.html @@ -1,13 +1,20 @@ <% my( $cust_main ) = @_; + my $conf = new FS::Conf; %> <%= ntable("#cccccc") %><TR><TD><%= &ntable("#cccccc",2) %> + <TR> <TD ALIGN="right">Customer number</TD> <TD BGCOLOR="#ffffff"><%= $cust_main->custnum %></TD> </TR> +<TR> + <TD ALIGN="right">Status</TD> + <TD BGCOLOR="#ffffff"><FONT COLOR="#<%= $cust_main->statuscolor %>"><B><%= ucfirst($cust_main->status) %></B></FONT></TD> +</TR> + <% my @agents = qsearch( 'agent', {} ); my $agent; @@ -25,8 +32,18 @@ $agent = $agents[0]; } - my @referrals = qsearch( 'part_referral', {} ); - unless ( scalar(@referrals) == 1 ) { + if ( $cust_main->agent_custid ) { +%> + +<TR> + <TD ALIGN="right">Agent customer ref#</TD> + <TD BGCOLOR="#ffffff"><%= $cust_main->agent_custid %></TD> +</TR> + +<% + } + + unless ( FS::part_referral->num_part_referral == 1 ) { my $referral = qsearchs('part_referral', { 'refnum' => $cust_main->refnum } ); @@ -40,10 +57,6 @@ <% } %> <TR> - <TD ALIGN="right">Order taker</TD> - <TD BGCOLOR="#ffffff"><%= $cust_main->otaker %></TD> -</TR> -<TR> <TD ALIGN="right">Referring Customer</TD> <TD BGCOLOR="#ffffff"> @@ -71,5 +84,10 @@ </TD> </TR> +<TR> + <TD ALIGN="right">Order taker</TD> + <TD BGCOLOR="#ffffff"><%= $cust_main->otaker %></TD> +</TR> + </TABLE></TD></TR></TABLE> diff --git a/httemplate/view/cust_main/packages.html b/httemplate/view/cust_main/packages.html index 32e0ee1fc..9cd1e284f 100755 --- a/httemplate/view/cust_main/packages.html +++ b/httemplate/view/cust_main/packages.html @@ -2,22 +2,28 @@ my( $cust_main ) = @_; my $conf = new FS::Conf; + my $curuser = $FS::CurrentUser::CurrentUser; + my $packages = get_packages($cust_main, $conf); %> -<STYLE TYPE="text/css"> -.package .provision { font-weight: bold } -</STYLE> - <A NAME="cust_pkg"><FONT SIZE="+2">Packages</FONT></A> -<%= include('order_pkg.html', $cust_main ) %> +<% if ( $curuser->access_right('Order customer package') ) { %> + <%= include('order_pkg.html', $cust_main ) %> +<% } %> -<% if ( $conf->config('payby-default') ne 'HIDE' ) { %> +<% if ( $curuser->access_right('One-time charge') + && $conf->config('payby-default') ne 'HIDE' + ) { +%> <%= include('quick-charge.html', $cust_main ) %> <% } %> -<A HREF="<%= $p %>edit/cust_pkg.cgi?<%= $cust_main->custnum %>">Bulk order and cancel packages</A> (preserves services) +<% if ( $curuser->access_right('Bulk change customer packages') ) { %> + <A HREF="<%= $p %>edit/cust_pkg.cgi?<%= $cust_main->custnum %>">Bulk order and cancel packages</A> (preserves services) +<% } %> + <BR><BR> <% if ( @$packages ) { %> @@ -44,39 +50,51 @@ Current packages <% if ( @$packages ) { %> -<TABLE CLASS="package" BORDER=1 CELLSPACING=0 CELLPADDING=2 BORDERCOLOR="#999999"> +<%= include('/elements/table-grid.html') %> + +<% my $bgcolor1 = '#eeeeee'; + my $bgcolor2 = '#ffffff'; + my $bgcolor = ''; +%> + <TR> - <TH>Package</TH> - <TH>Status</TH> - <TH COLSPAN=2>Services</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Package</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Status</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Services</TH> </TR> <% foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { - my $rowspan = 0; - if ($pkg->{cancel}) { - $rowspan = 0; + if ( $bgcolor eq $bgcolor1 ) { + $bgcolor = $bgcolor2; } else { - foreach my $svcpart (@{$pkg->{svcparts}}) { - $rowspan += $svcpart->{count}; - $rowspan++ if ($svcpart->{count} < $svcpart->{quantity}); - } - } + $bgcolor = $bgcolor1; + } + %> <!--pkgnum: <%=$pkg->{pkgnum}%>--> <TR> - <TD ROWSPAN=<%= $rowspan || 1 %>> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"> <A NAME="cust_pkg<%=$pkg->{pkgnum}%>"><%=$pkg->{pkgnum}%></A>: <%=$pkg->{pkg}%> - <%=$pkg->{comment}%><BR> -<% unless ($pkg->{cancel}) { %> - ( <%=pkg_change_link($pkg)%> ) - ( <%=pkg_dates_link($pkg)%> | <%=pkg_customize_link($pkg,$cust_main->custnum)%> ) -<% } %> + <FONT SIZE=-1> + <% unless ( $pkg->{cancel} ) { %> + <% if ( $curuser->access_right('Change customer package') ) { %> + ( <%=pkg_change_link($pkg)%> ) + <% } %> + <% if ( $curuser->access_right('Edit customer package dates') ) { %> + ( <%=pkg_dates_link($pkg)%> ) + <% } %> + <% if ( $curuser->access_right('Customize customer package') ) { %> + ( <%=pkg_customize_link($pkg,$cust_main->custnum)%> ) + <% } %> + <% } %> + </FONT> </TD> - <TD ROWSPAN=<%= $rowspan || 1 %>> - <TABLE BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%"> + <TD CLASS="inv" BGCOLOR="<%= $bgcolor %>"> + <TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%"> <% sub myfreq { @@ -182,7 +200,16 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { <% } %> <TR> - <TD COLSPAN=<%=$colspan%>>( <%= pkg_unsuspend_link($pkg) %> | <%= pkg_cancel_link($pkg) %> )</TD> + <TD COLSPAN=<%=$colspan%>> + <FONT SIZE=-1> + <% if ( $curuser->access_right('Unsuspend customer package') ) { %> + ( <%= pkg_unsuspend_link($pkg) %> ) + <% } %> + <% if ( $curuser->access_right('Cancel customer package') ) { %> + ( <%= pkg_cancel_link($pkg) %> ) + <% } %> + </FONT> + </TD> </TR> <% } else { %> <!-- #status: active --> @@ -196,7 +223,13 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { </TR> <TR> - <TD COLSPAN=<%=$colspan%>>( <%= pkg_cancel_link($pkg) %> )</TD> + <TD COLSPAN=<%=$colspan%>> + <FONT SIZE=-1> + <% if ( $curuser->access_right('Cancel customer package immediately') ) { %> + ( <%= pkg_cancel_link($pkg) %> ) + <% } %> + </FONT> + </TD> </TR> <% } else { %> @@ -258,7 +291,19 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { <% if ( $pkg->{freq} ) { %> <TR> - <TD COLSPAN=<%=$colspan%>>( <%= pkg_suspend_link($pkg) %> | <%= pkg_cancel_link($pkg) %> )</TD> + <TD COLSPAN=<%=$colspan%>> + <FONT SIZE=-1> + <% if ( $curuser->access_right('Suspend customer package') ) { %> + ( <%= pkg_suspend_link($pkg) %> ) + <% } %> + <% if ( $curuser->access_right('Cancel customer package immediately') ) { %> + ( <%= pkg_cancel_link($pkg) %> ) + <% } %> + <% if ( $curuser->access_right('Cancel customer package later') ) { %> + ( <%= pkg_expire_link($pkg) %> ) + <% } %> + <FONT> + </TD> </TR> <% } %> @@ -269,30 +314,51 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { </TABLE> </TD> -<% - if ($rowspan == 0) { print qq!</TR>\n!; next; } +<TD CLASS="inv" BGCOLOR="<%= $bgcolor %>"> + <TABLE CLASS="inv" BORDER=0 CELLSPACING=0 CELLPADDING=0 WIDTH="100%"> + - my $cnt = 0; +<% foreach my $svcpart (sort {$a->{svcpart} <=> $b->{svcpart}} @{$pkg->{svcparts}}) { foreach my $service (@{$svcpart->{services}}) { - print '<TR>' if ($cnt > 0); %> - <TD><%=svc_link($svcpart,$service)%></TD> - <TD><%=svc_label_link($svcpart,$service)%><BR>( <%=svc_unprovision_link($service)%> )</TD> -</TR> -<% - $cnt++; - } - if ($svcpart->{count} < $svcpart->{quantity}) { - print qq!<TR>\n! if ($cnt > 0); - print qq! <TD COLSPAN=2>!.svc_provision_link($pkg, $svcpart, $conf).qq!</TD>\n</TR>\n!; - } - } -} -#end display packages + <TR> + <TD ALIGN="right" VALIGN="top" ROWSPAN=2><%=svc_link($svcpart,$service)%></TD> + <TD STYLE="padding-bottom:0px"><B><%=svc_label_link($svcpart,$service)%></B></TD> + </TR> + + <% if ( $curuser->access_right('Unprovision customer service') ) { %> + <TR> + <TD ALIGN="right" VALIGN="top" STYLE="padding-bottom:5px;padding-top:0px"><FONT SIZE="-2">( <%=svc_unprovision_link($service)%> )</FONT></TD> + </TR> + <% } %> + + <% } %> + + <% if ( $curuser->access_right('Provision customer service') + && $svcpart->{count} < $svcpart->{quantity} + ) + { + %> + + <TR> + <TD COLSPAN=2 ALIGN="center" STYLE="padding-bottom:4px;padding-top:0px"> + <B><%= svc_provision_link($pkg, $svcpart, $conf, $curuser) %></B> + </TD> + </TR> + + <% } %> + +<% } %> + +</TABLE> +</TD> + +<% } #end display packages %> </TABLE> + <% } else { %> <BR> <% } %> @@ -393,7 +459,7 @@ sub svc_label_link { } sub svc_provision_link { - my ($pkg, $svcpart, $conf) = @_; + my ($pkg, $svcpart, $conf, $curuser) = @_; ( my $svc_nbsp = $svcpart->{svc} ) =~ s/\s+/ /g; my $num_left = $svcpart->{quantity} - $svcpart->{count}; my $pkgnum_svcpart = "pkgnum$pkg->{pkgnum}-svcpart$svcpart->{svcpart}"; @@ -411,7 +477,10 @@ sub svc_provision_link { my $link = qq!<A CLASS="provision" HREF="$url">!. "Provision $svc_nbsp ($num_left)</A>"; - if ( $conf->exists('legacy_link') ) { + if ( $conf->exists('legacy_link') + && $curuser->access_right('View/link unlinked services') + ) + { $link .= '<BR>'. qq!<A CLASS="provision" HREF="${p}misc/link.cgi?!. qq!$pkgnum_svcpart">!. @@ -475,7 +544,11 @@ sub pkg_cancel_link { my $pkg = shift or return ''; qq!<A HREF="javascript:areyousure('${p}misc/cancel_pkg.cgi?$pkg->{pkgnum}', !. qq!'Permanently delete included services and cancel this package?')">!. - qq!Cancel now</A> | !. + qq!Cancel now</A>!; +} + +sub pkg_expire_link { + my $pkg = shift or return ''; qq!<A HREF="${p}misc/expire_pkg.cgi?$pkg->{pkgnum}">Cancel later</A>!; } diff --git a/httemplate/view/cust_main/payment_history.html b/httemplate/view/cust_main/payment_history.html index f0cd993ff..aef5fb8f8 100644 --- a/httemplate/view/cust_main/payment_history.html +++ b/httemplate/view/cust_main/payment_history.html @@ -4,6 +4,8 @@ my $conf = new FS::Conf; + my $curuser = $FS::CurrentUser::CurrentUser; + my @payby = grep /\w/, $conf->config('payby'); #@payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH WEST COMP )) @payby = (qw( CARD DCRD CHEK DCHK LECB BILL CASH COMP )) @@ -16,53 +18,63 @@ <BR><BR><A NAME="history"><FONT SIZE="+2">Payment History</FONT></A><BR> -<% if ( $payby{'BILL'} ) { %> +<% if ( $payby{'BILL'} && $curuser->access_right('Post payment') ) { %> <%= $s++ ? ' | ' : '' %> - <A HREF="<%= $p %>edit/cust_pay.cgi?payby=BILL;custnum=<%= $custnum %>">Post check payment</A> + <A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('<%= $p %>edit/cust_pay.cgi?popup=1;payby=BILL;custnum=<%= $custnum %>', 392, 336, 'cust_pay_popup' ), CAPTION, 'Enter check payment', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK ); return false;">Enter check payment</A> <% } %> -<% if ( $payby{'CASH'} ) { %> +<% if ( $payby{'CASH'} && $curuser->access_right('Post payment') ) { %> <%= $s++ ? ' | ' : '' %> - <A HREF="<%= $p %>edit/cust_pay.cgi?payby=CASH;custnum=<%= $custnum %>">Post cash payment</A> + <A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('<%= $p %>edit/cust_pay.cgi?popup=1;payby=CASH;custnum=<%= $custnum %>', 392, 336, 'cust_pay_popup' ), CAPTION, 'Enter cash payment', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK ); return false;">Enter cash payment</A> <% } %> -<% if ( $payby{'WEST'} ) { %> +<% if ( $payby{'WEST'} && $curuser->access_right('Post payment') ) { %> <%= $s++ ? ' | ' : '' %> - <A HREF="<%= $p %>edit/cust_pay.cgi?payby=WEST;custnum=<%= $custnum %>">Post Western Union payment</A> + <A HREF="<%= $p %>edit/cust_pay.cgi?payby=WEST;custnum=<%= $custnum %>">Enter Western Union payment</A> <% } %> -<% if ( $payby{'CARD'} || $payby{'DCRD'} ) { %> +<% if ( ( $payby{'CARD'} || $payby{'DCRD'} ) + && $curuser->access_right('Process payment') + ) { +%> <%= $s++ ? ' | ' : '' %> <A HREF="<%= $p %>misc/payment.cgi?payby=CARD;custnum=<%= $custnum %>">Process credit card payment</A> <% } %> -<% if ( $payby{'CHEK'} || $payby{'DCHK'} ) { %> +<% if ( ( $payby{'CHEK'} || $payby{'DCHK'} ) + && $curuser->access_right('Process payment') + ) { +%> <%= $s++ ? ' | ' : '' %> <A HREF="<%= $p %>misc/payment.cgi?payby=CHEK;custnum=<%= $custnum %>">Process electronic check (ACH) payment</A> <% } %> -<% if ( $payby{'MCRD'} ) { %> +<% if ( $payby{'MCRD'} && $curuser->access_right('Post payment') ) { %> <%= $s++ ? ' | ' : '' %> - <A HREF="<%= $p %>edit/cust_pay.cgi?payby=MCRD;custnum=<%= $custnum %>">Post manual credit card payment</A> + <A HREF="<%= $p %>edit/cust_pay.cgi?payby=MCRD;custnum=<%= $custnum %>">Post manual (offline) credit card payment</A> <% } %> <BR> -<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('<%= $p %>edit/cust_credit.cgi?<%= $custnum %>', 392, 336, 'cust_credit_popup' ), CAPTION, 'Post credit', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK )">Post credit</A> +<% if ( $curuser->access_right('Post credit') ) { %> -<BR> + <A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('<%= $p %>edit/cust_credit.cgi?<%= $custnum %>', 392, 336, 'cust_credit_popup' ), CAPTION, 'Enter credit', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK ); return false;">Enter credit</A> + + <BR> + +<% } %> <% #get payment history @@ -75,11 +87,14 @@ foreach my $cust_bill ($cust_main->cust_bill) { : ''; my $post = ( $cust_bill->owed > 0 ) ? '</FONT></B>' : ''; my $invnum = $cust_bill->invnum; + my $link = $curuser->access_right('View invoices') + ? qq!<A HREF="${p}view/cust_bill.cgi?$invnum">! + : ''; push @history, { 'date' => $cust_bill->_date, - 'desc' => qq!<A HREF="${p}view/cust_bill.cgi?$invnum">!. $pre. + 'desc' => $link. $pre. "Invoice #$invnum (Balance \$". $cust_bill->owed. ')'. - $post. '</A>', + $post. ( $link ? '</A>' : '' ), 'charge' => $cust_bill->charged, }; } @@ -120,7 +135,7 @@ foreach my $cust_pay ($cust_main->cust_pay) { $post = '</FONT></B>'; $apply = qq! (<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('${p}edit/cust_bill_pay.cgi?!. $cust_pay->paynum. - qq!', 392, 336, 'cust_credit_popup' ), CAPTION, 'Post credit', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK )">apply</A>)!; + qq!', 392, 336, 'cust_bill_pay_popup' ), CAPTION, 'Apply payment', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK ); return false;">apply</A>)!; } elsif ( scalar(@cust_bill_pay) == 1 && scalar(@cust_pay_refund) == 0 @@ -146,7 +161,7 @@ foreach my $cust_pay ($cust_main->cust_pay) { } elsif ( $app->isa('FS::cust_pay_refund') ) { $desc .= ' '. '$'. $app->amount. - ' refunded on'. time2str("%D", $app->_date). + ' refunded on '. time2str("%D", $app->_date). '<BR>'; } else { die "$app is not a FS::cust_bill_pay or FS::cust_pay_refund"; @@ -158,7 +173,7 @@ foreach my $cust_pay ($cust_main->cust_pay) { $cust_pay->unapplied. ' unapplied</FONT></B>'. qq! (<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('${p}edit/cust_bill_pay.cgi?!. $cust_pay->paynum. - qq!', 392, 336, 'cust_credit_popup' ), CAPTION, 'Post credit', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK )">apply</A>)!. + qq!', 392, 336, 'cust_bill_pay_popup' ), CAPTION, 'Apply payment', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK ); return false;">apply</A>)!. '<BR>'; } } @@ -169,6 +184,7 @@ foreach my $cust_pay ($cust_main->cust_pay) { && $cust_pay->payby =~ /^(CARD|CHEK)$/ && time-$cust_pay->_date < $refund_days*86400 && $cust_pay->unrefunded > 0 + && $curuser->access_right('Refund payment') ) { $refund = qq! (<A HREF="${p}edit/cust_refund.cgi?payby=$1;!. qq!paynum=!. $cust_pay->paynum. '"'. @@ -178,9 +194,18 @@ foreach my $cust_pay ($cust_main->cust_pay) { my $void = ''; if ( $cust_pay->closed !~ /^Y/i - && ( $cust_pay->payby ne 'CARD' || $conf->exists('cc-void') ) - && ( $cust_pay->payby ne 'CHEK' || $conf->exists('echeck-void') ) - ) { + && ( ( $cust_pay->payby eq 'CARD' + && $curuser->access_right('Credit card void') + ) + || ( $cust_pay->payby eq 'CHEK' + && $curuser->access_right('Echeck void') + ) + || ( $cust_pay->payby !~ /^(CARD|CHEK)$/ + && $curuser->access_right('Regular void') + ) + ) + ) + { $void = qq! (<A HREF="javascript:areyousure('!. qq!${p}misc/void-cust_pay.cgi?!. $cust_pay->paynum. qq!', 'Are you sure you want to void this payment?')"!. @@ -193,7 +218,11 @@ foreach my $cust_pay ($cust_main->cust_pay) { } my $delete = ''; - if ( $cust_pay->closed !~ /^Y/i && $conf->exists('deletepayments') ) { + if ( $cust_pay->closed !~ /^Y/i + && $conf->exists('deletepayments') + && $curuser->access_right('Delete payment') + ) + { $delete = qq! (<A HREF="javascript:areyousure('!. qq!${p}misc/delete-cust_pay.cgi?!. $cust_pay->paynum. qq!', 'Are you sure you want to delete this payment?')"!. @@ -203,8 +232,10 @@ foreach my $cust_pay ($cust_main->cust_pay) { my $unapply = ''; if ( $cust_pay->closed !~ /^Y/i - && $conf->exists('unapplypayments') - && scalar(@cust_bill_pay) ) { + && scalar(@cust_bill_pay) + && $curuser->access_right('Unapply payment') + ) + { $unapply = qq! (<A HREF="javascript:areyousure('!. qq!${p}misc/unapply-cust_pay.cgi?!. $cust_pay->paynum. qq!', 'Are you sure you want to unapply this payment?')"!. @@ -236,7 +267,10 @@ foreach my $cust_pay_void ($cust_main->cust_pay_void) { my $info = $payby ? " ($payby$payinfo)" : ''; my $unvoid = ''; - if ( $cust_pay_void->closed !~ /^Y/i && $conf->exists('unvoid') ) { + if ( $cust_pay_void->closed !~ /^Y/i + && $curuser->access_right('Unvoid') + ) + { $unvoid = qq! (<A HREF="javascript:areyousure('!. qq!${p}misc/unvoid-cust_pay_void.cgi?!. $cust_pay_void->paynum. qq!', 'Are you sure you want to unvoid this payment?')"!. @@ -272,7 +306,7 @@ foreach my $cust_credit ($cust_main->cust_credit) { $post = '</FONT></B>'; $apply = qq! (<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('${p}edit/cust_credit_bill.cgi?!. $cust_credit->crednum. - qq!', 392, 336, 'cust_credit_popup' ), CAPTION, 'Post credit', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK )">apply</A>)!; + qq!', 392, 336, 'cust_credit_bill_popup' ), CAPTION, 'Apply credit', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK ); return false;">apply</A>)!; } elsif ( scalar(@cust_credit_bill) == 1 && scalar(@cust_credit_refund) == 0 && $cust_credit->credited == 0 ) { @@ -297,7 +331,7 @@ foreach my $cust_credit ($cust_main->cust_credit) { } elsif ( $app->isa('FS::cust_credit_refund') ) { $desc .= ' '. '$'. $app->amount. - ' refunded on'. time2str("%D", $app->_date). + ' refunded on '. time2str("%D", $app->_date). '<BR>'; } else { die "$app is not a FS::cust_credit_bill or a FS::cust_credit_refund"; @@ -308,13 +342,21 @@ foreach my $cust_credit ($cust_main->cust_credit) { $cust_credit->credited. ' unapplied</FONT></B>'. qq! (<A HREF="javascript:void(0);" onClick="overlib( OLiframeContent('${p}edit/cust_credit_bill.cgi?!. $cust_credit->crednum. - qq!', 392, 336, 'cust_credit_popup' ), CAPTION, 'Post credit', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK )">apply</A>)!. + qq!', 392, 336, 'cust_credit_bill_popup' ), CAPTION, 'Apply credit', STICKY, AUTOSTATUSCAP, MIDX, 0, MIDY, 0, DRAGGABLE, CLOSECLICK ); return false;">apply</A>)!. '<BR>'; } } # my $delete = ''; - if ( $cust_credit->closed !~ /^Y/i && $conf->exists('deletecredits') ) { + if ( $cust_credit->closed !~ /^Y/i + + #s'pose deleting a credit isn't bad like deleting a payment + # and this needs to be generally available until we have credit voiding.. + #&& $conf->exists('deletecredits') + + && $curuser->access_right('Delete credit') + ) + { $delete = qq! (<A HREF="javascript:areyousure('!. qq!${p}misc/delete-cust_credit.cgi?!. $cust_credit->crednum. qq!', 'Are you sure you want to delete this credit?')">!. @@ -323,8 +365,10 @@ foreach my $cust_credit ($cust_main->cust_credit) { my $unapply = ''; if ( $cust_credit->closed !~ /^Y/i - && $conf->exists('unapplycredits') - && scalar(@cust_credit_bill) ) { + && scalar(@cust_credit_bill) + && $curuser->access_right('Unapply credit') + ) + { $unapply = qq! (<A HREF="javascript:areyousure('!. qq!${p}misc/unapply-cust_credit.cgi?!. $cust_credit->crednum. qq!', 'Are you sure you want to unapply this credit?')">!. @@ -366,37 +410,98 @@ foreach my $cust_refund ($cust_main->cust_refund) { %> -<%= include("/elements/table.html") %> +<%= include("/elements/table-grid.html") %> + +<% my $bgcolor1 = '#eeeeee'; + my $bgcolor2 = '#ffffff'; + my $bgcolor = ''; +%> + <TR> - <TH>Date</TH> - <TH>Description</TH> - <TH><FONT SIZE=-1>Charge</FONT></TH> - <TH><FONT SIZE=-1>Payment</FONT></TH> - <TH><FONT SIZE=-1>In-house<BR>Credit</FONT></TH> - <TH><FONT SIZE=-1>Refund</FONT></TH> - <TH><FONT SIZE=-1>Balance</FONT></TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Date</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Description</TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Charge</FONT></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Payment</FONT></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>In-house<BR>Credit</FONT></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Refund</FONT></TH> + <TH CLASS="grid" BGCOLOR="#cccccc"><FONT SIZE=-1>Balance</FONT></TH> </TR> <% #display payment history -my %target; my $balance = 0; +my %target = (); +my $money_char = $conf->config('money_char') || '$'; + +my $years = $conf->config('payment_history-years') || 2; +my $older_than = time - $years * 31556736; #60*60*24*365.24 +my $hidden = 0; +my $seen = 0; +my $old_history = 0; + foreach my $item ( sort { $a->{'date'} <=> $b->{'date'} } @history ) { + my $display; + if ( $item->{'date'} < $older_than ) { + $display = ' STYLE="display:none" '; + $hidden = 1; + } else { + + $display = ''; + + if ( $hidden && ! $seen++ ) { + ( my $balance_forward = $money_char. $balance ) =~ s/^\$\-/- \$/; + %> + + <TR ID="balance_forward_row"> + <TD CLASS="grid" BGCOLOR="#dddddd"> + <%= time2str("%D",$item->{'date'}) %> + </TD> + + <TD CLASS="grid" BGCOLOR="#dddddd"> + <I>Starting balance on <%= time2str("%D",$item->{'date'}) %></I> + (<A HREF="javascript:void(0);" onClick="show_history();">show prior history</A>) + </TD> + + <TD CLASS="grid" BGCOLOR="#dddddd"></TD> + <TD CLASS="grid" BGCOLOR="#dddddd"></TD> + <TD CLASS="grid" BGCOLOR="#dddddd"></TD> + <TD CLASS="grid" BGCOLOR="#dddddd"></TD> + <TD CLASS="grid" BGCOLOR="#dddddd"><I><%= $balance_forward %></I></TD> + + </TR> + + <% + } + + } + + if ( $bgcolor eq $bgcolor1 ) { + $bgcolor = $bgcolor2; + } else { + $bgcolor = $bgcolor1; + } + my $charge = exists($item->{'charge'}) - ? sprintf('$%.2f', $item->{'charge'}) + ? sprintf("$money_char\%.2f", $item->{'charge'}) : ''; + my $payment = exists($item->{'payment'}) - ? sprintf('- $%.2f', $item->{'payment'}) + ? sprintf("- $money_char\%.2f", $item->{'payment'}) : ''; - $payment ||= sprintf('<DEL>- $%.2f</DEL>', $item->{'void_payment'}) + + $payment ||= sprintf( "<DEL>- $money_char\%.2f</DEL>", + $item->{'void_payment'} + ) if exists($item->{'void_payment'}); + my $credit = exists($item->{'credit'}) - ? sprintf('- $%.2f', $item->{'credit'}) + ? sprintf("- $money_char\%.2f", $item->{'credit'}) : ''; + my $refund = exists($item->{'refund'}) - ? sprintf('$%.2f', $item->{'refund'}) + ? sprintf("$money_char\%.2f", $item->{'refund'}) : ''; my $target = exists($item->{'target'}) ? $item->{'target'} : ''; @@ -407,12 +512,12 @@ foreach my $item ( sort { $a->{'date'} <=> $b->{'date'} } @history ) { $balance += $item->{'refund'} if exists $item->{'refund'}; $balance = sprintf("%.2f", $balance); $balance =~ s/^\-0\.00$/0.00/; #yay ieee fp - ( my $showbalance = '$'. $balance ) =~ s/^\$\-/- \$/; + ( my $showbalance = $money_char. $balance ) =~ s/^\$\-/- \$/; %> - <TR> - <TD> + <TR <%= $display ? $display.' ID="old_history'.$old_history++.'"' : ''%>> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"> <% unless ( !$target || $target{$target}++ ) { %> <A NAME="<%= $target %>"> <% } %> @@ -422,15 +527,44 @@ foreach my $item ( sort { $a->{'date'} <=> $b->{'date'} } @history ) { <% } %> </FONT> </TD> - <TD><%= $item->{'desc'} %></TD> - <TD ALIGN="right"><%= $charge %></TD> - <TD ALIGN="right"><%= $payment %></TD> - <TD ALIGN="right"><%= $credit %></TD> - <TD ALIGN="right"><%= $refund %></TD> - <TD ALIGN="right"><%= $showbalance %></TD> + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"> + <%= $item->{'desc'} %> + </TD> + <TD ALIGN="right" CLASS="grid" BGCOLOR="<%= $bgcolor %>"> + <%= $charge %> + </TD> + <TD ALIGN="right" CLASS="grid" BGCOLOR="<%= $bgcolor %>"> + <%= $payment %> + </TD> + <TD ALIGN="right" CLASS="grid" BGCOLOR="<%= $bgcolor %>"> + <%= $credit %> + </TD> + <TD ALIGN="right" CLASS="grid" BGCOLOR="<%= $bgcolor %>"> + <%= $refund %> + </TD> + <TD ALIGN="right" CLASS="grid" BGCOLOR="<%= $bgcolor %>"> + <%= $showbalance %> + </TD> </TR> <% } %> </TABLE> +<SCRIPT TYPE="text/javascript"> + +function show_history () { + //alert('showing history!'); + + var balance_forward_row = document.getElementById('balance_forward_row'); + + balance_forward_row.style.display = 'none'; + for ( var i = 0; i < <%= $old_history %>; i++ ) { + var oldRow = document.getElementById('old_history'+i); + oldRow.style.display = ''; + } + +} + +</SCRIPT> + diff --git a/httemplate/view/cust_main/tickets.html b/httemplate/view/cust_main/tickets.html index 5c1d94ee1..93cb51f25 100644 --- a/httemplate/view/cust_main/tickets.html +++ b/httemplate/view/cust_main/tickets.html @@ -2,7 +2,7 @@ my( $cust_main ) = @_; my $conf = new FS::Conf; - my $num = 10; + my $num = $conf->config('cust_main-max_tickets') || 10; my @tickets = (); unless ( $conf->config('ticket_system-custom_priority_field') ) { @@ -31,24 +31,46 @@ Highest priority tickets (<A HREF="<%= FS::TicketSystem->href_customer_tickets($cust_main->custnum) %>">View all tickets for this customer</A>) (<A HREF="<%= FS::TicketSystem->href_new_ticket($cust_main, join(', ', grep { $_ !~ /^(POST|FAX)$/ } $cust_main->invoicing_list ) ) %>">New ticket for this customer</A>) -<%= include("/elements/table.html") %> + +<%= include("/elements/table-grid.html") %> + +<% my $bgcolor1 = '#eeeeee'; + my $bgcolor2 = '#ffffff'; + my $bgcolor = ''; +%> + <TR> - <TH>#</TH> - <TH>Subject</TH> - <TH>Priority</TH> - <TH>Queue</TH> - <TH>Status</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">#</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Subject</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Priority</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Queue</TH> + <TH CLASS="grid" BGCOLOR="#cccccc">Status</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><A HREF=<%=$href%>><%= $ticket->{id} %></A></TD> - <TD><A HREF=<%=$href%>><%= $ticket->{subject} %></A></TD> - <TD ALIGN="right"><%= $ticket->{content} || $ticket->{priority} %></TD> - <TD><%= $ticket->{name} %></TD> - <TD><%= $ticket->{status} %></TD> + + <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 ALIGN="right" CLASS="grid" BGCOLOR="<%= $bgcolor %>"><%= $ticket->{content} || $ticket->{priority} %></TD> + + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"><%= $ticket->{name} %></TD> + + <TD CLASS="grid" BGCOLOR="<%= $bgcolor %>"><%= $ticket->{status} %></TD> + </TR> + <% } %> + </TABLE> diff --git a/httemplate/view/elements/svc_Common.html b/httemplate/view/elements/svc_Common.html new file mode 100644 index 000000000..0f103e3e0 --- /dev/null +++ b/httemplate/view/elements/svc_Common.html @@ -0,0 +1,116 @@ +<% + + # options example... + # + # 'table' => 'svc_something' + # + # 'labels' => { + # 'column' => 'Label', + # }, + # + # listref - each item is a literal column name (or method) or (notyet) coderef + # if not specified all columns (except for the primary key) will be viewable + # 'fields' => [ + # ] + + my(%opt) = @_; + + my $table = $opt{'table'}; + + my $fields = $opt{'fields'} + #|| [ grep { $_ ne 'svcnum' } dbdef->table($table)->columns ]; + || [ grep { $_ ne 'svcnum' } fields($table) ]; + + my($query) = $cgi->keywords; + $query =~ /^(\d+)$/; + my $svcnum = $1; + my $svc_x = qsearchs( $opt{'table'}, { 'svcnum' => $svcnum } ) + or die "Unknown svcnum $svcnum in ". $opt{'table'}. " table\n"; + + my $cust_svc = $svc_x->cust_svc; + my($label, $value, $svcdb) = $cust_svc->label; + + my $pkgnum = $cust_svc->pkgnum; + + my($cust_pkg, $custnum); + if ($pkgnum) { + $cust_pkg = $cust_svc->cust_pkg; + $custnum = $cust_pkg->custnum; + } else { + $cust_pkg = ''; + $custnum = ''; + } + +%> + +<% if ( $custnum ) { %> + + <%= include("/elements/header.html","View $label: $value", menubar( + "View this customer (#$custnum)" => "${p}view/cust_main.cgi?$custnum", + )) %> + + <%= include( '/elements/small_custview.html', $custnum, '', 1 ) %> + <BR> + +<% } else { %> + + <SCRIPT> + function areyousure(href) { + if (confirm("Permanently delete this <%= $label %>?") == true) + window.location.href = href; + } + </SCRIPT> + + <%= include("/elements/header.html","View $label: $value", menubar( + "Cancel this (unaudited) $label" => + "javascript:areyousure(\'${p}misc/cancel-unaudited.cgi?$svcnum\')" + )) %> + +<% } %> + +Service #<B><%= $svcnum %></B> +| <A HREF="<%=$p%>edit/<%= $opt{'table'} %>.cgi?<%=$svcnum%>">Edit this <%= $label %></A> +<BR> + +<%= ntable("#cccccc") %><TR><TD><%= ntable("#cccccc",2) %> + +<% foreach my $f ( @$fields ) { + + my( $field, $type); + if ( ref($f) ) { + $field = $f->{'field'}, + $type = $f->{'type'} || 'text', + } else { + $field = $f; + $type = 'text'; + } +%> + + <TR> + <TD ALIGN="right"> + <%= ( $opt{labels} && exists $opt{labels}->{$field} ) + ? $opt{labels}->{$field} + : $field + %> + </TD> + + <% + #eventually more options for <SELECT>, etc. fields + %> + + <TD BGCOLOR="#ffffff"><%= $svc_x->$field %><TD> + + </TR> + +<% } %> + +<% foreach (sort { $a cmp $b } $svc_x->virtual_fields) { %> + <%= $svc_x->pvf($_)->widget('HTML', 'view', $svc_x->getfield($_)) %> +<% } %> + +</TABLE></TD></TR></TABLE> + +<BR> +<%= joblisting({'svcnum'=>$svcnum}, 1) %> + +<%= include('/elements/footer.html') %> diff --git a/httemplate/view/svc_external.cgi b/httemplate/view/svc_external.cgi index 2acc3f9cf..7816d88dc 100644 --- a/httemplate/view/svc_external.cgi +++ b/httemplate/view/svc_external.cgi @@ -1,4 +1,3 @@ -<!-- mason kludge --> <% my($query) = $cgi->keywords; diff --git a/httemplate/view/svc_phone.cgi b/httemplate/view/svc_phone.cgi new file mode 100644 index 000000000..8de7cc8e7 --- /dev/null +++ b/httemplate/view/svc_phone.cgi @@ -0,0 +1,10 @@ +<%= include('elements/svc_Common.html', + 'table' => 'svc_phone', + 'fields' => [qw( countrycode phonenum )], #pin + 'labels' => { + 'countrycode' => 'Country code', + 'phonenum' => 'Phone number', + 'pin' => 'PIN', + }, + ) +%> |