diff options
author | Ivan Kohler <ivan@freeside.biz> | 2015-08-07 22:01:31 -0700 |
---|---|---|
committer | Ivan Kohler <ivan@freeside.biz> | 2015-08-07 22:01:31 -0700 |
commit | 0c76afbb717e1716e6126bc4a120b8d9471614a0 (patch) | |
tree | 9a398e455a7767372588077470685d25ef8d82b3 /httemplate/misc | |
parent | 7beec7068e00be5ae1b2599fdf2b494bc19e31d0 (diff) | |
parent | 3e2c2ad8aff1bd361ca07495b2255538c8231079 (diff) |
Merge branch 'FREESIDE_3_BRANCH' of git.freeside.biz:/home/git/freeside into FREESIDE_3_BRANCH
Diffstat (limited to 'httemplate/misc')
-rw-r--r-- | httemplate/misc/batch-cust_pay.html | 96 | ||||
-rwxr-xr-x | httemplate/misc/change_pkg.cgi | 13 | ||||
-rw-r--r-- | httemplate/misc/email-customer-statement.html | 95 | ||||
-rw-r--r-- | httemplate/misc/email-customers.html | 98 | ||||
-rw-r--r-- | httemplate/misc/process/batch-cust_pay.cgi | 7 | ||||
-rw-r--r-- | httemplate/misc/process/delete-cust_pay_batch.cgi | 37 | ||||
-rw-r--r-- | httemplate/misc/process/email-customer-statement.html | 9 | ||||
-rw-r--r-- | httemplate/misc/process/nms-add_iface.html | 2 |
8 files changed, 299 insertions, 58 deletions
diff --git a/httemplate/misc/batch-cust_pay.html b/httemplate/misc/batch-cust_pay.html index cc1a26a0e..9f2540cc7 100644 --- a/httemplate/misc/batch-cust_pay.html +++ b/httemplate/misc/batch-cust_pay.html @@ -26,11 +26,30 @@ function warnUnload() { } window.onbeforeunload = warnUnload; -function add_row_callback(rownum, prefix) { - document.getElementById('enable_app'+rownum).disabled = true; +function add_row_callback(rownum, values) { + if (values) { + custnum_update_callback(rownum); + } else { + document.getElementById('enable_app'+rownum).disabled = true; + } +} + +function delete_row_callback(rownum) { + var i = 0; + var delbutton = document.getElementById('delete'+rownum+'.'+i); + var delrows = []; + while (delbutton) { + delrows[i] = delbutton; + i++; + delbutton = document.getElementById('delete'+rownum+'.'+i); + } + delrows = delrows.reverse(); + for (i = 0; i < delrows.length; i++) { + delrows[i].onclick(); + } } -function custnum_update_callback(rownum, prefix) { +function custnum_update_callback(rownum) { var custnum = document.getElementById('custnum'+rownum).value; // if there is a custnum and more than one open invoice, enable // (and check) the box @@ -39,17 +58,17 @@ function custnum_update_callback(rownum, prefix) { enable_app_checkbox.disabled = show_applications; % if ( $use_discounts ) { - select_discount_term(rownum, prefix); + select_discount_term(rownum); % } } -function invnum_update_callback(rownum, prefix) { - custnum_update_callback(rownum, prefix); +function invnum_update_callback(rownum) { + custnum_update_callback(rownum); } -function select_discount_term(row, prefix) { - var custnum_obj = document.getElementById('custnum'+prefix+row); - var select_obj = document.getElementById('discount_term'+prefix+row); +function select_discount_term(row) { + var custnum_obj = document.getElementById('custnum'+row); + var select_obj = document.getElementById('discount_term'+row); var value = ''; if (select_obj.type == 'hidden') { @@ -313,17 +332,17 @@ function create_application_row(rownum, appnum) { %# for error handling--ugly, but the alternative is translating the whole %# process of creating rows into Mason -var row_array = <% encode_json(\@rows) %>; +var row_obj = <% encode_json(\%rows) %>; function preload() { var rownum; var appnum; - for (rownum=0; rownum < row_array.length; rownum++) { - if ( row_array[rownum].length ) { + for (rownum in row_obj) { + if ( row_obj[rownum].length ) { var enable = document.getElementById('enable_app'+rownum); enable.checked = true; var preload_row = function(r) {//continuation from toggle_application_row - for (appnum=0; appnum < row_array[r].length; appnum++) { - this_app = row_array[r][appnum]; + for (appnum=0; appnum < row_obj[r].length; appnum++) { + this_app = row_obj[r][appnum]; var x = r + '.' + appnum; //set invnum var select_invnum = document.getElementById('invnum'+x); @@ -345,7 +364,7 @@ function preload() { } //for appnum }; //preload_row function toggle_application_row.call(enable, null, preload_row); - } // if row_array[rownum].length + } // if (row_obj[rownum].length } //for rownum } @@ -380,6 +399,7 @@ function preload() { custnum_update_callback => 'custnum_update_callback', invnum_update_callback => 'invnum_update_callback', add_row_callback => 'add_row_callback', + delete_row_callback => 'delete_row_callback', &> <BR> @@ -387,13 +407,12 @@ function preload() { </FORM> -%if ( $cgi->param('error') ) { -<SCRIPT TYPE="text/javascript"> -% for ( my $row = 0; defined($cgi->param("custnum$row")); $row++ ) { - select_discount_term(<% $row %>, ''); -% } -</SCRIPT> -%} +% #XXX I think this can go away completely, but need to test with $use_discount +% ###not perl <SCRIPT TYPE="text/javascript"> +% #foreach my $row ( keys %rows ) { +% ###not perl select_discount_term(<% $row %>, ''); +% #} +% ###not perl </SCRIPT> <% include('/elements/footer.html') %> @@ -417,6 +436,7 @@ my @footer_align = ( 'r', 'r' ); my @onchange = ( '', '' );; my $use_discounts = ''; +# Not entirely sure this works anymore... if ( FS::Record->scalar_sql('SELECT COUNT(*) FROM part_pkg_discount') ) { #push @header, 'Discount'; push @header, ''; @@ -441,6 +461,16 @@ push @footer, ''; push @footer_align, ''; push @onchange, 'toggle_application_row'; +push @header, 'No Auto Allocate'; +push @fields, 'no_auto_apply'; +push @types, 'checkbox'; +push @align, 'c'; +push @sizes, '0'; +push @colors, ''; +push @footer, ''; +push @footer_align, ''; +push @onchange, ''; + #push @header, 'Error'; push @header, ''; push @fields, 'error'; @@ -455,29 +485,31 @@ push @onchange, ''; $m->comp('/elements/handle_uri_query'); # set up for preloading -my @rows; -my @row_errors; +my %rows; +my %row_errors; if ( $cgi->param('error') ) { my $param = $cgi->Vars; my $enum = 0; #errors numbered separately - for( my $row = 0; exists($param->{"custnum$row"}); $row++ ) { - $rows[$row] = []; - $row_errors[$row] = $param->{"error$enum"}; + my @invrows = grep /^invnum\d+\.\d+$/, keys %$param; #pare down possibilities + foreach my $row ( sort { $a <=> $b } map /^custnum(\d+)$/, keys %$param ) { +# for( my $row = 0; exists($param->{"custnum$row"}); $row++ ) { + $rows{$row} = []; + $row_errors{$row} = $param->{"error$enum"}; $enum++; - for( my $app = 0; exists($param->{"invnum$row.$app"}); $app++ ) { + foreach my $app ( map /^invnum$row\.(\d+)$/, @invrows ) { next if !$param->{"invnum$row.$app"}; my %this_app = map { $_ => ($param->{$_.$row.'.'.$app} || '') } qw( invnum amount ); $this_app{'error'} = $param->{"error$enum"} || ''; $param->{"error$enum"} = ''; # don't pass this error through - $rows[$row][$app] = \%this_app; + $rows{$row}[$app] = \%this_app; $enum++; } } - for( my $row = 0; $row < @row_errors; $row++ ) { - $param->{"error$row"} = $row_errors[$row]; + foreach my $row (keys %rows) { + $param->{"error$row"} = $row_errors{$row}; } } -#warn Dumper {rows => \@rows, row_errors => \@row_errors }; +#warn Dumper {rows => \%rows, row_errors => \%row_errors }; </%init> diff --git a/httemplate/misc/change_pkg.cgi b/httemplate/misc/change_pkg.cgi index 1b4a94e81..e74747e82 100755 --- a/httemplate/misc/change_pkg.cgi +++ b/httemplate/misc/change_pkg.cgi @@ -28,6 +28,14 @@ 'curr_value' => $cust_pkg->quantity &> +% if ($use_contract_end) { + <& /elements/tr-input-date-field.html, { + 'name' => 'contract_end', + 'value' => ($cgi->param('contract_end') || $cust_pkg->get('contract_end')), + 'label' => '<B>Contract End</B>', + } &> +% } + </TABLE> <BR> @@ -124,6 +132,8 @@ my $part_pkg = $cust_pkg->part_pkg; my $title = "Change Package"; +my $use_contract_end = $cust_pkg->get('contract_end') ? 1 : 0; + # if there's already a package change ordered, preload it if ( $cust_pkg->change_to_pkgnum ) { my $change_to = FS::cust_pkg->by_key($cust_pkg->change_to_pkgnum); @@ -131,6 +141,9 @@ if ( $cust_pkg->change_to_pkgnum ) { foreach(qw( start_date pkgpart locationnum quantity )) { $cgi->param($_, $change_to->get($_)); } + if ($use_contract_end) { + $cgi->param('contract_end', $change_to->get('contract_end')); + } $title = "Edit Scheduled Package Change"; } </%init> diff --git a/httemplate/misc/email-customer-statement.html b/httemplate/misc/email-customer-statement.html new file mode 100644 index 000000000..c0ed88031 --- /dev/null +++ b/httemplate/misc/email-customer-statement.html @@ -0,0 +1,95 @@ + + <% include('email-customers.html', + 'form_action' => 'email-customer-statement.html', + 'title' => 'Send statement to customer', + 'no_search_fields' => [ 'start_date', 'end_date' ], + 'alternate_form' => $alternate_form, + 'post_search_hook' => $post_search_hook, + 'acl' => $acl, + 'process_url' => 'process/email-customer-statement.html', + ) + %> + +<%init> + +my $acl = 'Resend invoices'; + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right($acl); + +my $alternate_form = sub { + # this could maaaybe be a separate element, for cleanliness + # but it's really only for use by this page, and it's not overly complicated + my $noinit = 0; + return join("\n", + '<TABLE BORDER="0">', + ( + map { + my $label = ucfirst($_); + $label =~ s/_/ /; + include('/elements/tr-input-date-field.html',{ + 'name' => $_, + 'value' => $cgi->param($_) || '', + 'label' => $label, + 'noinit' => $noinit++ + }); + } + qw( start_date end_date ) + ), + '</TABLE>', + '<INPUT TYPE="hidden" NAME="action" VALUE="preview">', + '<INPUT TYPE="submit" VALUE="Preview notice">', + ); +}; + +my $post_search_hook = sub { + my %opt = @_; + return unless $cgi->param('action') eq 'preview'; + my $cust_main = qsearchs('cust_main',$opt{'search'}) + or die "Could not find customer"; + + # so that the statement indicates the latest date + my $date_format = $opt{'conf'}->config('date_format') || '%m/%d/%Y'; + $cgi->param('end_date', time2str($date_format, time)) + unless $cgi->param('end_date'); + + # set from/subject/html_body based on date range + + $cgi->param('from', + $opt{'conf'}->config('invoice_from') + ); + + # shortcut for common text + my $summary_text = $cust_main->name_short . + ($cgi->param('start_date') ? ' from ' : '') . + $cgi->param('start_date') . + ($cgi->param('end_date') ? ' through ' : '') . + $cgi->param('end_date'); + + $cgi->param('subject', + $opt{'conf'}->config('company_name') . + ' statement for ' . + $summary_text + ); + + $cgi->param('html_body', + '<P>' . + $opt{'conf'}->config('company_name') . + ' statement of charges and payments for ' . + $summary_text . + "</P>" . + include('/elements/customer-statement.html', + 'history' => [ + $cust_main->payment_history( + map { + $_ => parse_datetime(scalar($cgi->param($_))) + } + qw( start_date end_date ), + ), + ], + ) + ); +}; + +</%init> + diff --git a/httemplate/misc/email-customers.html b/httemplate/misc/email-customers.html index 83e86158f..09ff93cca 100644 --- a/httemplate/misc/email-customers.html +++ b/httemplate/misc/email-customers.html @@ -1,3 +1,35 @@ +<%doc> + +Allows emailing one or more customers, based on a search for customers. Search can +be specified either through cust_main fields as cgi params, or through a base64 encoded +frozen hash in the 'search' cgi param. Form allows selecting an existing msg_template, +or creating a custom message, and shows a preview of the message before sending. +If linked to as a popup, include the cgi parameter 'popup' for proper header handling. + +This may also be used as an element in other pages, enabling you to provide an +alternate initial form while using this for search freezing/thawing and +preview/send actions, with the following options: + +acl - the access right to use (defaults to 'Bulk send customer notices') + +form_action - the URL to submit the form to + +process_url - the URL for starting the JSRPC process + +title - the title of the page + +no_search_fields - arrayref of additional fields that are not search parameters + +alternate_form - subroutine that returns alternate html for the initial form, +replaces msgnum/from/subject/html_body/action inputs and submit button, +not used if an action is specified + +post_search_hook - sub hook for additional processing after search has been processed from cgi, +gets passed options 'conf' and 'search' (a reference to the unfrozen %search hash), +should be used to set msgnum or from/subject/html_body cgi params + +</%doc> + % if ($popup) { <% include('/elements/header-popup.html', $title) %> % } else { @@ -5,7 +37,7 @@ % } -<FORM NAME="OneTrueForm" ACTION="email-customers.html" METHOD="POST"> +<FORM NAME="OneTrueForm" ACTION="<% $form_action %>" METHOD="POST"> <INPUT TYPE="hidden" NAME="table" VALUE="<% $table %>"> %# Mixing search params with from address, subject, etc. required special-case %# handling of those, risked name conflicts, and caused massive problems with @@ -19,13 +51,12 @@ <FONT SIZE="+2">Sending notice</FONT> - <% include('/elements/progress-init.html', + <& /elements/progress-init.html, 'OneTrueForm', [ qw( search table from subject html_body text_body msgnum ) ], - 'process/email-customers.html', + $process_url, $pdest, - ) - %> + &> % } elsif ( $cgi->param('action') eq 'preview' ) { @@ -36,7 +67,7 @@ % if ( $cgi->param('action') ) { <TABLE BGCOLOR="#cccccc" CELLSPACING=0> - <INPUT TYPE="hidden" NAME="msgnum" VALUE="<% $cgi->param('msgnum') %>"> + <INPUT TYPE="hidden" NAME="msgnum" VALUE="<% scalar($cgi->param('msgnum')) %>"> % if ( $msg_template ) { <% include('/elements/tr-fixed.html', @@ -62,7 +93,7 @@ <INPUT TYPE="hidden" NAME="html_body" VALUE="<% $html_body |h %>"> <TR> - <TD ALIGN="right" VALIGN="top">Message (HTML display): </TD> + <TH ALIGN="right" VALIGN="top">Message (HTML display): </TD> <TD CLASS="background" ALIGN="left"><% $html_body %></TD> </TR> @@ -73,13 +104,16 @@ % ); <INPUT TYPE="hidden" NAME="text_body" VALUE="<% $text_body |h %>"> <TR> - <TD ALIGN="right" VALIGN="top">Message (Text display): </TD> - <TD CLASS="background" STYLE="background-color:white" ALIGN="left"><PRE><% $text_body %></PRE></TD> + <TH ALIGN="right" VALIGN="top">Message (Text display): </TD> + <TD CLASS="background" STYLE="background-color:white" ALIGN="left"> + <a href="javascript:void(0)" onclick="this.style.display='none'; document.getElementById('email-message-text').style.display=''">click to view</a> + <PRE id="email-message-text" style="display: none;"><% $text_body %></PRE> + </TD> </TR> </TABLE> -% if ( $cgi->param('action') eq 'preview' ) { +% if ( $cgi->param('action') eq 'preview' ) { <SCRIPT> function areyousure(href) { @@ -93,6 +127,10 @@ % } +% } elsif ($opt{'alternate_form'}) { + +<% &{$opt{'alternate_form'}}() %> + % } else { <SCRIPT TYPE="text/javascript"> @@ -121,12 +159,11 @@ Template: 'size' => 20, &>></TD> - <% include('/elements/tr-input-text.html', + <& /elements/tr-input-text.html, 'field' => 'subject', 'label' => 'Subject:', 'size' => 50, - ) - %> + &> <TR> <TD ALIGN="right" VALIGN="top" STYLE="padding-top:3px">Message: </TD> @@ -144,7 +181,7 @@ Template: <INPUT TYPE="hidden" NAME="action" VALUE="preview"> <INPUT TYPE="submit" VALUE="Preview notice"> -% } +% } #end not action or alternate form </FORM> @@ -154,14 +191,24 @@ Template: </SCRIPT> % } -<% include('/elements/footer.html') %> +<& /elements/footer.html &> <%init> +my %opt = @_; + +$opt{'acl'} ||= 'Bulk send customer notices'; + die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Bulk send customer notices'); + unless $FS::CurrentUser::CurrentUser->access_right($opt{'acl'}); my $conf = FS::Conf->new; +my @no_search_fields = qw( action table from subject html_body text_body popup url ); + +my $form_action = $opt{'form_action'} || 'email-customers.html'; +my $process_url = $opt{'process_url'} || 'process/email-customers.html'; +my $title = $opt{'title'} || 'Send customer notices'; +push( @no_search_fields, @{$opt{'no_search_fields'}} ) if $opt{'no_search_fields'}; my $table = $cgi->param('table') or die "'table' required"; my $agent_virt_agentnum = $cgi->param('agent_virt_agentnum') || ''; @@ -173,19 +220,22 @@ $pdest->{'url'} = $cgi->param('url') if $url; my %search; if ( $cgi->param('search') ) { - %search = %{ thaw(decode_base64($cgi->param('search'))) }; + %search = %{ thaw(decode_base64( $cgi->param('search') )) }; } else { %search = $cgi->Vars; - delete $search{$_} for qw( action table from subject html_body text_body popup url ); + delete $search{$_} for @no_search_fields; # FS::$table->search is expected to know which parameters might be # multi-valued, and to accept scalar values for them also. No good # solution to this since CGI can't tell whether a parameter _might_ # have had multiple values, only whether it does. @search{keys %search} = map { /\0/ ? [ split /\0/, $_ ] : $_ } values %search; -} +} -my $title = 'Send customer notices'; +&{$opt{'post_search_hook'}}( + 'conf' => $conf, + 'search' => \%search, +) if $opt{'post_search_hook'}; my $num_cust; my $from = ''; @@ -203,6 +253,7 @@ my $html_body = $cgi->param('html_body') || ''; my $msg_template = ''; if ( $cgi->param('action') eq 'preview' ) { + my $sql_query = "FS::$table"->search(\%search); my $count_query = delete($sql_query->{'count_query'}); my $count_sth = dbh->prepare($count_query) @@ -214,17 +265,18 @@ if ( $cgi->param('action') eq 'preview' ) { if ( $cgi->param('msgnum') ) { $msg_template = qsearchs('msg_template', - { msgnum => $cgi->param('msgnum') } ) + { msgnum => scalar($cgi->param('msgnum')) } ) or die "template not found: ".$cgi->param('msgnum'); $sql_query->{'extra_sql'} .= ' LIMIT 1'; $sql_query->{'select'} = "$table.*"; $sql_query->{'order_by'} = ''; my $object = qsearchs($sql_query); my $cust = $object->cust_main; - my %message = $msg_template->prepare( + my %msgopts = ( 'cust_main' => $cust, - 'object' => $object + 'object' => $object, ); + my %message = $msg_template->prepare(%msgopts); ($from, $subject, $html_body) = @message{'from', 'subject', 'html_body'}; } } diff --git a/httemplate/misc/process/batch-cust_pay.cgi b/httemplate/misc/process/batch-cust_pay.cgi index 1105af943..ff7886239 100644 --- a/httemplate/misc/process/batch-cust_pay.cgi +++ b/httemplate/misc/process/batch-cust_pay.cgi @@ -12,7 +12,8 @@ my $paybatch = time2str('webbatch-%Y/%m/%d-%T'. "-$$-". rand() * 2**32, time); my @cust_pay = (); #my $row = 0; #while ( exists($param->{"custnum$row"}) ) { -for ( my $row = 0; exists($param->{"custnum$row"}); $row++ ) { +my @invrows = grep(/^invnum\d+\.\d+$/, keys %$param); +foreach my $row ( map /^custnum(\d+)$/, keys %$param ) { my $custnum = $param->{"custnum$row"}; my $cust_main; if ( $custnum =~ /^(\d+)$/ and $1 <= 2147483647 ) { @@ -39,6 +40,7 @@ for ( my $row = 0; exists($param->{"custnum$row"}); $row++ ) { 'payinfo' => $param->{"payinfo$row"}, 'discount_term' => $param->{"discount_term$row"}, 'paybatch' => $paybatch, + 'no_auto_apply' => exists($param->{"no_auto_apply$row"}) ? 'Y' : '', } if $param->{"custnum$row"} || $param->{"paid$row"} @@ -48,7 +50,8 @@ for ( my $row = 0; exists($param->{"custnum$row"}); $row++ ) { # payment applications, if any my @cust_bill_pay = (); - for ( my $app = 0; exists($param->{"invnum$row.$app"}); $app++ ) { + foreach my $app ( sort {$a <=> $b} map /^invnum$row\.(\d+)$/, @invrows ) { +# for ( my $app = 0; exists($param->{"invnum$row.$app"}); $app++ ) { next if !$param->{"invnum$row.$app"}; push @cust_bill_pay, new FS::cust_bill_pay { 'invnum' => $param->{"invnum$row.$app"}, diff --git a/httemplate/misc/process/delete-cust_pay_batch.cgi b/httemplate/misc/process/delete-cust_pay_batch.cgi new file mode 100644 index 000000000..4937b58e2 --- /dev/null +++ b/httemplate/misc/process/delete-cust_pay_batch.cgi @@ -0,0 +1,37 @@ +<% $server->process %> +<%init> + +my $curuser = $FS::CurrentUser::CurrentUser; + +die "access denied" + unless $curuser->access_right('Process batches') + || $curuser->access_right('Process global batches'); + +# look up paybatch using agentnums_sql & status constraints +# to validate access for this particular cust_pay_batch, +# similar to how it's done in cust_pay_batch.cgi + +my %arg = $cgi->param('arg'); +my $paybatchnum = $arg{'paybatchnum'}; +$paybatchnum =~ /^\d+$/ or die "Illegal paybatchnum"; +my @search = (); +push @search, 'cust_pay_batch.paybatchnum = ' . $paybatchnum; +push @search, '(cust_pay_batch.status = \'\' OR cust_pay_batch.status IS NULL)'; +push @search, 'pay_batch.status = \'O\''; +push @search, $curuser->agentnums_sql({ table => 'cust_main' }); +push @search, $curuser->agentnums_sql({ table => 'pay_batch', + null_right => 'Process global batches', + }); +my $search = ' WHERE ' . join(' AND ', @search); +die "permission denied" unless qsearchs({ + 'table' => 'cust_pay_batch', + 'hashref' => {}, + 'addl_from' => 'LEFT JOIN pay_batch USING ( batchnum ) '. + 'LEFT JOIN cust_main USING ( custnum ) '. + 'LEFT JOIN cust_pay USING ( batchnum, custnum ) ', + 'extra_sql' => $search +}); + +my $server = new FS::UI::Web::JSRPC 'FS::cust_pay_batch::process_unbatch_and_delete', $cgi; + +</%init> diff --git a/httemplate/misc/process/email-customer-statement.html b/httemplate/misc/process/email-customer-statement.html new file mode 100644 index 000000000..40a8a702a --- /dev/null +++ b/httemplate/misc/process/email-customer-statement.html @@ -0,0 +1,9 @@ +<% $server->process %> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Resend invoices'); + +my $server = new FS::UI::Web::JSRPC 'FS::cust_main_Mixin::process_email_search_result', $cgi; + +</%init> diff --git a/httemplate/misc/process/nms-add_iface.html b/httemplate/misc/process/nms-add_iface.html index d21b3792a..79e685686 100644 --- a/httemplate/misc/process/nms-add_iface.html +++ b/httemplate/misc/process/nms-add_iface.html @@ -1,4 +1,4 @@ -<& /elements/header-popup.html, 'Interface added') &> +<& /elements/header-popup.html, 'Interface added' &> <SCRIPT TYPE="text/javascript"> window.top.location.reload(); </SCRIPT> |