From b782294eb91805f708a7776fe67f1c0863f4096b Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 26 Jan 2006 15:27:10 +0000 Subject: whew, FINALLY can fix monthly exemption columns to work correctly. also make them agent-specific. also fix package exemption columns, they were bunk too, sheesh. start adding package classes for package class tax reporting. --- httemplate/search/cust_bill_pkg.cgi | 32 ++++-- httemplate/search/cust_tax_exempt_pkg.cgi | 143 ++++++++++++++++++++++++ httemplate/search/report_tax.cgi | 179 +++++++++++++++++------------- httemplate/search/report_tax.html | 30 ++++- 4 files changed, 291 insertions(+), 93 deletions(-) create mode 100644 httemplate/search/cust_tax_exempt_pkg.cgi (limited to 'httemplate') diff --git a/httemplate/search/cust_bill_pkg.cgi b/httemplate/search/cust_bill_pkg.cgi index 082ccc893..cc0f97536 100644 --- a/httemplate/search/cust_bill_pkg.cgi +++ b/httemplate/search/cust_bill_pkg.cgi @@ -4,7 +4,7 @@ my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi); my $join_cust = " JOIN cust_bill USING ( invnum ) - JOIN cust_main USING ( custnum ) + LEFT JOIN cust_main USING ( custnum ) "; my $join_pkg = " @@ -17,6 +17,10 @@ my $where = " AND payby != 'COMP' "; +if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { + $where .= " AND agentnum = $1 "; +} + if ( $cgi->param('out') ) { $where .= " @@ -62,19 +66,27 @@ my $count_query; if ( $cgi->param('pkg_tax') ) { $count_query = - "SELECT COUNT(*), SUM( ( CASE WHEN part_pkg.setuptax = 'Y' - THEN cust_bill_pkg.setup - ELSE 0 ) - + - ( CASE WHEN part_pkg.recurtax = 'Y' - THEN cust_bill_pkg.recur - ELSE 0 ) - )"; + "SELECT COUNT(*), SUM( + ( CASE WHEN part_pkg.setuptax = 'Y' + THEN cust_bill_pkg.setup + ELSE 0 + END + ) + + + ( CASE WHEN part_pkg.recurtax = 'Y' + THEN cust_bill_pkg.recur + ELSE 0 + END + ) + ) + "; $where .= " AND ( ( part_pkg.setuptax = 'Y' AND cust_bill_pkg.setup > 0 ) OR ( part_pkg.recurtax = 'Y' AND cust_bill_pkg.recur > 0 ) - )"; + ) + AND ( tax != 'Y' OR tax IS NULL ) + "; } else { diff --git a/httemplate/search/cust_tax_exempt_pkg.cgi b/httemplate/search/cust_tax_exempt_pkg.cgi new file mode 100644 index 000000000..bc1e743b2 --- /dev/null +++ b/httemplate/search/cust_tax_exempt_pkg.cgi @@ -0,0 +1,143 @@ +<% + +my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi); + +my $join_cust = " + JOIN cust_bill USING ( invnum ) + LEFT JOIN cust_main USING ( custnum ) +"; + +my $join_pkg = " + LEFT JOIN cust_pkg USING ( pkgnum ) + LEFT JOIN part_pkg USING ( pkgpart ) +"; + +my $join = " + JOIN cust_bill_pkg USING ( billpkgnum ) + $join_cust + $join_pkg +"; + +my $where = " + WHERE _date >= $beginning AND _date <= $ending +"; +# AND payby != 'COMP' + +if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { + $where .= " AND agentnum = $1 "; +} + +if ( $cgi->param('out') ) { + + $where .= " + AND 0 = ( + SELECT COUNT(*) FROM cust_main_county AS county_out + WHERE ( county_out.county = cust_main.county + OR ( county_out.county IS NULL AND cust_main.county = '' ) + OR ( county_out.county = '' AND cust_main.county IS NULL) + OR ( county_out.county IS NULL AND cust_main.county IS NULL) + ) + AND ( county_out.state = cust_main.state + OR ( county_out.state IS NULL AND cust_main.state = '' ) + OR ( county_out.state = '' AND cust_main.state IS NULL ) + OR ( county_out.state IS NULL AND cust_main.state IS NULL ) + ) + AND county_out.country = cust_main.country + AND county_out.tax > 0 + ) + "; + +} elsif ( $cgi->param('country' ) ) { + + my $county = dbh->quote( $cgi->param('county') ); + my $state = dbh->quote( $cgi->param('state') ); + my $country = dbh->quote( $cgi->param('country') ); + $where .= " + AND ( county = $county OR $county = '' ) + AND ( state = $state OR $state = '' ) + AND country = $country + "; + $where .= ' AND taxclass = '. dbh->quote( $cgi->param('taxclass') ) + if $cgi->param('taxclass'); + +} + +my $count_query = "SELECT COUNT(*), SUM(amount)". + " FROM cust_tax_exempt_pkg $join $where"; + +my $query = { + 'table' => 'cust_tax_exempt_pkg', + 'addl_from' => $join, + 'hashref' => {}, + 'select' => join(', ', + 'cust_tax_exempt_pkg.*', + #'cust_bill_pkg.*', + #'cust_bill._date', + #'part_pkg.pkg', + 'cust_main.custnum', + FS::UI::Web::cust_sql_fields(), + ), + 'extra_sql' => $where, +}; + +my $ilink = [ "${p}view/cust_bill.cgi?", 'invnum' ]; +my $clink = [ "${p}view/cust_main.cgi?", 'custnum' ]; + +my $conf = new FS::Conf; +my $money_char = $conf->config('money_char') || '$'; + +%><%= include( 'elements/search.html', + 'title' => 'Tax exemptions', + 'name' => 'tax exemptions', + 'query' => $query, + 'count_query' => $count_query, + 'count_addl' => [ $money_char. '%.2f total', ], + 'header' => [ + '#', + 'Date', + 'Amount', + + #'Description', + #'Setup charge', + #'Recurring charge', + #'Invoice', + #'Date', + + FS::UI::Web::cust_header(), + ], + 'fields' => [ + 'exemptpkgnum', + sub { $_[0]->month. '/'. $_[0]->year; }, + 'amount', + + #sub { $_[0]->pkgnum > 0 + # ? $_[0]->get('pkg') + # : $_[0]->get('itemdesc') + # }, + ##strikethrough or "N/A ($amount)" or something these when + ## they're not applicable to pkg_tax search + #sub { sprintf($money_char.'%.2f', shift->setup ) }, + #sub { sprintf($money_char.'%.2f', shift->recur ) }, + #'invnum', + #sub { time2str('%b %d %Y', shift->_date ) }, + + \&FS::UI::Web::cust_fields, + ], + 'links' => [ + '', + '', + '', + + #'', + #'', + #'', + #'', + #$ilink, + #$ilink, + + ( map { $clink } FS::UI::Web::cust_header() ), + ], + 'align' => 'rrr', # 'rlrrrc', + ) +%> + diff --git a/httemplate/search/report_tax.cgi b/httemplate/search/report_tax.cgi index 9062f0626..b1c6d3809 100755 --- a/httemplate/search/report_tax.cgi +++ b/httemplate/search/report_tax.cgi @@ -7,22 +7,25 @@ my $user = getotaker; my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi); -my $from_join_cust = " - FROM cust_bill_pkg +my $join_cust = " JOIN cust_bill USING ( invnum ) - JOIN cust_main USING ( custnum ) + LEFT JOIN cust_main USING ( custnum ) "; +my $from_join_cust = " + FROM cust_bill_pkg + $join_cust +"; my $join_pkg = " - JOIN cust_pkg USING ( pkgnum ) - JOIN part_pkg USING ( pkgpart ) + LEFT JOIN cust_pkg USING ( pkgnum ) + LEFT JOIN part_pkg USING ( pkgpart ) "; my $where = " WHERE _date >= $beginning AND _date <= $ending AND ( county = ? OR ? = '' ) AND ( state = ? OR ? = '' ) AND country = ? - AND payby != 'COMP' "; +# AND payby != 'COMP' my @base_param = qw( county county state state country ); my $agentname = ''; @@ -46,8 +49,6 @@ my $gotcust = " ) "; -my $monthly_exempt_warning = 0; -my $taxclass_flag = 0; my($total, $tot_taxable, $owed, $tax) = ( 0, 0, 0, 0, 0 ); my( $exempt_cust, $exempt_pkg, $exempt_monthly ) = ( 0, 0 ); my $out = 'Out of taxable region(s)'; @@ -59,17 +60,18 @@ foreach my $r (qsearch('cust_main_county', {}, '', $gotcust) ) { $regions{$label}->{'label'} = $label; $regions{$label}->{'url_param'} = join(';', map "$_=".$r->$_(), qw( county state country ) ); - my $fromwhere = $from_join_cust. $join_pkg. $where; my @param = @base_param; + my $mywhere = $where; if ( $r->taxclass ) { - $fromwhere .= " AND taxclass = ? "; + $mywhere .= " AND taxclass = ? "; push @param, 'taxclass'; $regions{$label}->{'url_param'} .= ';taxclass='. $r->taxclass if $cgi->param('show_taxclasses'); - $taxclass_flag = 1; } + my $fromwhere = $from_join_cust. $join_pkg. $mywhere. " AND payby != 'COMP' "; + # my $label = getlabel($r); # $regions{$label}->{'label'} = $label; @@ -83,57 +85,80 @@ foreach my $r (qsearch('cust_main_county', {}, '', $gotcust) ) { $total += $t; $regions{$label}->{'total'} += $t; - ## calculate package-exemption for this region - - foreach my $e ( grep { $r->get($_.'tax') =~ /^Y/i } - qw( cust_bill_pkg.setup cust_bill_pkg.recur ) ) { - my $x = scalar_sql($r, \@param, - "SELECT SUM($e) $fromwhere AND $nottax" - ); - $exempt_pkg += $x; - $regions{$label}->{'exempt_pkg'} += $x; - } - ## calculate customer-exemption for this region - my($taxable, $x_cust) = (0, 0); - foreach my $e ( grep { $r->get($_.'tax') !~ /^Y/i } - qw( cust_bill_pkg.setup cust_bill_pkg.recur ) ) { - $taxable += scalar_sql($r, \@param, - "SELECT SUM($e) $fromwhere AND $nottax AND ( tax != 'Y' OR tax IS NULL )" - ); - - $x_cust += scalar_sql($r, \@param, - "SELECT SUM($e) $fromwhere AND $nottax AND tax = 'Y'" - ); - } +## my $taxable = $t; + +# my($taxable, $x_cust) = (0, 0); +# foreach my $e ( grep { $r->get($_.'tax') !~ /^Y/i } +# qw( cust_bill_pkg.setup cust_bill_pkg.recur ) ) { +# $taxable += scalar_sql($r, \@param, +# "SELECT SUM($e) $fromwhere AND $nottax AND ( tax != 'Y' OR tax IS NULL )" +# ); +# +# $x_cust += scalar_sql($r, \@param, +# "SELECT SUM($e) $fromwhere AND $nottax AND tax = 'Y'" +# ); +# } + + my $x_cust = scalar_sql($r, \@param, + "SELECT SUM(cust_bill_pkg.setup+cust_bill_pkg.recur) + $fromwhere AND $nottax AND tax = 'Y' " + ); $exempt_cust += $x_cust; $regions{$label}->{'exempt_cust'} += $x_cust; + + ## calculate package-exemption for this region - ## calculate monthly exemption (texas tax) for this region + my $x_pkg = scalar_sql($r, \@param, + "SELECT SUM( + ( CASE WHEN part_pkg.setuptax = 'Y' + THEN cust_bill_pkg.setup + ELSE 0 + END + ) + + + ( CASE WHEN part_pkg.recurtax = 'Y' + THEN cust_bill_pkg.recur + ELSE 0 + END + ) + ) + $fromwhere + AND $nottax + AND ( + ( part_pkg.setuptax = 'Y' AND cust_bill_pkg.setup > 0 ) + OR ( part_pkg.recurtax = 'Y' AND cust_bill_pkg.recur > 0 ) + ) + AND ( tax != 'Y' OR tax IS NULL ) + " + ); + $exempt_pkg += $x_pkg; + $regions{$label}->{'exempt_pkg'} += $x_pkg; - my($sday,$smon,$syear) = (localtime($beginning) )[ 3, 4, 5 ]; - $monthly_exempt_warning=1 if $sday != 1 && $beginning; - $smon++; $syear+=1900; + ## calculate monthly exemption (texas tax) for this region - my $eending = ( $ending == 4294967295 ) ? time : $ending; - my($eday,$emon,$eyear) = (localtime($eending) )[ 3, 4, 5 ]; - $emon++; $eyear+=1900; + # count up all the cust_tax_exempt_pkg records associated with + # the actual line items. - my $x_monthly = scalar_sql($r, [ 'taxnum' ], - "SELECT SUM(amount) FROM cust_tax_exempt where taxnum = ? ". - " AND ( year > $syear OR ( year = $syear and month >= $smon ) )". - " AND ( year < $eyear OR ( year = $eyear and month <= $emon ) )" + my $x_monthly = scalar_sql($r, \@param, + "SELECT SUM(amount) + FROM cust_tax_exempt_pkg + JOIN cust_bill_pkg USING ( billpkgnum ) + $join_cust $join_pkg + $mywhere" ); - if ( $x_monthly ) { - warn $r->taxnum(). ": $x_monthly\n"; - $taxable -= $x_monthly; - } +# if ( $x_monthly ) { +# #warn $r->taxnum(). ": $x_monthly\n"; +# $taxable -= $x_monthly; +# } $exempt_monthly += $x_monthly; $regions{$label}->{'exempt_monthly'} += $x_monthly; + my $taxable = $t - $x_cust - $x_pkg - $x_monthly; + $tot_taxable += $taxable; $regions{$label}->{'taxable'} += $taxable; @@ -149,7 +174,7 @@ foreach my $r (qsearch('cust_main_county', {}, '', $gotcust) ) { } -my $taxwhere = "$from_join_cust $where"; +my $taxwhere = "$from_join_cust $where AND payby != 'COMP' "; my @taxparam = @base_param; my %base_regions = (); #foreach my $label ( keys %regions ) { @@ -165,7 +190,7 @@ foreach my $r ( my $label = getlabel($r); - my $fromwhere = $join_pkg. $where; + my $fromwhere = $join_pkg. $where. " AND payby != 'COMP' "; my @param = @base_param; #match itemdesc if necessary! @@ -246,7 +271,7 @@ sub getlabel { $label = "$label (". $r->taxclass. ")" if $r->taxclass && $cgi->param('show_taxclasses') - && ! $opt{'no_taxclasses'}; + && ! $opt{'no_taxclass'}; #$label = $r->taxname. " ($label)" if $r->taxname; } return $label; @@ -266,14 +291,19 @@ sub scalar_sql { %> <% - -my $baselink = $p. "search/cust_bill_pkg.cgi?begin=$beginning;end=$ending"; - +my $dateagentlink = "begin=$beginning;end=$ending"; +$dateagentlink .= ';agentnum='. $cgi->param('agentnum') + if length($agentname); +my $baselink = $p. "search/cust_bill_pkg.cgi?$dateagentlink"; +my $exemptlink = $p. "search/cust_tax_exempt_pkg.cgi?$dateagentlink"; %> - <%= header( "$agentname Sales Tax Report - ". - time2str('%h %o %Y through ', $beginning ). + ( $beginning + ? time2str('%h %o %Y ', $beginning ) + : '' + ). + 'through '. ( $ending == 4294967295 ? 'now' : time2str('%h %o %Y', $ending ) @@ -320,32 +350,36 @@ my $baselink = $p. "search/cust_bill_pkg.cgi?begin=$beginning;end=$ending"; $bgcolor = $bgcolor1; } - my $link = $baselink; + my $link = ''; if ( $region->{'label'} ne 'Total' ) { if ( $region->{'label'} eq $out ) { - $link .= ';out=1'; + $link = ';out=1'; } else { - $link .= ';'. $region->{'url_param'}; + $link = ';'. $region->{'url_param'}; } } + + + + %> <%= $region->{'label'} %> - <%= $money_char %><%= sprintf('%.2f', $region->{'total'} ) %> + <%= $money_char %><%= sprintf('%.2f', $region->{'total'} ) %> - - <%= $money_char %><%= sprintf('%.2f', $region->{'exempt_cust'} ) %> + <%= $money_char %><%= sprintf('%.2f', $region->{'exempt_cust'} ) %> - - <%= $money_char %><%= sprintf('%.2f', $region->{'exempt_pkg'} ) %> + <%= $money_char %><%= sprintf('%.2f', $region->{'exempt_pkg'} ) %> - - <%= $money_char %><%= sprintf('%.2f', $region->{'exempt_monthly'} ) %> + <%= $money_char %><%= sprintf('%.2f', $region->{'exempt_monthly'} ) %> = @@ -359,7 +393,7 @@ my $baselink = $p. "search/cust_bill_pkg.cgi?begin=$beginning;end=$ending"; <% unless ( $cgi->param('show_taxclasses') ) { %> - <%= $money_char %><%= sprintf('%.2f', $region->{'tax'} ) %> + <%= $money_char %><%= sprintf('%.2f', $region->{'tax'} ) %> <% } %> @@ -387,12 +421,12 @@ my $baselink = $p. "search/cust_bill_pkg.cgi?begin=$beginning;end=$ending"; $bgcolor = $bgcolor1; } - my $link = $baselink; + my $link = ''; #if ( $region->{'label'} ne 'Total' ) { if ( $region->{'label'} eq $out ) { - $link .= ';out=1'; + $link = ';out=1'; } else { - $link .= ';'. $region->{'url_param'}; + $link = ';'. $region->{'url_param'}; } #} %> @@ -400,7 +434,7 @@ my $baselink = $p. "search/cust_bill_pkg.cgi?begin=$beginning;end=$ending"; <%= $region->{'label'} %> - <%= $money_char %><%= sprintf('%.2f', $region->{'tax'} ) %> + <%= $money_char %><%= sprintf('%.2f', $region->{'tax'} ) %> @@ -417,15 +451,6 @@ my $baselink = $p. "search/cust_bill_pkg.cgi?begin=$beginning;end=$ending"; <% } %> - -<% if ( $monthly_exempt_warning ) { %> -
- Partial-month tax reports (except for current month) may not be correct due - to month-granularity tax exemption (usually "texas tax"). For an accurate - report, start on the first of a month and end on the last day of a month (or - leave blank for to now). -<% } %> - diff --git a/httemplate/search/report_tax.html b/httemplate/search/report_tax.html index eeaccc1ab..7a8ecd4f0 100755 --- a/httemplate/search/report_tax.html +++ b/httemplate/search/report_tax.html @@ -5,18 +5,36 @@

Tax Report Criteria

+ + <%= include( '/elements/tr-select-agent.html' ) %> + <%= include( '/elements/tr-input-beginning_ending.html' ) %> - - - - -
Show tax classes
-
+ <% my $conf = new FS::Conf; + if ( $conf->exists('enable_taxclasses') ) { + %> + + + Show tax classes + + <% } %> + <% my @pkg_class = qsearch('pkg_class', {}); + if ( @pkg_class ) { + %> + + + Show package classes + + <% } %> + + + +
+ -- cgit v1.2.1 From b5ecccfac56fc5d4eaa617a8c08dd168ffb74bac Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 27 Jan 2006 01:33:57 +0000 Subject: on tax exemption report, show more info on the specific line item and invoice --- httemplate/search/cust_tax_exempt_pkg.cgi | 67 +++++++++++++++++-------------- 1 file changed, 37 insertions(+), 30 deletions(-) (limited to 'httemplate') diff --git a/httemplate/search/cust_tax_exempt_pkg.cgi b/httemplate/search/cust_tax_exempt_pkg.cgi index bc1e743b2..e61947b7d 100644 --- a/httemplate/search/cust_tax_exempt_pkg.cgi +++ b/httemplate/search/cust_tax_exempt_pkg.cgi @@ -71,9 +71,9 @@ my $query = { 'hashref' => {}, 'select' => join(', ', 'cust_tax_exempt_pkg.*', - #'cust_bill_pkg.*', - #'cust_bill._date', - #'part_pkg.pkg', + 'cust_bill_pkg.*', + 'cust_bill.*', + 'part_pkg.pkg', 'cust_main.custnum', FS::UI::Web::cust_sql_fields(), ), @@ -94,32 +94,42 @@ my $money_char = $conf->config('money_char') || '$'; 'count_addl' => [ $money_char. '%.2f total', ], 'header' => [ '#', - 'Date', + 'Month', 'Amount', - - #'Description', - #'Setup charge', - #'Recurring charge', - #'Invoice', - #'Date', - + 'Line item', + 'Invoice', + 'Date', FS::UI::Web::cust_header(), ], 'fields' => [ 'exemptpkgnum', sub { $_[0]->month. '/'. $_[0]->year; }, - 'amount', - - #sub { $_[0]->pkgnum > 0 - # ? $_[0]->get('pkg') - # : $_[0]->get('itemdesc') - # }, - ##strikethrough or "N/A ($amount)" or something these when - ## they're not applicable to pkg_tax search - #sub { sprintf($money_char.'%.2f', shift->setup ) }, - #sub { sprintf($money_char.'%.2f', shift->recur ) }, - #'invnum', - #sub { time2str('%b %d %Y', shift->_date ) }, + sub { $money_char. $_[0]->amount; }, + + sub { + $_[0]->billpkgnum. ': '. + ( $_[0]->pkgnum > 0 + ? $_[0]->get('pkg') + : $_[0]->get('itemdesc') + ). + ' ('. + ( $_[0]->setup > 0 + ? $money_char. $_[0]->setup. ' setup' + : '' + ). + ( $_[0]->setup > 0 && $_[0]->recur > 0 + ? ' / ' + : '' + ). + ( $_[0]->recur > 0 + ? $money_char. $_[0]->recur. ' recur' + : '' + ). + ')'; + }, + + 'invnum', + sub { time2str('%b %d %Y', shift->_date ) }, \&FS::UI::Web::cust_fields, ], @@ -128,16 +138,13 @@ my $money_char = $conf->config('money_char') || '$'; '', '', - #'', - #'', - #'', - #'', - #$ilink, - #$ilink, + '', + $ilink, + $ilink, ( map { $clink } FS::UI::Web::cust_header() ), ], - 'align' => 'rrr', # 'rlrrrc', + 'align' => 'rrrlrc', # 'rlrrrc', ) %> -- cgit v1.2.1 From 0a4a314b33a22b314ac5c4c85840a4bbff49cdf3 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 27 Jan 2006 07:34:17 +0000 Subject: small visual fix to alternating row colors when show_taxclasses is on --- httemplate/search/report_tax.cgi | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'httemplate') diff --git a/httemplate/search/report_tax.cgi b/httemplate/search/report_tax.cgi index b1c6d3809..61ed26fac 100755 --- a/httemplate/search/report_tax.cgi +++ b/httemplate/search/report_tax.cgi @@ -413,6 +413,8 @@ my $exemptlink = $p. "search/cust_tax_exempt_pkg.cgi?$dateagentlink"; <% #some false laziness w/above + $bgcolor1 = '#eeeeee'; + $bgcolor2 = '#ffffff'; foreach my $region ( @base_regions ) { if ( $bgcolor eq $bgcolor1 ) { @@ -440,6 +442,14 @@ my $exemptlink = $p. "search/cust_tax_exempt_pkg.cgi?$dateagentlink"; <% } %> + <% + if ( $bgcolor eq $bgcolor1 ) { + $bgcolor = $bgcolor2; + } else { + $bgcolor = $bgcolor1; + } + %> + Total -- cgit v1.2.1 From c1bb4ddb71147d0571bd301a6d8c452fdf0e1bc9 Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 31 Jan 2006 04:26:54 +0000 Subject: move header() to include(/elements/header.html) so it can be changed in one place, thanks to Scott Edwards --- httemplate/browse/addr_block.cgi | 2 +- httemplate/browse/agent.cgi | 2 +- httemplate/browse/agent_type.cgi | 2 +- httemplate/browse/cust_pay_batch.cgi | 2 +- httemplate/browse/part_bill_event.cgi | 2 +- httemplate/browse/part_export.cgi | 2 +- httemplate/browse/part_pkg.cgi | 2 +- httemplate/browse/part_referral.cgi | 2 +- httemplate/browse/part_svc.cgi | 2 +- httemplate/browse/part_virtual_field.cgi | 2 +- httemplate/browse/payment_gateway.html | 2 +- httemplate/browse/queue.cgi | 2 +- httemplate/browse/rate.cgi | 2 +- httemplate/browse/router.cgi | 2 +- httemplate/browse/svc_acct_pop.cgi | 2 +- httemplate/config/config-view.cgi | 2 +- httemplate/config/config.cgi | 2 +- httemplate/edit/REAL_cust_pkg.cgi | 2 +- httemplate/edit/agent.cgi | 2 +- httemplate/edit/agent_payment_gateway.html | 2 +- httemplate/edit/agent_type.cgi | 2 +- httemplate/edit/bulk-cust_svc.html | 2 +- httemplate/edit/cust_pay.cgi | 2 +- httemplate/edit/part_export.cgi | 2 +- httemplate/edit/part_pkg.cgi | 2 +- httemplate/edit/part_svc.cgi | 2 +- httemplate/edit/payment_gateway.html | 2 +- httemplate/edit/prepay_credit.cgi | 2 +- httemplate/edit/process/prepay_credit.cgi | 2 +- httemplate/edit/process/reg_code.cgi | 2 +- httemplate/edit/rate.cgi | 2 +- httemplate/edit/rate_region.cgi | 2 +- httemplate/edit/reg_code.cgi | 2 +- httemplate/edit/svc_acct.cgi | 2 +- httemplate/edit/svc_broadband.cgi | 2 +- httemplate/edit/svc_forward.cgi | 2 +- httemplate/misc/batch-cust_pay.html | 2 +- httemplate/misc/cust_main-import.cgi | 2 +- httemplate/misc/cust_main-import_charges.cgi | 2 +- httemplate/misc/expire_pkg.cgi | 2 +- httemplate/misc/link.cgi | 2 +- httemplate/misc/meta-import.cgi | 2 +- httemplate/misc/process/cust_main-import.cgi | 2 +- httemplate/misc/process/cust_main-import_charges.cgi | 2 +- httemplate/misc/process/meta-import.cgi | 2 +- httemplate/misc/upload-batch.cgi | 2 +- httemplate/misc/whois.cgi | 2 +- httemplate/search/report_prepaid_income.cgi | 2 +- httemplate/search/report_tax.cgi | 2 +- httemplate/search/svc_external.cgi | 2 +- httemplate/view/cust_bill.cgi | 2 +- httemplate/view/cust_main.cgi | 2 +- httemplate/view/svc_acct.cgi | 4 ++-- httemplate/view/svc_broadband.cgi | 2 +- httemplate/view/svc_domain.cgi | 2 +- httemplate/view/svc_external.cgi | 2 +- 56 files changed, 57 insertions(+), 57 deletions(-) (limited to 'httemplate') diff --git a/httemplate/browse/addr_block.cgi b/httemplate/browse/addr_block.cgi index 06ac556cf..d453adf8e 100644 --- a/httemplate/browse/addr_block.cgi +++ b/httemplate/browse/addr_block.cgi @@ -1,4 +1,4 @@ -<%= header('Address Blocks', menubar('Main Menu' => $p)) %> +<%= include("/elements/header.html",'Address Blocks', menubar('Main Menu' => $p)) %> <% use NetAddr::IP; diff --git a/httemplate/browse/agent.cgi b/httemplate/browse/agent.cgi index 05300d0bd..17cc8bd40 100755 --- a/httemplate/browse/agent.cgi +++ b/httemplate/browse/agent.cgi @@ -11,7 +11,7 @@ my $conf = new FS::Conf; %> -<%= header('Agent Listing', menubar( +<%= include("/elements/header.html",'Agent Listing', menubar( 'Main Menu' => $p, 'Agent Types' => $p. 'browse/agent_type.cgi', # 'Add new agent' => '../edit/agent.cgi' diff --git a/httemplate/browse/agent_type.cgi b/httemplate/browse/agent_type.cgi index 5473804e8..2e1bdad42 100755 --- a/httemplate/browse/agent_type.cgi +++ b/httemplate/browse/agent_type.cgi @@ -1,5 +1,5 @@ -<%= header("Agent Type Listing", menubar( +<%= include("/elements/header.html","Agent Type Listing", menubar( 'Main Menu' => $p, 'Agents' => $p. 'browse/agent.cgi', )) %> diff --git a/httemplate/browse/cust_pay_batch.cgi b/httemplate/browse/cust_pay_batch.cgi index 3420e97b6..0f05ecb25 100755 --- a/httemplate/browse/cust_pay_batch.cgi +++ b/httemplate/browse/cust_pay_batch.cgi @@ -1,5 +1,5 @@ -<%= header("Pending credit card batch", menubar( 'Main Menu' => $p,)) %> +<%= include("/elements/header.html","Pending credit card batch", menubar( 'Main Menu' => $p,)) %>
Download batch in format '; -print "Invoice Event #", $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)"; +<% if ( $cgi->param('error') ) { %> + Error: <%= $cgi->param('error') %> +<% } %> -print ntable("#cccccc",2), <Payby +Invoice Event #<%= $hashref->{eventpart} ? $hashref->{eventpart} : "(NEW)" %> -for (qw(CARD DCRD CHEK DCHK LECB BILL COMP)) { - print qq!"; - } else { - print ">$_"; - } -} +<%= ntable("#cccccc",2) %> -my $days = $hashref->{seconds}/86400; + + Event name + + -print < -Event -After days -END + + For + + customers + + + + <% my $days = $hashref->{seconds}/86400; %> -print 'Disabled'; -print '{disabled} eq "Y"; -print '>'; -print ''; + + After + days + -print 'Action'; + + Test event + + + + + + + + Disabled + + {disabled} eq 'Y' ? ' CHECKED' : '' %>> + + + + + Action + + +<% #print ntable(); @@ -113,7 +151,7 @@ tie my %events, 'Tie::IxHash', 'code' => '$cust_main->suspend();', 'weight' => 10, }, - 'suspend' => { + 'suspend-if-balance' => { 'name' => 'Suspend if balance (this invoice and previous) over', 'code' => '$cust_bill->cust_suspend_if_balance_over( %%%balanceover%%% );', 'html' => " $money_char ". '', @@ -174,13 +212,13 @@ tie my %events, 'Tie::IxHash', }, 'send' => { - 'name' => 'Send invoice (email/print)', + 'name' => 'Send invoice (email/print/fax)', 'code' => '$cust_bill->send();', 'weight' => 50, }, 'send_alternate' => { - 'name' => 'Send invoice (email/print) with alternate template', + 'name' => 'Send invoice (email/print/fax) with alternate template', 'code' => '$cust_bill->send(\'%%%templatename%%%\');', 'html' => '', @@ -188,7 +226,7 @@ tie my %events, 'Tie::IxHash', }, 'send_if_newest' => { - 'name' => 'Send invoice (email/print) with alternate template, if it is still the newest invoice (useful for late notices - set to 31 days or later)', + 'name' => 'Send invoice (email/print/fax) with alternate template, if it is still the newest invoice (useful for late notices - set to 31 days or later)', 'code' => '$cust_bill->send_if_newest(\'%%%if_newest_templatename%%%\');', 'html' => '', @@ -196,7 +234,7 @@ tie my %events, 'Tie::IxHash', }, 'send_agent' => { - 'name' => 'Send invoice (email/print) ', + 'name' => 'Send invoice (email/print/fax) ', 'code' => '$cust_bill->send(\'%%%agent_templatename%%%\', [ %%%agentnum%%% ], \'%%%agent_invoice_from%%%\');', 'html' => sub { ' @@ -263,6 +301,7 @@ tie my %events, 'Tie::IxHash', 'code' => '$cust_bill->spool_csv( \'format\' => \'%%%spoolformat%%%\', \'dest\' => \'%%%spooldest%%%\', + \'balanceover\' => \'%%%spoolbalanceover%%%\', \'agent_spools\' => \'%%%spoolagent_spools%%%\', );', 'html' => sub { @@ -303,6 +342,13 @@ tie my %events, 'Tie::IxHash', $html .= ''. ''. + + ''. + ''. + ''. ''. ' <% } %> diff --git a/httemplate/edit/payment_gateway.html b/httemplate/edit/payment_gateway.html index cf825df00..1eda11249 100644 --- a/httemplate/edit/payment_gateway.html +++ b/httemplate/edit/payment_gateway.html @@ -34,70 +34,89 @@ Gateway #<%= $payment_gateway->gatewaynum || "(NEW)" %> - - + - + - +
if balance (this invoice and previous) over '. + "$money_char ". + ''. + '
Individual per-agent spools? {'spoolagent_spools'} ? 'CHECKED' : '' ). -- cgit v1.2.1 From a9c8414692c1777da3ff78b83a1e6bbb0729f6eb Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 1 Feb 2006 23:13:48 +0000 Subject: finish adding freeside-monthly and monthly events --- httemplate/browse/part_bill_event.cgi | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'httemplate') diff --git a/httemplate/browse/part_bill_event.cgi b/httemplate/browse/part_bill_event.cgi index 0b6d0cb2b..380e4d78b 100755 --- a/httemplate/browse/part_bill_event.cgi +++ b/httemplate/browse/part_bill_event.cgi @@ -32,7 +32,8 @@ my $total = scalar(@part_bill_event); my $oldfreq = ''; my @payby_part_bill_event = grep { $payby eq $_->payby } - sort { $a->seconds <=> $b->seconds + sort { $a->freq cmp $b->freq # for now + || $a->seconds <=> $b->seconds || $a->weight <=> $b->weight || $a->eventpart <=> $b->eventpart } -- cgit v1.2.1 From 860e628d3d0d2ba432d401de5c9d4784c918be54 Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 5 Feb 2006 12:27:20 +0000 Subject: payment gateway editing --- httemplate/browse/payment_gateway.html | 11 +-- httemplate/edit/payment_gateway.html | 103 ++++++++++++++++----------- httemplate/edit/process/payment_gateway.html | 2 +- 3 files changed, 69 insertions(+), 47 deletions(-) (limited to 'httemplate') diff --git a/httemplate/browse/payment_gateway.html b/httemplate/browse/payment_gateway.html index 002932ccd..791906b78 100644 --- a/httemplate/browse/payment_gateway.html +++ b/httemplate/browse/payment_gateway.html @@ -40,10 +40,13 @@ <%= $payment_gateway->disabled ? 'DISABLED' : '' %><%= $payment_gateway->gateway_module %> - <%= !$payment_gateway->disabled - ? ' (disable)' - : '' - %> + + (edit) + <%= !$payment_gateway->disabled + ? '(disable)' + : '' + %> + <%= $payment_gateway->gateway_username %> -
Gateway: + + <% if ( $payment_gateway->gatewaynum ) { %> + + <%= $payment_gateway->gateway_module %> + + + <% } else { %> + + + <% } %> - +
Username:
Password:
Action:
Options: + +
diff --git a/httemplate/edit/process/payment_gateway.html b/httemplate/edit/process/payment_gateway.html index b9e4d47da..42205a02d 100644 --- a/httemplate/edit/process/payment_gateway.html +++ b/httemplate/edit/process/payment_gateway.html @@ -17,7 +17,7 @@ my %options = @options; my $error; if ( $gatewaynum ) { - $error=$new->replace($old); + $error=$new->replace($old, \%options); } else { $error=$new->insert(\%options); $gatewaynum=$new->getfield('gatewaynum'); -- cgit v1.2.1 From 1acbcf55d8cd4675408f8ad3406f431623918c8d Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 7 Feb 2006 11:12:29 +0000 Subject: remove inadvertant extra table statement preventing page from showing up in konq --- httemplate/edit/cust_pay.cgi | 2 -- 1 file changed, 2 deletions(-) (limited to 'httemplate') diff --git a/httemplate/edit/cust_pay.cgi b/httemplate/edit/cust_pay.cgi index 94fd06ca5..a03a245eb 100755 --- a/httemplate/edit/cust_pay.cgi +++ b/httemplate/edit/cust_pay.cgi @@ -52,8 +52,6 @@ $title .= " against Invoice #$linknum" if $link eq 'invnum';

<% } %> -<%= ntable("#cccccc",2) %> - -- cgit v1.2.1 From 4c9e6e4863e2045d984933ab0e229b5dd500e1f7 Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 8 Feb 2006 03:50:42 +0000 Subject: slightly html-ize the 1.5.8 upgrade instructions --- httemplate/docs/index.html | 4 +- httemplate/docs/upgrade10.html | 116 +++++++++++++++++++++++------------------ 2 files changed, 66 insertions(+), 54 deletions(-) (limited to 'httemplate') diff --git a/httemplate/docs/index.html b/httemplate/docs/index.html index 7254d76f3..bec62e34a 100644 --- a/httemplate/docs/index.html +++ b/httemplate/docs/index.html @@ -8,11 +8,9 @@

Configuration and setup

    diff --git a/httemplate/docs/upgrade10.html b/httemplate/docs/upgrade10.html index ac2c6238d..8d90ab7a2 100644 --- a/httemplate/docs/upgrade10.html +++ b/httemplate/docs/upgrade10.html @@ -1,76 +1,86 @@ -
    -this is incomplete
    -
    -NOTE: Version numbering has been simplified.  1.5.7 is the version after
    -1.5.0pre6.  It is still a development version - releases with odd numbered 
    -middle parts (NN in x.NN.x) are development versions, like Perl or Linux.
    -
    -If migrating from 1.5.7, see README.1.5.8 instead
    -
    -If migrating from 1.5.0pre6, see README.1.5.7 instead
    -
    -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 this patch and commenting out the "use DBD::Pg 1.32" at the top of DBIx/DBSchema/DBD/Pg.pm)
    -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)
    -install Net::SSH 0.08
    -install HTML::Widgets::SelectLayers 0.05
    -install Business::CreditCard 0.28
    -
    -- 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.
    -- In httpd.conf, change <Files ~ \.cgi> to  <Files ~ (\.cgi|\.html)>
    -- In httpd.conf, change AddHandler perl-script .cgi or SetHandler perl-script to AddHandler perl-script .cgi .html
    -
    -install NetAddr::IP, Chart::Base, Locale::SubCountry, Text::CSV_XS, 
    +
    +  Upgrading to 1.5.8
    +
    +
    +

    Upgrading to 1.5.8 from 1.4.1 or 1.4.2

    + +Note: 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. + + +
    + +
      +
    • If migrating from 1.5.0pre6, see README.1.5.7 instead +
    • If migrating from 1.5.7, see README.1.5.8 instead +
    • 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 this patch and commenting out the "use DBD::Pg 1.32" at the top of DBIx/DBSchema/DBD/Pg.pm) +
    • 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) +
    • install Net::SSH 0.08 or later +
    • install HTML::Widgets::SelectLayers 0.05 or later +
    • install Business::CreditCard 0.28 or later + +
    • 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. +
        +
      • In httpd.conf, change <Files ~ \.cgi> to <Files ~ (\.cgi|\.html)> +
      • In httpd.conf, change AddHandler perl-script .cgi or SetHandler perl-script to AddHandler perl-script .cgi .html +
      +
    • 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 and Term::ReadKey +
    • Apply the following changes to your database: +
       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;
      +
      -On recent Pg versions: - +
    • On recent Pg versions: +
       ALTER TABLE cust_main ALTER COLUMN payinfo varchar(512) NULL;
       ALTER TABLE h_cust_main ALTER COLUMN payinfo varchar(512) NULL;
      +
      +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. -Or on older Pg versions that don't support altering columns directly: -(dump database, edit & reload) - -On recent Pg versions: - +
    • On recent Pg versions: +
       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;
      -
      +
      Or on Pg versions that don't support DROP NOT NULL (tested on 7.1 and 7.2 so far): +
       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' ) );
      +
      -If you created your database with a version before 1.4.2, dump database, edit: -- cust_main and h_cust_main: increase otaker from 8 to 32 -- cust_main and h_cust_main: change ss from char(11) to varchar(11) ( "character(11)" to "character varying(11)" ) -- cust_credit and h_cust_credit: increase otaker from 8 to 32 -- cust_pkg and h_cust_pkg: increase otaker from 8 to 32 -- cust_refund and h_cust_refund: increase otaker from 8 to 32 -- domain_record and h_domain_record: increase reczone from 80 to 255 -- domain_record and h_domain_record: change rectype from char to varchar ( "character(5)" to "character varying(5)" ) -- domain_record and h_domain_record: increase recdata from 80 to 255 -then reload - -mandatory again: - -make install-perl-modules to install the new libraries and CLI utilities -run "freeside-upgrade username" to create the remaining new tables and columns - -optionally: - +
    • If you created your database with a version before 1.4.2, dump database, edit the following, then reload: +
        +
      • cust_main and h_cust_main: increase otaker from 8 to 32 +
      • cust_main and h_cust_main: change ss from char(11) to varchar(11) ( "character(11)" to "character varying(11)" ) +
      • cust_credit and h_cust_credit: increase otaker from 8 to 32 +
      • cust_pkg and h_cust_pkg: increase otaker from 8 to 32 +
      • cust_refund and h_cust_refund: increase otaker from 8 to 32 +
      • domain_record and h_domain_record: increase reczone from 80 to 255 +
      • domain_record and h_domain_record: change rectype from char to varchar ( "character(5)" to "character varying(5)" ) +
      • domain_record and h_domain_record: increase recdata from 80 to 255 +
      + +
    • make install-perl-modules to install the new libraries and CLI utilities +
    • run "freeside-upgrade username" to create the remaining new tables and columns + +
    • optionally: +
       CREATE INDEX cust_main4 ON cust_main ( daytime );
       CREATE INDEX cust_main5 ON cust_main ( night );
       CREATE INDEX cust_main6 ON cust_main ( fax );
      @@ -89,5 +99,9 @@ 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 );
      -
       
      + +
    + + + -- cgit v1.2.1 From eb035e51ad8df6b3301c81679a9f4b51b6ea4c4d Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 8 Feb 2006 03:50:53 +0000 Subject: remove ancient upgrade instructions --- httemplate/docs/upgrade7.html | 24 --- httemplate/docs/upgrade8.html | 394 ------------------------------------------ 2 files changed, 418 deletions(-) delete mode 100644 httemplate/docs/upgrade7.html delete mode 100644 httemplate/docs/upgrade8.html (limited to 'httemplate') diff --git a/httemplate/docs/upgrade7.html b/httemplate/docs/upgrade7.html deleted file mode 100644 index d9dcfe2ae..000000000 --- a/httemplate/docs/upgrade7.html +++ /dev/null @@ -1,24 +0,0 @@ - - Upgrading to 1.3.1 - - -

    Upgrading to 1.3.1 from 1.3.0

    -
      -
    • If migrating from 1.0.0, see these instructions first. -
    • If migrating from less than 1.1.4, see these instructions first. -
    • If migrating from less than 1.2.0, see these instructions first. -
    • If migrating from less than 1.2.2, see these instructions first. -
    • If migrating from less than 1.2.3, see these instructions first. -
    • If migrating from less than 1.3.0, see these instructions first. -
    • Back up your data and current Freeside installation. -
    • Copy or symlink htdocs to the new copy. -
    • Change to the FS directory in the new tarball, and build and install the - Perl modules: -
      -$ cd FS/
      -$ perl Makefile.PL
      -$ make
      -$ su
      -# make install UNINST=1
      -
    • Run bin/dbdef-create. - diff --git a/httemplate/docs/upgrade8.html b/httemplate/docs/upgrade8.html deleted file mode 100644 index 9ca7cb7b9..000000000 --- a/httemplate/docs/upgrade8.html +++ /dev/null @@ -1,394 +0,0 @@ - - Upgrading to 1.4.0 - - -

      Upgrading to 1.4.0 from 1.3.1

      - - - - - - - - - -
      Apache::ASPMason
        -
      • Run make aspdocs -
      • Copy aspdocs/ to your web server's document space. -
      • Create a Global directory, such as /usr/local/etc/freeside/asp-global/ -
      • Copy htetc/global.asa to the Global directory. -
      • Configure Apache for the Global directory and to execute .cgi files using Apache::ASP. For example: -
        -<Directory /usr/local/apache/htdocs/freeside-asp>
        -<Files ~ (\.cgi)>
        -AddHandler perl-script .cgi
        -PerlHandler Apache::ASP
        -</Files>
        -<Perl>
        -$MLDBM::RemoveTaint = 1;
        -</Perl>
        -PerlSetVar Global /usr/local/etc/freeside/asp-global/
        -</Directory>
        -
        -
        -
      • (use version 1.0x - Freeside is not yet compatible with version 1.1x) -
      • Run make masondocs -
      • Copy masondocs/ to your web server's document space. -
      • Copy htetc/handler.pl to your web server's configuration directory. -
      • Edit handler.pl and set an appropriate data_dir, such as /usr/local/etc/freeside/mason-data -
      • Configure Apache to use the handler.pl file and to execute .cgi files using HTML::Mason. For example: -
        -<Directory /usr/local/apache/htdocs/freeside-mason>
        -<Files ~ (\.cgi)>
        -AddHandler perl-script .cgi
        -PerlHandler HTML::Mason
        -</Files>
        -<Perl>
        -require "/usr/local/apache/conf/handler.pl";
        -</Perl>
        -</Directory>
        -
        -
      -
        -
      • Build and install the Perl modules: -
        -$ su
        -# make install-perl-modules
        -
      • Apply the following changes to your database: -
        -CREATE TABLE svc_forward (
        -  svcnum int NOT NULL,
        -  srcsvc int NOT NULL,
        -  dstsvc int NOT NULL,
        -  dst varchar(80),
        -  PRIMARY KEY (svcnum)
        -);
        -ALTER TABLE part_svc ADD svc_forward__srcsvc varchar(80) NULL;
        -ALTER TABLE part_svc ADD svc_forward__srcsvc_flag char(1) NULL;
        -ALTER TABLE part_svc ADD svc_forward__dstsvc varchar(80) NULL;
        -ALTER TABLE part_svc ADD svc_forward__dstsvc_flag char(1) NULL;
        -ALTER TABLE part_svc ADD svc_forward__dst varchar(80) NULL;
        -ALTER TABLE part_svc ADD svc_forward__dst_flag char(1) NULL;
        -
        -CREATE TABLE cust_credit_bill (
        -  creditbillnum int primary key,
        -  crednum int not null,
        -  invnum int not null,
        -  _date int not null,
        -  amount decimal(10,2) not null
        -);
        -
        -CREATE TABLE cust_bill_pay (
        -  billpaynum int primary key,
        -  invnum int not null,
        -  paynum int not null,
        -  _date int not null,
        -  amount decimal(10,2) not null
        -);
        -
        -CREATE TABLE cust_credit_refund (
        -  creditrefundnum int primary key,
        -  crednum int not null,
        -  refundnum int not null,
        -  _date int not null,
        -  amount decimal(10,2) not null
        -);
        -
        -CREATE TABLE part_svc_column (
        -  columnnum int primary key,
        -  svcpart int not null,
        -  columnname varchar(64) not null,
        -  columnvalue varchar(80) null,
        -  columnflag char(1) null
        -);
        -
        -CREATE TABLE queue (
        -  jobnum int primary key,
        -  job text not null,
        -  _date int not null,
        -  status varchar(80) not null,
        -  statustext text null,
        -  svcnum int null
        -);
        -CREATE INDEX queue1 ON queue ( svcnum );
        -CREATE INDEX queue2 ON queue ( status );
        -
        -CREATE TABLE queue_arg (
        -  argnum int primary key,
        -  jobnum int not null,
        -  arg text null
        -);
        -CREATE INDEX queue_arg1 ON queue_arg ( jobnum );
        -
        -CREATE TABLE queue_depend (
        -  dependnum int primary key,
        -  jobnum int not null,
        -  depend_jobnum int not null
        -);
        -CREATE INDEX queue_depend1 ON queue_depend ( jobnum );
        -CREATE INDEX queue_depend2 ON queue_depend ( depend_jobnum );
        -
        -CREATE TABLE part_pop_local (
        -  localnum int primary key,
        -  popnum int not null,
        -  city varchar(80) null,
        -  state char(2) null,
        -  npa char(3) not null,
        -  nxx char(3) not null
        -);
        -CREATE UNIQUE INDEX part_pop_local1 ON part_pop_local ( npa, nxx );
        -
        -CREATE TABLE cust_bill_event (
        -  eventnum int primary key,
        -  invnum int not null,
        -  eventpart int not null,
        -  _date int not null,
        -  status varchar(80) not null, 
        -  statustext text
        -);
        -CREATE UNIQUE INDEX cust_bill_event1 ON cust_bill_event ( eventpart, invnum );
        -CREATE INDEX cust_bill_event2 ON cust_bill_event ( invnum );
        -
        -CREATE TABLE part_bill_event (
        -  eventpart int primary key,
        -  payby char(4) not null,
        -  event varchar(80) not null,
        -  eventcode text null,
        -  seconds int null,
        -  weight int not null,
        -  plan varchar(80) null,
        -  plandata text null,
        -  disabled char(1) null
        -);
        -CREATE INDEX part_bill_event1 ON part_bill_event ( payby );
        -
        -CREATE TABLE export_svc (
        -  exportsvcnum int primary key,
        -  exportnum int not null,
        -  svcpart int not null
        -);
        -CREATE UNIQUE INDEX export_svc1 ON export_svc ( exportnum, svcpart );
        -CREATE INDEX export_svc2 ON export_svc ( exportnum );
        -CREATE INDEX export_svc3 ON export_svc ( svcpart );
        -
        -CREATE TABLE part_export (
        -  exportnum int primary key,
        -  machine varchar(80) not null,
        -  exporttype varchar(80) not null,
        -  nodomain char(1) NULL
        -);
        -CREATE INDEX part_export1 ON part_export ( machine );
        -CREATE INDEX part_export2 ON part_export ( exporttype );
        -
        -CREATE TABLE part_export_option (
        -  optionnum int primary key,
        -  exportnum int not null,
        -  optionname varchar(80) not null,
        -  optionvalue text NULL
        -);
        -CREATE INDEX part_export_option1 ON part_export_option ( exportnum );
        -CREATE INDEX part_export_option2 ON part_export_option ( optionname );
        -
        -CREATE TABLE radius_usergroup (
        -  usergroupnum int primary key,
        -  svcnum int not null,
        -  groupname varchar(80) not null
        -);
        -CREATE INDEX radius_usergroup1 ON radius_usergroup ( svcnum );
        -CREATE INDEX radius_usergroup2 ON radius_usergroup ( groupname );
        -
        -CREATE TABLE msgcat (
        -  msgnum int primary key,
        -  msgcode varchar(80) not null,
        -  locale varchar(16) not null,
        -  msg text not null
        -);
        -CREATE INDEX msgcat1 ON msgcat ( msgcode, locale );
        -
        -CREATE TABLE cust_tax_exempt (
        -  exemptnum int primary key,
        -  custnum int not null,
        -  taxnum int not null,
        -  year int not null,
        -  month int not null,
        -  amount decimal(10,2)
        -);
        -CREATE UNIQUE INDEX cust_tax_exempt1 ON cust_tax_exempt ( taxnum, year, month );
        -
        -ALTER TABLE svc_acct ADD domsvc integer NULL;
        -ALTER TABLE part_svc ADD svc_acct__domsvc varchar(80) NULL;
        -ALTER TABLE part_svc ADD svc_acct__domsvc_flag char(1) NULL;
        -ALTER TABLE svc_domain ADD catchall integer NULL;
        -ALTER TABLE cust_main ADD referral_custnum integer NULL;
        -ALTER TABLE cust_main ADD comments text NULL;
        -ALTER TABLE cust_pay ADD custnum integer;
        -ALTER TABLE cust_pay_batch ADD paybatchnum integer;
        -ALTER TABLE cust_refund ADD custnum integer;
        -ALTER TABLE cust_pkg ADD manual_flag char(1) NULL;
        -ALTER TABLE part_pkg ADD plan varchar(80) NULL;
        -ALTER TABLE part_pkg ADD plandata text NULL;
        -ALTER TABLE part_pkg ADD setuptax char(1) NULL;
        -ALTER TABLE part_pkg ADD recurtax char(1) NULL;
        -ALTER TABLE part_pkg ADD disabled char(1) NULL;
        -ALTER TABLE part_svc ADD disabled char(1) NULL;
        -ALTER TABLE cust_bill ADD closed char(1) NULL;
        -ALTER TABLE cust_pay ADD closed char(1) NULL;
        -ALTER TABLE cust_credit ADD closed char(1) NULL;
        -ALTER TABLE cust_refund ADD closed char(1) NULL;
        -ALTER TABLE cust_bill_event ADD status varchar(80);
        -ALTER TABLE cust_bill_event ADD statustext text NULL;
        -ALTER TABLE svc_acct ADD sec_phrase varchar(80) NULL;
        -ALTER TABLE part_svc ADD svc_acct__sec_phrase varchar(80) NULL;
        -ALTER TABLE part_svc ADD svc_acct__sec_phrase_flag char(1) NULL;
        -ALTER TABLE part_pkg ADD taxclass varchar(80) NULL;
        -ALTER TABLE cust_main_county ADD taxclass varchar(80) NULL;
        -ALTER TABLE cust_main_county ADD exempt_amount decimal(10,2);
        -CREATE INDEX cust_main3 ON cust_main ( referral_custnum );
        -CREATE INDEX cust_credit_bill1 ON cust_credit_bill ( crednum );
        -CREATE INDEX cust_credit_bill2 ON cust_credit_bill ( invnum );
        -CREATE INDEX cust_bill_pay1 ON cust_bill_pay ( invnum );
        -CREATE INDEX cust_bill_pay2 ON cust_bill_pay ( paynum );
        -CREATE INDEX cust_credit_refund1 ON cust_credit_refund ( crednum );
        -CREATE INDEX cust_credit_refund2 ON cust_credit_refund ( refundnum );
        -CREATE UNIQUE INDEX cust_pay_batch_pkey ON cust_pay_batch ( paybatchnum );
        -CREATE UNIQUE INDEX part_svc_column1 ON part_svc_column ( svcpart, columnname );
        -CREATE INDEX cust_pay2 ON cust_pay ( paynum );
        -CREATE INDEX cust_pay3 ON cust_pay ( custnum );
        -CREATE INDEX cust_pay4 ON cust_pay ( paybatch );
        -
        - -
      • If you are using PostgreSQL, apply the following changes to your database: -
        -CREATE UNIQUE INDEX agent_pkey ON agent ( agentnum );
        -CREATE UNIQUE INDEX agent_type_pkey ON agent_type ( typenum );
        -CREATE UNIQUE INDEX cust_bill_pkey ON cust_bill ( invnum );
        -CREATE UNIQUE INDEX cust_credit_pkey ON cust_credit ( crednum );
        -CREATE UNIQUE INDEX cust_main_pkey ON cust_main ( custnum );
        -CREATE UNIQUE INDEX cust_main_county_pkey ON cust_main_county ( taxnum );
        -CREATE UNIQUE INDEX cust_main_invoice_pkey ON cust_main_invoice ( destnum );
        -CREATE UNIQUE INDEX cust_pay_pkey ON cust_pay ( paynum );
        -CREATE UNIQUE INDEX cust_pkg_pkey ON cust_pkg ( pkgnum );
        -CREATE UNIQUE INDEX cust_refund_pkey ON cust_refund ( refundnum );
        -CREATE UNIQUE INDEX cust_svc_pkey ON cust_svc ( svcnum );
        -CREATE UNIQUE INDEX domain_record_pkey ON domain_record ( recnum );
        -CREATE UNIQUE INDEX nas_pkey ON nas ( nasnum );
        -CREATE UNIQUE INDEX part_pkg_pkey ON part_pkg ( pkgpart );
        -CREATE UNIQUE INDEX part_referral_pkey ON part_referral ( refnum );
        -CREATE UNIQUE INDEX part_svc_pkey ON part_svc ( svcpart );
        -CREATE UNIQUE INDEX port_pkey ON port ( portnum );
        -CREATE UNIQUE INDEX prepay_credit_pkey ON prepay_credit ( prepaynum );
        -CREATE UNIQUE INDEX session_pkey ON session ( sessionnum );
        -CREATE UNIQUE INDEX svc_acct_pkey ON svc_acct ( svcnum );
        -CREATE UNIQUE INDEX svc_acct_pop_pkey ON svc_acct_pop ( popnum );
        -CREATE UNIQUE INDEX svc_acct_sm_pkey ON svc_acct_sm ( svcnum );
        -CREATE UNIQUE INDEX svc_domain_pkey ON svc_domain ( svcnum );
        -CREATE UNIQUE INDEX svc_www_pkey ON svc_www ( svcnum );
        -
        -
      • If you wish to enable service/shipping addresses, apply the following - changes to your database: -
        -ALTER TABLE cust_main ADD COLUMN ship_last varchar(80) NULL;
        -ALTER TABLE cust_main ADD COLUMN ship_first varchar(80) NULL;
        -ALTER TABLE cust_main ADD COLUMN ship_company varchar(80) NULL;
        -ALTER TABLE cust_main ADD COLUMN ship_address1 varchar(80) NULL;
        -ALTER TABLE cust_main ADD COLUMN ship_address2 varchar(80) NULL;
        -ALTER TABLE cust_main ADD COLUMN ship_city varchar(80) NULL;
        -ALTER TABLE cust_main ADD COLUMN ship_county varchar(80) NULL;
        -ALTER TABLE cust_main ADD COLUMN ship_state varchar(80) NULL;
        -ALTER TABLE cust_main ADD COLUMN ship_zip varchar(10) NULL;
        -ALTER TABLE cust_main ADD COLUMN ship_country char(2) NULL;
        -ALTER TABLE cust_main ADD COLUMN ship_daytime varchar(20) NULL;
        -ALTER TABLE cust_main ADD COLUMN ship_night varchar(20) NULL;
        -ALTER TABLE cust_main ADD COLUMN ship_fax varchar(12) NULL;
        -CREATE INDEX cust_main4 ON cust_main ( ship_last );
        -CREATE INDEX cust_main5 ON cust_main ( ship_company );
        -
        -
      • If you are using the signup server, reinstall it according to the instructions. The 1.3.x signup server is not compatible with 1.4.x. -
      • Run bin/dbdef-create username -
      • If you have svc_acct_sm records or service definitions: -
          -
        • Create a service definition with table svc_forward -
        • Run bin/fs-migrate-svc_acct_sm username -
        -
      • Or if you just have svc_acct records: -
          -
        • Order and provision a package for your default domain and note down the Service # or svcnum. -
        • UPDATE svc_acct SET domsvc = svcnum -
        • Update your service definitions to have default (or fixed) domsvc. -
        -
      • Run bin/fs-migrate-payrefusername -
      • Run bin/fs-migrate-part_svcusername -
      • After running bin/fs-migrate-payref, apply the following changes to your database: - -
        PostgreSQLMySQL, others
        -
        -CREATE TABLE cust_pay_temp (
        -  paynum int primary key,
        -  custnum int not null,
        -  paid decimal(10,2) not null,
        -  _date int null,
        -  payby char(4) not null,
        -  payinfo varchar(16) null,
        -  paybatch varchar(80) null,
        -  closed char(1) null
        -);
        -INSERT INTO cust_pay_temp SELECT paynum, custnum, paid, _date, payby, payinfo, paybatch, closed FROM cust_pay;
        -DROP TABLE cust_pay;
        -ALTER TABLE cust_pay_temp RENAME TO cust_pay;
        -CREATE UNIQUE INDEX cust_pay1 ON cust_pay (paynum);
        -CREATE TABLE cust_refund_temp (
        -  refundnum int primary key,
        -  custnum int not null,
        -  _date int null,
        -  refund decimal(10,2) not null,
        -  otaker varchar(8) not null,
        -  reason varchar(80) not null,
        -  payby char(4) not null,
        -  payinfo varchar(16) null,
        -  paybatch varchar(80) null,
        -  closed char(1) null
        -);
        -INSERT INTO cust_refund_temp SELECT refundnum, custnum, _date, refund, otaker, reason, payby, payinfo, '', closed from cust_refund;
        -DROP TABLE cust_refund;
        -ALTER TABLE cust_refund_temp RENAME TO cust_refund;
        -CREATE UNIQUE INDEX cust_refund1 ON cust_refund (refundnum);
        -
        -
        -
        -ALTER TABLE cust_pay DROP COLUMN invnum;
        -ALTER TABLE cust_refund DROP COLUMN crednum;
        -
        -
        -
      • IMPORTANT: After applying the second set of database changes, run bin/dbdef-create username again. -
      • IMPORTANT: run bin/create-history-tables username -
      • IMPORTANT: After running bin/create-history-tables, run bin/dbdef-create username again. -
      • As the freeside UNIX user, run bin/populate-msgcat username to populate the message catalog - -
      • set the locale configuration value to en_US. -
      • the mxmachines, nsmachines, arecords and cnamerecords configuration values have been deprecated. Set the defaultrecords configuration value instead. -
      • Create the `/usr/local/etc/freeside/cache.datasrc' directory - (owned by the freeside user). -
      • freeside-queued was installed with the Perl modules. Start it now and ensure that is run upon system startup. -
      • Set appropriate invoice events for your site. At the very least, you'll want to set some invoice events "After 0 days": a BILL invoice event to print invoices, a CARD invoice event to batch or run cards real-time, and a COMP invoice event to "pay" complimentary customers. If you were using the -i option to freeside-bill it should be removed. -
      • Use freeside-daily instead of freeside-bill. -
      • If you would like Freeside to notify your customers when their credit - cards and other billing arrangements are about to expire, arrange for - freeside-expiration-alerter to be run daily by cron or similar - facility. The message it sends can be configured from the - Configuration choice of the main menu as alerter_template. -
      • Export has been rewritten. If you were using the icradiusmachines, - icradius_mysqldest, icradius_mysqlsource, or icradius_secrets files, add - an appropriate "sqlradius" export to all relevant Service Definitions - instead. Use MySQL replication or - point the "sqlradius" export directly at your external ICRADIUS or FreeRADIUS - database (or through an SSL-necrypting proxy...) -
      - -- cgit v1.2.1 From c8a6843a92a556315b85e6b3f4ed1bebdfd2e35d Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 9 Feb 2006 07:18:08 +0000 Subject: update jscalendar --- httemplate/elements/calendar-en.js | 10 +- httemplate/elements/calendar-setup.js | 45 ++- httemplate/elements/calendar-win2k-2.css | 1 + httemplate/elements/calendar.js | 653 ++++++++++++++++++------------- httemplate/elements/calendar_stripped.js | 12 +- 5 files changed, 419 insertions(+), 302 deletions(-) (limited to 'httemplate') diff --git a/httemplate/elements/calendar-en.js b/httemplate/elements/calendar-en.js index e9d6a222e..0dbde793d 100644 --- a/httemplate/elements/calendar-en.js +++ b/httemplate/elements/calendar-en.js @@ -1,7 +1,7 @@ // ** I18N // Calendar EN language -// Author: Mihai Bazon, +// Author: Mihai Bazon, // Encoding: any // Distributed under the same terms as the calendar itself. @@ -43,6 +43,10 @@ Calendar._SDN = new Array "Sat", "Sun"); +// First day of the week. "0" means display Sunday first, "1" means display +// Monday first, etc. +Calendar._FD = 0; + // full month names Calendar._MN = new Array ("January", @@ -79,8 +83,8 @@ Calendar._TT["INFO"] = "About the calendar"; Calendar._TT["ABOUT"] = "DHTML Date/Time Selector\n" + -"(c) dynarch.com 2002-2003\n" + // don't translate this this ;-) -"For latest version visit: http://dynarch.com/mishoo/calendar.epl\n" + +"(c) dynarch.com 2002-2005 / Author: Mihai Bazon\n" + // don't translate this this ;-) +"For latest version visit: http://www.dynarch.com/projects/calendar/\n" + "Distributed under GNU LGPL. See http://gnu.org/licenses/lgpl.html for details." + "\n\n" + "Date selection:\n" + diff --git a/httemplate/elements/calendar-setup.js b/httemplate/elements/calendar-setup.js index 55e22b933..b27d9bed0 100644 --- a/httemplate/elements/calendar-setup.js +++ b/httemplate/elements/calendar-setup.js @@ -19,7 +19,7 @@ * than modifying calendar.js itself). */ -// $Id: calendar-setup.js,v 1.4 2004-09-22 11:04:41 ivan Exp $ +// $Id: calendar-setup.js,v 1.5 2006-02-09 07:18:08 ivan Exp $ /** * This function "patches" an input field (or other element) to use a calendar @@ -71,7 +71,8 @@ Calendar.setup = function (params) { param_default("singleClick", true); param_default("disableFunc", null); param_default("dateStatusFunc", params["disableFunc"]); // takes precedence if both are defined - param_default("firstDay", 0); // defaults to "Sunday" first + param_default("dateText", null); + param_default("firstDay", null); param_default("align", "Br"); param_default("range", [1900, 2999]); param_default("weekNumbers", true); @@ -88,6 +89,7 @@ Calendar.setup = function (params) { param_default("position", null); param_default("cache", false); param_default("showOthers", false); + param_default("multiple", null); var tmp = ["inputField", "displayArea", "button"]; for (var i in tmp) { @@ -95,7 +97,7 @@ Calendar.setup = function (params) { params[tmp[i]] = document.getElementById(params[tmp[i]]); } } - if (!(params.flat || params.inputField || params.displayArea || params.button)) { + if (!(params.flat || params.multiple || params.inputField || params.displayArea || params.button)) { alert("Calendar.setup:\n Nothing to setup (no fields found). Please check your code"); return false; } @@ -103,13 +105,6 @@ Calendar.setup = function (params) { function onSelect(cal) { var p = cal.params; var update = (cal.dateClicked || p.electric); - if (update && p.flat) { - if (typeof p.flatCallback == "function") - p.flatCallback(cal); - else - alert("No flatCallback given -- doing nothing."); - return false; - } if (update && p.inputField) { p.inputField.value = cal.date.print(p.ifFormat); if (typeof p.inputField.onchange == "function") @@ -117,10 +112,14 @@ Calendar.setup = function (params) { } if (update && p.displayArea) p.displayArea.innerHTML = cal.date.print(p.daFormat); - if (update && p.singleClick && cal.dateClicked) - cal.callCloseHandler(); if (update && typeof p.onUpdate == "function") p.onUpdate(cal); + if (update && p.flat) { + if (typeof p.flatCallback == "function") + p.flatCallback(cal); + } + if (update && p.singleClick && cal.dateClicked) + cal.callCloseHandler(); }; if (params.flat != null) { @@ -131,12 +130,20 @@ Calendar.setup = function (params) { return false; } var cal = new Calendar(params.firstDay, params.date, params.onSelect || onSelect); + cal.showsOtherMonths = params.showOthers; cal.showsTime = params.showsTime; cal.time24 = (params.timeFormat == "24"); cal.params = params; cal.weekNumbers = params.weekNumbers; cal.setRange(params.range[0], params.range[1]); cal.setDateStatusHandler(params.dateStatusFunc); + cal.getDateText = params.dateText; + if (params.ifFormat) { + cal.setDateFormat(params.ifFormat); + } + if (params.inputField && typeof params.inputField.value == "string") { + cal.parseDate(params.inputField.value); + } cal.create(params.flat); cal.show(); return false; @@ -148,6 +155,8 @@ Calendar.setup = function (params) { var dateFmt = params.inputField ? params.ifFormat : params.daFormat; var mustCreate = false; var cal = window.calendar; + if (dateEl) + params.date = Date.parseDate(dateEl.value || dateEl.innerHTML, dateFmt); if (!(cal && params.cache)) { window.calendar = cal = new Calendar(params.firstDay, params.date, @@ -162,15 +171,23 @@ Calendar.setup = function (params) { cal.setDate(params.date); cal.hide(); } + if (params.multiple) { + cal.multiple = {}; + for (var i = params.multiple.length; --i >= 0;) { + var d = params.multiple[i]; + var ds = d.print("%Y%m%d"); + cal.multiple[ds] = d; + } + } cal.showsOtherMonths = params.showOthers; cal.yearStep = params.step; cal.setRange(params.range[0], params.range[1]); cal.params = params; cal.setDateStatusHandler(params.dateStatusFunc); + cal.getDateText = params.dateText; cal.setDateFormat(dateFmt); if (mustCreate) cal.create(); - cal.parseDate(dateEl.value || dateEl.innerHTML); cal.refresh(); if (!params.position) cal.showAtElement(params.button || params.displayArea || params.inputField, params.align); @@ -178,4 +195,6 @@ Calendar.setup = function (params) { cal.showAt(params.position[0], params.position[1]); return false; }; + + return cal; }; diff --git a/httemplate/elements/calendar-win2k-2.css b/httemplate/elements/calendar-win2k-2.css index 6001cfaa4..6f37b7dcd 100644 --- a/httemplate/elements/calendar-win2k-2.css +++ b/httemplate/elements/calendar-win2k-2.css @@ -206,6 +206,7 @@ background: #e4d8e0; font-size: 90%; padding: 1px; + z-index: 100; } .calendar .combo .label, diff --git a/httemplate/elements/calendar.js b/httemplate/elements/calendar.js index ec18d80ce..f5c74f608 100644 --- a/httemplate/elements/calendar.js +++ b/httemplate/elements/calendar.js @@ -1,16 +1,18 @@ -/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.com/mishoo/ - * ------------------------------------------------------------------ +/* Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo + * ----------------------------------------------------------- * - * The DHTML Calendar, version 0.9.6 "Keep cool but don't freeze" + * The DHTML Calendar, version 1.0 "It is happening again" * * Details and latest version at: - * http://dynarch.com/mishoo/calendar.epl + * www.dynarch.com/projects/calendar + * + * This script is developed by Dynarch.com. Visit us at www.dynarch.com. * * This script is distributed under the GNU Lesser General Public License. * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html */ -// $Id: calendar.js,v 1.4 2004-09-22 11:04:41 ivan Exp $ +// $Id: calendar.js,v 1.5 2006-02-09 07:18:08 ivan Exp $ /** The Calendar object constructor. */ Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) { @@ -18,6 +20,8 @@ Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) { this.activeDiv = null; this.currentDateEl = null; this.getDateStatus = null; + this.getDateToolTip = null; + this.getDateText = null; this.timeout = null; this.onSelected = onSelected || null; this.onClose = onClose || null; @@ -29,13 +33,15 @@ Calendar = function (firstDayOfWeek, dateStr, onSelected, onClose) { this.ttDateFormat = Calendar._TT["TT_DATE_FORMAT"]; this.isPopup = true; this.weekNumbers = true; - this.firstDayOfWeek = firstDayOfWeek; // 0 for Sunday, 1 for Monday, etc. + this.firstDayOfWeek = typeof firstDayOfWeek == "number" ? firstDayOfWeek : Calendar._FD; // 0 for Sunday, 1 for Monday, etc. this.showsOtherMonths = false; this.dateStr = dateStr; this.ar_days = null; this.showsTime = false; this.time24 = true; this.yearStep = 2; + this.hiliteToday = true; + this.multiple = null; // HTML elements this.table = null; this.element = null; @@ -146,20 +152,19 @@ Calendar.addClass = function(el, className) { el.className += " " + className; }; +// FIXME: the following 2 functions totally suck, are useless and should be replaced immediately. Calendar.getElement = function(ev) { - if (Calendar.is_ie) { - return window.event.srcElement; - } else { - return ev.currentTarget; - } + var f = Calendar.is_ie ? window.event.srcElement : ev.currentTarget; + while (f.nodeType != 1 || /^div$/i.test(f.tagName)) + f = f.parentNode; + return f; }; Calendar.getTargetElement = function(ev) { - if (Calendar.is_ie) { - return window.event.srcElement; - } else { - return ev.target; - } + var f = Calendar.is_ie ? window.event.srcElement : ev.target; + while (f.nodeType != 1) + f = f.parentNode; + return f; }; Calendar.stopEvent = function(ev) { @@ -295,7 +300,7 @@ Calendar.showYearsCombo = function (fwd) { var show = false; for (var i = 12; i > 0; --i) { if (Y >= cal.minYear && Y <= cal.maxYear) { - yr.firstChild.data = Y; + yr.innerHTML = Y; yr.year = Y; yr.style.display = "block"; show = true; @@ -416,7 +421,7 @@ Calendar.tableMouseOver = function (ev) { } else if ( ++i >= range.length ) i = 0; var newval = range[i]; - el.firstChild.data = newval; + el.innerHTML = newval; cal.onUpdateTime(); } @@ -504,7 +509,7 @@ Calendar.dayMouseDown = function(ev) { Calendar._C = cal; if (el.navtype != 300) with (Calendar) { if (el.navtype == 50) { - el._current = el.firstChild.data; + el._current = el.innerHTML; addEvent(document, "mousemove", tableMouseOver); } else addEvent(document, Calendar.is_ie5 ? "mousemove" : "mouseover", tableMouseOver); @@ -541,7 +546,7 @@ Calendar.dayMouseOver = function(ev) { if (el.ttip.substr(0, 1) == "_") { el.ttip = el.caldate.print(el.calendar.ttDateFormat) + el.ttip.substr(1); } - el.calendar.tooltips.firstChild.data = el.ttip; + el.calendar.tooltips.innerHTML = el.ttip; } if (el.navtype != 300) { Calendar.addClass(el, "hilite"); @@ -555,14 +560,13 @@ Calendar.dayMouseOver = function(ev) { Calendar.dayMouseOut = function(ev) { with (Calendar) { var el = getElement(ev); - if (isRelated(el, ev) || _C || el.disabled) { + if (isRelated(el, ev) || _C || el.disabled) return false; - } removeClass(el, "hilite"); - if (el.caldate) { + if (el.caldate) removeClass(el.parentNode, "rowhilite"); - } - el.calendar.tooltips.firstChild.data = _TT["SEL_DATE"]; + if (el.calendar) + el.calendar.tooltips.innerHTML = _TT["SEL_DATE"]; return stopEvent(ev); } }; @@ -577,17 +581,23 @@ Calendar.cellClick = function(el, ev) { var newdate = false; var date = null; if (typeof el.navtype == "undefined") { - Calendar.removeClass(cal.currentDateEl, "selected"); - Calendar.addClass(el, "selected"); - closing = (cal.currentDateEl == el); - if (!closing) { - cal.currentDateEl = el; + if (cal.currentDateEl) { + Calendar.removeClass(cal.currentDateEl, "selected"); + Calendar.addClass(el, "selected"); + closing = (cal.currentDateEl == el); + if (!closing) { + cal.currentDateEl = el; + } } - cal.date = new Date(el.caldate); + cal.date.setDateOnly(el.caldate); date = cal.date; - newdate = true; + var other_month = !(cal.dateClicked = !el.otherMonth); + if (!other_month && !cal.currentDateEl) + cal._toggleMultipleDate(new Date(date)); + else + newdate = !el.disabled; // a date was clicked - if (!(cal.dateClicked = !el.otherMonth)) + if (other_month) cal._init(cal.firstDayOfWeek, date); } else { if (el.navtype == 200) { @@ -595,7 +605,9 @@ Calendar.cellClick = function(el, ev) { cal.callCloseHandler(); return; } - date = (el.navtype == 0) ? new Date() : new Date(cal.date); + date = new Date(cal.date); + if (el.navtype == 0) + date.setDateOnly(new Date()); // TODAY // unless "today" was clicked, we assume no date was clicked so // the selected handler will know not to close the calenar when // in single-click mode. @@ -622,7 +634,7 @@ Calendar.cellClick = function(el, ev) { text = "Help and about box text is not translated into this language.\n" + "If you know this language and you feel generous please update\n" + "the corresponding file in \"lang\" subdir to match calendar-en.js\n" + - "and send it back to to get it into the distribution ;-)\n\n" + + "and send it back to to get it into the distribution ;-)\n\n" + "Thank you!\n" + "http://dynarch.com/mishoo/calendar.epl\n"; } @@ -659,7 +671,7 @@ Calendar.cellClick = function(el, ev) { return; case 50: var range = el._range; - var current = el.firstChild.data; + var current = el.innerHTML; for (var i = range.length; --i >= 0;) if (range[i] == current) break; @@ -669,15 +681,13 @@ Calendar.cellClick = function(el, ev) { } else if ( ++i >= range.length ) i = 0; var newval = range[i]; - el.firstChild.data = newval; + el.innerHTML = newval; cal.onUpdateTime(); return; case 0: // TODAY will bring us here - if ((typeof cal.getDateStatus == "function") && cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) { - // remember, "date" was previously set to new - // Date() if TODAY was clicked; thus, it - // contains today date. + if ((typeof cal.getDateStatus == "function") && + cal.getDateStatus(date, date.getFullYear(), date.getMonth(), date.getDate())) { return false; } break; @@ -685,14 +695,15 @@ Calendar.cellClick = function(el, ev) { if (!date.equalsTo(cal.date)) { cal.setDate(date); newdate = true; - } + } else if (el.navtype == 0) + newdate = closing = true; } if (newdate) { - cal.callHandler(); + ev && cal.callHandler(); } if (closing) { Calendar.removeClass(el, "hilite"); - cal.callCloseHandler(); + ev && cal.callCloseHandler(); } }; @@ -749,13 +760,7 @@ Calendar.prototype.create = function (_par) { Calendar._add_evs(cell); cell.calendar = cal; cell.navtype = navtype; - if (text.substr(0, 1) != "&") { - cell.appendChild(document.createTextNode(text)); - } - else { - // FIXME: dirty hack for entities - cell.innerHTML = text; - } + cell.innerHTML = "
      " + text + "
      "; return cell; }; @@ -797,11 +802,10 @@ Calendar.prototype.create = function (_par) { if (this.weekNumbers) { cell = Calendar.createElement("td", row); cell.className = "name wn"; - cell.appendChild(document.createTextNode(Calendar._TT["WK"])); + cell.innerHTML = Calendar._TT["WK"]; } for (var i = 7; i > 0; --i) { cell = Calendar.createElement("td", row); - cell.appendChild(document.createTextNode("")); if (!i) { cell.navtype = 100; cell.calendar = this; @@ -818,11 +822,9 @@ Calendar.prototype.create = function (_par) { row = Calendar.createElement("tr", tbody); if (this.weekNumbers) { cell = Calendar.createElement("td", row); - cell.appendChild(document.createTextNode("")); } for (var j = 7; j > 0; --j) { cell = Calendar.createElement("td", row); - cell.appendChild(document.createTextNode("")); cell.calendar = this; Calendar._add_evs(cell); } @@ -845,7 +847,7 @@ Calendar.prototype.create = function (_par) { function makeTimePart(className, init, range_start, range_end) { var part = Calendar.createElement("span", cell); part.className = className; - part.appendChild(document.createTextNode(init)); + part.innerHTML = init; part.calendar = cal; part.ttip = Calendar._TT["TIME_PART"]; part.navtype = 50; @@ -870,7 +872,7 @@ Calendar.prototype.create = function (_par) { if (t12 && pm) hrs -= 12; var H = makeTimePart("hour", hrs, t12 ? 1 : 0, t12 ? 12 : 23); var span = Calendar.createElement("span", cell); - span.appendChild(document.createTextNode(":")); + span.innerHTML = ":"; span.className = "colon"; var M = makeTimePart("minute", mins, 0, 59); var AP = null; @@ -883,30 +885,32 @@ Calendar.prototype.create = function (_par) { cell.innerHTML = " "; cal.onSetTime = function() { - var hrs = this.date.getHours(); - var mins = this.date.getMinutes(); - var pm = (hrs > 12); - if (pm && t12) hrs -= 12; - H.firstChild.data = (hrs < 10) ? ("0" + hrs) : hrs; - M.firstChild.data = (mins < 10) ? ("0" + mins) : mins; - if (t12) - AP.firstChild.data = pm ? "pm" : "am"; + var pm, hrs = this.date.getHours(), + mins = this.date.getMinutes(); + if (t12) { + pm = (hrs >= 12); + if (pm) hrs -= 12; + if (hrs == 0) hrs = 12; + AP.innerHTML = pm ? "pm" : "am"; + } + H.innerHTML = (hrs < 10) ? ("0" + hrs) : hrs; + M.innerHTML = (mins < 10) ? ("0" + mins) : mins; }; cal.onUpdateTime = function() { var date = this.date; - var h = parseInt(H.firstChild.data, 10); + var h = parseInt(H.innerHTML, 10); if (t12) { - if (/pm/i.test(AP.firstChild.data) && h < 12) + if (/pm/i.test(AP.innerHTML) && h < 12) h += 12; - else if (/am/i.test(AP.firstChild.data) && h == 12) + else if (/am/i.test(AP.innerHTML) && h == 12) h = 0; } var d = date.getDate(); var m = date.getMonth(); var y = date.getFullYear(); date.setHours(h); - date.setMinutes(parseInt(M.firstChild.data, 10)); + date.setMinutes(parseInt(M.innerHTML, 10)); date.setFullYear(y); date.setMonth(m); date.setDate(d); @@ -938,7 +942,7 @@ Calendar.prototype.create = function (_par) { var mn = Calendar.createElement("div"); mn.className = Calendar.is_ie ? "label-IEfix" : "label"; mn.month = i; - mn.appendChild(document.createTextNode(Calendar._SMN[i])); + mn.innerHTML = Calendar._SMN[i]; div.appendChild(mn); } @@ -948,7 +952,6 @@ Calendar.prototype.create = function (_par) { for (i = 12; i > 0; --i) { var yr = Calendar.createElement("div"); yr.className = Calendar.is_ie ? "label-IEfix" : "label"; - yr.appendChild(document.createTextNode("")); div.appendChild(yr); } @@ -958,14 +961,14 @@ Calendar.prototype.create = function (_par) { /** keyboard navigation, only for popup calendars */ Calendar._keyEvent = function(ev) { - if (!window.calendar) { + var cal = window._dynarch_popupCalendar; + if (!cal || cal.multiple) return false; - } (Calendar.is_ie) && (ev = window.event); - var cal = window.calendar; - var act = (Calendar.is_ie || ev.type == "keypress"); + var act = (Calendar.is_ie || ev.type == "keypress"), + K = ev.keyCode; if (ev.ctrlKey) { - switch (ev.keyCode) { + switch (K) { case 37: // KEY left act && Calendar.cellClick(cal._nav_pm); break; @@ -981,7 +984,7 @@ Calendar._keyEvent = function(ev) { default: return false; } - } else switch (ev.keyCode) { + } else switch (K) { case 32: // KEY space (now) Calendar.cellClick(cal._nav_now); break; @@ -993,48 +996,78 @@ Calendar._keyEvent = function(ev) { case 39: // KEY right case 40: // KEY down if (act) { - var date = cal.date.getDate() - 1; - var el = cal.currentDateEl; - var ne = null; - var prev = (ev.keyCode == 37) || (ev.keyCode == 38); - switch (ev.keyCode) { - case 37: // KEY left - (--date >= 0) && (ne = cal.ar_days[date]); - break; - case 38: // KEY up - date -= 7; - (date >= 0) && (ne = cal.ar_days[date]); - break; - case 39: // KEY right - (++date < cal.ar_days.length) && (ne = cal.ar_days[date]); - break; - case 40: // KEY down - date += 7; - (date < cal.ar_days.length) && (ne = cal.ar_days[date]); + var prev, x, y, ne, el, step; + prev = K == 37 || K == 38; + step = (K == 37 || K == 39) ? 1 : 7; + function setVars() { + el = cal.currentDateEl; + var p = el.pos; + x = p & 15; + y = p >> 4; + ne = cal.ar_days[y][x]; + };setVars(); + function prevMonth() { + var date = new Date(cal.date); + date.setDate(date.getDate() - step); + cal.setDate(date); + }; + function nextMonth() { + var date = new Date(cal.date); + date.setDate(date.getDate() + step); + cal.setDate(date); + }; + while (1) { + switch (K) { + case 37: // KEY left + if (--x >= 0) + ne = cal.ar_days[y][x]; + else { + x = 6; + K = 38; + continue; + } + break; + case 38: // KEY up + if (--y >= 0) + ne = cal.ar_days[y][x]; + else { + prevMonth(); + setVars(); + } + break; + case 39: // KEY right + if (++x < 7) + ne = cal.ar_days[y][x]; + else { + x = 0; + K = 40; + continue; + } + break; + case 40: // KEY down + if (++y < cal.ar_days.length) + ne = cal.ar_days[y][x]; + else { + nextMonth(); + setVars(); + } + break; + } break; } - if (!ne) { - if (prev) { - Calendar.cellClick(cal._nav_pm); - } else { - Calendar.cellClick(cal._nav_nm); - } - date = (prev) ? cal.date.getMonthDays() : 1; - el = cal.currentDateEl; - ne = cal.ar_days[date - 1]; + if (ne) { + if (!ne.disabled) + Calendar.cellClick(ne); + else if (prev) + prevMonth(); + else + nextMonth(); } - Calendar.removeClass(el, "selected"); - Calendar.addClass(ne, "selected"); - cal.date = new Date(ne.caldate); - cal.callHandler(); - cal.currentDateEl = ne; } break; case 13: // KEY enter - if (act) { - cal.callHandler(); - cal.hide(); - } + if (act) + Calendar.cellClick(cal.currentDateEl, ev); break; default: return false; @@ -1046,7 +1079,10 @@ Calendar._keyEvent = function(ev) { * (RE)Initializes the calendar to the given date and firstDayOfWeek */ Calendar.prototype._init = function (firstDayOfWeek, date) { - var today = new Date(); + var today = new Date(), + TY = today.getFullYear(), + TM = today.getMonth(), + TD = today.getDate(); this.table.style.visibility = "hidden"; var year = date.getFullYear(); if (year < this.minYear) { @@ -1074,21 +1110,24 @@ Calendar.prototype._init = function (firstDayOfWeek, date) { var row = this.tbody.firstChild; var MN = Calendar._SMN[month]; - var ar_days = new Array(); + var ar_days = this.ar_days = new Array(); var weekend = Calendar._TT["WEEKEND"]; + var dates = this.multiple ? (this.datesCells = {}) : null; for (var i = 0; i < 6; ++i, row = row.nextSibling) { var cell = row.firstChild; if (this.weekNumbers) { cell.className = "day wn"; - cell.firstChild.data = date.getWeekNumber(); + cell.innerHTML = date.getWeekNumber(); cell = cell.nextSibling; } row.className = "daysrow"; - var hasdays = false; - for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(date.getDate() + 1)) { - var iday = date.getDate(); + var hasdays = false, iday, dpos = ar_days[i] = []; + for (var j = 0; j < 7; ++j, cell = cell.nextSibling, date.setDate(iday + 1)) { + iday = date.getDate(); var wday = date.getDay(); cell.className = "day"; + cell.pos = i << 4 | j; + dpos[j] = cell; var current_month = (date.getMonth() == month); if (!current_month) { if (this.showsOtherMonths) { @@ -1105,9 +1144,16 @@ Calendar.prototype._init = function (firstDayOfWeek, date) { hasdays = true; } cell.disabled = false; - cell.firstChild.data = iday; - if (typeof this.getDateStatus == "function") { + cell.innerHTML = this.getDateText ? this.getDateText(date, iday) : iday; + if (dates) + dates[date.print("%Y%m%d")] = cell; + if (this.getDateStatus) { var status = this.getDateStatus(date, year, month, iday); + if (this.getDateToolTip) { + var toolTip = this.getDateToolTip(date, year, month, iday); + if (toolTip) + cell.title = toolTip; + } if (status === true) { cell.className += " disabled"; cell.disabled = true; @@ -1118,33 +1164,66 @@ Calendar.prototype._init = function (firstDayOfWeek, date) { } } if (!cell.disabled) { - ar_days[ar_days.length] = cell; cell.caldate = new Date(date); cell.ttip = "_"; - if (current_month && iday == mday) { + if (!this.multiple && current_month + && iday == mday && this.hiliteToday) { cell.className += " selected"; this.currentDateEl = cell; } - if (date.getFullYear() == today.getFullYear() && - date.getMonth() == today.getMonth() && - iday == today.getDate()) { + if (date.getFullYear() == TY && + date.getMonth() == TM && + iday == TD) { cell.className += " today"; cell.ttip += Calendar._TT["PART_TODAY"]; } - if (weekend.indexOf(wday.toString()) != -1) { + if (weekend.indexOf(wday.toString()) != -1) cell.className += cell.otherMonth ? " oweekend" : " weekend"; - } } } if (!(hasdays || this.showsOtherMonths)) row.className = "emptyrow"; } - this.ar_days = ar_days; - this.title.firstChild.data = Calendar._MN[month] + ", " + year; + this.title.innerHTML = Calendar._MN[month] + ", " + year; this.onSetTime(); this.table.style.visibility = "visible"; + this._initMultipleDates(); // PROFILE - // this.tooltips.firstChild.data = "Generated in " + ((new Date()) - today) + " ms"; + // this.tooltips.innerHTML = "Generated in " + ((new Date()) - today) + " ms"; +}; + +Calendar.prototype._initMultipleDates = function() { + if (this.multiple) { + for (var i in this.multiple) { + var cell = this.datesCells[i]; + var d = this.multiple[i]; + if (!d) + continue; + if (cell) + cell.className += " selected"; + } + } +}; + +Calendar.prototype._toggleMultipleDate = function(date) { + if (this.multiple) { + var ds = date.print("%Y%m%d"); + var cell = this.datesCells[ds]; + if (cell) { + var d = this.multiple[ds]; + if (!d) { + Calendar.addClass(cell, "selected"); + this.multiple[ds] = date; + } else { + Calendar.removeClass(cell, "selected"); + delete this.multiple[ds]; + } + } + } +}; + +Calendar.prototype.setDateToolTipHandler = function (unaryFunction) { + this.getDateToolTip = unaryFunction; }; /** @@ -1209,7 +1288,7 @@ Calendar.prototype.destroy = function () { var el = this.element.parentNode; el.removeChild(this.element); Calendar._C = null; - window.calendar = null; + window._dynarch_popupCalendar = null; }; /** @@ -1226,14 +1305,15 @@ Calendar.prototype.reparent = function (new_parent) { // document, if the calendar is shown. If the click was outside the open // calendar this function closes it. Calendar._checkCalendar = function(ev) { - if (!window.calendar) { + var calendar = window._dynarch_popupCalendar; + if (!calendar) { return false; } var el = Calendar.is_ie ? Calendar.getElement(ev) : Calendar.getTargetElement(ev); for (; el != null && el != calendar.element; el = el.parentNode); if (el == null) { // calls closeHandler which should hide the calendar. - window.calendar.callCloseHandler(); + window._dynarch_popupCalendar.callCloseHandler(); return Calendar.stopEvent(ev); } }; @@ -1254,7 +1334,7 @@ Calendar.prototype.show = function () { this.element.style.display = "block"; this.hidden = false; if (this.isPopup) { - window.calendar = this; + window._dynarch_popupCalendar = this; Calendar.addEvent(document, "keydown", Calendar._keyEvent); Calendar.addEvent(document, "keypress", Calendar._keyEvent); Calendar.addEvent(document, "mousedown", Calendar._checkCalendar); @@ -1344,8 +1424,8 @@ Calendar.prototype.showAtElement = function (el, opts) { case "L": p.x -= w; break; case "R": p.x += el.offsetWidth; break; case "C": p.x += (el.offsetWidth - w) / 2; break; - case "r": p.x += el.offsetWidth - w; break; - case "l": break; // already there + case "l": p.x += el.offsetWidth - w; break; + case "r": break; // already there } p.width = w; p.height = h + 40; @@ -1373,14 +1453,140 @@ Calendar.prototype.setTtDateFormat = function (str) { * Tries to identify the date represented in a string. If successful it also * calls this.setDate which moves the calendar to the given date. */ -Calendar.prototype.parseDate = function (str, fmt) { +Calendar.prototype.parseDate = function(str, fmt) { + if (!fmt) + fmt = this.dateFormat; + this.setDate(Date.parseDate(str, fmt)); +}; + +Calendar.prototype.hideShowCovered = function () { + if (!Calendar.is_ie && !Calendar.is_opera) + return; + function getVisib(obj){ + var value = obj.style.visibility; + if (!value) { + if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C + if (!Calendar.is_khtml) + value = document.defaultView. + getComputedStyle(obj, "").getPropertyValue("visibility"); + else + value = ''; + } else if (obj.currentStyle) { // IE + value = obj.currentStyle.visibility; + } else + value = ''; + } + return value; + }; + + var tags = new Array("applet", "iframe", "select"); + var el = this.element; + + var p = Calendar.getAbsolutePos(el); + var EX1 = p.x; + var EX2 = el.offsetWidth + EX1; + var EY1 = p.y; + var EY2 = el.offsetHeight + EY1; + + for (var k = tags.length; k > 0; ) { + var ar = document.getElementsByTagName(tags[--k]); + var cc = null; + + for (var i = ar.length; i > 0;) { + cc = ar[--i]; + + p = Calendar.getAbsolutePos(cc); + var CX1 = p.x; + var CX2 = cc.offsetWidth + CX1; + var CY1 = p.y; + var CY2 = cc.offsetHeight + CY1; + + if (this.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) { + if (!cc.__msh_save_visibility) { + cc.__msh_save_visibility = getVisib(cc); + } + cc.style.visibility = cc.__msh_save_visibility; + } else { + if (!cc.__msh_save_visibility) { + cc.__msh_save_visibility = getVisib(cc); + } + cc.style.visibility = "hidden"; + } + } + } +}; + +/** Internal function; it displays the bar with the names of the weekday. */ +Calendar.prototype._displayWeekdays = function () { + var fdow = this.firstDayOfWeek; + var cell = this.firstdayname; + var weekend = Calendar._TT["WEEKEND"]; + for (var i = 0; i < 7; ++i) { + cell.className = "day name"; + var realday = (i + fdow) % 7; + if (i) { + cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]); + cell.navtype = 100; + cell.calendar = this; + cell.fdow = realday; + Calendar._add_evs(cell); + } + if (weekend.indexOf(realday.toString()) != -1) { + Calendar.addClass(cell, "weekend"); + } + cell.innerHTML = Calendar._SDN[(i + fdow) % 7]; + cell = cell.nextSibling; + } +}; + +/** Internal function. Hides all combo boxes that might be displayed. */ +Calendar.prototype._hideCombos = function () { + this.monthsCombo.style.display = "none"; + this.yearsCombo.style.display = "none"; +}; + +/** Internal function. Starts dragging the element. */ +Calendar.prototype._dragStart = function (ev) { + if (this.dragging) { + return; + } + this.dragging = true; + var posX; + var posY; + if (Calendar.is_ie) { + posY = window.event.clientY + document.body.scrollTop; + posX = window.event.clientX + document.body.scrollLeft; + } else { + posY = ev.clientY + window.scrollY; + posX = ev.clientX + window.scrollX; + } + var st = this.element.style; + this.xOffs = posX - parseInt(st.left); + this.yOffs = posY - parseInt(st.top); + with (Calendar) { + addEvent(document, "mousemove", calDragIt); + addEvent(document, "mouseup", calDragEnd); + } +}; + +// BEGIN: DATE OBJECT PATCHES + +/** Adds the number of days array to the Date object. */ +Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31); + +/** Constants used for time computations */ +Date.SECOND = 1000 /* milliseconds */; +Date.MINUTE = 60 * Date.SECOND; +Date.HOUR = 60 * Date.MINUTE; +Date.DAY = 24 * Date.HOUR; +Date.WEEK = 7 * Date.DAY; + +Date.parseDate = function(str, fmt) { + var today = new Date(); var y = 0; var m = -1; var d = 0; var a = str.split(/\W+/); - if (!fmt) { - fmt = this.dateFormat; - } var b = fmt.match(/%./g); var i = 0, j = 0; var hr = 0; @@ -1422,6 +1628,8 @@ Calendar.prototype.parseDate = function (str, fmt) { case "%p": if (/pm/i.test(a[i]) && hr < 12) hr += 12; + else if (/am/i.test(a[i]) && hr >= 12) + hr -= 12; break; case "%M": @@ -1429,10 +1637,13 @@ Calendar.prototype.parseDate = function (str, fmt) { break; } } - if (y != 0 && m != -1 && d != 0) { - this.setDate(new Date(y, m, d, hr, min, 0)); - return; - } + if (isNaN(y)) y = today.getFullYear(); + if (isNaN(m)) m = today.getMonth(); + if (isNaN(d)) d = today.getDate(); + if (isNaN(hr)) hr = today.getHours(); + if (isNaN(min)) min = today.getMinutes(); + if (y != 0 && m != -1 && d != 0) + return new Date(y, m, d, hr, min, 0); y = 0; m = -1; d = 0; for (i = 0; i < a.length; ++i) { if (a[i].search(/[a-zA-Z]+/) != -1) { @@ -1455,142 +1666,13 @@ Calendar.prototype.parseDate = function (str, fmt) { d = a[i]; } } - if (y == 0) { - var today = new Date(); + if (y == 0) y = today.getFullYear(); - } - if (m != -1 && d != 0) { - this.setDate(new Date(y, m, d, hr, min, 0)); - } -}; - -Calendar.prototype.hideShowCovered = function () { - var self = this; - Calendar.continuation_for_the_fucking_khtml_browser = function() { - function getVisib(obj){ - var value = obj.style.visibility; - if (!value) { - if (document.defaultView && typeof (document.defaultView.getComputedStyle) == "function") { // Gecko, W3C - if (!Calendar.is_khtml) - value = document.defaultView. - getComputedStyle(obj, "").getPropertyValue("visibility"); - else - value = ''; - } else if (obj.currentStyle) { // IE - value = obj.currentStyle.visibility; - } else - value = ''; - } - return value; - }; - - var tags = new Array("applet", "iframe", "select"); - var el = self.element; - - var p = Calendar.getAbsolutePos(el); - var EX1 = p.x; - var EX2 = el.offsetWidth + EX1; - var EY1 = p.y; - var EY2 = el.offsetHeight + EY1; - - for (var k = tags.length; k > 0; ) { - var ar = document.getElementsByTagName(tags[--k]); - var cc = null; - - for (var i = ar.length; i > 0;) { - cc = ar[--i]; - - p = Calendar.getAbsolutePos(cc); - var CX1 = p.x; - var CX2 = cc.offsetWidth + CX1; - var CY1 = p.y; - var CY2 = cc.offsetHeight + CY1; - - if (self.hidden || (CX1 > EX2) || (CX2 < EX1) || (CY1 > EY2) || (CY2 < EY1)) { - if (!cc.__msh_save_visibility) { - cc.__msh_save_visibility = getVisib(cc); - } - cc.style.visibility = cc.__msh_save_visibility; - } else { - if (!cc.__msh_save_visibility) { - cc.__msh_save_visibility = getVisib(cc); - } - cc.style.visibility = "hidden"; - } - } - } - }; - if (Calendar.is_khtml) - setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()", 10); - else - Calendar.continuation_for_the_fucking_khtml_browser(); -}; - -/** Internal function; it displays the bar with the names of the weekday. */ -Calendar.prototype._displayWeekdays = function () { - var fdow = this.firstDayOfWeek; - var cell = this.firstdayname; - var weekend = Calendar._TT["WEEKEND"]; - for (var i = 0; i < 7; ++i) { - cell.className = "day name"; - var realday = (i + fdow) % 7; - if (i) { - cell.ttip = Calendar._TT["DAY_FIRST"].replace("%s", Calendar._DN[realday]); - cell.navtype = 100; - cell.calendar = this; - cell.fdow = realday; - Calendar._add_evs(cell); - } - if (weekend.indexOf(realday.toString()) != -1) { - Calendar.addClass(cell, "weekend"); - } - cell.firstChild.data = Calendar._SDN[(i + fdow) % 7]; - cell = cell.nextSibling; - } -}; - -/** Internal function. Hides all combo boxes that might be displayed. */ -Calendar.prototype._hideCombos = function () { - this.monthsCombo.style.display = "none"; - this.yearsCombo.style.display = "none"; -}; - -/** Internal function. Starts dragging the element. */ -Calendar.prototype._dragStart = function (ev) { - if (this.dragging) { - return; - } - this.dragging = true; - var posX; - var posY; - if (Calendar.is_ie) { - posY = window.event.clientY + document.body.scrollTop; - posX = window.event.clientX + document.body.scrollLeft; - } else { - posY = ev.clientY + window.scrollY; - posX = ev.clientX + window.scrollX; - } - var st = this.element.style; - this.xOffs = posX - parseInt(st.left); - this.yOffs = posY - parseInt(st.top); - with (Calendar) { - addEvent(document, "mousemove", calDragIt); - addEvent(document, "mouseup", calDragEnd); - } + if (m != -1 && d != 0) + return new Date(y, m, d, hr, min, 0); + return today; }; -// BEGIN: DATE OBJECT PATCHES - -/** Adds the number of days array to the Date object. */ -Date._MD = new Array(31,28,31,30,31,30,31,31,30,31,30,31); - -/** Constants used for time computations */ -Date.SECOND = 1000 /* milliseconds */; -Date.MINUTE = 60 * Date.SECOND; -Date.HOUR = 60 * Date.MINUTE; -Date.DAY = 24 * Date.HOUR; -Date.WEEK = 7 * Date.DAY; - /** Returns the number of days in the current month */ Date.prototype.getMonthDays = function(month) { var year = this.getFullYear(); @@ -1623,7 +1705,7 @@ Date.prototype.getWeekNumber = function() { return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1; }; -/** Checks dates equality (ignores time) */ +/** Checks date and time equality */ Date.prototype.equalsTo = function(date) { return ((this.getFullYear() == date.getFullYear()) && (this.getMonth() == date.getMonth()) && @@ -1632,6 +1714,15 @@ Date.prototype.equalsTo = function(date) { (this.getMinutes() == date.getMinutes())); }; +/** Set only the year, month, date parts (keep existing time) */ +Date.prototype.setDateOnly = function(date) { + var tmp = new Date(date); + this.setDate(1); + this.setFullYear(tmp.getFullYear()); + this.setMonth(tmp.getMonth()); + this.setDate(tmp.getDate()); +}; + /** Prints the date in a string according to the given format. */ Date.prototype.print = function (str) { var m = this.getMonth(); @@ -1684,7 +1775,7 @@ Date.prototype.print = function (str) { s["%%"] = "%"; // a literal '%' character var re = /%./g; - if (!Calendar.is_ie5) + if (!Calendar.is_ie5 && !Calendar.is_khtml) return str.replace(re, function (par) { return s[par] || par; }); var a = str.match(re); @@ -1712,4 +1803,4 @@ Date.prototype.setFullYear = function(y) { // global object that remembers the calendar -window.calendar = null; +window._dynarch_popupCalendar = null; diff --git a/httemplate/elements/calendar_stripped.js b/httemplate/elements/calendar_stripped.js index 6a8e326af..4fe03f1ea 100644 --- a/httemplate/elements/calendar_stripped.js +++ b/httemplate/elements/calendar_stripped.js @@ -1,12 +1,14 @@ -/* Copyright Mihai Bazon, 2002, 2003 | http://dynarch.com/mishoo/ - * ------------------------------------------------------------------ +/* Copyright Mihai Bazon, 2002-2005 | www.bazon.net/mishoo + * ----------------------------------------------------------- * - * The DHTML Calendar, version 0.9.6 "Keep cool but don't freeze" + * The DHTML Calendar, version 1.0 "It is happening again" * * Details and latest version at: - * http://dynarch.com/mishoo/calendar.epl + * www.dynarch.com/projects/calendar + * + * This script is developed by Dynarch.com. Visit us at www.dynarch.com. * * This script is distributed under the GNU Lesser General Public License. * Read the entire license text here: http://www.gnu.org/licenses/lgpl.html */ - Calendar=function(firstDayOfWeek,dateStr,onSelected,onClose){this.activeDiv=null;this.currentDateEl=null;this.getDateStatus=null;this.timeout=null;this.onSelected=onSelected||null;this.onClose=onClose||null;this.dragging=false;this.hidden=false;this.minYear=1970;this.maxYear=2050;this.dateFormat=Calendar._TT["DEF_DATE_FORMAT"];this.ttDateFormat=Calendar._TT["TT_DATE_FORMAT"];this.isPopup=true;this.weekNumbers=true;this.firstDayOfWeek=firstDayOfWeek;this.showsOtherMonths=false;this.dateStr=dateStr;this.ar_days=null;this.showsTime=false;this.time24=true;this.yearStep=2;this.table=null;this.element=null;this.tbody=null;this.firstdayname=null;this.monthsCombo=null;this.yearsCombo=null;this.hilitedMonth=null;this.activeMonth=null;this.hilitedYear=null;this.activeYear=null;this.dateClicked=false;if(typeof Calendar._SDN=="undefined"){if(typeof Calendar._SDN_len=="undefined")Calendar._SDN_len=3;var ar=new Array();for(var i=8;i>0;){ar[--i]=Calendar._DN[i].substr(0,Calendar._SDN_len);}Calendar._SDN=ar;if(typeof Calendar._SMN_len=="undefined")Calendar._SMN_len=3;ar=new Array();for(var i=12;i>0;){ar[--i]=Calendar._MN[i].substr(0,Calendar._SMN_len);}Calendar._SMN=ar;}};Calendar._C=null;Calendar.is_ie=(/msie/i.test(navigator.userAgent)&&!/opera/i.test(navigator.userAgent));Calendar.is_ie5=(Calendar.is_ie&&/msie 5\.0/i.test(navigator.userAgent));Calendar.is_opera=/opera/i.test(navigator.userAgent);Calendar.is_khtml=/Konqueror|Safari|KHTML/i.test(navigator.userAgent);Calendar.getAbsolutePos=function(el){var SL=0,ST=0;var is_div=/^div$/i.test(el.tagName);if(is_div&&el.scrollLeft)SL=el.scrollLeft;if(is_div&&el.scrollTop)ST=el.scrollTop;var r={x:el.offsetLeft-SL,y:el.offsetTop-ST};if(el.offsetParent){var tmp=this.getAbsolutePos(el.offsetParent);r.x+=tmp.x;r.y+=tmp.y;}return r;};Calendar.isRelated=function(el,evt){var related=evt.relatedTarget;if(!related){var type=evt.type;if(type=="mouseover"){related=evt.fromElement;}else if(type=="mouseout"){related=evt.toElement;}}while(related){if(related==el){return true;}related=related.parentNode;}return false;};Calendar.removeClass=function(el,className){if(!(el&&el.className)){return;}var cls=el.className.split(" ");var ar=new Array();for(var i=cls.length;i>0;){if(cls[--i]!=className){ar[ar.length]=cls[i];}}el.className=ar.join(" ");};Calendar.addClass=function(el,className){Calendar.removeClass(el,className);el.className+=" "+className;};Calendar.getElement=function(ev){if(Calendar.is_ie){return window.event.srcElement;}else{return ev.currentTarget;}};Calendar.getTargetElement=function(ev){if(Calendar.is_ie){return window.event.srcElement;}else{return ev.target;}};Calendar.stopEvent=function(ev){ev||(ev=window.event);if(Calendar.is_ie){ev.cancelBubble=true;ev.returnValue=false;}else{ev.preventDefault();ev.stopPropagation();}return false;};Calendar.addEvent=function(el,evname,func){if(el.attachEvent){el.attachEvent("on"+evname,func);}else if(el.addEventListener){el.addEventListener(evname,func,true);}else{el["on"+evname]=func;}};Calendar.removeEvent=function(el,evname,func){if(el.detachEvent){el.detachEvent("on"+evname,func);}else if(el.removeEventListener){el.removeEventListener(evname,func,true);}else{el["on"+evname]=null;}};Calendar.createElement=function(type,parent){var el=null;if(document.createElementNS){el=document.createElementNS("http://www.w3.org/1999/xhtml",type);}else{el=document.createElement(type);}if(typeof parent!="undefined"){parent.appendChild(el);}return el;};Calendar._add_evs=function(el){with(Calendar){addEvent(el,"mouseover",dayMouseOver);addEvent(el,"mousedown",dayMouseDown);addEvent(el,"mouseout",dayMouseOut);if(is_ie){addEvent(el,"dblclick",dayMouseDblClick);el.setAttribute("unselectable",true);}}};Calendar.findMonth=function(el){if(typeof el.month!="undefined"){return el;}else if(typeof el.parentNode.month!="undefined"){return el.parentNode;}return null;};Calendar.findYear=function(el){if(typeof el.year!="undefined"){return el;}else if(typeof el.parentNode.year!="undefined"){return el.parentNode;}return null;};Calendar.showMonthsCombo=function(){var cal=Calendar._C;if(!cal){return false;}var cal=cal;var cd=cal.activeDiv;var mc=cal.monthsCombo;if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}if(cal.activeMonth){Calendar.removeClass(cal.activeMonth,"active");}var mon=cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];Calendar.addClass(mon,"active");cal.activeMonth=mon;var s=mc.style;s.display="block";if(cd.navtype<0)s.left=cd.offsetLeft+"px";else{var mcw=mc.offsetWidth;if(typeof mcw=="undefined")mcw=50;s.left=(cd.offsetLeft+cd.offsetWidth-mcw)+"px";}s.top=(cd.offsetTop+cd.offsetHeight)+"px";};Calendar.showYearsCombo=function(fwd){var cal=Calendar._C;if(!cal){return false;}var cal=cal;var cd=cal.activeDiv;var yc=cal.yearsCombo;if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}if(cal.activeYear){Calendar.removeClass(cal.activeYear,"active");}cal.activeYear=null;var Y=cal.date.getFullYear()+(fwd?1:-1);var yr=yc.firstChild;var show=false;for(var i=12;i>0;--i){if(Y>=cal.minYear&&Y<=cal.maxYear){yr.firstChild.data=Y;yr.year=Y;yr.style.display="block";show=true;}else{yr.style.display="none";}yr=yr.nextSibling;Y+=fwd?cal.yearStep:-cal.yearStep;}if(show){var s=yc.style;s.display="block";if(cd.navtype<0)s.left=cd.offsetLeft+"px";else{var ycw=yc.offsetWidth;if(typeof ycw=="undefined")ycw=50;s.left=(cd.offsetLeft+cd.offsetWidth-ycw)+"px";}s.top=(cd.offsetTop+cd.offsetHeight)+"px";}};Calendar.tableMouseUp=function(ev){var cal=Calendar._C;if(!cal){return false;}if(cal.timeout){clearTimeout(cal.timeout);}var el=cal.activeDiv;if(!el){return false;}var target=Calendar.getTargetElement(ev);ev||(ev=window.event);Calendar.removeClass(el,"active");if(target==el||target.parentNode==el){Calendar.cellClick(el,ev);}var mon=Calendar.findMonth(target);var date=null;if(mon){date=new Date(cal.date);if(mon.month!=date.getMonth()){date.setMonth(mon.month);cal.setDate(date);cal.dateClicked=false;cal.callHandler();}}else{var year=Calendar.findYear(target);if(year){date=new Date(cal.date);if(year.year!=date.getFullYear()){date.setFullYear(year.year);cal.setDate(date);cal.dateClicked=false;cal.callHandler();}}}with(Calendar){removeEvent(document,"mouseup",tableMouseUp);removeEvent(document,"mouseover",tableMouseOver);removeEvent(document,"mousemove",tableMouseOver);cal._hideCombos();_C=null;return stopEvent(ev);}};Calendar.tableMouseOver=function(ev){var cal=Calendar._C;if(!cal){return;}var el=cal.activeDiv;var target=Calendar.getTargetElement(ev);if(target==el||target.parentNode==el){Calendar.addClass(el,"hilite active");Calendar.addClass(el.parentNode,"rowhilite");}else{if(typeof el.navtype=="undefined"||(el.navtype!=50&&(el.navtype==0||Math.abs(el.navtype)>2)))Calendar.removeClass(el,"active");Calendar.removeClass(el,"hilite");Calendar.removeClass(el.parentNode,"rowhilite");}ev||(ev=window.event);if(el.navtype==50&&target!=el){var pos=Calendar.getAbsolutePos(el);var w=el.offsetWidth;var x=ev.clientX;var dx;var decrease=true;if(x>pos.x+w){dx=x-pos.x-w;decrease=false;}else dx=pos.x-x;if(dx<0)dx=0;var range=el._range;var current=el._current;var count=Math.floor(dx/10)%range.length;for(var i=range.length;--i>=0;)if(range[i]==current)break;while(count-->0)if(decrease){if(--i<0)i=range.length-1;}else if(++i>=range.length)i=0;var newval=range[i];el.firstChild.data=newval;cal.onUpdateTime();}var mon=Calendar.findMonth(target);if(mon){if(mon.month!=cal.date.getMonth()){if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}Calendar.addClass(mon,"hilite");cal.hilitedMonth=mon;}else if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}}else{if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}var year=Calendar.findYear(target);if(year){if(year.year!=cal.date.getFullYear()){if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}Calendar.addClass(year,"hilite");cal.hilitedYear=year;}else if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}}else if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}}return Calendar.stopEvent(ev);};Calendar.tableMouseDown=function(ev){if(Calendar.getTargetElement(ev)==Calendar.getElement(ev)){return Calendar.stopEvent(ev);}};Calendar.calDragIt=function(ev){var cal=Calendar._C;if(!(cal&&cal.dragging)){return false;}var posX;var posY;if(Calendar.is_ie){posY=window.event.clientY+document.body.scrollTop;posX=window.event.clientX+document.body.scrollLeft;}else{posX=ev.pageX;posY=ev.pageY;}cal.hideShowCovered();var st=cal.element.style;st.left=(posX-cal.xOffs)+"px";st.top=(posY-cal.yOffs)+"px";return Calendar.stopEvent(ev);};Calendar.calDragEnd=function(ev){var cal=Calendar._C;if(!cal){return false;}cal.dragging=false;with(Calendar){removeEvent(document,"mousemove",calDragIt);removeEvent(document,"mouseup",calDragEnd);tableMouseUp(ev);}cal.hideShowCovered();};Calendar.dayMouseDown=function(ev){var el=Calendar.getElement(ev);if(el.disabled){return false;}var cal=el.calendar;cal.activeDiv=el;Calendar._C=cal;if(el.navtype!=300)with(Calendar){if(el.navtype==50){el._current=el.firstChild.data;addEvent(document,"mousemove",tableMouseOver);}else addEvent(document,Calendar.is_ie5?"mousemove":"mouseover",tableMouseOver);addClass(el,"hilite active");addEvent(document,"mouseup",tableMouseUp);}else if(cal.isPopup){cal._dragStart(ev);}if(el.navtype==-1||el.navtype==1){if(cal.timeout)clearTimeout(cal.timeout);cal.timeout=setTimeout("Calendar.showMonthsCombo()",250);}else if(el.navtype==-2||el.navtype==2){if(cal.timeout)clearTimeout(cal.timeout);cal.timeout=setTimeout((el.navtype>0)?"Calendar.showYearsCombo(true)":"Calendar.showYearsCombo(false)",250);}else{cal.timeout=null;}return Calendar.stopEvent(ev);};Calendar.dayMouseDblClick=function(ev){Calendar.cellClick(Calendar.getElement(ev),ev||window.event);if(Calendar.is_ie){document.selection.empty();}};Calendar.dayMouseOver=function(ev){var el=Calendar.getElement(ev);if(Calendar.isRelated(el,ev)||Calendar._C||el.disabled){return false;}if(el.ttip){if(el.ttip.substr(0,1)=="_"){el.ttip=el.caldate.print(el.calendar.ttDateFormat)+el.ttip.substr(1);}el.calendar.tooltips.firstChild.data=el.ttip;}if(el.navtype!=300){Calendar.addClass(el,"hilite");if(el.caldate){Calendar.addClass(el.parentNode,"rowhilite");}}return Calendar.stopEvent(ev);};Calendar.dayMouseOut=function(ev){with(Calendar){var el=getElement(ev);if(isRelated(el,ev)||_C||el.disabled){return false;}removeClass(el,"hilite");if(el.caldate){removeClass(el.parentNode,"rowhilite");}el.calendar.tooltips.firstChild.data=_TT["SEL_DATE"];return stopEvent(ev);}};Calendar.cellClick=function(el,ev){var cal=el.calendar;var closing=false;var newdate=false;var date=null;if(typeof el.navtype=="undefined"){Calendar.removeClass(cal.currentDateEl,"selected");Calendar.addClass(el,"selected");closing=(cal.currentDateEl==el);if(!closing){cal.currentDateEl=el;}cal.date=new Date(el.caldate);date=cal.date;newdate=true;if(!(cal.dateClicked=!el.otherMonth))cal._init(cal.firstDayOfWeek,date);}else{if(el.navtype==200){Calendar.removeClass(el,"hilite");cal.callCloseHandler();return;}date=(el.navtype==0)?new Date():new Date(cal.date);cal.dateClicked=false;var year=date.getFullYear();var mon=date.getMonth();function setMonth(m){var day=date.getDate();var max=date.getMonthDays(m);if(day>max){date.setDate(max);}date.setMonth(m);};switch(el.navtype){case 400:Calendar.removeClass(el,"hilite");var text=Calendar._TT["ABOUT"];if(typeof text!="undefined"){text+=cal.showsTime?Calendar._TT["ABOUT_TIME"]:"";}else{text="Help and about box text is not translated into this language.\n"+"If you know this language and you feel generous please update\n"+"the corresponding file in \"lang\" subdir to match calendar-en.js\n"+"and send it back to to get it into the distribution ;-)\n\n"+"Thank you!\n"+"http://dynarch.com/mishoo/calendar.epl\n";}alert(text);return;case-2:if(year>cal.minYear){date.setFullYear(year-1);}break;case-1:if(mon>0){setMonth(mon-1);}else if(year-->cal.minYear){date.setFullYear(year);setMonth(11);}break;case 1:if(mon<11){setMonth(mon+1);}else if(year=0;)if(range[i]==current)break;if(ev&&ev.shiftKey){if(--i<0)i=range.length-1;}else if(++i>=range.length)i=0;var newval=range[i];el.firstChild.data=newval;cal.onUpdateTime();return;case 0:if((typeof cal.getDateStatus=="function")&&cal.getDateStatus(date,date.getFullYear(),date.getMonth(),date.getDate())){return false;}break;}if(!date.equalsTo(cal.date)){cal.setDate(date);newdate=true;}}if(newdate){cal.callHandler();}if(closing){Calendar.removeClass(el,"hilite");cal.callCloseHandler();}};Calendar.prototype.create=function(_par){var parent=null;if(!_par){parent=document.getElementsByTagName("body")[0];this.isPopup=true;}else{parent=_par;this.isPopup=false;}this.date=this.dateStr?new Date(this.dateStr):new Date();var table=Calendar.createElement("table");this.table=table;table.cellSpacing=0;table.cellPadding=0;table.calendar=this;Calendar.addEvent(table,"mousedown",Calendar.tableMouseDown);var div=Calendar.createElement("div");this.element=div;div.className="calendar";if(this.isPopup){div.style.position="absolute";div.style.display="none";}div.appendChild(table);var thead=Calendar.createElement("thead",table);var cell=null;var row=null;var cal=this;var hh=function(text,cs,navtype){cell=Calendar.createElement("td",row);cell.colSpan=cs;cell.className="button";if(navtype!=0&&Math.abs(navtype)<=2)cell.className+=" nav";Calendar._add_evs(cell);cell.calendar=cal;cell.navtype=navtype;if(text.substr(0,1)!="&"){cell.appendChild(document.createTextNode(text));}else{cell.innerHTML=text;}return cell;};row=Calendar.createElement("tr",thead);var title_length=6;(this.isPopup)&&--title_length;(this.weekNumbers)&&++title_length;hh("?",1,400).ttip=Calendar._TT["INFO"];this.title=hh("",title_length,300);this.title.className="title";if(this.isPopup){this.title.ttip=Calendar._TT["DRAG_TO_MOVE"];this.title.style.cursor="move";hh("×",1,200).ttip=Calendar._TT["CLOSE"];}row=Calendar.createElement("tr",thead);row.className="headrow";this._nav_py=hh("«",1,-2);this._nav_py.ttip=Calendar._TT["PREV_YEAR"];this._nav_pm=hh("‹",1,-1);this._nav_pm.ttip=Calendar._TT["PREV_MONTH"];this._nav_now=hh(Calendar._TT["TODAY"],this.weekNumbers?4:3,0);this._nav_now.ttip=Calendar._TT["GO_TODAY"];this._nav_nm=hh("›",1,1);this._nav_nm.ttip=Calendar._TT["NEXT_MONTH"];this._nav_ny=hh("»",1,2);this._nav_ny.ttip=Calendar._TT["NEXT_YEAR"];row=Calendar.createElement("tr",thead);row.className="daynames";if(this.weekNumbers){cell=Calendar.createElement("td",row);cell.className="name wn";cell.appendChild(document.createTextNode(Calendar._TT["WK"]));}for(var i=7;i>0;--i){cell=Calendar.createElement("td",row);cell.appendChild(document.createTextNode(""));if(!i){cell.navtype=100;cell.calendar=this;Calendar._add_evs(cell);}}this.firstdayname=(this.weekNumbers)?row.firstChild.nextSibling:row.firstChild;this._displayWeekdays();var tbody=Calendar.createElement("tbody",table);this.tbody=tbody;for(i=6;i>0;--i){row=Calendar.createElement("tr",tbody);if(this.weekNumbers){cell=Calendar.createElement("td",row);cell.appendChild(document.createTextNode(""));}for(var j=7;j>0;--j){cell=Calendar.createElement("td",row);cell.appendChild(document.createTextNode(""));cell.calendar=this;Calendar._add_evs(cell);}}if(this.showsTime){row=Calendar.createElement("tr",tbody);row.className="time";cell=Calendar.createElement("td",row);cell.className="time";cell.colSpan=2;cell.innerHTML=Calendar._TT["TIME"]||" ";cell=Calendar.createElement("td",row);cell.className="time";cell.colSpan=this.weekNumbers?4:3;(function(){function makeTimePart(className,init,range_start,range_end){var part=Calendar.createElement("span",cell);part.className=className;part.appendChild(document.createTextNode(init));part.calendar=cal;part.ttip=Calendar._TT["TIME_PART"];part.navtype=50;part._range=[];if(typeof range_start!="number")part._range=range_start;else{for(var i=range_start;i<=range_end;++i){var txt;if(i<10&&range_end>=10)txt='0'+i;else txt=''+i;part._range[part._range.length]=txt;}}Calendar._add_evs(part);return part;};var hrs=cal.date.getHours();var mins=cal.date.getMinutes();var t12=!cal.time24;var pm=(hrs>12);if(t12&&pm)hrs-=12;var H=makeTimePart("hour",hrs,t12?1:0,t12?12:23);var span=Calendar.createElement("span",cell);span.appendChild(document.createTextNode(":"));span.className="colon";var M=makeTimePart("minute",mins,0,59);var AP=null;cell=Calendar.createElement("td",row);cell.className="time";cell.colSpan=2;if(t12)AP=makeTimePart("ampm",pm?"pm":"am",["am","pm"]);else cell.innerHTML=" ";cal.onSetTime=function(){var hrs=this.date.getHours();var mins=this.date.getMinutes();var pm=(hrs>12);if(pm&&t12)hrs-=12;H.firstChild.data=(hrs<10)?("0"+hrs):hrs;M.firstChild.data=(mins<10)?("0"+mins):mins;if(t12)AP.firstChild.data=pm?"pm":"am";};cal.onUpdateTime=function(){var date=this.date;var h=parseInt(H.firstChild.data,10);if(t12){if(/pm/i.test(AP.firstChild.data)&&h<12)h+=12;else if(/am/i.test(AP.firstChild.data)&&h==12)h=0;}var d=date.getDate();var m=date.getMonth();var y=date.getFullYear();date.setHours(h);date.setMinutes(parseInt(M.firstChild.data,10));date.setFullYear(y);date.setMonth(m);date.setDate(d);this.dateClicked=false;this.callHandler();};})();}else{this.onSetTime=this.onUpdateTime=function(){};}var tfoot=Calendar.createElement("tfoot",table);row=Calendar.createElement("tr",tfoot);row.className="footrow";cell=hh(Calendar._TT["SEL_DATE"],this.weekNumbers?8:7,300);cell.className="ttip";if(this.isPopup){cell.ttip=Calendar._TT["DRAG_TO_MOVE"];cell.style.cursor="move";}this.tooltips=cell;div=Calendar.createElement("div",this.element);this.monthsCombo=div;div.className="combo";for(i=0;i0;--i){var yr=Calendar.createElement("div");yr.className=Calendar.is_ie?"label-IEfix":"label";yr.appendChild(document.createTextNode(""));div.appendChild(yr);}this._init(this.firstDayOfWeek,this.date);parent.appendChild(this.element);};Calendar._keyEvent=function(ev){if(!window.calendar){return false;}(Calendar.is_ie)&&(ev=window.event);var cal=window.calendar;var act=(Calendar.is_ie||ev.type=="keypress");if(ev.ctrlKey){switch(ev.keyCode){case 37:act&&Calendar.cellClick(cal._nav_pm);break;case 38:act&&Calendar.cellClick(cal._nav_py);break;case 39:act&&Calendar.cellClick(cal._nav_nm);break;case 40:act&&Calendar.cellClick(cal._nav_ny);break;default:return false;}}else switch(ev.keyCode){case 32:Calendar.cellClick(cal._nav_now);break;case 27:act&&cal.callCloseHandler();break;case 37:case 38:case 39:case 40:if(act){var date=cal.date.getDate()-1;var el=cal.currentDateEl;var ne=null;var prev=(ev.keyCode==37)||(ev.keyCode==38);switch(ev.keyCode){case 37:(--date>=0)&&(ne=cal.ar_days[date]);break;case 38:date-=7;(date>=0)&&(ne=cal.ar_days[date]);break;case 39:(++datethis.maxYear){year=this.maxYear;date.setFullYear(year);}this.firstDayOfWeek=firstDayOfWeek;this.date=new Date(date);var month=date.getMonth();var mday=date.getDate();var no_days=date.getMonthDays();date.setDate(1);var day1=(date.getDay()-this.firstDayOfWeek)%7;if(day1<0)day1+=7;date.setDate(-day1);date.setDate(date.getDate()+1);var row=this.tbody.firstChild;var MN=Calendar._SMN[month];var ar_days=new Array();var weekend=Calendar._TT["WEEKEND"];for(var i=0;i<6;++i,row=row.nextSibling){var cell=row.firstChild;if(this.weekNumbers){cell.className="day wn";cell.firstChild.data=date.getWeekNumber();cell=cell.nextSibling;}row.className="daysrow";var hasdays=false;for(var j=0;j<7;++j,cell=cell.nextSibling,date.setDate(date.getDate()+1)){var iday=date.getDate();var wday=date.getDay();cell.className="day";var current_month=(date.getMonth()==month);if(!current_month){if(this.showsOtherMonths){cell.className+=" othermonth";cell.otherMonth=true;}else{cell.className="emptycell";cell.innerHTML=" ";cell.disabled=true;continue;}}else{cell.otherMonth=false;hasdays=true;}cell.disabled=false;cell.firstChild.data=iday;if(typeof this.getDateStatus=="function"){var status=this.getDateStatus(date,year,month,iday);if(status===true){cell.className+=" disabled";cell.disabled=true;}else{if(/disabled/i.test(status))cell.disabled=true;cell.className+=" "+status;}}if(!cell.disabled){ar_days[ar_days.length]=cell;cell.caldate=new Date(date);cell.ttip="_";if(current_month&&iday==mday){cell.className+=" selected";this.currentDateEl=cell;}if(date.getFullYear()==today.getFullYear()&&date.getMonth()==today.getMonth()&&iday==today.getDate()){cell.className+=" today";cell.ttip+=Calendar._TT["PART_TODAY"];}if(weekend.indexOf(wday.toString())!=-1){cell.className+=cell.otherMonth?" oweekend":" weekend";}}}if(!(hasdays||this.showsOtherMonths))row.className="emptyrow";}this.ar_days=ar_days;this.title.firstChild.data=Calendar._MN[month]+", "+year;this.onSetTime();this.table.style.visibility="visible";};Calendar.prototype.setDate=function(date){if(!date.equalsTo(this.date)){this._init(this.firstDayOfWeek,date);}};Calendar.prototype.refresh=function(){this._init(this.firstDayOfWeek,this.date);};Calendar.prototype.setFirstDayOfWeek=function(firstDayOfWeek){this._init(firstDayOfWeek,this.date);this._displayWeekdays();};Calendar.prototype.setDateStatusHandler=Calendar.prototype.setDisabledHandler=function(unaryFunction){this.getDateStatus=unaryFunction;};Calendar.prototype.setRange=function(a,z){this.minYear=a;this.maxYear=z;};Calendar.prototype.callHandler=function(){if(this.onSelected){this.onSelected(this,this.date.print(this.dateFormat));}};Calendar.prototype.callCloseHandler=function(){if(this.onClose){this.onClose(this);}this.hideShowCovered();};Calendar.prototype.destroy=function(){var el=this.element.parentNode;el.removeChild(this.element);Calendar._C=null;window.calendar=null;};Calendar.prototype.reparent=function(new_parent){var el=this.element;el.parentNode.removeChild(el);new_parent.appendChild(el);};Calendar._checkCalendar=function(ev){if(!window.calendar){return false;}var el=Calendar.is_ie?Calendar.getElement(ev):Calendar.getTargetElement(ev);for(;el!=null&&el!=calendar.element;el=el.parentNode);if(el==null){window.calendar.callCloseHandler();return Calendar.stopEvent(ev);}};Calendar.prototype.show=function(){var rows=this.table.getElementsByTagName("tr");for(var i=rows.length;i>0;){var row=rows[--i];Calendar.removeClass(row,"rowhilite");var cells=row.getElementsByTagName("td");for(var j=cells.length;j>0;){var cell=cells[--j];Calendar.removeClass(cell,"hilite");Calendar.removeClass(cell,"active");}}this.element.style.display="block";this.hidden=false;if(this.isPopup){window.calendar=this;Calendar.addEvent(document,"keydown",Calendar._keyEvent);Calendar.addEvent(document,"keypress",Calendar._keyEvent);Calendar.addEvent(document,"mousedown",Calendar._checkCalendar);}this.hideShowCovered();};Calendar.prototype.hide=function(){if(this.isPopup){Calendar.removeEvent(document,"keydown",Calendar._keyEvent);Calendar.removeEvent(document,"keypress",Calendar._keyEvent);Calendar.removeEvent(document,"mousedown",Calendar._checkCalendar);}this.element.style.display="none";this.hidden=true;this.hideShowCovered();};Calendar.prototype.showAt=function(x,y){var s=this.element.style;s.left=x+"px";s.top=y+"px";this.show();};Calendar.prototype.showAtElement=function(el,opts){var self=this;var p=Calendar.getAbsolutePos(el);if(!opts||typeof opts!="string"){this.showAt(p.x,p.y+el.offsetHeight);return true;}function fixPosition(box){if(box.x<0)box.x=0;if(box.y<0)box.y=0;var cp=document.createElement("div");var s=cp.style;s.position="absolute";s.right=s.bottom=s.width=s.height="0px";document.body.appendChild(cp);var br=Calendar.getAbsolutePos(cp);document.body.removeChild(cp);if(Calendar.is_ie){br.y+=document.body.scrollTop;br.x+=document.body.scrollLeft;}else{br.y+=window.scrollY;br.x+=window.scrollX;}var tmp=box.x+box.width-br.x;if(tmp>0)box.x-=tmp;tmp=box.y+box.height-br.y;if(tmp>0)box.y-=tmp;};this.element.style.display="block";Calendar.continuation_for_the_fucking_khtml_browser=function(){var w=self.element.offsetWidth;var h=self.element.offsetHeight;self.element.style.display="none";var valign=opts.substr(0,1);var halign="l";if(opts.length>1){halign=opts.substr(1,1);}switch(valign){case "T":p.y-=h;break;case "B":p.y+=el.offsetHeight;break;case "C":p.y+=(el.offsetHeight-h)/2;break;case "t":p.y+=el.offsetHeight-h;break;case "b":break;}switch(halign){case "L":p.x-=w;break;case "R":p.x+=el.offsetWidth;break;case "C":p.x+=(el.offsetWidth-w)/2;break;case "r":p.x+=el.offsetWidth-w;break;case "l":break;}p.width=w;p.height=h+40;self.monthsCombo.style.display="none";fixPosition(p);self.showAt(p.x,p.y);};if(Calendar.is_khtml)setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()",10);else Calendar.continuation_for_the_fucking_khtml_browser();};Calendar.prototype.setDateFormat=function(str){this.dateFormat=str;};Calendar.prototype.setTtDateFormat=function(str){this.ttDateFormat=str;};Calendar.prototype.parseDate=function(str,fmt){var y=0;var m=-1;var d=0;var a=str.split(/\W+/);if(!fmt){fmt=this.dateFormat;}var b=fmt.match(/%./g);var i=0,j=0;var hr=0;var min=0;for(i=0;i29)?1900:2000);break;case "%b":case "%B":for(j=0;j<12;++j){if(Calendar._MN[j].substr(0,a[i].length).toLowerCase()==a[i].toLowerCase()){m=j;break;}}break;case "%H":case "%I":case "%k":case "%l":hr=parseInt(a[i],10);break;case "%P":case "%p":if(/pm/i.test(a[i])&&hr<12)hr+=12;break;case "%M":min=parseInt(a[i],10);break;}}if(y!=0&&m!=-1&&d!=0){this.setDate(new Date(y,m,d,hr,min,0));return;}y=0;m=-1;d=0;for(i=0;i31&&y==0){y=parseInt(a[i],10);(y<100)&&(y+=(y>29)?1900:2000);}else if(d==0){d=a[i];}}if(y==0){var today=new Date();y=today.getFullYear();}if(m!=-1&&d!=0){this.setDate(new Date(y,m,d,hr,min,0));}};Calendar.prototype.hideShowCovered=function(){var self=this;Calendar.continuation_for_the_fucking_khtml_browser=function(){function getVisib(obj){var value=obj.style.visibility;if(!value){if(document.defaultView&&typeof(document.defaultView.getComputedStyle)=="function"){if(!Calendar.is_khtml)value=document.defaultView. getComputedStyle(obj,"").getPropertyValue("visibility");else value='';}else if(obj.currentStyle){value=obj.currentStyle.visibility;}else value='';}return value;};var tags=new Array("applet","iframe","select");var el=self.element;var p=Calendar.getAbsolutePos(el);var EX1=p.x;var EX2=el.offsetWidth+EX1;var EY1=p.y;var EY2=el.offsetHeight+EY1;for(var k=tags.length;k>0;){var ar=document.getElementsByTagName(tags[--k]);var cc=null;for(var i=ar.length;i>0;){cc=ar[--i];p=Calendar.getAbsolutePos(cc);var CX1=p.x;var CX2=cc.offsetWidth+CX1;var CY1=p.y;var CY2=cc.offsetHeight+CY1;if(self.hidden||(CX1>EX2)||(CX2EY2)||(CY2=12);var ir=(pm)?(hr-12):hr;var dy=this.getDayOfYear();if(ir==0)ir=12;var min=this.getMinutes();var sec=this.getSeconds();s["%a"]=Calendar._SDN[w];s["%A"]=Calendar._DN[w];s["%b"]=Calendar._SMN[m];s["%B"]=Calendar._MN[m];s["%C"]=1+Math.floor(y/100);s["%d"]=(d<10)?("0"+d):d;s["%e"]=d;s["%H"]=(hr<10)?("0"+hr):hr;s["%I"]=(ir<10)?("0"+ir):ir;s["%j"]=(dy<100)?((dy<10)?("00"+dy):("0"+dy)):dy;s["%k"]=hr;s["%l"]=ir;s["%m"]=(m<9)?("0"+(1+m)):(1+m);s["%M"]=(min<10)?("0"+min):min;s["%n"]="\n";s["%p"]=pm?"PM":"AM";s["%P"]=pm?"pm":"am";s["%s"]=Math.floor(this.getTime()/1000);s["%S"]=(sec<10)?("0"+sec):sec;s["%t"]="\t";s["%U"]=s["%W"]=s["%V"]=(wn<10)?("0"+wn):wn;s["%u"]=w+1;s["%w"]=w;s["%y"]=(''+y).substr(2,2);s["%Y"]=y;s["%%"]="%";var re=/%./g;if(!Calendar.is_ie5)return str.replace(re,function(par){return s[par]||par;});var a=str.match(re);for(var i=0;i0;){ar[--i]=Calendar._DN[i].substr(0,Calendar._SDN_len);}Calendar._SDN=ar;if(typeof Calendar._SMN_len=="undefined")Calendar._SMN_len=3;ar=new Array();for(var i=12;i>0;){ar[--i]=Calendar._MN[i].substr(0,Calendar._SMN_len);}Calendar._SMN=ar;}};Calendar._C=null;Calendar.is_ie=(/msie/i.test(navigator.userAgent)&&!/opera/i.test(navigator.userAgent));Calendar.is_ie5=(Calendar.is_ie&&/msie 5\.0/i.test(navigator.userAgent));Calendar.is_opera=/opera/i.test(navigator.userAgent);Calendar.is_khtml=/Konqueror|Safari|KHTML/i.test(navigator.userAgent);Calendar.getAbsolutePos=function(el){var SL=0,ST=0;var is_div=/^div$/i.test(el.tagName);if(is_div&&el.scrollLeft)SL=el.scrollLeft;if(is_div&&el.scrollTop)ST=el.scrollTop;var r={x:el.offsetLeft-SL,y:el.offsetTop-ST};if(el.offsetParent){var tmp=this.getAbsolutePos(el.offsetParent);r.x+=tmp.x;r.y+=tmp.y;}return r;};Calendar.isRelated=function(el,evt){var related=evt.relatedTarget;if(!related){var type=evt.type;if(type=="mouseover"){related=evt.fromElement;}else if(type=="mouseout"){related=evt.toElement;}}while(related){if(related==el){return true;}related=related.parentNode;}return false;};Calendar.removeClass=function(el,className){if(!(el&&el.className)){return;}var cls=el.className.split(" ");var ar=new Array();for(var i=cls.length;i>0;){if(cls[--i]!=className){ar[ar.length]=cls[i];}}el.className=ar.join(" ");};Calendar.addClass=function(el,className){Calendar.removeClass(el,className);el.className+=" "+className;};Calendar.getElement=function(ev){var f=Calendar.is_ie?window.event.srcElement:ev.currentTarget;while(f.nodeType!=1||/^div$/i.test(f.tagName))f=f.parentNode;return f;};Calendar.getTargetElement=function(ev){var f=Calendar.is_ie?window.event.srcElement:ev.target;while(f.nodeType!=1)f=f.parentNode;return f;};Calendar.stopEvent=function(ev){ev||(ev=window.event);if(Calendar.is_ie){ev.cancelBubble=true;ev.returnValue=false;}else{ev.preventDefault();ev.stopPropagation();}return false;};Calendar.addEvent=function(el,evname,func){if(el.attachEvent){el.attachEvent("on"+evname,func);}else if(el.addEventListener){el.addEventListener(evname,func,true);}else{el["on"+evname]=func;}};Calendar.removeEvent=function(el,evname,func){if(el.detachEvent){el.detachEvent("on"+evname,func);}else if(el.removeEventListener){el.removeEventListener(evname,func,true);}else{el["on"+evname]=null;}};Calendar.createElement=function(type,parent){var el=null;if(document.createElementNS){el=document.createElementNS("http://www.w3.org/1999/xhtml",type);}else{el=document.createElement(type);}if(typeof parent!="undefined"){parent.appendChild(el);}return el;};Calendar._add_evs=function(el){with(Calendar){addEvent(el,"mouseover",dayMouseOver);addEvent(el,"mousedown",dayMouseDown);addEvent(el,"mouseout",dayMouseOut);if(is_ie){addEvent(el,"dblclick",dayMouseDblClick);el.setAttribute("unselectable",true);}}};Calendar.findMonth=function(el){if(typeof el.month!="undefined"){return el;}else if(typeof el.parentNode.month!="undefined"){return el.parentNode;}return null;};Calendar.findYear=function(el){if(typeof el.year!="undefined"){return el;}else if(typeof el.parentNode.year!="undefined"){return el.parentNode;}return null;};Calendar.showMonthsCombo=function(){var cal=Calendar._C;if(!cal){return false;}var cal=cal;var cd=cal.activeDiv;var mc=cal.monthsCombo;if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}if(cal.activeMonth){Calendar.removeClass(cal.activeMonth,"active");}var mon=cal.monthsCombo.getElementsByTagName("div")[cal.date.getMonth()];Calendar.addClass(mon,"active");cal.activeMonth=mon;var s=mc.style;s.display="block";if(cd.navtype<0)s.left=cd.offsetLeft+"px";else{var mcw=mc.offsetWidth;if(typeof mcw=="undefined")mcw=50;s.left=(cd.offsetLeft+cd.offsetWidth-mcw)+"px";}s.top=(cd.offsetTop+cd.offsetHeight)+"px";};Calendar.showYearsCombo=function(fwd){var cal=Calendar._C;if(!cal){return false;}var cal=cal;var cd=cal.activeDiv;var yc=cal.yearsCombo;if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}if(cal.activeYear){Calendar.removeClass(cal.activeYear,"active");}cal.activeYear=null;var Y=cal.date.getFullYear()+(fwd?1:-1);var yr=yc.firstChild;var show=false;for(var i=12;i>0;--i){if(Y>=cal.minYear&&Y<=cal.maxYear){yr.innerHTML=Y;yr.year=Y;yr.style.display="block";show=true;}else{yr.style.display="none";}yr=yr.nextSibling;Y+=fwd?cal.yearStep:-cal.yearStep;}if(show){var s=yc.style;s.display="block";if(cd.navtype<0)s.left=cd.offsetLeft+"px";else{var ycw=yc.offsetWidth;if(typeof ycw=="undefined")ycw=50;s.left=(cd.offsetLeft+cd.offsetWidth-ycw)+"px";}s.top=(cd.offsetTop+cd.offsetHeight)+"px";}};Calendar.tableMouseUp=function(ev){var cal=Calendar._C;if(!cal){return false;}if(cal.timeout){clearTimeout(cal.timeout);}var el=cal.activeDiv;if(!el){return false;}var target=Calendar.getTargetElement(ev);ev||(ev=window.event);Calendar.removeClass(el,"active");if(target==el||target.parentNode==el){Calendar.cellClick(el,ev);}var mon=Calendar.findMonth(target);var date=null;if(mon){date=new Date(cal.date);if(mon.month!=date.getMonth()){date.setMonth(mon.month);cal.setDate(date);cal.dateClicked=false;cal.callHandler();}}else{var year=Calendar.findYear(target);if(year){date=new Date(cal.date);if(year.year!=date.getFullYear()){date.setFullYear(year.year);cal.setDate(date);cal.dateClicked=false;cal.callHandler();}}}with(Calendar){removeEvent(document,"mouseup",tableMouseUp);removeEvent(document,"mouseover",tableMouseOver);removeEvent(document,"mousemove",tableMouseOver);cal._hideCombos();_C=null;return stopEvent(ev);}};Calendar.tableMouseOver=function(ev){var cal=Calendar._C;if(!cal){return;}var el=cal.activeDiv;var target=Calendar.getTargetElement(ev);if(target==el||target.parentNode==el){Calendar.addClass(el,"hilite active");Calendar.addClass(el.parentNode,"rowhilite");}else{if(typeof el.navtype=="undefined"||(el.navtype!=50&&(el.navtype==0||Math.abs(el.navtype)>2)))Calendar.removeClass(el,"active");Calendar.removeClass(el,"hilite");Calendar.removeClass(el.parentNode,"rowhilite");}ev||(ev=window.event);if(el.navtype==50&&target!=el){var pos=Calendar.getAbsolutePos(el);var w=el.offsetWidth;var x=ev.clientX;var dx;var decrease=true;if(x>pos.x+w){dx=x-pos.x-w;decrease=false;}else dx=pos.x-x;if(dx<0)dx=0;var range=el._range;var current=el._current;var count=Math.floor(dx/10)%range.length;for(var i=range.length;--i>=0;)if(range[i]==current)break;while(count-->0)if(decrease){if(--i<0)i=range.length-1;}else if(++i>=range.length)i=0;var newval=range[i];el.innerHTML=newval;cal.onUpdateTime();}var mon=Calendar.findMonth(target);if(mon){if(mon.month!=cal.date.getMonth()){if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}Calendar.addClass(mon,"hilite");cal.hilitedMonth=mon;}else if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}}else{if(cal.hilitedMonth){Calendar.removeClass(cal.hilitedMonth,"hilite");}var year=Calendar.findYear(target);if(year){if(year.year!=cal.date.getFullYear()){if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}Calendar.addClass(year,"hilite");cal.hilitedYear=year;}else if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}}else if(cal.hilitedYear){Calendar.removeClass(cal.hilitedYear,"hilite");}}return Calendar.stopEvent(ev);};Calendar.tableMouseDown=function(ev){if(Calendar.getTargetElement(ev)==Calendar.getElement(ev)){return Calendar.stopEvent(ev);}};Calendar.calDragIt=function(ev){var cal=Calendar._C;if(!(cal&&cal.dragging)){return false;}var posX;var posY;if(Calendar.is_ie){posY=window.event.clientY+document.body.scrollTop;posX=window.event.clientX+document.body.scrollLeft;}else{posX=ev.pageX;posY=ev.pageY;}cal.hideShowCovered();var st=cal.element.style;st.left=(posX-cal.xOffs)+"px";st.top=(posY-cal.yOffs)+"px";return Calendar.stopEvent(ev);};Calendar.calDragEnd=function(ev){var cal=Calendar._C;if(!cal){return false;}cal.dragging=false;with(Calendar){removeEvent(document,"mousemove",calDragIt);removeEvent(document,"mouseup",calDragEnd);tableMouseUp(ev);}cal.hideShowCovered();};Calendar.dayMouseDown=function(ev){var el=Calendar.getElement(ev);if(el.disabled){return false;}var cal=el.calendar;cal.activeDiv=el;Calendar._C=cal;if(el.navtype!=300)with(Calendar){if(el.navtype==50){el._current=el.innerHTML;addEvent(document,"mousemove",tableMouseOver);}else addEvent(document,Calendar.is_ie5?"mousemove":"mouseover",tableMouseOver);addClass(el,"hilite active");addEvent(document,"mouseup",tableMouseUp);}else if(cal.isPopup){cal._dragStart(ev);}if(el.navtype==-1||el.navtype==1){if(cal.timeout)clearTimeout(cal.timeout);cal.timeout=setTimeout("Calendar.showMonthsCombo()",250);}else if(el.navtype==-2||el.navtype==2){if(cal.timeout)clearTimeout(cal.timeout);cal.timeout=setTimeout((el.navtype>0)?"Calendar.showYearsCombo(true)":"Calendar.showYearsCombo(false)",250);}else{cal.timeout=null;}return Calendar.stopEvent(ev);};Calendar.dayMouseDblClick=function(ev){Calendar.cellClick(Calendar.getElement(ev),ev||window.event);if(Calendar.is_ie){document.selection.empty();}};Calendar.dayMouseOver=function(ev){var el=Calendar.getElement(ev);if(Calendar.isRelated(el,ev)||Calendar._C||el.disabled){return false;}if(el.ttip){if(el.ttip.substr(0,1)=="_"){el.ttip=el.caldate.print(el.calendar.ttDateFormat)+el.ttip.substr(1);}el.calendar.tooltips.innerHTML=el.ttip;}if(el.navtype!=300){Calendar.addClass(el,"hilite");if(el.caldate){Calendar.addClass(el.parentNode,"rowhilite");}}return Calendar.stopEvent(ev);};Calendar.dayMouseOut=function(ev){with(Calendar){var el=getElement(ev);if(isRelated(el,ev)||_C||el.disabled)return false;removeClass(el,"hilite");if(el.caldate)removeClass(el.parentNode,"rowhilite");if(el.calendar)el.calendar.tooltips.innerHTML=_TT["SEL_DATE"];return stopEvent(ev);}};Calendar.cellClick=function(el,ev){var cal=el.calendar;var closing=false;var newdate=false;var date=null;if(typeof el.navtype=="undefined"){if(cal.currentDateEl){Calendar.removeClass(cal.currentDateEl,"selected");Calendar.addClass(el,"selected");closing=(cal.currentDateEl==el);if(!closing){cal.currentDateEl=el;}}cal.date.setDateOnly(el.caldate);date=cal.date;var other_month=!(cal.dateClicked=!el.otherMonth);if(!other_month&&!cal.currentDateEl)cal._toggleMultipleDate(new Date(date));else newdate=!el.disabled;if(other_month)cal._init(cal.firstDayOfWeek,date);}else{if(el.navtype==200){Calendar.removeClass(el,"hilite");cal.callCloseHandler();return;}date=new Date(cal.date);if(el.navtype==0)date.setDateOnly(new Date());cal.dateClicked=false;var year=date.getFullYear();var mon=date.getMonth();function setMonth(m){var day=date.getDate();var max=date.getMonthDays(m);if(day>max){date.setDate(max);}date.setMonth(m);};switch(el.navtype){case 400:Calendar.removeClass(el,"hilite");var text=Calendar._TT["ABOUT"];if(typeof text!="undefined"){text+=cal.showsTime?Calendar._TT["ABOUT_TIME"]:"";}else{text="Help and about box text is not translated into this language.\n"+"If you know this language and you feel generous please update\n"+"the corresponding file in \"lang\" subdir to match calendar-en.js\n"+"and send it back to to get it into the distribution ;-)\n\n"+"Thank you!\n"+"http://dynarch.com/mishoo/calendar.epl\n";}alert(text);return;case-2:if(year>cal.minYear){date.setFullYear(year-1);}break;case-1:if(mon>0){setMonth(mon-1);}else if(year-->cal.minYear){date.setFullYear(year);setMonth(11);}break;case 1:if(mon<11){setMonth(mon+1);}else if(year=0;)if(range[i]==current)break;if(ev&&ev.shiftKey){if(--i<0)i=range.length-1;}else if(++i>=range.length)i=0;var newval=range[i];el.innerHTML=newval;cal.onUpdateTime();return;case 0:if((typeof cal.getDateStatus=="function")&&cal.getDateStatus(date,date.getFullYear(),date.getMonth(),date.getDate())){return false;}break;}if(!date.equalsTo(cal.date)){cal.setDate(date);newdate=true;}else if(el.navtype==0)newdate=closing=true;}if(newdate){ev&&cal.callHandler();}if(closing){Calendar.removeClass(el,"hilite");ev&&cal.callCloseHandler();}};Calendar.prototype.create=function(_par){var parent=null;if(!_par){parent=document.getElementsByTagName("body")[0];this.isPopup=true;}else{parent=_par;this.isPopup=false;}this.date=this.dateStr?new Date(this.dateStr):new Date();var table=Calendar.createElement("table");this.table=table;table.cellSpacing=0;table.cellPadding=0;table.calendar=this;Calendar.addEvent(table,"mousedown",Calendar.tableMouseDown);var div=Calendar.createElement("div");this.element=div;div.className="calendar";if(this.isPopup){div.style.position="absolute";div.style.display="none";}div.appendChild(table);var thead=Calendar.createElement("thead",table);var cell=null;var row=null;var cal=this;var hh=function(text,cs,navtype){cell=Calendar.createElement("td",row);cell.colSpan=cs;cell.className="button";if(navtype!=0&&Math.abs(navtype)<=2)cell.className+=" nav";Calendar._add_evs(cell);cell.calendar=cal;cell.navtype=navtype;cell.innerHTML="
      "+text+"
      ";return cell;};row=Calendar.createElement("tr",thead);var title_length=6;(this.isPopup)&&--title_length;(this.weekNumbers)&&++title_length;hh("?",1,400).ttip=Calendar._TT["INFO"];this.title=hh("",title_length,300);this.title.className="title";if(this.isPopup){this.title.ttip=Calendar._TT["DRAG_TO_MOVE"];this.title.style.cursor="move";hh("×",1,200).ttip=Calendar._TT["CLOSE"];}row=Calendar.createElement("tr",thead);row.className="headrow";this._nav_py=hh("«",1,-2);this._nav_py.ttip=Calendar._TT["PREV_YEAR"];this._nav_pm=hh("‹",1,-1);this._nav_pm.ttip=Calendar._TT["PREV_MONTH"];this._nav_now=hh(Calendar._TT["TODAY"],this.weekNumbers?4:3,0);this._nav_now.ttip=Calendar._TT["GO_TODAY"];this._nav_nm=hh("›",1,1);this._nav_nm.ttip=Calendar._TT["NEXT_MONTH"];this._nav_ny=hh("»",1,2);this._nav_ny.ttip=Calendar._TT["NEXT_YEAR"];row=Calendar.createElement("tr",thead);row.className="daynames";if(this.weekNumbers){cell=Calendar.createElement("td",row);cell.className="name wn";cell.innerHTML=Calendar._TT["WK"];}for(var i=7;i>0;--i){cell=Calendar.createElement("td",row);if(!i){cell.navtype=100;cell.calendar=this;Calendar._add_evs(cell);}}this.firstdayname=(this.weekNumbers)?row.firstChild.nextSibling:row.firstChild;this._displayWeekdays();var tbody=Calendar.createElement("tbody",table);this.tbody=tbody;for(i=6;i>0;--i){row=Calendar.createElement("tr",tbody);if(this.weekNumbers){cell=Calendar.createElement("td",row);}for(var j=7;j>0;--j){cell=Calendar.createElement("td",row);cell.calendar=this;Calendar._add_evs(cell);}}if(this.showsTime){row=Calendar.createElement("tr",tbody);row.className="time";cell=Calendar.createElement("td",row);cell.className="time";cell.colSpan=2;cell.innerHTML=Calendar._TT["TIME"]||" ";cell=Calendar.createElement("td",row);cell.className="time";cell.colSpan=this.weekNumbers?4:3;(function(){function makeTimePart(className,init,range_start,range_end){var part=Calendar.createElement("span",cell);part.className=className;part.innerHTML=init;part.calendar=cal;part.ttip=Calendar._TT["TIME_PART"];part.navtype=50;part._range=[];if(typeof range_start!="number")part._range=range_start;else{for(var i=range_start;i<=range_end;++i){var txt;if(i<10&&range_end>=10)txt='0'+i;else txt=''+i;part._range[part._range.length]=txt;}}Calendar._add_evs(part);return part;};var hrs=cal.date.getHours();var mins=cal.date.getMinutes();var t12=!cal.time24;var pm=(hrs>12);if(t12&&pm)hrs-=12;var H=makeTimePart("hour",hrs,t12?1:0,t12?12:23);var span=Calendar.createElement("span",cell);span.innerHTML=":";span.className="colon";var M=makeTimePart("minute",mins,0,59);var AP=null;cell=Calendar.createElement("td",row);cell.className="time";cell.colSpan=2;if(t12)AP=makeTimePart("ampm",pm?"pm":"am",["am","pm"]);else cell.innerHTML=" ";cal.onSetTime=function(){var pm,hrs=this.date.getHours(),mins=this.date.getMinutes();if(t12){pm=(hrs>=12);if(pm)hrs-=12;if(hrs==0)hrs=12;AP.innerHTML=pm?"pm":"am";}H.innerHTML=(hrs<10)?("0"+hrs):hrs;M.innerHTML=(mins<10)?("0"+mins):mins;};cal.onUpdateTime=function(){var date=this.date;var h=parseInt(H.innerHTML,10);if(t12){if(/pm/i.test(AP.innerHTML)&&h<12)h+=12;else if(/am/i.test(AP.innerHTML)&&h==12)h=0;}var d=date.getDate();var m=date.getMonth();var y=date.getFullYear();date.setHours(h);date.setMinutes(parseInt(M.innerHTML,10));date.setFullYear(y);date.setMonth(m);date.setDate(d);this.dateClicked=false;this.callHandler();};})();}else{this.onSetTime=this.onUpdateTime=function(){};}var tfoot=Calendar.createElement("tfoot",table);row=Calendar.createElement("tr",tfoot);row.className="footrow";cell=hh(Calendar._TT["SEL_DATE"],this.weekNumbers?8:7,300);cell.className="ttip";if(this.isPopup){cell.ttip=Calendar._TT["DRAG_TO_MOVE"];cell.style.cursor="move";}this.tooltips=cell;div=Calendar.createElement("div",this.element);this.monthsCombo=div;div.className="combo";for(i=0;i0;--i){var yr=Calendar.createElement("div");yr.className=Calendar.is_ie?"label-IEfix":"label";div.appendChild(yr);}this._init(this.firstDayOfWeek,this.date);parent.appendChild(this.element);};Calendar._keyEvent=function(ev){var cal=window._dynarch_popupCalendar;if(!cal||cal.multiple)return false;(Calendar.is_ie)&&(ev=window.event);var act=(Calendar.is_ie||ev.type=="keypress"),K=ev.keyCode;if(ev.ctrlKey){switch(K){case 37:act&&Calendar.cellClick(cal._nav_pm);break;case 38:act&&Calendar.cellClick(cal._nav_py);break;case 39:act&&Calendar.cellClick(cal._nav_nm);break;case 40:act&&Calendar.cellClick(cal._nav_ny);break;default:return false;}}else switch(K){case 32:Calendar.cellClick(cal._nav_now);break;case 27:act&&cal.callCloseHandler();break;case 37:case 38:case 39:case 40:if(act){var prev,x,y,ne,el,step;prev=K==37||K==38;step=(K==37||K==39)?1:7;function setVars(){el=cal.currentDateEl;var p=el.pos;x=p&15;y=p>>4;ne=cal.ar_days[y][x];};setVars();function prevMonth(){var date=new Date(cal.date);date.setDate(date.getDate()-step);cal.setDate(date);};function nextMonth(){var date=new Date(cal.date);date.setDate(date.getDate()+step);cal.setDate(date);};while(1){switch(K){case 37:if(--x>=0)ne=cal.ar_days[y][x];else{x=6;K=38;continue;}break;case 38:if(--y>=0)ne=cal.ar_days[y][x];else{prevMonth();setVars();}break;case 39:if(++x<7)ne=cal.ar_days[y][x];else{x=0;K=40;continue;}break;case 40:if(++ythis.maxYear){year=this.maxYear;date.setFullYear(year);}this.firstDayOfWeek=firstDayOfWeek;this.date=new Date(date);var month=date.getMonth();var mday=date.getDate();var no_days=date.getMonthDays();date.setDate(1);var day1=(date.getDay()-this.firstDayOfWeek)%7;if(day1<0)day1+=7;date.setDate(-day1);date.setDate(date.getDate()+1);var row=this.tbody.firstChild;var MN=Calendar._SMN[month];var ar_days=this.ar_days=new Array();var weekend=Calendar._TT["WEEKEND"];var dates=this.multiple?(this.datesCells={}):null;for(var i=0;i<6;++i,row=row.nextSibling){var cell=row.firstChild;if(this.weekNumbers){cell.className="day wn";cell.innerHTML=date.getWeekNumber();cell=cell.nextSibling;}row.className="daysrow";var hasdays=false,iday,dpos=ar_days[i]=[];for(var j=0;j<7;++j,cell=cell.nextSibling,date.setDate(iday+1)){iday=date.getDate();var wday=date.getDay();cell.className="day";cell.pos=i<<4|j;dpos[j]=cell;var current_month=(date.getMonth()==month);if(!current_month){if(this.showsOtherMonths){cell.className+=" othermonth";cell.otherMonth=true;}else{cell.className="emptycell";cell.innerHTML=" ";cell.disabled=true;continue;}}else{cell.otherMonth=false;hasdays=true;}cell.disabled=false;cell.innerHTML=this.getDateText?this.getDateText(date,iday):iday;if(dates)dates[date.print("%Y%m%d")]=cell;if(this.getDateStatus){var status=this.getDateStatus(date,year,month,iday);if(this.getDateToolTip){var toolTip=this.getDateToolTip(date,year,month,iday);if(toolTip)cell.title=toolTip;}if(status===true){cell.className+=" disabled";cell.disabled=true;}else{if(/disabled/i.test(status))cell.disabled=true;cell.className+=" "+status;}}if(!cell.disabled){cell.caldate=new Date(date);cell.ttip="_";if(!this.multiple&¤t_month&&iday==mday&&this.hiliteToday){cell.className+=" selected";this.currentDateEl=cell;}if(date.getFullYear()==TY&&date.getMonth()==TM&&iday==TD){cell.className+=" today";cell.ttip+=Calendar._TT["PART_TODAY"];}if(weekend.indexOf(wday.toString())!=-1)cell.className+=cell.otherMonth?" oweekend":" weekend";}}if(!(hasdays||this.showsOtherMonths))row.className="emptyrow";}this.title.innerHTML=Calendar._MN[month]+", "+year;this.onSetTime();this.table.style.visibility="visible";this._initMultipleDates();};Calendar.prototype._initMultipleDates=function(){if(this.multiple){for(var i in this.multiple){var cell=this.datesCells[i];var d=this.multiple[i];if(!d)continue;if(cell)cell.className+=" selected";}}};Calendar.prototype._toggleMultipleDate=function(date){if(this.multiple){var ds=date.print("%Y%m%d");var cell=this.datesCells[ds];if(cell){var d=this.multiple[ds];if(!d){Calendar.addClass(cell,"selected");this.multiple[ds]=date;}else{Calendar.removeClass(cell,"selected");delete this.multiple[ds];}}}};Calendar.prototype.setDateToolTipHandler=function(unaryFunction){this.getDateToolTip=unaryFunction;};Calendar.prototype.setDate=function(date){if(!date.equalsTo(this.date)){this._init(this.firstDayOfWeek,date);}};Calendar.prototype.refresh=function(){this._init(this.firstDayOfWeek,this.date);};Calendar.prototype.setFirstDayOfWeek=function(firstDayOfWeek){this._init(firstDayOfWeek,this.date);this._displayWeekdays();};Calendar.prototype.setDateStatusHandler=Calendar.prototype.setDisabledHandler=function(unaryFunction){this.getDateStatus=unaryFunction;};Calendar.prototype.setRange=function(a,z){this.minYear=a;this.maxYear=z;};Calendar.prototype.callHandler=function(){if(this.onSelected){this.onSelected(this,this.date.print(this.dateFormat));}};Calendar.prototype.callCloseHandler=function(){if(this.onClose){this.onClose(this);}this.hideShowCovered();};Calendar.prototype.destroy=function(){var el=this.element.parentNode;el.removeChild(this.element);Calendar._C=null;window._dynarch_popupCalendar=null;};Calendar.prototype.reparent=function(new_parent){var el=this.element;el.parentNode.removeChild(el);new_parent.appendChild(el);};Calendar._checkCalendar=function(ev){var calendar=window._dynarch_popupCalendar;if(!calendar){return false;}var el=Calendar.is_ie?Calendar.getElement(ev):Calendar.getTargetElement(ev);for(;el!=null&&el!=calendar.element;el=el.parentNode);if(el==null){window._dynarch_popupCalendar.callCloseHandler();return Calendar.stopEvent(ev);}};Calendar.prototype.show=function(){var rows=this.table.getElementsByTagName("tr");for(var i=rows.length;i>0;){var row=rows[--i];Calendar.removeClass(row,"rowhilite");var cells=row.getElementsByTagName("td");for(var j=cells.length;j>0;){var cell=cells[--j];Calendar.removeClass(cell,"hilite");Calendar.removeClass(cell,"active");}}this.element.style.display="block";this.hidden=false;if(this.isPopup){window._dynarch_popupCalendar=this;Calendar.addEvent(document,"keydown",Calendar._keyEvent);Calendar.addEvent(document,"keypress",Calendar._keyEvent);Calendar.addEvent(document,"mousedown",Calendar._checkCalendar);}this.hideShowCovered();};Calendar.prototype.hide=function(){if(this.isPopup){Calendar.removeEvent(document,"keydown",Calendar._keyEvent);Calendar.removeEvent(document,"keypress",Calendar._keyEvent);Calendar.removeEvent(document,"mousedown",Calendar._checkCalendar);}this.element.style.display="none";this.hidden=true;this.hideShowCovered();};Calendar.prototype.showAt=function(x,y){var s=this.element.style;s.left=x+"px";s.top=y+"px";this.show();};Calendar.prototype.showAtElement=function(el,opts){var self=this;var p=Calendar.getAbsolutePos(el);if(!opts||typeof opts!="string"){this.showAt(p.x,p.y+el.offsetHeight);return true;}function fixPosition(box){if(box.x<0)box.x=0;if(box.y<0)box.y=0;var cp=document.createElement("div");var s=cp.style;s.position="absolute";s.right=s.bottom=s.width=s.height="0px";document.body.appendChild(cp);var br=Calendar.getAbsolutePos(cp);document.body.removeChild(cp);if(Calendar.is_ie){br.y+=document.body.scrollTop;br.x+=document.body.scrollLeft;}else{br.y+=window.scrollY;br.x+=window.scrollX;}var tmp=box.x+box.width-br.x;if(tmp>0)box.x-=tmp;tmp=box.y+box.height-br.y;if(tmp>0)box.y-=tmp;};this.element.style.display="block";Calendar.continuation_for_the_fucking_khtml_browser=function(){var w=self.element.offsetWidth;var h=self.element.offsetHeight;self.element.style.display="none";var valign=opts.substr(0,1);var halign="l";if(opts.length>1){halign=opts.substr(1,1);}switch(valign){case "T":p.y-=h;break;case "B":p.y+=el.offsetHeight;break;case "C":p.y+=(el.offsetHeight-h)/2;break;case "t":p.y+=el.offsetHeight-h;break;case "b":break;}switch(halign){case "L":p.x-=w;break;case "R":p.x+=el.offsetWidth;break;case "C":p.x+=(el.offsetWidth-w)/2;break;case "l":p.x+=el.offsetWidth-w;break;case "r":break;}p.width=w;p.height=h+40;self.monthsCombo.style.display="none";fixPosition(p);self.showAt(p.x,p.y);};if(Calendar.is_khtml)setTimeout("Calendar.continuation_for_the_fucking_khtml_browser()",10);else Calendar.continuation_for_the_fucking_khtml_browser();};Calendar.prototype.setDateFormat=function(str){this.dateFormat=str;};Calendar.prototype.setTtDateFormat=function(str){this.ttDateFormat=str;};Calendar.prototype.parseDate=function(str,fmt){if(!fmt)fmt=this.dateFormat;this.setDate(Date.parseDate(str,fmt));};Calendar.prototype.hideShowCovered=function(){if(!Calendar.is_ie&&!Calendar.is_opera)return;function getVisib(obj){var value=obj.style.visibility;if(!value){if(document.defaultView&&typeof(document.defaultView.getComputedStyle)=="function"){if(!Calendar.is_khtml)value=document.defaultView. getComputedStyle(obj,"").getPropertyValue("visibility");else value='';}else if(obj.currentStyle){value=obj.currentStyle.visibility;}else value='';}return value;};var tags=new Array("applet","iframe","select");var el=this.element;var p=Calendar.getAbsolutePos(el);var EX1=p.x;var EX2=el.offsetWidth+EX1;var EY1=p.y;var EY2=el.offsetHeight+EY1;for(var k=tags.length;k>0;){var ar=document.getElementsByTagName(tags[--k]);var cc=null;for(var i=ar.length;i>0;){cc=ar[--i];p=Calendar.getAbsolutePos(cc);var CX1=p.x;var CX2=cc.offsetWidth+CX1;var CY1=p.y;var CY2=cc.offsetHeight+CY1;if(this.hidden||(CX1>EX2)||(CX2EY2)||(CY229)?1900:2000);break;case "%b":case "%B":for(j=0;j<12;++j){if(Calendar._MN[j].substr(0,a[i].length).toLowerCase()==a[i].toLowerCase()){m=j;break;}}break;case "%H":case "%I":case "%k":case "%l":hr=parseInt(a[i],10);break;case "%P":case "%p":if(/pm/i.test(a[i])&&hr<12)hr+=12;else if(/am/i.test(a[i])&&hr>=12)hr-=12;break;case "%M":min=parseInt(a[i],10);break;}}if(isNaN(y))y=today.getFullYear();if(isNaN(m))m=today.getMonth();if(isNaN(d))d=today.getDate();if(isNaN(hr))hr=today.getHours();if(isNaN(min))min=today.getMinutes();if(y!=0&&m!=-1&&d!=0)return new Date(y,m,d,hr,min,0);y=0;m=-1;d=0;for(i=0;i31&&y==0){y=parseInt(a[i],10);(y<100)&&(y+=(y>29)?1900:2000);}else if(d==0){d=a[i];}}if(y==0)y=today.getFullYear();if(m!=-1&&d!=0)return new Date(y,m,d,hr,min,0);return today;};Date.prototype.getMonthDays=function(month){var year=this.getFullYear();if(typeof month=="undefined"){month=this.getMonth();}if(((0==(year%4))&&((0!=(year%100))||(0==(year%400))))&&month==1){return 29;}else{return Date._MD[month];}};Date.prototype.getDayOfYear=function(){var now=new Date(this.getFullYear(),this.getMonth(),this.getDate(),0,0,0);var then=new Date(this.getFullYear(),0,0,0,0,0);var time=now-then;return Math.floor(time/Date.DAY);};Date.prototype.getWeekNumber=function(){var d=new Date(this.getFullYear(),this.getMonth(),this.getDate(),0,0,0);var DoW=d.getDay();d.setDate(d.getDate()-(DoW+6)%7+3);var ms=d.valueOf();d.setMonth(0);d.setDate(4);return Math.round((ms-d.valueOf())/(7*864e5))+1;};Date.prototype.equalsTo=function(date){return((this.getFullYear()==date.getFullYear())&&(this.getMonth()==date.getMonth())&&(this.getDate()==date.getDate())&&(this.getHours()==date.getHours())&&(this.getMinutes()==date.getMinutes()));};Date.prototype.setDateOnly=function(date){var tmp=new Date(date);this.setDate(1);this.setFullYear(tmp.getFullYear());this.setMonth(tmp.getMonth());this.setDate(tmp.getDate());};Date.prototype.print=function(str){var m=this.getMonth();var d=this.getDate();var y=this.getFullYear();var wn=this.getWeekNumber();var w=this.getDay();var s={};var hr=this.getHours();var pm=(hr>=12);var ir=(pm)?(hr-12):hr;var dy=this.getDayOfYear();if(ir==0)ir=12;var min=this.getMinutes();var sec=this.getSeconds();s["%a"]=Calendar._SDN[w];s["%A"]=Calendar._DN[w];s["%b"]=Calendar._SMN[m];s["%B"]=Calendar._MN[m];s["%C"]=1+Math.floor(y/100);s["%d"]=(d<10)?("0"+d):d;s["%e"]=d;s["%H"]=(hr<10)?("0"+hr):hr;s["%I"]=(ir<10)?("0"+ir):ir;s["%j"]=(dy<100)?((dy<10)?("00"+dy):("0"+dy)):dy;s["%k"]=hr;s["%l"]=ir;s["%m"]=(m<9)?("0"+(1+m)):(1+m);s["%M"]=(min<10)?("0"+min):min;s["%n"]="\n";s["%p"]=pm?"PM":"AM";s["%P"]=pm?"pm":"am";s["%s"]=Math.floor(this.getTime()/1000);s["%S"]=(sec<10)?("0"+sec):sec;s["%t"]="\t";s["%U"]=s["%W"]=s["%V"]=(wn<10)?("0"+wn):wn;s["%u"]=w+1;s["%w"]=w;s["%y"]=(''+y).substr(2,2);s["%Y"]=y;s["%%"]="%";var re=/%./g;if(!Calendar.is_ie5&&!Calendar.is_khtml)return str.replace(re,function(par){return s[par]||par;});var a=str.match(re);for(var i=0;i Date: Thu, 16 Feb 2006 21:43:02 +0000 Subject: automate more of the initial data adding... --- httemplate/docs/admin.html | 45 ++------------------------------------------ httemplate/docs/install.html | 11 ++--------- 2 files changed, 4 insertions(+), 52 deletions(-) (limited to 'httemplate') diff --git a/httemplate/docs/admin.html b/httemplate/docs/admin.html index 9ce259c2b..2aa934812 100755 --- a/httemplate/docs/admin.html +++ b/httemplate/docs/admin.html @@ -11,49 +11,8 @@ /home/httpd/html, open https://your_host/freeside/. Replace "your_host" with the name or network address of your web server.
    • Select Configuration from the main menu and update your configuration values. -
    • Next you must create a service definition. An example of a service - definition would be a dial-up account or a domain. First, it is - necessary to create a domain definition. Click on View/Edit service - definitions and Add a new service definition with Table - svc_domain (and no modifiers). -
    • Now that you have created your first service, you must create a package - including this service which you can sell to customers. Zero, one, or many - services are bundled into a package. Click on View/Edit package - definitions and Add a new package definition which includes - quantity 1 of the svc_domain service you created above. - -
    • After you create your first package, then you must define who is - able to sell that package by creating an agent type. An example of - an agent type would be an internal sales representitive which sells - regular and promotional packages, as opposed to an external sales - representitive which would only sell regular packages of services. Click on - View/Edit agent types and Add a new agent type. Allow this - agent type to sell the package you created above. - -
    • After creating a new agent type, you must create an agent. Click on - View/Edit agents and Add a new agent. - -
    • Set up at least one Advertising source. Advertising sources will help - you keep track of how effective your advertising is, tracking where customers - heard of your service offerings. You must create at least one advertising - source. If you do not wish to use the referral functionality, simply create - a single advertising source only. Click on View/Edit advertising - sources and Add a new advertising source. - -
    • Click on New Customer and create a new customer for your system - accounts with billing type Complimentary. Leave the First - package dropdown set to (none). - -
    • From the Customer View screen of the newly created customer, order the - package you defined above. - -
    • From the Package View screen of the newly created package, choose - (Provision) to add the customer's service for this new package. - -
    • Add your own domain. - -
    • Go back to View/Edit service definitions on the main menu, and +
    • Go to View/Edit service definitions on the main menu, and Add a new service definition with Table svc_acct. Select your domain in the domsvc Modifier. Set Fixed to define a service locked-in to this domain, or Default to define a service @@ -69,7 +28,7 @@
    • If you are using Freeside to keep track of sales taxes, define tax information for your locales by clicking on the View/Edit locales and tax - rates on the main menu. + rates on the main menu.
    • If you would like Freeside to notify your customers when their credit cards and other billing arrangements are about to expire, arrange for diff --git a/httemplate/docs/install.html b/httemplate/docs/install.html index 1f80db1a7..02572759e 100644 --- a/httemplate/docs/install.html +++ b/httemplate/docs/install.html @@ -196,17 +196,10 @@ require valid-user
      $ su
       # freeside-adduser fs_queue
       # freeside-adduser fs_selfservice
      -
    • As the freeside UNIX user, run freeside-setup username to create the database tables, passing the username of a Freeside user you created above: +
    • As the freeside UNIX user, run freeside-setup -d domain.name username to create the database tables and initial data, passing the username of a Freeside user you created above:
       $ su freeside
      -$ freeside-setup username
      -
      - Alternately, use the -s option to enable shipping addresses: freeside-setup -s username -
    • As the freeside UNIX user, run bin/populate-msgcat username (in the untar'ed freeside directory) to populate the message catalog, passing the username of a Freeside user you created above: -
      -$ su freeside
      -$ cd /path/to/freeside/
      -$ bin/populate-msgcat username
      +$ freeside-setup -d example.com username
       
    • freeside-queued 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 make install-init)
    • Now proceed to the initial administration of your installation. -- cgit v1.2.1 From 6d27649c93f3f83c14611c790281a7b667062fc0 Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 18 Feb 2006 04:32:57 +0000 Subject: Mason it is --- httemplate/docs/install.html | 39 ++------------------------------------- 1 file changed, 2 insertions(+), 37 deletions(-) (limited to 'httemplate') diff --git a/httemplate/docs/install.html b/httemplate/docs/install.html index 02572759e..6e366cbbb 100644 --- a/httemplate/docs/install.html +++ b/httemplate/docs/install.html @@ -52,7 +52,7 @@ Before installing, you need:
    • Net-SSH
    • String-ShellQuote
    • Net-SCP -
    • HTML::Mason (recommended, enables full functionality) or Apache::ASP (deprecated, integrated RT ticketing will not be available) +
    • HTML::Mason
    • Tie-IxHash
    • Time-Duration
    • HTML-Widgets-SelectLayers @@ -123,15 +123,7 @@ $ su
    • Run a separate iteration of Apache[-SSL] with mod_perl enabled as the freeside user.
    • Edit the Makefile and set TEMPLATE to asp or mason. Also set FREESIDE_DOCUMENT_ROOT.
    • Run make install-docs. -
    - - - - - - - - - - - -
    Mason (recommended)Apache::ASP (deprecated)
      -
    • Configure Apache: +
    • Configure Apache:
       PerlModule HTML::Mason
       # your freeside docuemnt root
      @@ -145,33 +137,6 @@ require "/usr/local/etc/freeside/handler.pl";
       </Perl>
       </Directory>
       
      -
      -
    • Configure Apache: -
      -PerlModule Apache::ASP
      -# your freeside document root
      -<Directory /var/www/freeside>
      -<Files ~ (\.cgi|\.html)>
      -AddHandler perl-script .cgi .html
      -PerlHandler Apache::ASP
      -</Files>
      -<Perl>
      -$MLDBM::RemoveTaint = 1;
      -</Perl>
      -PerlSetVar Global /usr/local/etc/freeside/asp-global/
      -PerlSetVar Debug 2
      -PerlSetVar RequestBinaryRead Off
      -# your freeside document root
      -PerlSetVar IncludesDir /var/www/freeside
      -</Directory>
      -
      -
    -
    • Restrict access to this web interface - see the Apache documentation on user authentication. For example, to configure user authentication with mod_auth (flat files), add something like the following to your Apache httpd.conf file, adjusting for your actual paths:
       #your freeside document root
      -- 
      cgit v1.2.1
      
      
      From fadaa67e77ad8d5d966e252aba7f193e9e3840e3 Mon Sep 17 00:00:00 2001
      From: ivan 
      Date: Sat, 18 Feb 2006 11:14:21 +0000
      Subject: CDR schema and class
      
      ---
       httemplate/misc/cdr-import.html         | 15 +++++++++++++++
       httemplate/misc/process/cdr-import.html | 26 ++++++++++++++++++++++++++
       httemplate/search/cdr.html              | 20 ++++++++++++++++++++
       httemplate/search/report_cdr.html       |  7 +++++++
       4 files changed, 68 insertions(+)
       create mode 100644 httemplate/misc/cdr-import.html
       create mode 100644 httemplate/misc/process/cdr-import.html
       create mode 100644 httemplate/search/cdr.html
       create mode 100644 httemplate/search/report_cdr.html
      
      (limited to 'httemplate')
      
      diff --git a/httemplate/misc/cdr-import.html b/httemplate/misc/cdr-import.html
      new file mode 100644
      index 000000000..dc1733249
      --- /dev/null
      +++ b/httemplate/misc/cdr-import.html
      @@ -0,0 +1,15 @@
      +<%= include("/elements/header.html",'Call Detail Record Import') %>
      +
      +Import a CSV file containing Call Detail Records (CDRs).

      +CDR Format:

      + +Filename:

      + + + + +<%= include('/elements/footer.html') %> + diff --git a/httemplate/misc/process/cdr-import.html b/httemplate/misc/process/cdr-import.html new file mode 100644 index 000000000..381b07820 --- /dev/null +++ b/httemplate/misc/process/cdr-import.html @@ -0,0 +1,26 @@ +<% + + my $fh = $cgi->upload('csvfile'); + + my $error = defined($fh) + ? FS::cdr::batch_import( { + 'filehandle' => $fh, + 'format' => $cgi->param('format'), + } ) + : 'No file'; + + if ( $error ) { + %> + + <% + eidiot($error); +# $cgi->param('error', $error); +# print $cgi->redirect( "${p}cust_main-import.cgi + } else { + %> + + <%= include("/elements/header.html",'Import sucessful') %> + + <%= include("/elements/footer.html",'Import sucessful') %> <% + } +%> diff --git a/httemplate/search/cdr.html b/httemplate/search/cdr.html new file mode 100644 index 000000000..75049b443 --- /dev/null +++ b/httemplate/search/cdr.html @@ -0,0 +1,20 @@ +<% + +my $hashref = {}; +#process params for CDR search, populate $hashref... + +my $count_query = 'SELECT COUNT(*) FROM cdr'; +# and fixup $count_query + +%><%= include( 'elements/search.html', + 'title' => 'Call Detail Records', + 'name' => 'call detail records', + 'query' => { 'table' => 'cdr', + 'hashref' => $hashref + }, + 'count_query' => $count_query, + 'header' => [ fields('cdr') ], #XXX fill in some nice names + 'fields' => [ fields('cdr') ], #XXX fill in some pretty-print + # processing, etc. + ) +%> diff --git a/httemplate/search/report_cdr.html b/httemplate/search/report_cdr.html new file mode 100644 index 000000000..b9ad55e10 --- /dev/null +++ b/httemplate/search/report_cdr.html @@ -0,0 +1,7 @@ +<%= include('/elements/header.html', 'Call Detail Record Search' ) %> + +
      + + +<%= include('/elements/footer.html') %> + -- cgit v1.2.1 From e9b7648aa4f838e45de95128dc22053aa8eafdb4 Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 22 Feb 2006 13:07:48 +0000 Subject: add vonage click2call feature --- httemplate/elements/phonenumber.html | 23 +++++++++++++++++++++ httemplate/images/red_telephone_mimooh_01.png | Bin 0 -> 921 bytes httemplate/view/cust_main/contacts.html | 28 ++++++++++++++++++++------ 3 files changed, 45 insertions(+), 6 deletions(-) create mode 100644 httemplate/elements/phonenumber.html create mode 100644 httemplate/images/red_telephone_mimooh_01.png (limited to 'httemplate') diff --git a/httemplate/elements/phonenumber.html b/httemplate/elements/phonenumber.html new file mode 100644 index 000000000..1330ca109 --- /dev/null +++ b/httemplate/elements/phonenumber.html @@ -0,0 +1,23 @@ +<% + my( $number, %opt ) = @_; + my $conf = new FS::Conf; + ( my $snumber = $number ) =~ s/\D//g; +%> + + + + +<% if ( length($number) ) { %> + <%= $number %> + <% if ( $opt{'callable'} && $conf->config('vonage-username') ) { %> + Call this number + <% } %> +<% } else { %> +   +<% } %> diff --git a/httemplate/images/red_telephone_mimooh_01.png b/httemplate/images/red_telephone_mimooh_01.png new file mode 100644 index 000000000..2212ff0e8 Binary files /dev/null and b/httemplate/images/red_telephone_mimooh_01.png differ diff --git a/httemplate/view/cust_main/contacts.html b/httemplate/view/cust_main/contacts.html index 456d117a6..89926ea64 100644 --- a/httemplate/view/cust_main/contacts.html +++ b/httemplate/view/cust_main/contacts.html @@ -51,14 +51,22 @@ Billing address %> <%= $daytime_label %> - - <%= $cust_main->daytime || ' ' %> + + <%= include('/elements/phonenumber.html', + $cust_main->daytime, + 'callable'=>1 + ) + %> <%= $night_label %> - - <%= $cust_main->night || ' ' %> + + <%= include('/elements/phonenumber.html', + $cust_main->night, + 'callable'=>1 + ) + %> @@ -111,13 +119,21 @@ Service address <%= $daytime_label %> - <%= $cust_main->get("${pre}daytime") || ' ' %> + <%= include('/elements/phonenumber.html', + $cust_main->get("${pre}daytime"), + 'callable'=>1 + ) + %> <%= $night_label %> - <%= $cust_main->get("${pre}night") || ' ' %> + <%= include('/elements/phonenumber.html', + $cust_main->get("${pre}night"), + 'callable'=>1 + ) + %> -- cgit v1.2.1 From 02ffd747f8cbc05815c0d96f437c507cfac04ba6 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 3 Mar 2006 15:02:33 +0000 Subject: agent-specific sales/credit/receipts summary --- httemplate/graph/money_time-graph.cgi | 7 +++++++ httemplate/graph/money_time.cgi | 29 +++++++++++++++++++++-------- 2 files changed, 28 insertions(+), 8 deletions(-) (limited to 'httemplate') diff --git a/httemplate/graph/money_time-graph.cgi b/httemplate/graph/money_time-graph.cgi index bb3d23aae..fc8207a81 100755 --- a/httemplate/graph/money_time-graph.cgi +++ b/httemplate/graph/money_time-graph.cgi @@ -12,6 +12,12 @@ my $eyear = $cgi->param('eyear') || 1900+$curyear; my $emonth = $cgi->param('emonth') || $curmon+1; #if ( $emonth++>12 ) { $emonth-=12; $eyear++; } +# XXX or virtual +my $agentnum = ''; +if ( $cgi->param('agentnum') =~ /^(\d*)$/ ) { + $agentnum = $1; +} + #my @labels; #my %data; @@ -37,6 +43,7 @@ my $report = new FS::Report::Table::Monthly ( 'start_year' => $syear, 'end_month' => $emonth, 'end_year' => $eyear, + 'agentnum' => $agentnum, ); my %data = %{$report->data}; diff --git a/httemplate/graph/money_time.cgi b/httemplate/graph/money_time.cgi index 1c7d54266..874f58b09 100644 --- a/httemplate/graph/money_time.cgi +++ b/httemplate/graph/money_time.cgi @@ -12,13 +12,23 @@ my $smonth = $cgi->param('smonth') || $curmon+1; my $eyear = $cgi->param('eyear') || 1900+$curyear; my $emonth = $cgi->param('emonth') || $curmon+1; +#XXX or virtual +my( $agentnum, $agent ) = ('', ''); +if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { + $agentnum = $1; + $agent = qsearchs('agent', { 'agentnum' => $agentnum } ); + die "agentnum $agentnum not found!" unless $agent; +} +my $agentname = $agent ? $agent->agent.' ' : ''; +warn $agentname; + +%> + +<%= include('/elements/header.html', + $agentname. 'Sales, Credits and Receipts Summary' + ) %> - - - Sales, Credits and Receipts Summary - -
      @@ -41,9 +51,9 @@ my %color = ( 'receipts' => '00cc00', #green ); my %link = ( - 'invoiced' => "${p}search/cust_bill.html?", - 'credits' => "${p}search/cust_credit.html?", - 'payments' => "${p}search/cust_pay.cgi?magic=_date;", + 'invoiced' => "${p}search/cust_bill.html?agentnum=$agentnum;", + 'credits' => "${p}search/cust_credit.html?agentnum=$agentnum;", + 'payments' => "${p}search/cust_pay.cgi?magic=_date;agentnum=$agentnum;", ); my $report = new FS::Report::Table::Monthly ( @@ -52,6 +62,7 @@ my $report = new FS::Report::Table::Monthly ( 'start_year' => $syear, 'end_month' => $emonth, 'end_year' => $eyear, + 'agentnum' => $agentnum, ); my $data = $report->data; @@ -119,6 +130,8 @@ From +for agent: <%= include('/elements/select-agent.html', $agentnum) %> + -- cgit v1.2.1 From 600a0939e7e7e589dae4f4f5bfef3650728940b7 Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 8 Mar 2006 10:05:01 +0000 Subject: Add a new table for inventory with for DIDs/serials/etc., and an additional new table for inventory category (i.e. to distinguish DIDs, serials, MACs, etc.) --- httemplate/edit/elements/edit.html | 118 ++++++++++++++++++++++++++ httemplate/edit/inventory_class.html | 9 ++ httemplate/edit/process/elements/process.html | 46 ++++++++++ httemplate/edit/process/inventory_class.html | 4 + httemplate/search/elements/search.html | 80 ++++++++++++++++- httemplate/search/inventory_class.html | 58 +++++++++++++ httemplate/search/inventory_item.html | 35 ++++++++ 7 files changed, 346 insertions(+), 4 deletions(-) create mode 100644 httemplate/edit/elements/edit.html create mode 100644 httemplate/edit/inventory_class.html create mode 100644 httemplate/edit/process/elements/process.html create mode 100644 httemplate/edit/process/inventory_class.html create mode 100644 httemplate/search/inventory_class.html create mode 100644 httemplate/search/inventory_item.html (limited to 'httemplate') diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html new file mode 100644 index 000000000..ce6e2dbb1 --- /dev/null +++ b/httemplate/edit/elements/edit.html @@ -0,0 +1,118 @@ +<% + + # options example... + # + # 'name' => + # 'table' => + # #? 'primary_key' => #required when the dbdef doesn't know...??? + # '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 editable + # 'fields' => [ + # ] + # + # 'menubar' => '', #menubar arrayref + + my(%opt) = @_; + + #false laziness w/process.html + my $table = $opt{'table'}; + my $class = "FS::$table"; + my $pkey = dbdef->table($table)->primary_key; #? $opt{'primary_key'} || + my $fields = $opt{'fields'} + #|| [ grep { $_ ne $pkey } dbdef->table($table)->columns ]; + || [ grep { $_ ne $pkey } fields($table) ]; + + my $object; + if ( $cgi->param('error') ) { + + $object = $class->new( { + map { $_ => scalar($cgi->param($_)) } fields($table) + }); + + } elsif ( $cgi->keywords ) { #editing + + my( $query ) = $cgi->keywords; + $query =~ /^(\d+)$/; + $object = qsearchs( $table, { $pkey => $1 } ); + + } else { #adding + + $object = $class->new( {} ); + + } + + my $action = $object->$pkey() ? 'Edit' : 'Add'; + + my $title = "$action $opt{'name'}"; + + my @menubar = (); + if ( $opt{'menubar'} ) { + @menubar = @{ $opt{'menubar'} }; + } else { + @menubar = ( + 'Main menu' => $p, #eventually get rid of this when the ACL/UI update is done + "View all $opt{'name'}s" => "${p}search/$table.html", #eventually use Lingua::bs to pluralize + ); + } + +%> + + +<%= include("/elements/header.html", $title, + include( '/elements/menubar.html', @menubar ) + ) +%> + +<% if ( $cgi->param('error') ) { %> + Error: <%= $cgi->param('error') %> +

      +<% } %> + +
      + +<%= ( $opt{labels} && exists $opt{labels}->{$pkey} ) + ? $opt{labels}->{$pkey} + : $pkey +%> +#<%= $object->$pkey() || "(NEW)" %> + +<%= ntable("#cccccc",2) %> + +<% foreach my $field ( @$fields ) { %> + + + + + <%= ( $opt{labels} && exists $opt{labels}->{$field} ) + ? $opt{labels}->{$field} + : $field + %> + + + <% + #just text in one size for now... eventually more options for + # uneditable, hidden, + + + + +<% } %> + + + +
      + +"> + +
      + +<%= include("/elements/footer.html") %> + diff --git a/httemplate/edit/inventory_class.html b/httemplate/edit/inventory_class.html new file mode 100644 index 000000000..5dde2e595 --- /dev/null +++ b/httemplate/edit/inventory_class.html @@ -0,0 +1,9 @@ +<%= include( 'elements/edit.html', + 'name' => 'Inventory Class', + 'table' => 'inventory_class', + 'labels' => { + 'classnum' => 'Class number', + 'classname' => 'Class name', + }, + ) +%> diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html new file mode 100644 index 000000000..52c876720 --- /dev/null +++ b/httemplate/edit/process/elements/process.html @@ -0,0 +1,46 @@ +<% + + # options example... + # + # 'table' => + # #? 'primary_key' => #required when the dbdef doesn't know...??? + # #? 'fields' => [] + + my(%opt) = @_; + + #false laziness w/edit.html + my $table = $opt{'table'}; + my $class = "FS::$table"; + my $pkey = dbdef->table($table)->primary_key; #? $opt{'primary_key'} || + my $fields = $opt{'fields'} + #|| [ grep { $_ ne $pkey } dbdef->table($table)->columns ]; + || [ fields($table) ]; + + my $pkeyvalue = $cgi->param($pkey); + + my $old = qsearchs( $table, { $pkey => $pkeyvalue } ) if $pkeyvalue; + + my $new = $class->new( { + map { + $_, scalar($cgi->param($_)); + } @$fields + } ); + + my $error; + if ( $pkeyvalue ) { + $error = $new->replace($old); + } else { + warn $new; + $error = $new->insert; + warn $error; + $pkeyvalue = $new->getfield($pkey); + } + + if ( $error ) { + $cgi->param('error', $error); + print $cgi->redirect(popurl(2). "$table.html?". $cgi->query_string ); + } else { + print $cgi->redirect(popurl(3). "search/$table.html"); + } + +%> diff --git a/httemplate/edit/process/inventory_class.html b/httemplate/edit/process/inventory_class.html new file mode 100644 index 000000000..e30e74e7b --- /dev/null +++ b/httemplate/edit/process/inventory_class.html @@ -0,0 +1,4 @@ +<%= include( 'elements/process.html', + 'table' => 'inventory_class', + ) +%> diff --git a/httemplate/search/elements/search.html b/httemplate/search/elements/search.html index d19fb4acd..b14bded10 100644 --- a/httemplate/search/elements/search.html +++ b/httemplate/search/elements/search.html @@ -1,5 +1,73 @@ <% + # options example... + # (everything not commented required is optional) + # + # # basic options, required + # 'title' => 'Page title', + # 'name' => 'items', #name for the records returned + # + # # some HTML callbacks... + # 'menubar' => '', #menubar arrayref + # 'html_init' => '', #after the header/menubar and before the pager + # + # #literal SQL query string or qsearch hashref, required + # 'query' => { + # 'table' => 'tablename', + # #everything else is optional... + # 'hashref' => { 'field' => 'value', + # 'field' => { 'op' => '<', + # 'value' => '54', + # }, + # }, + # 'select' => '*', + # 'addl_from' => '', #'LEFT JOIN othertable USING ( key )', + # 'extra_sql' => '', #'AND otherstuff', #'WHERE onlystuff', + # + # + # }, + # # "select * from tablename"; + # + # #required unless 'query' is an SQL query string (shouldn't be...) + # 'count_query' => 'SELECT COUNT(*) FROM tablename', + # + # 'count_addl' => [], #additional count fields listref of sprintf strings + # # [ $money_char.'%.2f total paid', ], + # + # #listref of column labels, + # #required unless 'query' is an SQL query string + # # (if not specified the database column names will be used) + # 'header' => [ '#', 'Item' ], + # + # #listref - each item is a literal column name (or method) or coderef + # #if not specified all columns will be shown + # 'fields' => [ + # 'column', + # sub { my $row = shift; $row->column; }, + # ], + # + # #listref of column footers + # 'footer' => [], + # + # #listref - each item is the empty string, or a listref of ... + # 'links' => + # + # + # 'align' => 'lrc.', #one letter for each column, left/right/center/none + # # can also pass a listref with full values: + # # [ 'left', 'right', 'center', '' ] + # + # #listrefs... + # #currently only HTML, maybe eventually Excel too + # 'color' => [], + # 'size' => [], + # 'style' => [], + # + # #redirect if there's only one item... + # # listref of URL base and column name (or method) + # # or a coderef that returns the same + # 'redirect' => + my(%opt) = @_; #warn join(' / ', map { "$_ => $opt{$_}" } keys %opt ). "\n"; @@ -189,7 +257,9 @@ redirect( $url. $rows->[0]->$method() ); } else { ( my $xlsname = $opt{'name'} ) =~ s/\W//g; - $opt{'name'} =~ s/s$// if $total == 1; + #$opt{'name'} =~ s/s$// if $total == 1; + $opt{'name'} =~ s/((s)e)?s$/$2/ if $total == 1; #should use Lingua::bs + # to "depluralize" my @menubar = (); if ( $opt{'menubar'} ) { @@ -197,6 +267,8 @@ } else { @menubar = ( 'Main menu' => $p ); } + + %> <%= include( '/elements/header.html', $opt{'title'}, include( '/elements/menubar.html', @menubar ) @@ -239,7 +311,8 @@ <%= include('/elements/table-grid.html') %> - <% foreach my $header ( @$header ) { %> + <% + foreach my $header ( @$header ) { %> <%= $header %> <% } %> @@ -386,7 +459,6 @@ <% } %> - - + <%= include( '/elements/footer.html' ) %> <% } %> <% } %> diff --git a/httemplate/search/inventory_class.html b/httemplate/search/inventory_class.html new file mode 100644 index 000000000..1bf1bcbce --- /dev/null +++ b/httemplate/search/inventory_class.html @@ -0,0 +1,58 @@ +<% + +tie my %labels, 'Tie::IxHash', + 'num_avail' => 'Available', # (upload batch)', + 'num_used' => 'In use', #'Used', #'Allocated', + 'num_total' => 'Total', +; +my %inv_action_link = ( + 'num_avail' => 'eventually' +); +my %inv_action_label = ( + 'num_avail' => 'upload_batch' +); + +my $link = [ "${p}edit/inventory_class.html?", 'classnum' ]; + +%><%= include( 'elements/search.html', + 'title' => 'Inventory Classes', + 'name' => 'inventory classes', + 'menubar' => [ 'Add a new inventory class' => + $p.'edit/inventory_class.html', + ], + 'query' => { 'table' => 'inventory_class', }, + 'count_query' => 'SELECT COUNT(*) FROM inventory_class', + 'header' => [ '#', 'Inventory class', 'Inventory' ], + 'fields' => [ 'classnum', + 'classname', + sub { + #my $inventory_class = shift; + my $i_c = shift; + + [ map { + [ + { + 'data' => ''. $i_c->$_(). '', + 'align' => 'right', + }, + { + 'data' => $labels{$_}, + 'align' => 'left', + }, + { 'data' => ( exists($inv_action_link{$_}) + ? '('. $inv_action_label{$_}. ')' + : '' + ), + 'align' => 'left', + }, + ] + } keys %labels + ]; + }, + ], + 'links' => [ $link, + $link, + '', + ], + ) +%> diff --git a/httemplate/search/inventory_item.html b/httemplate/search/inventory_item.html new file mode 100644 index 000000000..ff7f1fadf --- /dev/null +++ b/httemplate/search/inventory_item.html @@ -0,0 +1,35 @@ +<% + +my $classnum = $cgi->param('classnum'); +$classnum =~ /^(\d+)$/ or eidiot "illegal agentnum $agentnum"; +$classnum = $1; +my $inventory_class = qsearchs('inventory_class', { 'classnum' => $classnum } ); + +my $count_query = + "SELECT COUNT(*) FROM inventory_class WHERE classnum = $classnum"; + +%><%= include( 'elements/search.html', + 'title' => $inventory_class->classname. ' Inventory', + + #less lame to use Lingua:: something to pluralize + 'name' => $inventory_class->classname. 's', + + 'query' => { + 'table' => 'inventory_item', + 'hashref' => { 'classnum' => $classnum }, + }, + + 'count_query' => $count_query, + + # XXX proper full service/customer link ala svc_acct + 'header' => [ '#', $inventory_class->classname, 'svcnum' ], + + 'fields' => [ + 'itemnum', + 'item', + 'svcnum', #XXX proper full service customer link ala svc_acct + # "unallocated" ? "available" ? + ], + + ) +%> -- cgit v1.2.1 From 6d2cd8e6fc566b4fccd0075156e3e1ddd59fa042 Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 8 Mar 2006 12:14:04 +0000 Subject: Add an option to the web interface to batch upload new entries to the inventory_item table. --- httemplate/misc/inventory_item-import.html | 20 +++++++++ httemplate/misc/process/inventory_item-import.html | 27 ++++++++++++ httemplate/search/inventory_class.html | 49 ++++++++++++++++++---- httemplate/search/inventory_item.html | 25 +++++++++-- 4 files changed, 108 insertions(+), 13 deletions(-) create mode 100644 httemplate/misc/inventory_item-import.html create mode 100644 httemplate/misc/process/inventory_item-import.html (limited to 'httemplate') diff --git a/httemplate/misc/inventory_item-import.html b/httemplate/misc/inventory_item-import.html new file mode 100644 index 000000000..a702fbc49 --- /dev/null +++ b/httemplate/misc/inventory_item-import.html @@ -0,0 +1,20 @@ +<% + +my $classnum = $cgi->param('classnum'); +$classnum =~ /^(\d+)$/ or eidiot "illegal classnum $classnum"; +$classnum = $1; +my $inventory_class = qsearchs('inventory_class', { 'classnum' => $classnum } ); + +%><%= include("/elements/header.html", $inventory_class->classname. 's') %> + +
      + +Import a file containing <%= $inventory_class->classname %>s, one per line.

      + +Filename:

      + + +
      + +<%= include('/elements/footer.html') %> + diff --git a/httemplate/misc/process/inventory_item-import.html b/httemplate/misc/process/inventory_item-import.html new file mode 100644 index 000000000..8a58203c2 --- /dev/null +++ b/httemplate/misc/process/inventory_item-import.html @@ -0,0 +1,27 @@ +<% + + my $fh = $cgi->upload('filename'); + + my $error = defined($fh) + ? FS::inventory_item::batch_import( { + 'filehandle' => $fh, + 'classnum' => $cgi->param('classnum'), + } ) + : 'No file'; + + if ( $error ) { + %> + + <% + eidiot($error); +# $cgi->param('error', $error); +# print $cgi->redirect( "${p}cust_main-import.cgi + } else { + %> + + <%= include("/elements/header.html",'Import sucessful') %> + + <%= include("/elements/footer.html",'Import sucessful') %> <% + } +%> + diff --git a/httemplate/search/inventory_class.html b/httemplate/search/inventory_class.html index 1bf1bcbce..37735f3c9 100644 --- a/httemplate/search/inventory_class.html +++ b/httemplate/search/inventory_class.html @@ -5,11 +5,18 @@ tie my %labels, 'Tie::IxHash', 'num_used' => 'In use', #'Used', #'Allocated', 'num_total' => 'Total', ; -my %inv_action_link = ( - 'num_avail' => 'eventually' + +my %link = ( + 'num_avail' => ';avail=1', + 'num_used' => ';avail=1', + 'num_total' => '', ); -my %inv_action_label = ( - 'num_avail' => 'upload_batch' + +my %inv_action_link = ( + 'num_avail' => [ 'upload batch', + $p.'misc/inventory_item-import.html?classnum=', + 'classnum' + ], ); my $link = [ "${p}edit/inventory_class.html?", 'classnum' ]; @@ -29,20 +36,44 @@ my $link = [ "${p}edit/inventory_class.html?", 'classnum' ]; #my $inventory_class = shift; my $i_c = shift; + my $link = + $p. 'search/inventory_item.html?'. + 'classnum='. $i_c->classnum; + + my %actioncol = (); + foreach ( keys %inv_action_link ) { + my($label, $baseurl, $method) = + @{ $inv_action_link{$_} }; + my $url = $baseurl. $i_c->$method(); + $actioncol{$_} = + ''. + '('. + ''. + $label. + ''. + ')'. + ''; + } + + my %num = map { + $_ => $i_c->$_(); + } keys %labels; + [ map { [ { - 'data' => ''. $i_c->$_(). '', + 'data' => ''. $num{$_}. '', 'align' => 'right', }, { 'data' => $labels{$_}, 'align' => 'left', - }, - { 'data' => ( exists($inv_action_link{$_}) - ? '('. $inv_action_label{$_}. ')' - : '' + 'link' => ( $num{$_} + ? $link.$link{$_} + : '' ), + }, + { 'data' => $actioncol{$_}, 'align' => 'left', }, ] diff --git a/httemplate/search/inventory_item.html b/httemplate/search/inventory_item.html index ff7f1fadf..bd74f5619 100644 --- a/httemplate/search/inventory_item.html +++ b/httemplate/search/inventory_item.html @@ -1,15 +1,31 @@ <% my $classnum = $cgi->param('classnum'); -$classnum =~ /^(\d+)$/ or eidiot "illegal agentnum $agentnum"; +$classnum =~ /^(\d+)$/ or eidiot "illegal classnum $classnum"; $classnum = $1; -my $inventory_class = qsearchs('inventory_class', { 'classnum' => $classnum } ); + +my $inventory_class = qsearchs( { + 'table' => 'inventory_class', + 'hashref' => { 'classnum' => $classnum }, +} ); + +my $title = $inventory_class->classname. ' Inventory'; + +#little false laziness with SQL fragments in inventory_class.pm +my $extra_sql = ''; +if ( $cgi->param('avail') ) { + $extra_sql = 'AND ( svcnum IS NULL OR svcnum = 0 )'; + $title .= ' - Available'; +} elsif ( $cgi->param('used') ) { + $extra_sql = 'AND svcnum IS NOT NULL AND svcnum > 0'; + $title .= ' - In use'; +} my $count_query = - "SELECT COUNT(*) FROM inventory_class WHERE classnum = $classnum"; + "SELECT COUNT(*) FROM inventory_item WHERE classnum = $classnum $extra_sql"; %><%= include( 'elements/search.html', - 'title' => $inventory_class->classname. ' Inventory', + 'title' => $title, #less lame to use Lingua:: something to pluralize 'name' => $inventory_class->classname. 's', @@ -17,6 +33,7 @@ my $count_query = 'query' => { 'table' => 'inventory_item', 'hashref' => { 'classnum' => $classnum }, + 'extra_sql' => $extra_sql, }, 'count_query' => $count_query, -- cgit v1.2.1 From b3d608b436cdf673a5552acf9e4b4601f4f79b9d Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 9 Mar 2006 11:48:06 +0000 Subject: don't use a table with WIDTH="100%", it shoves the custnum and "billing information" boxes way out to the right --- httemplate/view/cust_main.cgi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'httemplate') diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi index 4975c52fd..082a93bb7 100755 --- a/httemplate/view/cust_main.cgi +++ b/httemplate/view/cust_main.cgi @@ -92,12 +92,12 @@ print "This customer's signup URL: ". %> -<%= &itable() %> + - +<% my $conf = new FS::Conf; if ( $conf->exists('voip-cust_cdr_spools') ) { %> + + + + +<% } %>
      <%= include('cust_main/contacts.html', $cust_main ) %> + <%= include('cust_main/misc.html', $cust_main ) %> <% if ( $conf->config('payby-default') ne 'HIDE' ) { %>
      -- cgit v1.2.1 From 5f155263a2c9837640d2fab0817d1f36b8cb3f8c Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 10 Mar 2006 22:30:48 +0000 Subject: fix to (hopefully) allow multiple progress-init's in a page, also add second $cgi arg to all these progressbar calls... --- httemplate/elements/progress-init.html | 8 ++++---- httemplate/misc/email_invoice_events.cgi | 2 +- httemplate/misc/email_invoices.cgi | 2 +- httemplate/misc/fax_invoice_events.cgi | 2 +- httemplate/misc/fax_invoices.cgi | 2 +- httemplate/misc/print_invoice_events.cgi | 2 +- httemplate/misc/print_invoices.cgi | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) (limited to 'httemplate') diff --git a/httemplate/elements/progress-init.html b/httemplate/elements/progress-init.html index 7844f5678..ba9f6edd6 100644 --- a/httemplate/elements/progress-init.html +++ b/httemplate/elements/progress-init.html @@ -14,7 +14,7 @@ <%= include('/elements/xmlhttp.html', 'method' => 'POST', 'url' => $action, - 'subs' => [ 'start_job' ], + 'subs' => [ $key.'start_job' ], ) %> @@ -32,7 +32,7 @@ function <%=$key%>process () { document.<%=$formname%>.submit.disabled=true; - overlib( 'Submitting job to server...', WIDTH, 432, HEIGHT, 136, CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 ); + overlib( 'Submitting job to server...', WIDTH, 444, HEIGHT, 168, CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 ); var Hash = new Array(); var x = 0; @@ -68,13 +68,13 @@ function <%=$key%>process () { //alert('start_job( ' + Hash + ', <%=$key%>myCallback )' ); //alert('start_job()' ); - start_job( Hash, <%=$key%>myCallback ); + <%=$key%>start_job( Hash, <%=$key%>myCallback ); } function <%=$key%>myCallback( jobnum ) { - overlib( OLiframeContent('<%=$p%>elements/progress-popup.html?jobnum=' + jobnum + ';<%=$url_or_message_link%>;formname=<%=$formname%>' , 432, 136, 'progress_popup'), CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 ); + overlib( OLiframeContent('<%=$p%>elements/progress-popup.html?jobnum=' + jobnum + ';<%=$url_or_message_link%>;formname=<%=$formname%>' , 444, 168, 'progress_popup'), CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 ); } diff --git a/httemplate/misc/email_invoice_events.cgi b/httemplate/misc/email_invoice_events.cgi index 12d58d608..b5e66d5ac 100644 --- a/httemplate/misc/email_invoice_events.cgi +++ b/httemplate/misc/email_invoice_events.cgi @@ -1,6 +1,6 @@ <% -my $server = new FS::UI::Web::JSRPC 'FS::cust_bill_event::process_reemail'; +my $server = new FS::UI::Web::JSRPC 'FS::cust_bill_event::process_reemail', $cgi; $server->process; %> diff --git a/httemplate/misc/email_invoices.cgi b/httemplate/misc/email_invoices.cgi index 0a3978395..bd231261c 100644 --- a/httemplate/misc/email_invoices.cgi +++ b/httemplate/misc/email_invoices.cgi @@ -1,6 +1,6 @@ <% -my $server = new FS::UI::Web::JSRPC 'FS::cust_bill::process_reemail'; +my $server = new FS::UI::Web::JSRPC 'FS::cust_bill::process_reemail', $cgi; $server->process; %> diff --git a/httemplate/misc/fax_invoice_events.cgi b/httemplate/misc/fax_invoice_events.cgi index a8ded0550..9a5e8aaea 100644 --- a/httemplate/misc/fax_invoice_events.cgi +++ b/httemplate/misc/fax_invoice_events.cgi @@ -1,6 +1,6 @@ <% -my $server = new FS::UI::Web::JSRPC 'FS::cust_bill_event::process_refax'; +my $server = new FS::UI::Web::JSRPC 'FS::cust_bill_event::process_refax', $cgi; $server->process; %> diff --git a/httemplate/misc/fax_invoices.cgi b/httemplate/misc/fax_invoices.cgi index f16ba8b5e..24bee7da9 100644 --- a/httemplate/misc/fax_invoices.cgi +++ b/httemplate/misc/fax_invoices.cgi @@ -1,6 +1,6 @@ <% -my $server = new FS::UI::Web::JSRPC 'FS::cust_bill::process_refax'; +my $server = new FS::UI::Web::JSRPC 'FS::cust_bill::process_refax', $cgi; $server->process; %> diff --git a/httemplate/misc/print_invoice_events.cgi b/httemplate/misc/print_invoice_events.cgi index c6a7885a4..3cf4cf7c8 100644 --- a/httemplate/misc/print_invoice_events.cgi +++ b/httemplate/misc/print_invoice_events.cgi @@ -1,6 +1,6 @@ <% -my $server = new FS::UI::Web::JSRPC 'FS::cust_bill_event::process_reprint'; +my $server = new FS::UI::Web::JSRPC 'FS::cust_bill_event::process_reprint', $cgi; $server->process; %> diff --git a/httemplate/misc/print_invoices.cgi b/httemplate/misc/print_invoices.cgi index d7b271c37..6d32eaaac 100644 --- a/httemplate/misc/print_invoices.cgi +++ b/httemplate/misc/print_invoices.cgi @@ -1,6 +1,6 @@ <% -my $server = new FS::UI::Web::JSRPC 'FS::cust_bill::process_reprint'; +my $server = new FS::UI::Web::JSRPC 'FS::cust_bill::process_reprint', $cgi; $server->process; %> -- cgit v1.2.1 From 36d9b47e5c20ae3bc71c0bd0eaf289b566d0cf7c Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 11 Mar 2006 05:21:20 +0000 Subject: fix the progressbar bug with multiple progressbar forms on a page --- httemplate/elements/progress-init.html | 3 ++- httemplate/elements/xmlhttp.html | 5 +++-- httemplate/misc/email_invoice_events.cgi | 5 +---- httemplate/misc/email_invoices.cgi | 5 +---- httemplate/misc/fax_invoice_events.cgi | 7 ++----- httemplate/misc/fax_invoices.cgi | 7 ++----- httemplate/misc/print_invoice_events.cgi | 7 ++----- httemplate/misc/print_invoices.cgi | 7 ++----- 8 files changed, 15 insertions(+), 31 deletions(-) (limited to 'httemplate') diff --git a/httemplate/elements/progress-init.html b/httemplate/elements/progress-init.html index ba9f6edd6..efebe48e9 100644 --- a/httemplate/elements/progress-init.html +++ b/httemplate/elements/progress-init.html @@ -14,7 +14,8 @@ <%= include('/elements/xmlhttp.html', 'method' => 'POST', 'url' => $action, - 'subs' => [ $key.'start_job' ], + 'subs' => [ 'start_job' ], + 'key' => $key, ) %> diff --git a/httemplate/elements/xmlhttp.html b/httemplate/elements/xmlhttp.html index 28130e501..e03438822 100644 --- a/httemplate/elements/xmlhttp.html +++ b/httemplate/elements/xmlhttp.html @@ -4,6 +4,7 @@ my $url = $opt{'url'}; my $method = exists($opt{'method'}) ? $opt{'method'} : 'GET'; #my @subs = @{ $opt{'subs'}; + my $key = exists($opt{'key'}) ? $opt{'key'} : ''; $url .= ( ($url =~ /\?/) ? '&' : '?' ) if $method eq 'GET'; @@ -38,10 +39,10 @@ %> - function <%=$func%>() { + function <%=$key%><%=$func%>() { // count args; build URL var url = "<%=$furl%>"; - var a = <%=$func%>.arguments; + var a = <%=$key%><%=$func%>.arguments; var args; var len; diff --git a/httemplate/misc/email_invoice_events.cgi b/httemplate/misc/email_invoice_events.cgi index b5e66d5ac..3a39bcd19 100644 --- a/httemplate/misc/email_invoice_events.cgi +++ b/httemplate/misc/email_invoice_events.cgi @@ -1,6 +1,3 @@ <% - my $server = new FS::UI::Web::JSRPC 'FS::cust_bill_event::process_reemail', $cgi; -$server->process; - -%> +%><%= $server->process %> diff --git a/httemplate/misc/email_invoices.cgi b/httemplate/misc/email_invoices.cgi index bd231261c..490c42f52 100644 --- a/httemplate/misc/email_invoices.cgi +++ b/httemplate/misc/email_invoices.cgi @@ -1,6 +1,3 @@ <% - my $server = new FS::UI::Web::JSRPC 'FS::cust_bill::process_reemail', $cgi; -$server->process; - -%> +%><%= $server->process %> diff --git a/httemplate/misc/fax_invoice_events.cgi b/httemplate/misc/fax_invoice_events.cgi index 9a5e8aaea..778c4291e 100644 --- a/httemplate/misc/fax_invoice_events.cgi +++ b/httemplate/misc/fax_invoice_events.cgi @@ -1,6 +1,3 @@ -<% - +<% my $server = new FS::UI::Web::JSRPC 'FS::cust_bill_event::process_refax', $cgi; -$server->process; - -%> +%><%= $server->process %> diff --git a/httemplate/misc/fax_invoices.cgi b/httemplate/misc/fax_invoices.cgi index 24bee7da9..b3238885f 100644 --- a/httemplate/misc/fax_invoices.cgi +++ b/httemplate/misc/fax_invoices.cgi @@ -1,6 +1,3 @@ -<% - +<% my $server = new FS::UI::Web::JSRPC 'FS::cust_bill::process_refax', $cgi; -$server->process; - -%> +%><%= $server->process %> diff --git a/httemplate/misc/print_invoice_events.cgi b/httemplate/misc/print_invoice_events.cgi index 3cf4cf7c8..897c39ede 100644 --- a/httemplate/misc/print_invoice_events.cgi +++ b/httemplate/misc/print_invoice_events.cgi @@ -1,6 +1,3 @@ <% - -my $server = new FS::UI::Web::JSRPC 'FS::cust_bill_event::process_reprint', $cgi; -$server->process; - -%> +my $server = new FS::UI::Web::JSRPC 'FS::cust_bill_event::process_reprint', $cgi; %> +<%= $server->process %> diff --git a/httemplate/misc/print_invoices.cgi b/httemplate/misc/print_invoices.cgi index 6d32eaaac..218262077 100644 --- a/httemplate/misc/print_invoices.cgi +++ b/httemplate/misc/print_invoices.cgi @@ -1,6 +1,3 @@ -<% - +<% my $server = new FS::UI::Web::JSRPC 'FS::cust_bill::process_reprint', $cgi; -$server->process; - -%> +%><%= $server->process %> -- cgit v1.2.1 From d6a8b9a62765dbfe757e97c35a1c3ba2e0a32b42 Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 11 Mar 2006 07:27:40 +0000 Subject: some pages from ui hoohaw have leaked footer include, need something here for now --- httemplate/elements/footer.html | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 httemplate/elements/footer.html (limited to 'httemplate') diff --git a/httemplate/elements/footer.html b/httemplate/elements/footer.html new file mode 100644 index 000000000..6029d7637 --- /dev/null +++ b/httemplate/elements/footer.html @@ -0,0 +1,2 @@ + + -- cgit v1.2.1 From c1bc54f7523d2af6114d7445bbbe5618f1429794 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 13 Mar 2006 22:32:51 +0000 Subject: fix progress hoohaw for internet exploder again, whew. also make sure error/finish messages are centered, looks better --- httemplate/elements/progress-init.html | 4 +++- httemplate/elements/progress-popup.html | 10 +++++++--- 2 files changed, 10 insertions(+), 4 deletions(-) (limited to 'httemplate') diff --git a/httemplate/elements/progress-init.html b/httemplate/elements/progress-init.html index efebe48e9..ec485f438 100644 --- a/httemplate/elements/progress-init.html +++ b/httemplate/elements/progress-init.html @@ -31,7 +31,9 @@ function <%=$key%>process () { //alert('<%=$key%>process for form <%=$formname%>'); - document.<%=$formname%>.submit.disabled=true; + if ( document.<%=$formname%>.submit.disabled == false ) { + document.<%=$formname%>.submit.disabled=true; + } overlib( 'Submitting job to server...', WIDTH, 444, HEIGHT, 168, CAPTION, 'Please wait...', STICKY, AUTOSTATUSCAP, CLOSETEXT, '', CLOSECLICK, MIDX, 0, MIDY, 0 ); diff --git a/httemplate/elements/progress-popup.html b/httemplate/elements/progress-popup.html index 200f97d9b..544440138 100644 --- a/httemplate/elements/progress-popup.html +++ b/httemplate/elements/progress-popup.html @@ -45,7 +45,9 @@ function updateStatus( status_statustext ) { document.getElementById("progress_bar").innerHTML = ''; document.getElementById("progress_percent").innerHTML = ''; document.getElementById("progress_jobnum").innerHTML = ''; - parent.document.<%=$formname%>.submit.disabled=false; + if ( parent.document.<%=$formname%>.submit.disabled == true ) { + parent.document.<%=$formname%>.submit.disabled=false; + } <% } elsif ( $url ) { %> window.top.location.href = '<%= $url %>'; <% } else { %> @@ -56,7 +58,9 @@ function updateStatus( status_statustext ) { document.getElementById("progress_bar").innerHTML = ''; document.getElementById("progress_percent").innerHTML = ''; document.getElementById("progress_jobnum").innerHTML = ''; - parent.document.<%=$formname%>.submit.disabled=false; + if ( parent.document.<%=$formname%>.submit.disabled == true ) { + parent.document.<%=$formname%>.submit.disabled=false; + } } else { alert('XXX unknown status returned from server: ' + status); } @@ -64,7 +68,7 @@ function updateStatus( status_statustext ) { } - +
      + <% if ( $conf->exists('voip-cust_cdr_spools') ) { %> + + + + <% } else { %> + + <% } %> +
      Server processing job... -- cgit v1.2.1 From ff24bc786a5fd479f2252260e0da580a736f97be Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 20 Mar 2006 19:13:27 +0000 Subject: add price plan to bill on internal or external CDRs directly, add option to export CDRs to a per-customer downstream file --- httemplate/edit/cust_main/billing.html | 10 ++++++++- httemplate/edit/part_pkg.cgi | 39 +++++++++++++++++++++++++--------- httemplate/edit/rate.cgi | 7 ++++-- httemplate/search/cdr.html | 21 +++++++++++++++--- httemplate/search/report_cdr.html | 5 +++++ httemplate/view/cust_main/billing.html | 6 ++++++ 6 files changed, 72 insertions(+), 16 deletions(-) (limited to 'httemplate') diff --git a/httemplate/edit/cust_main/billing.html b/httemplate/edit/cust_main/billing.html index 96f777baa..790f41f00 100644 --- a/httemplate/edit/cust_main/billing.html +++ b/httemplate/edit/cust_main/billing.html @@ -348,7 +348,7 @@ if ( $payby_default eq 'HIDE' ) { ); - + #this should use FS::payby my %allopt = ( 'CARD' => 'Credit card', 'CHEK' => 'Electronic check', @@ -433,6 +433,14 @@ if ( $payby_default eq 'HIDE' ) {
      spool_cdr eq "Y" ? 'CHECKED' : '' %>> Spool CDRs
      diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi index 61e4086be..158c6e2ff 100755 --- a/httemplate/edit/part_pkg.cgi +++ b/httemplate/edit/part_pkg.cgi @@ -297,16 +297,35 @@ my $widget = new HTML::Widgets::SelectLayers( $html .= ' MULTIPLE' if $href->{$field}{'type'} eq 'select_multiple'; $html .= qq! NAME="$field" onChange="fchanged(this)">!; - foreach my $record ( - qsearch( $href->{$field}{'select_table'}, - $href->{$field}{'select_hash'} ) - ) { - my $value = $record->getfield($href->{$field}{'select_key'}); - $html .= qq!
      Spool CDRs<%= $cust_main->spool_cdr ? 'yes' : 'no' %>
      -- cgit v1.2.1 From c39fc534e347971479110595c6a4bb36b40e1198 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 24 Mar 2006 19:49:53 +0000 Subject: fix spelling --- httemplate/misc/process/payment.cgi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'httemplate') diff --git a/httemplate/misc/process/payment.cgi b/httemplate/misc/process/payment.cgi index fa0ede89c..d21c57c40 100644 --- a/httemplate/misc/process/payment.cgi +++ b/httemplate/misc/process/payment.cgi @@ -126,7 +126,7 @@ if ( $cgi->param('save') ) { $new->set( $_ => $cgi->param($_) ) foreach @{$payby2fields{$payby}}; my $error = $new->replace($cust_main); - eidiot "payment processed sucessfully, but error saving info: $error" + eidiot "payment processed successfully, but error saving info: $error" if $error; $cust_main = $new; } @@ -134,7 +134,7 @@ if ( $cgi->param('save') ) { #success! %> -<%= include( '/elements/header.html', ucfirst($type{$payby}). ' processing sucessful', +<%= include( '/elements/header.html', ucfirst($type{$payby}). ' processing successful', include('/elements/menubar.html', 'Main menu' => popurl(3), "View this customer (#$custnum)" => -- cgit v1.2.1 From b9f9a5dc444a66ca138073a0e5229d85569e51b4 Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 25 Mar 2006 02:23:26 +0000 Subject: successfully correct the spelling of sucessful --- httemplate/misc/process/cdr-import.html | 4 ++-- httemplate/misc/process/cust_main-import.cgi | 2 +- httemplate/misc/process/cust_main-import_charges.cgi | 2 +- httemplate/misc/process/inventory_item-import.html | 4 ++-- httemplate/misc/upload-batch.cgi | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) (limited to 'httemplate') diff --git a/httemplate/misc/process/cdr-import.html b/httemplate/misc/process/cdr-import.html index 381b07820..653dd479e 100644 --- a/httemplate/misc/process/cdr-import.html +++ b/httemplate/misc/process/cdr-import.html @@ -19,8 +19,8 @@ } else { %> - <%= include("/elements/header.html",'Import sucessful') %> + <%= include("/elements/header.html",'Import successful') %> - <%= include("/elements/footer.html",'Import sucessful') %> <% + <%= include("/elements/footer.html",'Import successful') %> <% } %> diff --git a/httemplate/misc/process/cust_main-import.cgi b/httemplate/misc/process/cust_main-import.cgi index 2348ef680..371929a5e 100644 --- a/httemplate/misc/process/cust_main-import.cgi +++ b/httemplate/misc/process/cust_main-import.cgi @@ -25,6 +25,6 @@ } else { %> - <%= include("/elements/header.html",'Import sucessful') %> <% + <%= include("/elements/header.html",'Import successful') %> <% } %> diff --git a/httemplate/misc/process/cust_main-import_charges.cgi b/httemplate/misc/process/cust_main-import_charges.cgi index c14228cf4..404dfde2e 100644 --- a/httemplate/misc/process/cust_main-import_charges.cgi +++ b/httemplate/misc/process/cust_main-import_charges.cgi @@ -21,6 +21,6 @@ } else { %> - <%= include("/elements/header.html",'Import sucessful') %> <% + <%= include("/elements/header.html",'Import successful') %> <% } %> diff --git a/httemplate/misc/process/inventory_item-import.html b/httemplate/misc/process/inventory_item-import.html index 8a58203c2..e98a6ed2a 100644 --- a/httemplate/misc/process/inventory_item-import.html +++ b/httemplate/misc/process/inventory_item-import.html @@ -19,9 +19,9 @@ } else { %> - <%= include("/elements/header.html",'Import sucessful') %> + <%= include("/elements/header.html",'Import successful') %> - <%= include("/elements/footer.html",'Import sucessful') %> <% + <%= include("/elements/footer.html",'Import successful') %> <% } %> diff --git a/httemplate/misc/upload-batch.cgi b/httemplate/misc/upload-batch.cgi index 24d7cf15c..746b81b17 100644 --- a/httemplate/misc/upload-batch.cgi +++ b/httemplate/misc/upload-batch.cgi @@ -24,7 +24,7 @@ } else { %> - <%= include("/elements/header.html",'Batch results upload sucessful') %> <% + <%= include("/elements/header.html",'Batch results upload successful') %> <% } %> -- cgit v1.2.1 From 9719693a031bee8d35dffa7ea543f27a25443309 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 31 Mar 2006 23:22:08 +0000 Subject: quick sort fix for billing events --- httemplate/browse/part_bill_event.cgi | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'httemplate') diff --git a/httemplate/browse/part_bill_event.cgi b/httemplate/browse/part_bill_event.cgi index 380e4d78b..91e31d832 100755 --- a/httemplate/browse/part_bill_event.cgi +++ b/httemplate/browse/part_bill_event.cgi @@ -31,13 +31,14 @@ my $total = scalar(@part_bill_event); foreach my $payby ( keys %payby ) { my $oldfreq = ''; - my @payby_part_bill_event = grep { $payby eq $_->payby } - sort { $a->freq cmp $b->freq # for now - || $a->seconds <=> $b->seconds - || $a->weight <=> $b->weight - || $a->eventpart <=> $b->eventpart - } - @part_bill_event; + my @payby_part_bill_event = + grep { $payby eq $_->payby } + sort { ( $a->freq || '1d') cmp ( $b->freq || '1d' ) # for now + || $a->seconds <=> $b->seconds + || $a->weight <=> $b->weight + || $a->eventpart <=> $b->eventpart + } + @part_bill_event; %> -- cgit v1.2.1 From 929f432c766bbe3bdeed5b80818a12ddf6ec6339 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 3 Apr 2006 09:46:57 +0000 Subject: have the UI use full country names, and state names outside the US... --- httemplate/edit/cust_main/contact.html | 2 +- httemplate/edit/cust_main/select-country.html | 11 ++++++----- httemplate/edit/cust_main/select-state.html | 13 +++---------- httemplate/misc/states.cgi | 14 ++------------ httemplate/view/cust_main/contacts.html | 4 ++-- 5 files changed, 14 insertions(+), 30 deletions(-) (limited to 'httemplate') diff --git a/httemplate/edit/cust_main/contact.html b/httemplate/edit/cust_main/contact.html index e0cd06f56..6e4f08957 100644 --- a/httemplate/edit/cust_main/contact.html +++ b/httemplate/edit/cust_main/contact.html @@ -96,7 +96,7 @@ my $r = qq!* !; <%=$r%>Country - <%= include('select-country.html', %select_hash ) %> + <%= include('select-country.html', %select_hash ) %> diff --git a/httemplate/edit/cust_main/select-country.html b/httemplate/edit/cust_main/select-country.html index 014effd66..3941f2f93 100644 --- a/httemplate/edit/cust_main/select-country.html +++ b/httemplate/edit/cust_main/select-country.html @@ -26,7 +26,7 @@ function <%= $opt{'prefix'} %>country_changed(what, callback) { - country = what.options[what.selectedIndex].text; + country = what.options[what.selectedIndex].value; function <%= $opt{'prefix'} %>update_states(states) { @@ -36,8 +36,8 @@ // add the new states var statesArray = eval('(' + states + ')' ); - for ( var s = 0; s < statesArray.length; s++ ) { - var stateLabel = statesArray[s]; + for ( var s = 0; s < statesArray.length; s=s+2 ) { + var stateLabel = statesArray[s+1]; if ( stateLabel == "" ) stateLabel = '(n/a)'; opt(what.form.<%= $opt{'prefix'} %>state, statesArray[s], stateLabel); @@ -58,13 +58,14 @@ > -<% foreach my $state ( - sort - map { $_->state } - qsearch( 'cust_main_county', - { 'country' => $opt{'country'} }, - 'DISTINCT ON ( state ) *', - ) - ) { -%> +<% tie my %states, 'Tie::IxHash', states_hash( $opt{'country'} ); %> +<% foreach my $state ( keys %states ) { %> -
    @@ -234,6 +234,8 @@ - Locally defined fields
  • View/Edit message catalog - Change error messages and other customizable labels. +
  • View/Edit inventory classes and inventory + - Setup inventory classes and stock inventory.

diff --git a/httemplate/search/cust_pkg.cgi b/httemplate/search/cust_pkg.cgi index 5da4d82fb..a2fb89c12 100755 --- a/httemplate/search/cust_pkg.cgi +++ b/httemplate/search/cust_pkg.cgi @@ -19,8 +19,10 @@ if ( $cgi->param('magic') && $cgi->param('magic') eq 'bill' ) { my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi); push @where, - "bill >= $beginning ", - "bill <= $ending", + #"bill >= $beginning ", + #"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 )'; } else { @@ -141,7 +143,7 @@ sub time_or_blank { 'name' => 'packages', 'query' => $sql_query, 'count_query' => $count_query, - 'redirect' => $link, + #'redirect' => $link, 'header' => [ '#', 'Package', 'Status', diff --git a/httemplate/search/elements/search.html b/httemplate/search/elements/search.html index 7f7243588..6cf574164 100644 --- a/httemplate/search/elements/search.html +++ b/httemplate/search/elements/search.html @@ -8,8 +8,12 @@ # 'name' => 'items', #name for the records returned # # # some HTML callbacks... - # 'menubar' => '', #menubar arrayref - # 'html_init' => '', #after the header/menubar and before the pager + # 'menubar' => '', #menubar arrayref + # 'html_init' => '', #after the header/menubar and before the pager + # 'html_foot' => '', #at the bottom + # 'html_posttotal' => '', #at the bottom + # # (these three can be strings or coderefs) + # # # #literal SQL query string or qsearch hashref, required # 'query' => { @@ -39,6 +43,10 @@ # # (if not specified the database column names will be used) # 'header' => [ '#', 'Item' ], # + # 'disable_download' => '', # set true to hide the CSV/Excel download links + # 'disable_nonefound' => '', # set true to disable the "No matching Xs found" + # # message + # # #listref - each item is a literal column name (or method) or coderef # #if not specified all columns will be shown # 'fields' => [ @@ -286,7 +294,13 @@ include( '/elements/menubar.html', @menubar ) ) %> - <%= defined($opt{'html_init'}) ? $opt{'html_init'} : '' %> + <%= defined($opt{'html_init'}) + ? ( ref($opt{'html_init'}) + ? &{$opt{'html_init'}}() + : $opt{'html_init'} + ) + : '' + %> <% my $pager = include ( '/elements/pager.html', 'offset' => $offset, 'num_rows' => scalar(@$rows), @@ -295,26 +309,38 @@ ); %> <% unless ( $total ) { %> - No matching <%= $opt{'name'} %> found.
+ <% unless ( $opt{'disable_nonefound'} ) { %> + No matching <%= $opt{'name'} %> found.
+ <% } %> <% } else { %> - + <% unless ( $opt{'disable_download'} ) { %> + + <% } %>
- <%= $total %> total <%= $opt{'name'} %>
+ <%= $total %> total <%= $opt{'name'} %> + <%= defined($opt{'html_posttotal'}) + ? ( ref($opt{'html_posttotal'}) + ? &{$opt{'html_posttotal'}}() + : $opt{'html_posttotal'} + ) + : '' + %> +
<% if ( $opt{'count_addl'} ) { %> <% my $n=0; foreach my $count ( @{$opt{'count_addl'}} ) { %> <%= sprintf( $count, $count_arrayref->[++$n] ) %>
<% } %> <% } %>
- <% $cgi->param('_type', "$xlsname.xls" ); %> - Download full results
- as Excel spreadsheet
- <% $cgi->param('_type', 'csv'); %> - as CSV file -
+ <% $cgi->param('_type', "$xlsname.xls" ); %> + Download full results
+ as Excel spreadsheet
+ <% $cgi->param('_type', 'csv'); %> + as CSV file +
@@ -471,6 +497,13 @@
<% } %> + <%= defined($opt{'html_foot'}) + ? ( ref($opt{'html_foot'}) + ? &{$opt{'html_foot'}}() + : $opt{'html_foot'} + ) + : '' + %> <%= include( '/elements/footer.html' ) %> <% } %> <% } %> diff --git a/httemplate/search/inventory_class.html b/httemplate/search/inventory_class.html deleted file mode 100644 index 37735f3c9..000000000 --- a/httemplate/search/inventory_class.html +++ /dev/null @@ -1,89 +0,0 @@ -<% - -tie my %labels, 'Tie::IxHash', - 'num_avail' => 'Available', # (upload batch)', - 'num_used' => 'In use', #'Used', #'Allocated', - 'num_total' => 'Total', -; - -my %link = ( - 'num_avail' => ';avail=1', - 'num_used' => ';avail=1', - 'num_total' => '', -); - -my %inv_action_link = ( - 'num_avail' => [ 'upload batch', - $p.'misc/inventory_item-import.html?classnum=', - 'classnum' - ], -); - -my $link = [ "${p}edit/inventory_class.html?", 'classnum' ]; - -%><%= include( 'elements/search.html', - 'title' => 'Inventory Classes', - 'name' => 'inventory classes', - 'menubar' => [ 'Add a new inventory class' => - $p.'edit/inventory_class.html', - ], - 'query' => { 'table' => 'inventory_class', }, - 'count_query' => 'SELECT COUNT(*) FROM inventory_class', - 'header' => [ '#', 'Inventory class', 'Inventory' ], - 'fields' => [ 'classnum', - 'classname', - sub { - #my $inventory_class = shift; - my $i_c = shift; - - my $link = - $p. 'search/inventory_item.html?'. - 'classnum='. $i_c->classnum; - - my %actioncol = (); - foreach ( keys %inv_action_link ) { - my($label, $baseurl, $method) = - @{ $inv_action_link{$_} }; - my $url = $baseurl. $i_c->$method(); - $actioncol{$_} = - ''. - '('. - ''. - $label. - ''. - ')'. - ''; - } - - my %num = map { - $_ => $i_c->$_(); - } keys %labels; - - [ map { - [ - { - 'data' => ''. $num{$_}. '', - 'align' => 'right', - }, - { - 'data' => $labels{$_}, - 'align' => 'left', - 'link' => ( $num{$_} - ? $link.$link{$_} - : '' - ), - }, - { 'data' => $actioncol{$_}, - 'align' => 'left', - }, - ] - } keys %labels - ]; - }, - ], - 'links' => [ $link, - $link, - '', - ], - ) -%> -- cgit v1.2.1 From f29c752d6f9e813c10295b334eefb924216e34cf Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 2 May 2006 11:59:31 +0000 Subject: add a "pre-report" page to this report/graph as requested by lewis/wtxs, also add 12mo total option --- httemplate/graph/money_time-graph.cgi | 9 +++++ httemplate/graph/money_time.cgi | 67 +++++++++---------------------- httemplate/graph/report_money_time.html | 71 +++++++++++++++++++++++++++++++++ httemplate/index.html | 2 +- 4 files changed, 99 insertions(+), 50 deletions(-) create mode 100644 httemplate/graph/report_money_time.html (limited to 'httemplate') diff --git a/httemplate/graph/money_time-graph.cgi b/httemplate/graph/money_time-graph.cgi index fc8207a81..637a3bf94 100755 --- a/httemplate/graph/money_time-graph.cgi +++ b/httemplate/graph/money_time-graph.cgi @@ -22,6 +22,10 @@ if ( $cgi->param('agentnum') =~ /^(\d*)$/ ) { #my %data; my @items = qw( invoiced netsales credits payments receipts ); +if ( $cgi->param('12mo') == 1 ) { + @items = map $_.'_12mo', @items; +} + my %label = ( 'invoiced' => 'Gross Sales (invoiced)', 'netsales' => 'Net Sales (invoiced - applied credits)', @@ -29,6 +33,9 @@ my %label = ( 'payments' => 'Gross Receipts (payments)', 'receipts' => 'Net Receipts/Cashflow (payments - refunds)', ); +$label{$_.'_12mo'} = $label{$_}. " (previous 12 months)" + foreach keys %label; + my %color = ( 'invoiced' => [ 153, 153, 255 ], #light blue 'netsales' => [ 0, 0, 204 ], #blue @@ -36,6 +43,8 @@ my %color = ( 'payments' => [ 153, 204, 153 ], #light green 'receipts' => [ 0, 204, 0 ], #green ); +$color{$_.'_12mo'} = $color{$_} + foreach keys %color; my $report = new FS::Report::Table::Monthly ( 'items' => \@items, diff --git a/httemplate/graph/money_time.cgi b/httemplate/graph/money_time.cgi index bc789cb7e..73f9d23a2 100644 --- a/httemplate/graph/money_time.cgi +++ b/httemplate/graph/money_time.cgi @@ -1,16 +1,15 @@ - <% -#my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); -my ($curmon,$curyear) = (localtime(time))[4,5]; +# #my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); +# my ($curmon,$curyear) = (localtime(time))[4,5]; #find first month -my $syear = $cgi->param('syear') || 1899+$curyear; -my $smonth = $cgi->param('smonth') || $curmon+1; +my $syear = $cgi->param('syear'); # || 1899+$curyear; +my $smonth = $cgi->param('smonth'); # || $curmon+1; #find last month -my $eyear = $cgi->param('eyear') || 1900+$curyear; -my $emonth = $cgi->param('emonth') || $curmon+1; +my $eyear = $cgi->param('eyear'); # || 1900+$curyear; +my $emonth = $cgi->param('emonth'); # || $curmon+1; #XXX or virtual my( $agentnum, $agent ) = ('', ''); @@ -20,10 +19,8 @@ if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { die "agentnum $agentnum not found!" unless $agent; } my $agentname = $agent ? $agent->agent.' ' : ''; -warn $agentname; %> - <%= include('/elements/header.html', $agentname. 'Sales, Credits and Receipts Summary' ) @@ -36,6 +33,10 @@ warn $agentname; <% my @items = qw( invoiced netsales credits payments receipts ); +if ( $cgi->param('12mo') == 1 ) { + @items = map $_.'_12mo', @items; +} + my %label = ( 'invoiced' => 'Gross Sales', 'netsales' => 'Net Sales', @@ -43,6 +44,9 @@ my %label = ( 'payments' => 'Gross Receipts', 'receipts' => 'Net Receipts', ); +$label{$_.'_12mo'} = $label{$_}. " (previous 12 months)" + foreach keys %label; + my %color = ( 'invoiced' => '9999ff', #light blue 'netsales' => '0000cc', #blue @@ -50,11 +54,15 @@ my %color = ( 'payments' => '99cc99', #light green 'receipts' => '00cc00', #green ); +$color{$_.'_12mo'} = $color{$_} + foreach keys %color; + my %link = ( 'invoiced' => "${p}search/cust_bill.html?agentnum=$agentnum;", 'credits' => "${p}search/cust_credit.html?agentnum=$agentnum;", 'payments' => "${p}search/cust_pay.cgi?magic=_date;agentnum=$agentnum;", ); +# XXX link 12mo? my $report = new FS::Report::Table::Monthly ( 'items' => \@items, @@ -102,43 +110,4 @@ my @mon = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); <% } %> -
-
- -From - - to - - -for agent: <%= include('/elements/select-agent.html', $agentnum) %> - - -
- - +<%= include('/elements/footer.html') %> diff --git a/httemplate/graph/report_money_time.html b/httemplate/graph/report_money_time.html new file mode 100644 index 000000000..6c7e42716 --- /dev/null +++ b/httemplate/graph/report_money_time.html @@ -0,0 +1,71 @@ +<% + +#my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); +my ($curmon,$curyear) = (localtime(time))[4,5]; + +#find first month +my $syear = 1899+$curyear; +my $smonth = $curmon+1; + +#want 12 month by default, not 13 +$smonth++; +if ( $smonth > 12 ) { $smonth-=12; $syear++ } + +#find last month +my $eyear = 1900+$curyear; +my $emonth = $curmon+1; + +my @mon = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); + +%> +<%= include('/elements/header.html', 'Sales, Credits and Receipts Summary' ) %> + +
+ + + +From: + +
+ +To: + +
+ +For agent: <%= include('/elements/select-agent.html' ) %> +
+ + Show 12 month totals instead of monthly values. +
+ + +
+ +<%= include('/elements/footer.html') %> + diff --git a/httemplate/index.html b/httemplate/index.html index 6cd667d8a..4704ebe33 100644 --- a/httemplate/index.html +++ b/httemplate/index.html @@ -97,7 +97,7 @@ Payment report (by type and/or date range)

Credit report (by employee and/or date range) -

Sales, Credits and Receipts Summary +

Sales, Credits and Receipts Summary

Accounts Receivable Aging Summary

Prepaid Income (Unearned Revenue) Report

Sales Tax Liability Report -- cgit v1.2.1 From 0e2bb254c0e5018b6b2a7766962319cd4137683f Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 2 May 2006 15:03:00 +0000 Subject: add an agent pre-selection page to receivables report --- httemplate/index.html | 2 +- httemplate/search/report_receivables.html | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) create mode 100755 httemplate/search/report_receivables.html (limited to 'httemplate') diff --git a/httemplate/index.html b/httemplate/index.html index 4704ebe33..1a9293ecd 100644 --- a/httemplate/index.html +++ b/httemplate/index.html @@ -98,7 +98,7 @@ Payment report (by type and/or date range)

Credit report (by employee and/or date range)

Sales, Credits and Receipts Summary -

Accounts Receivable Aging Summary +

Accounts Receivable Aging Summary

Prepaid Income (Unearned Revenue) Report

Sales Tax Liability Report

diff --git a/httemplate/search/report_receivables.html b/httemplate/search/report_receivables.html new file mode 100755 index 000000000..fc5174116 --- /dev/null +++ b/httemplate/search/report_receivables.html @@ -0,0 +1,16 @@ +<%= include('/elements/header.html', 'Accounts Receivable Aging Summary' ) %> + +
+ + + + <%= include( '/elements/tr-select-agent.html' ) %> + +
+ +
+
+ + + + -- cgit v1.2.1 From 29644d5921c99520965b884b25800ed084891e94 Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 3 May 2006 09:47:31 +0000 Subject: pg 8.1 fix from Chris Cappuccio --- httemplate/search/report_receivables.cgi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'httemplate') diff --git a/httemplate/search/report_receivables.cgi b/httemplate/search/report_receivables.cgi index d675346f0..1dd0fee86 100755 --- a/httemplate/search/report_receivables.cgi +++ b/httemplate/search/report_receivables.cgi @@ -110,7 +110,7 @@ END $owed_cols =~ s/cust_bill\.custnum/cust_bill.custnum AND cust_main.agentnum = '$agentnum'/g; } - my $total_sql = "select $owed_cols"; + my $total_sql = "select $owed_cols from cust_main"; my $total_sth = dbh->prepare($total_sql) or die dbh->errstr; $total_sth->execute or die $total_sth->errstr; my $row = $total_sth->fetchrow_hashref(); -- cgit v1.2.1 From e65c6a26ca778166aec2b2d1dd3012ab84fa611a Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 7 May 2006 20:27:21 +0000 Subject: first pass at sales reports per agent and package class --- httemplate/docs/upgrade10.html | 2 +- httemplate/elements/select-month_year.html | 19 +++- httemplate/elements/select-pkg_class.html | 7 +- httemplate/elements/select-table.html | 11 +- httemplate/elements/tr-select-from_to.html | 51 +++++++++ httemplate/elements/tr-select-pkg_class.html | 15 +-- httemplate/graph/cust_bill_pkg-graph.cgi | 84 ++++++++++++++ httemplate/graph/cust_bill_pkg.cgi | 104 ++++++++++++++++++ httemplate/graph/elements/monthly.html | 157 +++++++++++++++++++++++++++ httemplate/graph/money_time-graph.cgi | 84 -------------- httemplate/graph/money_time.cgi | 97 ++++++----------- httemplate/graph/report_cust_bill_pkg.html | 29 +++++ httemplate/graph/report_money_time.html | 58 ++-------- 13 files changed, 500 insertions(+), 218 deletions(-) create mode 100644 httemplate/elements/tr-select-from_to.html create mode 100755 httemplate/graph/cust_bill_pkg-graph.cgi create mode 100644 httemplate/graph/cust_bill_pkg.cgi create mode 100644 httemplate/graph/elements/monthly.html delete mode 100755 httemplate/graph/money_time-graph.cgi create mode 100644 httemplate/graph/report_cust_bill_pkg.html (limited to 'httemplate') diff --git a/httemplate/docs/upgrade10.html b/httemplate/docs/upgrade10.html index 8d90ab7a2..7cd1d8e50 100644 --- a/httemplate/docs/upgrade10.html +++ b/httemplate/docs/upgrade10.html @@ -31,7 +31,7 @@ Perl or Linux.
  • 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 and Term::ReadKey +JSON, Term::ReadKey and Color::Scheme
  • Apply the following changes to your database: diff --git a/httemplate/elements/select-month_year.html b/httemplate/elements/select-month_year.html index a0ea74ddd..2866960bd 100644 --- a/httemplate/elements/select-month_year.html +++ b/httemplate/elements/select-month_year.html @@ -5,13 +5,22 @@ my $prefix = $opt{'prefix'} || ''; my $disabled = $opt{'disabled'} || ''; my $empty = $opt{'empty_option'} || ''; + my $start_year = $opt{'start_year'}; + my $end_year = $opt{'end_year'} || '2037'; + + my @mon; + if ( $opt{'show_month_abbr'} ) { + @mon = qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec); + } else { + @mon = ( 1 .. 12 ); + } + my $date = $opt{'selected_date'} || ''; $date = '' if $date eq '-'; #$date ||= '01-2000' unless $empty; - my $start_year = $opt{'start_year'}; - my $end_year = $opt{'end_year'} || '2037'; - my( $mon, $year ) = (0, 0); + my $mon = $opt{'selected_mon'} || 0; + my $year = $opt{'selected_year'} || 0; if ( $date ) { if ( $date =~ /^(\d{4})-(\d{1,2})-\d{1,2}$/ ) { #PostgreSQL date format ( $mon, $year ) = ( $2, $1 ); @@ -34,8 +43,8 @@ <%= $empty ? '
  • All invoice events for a date range
  • Invoice event errors for a date range (failed credit cards, processor or printer problems, etc.) - Payment report (by type and/or date range) + Sales, Credits and Receipts Summary +

    Sales report (by agent, package class and/or date range)

    Credit report (by employee and/or date range) -

    Sales, Credits and Receipts Summary +

    Payment report (by type and/or date range)

    Accounts Receivable Aging Summary

    Prepaid Income (Unearned Revenue) Report

    Sales Tax Liability Report diff --git a/httemplate/search/cust_bill_pkg.cgi b/httemplate/search/cust_bill_pkg.cgi index cc0f97536..4779071a4 100644 --- a/httemplate/search/cust_bill_pkg.cgi +++ b/httemplate/search/cust_bill_pkg.cgi @@ -12,15 +12,23 @@ my $join_pkg = " LEFT JOIN part_pkg USING ( pkgpart ) "; -my $where = " - WHERE _date >= $beginning AND _date <= $ending - AND payby != 'COMP' -"; +my $where = " WHERE _date >= $beginning AND _date <= $ending "; + +$where .= " AND payby != 'COMP' " + unless $cgi->param('include_comp_cust'); if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { $where .= " AND agentnum = $1 "; } +if ( $cgi->param('classnum') =~ /^(\d+)$/ ) { + if ( $1 == 0 ) { + $where .= " AND classnum IS NULL "; + } else { + $where .= " AND classnum = $1 "; + } +} + if ( $cgi->param('out') ) { $where .= " -- cgit v1.2.1 From c363307c1af959dce2ab4821ff5dfa697e3f0e19 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 8 May 2006 11:28:52 +0000 Subject: add config switch to base tax off shipping address if present --- httemplate/search/report_tax.cgi | 107 ++++++++++++++++++++++++++++++++------- 1 file changed, 89 insertions(+), 18 deletions(-) (limited to 'httemplate') diff --git a/httemplate/search/report_tax.cgi b/httemplate/search/report_tax.cgi index 0f33c4676..1b6f40b8a 100755 --- a/httemplate/search/report_tax.cgi +++ b/httemplate/search/report_tax.cgi @@ -19,14 +19,38 @@ my $join_pkg = " LEFT JOIN cust_pkg USING ( pkgnum ) LEFT JOIN part_pkg USING ( pkgpart ) "; -my $where = " - WHERE _date >= $beginning AND _date <= $ending - AND ( county = ? OR ? = '' ) - AND ( state = ? OR ? = '' ) - AND country = ? -"; -# AND payby != 'COMP' + +my $where = "WHERE _date >= $beginning AND _date <= $ending "; my @base_param = qw( county county state state country ); +if ( $conf->exists('tax-ship_address') ) { + + $where .= " + AND ( ( ( ship_last IS NULL OR ship_last = '' ) + AND ( county = ? OR ? = '' ) + AND ( state = ? OR ? = '' ) + AND country = ? + ) + OR ( ship_last IS NOT NULL AND ship_last != '' + AND ( ship_county = ? OR ? = '' ) + AND ( ship_state = ? OR ? = '' ) + AND ship_country = ? + ) + ) + "; + # AND payby != 'COMP' + + push @base_param, @base_param; + +} else { + + $where .= " + AND ( county = ? OR ? = '' ) + AND ( state = ? OR ? = '' ) + AND country = ? + "; + # AND payby != 'COMP' + +} my $agentname = ''; if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { @@ -38,16 +62,63 @@ if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { my $gotcust = " WHERE 0 < ( SELECT COUNT(*) FROM cust_main - WHERE ( cust_main.county = cust_main_county.county - OR cust_main_county.county = '' - OR cust_main_county.county IS NULL ) - AND ( cust_main.state = cust_main_county.state - OR cust_main_county.state = '' - OR cust_main_county.state IS NULL ) - AND ( cust_main.country = cust_main_county.country ) - LIMIT 1 - ) "; +if ( $conf->exists('tax-ship_address') ) { + + $gotcust .= " + WHERE + + ( cust_main_county.country = cust_main.country + OR cust_main_county.country = cust_main.ship_country + ) + + AND + + ( + + ( ( ship_last IS NULL OR ship_last = '' ) + AND ( cust_main_county.country = cust_main.country ) + AND ( cust_main_county.state = cust_main.state + OR cust_main_county.state = '' + OR cust_main_county.state IS NULL ) + AND ( cust_main_county.county = cust_main.county + OR cust_main_county.county = '' + OR cust_main_county.county IS NULL ) + ) + + OR + + ( ship_last IS NOT NULL AND ship_last != '' + AND ( cust_main_county.country = cust_main.ship_country ) + AND ( cust_main_county.state = cust_main.ship_state + OR cust_main_county.state = '' + OR cust_main_county.state IS NULL ) + AND ( cust_main_county.county = cust_main.ship_county + OR cust_main_county.county = '' + OR cust_main_county.county IS NULL ) + ) + + ) + + LIMIT 1 + ) + "; + +} else { + + $gotcust .= " + WHERE ( cust_main.county = cust_main_county.county + OR cust_main_county.county = '' + OR cust_main_county.county IS NULL ) + AND ( cust_main.state = cust_main_county.state + OR cust_main_county.state = '' + OR cust_main_county.state IS NULL ) + AND ( cust_main.country = cust_main_county.country ) + LIMIT 1 + ) + "; + +} my($total, $tot_taxable, $owed, $tax) = ( 0, 0, 0, 0, 0 ); my( $exempt_cust, $exempt_pkg, $exempt_monthly ) = ( 0, 0 ); @@ -190,8 +261,8 @@ foreach my $r ( my $label = getlabel($r); - my $fromwhere = $join_pkg. $where. " AND payby != 'COMP' "; - my @param = @base_param; + #my $fromwhere = $join_pkg. $where. " AND payby != 'COMP' "; + #my @param = @base_param; #match itemdesc if necessary! my $named_tax = -- cgit v1.2.1 From 3059dc3cfe6fa7280c40f64e598fc05f37ffa96f Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 12 May 2006 13:57:23 +0000 Subject: Pg 8.1 fix was incorrect and broke things, this should actually work --- httemplate/search/report_receivables.cgi | 113 +++++++++++++++---------------- 1 file changed, 53 insertions(+), 60 deletions(-) (limited to 'httemplate') diff --git a/httemplate/search/report_receivables.cgi b/httemplate/search/report_receivables.cgi index 1dd0fee86..ac94e1a5c 100755 --- a/httemplate/search/report_receivables.cgi +++ b/httemplate/search/report_receivables.cgi @@ -1,6 +1,38 @@ <% - my $charged = < extract(epoch from now()) - ". + ($end * 86400) + if $end; + + #handle 'cust' option + + push @where, "cust_main.custnum = cust_bill.custnum" + if $opt{'cust'}; + + #handle 'agentnum' option + my $join = ''; + if ( $opt{'agentnum'} ) { + $join = 'LEFT JOIN cust_main USING ( custnum )'; + push @where, "agentnum = '$opt{'agentnum'}'"; + } + + my $where = scalar(@where) ? 'WHERE '.join(' AND ', @where) : ''; + + my $as = $opt{'noas'} ? '' : "as owed_${start}_$end"; + + my $charged = < extract(epoch from now())-2592000 - and cust_main.custnum = cust_bill.custnum - ) - ,0 - ) as owed_0_30, - - coalesce( - ( select $charged from cust_bill - where cust_bill._date > extract(epoch from now())-5184000 - and cust_bill._date <= extract(epoch from now())-2592000 - and cust_main.custnum = cust_bill.custnum - ) - ,0 - ) as owed_30_60, - - coalesce( - ( select $charged from cust_bill - where cust_bill._date > extract(epoch from now())-7776000 - and cust_bill._date <= extract(epoch from now())-5184000 - and cust_main.custnum = cust_bill.custnum - ) - ,0 - ) as owed_60_90, + "coalesce( ( select $charged from cust_bill $join $where ) ,0 ) $as"; + + } - coalesce( - ( select $charged from cust_bill - where cust_bill._date <= extract(epoch from now())-7776000 - and cust_main.custnum = cust_bill.custnum - ) - ,0 - ) as owed_90_pl, + my @ranges = ( + [ 0, 30 ], + [ 30, 60 ], + [ 60, 90 ], + [ 90, 0 ], + [ 0, 0 ], + ); - coalesce( - ( select $charged from cust_bill - where cust_main.custnum = cust_bill.custnum - ) - ,0 - ) as owed_total -END + my $owed_cols = join(',', map owed( @$_, 'cust'=>1 ), @ranges ); my $recurring = <1, 'noas'=>1). " > 0"; my $agentnum = ''; if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { @@ -106,13 +101,11 @@ END 'extra_sql' => "$where order by coalesce(lower(company), ''), lower(last)", }; - if ( $agentnum ) { - $owed_cols =~ - s/cust_bill\.custnum/cust_bill.custnum AND cust_main.agentnum = '$agentnum'/g; - } - my $total_sql = "select $owed_cols from cust_main"; + my $total_sql = "select ". + join(',', map owed( @$_, 'agentnum'=>$agentnum ), @ranges ); + my $total_sth = dbh->prepare($total_sql) or die dbh->errstr; - $total_sth->execute or die $total_sth->errstr; + $total_sth->execute or die "error executing $total_sql: ". $total_sth->errstr; my $row = $total_sth->fetchrow_hashref(); my $conf = new FS::Conf; @@ -154,9 +147,9 @@ END sprintf( $money_char.'%.2f', $row->{'owed_60_90'} ), sprintf( $money_char.'%.2f', - $row->{'owed_90_pl'} ), + $row->{'owed_90_0'} ), sprintf( ''. $money_char.'%.2f'. '', - $row->{'owed_total'} ), + $row->{'owed_0_0'} ), ], 'fields' => [ \&FS::UI::Web::cust_fields, @@ -182,9 +175,9 @@ END sub { sprintf( $money_char.'%.2f', shift->get('owed_60_90') ) }, sub { sprintf( $money_char.'%.2f', - shift->get('owed_90_pl') ) }, + shift->get('owed_90_0') ) }, sub { sprintf( $money_char.'%.2f', - shift->get('owed_total') ) }, + shift->get('owed_0_0') ) }, ], 'links' => [ ( map $clink, FS::UI::Web::cust_header() ), -- cgit v1.2.1 From 20d1889a5fcecf66b720500326726ab266c7b712 Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 13 May 2006 15:31:58 +0000 Subject: adding new images --- httemplate/images/32clear.gif | Bin 0 -> 815 bytes httemplate/images/arrow.down.png | Bin 0 -> 170 bytes httemplate/images/arrow.right.black.png | Bin 0 -> 160 bytes httemplate/images/arrow.right.png | Bin 0 -> 160 bytes httemplate/images/black-gradient.png | Bin 0 -> 397 bytes httemplate/images/black-gray-corner.png | Bin 0 -> 460 bytes httemplate/images/black-gray-gradient.png | Bin 0 -> 384 bytes httemplate/images/black-gray-side.png | Bin 0 -> 198 bytes httemplate/images/black-gray-top.png | Bin 0 -> 203 bytes 9 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 httemplate/images/32clear.gif create mode 100644 httemplate/images/arrow.down.png create mode 100644 httemplate/images/arrow.right.black.png create mode 100644 httemplate/images/arrow.right.png create mode 100644 httemplate/images/black-gradient.png create mode 100644 httemplate/images/black-gray-corner.png create mode 100644 httemplate/images/black-gray-gradient.png create mode 100644 httemplate/images/black-gray-side.png create mode 100644 httemplate/images/black-gray-top.png (limited to 'httemplate') diff --git a/httemplate/images/32clear.gif b/httemplate/images/32clear.gif new file mode 100644 index 000000000..5fdcea204 Binary files /dev/null and b/httemplate/images/32clear.gif differ diff --git a/httemplate/images/arrow.down.png b/httemplate/images/arrow.down.png new file mode 100644 index 000000000..675d84bde Binary files /dev/null and b/httemplate/images/arrow.down.png differ diff --git a/httemplate/images/arrow.right.black.png b/httemplate/images/arrow.right.black.png new file mode 100644 index 000000000..933c25894 Binary files /dev/null and b/httemplate/images/arrow.right.black.png differ diff --git a/httemplate/images/arrow.right.png b/httemplate/images/arrow.right.png new file mode 100644 index 000000000..60bcb76ab Binary files /dev/null and b/httemplate/images/arrow.right.png differ diff --git a/httemplate/images/black-gradient.png b/httemplate/images/black-gradient.png new file mode 100644 index 000000000..225732d16 Binary files /dev/null and b/httemplate/images/black-gradient.png differ diff --git a/httemplate/images/black-gray-corner.png b/httemplate/images/black-gray-corner.png new file mode 100644 index 000000000..17954cdd7 Binary files /dev/null and b/httemplate/images/black-gray-corner.png differ diff --git a/httemplate/images/black-gray-gradient.png b/httemplate/images/black-gray-gradient.png new file mode 100644 index 000000000..f5c318fe7 Binary files /dev/null and b/httemplate/images/black-gray-gradient.png differ diff --git a/httemplate/images/black-gray-side.png b/httemplate/images/black-gray-side.png new file mode 100644 index 000000000..f7a98a43d Binary files /dev/null and b/httemplate/images/black-gray-side.png differ diff --git a/httemplate/images/black-gray-top.png b/httemplate/images/black-gray-top.png new file mode 100644 index 000000000..ed0707573 Binary files /dev/null and b/httemplate/images/black-gray-top.png differ -- cgit v1.2.1 From c46235292c6bf929615ac28fc48c1d5609ce4590 Mon Sep 17 00:00:00 2001 From: ivan Date: Sat, 13 May 2006 18:34:39 +0000 Subject: yay for cheating --- httemplate/images/background-cheat.png | Bin 0 -> 338 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 httemplate/images/background-cheat.png (limited to 'httemplate') diff --git a/httemplate/images/background-cheat.png b/httemplate/images/background-cheat.png new file mode 100644 index 000000000..ad332f675 Binary files /dev/null and b/httemplate/images/background-cheat.png differ -- cgit v1.2.1 From 2c757d7db4cb6a7b9655de13206fcc84fb7ce61f Mon Sep 17 00:00:00 2001 From: ivan Date: Sun, 14 May 2006 16:47:31 +0000 Subject: first part of ACL and re-skinning work and some other small stuff --- httemplate/autohandler | 10 +- httemplate/browse/access_group.html | 33 ++ httemplate/browse/access_user.html | 63 +++ httemplate/browse/agent_type.cgi | 108 ++-- httemplate/browse/cust_main_county.cgi | 185 +++---- httemplate/browse/msgcat.cgi | 20 +- httemplate/browse/part_pkg.cgi | 14 +- httemplate/edit/access_group.html | 10 + httemplate/edit/access_user.html | 37 ++ httemplate/edit/agent_type.cgi | 52 +- httemplate/edit/cust_bill_pay.cgi | 87 ++- httemplate/edit/cust_credit.cgi | 71 ++- httemplate/edit/cust_credit_bill.cgi | 90 ++-- httemplate/edit/cust_main.cgi | 105 ++-- httemplate/edit/cust_pkg.cgi | 136 +++-- httemplate/edit/elements/edit.html | 36 +- httemplate/edit/part_referral.cgi | 36 +- httemplate/edit/part_virtual_field.cgi | 19 +- httemplate/edit/process/access_group.html | 5 + httemplate/edit/process/access_user.html | 8 + httemplate/edit/process/agent_type.cgi | 39 +- httemplate/edit/process/cust_bill_pay.cgi | 16 +- httemplate/edit/process/cust_credit.cgi | 17 +- httemplate/edit/process/cust_credit_bill.cgi | 16 +- httemplate/edit/process/elements/process.html | 19 +- httemplate/edit/svc_domain.cgi | 55 +- httemplate/elements/checkboxes-table.html | 110 ++++ httemplate/elements/cssexpr.js | 66 +++ httemplate/elements/footer.html | 3 + httemplate/elements/header.html | 289 +++++++++- httemplate/elements/menubar.html | 1 + httemplate/elements/select-access_group.html | 15 + httemplate/elements/tr-select-access_group.html | 22 + httemplate/elements/xmenu.css | 185 +++++++ httemplate/elements/xmenu.js | 668 ++++++++++++++++++++++++ httemplate/index.html | 12 +- httemplate/misc/batch-cust_pay.html | 2 - httemplate/misc/payment.cgi | 38 +- httemplate/search/cust_bill.cgi | 165 ------ httemplate/search/cust_main-otaker.cgi | 47 +- httemplate/search/cust_main-payinfo.html | 20 - httemplate/search/cust_main-quickpay.html | 44 -- httemplate/search/cust_main.cgi | 50 +- httemplate/search/cust_pay.html | 18 - httemplate/search/cust_pkg_report.cgi | 39 +- httemplate/search/report_cust_bill.html | 54 +- httemplate/search/report_cust_credit.html | 62 +-- httemplate/search/report_cust_pay.html | 81 +-- httemplate/search/report_prepaid_income.html | 26 +- httemplate/search/report_tax.html | 73 ++- httemplate/search/sqlradius.html | 52 +- httemplate/search/svc_acct.html | 19 - httemplate/search/svc_domain.cgi | 2 +- httemplate/search/svc_domain.html | 19 - httemplate/search/svc_external.cgi | 21 +- httemplate/view/cust_main/packages.html | 4 +- httemplate/view/cust_main/payment_history.html | 26 +- 57 files changed, 2380 insertions(+), 1140 deletions(-) create mode 100644 httemplate/browse/access_group.html create mode 100644 httemplate/browse/access_user.html create mode 100644 httemplate/edit/access_group.html create mode 100644 httemplate/edit/access_user.html create mode 100644 httemplate/edit/process/access_group.html create mode 100644 httemplate/edit/process/access_user.html create mode 100644 httemplate/elements/checkboxes-table.html create mode 100644 httemplate/elements/cssexpr.js create mode 100644 httemplate/elements/select-access_group.html create mode 100644 httemplate/elements/tr-select-access_group.html create mode 100644 httemplate/elements/xmenu.css create mode 100644 httemplate/elements/xmenu.js delete mode 100755 httemplate/search/cust_bill.cgi delete mode 100755 httemplate/search/cust_main-payinfo.html delete mode 100755 httemplate/search/cust_main-quickpay.html delete mode 100755 httemplate/search/cust_pay.html delete mode 100755 httemplate/search/svc_acct.html delete mode 100755 httemplate/search/svc_domain.html (limited to 'httemplate') diff --git a/httemplate/autohandler b/httemplate/autohandler index a3f7eb008..ad0ab8ba6 100644 --- a/httemplate/autohandler +++ b/httemplate/autohandler @@ -9,7 +9,15 @@ if ( UNIVERSAL::can(dbh, 'sprintProfile') ) { if ( lc($r->content_type) eq 'text/html' ) { - $profile = '
    '. encode_entities(dbh->sprintProfile()).
    +    # 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 );
    +
    +    $profile = '
    '.
    +               encode_entities( $wrapper->wrap( dbh->sprintProfile() ) ).
                    #"\n\n". &sprintAutoProfile(). '
    '; "\n\n". '
    '; } diff --git a/httemplate/browse/access_group.html b/httemplate/browse/access_group.html new file mode 100644 index 000000000..6ba89ea81 --- /dev/null +++ b/httemplate/browse/access_group.html @@ -0,0 +1,33 @@ +<% + +my $html_init = + "Internal access groups control access to the back-office interface.

    ". + qq!Add an internal access group

    !; + +my $count_query = 'SELECT COUNT(*) FROM access_group'; + +my $link = [ $p.'edit/access_group.html?', 'groupnum' ]; + +%><%= include( 'elements/browse.html', + 'title' => 'Internal Access Groups', + 'menubar' => [ # 'Main menu' => $p, + 'Internal users' => $p.'browse/access_user.html', + ], + 'html_init' => $html_init, + 'name' => 'internal access groups', + 'query' => { 'table' => 'access_group', + 'hashref' => {}, + 'extra_sql' => 'ORDER BY groupname', #?? + }, + 'count_query' => $count_query, + 'header' => [ '#', + 'Group name', + ], + 'fields' => [ 'groupnum', + 'groupname', + ], + 'links' => [ $link, + $link, + ], + ) +%> diff --git a/httemplate/browse/access_user.html b/httemplate/browse/access_user.html new file mode 100644 index 000000000..38d5430b1 --- /dev/null +++ b/httemplate/browse/access_user.html @@ -0,0 +1,63 @@ +<% + +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 highly recommended to add a separate account for each person rather than using role accounts.

    ". + qq!Add an internal user

    !; + +#false laziness w/agent_type.cgi +my $groups_sub = sub { + my $access_user = shift; + + [ map { + my $access_usergroup = $_; + my $access_group = $access_usergroup->access_group; + [ + { + 'data' => $access_group->groupname, + 'align' => 'left', + 'link' => + $p. 'edit/access_group.html?'. $access_usergroup->groupnum, + }, + ]; + } + grep { $_->access_group # and ! $_->access_group->disabled + } + $access_user->access_usergroup, + + ]; + +}; + +my $count_query = 'SELECT COUNT(*) FROM access_user'; + +my $link = [ $p.'edit/access_user.html?', 'usernum' ]; + +%><%= 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, + '' + ], + ) +%> diff --git a/httemplate/browse/agent_type.cgi b/httemplate/browse/agent_type.cgi index 2e1bdad42..a5ffb1048 100755 --- a/httemplate/browse/agent_type.cgi +++ b/httemplate/browse/agent_type.cgi @@ -1,60 +1,62 @@ - -<%= include("/elements/header.html","Agent Type Listing", menubar( - 'Main Menu' => $p, - 'Agents' => $p. 'browse/agent.cgi', -)) %> -Agent types define groups of packages that you can then assign to particular -agents.

    -Add a new agent type

    +<% -<%= table() %> - - Agent Type - Packages - +my $html_init = + 'Agent types define groups of packages that you can then assign to'. + ' particular agents.

    '. + qq!Add a new agent type

    !; -<% -foreach my $agent_type ( sort { - $a->getfield('typenum') <=> $b->getfield('typenum') -} qsearch('agent_type',{}) ) { - my $hashref = $agent_type->hashref; - #more efficient to do this with SQL... - my @type_pkgs = grep { $_->part_pkg and ! $_->part_pkg->disabled } - qsearch('type_pkgs',{'typenum'=> $hashref->{typenum} }); - my $rowspan = scalar(@type_pkgs); - $rowspan = int($rowspan/2+0.5) ; - print < - - $hashref->{typenum} - - $hashref->{atype} -END +my $count_query = 'SELECT COUNT(*) FROM agent_type'; - my($type_pkgs); - my($tdcount) = -1 ; - foreach $type_pkgs ( @type_pkgs ) { - my($pkgpart)=$type_pkgs->getfield('pkgpart'); - my($part_pkg) = qsearchs('part_pkg',{'pkgpart'=> $pkgpart }); - print qq!! if ($tdcount == 0) ; - $tdcount = 0 if ($tdcount == -1) ; - print qq!!, - $part_pkg->getfield('pkg'),""; - $tdcount ++ ; - if ($tdcount == 2) - { - print qq!\n! ; - $tdcount = 0 ; - } - } +#false laziness w/access_user.html +my $packages_sub = sub { + my $agent_type = shift; - print ""; -} + [ map { + my $type_pkgs = $_; + my $part_pkg = $type_pkgs->part_pkg; + [ + { + 'data' => $part_pkg->pkg. ' - '. $part_pkg->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 + ]; -print < - - -END +}; +my $link = [ $p.'edit/agent_type.cgi?', 'typenum' ]; + +%><%= include( 'elements/browse.html', + 'title' => 'Agent Types', + 'menubar' => [ #'Main menu' => $p, + 'Agents' =>"${p}browse/agent.cgi", + ], + 'html_init' => $html_init, + 'name' => 'agent types', + 'query' => { 'table' => 'agent_type', + 'hashref' => {}, + 'extra_sql' => 'ORDER BY typenum', # 'ORDER BY atype', + }, + 'count_query' => $count_query, + 'header' => [ '#', + 'Agent Type', + 'Packages', + ], + 'fields' => [ 'typenum', + 'atype', + $packages_sub, + ], + 'links' => [ $link, + $link, + '', + ], + ) %> diff --git a/httemplate/browse/cust_main_county.cgi b/httemplate/browse/cust_main_county.cgi index 1e0e0880c..9e3feb8f3 100755 --- a/httemplate/browse/cust_main_county.cgi +++ b/httemplate/browse/cust_main_county.cgi @@ -1,33 +1,34 @@ - -<% +<%= include('/elements/header.html', "Tax Rate Listing", menubar( + 'Edit tax rates' => $p. "edit/cust_main_county.cgi", +)) %> + + Click on expand country to specify a country's tax rates by state. +
    Click on expand state to specify a state's tax rates by county. +<% my $conf = new FS::Conf; my $enable_taxclasses = $conf->exists('enable_taxclasses'); -print header("Tax Rate Listing", menubar( - 'Main Menu' => $p, - 'Edit tax rates' => $p. "edit/cust_main_county.cgi", -)),<expand country to specify a country's tax rates by state. -
    Click on expand state to specify a state's tax rates by county. -END +if ( $enable_taxclasses ) { %> -if ( $enable_taxclasses ) { - print '
    Click on expand taxclasses to specify tax classes'; -} +
    Click on expand taxclasses to specify tax classes -print '

    '. &table(). < - Country - State - County - Taxclass
    (per-package classification) - Tax name
    (printed on invoices) - Tax - Exemption - -END +<% } %> + +

    +<%= table() %> + + + Country + State + County + Taxclass
    (per-package classification) + Tax name
    (printed on invoices) + Tax + Exemption + +<% my @regions = sort { $a->country cmp $b->country or $a->state cmp $b->state or $a->county cmp $b->county @@ -39,10 +40,12 @@ my $sup=0; for ( my $i=0; $i<@regions; $i++ ) { my $cust_main_county = $regions[$i]; my $hashref = $cust_main_county->hashref; - print < - $hashref->{country} -END + <%= $hashref->{country} %> + + <% my $j; if ( $sup ) { @@ -74,69 +77,73 @@ END $j = 1; } - print "{state} + %> + + <%= + $hashref->{state} ? ' BGCOLOR="#ffffff">'. $hashref->{state} : qq! BGCOLOR="#cccccc">(ALL) !. qq!expand country!; - - print qq! collapse state! if $j>1; - - print ""; - } - -# $sup=$newsup; - - print "{county} ) { - print ' BGCOLOR="#ffffff">'. $hashref->{county}; - } else { - print ' BGCOLOR="#cccccc">(ALL)'; - if ( $hashref->{state} ) { - print qq!!. - qq!expand state!; - } - } - print ""; - - print "{taxclass} ) { - print ' BGCOLOR="#ffffff">'. $hashref->{taxclass}; - } else { - print ' BGCOLOR="#cccccc">(ALL)'; - if ( $enable_taxclasses ) { - print qq!!. - qq!expand taxclasses!; - } - - } - print ""; - - print "{taxname} ) { - print ' BGCOLOR="#ffffff">'. $hashref->{taxname}; - } else { - print ' BGCOLOR="#cccccc">Tax'; - } - print ""; - - print "$hashref->{tax}%". - ''; - print '$'. sprintf("%.2f", $hashref->{exempt_amount} ). - ' per month
    ' - if $hashref->{exempt_amount} > 0; - print 'Setup fee
    ' if $hashref->{setuptax} =~ /^Y$/i; - print 'Recurring fee
    ' if $hashref->{recurtax} =~ /^Y$/i; - print ''; - -} - -print < - - -END - -%> + qq!">expand country
    ! + %> + <% if ( $j>1 ) { %> + collapse state + <% } %> + + + <% } %> + +<% # $sup=$newsup; %> + + {county} ) { + %> BGCOLOR="#ffffff"><%= $hashref->{county} %> + <% } else { + %> BGCOLOR="#cccccc">(ALL) + <% if ( $hashref->{state} ) { %> + expand state + <% } %> + <% } %> + + + {taxclass} ) { + %> BGCOLOR="#ffffff"><%= $hashref->{taxclass} %> + <% } else { + %> BGCOLOR="#cccccc">(ALL) + <% if ( $enable_taxclasses ) { %> + expand taxclasses + <% } %> + <% } %> + + + {taxname} ) { + %> BGCOLOR="#ffffff"><%= $hashref->{taxname} %> + <% } else { + %> BGCOLOR="#cccccc">Tax + <% } %> + + + <%= $hashref->{tax} %>% + + + + <% if ( $hashref->{exempt_amount} > 0 ) { %> + $<%= sprintf("%.2f", $hashref->{exempt_amount} ) %> per month
    + <% } %> + + <% if ( $hashref->{setuptax} =~ /^Y$/i ) { %> + Setup fee
    + <% } %> + + <% if ( $hashref->{recurtax} =~ /^Y$/i ) { %> + Recurring fee
    + <% } %> + + + + + +<% } %> + + + +<%= include('/elements/footer.html') %> diff --git a/httemplate/browse/msgcat.cgi b/httemplate/browse/msgcat.cgi index d4adf9f1a..318ebfdff 100755 --- a/httemplate/browse/msgcat.cgi +++ b/httemplate/browse/msgcat.cgi @@ -1,10 +1,6 @@ - -<% - -print header("View Message catalog", menubar( - 'Main Menu' => $p, +<%= include('/elements/header.html', "View Message catalog", menubar( 'Edit message catalog' => $p. "edit/msgcat.cgi", -)), '
    '; +)) %><% my $widget = new HTML::Widgets::SelectLayers( 'selected_layer' => 'en_US', @@ -38,13 +34,7 @@ my $widget = new HTML::Widgets::SelectLayers( }, ); - -print $widget->html; - -print < - - -END - %> + +<%= $widget->html %> +<%= include('/elements/footer.html') %> diff --git a/httemplate/browse/part_pkg.cgi b/httemplate/browse/part_pkg.cgi index 0afa54750..41d86358c 100755 --- a/httemplate/browse/part_pkg.cgi +++ b/httemplate/browse/part_pkg.cgi @@ -11,8 +11,8 @@ my $select = '*'; my $orderby = 'pkgpart'; if ( $cgi->param('active') ) { - $orderby = 'num_active'; - + $orderby = 'num_active DESC'; +} $select = " *, @@ -33,13 +33,13 @@ if ( $cgi->param('active') ) { "; -} +#} my $conf = new FS::Conf; my $taxclasses = $conf->exists('enable_taxclasses'); my $html_init; -unless ( $cgi->param('active') ) { +#unless ( $cgi->param('active') ) { $html_init = qq! One or more service definitions are grouped together into a package definition and given pricing information. Customers purchase packages @@ -47,7 +47,7 @@ unless ( $cgi->param('active') ) { Add a new package definition

    !; -} +#} my $posttotal; if ( $cgi->param('showdisabled') ) { @@ -85,7 +85,7 @@ unless ( 0 ) { #already showing only one class or something? $align .= 'l'; } -if ( $cgi->param('active') ) { +#if ( $cgi->param('active') ) { push @header, 'Customer
    packages'; my %col = ( 'active' => '00CC00', @@ -117,7 +117,7 @@ if ( $cgi->param('active') ) { } (qw( active suspended cancelled )) ]; }; $align .= 'r'; -} +#} push @header, 'Frequency'; push @fields, sub { shift->freq_pretty; }; diff --git a/httemplate/edit/access_group.html b/httemplate/edit/access_group.html new file mode 100644 index 000000000..11b8df7bc --- /dev/null +++ b/httemplate/edit/access_group.html @@ -0,0 +1,10 @@ +<%= include( 'elements/edit.html', + 'name' => 'Internal Access Group', + 'table' => 'access_group', + 'labels' => { + 'groupnum' => 'Group number', + 'groupname' => 'Group name', + }, + 'viewall_dir' => 'browse', + ) +%> diff --git a/httemplate/edit/access_user.html b/httemplate/edit/access_user.html new file mode 100644 index 000000000..2b19dbf7b --- /dev/null +++ b/httemplate/edit/access_user.html @@ -0,0 +1,37 @@ +<%= include( 'elements/edit.html', + 'name' => 'Internal User', + 'table' => 'access_user', + 'fields' => [ + 'username', + { field=>'_password', type=>'password' }, + 'last', + 'first', + ], + 'labels' => { + 'usernum' => 'User number', + 'username' => 'Username', + '_password' => 'Password', + 'last' => 'Last name', + 'first' => 'First name', + }, + 'viewall_dir' => 'browse', + 'html_bottom' => + sub { + my $access_user = shift; + + '
    Internal Access Groups
    '. + ntable("#cccccc",2). + ''. + include( '/elements/checkboxes-table.html', + 'source_obj' => $access_user, + 'link_table' => 'access_usergroup', + 'target_table' => 'access_group', + 'name_col' => 'groupname', + 'target_link' => $p.'edit/access_group.html?', + #'disable-able' => 1, + ). + '' + ; + }, + ) +%> diff --git a/httemplate/edit/agent_type.cgi b/httemplate/edit/agent_type.cgi index 944ddd0d0..f5afd3a96 100755 --- a/httemplate/edit/agent_type.cgi +++ b/httemplate/edit/agent_type.cgi @@ -14,9 +14,7 @@ if ( $cgi->param('error') ) { } my $action = $agent_type->typenum ? 'Edit' : 'Add'; -%> - -<%= include("/elements/header.html","$action Agent Type", menubar( +%><%= include("/elements/header.html","$action Agent Type", menubar( 'Main Menu' => "$p", 'View all agent types' => "${p}browse/agent_type.cgi", )) @@ -29,47 +27,29 @@ my $action = $agent_type->typenum ? 'Edit' : 'Add';
    Agent Type #<%= $agent_type->typenum || "(NEW)" %> -

    +
    Agent Type

    Select which packages agents of this type may sell to customers
    - -<% foreach my $part_pkg ( - qsearch({ 'table' => 'part_pkg', - 'hashref' => { 'disabled' => '' }, - 'select' => 'part_pkg.*', - 'addl_from' => 'LEFT JOIN type_pkgs USING ( pkgpart )', - 'extra_sql' => ( $agent_type->typenum - ? 'OR typenum = '. $agent_type->typenum - : '' - ), - }) - ) { +<%= ntable("#cccccc", 2) %> +<%= include('/elements/checkboxes-table.html', + 'source_obj' => $agent_type, + 'link_table' => 'type_pkgs', + 'target_table' => 'part_pkg', + 'name_callback' => sub { $_[0]->pkg. ' - '. $_[0]->comment; }, + 'target_link' => $p.'edit/part_pkg.cgi?', + 'disable-able' => 1, + + ) %> - -
    - $agent_type->typenum, - 'pkgpart' => $part_pkg->pkgpart, - }) - ? 'CHECKED ' - : '' - %> VALUE="ON"> - - <%= $part_pkg->pkgpart %>: - <%= $part_pkg->pkg %> - <%= $part_pkg->comment %> - <%= $part_pkg->disabled =~ /^Y/i ? ' (DISABLED)' : '' %> - -<% } %> - -

    + +
    ">
    - - + +<%= include('/elements/footer.html') %> diff --git a/httemplate/edit/cust_bill_pay.cgi b/httemplate/edit/cust_bill_pay.cgi index 24bce308a..9d3bdd8cb 100755 --- a/httemplate/edit/cust_bill_pay.cgi +++ b/httemplate/edit/cust_bill_pay.cgi @@ -1,4 +1,3 @@ - <% my($paynum, $amount, $invnum); @@ -18,78 +17,76 @@ my $otaker = getotaker; my $p1 = popurl(1); -print header("Apply Payment", ''); -print qq!Error: !, $cgi->param('error'), - "

    " - if $cgi->param('error'); -print < -END +%><%= header("Apply Payment", '') %> +<% if ( $cgi->param('error') ) { %> + Error: <%= $cgi->param('error') %> +

    +<% } %> + +
    + +<% my $cust_pay = qsearchs('cust_pay', { 'paynum' => $paynum } ); die "payment $paynum not found!" unless $cust_pay; my $unapplied = $cust_pay->unapplied; +%> + +Payment #<%= $paynum %> + -print "Payment # $paynum". - qq!!. - '
    Date: '. time2str("%D", $cust_pay->_date). ''. - '
    Amount: $'. $cust_pay->paid. ''. - "
    Unapplied amount: \$$unapplied" - ; +
    Date: <%= time2str("%D", $cust_pay->_date) %> +
    Amount: $<%= $cust_pay->paid %> + +
    Unapplied amount: $<%= $unapplied %> + +<% my @cust_bill = grep $_->owed != 0, qsearch('cust_bill', { 'custnum' => $cust_pay->custnum } ); -print < + -END - -print qq!
    Invoice #"; -print qq!
    Amount \$!; +
    Invoice # + +
    Amount $ -print < - -END +
    -print < - - + -END - -%> diff --git a/httemplate/edit/cust_credit.cgi b/httemplate/edit/cust_credit.cgi index aae0df2fc..946b1087b 100755 --- a/httemplate/edit/cust_credit.cgi +++ b/httemplate/edit/cust_credit.cgi @@ -1,4 +1,3 @@ - <% my $conf = new FS::Conf; @@ -25,39 +24,57 @@ my $otaker = getotaker; my $p1 = popurl(1); -print header("Post Credit", ''); -print qq!Error: !, $cgi->param('error'), - "" - if $cgi->param('error'); -print <config('countrydefault')); -
    - - - - - - -END - -print '

    Credit'. ntable("#cccccc", 2). - 'Date'. - time2str("%D",$_date). ''; - -print qq!Amount\$!; +%> + +<%= header("Post Credit", '') %> + +<% if ( $cgi->param('error') ) { %> + Error: <%= $cgi->param('error') %> +

    +<% } %> + + + + + + + + + + + +Credit + +<%= ntable("#cccccc", 2) %> + + Date + <%= time2str("%D",$_date) %> + + + + Amount + $ + + +<% #print qq! Also post refund!; +%> -print qq!Reason!; + + Reason + + -print qq!Auto-apply
    to invoices!; + + Auto-apply
    to invoices + + -print < +
    - +
    -END - -%> diff --git a/httemplate/edit/cust_credit_bill.cgi b/httemplate/edit/cust_credit_bill.cgi index 1a97e1312..409ea3c25 100755 --- a/httemplate/edit/cust_credit_bill.cgi +++ b/httemplate/edit/cust_credit_bill.cgi @@ -1,4 +1,3 @@ - <% my($crednum, $amount, $invnum); @@ -23,79 +22,78 @@ my $otaker = getotaker; my $p1 = popurl(1); -print header("Apply Credit", ''); -print qq!Error: !, $cgi->param('error'), - "

    " - if $cgi->param('error'); -print < -END +%><%= header("Apply Credit", '') %> +<% if ( $cgi->param('error') ) { %> + Error: <%= $cgi->param('error') %> +

    +<% } %> + +
    + +<% my $cust_credit = qsearchs('cust_credit', { 'crednum' => $crednum } ); die "credit $crednum not found!" unless $cust_credit; my $credited = $cust_credit->credited; +%> + +Credit #<%= $crednum %> + + +
    Date: <%= time2str("%D", $cust_credit->_date) %> -print "Credit # $crednum". - qq!!. - '
    Date: '. time2str("%D", $cust_credit->_date). ''. - '
    Amount: $'. $cust_credit->amount. ''. - "
    Unapplied amount: \$$credited". - '
    Reason: '. $cust_credit->reason. '' - ; +
    Amount: $<%= $cust_credit->amount %> +
    Unapplied amount: $<%= $credited %> + +
    Reason: <%= $cust_credit->reason %> + +<% my @cust_bill = grep $_->owed != 0, qsearch('cust_bill', { 'custnum' => $cust_credit->custnum } ); -print < + -END - -print qq!
    Invoice #"; -print qq!
    Amount \$!; +
    Invoice # + +
    Amount $ -print < - -END +
    -print < - - + -END - -%> diff --git a/httemplate/edit/cust_main.cgi b/httemplate/edit/cust_main.cgi index 80fec9359..bb2a8618e 100755 --- a/httemplate/edit/cust_main.cgi +++ b/httemplate/edit/cust_main.cgi @@ -397,49 +397,66 @@ unless ( $custnum ) { if ( @part_pkg ) { -# print "

    First package", &itable("#cccccc", "0 ALIGN=LEFT"), -#apiabuse & undesirable wrapping - print "
    First package", &ntable("#cccccc"), - qq!"; - - #false laziness: (mostly) copied from edit/svc_acct.cgi - #$ulen = $svc_acct->dbdef_table->column('username')->length; - my $ulen = dbdef->table('svc_acct')->column('username')->length; - my $ulen2 = $ulen+2; - my $passwordmax = $conf->config('passwordmax') || 8; - my $pmax2 = $passwordmax + 2; - print <Username - -Password - -(blank to generate) -END - - print 'Access number' - . - &FS::svc_acct_pop::popselector($popnum). - '' - ; - } -} + # print "

    First package", &itable("#cccccc", "0 ALIGN=LEFT"), + #apiabuse & undesirable wrapping + + %> +
    First package + <%= ntable("#cccccc") %> + + + + + + + + <% + #false laziness: (mostly) copied from edit/svc_acct.cgi + #$ulen = $svc_acct->dbdef_table->column('username')->length; + my $ulen = dbdef->table('svc_acct')->column('username')->length; + my $ulen2 = $ulen+2; + my $passwordmax = $conf->config('passwordmax') || 8; + my $pmax2 = $passwordmax + 2; + %> + + + Username + + MAXLENGTH=<%= $ulen %>> + + + + + Password + + MAXLENGTH=<%= $passwordmax %>> + (blank to generate) + + + + + Access number + <%= FS::svc_acct_pop::popselector($popnum) %> + + + + <% } %> + +<% } %> -my $otaker = $cust_main->otaker; -print qq!!, - qq!

    !, - "", -; + +
    +"> +
    + + +<%= include('/elements/footer.html') %> -%> diff --git a/httemplate/edit/cust_pkg.cgi b/httemplate/edit/cust_pkg.cgi index ce1c86612..174d4dde1 100755 --- a/httemplate/edit/cust_pkg.cgi +++ b/httemplate/edit/cust_pkg.cgi @@ -1,4 +1,3 @@ - <% my %pkg = (); @@ -29,48 +28,62 @@ if ( $cgi->param('error') ) { } my $p1 = popurl(1); -print header("Add/Edit Packages", ''); -print qq!Error: !, $cgi->param('error'), - "" - if $cgi->param('error'); +%><%= include('/elements/header.html', "Add/Edit Packages", '') %> -print qq!
    !; +<% if ( $cgi->param('error') ) { %> + Error: <%= $cgi->param('error') %> +<% } %> -print qq!!; + + + +<% #current packages -my @cust_pkg = qsearch('cust_pkg',{ 'custnum' => $custnum, 'cancel' => '' } ); +my @cust_pkg = qsearch('cust_pkg', { 'custnum' => $custnum, 'cancel' => '' } ); if (@cust_pkg) { - print < - - Pkg # - Package description - -

    -END +%> + + Current packages - select to remove (services are moved to a new package below) + + + + + +

    - foreach (sort { $all_pkg{$a->getfield('pkgpart')} cmp $all_pkg{$b->getfield('pkgpart')} } @cust_pkg) { + <% + + foreach ( sort { $all_pkg{ $a->getfield('pkgpart') } + cmp $all_pkg{ $b->getfield('pkgpart') } + } + @cust_pkg + ) + { my($pkgnum,$pkgpart)=( $_->getfield('pkgnum'), $_->getfield('pkgpart') ); my $checked = $remove_pkg{$pkgnum} ? ' CHECKED' : ''; - print < - - \n - - -END - } - print qq!
    Pkg #Package description
    $pkgnum:$all_pkg{$pkgpart} - $all_comment{$pkgpart}


    !; -} -print <
    -END + %> + + + > + <%= $pkgnum %>: + <%= $all_pkg{$pkgpart} %> - <%= $all_comment{$pkgpart} %> + + + <% } %> + + +

    +<% } %> + +Order new packages +

    + +<% my $cust_main = qsearchs('cust_main',{'custnum'=>$custnum}); my $agent = qsearchs('agent',{'agentnum'=> $cust_main->agentnum }); @@ -79,13 +92,15 @@ my %agent_pkgs = map { ( $_->pkgpart , $all_pkg{$_->pkgpart} ) } my $count = 0; my $pkgparts = 0; -print < + -END + +<% #foreach my $type_pkgs ( qsearch('type_pkgs',{'typenum'=> $agent->typenum }) ) { foreach my $pkgpart ( sort { $agent_pkgs{$a} cmp $agent_pkgs{$b} } keys(%agent_pkgs) ) { @@ -93,38 +108,43 @@ foreach my $pkgpart ( sort { $agent_pkgs{$a} cmp $agent_pkgs{$b} } next unless exists $pkg{$pkgpart}; #skip disabled ones #print qq!! if ( $count == 0 ); my $value = $cgi->param("pkg$pkgpart") || 0; - print < + - - - + + + -END + +<% $count ++ ; #if ( $count == 2 ) { # print qq!\n! ; # $count = 0; #} } -print qq!
    Qty. Package Description
    $pkgpart:$pkg{$pkgpart} - $comment{$pkgpart} + " VALUE="<%= $value %>" SIZE="2" MAXLENGTH="2"> + <%= $pkgpart %>:<%= $pkg{$pkgpart} %> - <%= $comment{$pkgpart}%>
    !; - -unless ( $pkgparts ) { - my $p2 = popurl(2); - my $typenum = $agent->typenum; - my $agent_type = qsearchs( 'agent_type', { 'typenum' => $typenum } ); - my $atype = $agent_type->atype; - print <package definitions, or agent type -$atype not allowed to purchase -any packages.) -END -} +%> -#submit -print < - - - -END + + +<% unless ( $pkgparts ) { + my $p2 = popurl(2); + my $typenum = $agent->typenum; + my $agent_type = qsearchs( 'agent_type', { 'typenum' => $typenum } ); + my $atype = $agent_type->atype; %> + + (No package definitions, + or agent type + <%= $atype %> + is not allowed to purchase any packages.) + +<% } %> + +

    + + + +<%= include('/elements/footer.html') %> diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html index 5486b4b00..120c03a3c 100644 --- a/httemplate/edit/elements/edit.html +++ b/httemplate/edit/elements/edit.html @@ -17,6 +17,13 @@ # 'menubar' => '', #menubar arrayref # # 'viewall_dir' => '', #'search' or 'browse', defaults to 'search' + # + # 'html_bottom' => '', #string + # 'html_bottom' => sub { + # my $object = shift; + # # ... + # "html_string"; + # }, my(%opt) = @_; @@ -27,6 +34,7 @@ my $fields = $opt{'fields'} #|| [ grep { $_ ne $pkey } dbdef->table($table)->columns ]; || [ grep { $_ ne $pkey } fields($table) ]; + #my @actualfields = map { ref($_) ? $_->{'field'} : $_ } @$fields; my $object; if ( $cgi->param('error') ) { @@ -63,10 +71,7 @@ ); } -%> - - -<%= include("/elements/header.html", $title, +%><%= include("/elements/header.html", $title, include( '/elements/menubar.html', @menubar ) ) %> @@ -86,7 +91,18 @@ <%= ntable("#cccccc",2) %> -<% foreach my $field ( @$fields ) { %> +<% foreach my $f ( @$fields ) { + + my( $field, $type); + if ( ref($f) ) { + $field = $f->{'field'}, + $type = $f->{'type'} || 'text', + } else { + $field = $f; + $type = 'text'; + } + +%> @@ -98,12 +114,11 @@ <% - #just text in one size for now... eventually more options for - # uneditable, hidden, , etc. fields %> - + @@ -112,6 +127,11 @@ +<%= ref( $opt{'html_bottom'} ) + ? &{ $opt{'html_bottom'} }( $object ) + : $opt{'html_bottom'} +%> +
    "> diff --git a/httemplate/edit/part_referral.cgi b/httemplate/edit/part_referral.cgi index f784dfa3e..dce1e6394 100755 --- a/httemplate/edit/part_referral.cgi +++ b/httemplate/edit/part_referral.cgi @@ -1,4 +1,3 @@ - <% my $part_referral; @@ -17,32 +16,29 @@ my $action = $part_referral->refnum ? 'Edit' : 'Add'; my $hashref = $part_referral->hashref; my $p1 = popurl(1); -print header("$action Advertising source", menubar( + +%><%= 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') ) { %> + Error: <%= $cgi->param('error') %> +<% } %> -print qq!Error: !, $cgi->param('error'), - "" - if $cgi->param('error'); +

    -print qq!!; + -print qq!!; +<% #print "Referral #", $hashref->{refnum} ? $hashref->{refnum} : "(NEW)"; +%> -print < -END +Advertising source -print qq!
    !; +
    +"> -print < - - -END + -%> +<%= include('/elements/footer.html') %> diff --git a/httemplate/edit/part_virtual_field.cgi b/httemplate/edit/part_virtual_field.cgi index fb10321e8..7b2c768a7 100644 --- a/httemplate/edit/part_virtual_field.cgi +++ b/httemplate/edit/part_virtual_field.cgi @@ -1,4 +1,3 @@ - <% my ($vfieldpart, $part_virtual_field); @@ -21,12 +20,14 @@ if ( $cgi->param('error') ) { my $action = $part_virtual_field->vfieldpart ? 'Edit' : 'Add'; my $p1 = popurl(1); -print header("$action Virtual Field Definition", ''); -print qq!Error: !, $cgi->param('error'), - "" - if $cgi->param('error'); -%> +%><%= include('/elements/header.html', "$action Virtual Field Definition") %> + +<% if ( $cgi->param('error') ) { %> + Error: <%= $cgi->param('error') %> +

    +<% } %> +
    @@ -83,10 +84,8 @@ Field #<%=$vfieldpart or "(NEW)"%>

    -

    +
    If you don't understand what check_block and list_source mean, LEAVE THEM BLANK. We mean it. - - - +<%= include('/elements/footer.html') %> diff --git a/httemplate/edit/process/access_group.html b/httemplate/edit/process/access_group.html new file mode 100644 index 000000000..e8c6d07b1 --- /dev/null +++ b/httemplate/edit/process/access_group.html @@ -0,0 +1,5 @@ +<%= include( 'elements/process.html', + 'table' => 'access_group', + 'viewall_dir' => 'browse', + ) +%> diff --git a/httemplate/edit/process/access_user.html b/httemplate/edit/process/access_user.html new file mode 100644 index 000000000..a6c2a36b1 --- /dev/null +++ b/httemplate/edit/process/access_user.html @@ -0,0 +1,8 @@ +<%= include( 'elements/process.html', + 'table' => 'access_user', + 'viewall_dir' => 'browse', + 'process_m2m' => { 'link_table' => 'access_usergroup', + 'target_table' => 'access_group', + }, + ) +%> diff --git a/httemplate/edit/process/agent_type.cgi b/httemplate/edit/process/agent_type.cgi index 516594573..fd8ca8833 100755 --- a/httemplate/edit/process/agent_type.cgi +++ b/httemplate/edit/process/agent_type.cgi @@ -11,43 +11,24 @@ my $new = new FS::agent_type ( { my $error; if ( $typenum ) { - $error=$new->replace($old); + $error = $new->replace($old); } else { - $error=$new->insert; - $typenum=$new->getfield('typenum'); + $error = $new->insert; + $typenum = $new->getfield('typenum'); } +#$error ||= $new->process_m2m( ); if ( $error ) { $cgi->param('error', $error); print $cgi->redirect(popurl(2). "agent_type.cgi?". $cgi->query_string ); } else { - #false laziness w/ edit/process/part_svc.cgi - foreach my $part_pkg (qsearch('part_pkg',{})) { - my($pkgpart)=$part_pkg->getfield('pkgpart'); - - my($type_pkgs)=qsearchs('type_pkgs',{ - 'typenum' => $typenum, - 'pkgpart' => $pkgpart, - }); - if ( $type_pkgs && ! $cgi->param("pkgpart$pkgpart") ) { - my($d_type_pkgs)=$type_pkgs; #need to save $type_pkgs for below. - $error=$d_type_pkgs->delete; - die $error if $error; - - } elsif ( $cgi->param("pkgpart$pkgpart") - && ! $type_pkgs - ) { - #ok to clobber it now (but bad form nonetheless?) - $type_pkgs=new FS::type_pkgs ({ - 'typenum' => $typenum, - 'pkgpart' => $pkgpart, - }); - $error= $type_pkgs->insert; - die $error if $error; - } - - } + my $error = $new->process_m2m( + 'link_table' => 'type_pkgs', + 'target_table' => 'part_pkg', + 'params' => scalar($cgi->Vars) + ); + die $error if $error; print $cgi->redirect(popurl(3). "browse/agent_type.cgi"); } diff --git a/httemplate/edit/process/cust_bill_pay.cgi b/httemplate/edit/process/cust_bill_pay.cgi index 0025b16b5..fc668bb07 100755 --- a/httemplate/edit/process/cust_bill_pay.cgi +++ b/httemplate/edit/process/cust_bill_pay.cgi @@ -33,11 +33,19 @@ if ($cgi->param('invnum') =~ /^Refund$/) { my $error = $new->insert; if ( $error ) { + $cgi->param('error', $error); - print $cgi->redirect(popurl(2). "cust_bill_pay.cgi?". $cgi->query_string ); + %><%= $cgi->redirect(popurl(2). "cust_bill_pay.cgi?". $cgi->query_string ) %><% + } else { - print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); -} + #print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); + + %><%= header('Payment application sucessful') %> + + + -%> +<% } %> diff --git a/httemplate/edit/process/cust_credit.cgi b/httemplate/edit/process/cust_credit.cgi index 85bfd4489..6a4ef194a 100755 --- a/httemplate/edit/process/cust_credit.cgi +++ b/httemplate/edit/process/cust_credit.cgi @@ -13,14 +13,23 @@ my $error = $new->insert; if ( $error ) { $cgi->param('error', $error); - print $cgi->redirect(popurl(2). "cust_credit.cgi?". $cgi->query_string ); + + %><%= $cgi->redirect(popurl(2). "cust_credit.cgi?". $cgi->query_string ) %><% + } else { + if ( $cgi->param('apply') eq 'yes' ) { my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum }) or die "unknown custnum $custnum"; $cust_main->apply_credits; } - print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); -} + #print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); + + %><%= header('Credit sucessful') %> + + + -%> +<% } %> diff --git a/httemplate/edit/process/cust_credit_bill.cgi b/httemplate/edit/process/cust_credit_bill.cgi index 28f892f62..3b759536f 100755 --- a/httemplate/edit/process/cust_credit_bill.cgi +++ b/httemplate/edit/process/cust_credit_bill.cgi @@ -34,11 +34,19 @@ if ($cgi->param('invnum') =~ /^Refund$/) { my $error = $new->insert; if ( $error ) { + $cgi->param('error', $error); - print $cgi->redirect(popurl(2). "cust_credit_bill.cgi?". $cgi->query_string ); + %><%= $cgi->redirect(popurl(2). "cust_credit_bill.cgi?". $cgi->query_string ) %><% + } else { - print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); -} + #print $cgi->redirect(popurl(3). "view/cust_main.cgi?$custnum"); + + %><%= header('Credit application sucessful') %> + + + -%> +<% } %> diff --git a/httemplate/edit/process/elements/process.html b/httemplate/edit/process/elements/process.html index 83ff6f728..59ad35ee4 100644 --- a/httemplate/edit/process/elements/process.html +++ b/httemplate/edit/process/elements/process.html @@ -2,10 +2,21 @@ # options example... # + ### + ##req + ## # 'table' => + # # #? 'primary_key' => #required when the dbdef doesn't know...??? # #? 'fields' => [] + # + ### + ##opt + ### # 'viewall_dir' => '', #'search' or 'browse', defaults to 'search' + # 'process_m2m' => { 'link_table' => 'link_table_name', + # 'target_table' => 'target_table_name', + # }. my(%opt) = @_; @@ -31,12 +42,16 @@ if ( $pkeyvalue ) { $error = $new->replace($old); } else { - warn $new; $error = $new->insert; - warn $error; $pkeyvalue = $new->getfield($pkey); } + if ( !$error && $opt{'process_m2m'} ) { + $error = $new->process_m2m( %{ $opt{'process_m2m'} }, + 'params' => scalar($cgi->Vars), + ); + } + if ( $error ) { $cgi->param('error', $error); print $cgi->redirect(popurl(2). "$table.html?". $cgi->query_string ); diff --git a/httemplate/edit/svc_domain.cgi b/httemplate/edit/svc_domain.cgi index ca0e3398f..f47ba0a8f 100755 --- a/httemplate/edit/svc_domain.cgi +++ b/httemplate/edit/svc_domain.cgi @@ -1,4 +1,3 @@ - <% my($svcnum, $pkgnum, $svcpart, $kludge_action, $purpose, $part_svc, @@ -66,33 +65,31 @@ my $otaker = getotaker; my $domain = $svc_domain->domain; my $p1 = popurl(1); -print header("$action $svc", ''); - -print qq!Error: !, $cgi->param('error'), - "" - if $cgi->param('error'); - -print < - - - -END - -print qq!New!; -print qq!
    Transfer!; - -print <Domain -
    Purpose/Description: -

    - - - -END %> + +<%= include('/elements/header.html', "$action $svc", '') %> + +<% if ( $cgi->param('error') ) { %> + Error: <%= $cgi->param('error') %> +<% } %> + +

    + + + + +>New +
    + +>Transfer + +

    Domain + +
    Purpose/Description: + +

    + +

    + +<%= include('/elements/footer.html') %> diff --git a/httemplate/elements/checkboxes-table.html b/httemplate/elements/checkboxes-table.html new file mode 100644 index 000000000..d26ebef35 --- /dev/null +++ b/httemplate/elements/checkboxes-table.html @@ -0,0 +1,110 @@ +<% + + ## + # required + ## + # 'target_table' => 'table_name', + # 'link_table' => 'table_name', + # + # 'name_col' => 'name_column', + # #or + # 'name_callback' => sub { }, + # + ## + # 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 + ## + # 'disable-able' => 1, + + my( %opt ) = @_; + + my $target_pkey = dbdef->table($opt{'target_table'})->primary_key; + + 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'}; + } + + my $hashref = $opt{'hashref'} || {}; + + my $extra_sql = ''; + + if ( $opt{'disable-able'} ) { + $hashref->{'disabled'} = ''; + + $extra_sql .= ( $sourcenum && $source_pkey ) + ? "OR $source_pkey = $sourcenum" + : ''; + } + +%> + +<% foreach my $target_obj ( + qsearch({ 'table' => $opt{'target_table'}, + 'hashref' => $hashref, + 'select' => $opt{'target_table'}. '.*', + 'addl_from' => "LEFT JOIN $opt{'link_table'} USING ( $target_pkey )", + 'extra_sql' => $extra_sql, + }) + ) { + + my $targetnum = $target_obj->$target_pkey(); +%> + + $sourcenum, + $target_pkey => $targetnum, + }) + ? 'CHECKED ' + : '' + %> VALUE="ON"> + + <% if ( $opt{'target_link'} ) { %> + + <% + + } + %><%= $targetnum %>: + + <% if ( $opt{'name_callback'} ) { %> + + <%= &{ $opt{'name_callback'} }( $target_obj ) %><%= $opt{'target_link'} ? '' : '' %> + + <% } else { + my $name_col = $opt{'name_col'}; + %> + + <%= $target_obj->$name_col() %><%= $opt{'target_link'} ? '' : '' %> + + <% } %> + + <% if ( $opt{'disable-able'} ) { %> + + <%= $target_obj->disabled =~ /^Y/i ? ' (DISABLED)' : '' %> + + <% } %> + +
    + +<% } %> + diff --git a/httemplate/elements/cssexpr.js b/httemplate/elements/cssexpr.js new file mode 100644 index 000000000..c434d8da0 --- /dev/null +++ b/httemplate/elements/cssexpr.js @@ -0,0 +1,66 @@ +function constExpression(x) { + return x; +} + +function simplifyCSSExpression() { + try { + var ss,sl, rs, rl; + ss = document.styleSheets; + sl = ss.length + + for (var i = 0; i < sl; i++) { + simplifyCSSBlock(ss[i]); + } + } + catch (exc) { + //alert("Got an error while processing css. The page should still work but might be a bit slower"); + throw exc; + } +} + +function simplifyCSSBlock(ss) { + var rs, rl; + + for (var i = 0; i < ss.imports.length; i++) + simplifyCSSBlock(ss.imports[i]); + + if (ss.cssText.indexOf("expression(constExpression(") == -1) + return; + + rs = ss.rules; + rl = rs.length; + for (var j = 0; j < rl; j++) + simplifyCSSRule(rs[j]); + +} + +function simplifyCSSRule(r) { + var str = r.style.cssText; + var str2 = str; + var lastStr; + do { + lastStr = str2; + str2 = simplifyCSSRuleHelper(lastStr); + } while (str2 != lastStr) + + if (str2 != str) + r.style.cssText = str2; +} + +function simplifyCSSRuleHelper(str) { + var i, i2; + i = str.indexOf("expression(constExpression("); + if (i == -1) return str; + i2 = str.indexOf("))", i); + var hd = str.substring(0, i); + var tl = str.substring(i2 + 2); + var exp = str.substring(i + 27, i2); + var val = eval(exp) + return hd + val + tl; +} + +if (/msie/i.test(navigator.userAgent) && window.attachEvent != null) { + window.attachEvent("onload", function () { + simplifyCSSExpression(); + }); +} diff --git a/httemplate/elements/footer.html b/httemplate/elements/footer.html index 6029d7637..32d121996 100644 --- a/httemplate/elements/footer.html +++ b/httemplate/elements/footer.html @@ -1,2 +1,5 @@ + + + diff --git a/httemplate/elements/header.html b/httemplate/elements/header.html index 10e4e40f1..49814577e 100644 --- a/httemplate/elements/header.html +++ b/httemplate/elements/header.html @@ -2,20 +2,285 @@ my($title, $menubar) = ( shift, shift ); my $etc = @_ ? shift : ''; #$etc is for things like onLoad= etc. my $head = @_ ? shift : ''; #$head is for things that go in the section + my $conf = new FS::Conf; %> - - - - <%= $title %> - - - - - <%= $head %> - - > + + + + + <%= $title %> + + + + + + + + <% + + tie my %report_menu, 'Tie::IxHash', + 'Report one' => [ 'there', 'theretip' ], + 'Report too' => [ 'here', 'heretip' ], + ; + + tie my %config_employees, 'Tie::IxHash', + 'View/Edit employees' => [ $fsurl.'browse/access_user.html', 'Setup internal users' ], + 'View/Edit employee groups' => [ $fsurl.'browse/access_group.html', 'Employee groups allow you to control access to the backend' ], + ; + + tie my %config_export_svc_pkg, 'Tie::IxHash', + 'View/Edit exports' => [ $fsurl.'browse/part_export.cgi', 'Provisioning services to external machines, databases and APIs' ], + 'View/Edit service definitions' => [ $fsurl.'browse/part_svc.cgi', 'Services are items you offer to your customers' ], + 'View/Edit package definitions' => [ $fsurl.'browse/part_pkg.cgi', 'One or more services are grouped together into a package and given pricing information. Customers purchase packages, not services' ], + 'View/Edit package classes' => [ $fsurl.'browse/pkg_class.html', 'Package classes define groups of packages, for reporting and convenience purposes.' ], + ; + + tie my %config_agent, 'Tie::IxHash', + 'View/Edit agent types' => [ $fsurl.'browse/agent_type.cgi', 'Agent types define groups of package definitions that you can then assign to particular agents' ], + 'View/Edit agents' => [ $fsurl.'browse/agent.cgi', 'Agents are resellers of your service. Agents may be limited to a subset of your full offerings (via their type)' ], + ; + + tie my %config_billing, 'Tie::IxHash', + 'View/Edit payment gateways' => [ $fsurl.'browse/payment_gateway.html', 'Credit card and electronic check processors' ], + 'View/Edit invoice events' => [ $fsurl.'browse/part_bill_event.cgi', 'Actions for overdue invoices' ], + 'View/Edit prepaid cards' => [ $fsurl.'browse/prepay_credit.html', 'View outstanding cards, generate new cards' ], + 'View/Edit call rates and regions' => [ $fsurl.'browse/rate.cgi', 'Manage rate plans, regions and prefixes for VoIP and call billing' ], + 'View/Edit locales and tax rates' => [ $fsurl.'browse/cust_main_county.cgi', 'Change tax rates, or break down a country into states, or a state into counties and assign different tax rates to each' ], + ; + + tie my %config_dialup, 'Tie::IxHash', + 'View/Edit access numbers' => [ $fsurl.'browse/svc_acct_pop.cgi', 'Points of Presence' ], + ; + + tie my %config_broadband, 'Tie::IxHash', + 'View/Edit routers' => [ $fsurl.'browse/router.cgi', 'Broadband access routers' ], + '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_menu, 'Tie::IxHash', + 'Settings' => [ $fsurl.'config/config-view.cgi', 'XXXconfigittip' ], + 'separator' => '', #its a separator! + 'Employees' => [ \%config_employees, 'XXXtooltip' ], + 'Provisioning, services and packages' + => [ \%config_export_svc_pkg, 'XXXtootip' ], + 'Resellers' => [ \%config_agent, 'XXXtootip' ], + 'Billing' => [ \%config_billing, 'XXXtootip' ], + 'Dialup' => [ \%config_dialup, 'XXXtootip' ], + 'Fixed (username-less) broadband' + => [ \%config_broadband, 'XXXtootip' ], + 'Miscellaneous' => [ \%config_misc, 'XXXtootip' ], + ; + + tie my %menu, 'Tie::IxHash', + 'Home' => [ $fsurl, 'hometip', ], + 'Top item one' => [ 'nowhere_yet', 'nowheretip', ], + 'Top item too' => [ 'nowhere_yet_either', 'eithertip', ], + 'Reports' => [ \%report_menu, 'reportmenutip' ], + 'Configuration' => [ \%config_menu, 'configmenutip' ], + ; + + use vars qw($gmenunum); + $gmenunum = 0; + + sub submenu { + my($submenu, $title) = @_; + my $menunum = $gmenunum++; + + #return two args: html, menuname + + "var myMenu$menunum = new WebFXMenu;\n". + #"myMenu$menunum.useAutoPosition = true;\n". + "myMenu$menunum.emptyText = '$title';\n". + + ( + join("\n", map { + + if ( !ref( $submenu->{$_} ) ) { + + "myMenu$menunum.add(new WebFXMenuSeparator());"; + + } else { + + my($url_or_submenu, $tooltip ) = @{ $submenu->{$_} }; + if ( ref($url_or_submenu) ) { + + my($subhtml, $submenuname ) = submenu($url_or_submenu, $_); #mmm, recursion + + "$subhtml\n". + "myMenu$menunum.add(new WebFXMenuItem(\"$_\", null, \"$tooltip\", $submenuname ));"; + + } else { + + "myMenu$menunum.add(new WebFXMenuItem(\"$_\", \"$url_or_submenu\", \"$tooltip\" ));"; + + } + + } + + } keys %$submenu ) + ). "\n". + "myMenu$menunum.width = 224\n", + + "myMenu$menunum"; + + } + + %> + + + + + <%= $head %> + + + STYLE="margin-top:0; margin-bottom:0; margin-left:0; margin-right:0"> + + + + + + + + + +
    + freeside + + <%= $conf->config('company_name') %> Billing + Logged in as <%= getotaker %> 
    Preferences 

    +
    + + + + + <% if ( $conf->config('ticket_system') eq 'RT_Internal' ) { %> + <% eval "use RT;"; %> + + + <% } %> + + +
    + + Freeside v<%= $FS::VERSION %>
    + Documentation
    +
    +
    + + RT v<%= $RT::VERSION %>
    +
    Documentation
    +
    +
    + +
    + + + + + + + + + + + +
    + +
    + +
    +
    +
    + + +
    +
    +
    + + +
    +
    + + + + + + + + + + + + + + +<% } %> diff --git a/httemplate/elements/xmenu.css b/httemplate/elements/xmenu.css new file mode 100644 index 000000000..5bb8a0deb --- /dev/null +++ b/httemplate/elements/xmenu.css @@ -0,0 +1,185 @@ + +.webfx-menu, .webfx-menu * { + /* + Set the box sizing to content box + in the future when IE6 supports box-sizing + there will be an issue to fix the sizes + + There is probably an issue with IE5 mac now + because IE5 uses content-box but the script + assumes all versions of IE uses border-box. + + At the time of this writing mozilla did not support + box-sizing for absolute positioned element. + + Opera only supports content-box + */ + box-sizing: content-box; + -moz-box-sizing: content-box; +} + +.webfx-menu { + position: absolute; + z-index: 100; + visibility: hidden; + width: 154px; + border: 1px solid black; + padding: 1px; + background: white; + filter: progid:DXImageTransform.Microsoft.Shadow(color="#777777", Direction=135, Strength=4) + alpha(Opacity=95); + -moz-opacity: 0.95; + /* a drop shadow would be nice in moz/others too... */ +} + +.webfx-menu-empty { + display: block; + border: 1px solid white; + padding: 2px 5px 2px 5px; + font-size: 11px; + /* font-family: Tahoma, Verdan, Helvetica, Sans-Serif; */ + color: black; +} + +.webfx-menu a { + display: block; + width: expression(constExpression(ieBox ? "100%": "auto")); /* should be ignored by mz and op */ + height: expression(constExpression("1px")); + overflow: visible; + padding: 2px 0px 2px 5px; + font-size: 11px; + font-family: Tahoma, Verdan, Helvetica, Sans-Serif; + text-decoration: none; + vertical-align: center; + color: black; + border: 1px solid white; +} + +.webfx-menu a:visited, +.webfx-menu a:visited:hover { + color: black; +} + +.webfx-menu a:hover { + color: black; + /* background: #faf7fa; #f5ebf4; #efdfef; white; #BC79B8; */ + /* background: #ffe6fe; */ + /* background: #ffc2fe; */ + background: #fff2fe; + border: 1px solid #7e0079; /*rgb(120,172,255);#ff8800;*/ +} + +.webfx-menu a .arrow { + float: right; + border: 0; + width: 3px; + margin-right: 3px; + margin-top: 4px; +} + +/* separtor */ +.webfx-menu div { + height: 0; + height: expression(constExpression(ieBox ? "2px" : "0")); + border-top: 1px solid #7e0079; /* rgb(120,172,255); */ + border-bottom: 1px solid rgb(234,242,255); + overflow: hidden; + margin: 2px 0px 2px 0px; + font-size: 0mm; +} + +.webfx-menu-bar { + /* i want a vertical bar */ + display: block; + + /* background: rgb(120,172,255);/*rgb(255,128,0);*/ + /* background: #a097ed; */ + background: #000000; + /* border: 1px solid #7E0079; */ + /* border: 1px solid #000000; */ + /* border: none */ + + padding: 2px; + + font-family: Verdana, Helvetica, Sans-Serif; + font-size: 11px; + + /* IE5.0 has the wierdest box model for inline elements */ + padding: expression(constExpression(ie50 ? "0px" : "2px")); +} + +.webfx-menu-bar a, +.webfx-menu-bar a:visited { + /* i want a vertical bar */ + display: block; + + /* border: 1px solid black; /*rgb(0,0,0);/*rgb(255,128,0);*/ + /* border: 1px solid black; /* #ffffff; */ + /* border-bottom: 1px solid black; */ + border-bottom: 1px solid white; + /* border-bottom: 1px solid rgb(0,66,174); + /* border-bottom: 1px solid black; + border-bottom: 1px solid black; + border-bottom: 1px solid black; */ + + padding: 1px 5px 1px 5px; + + /* color: black; */ + color: white; + text-decoration: none; + + /* IE5.0 Does not paint borders and padding on inline elements without a height/width */ + height: expression(constExpression(ie50 ? "17px" : "auto")); +} + +.webfx-menu-bar a:hover { + /* color: black; */ + color: white; + /* background: rgb(120,172,255); */ + /* background: #BC79B8; */ + background: #7E0079; + /* border-left: 1px solid rgb(234,242,255); + border-right: 1px solid rgb(0,66,174); + border-top: 1px solid rgb(234,242,255); + border-bottom: 1px solid rgb(0,66,174); */ +} + +.webfx-menu-bar a .arrow { + border: 0; + float: right; +/* vertical-align: top; */ + width: 3px; + margin-right: 3px; + margin-top: 4px; +} + +.webfx-menu-bar a:active, .webfx-menu-bar a:focus { + -moz-outline: none; + outline: none; + /* + ie does not support outline but ie55 can hide the outline using + a proprietary property on HTMLElement. Did I say that IE sucks at CSS? + */ + ie-dummy: expression(this.hideFocus=true); + + border-left: 1px solid rgb(0,66,174); + border-right: 1px solid rgb(234,242,255); + border-top: 1px solid rgb(0,66,174); + border-bottom: 1px solid rgb(234,242,255); +} + +.webfx-menu-title { + color: black; + /* background: #faf7fa; #f5ebf4; #efdfef; white; #BC79B8; */ + background: #7e0079; +/* border: 1px solid #7e0079; /*rgb(120,172,255);#ff8800;*/ + padding: 3px 1px 3px 6px; + display: block; + font-size: 13px; + font-family: Tahoma, Verdan, Helvetica, Sans-Serif; + text-decoration: none; + color: white; +/* border: 1px solid white; */ + border-bottom: 1px solid white; +} + diff --git a/httemplate/elements/xmenu.js b/httemplate/elements/xmenu.js new file mode 100644 index 000000000..134265f53 --- /dev/null +++ b/httemplate/elements/xmenu.js @@ -0,0 +1,668 @@ +// + + + + <% #include( '/elements/table.html', '#cccccc' ) %> <%= ntable('#cccccc') %> @@ -112,7 +102,7 @@ function achclose() { @@ -173,7 +163,7 @@ function achclose() { @@ -205,5 +195,5 @@ function achclose() {
    - - + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/cust_bill.cgi b/httemplate/search/cust_bill.cgi deleted file mode 100755 index 5b0538ca3..000000000 --- a/httemplate/search/cust_bill.cgi +++ /dev/null @@ -1,165 +0,0 @@ -<% - -my $conf = new FS::Conf; -my $maxrecords = $conf->config('maxsearchrecordsperpage'); - -my $orderby = ''; #removeme - -my $limit = ''; -$limit .= "LIMIT $maxrecords" if $maxrecords; - -my $offset = $cgi->param('offset') || 0; -$limit .= " OFFSET $offset" if $offset; - -my($total, $tot_amount, $tot_balance); - -my(@cust_bill); -if ( $cgi->keywords ) { - my($query) = $cgi->keywords; - my $owed = "charged - ( select coalesce(sum(amount),0) from cust_bill_pay - where cust_bill_pay.invnum = cust_bill.invnum ) - - ( select coalesce(sum(amount),0) from cust_credit_bill - where cust_credit_bill.invnum = cust_bill.invnum )"; - my @where; - if ( $query =~ /^(OPEN(\d*)_)?(invnum|date|custnum)$/ ) { - my($open, $days, $field) = ($1, $2, $3); - $field = "_date" if $field eq 'date'; - $orderby = "ORDER BY cust_bill.$field"; - push @where, "0 != $owed" if $open; - push @where, "cust_bill._date < ". (time-86400*$days) if $days; - } else { - die "unknown query string $query"; - } - - my $extra_sql = scalar(@where) ? 'WHERE '. join(' AND ', @where) : ''; - - my $statement = "SELECT COUNT(*), sum(charged), sum($owed) - FROM cust_bill $extra_sql"; - my $sth = dbh->prepare($statement) or die dbh->errstr. " doing $statement"; - $sth->execute or die "Error executing \"$statement\": ". $sth->errstr; - - ( $total, $tot_amount, $tot_balance ) = @{$sth->fetchrow_arrayref}; - - @cust_bill = qsearch( - 'cust_bill', - {}, - "cust_bill.*, $owed as owed", - "$extra_sql $orderby $limit" - ); -} else { - $cgi->param('invnum') =~ /^\s*(FS-)?(\d+)\s*$/; - my $invnum = $2; - @cust_bill = qsearchs('cust_bill', { 'invnum' => $invnum } ); - $total = scalar(@cust_bill); -} - -#if ( scalar(@cust_bill) == 1 ) { -if ( $total == 1 ) { - my $invnum = $cust_bill[0]->invnum; - print $cgi->redirect(popurl(2). "view/cust_bill.cgi?$invnum"); #redirect -} elsif ( scalar(@cust_bill) == 0 ) { -%> - -<% - eidiot("Invoice not found."); -} else { -%> - -<% - - #begin pager - my $pager = ''; - if ( $total != scalar(@cust_bill) && $maxrecords ) { - unless ( $offset == 0 ) { - $cgi->param('offset', $offset - $maxrecords); - $pager .= 'Previous '; - } - my $poff; - my $page; - for ( $poff = 0; $poff < $total; $poff += $maxrecords ) { - $page++; - if ( $offset == $poff ) { - $pager .= qq!$page !; - } else { - $cgi->param('offset', $poff); - $pager .= qq!$page !; - } - } - unless ( $offset + $maxrecords > $total ) { - $cgi->param('offset', $offset + $maxrecords); - $pager .= 'Next '; - } - } - #end pager - - print header("Invoice Search Results", menubar( - 'Main Menu', popurl(2) - )). - "$total matching invoices found
    ". - "\$$tot_balance total balance
    ". - "\$$tot_amount total amount
    ". - "
    $pager". table(). < - - - - - - - -END - - foreach my $cust_bill ( @cust_bill ) { - my($invnum, $owed, $charged, $date ) = ( - $cust_bill->invnum, - sprintf("%.2f", $cust_bill->getfield('owed')), - sprintf("%.2f", $cust_bill->charged), - $cust_bill->_date, - ); - my $pdate = time2str("%b %d %Y", $date); - - my $rowspan = 1; - - my $view = popurl(2). "view/cust_bill.cgi?$invnum"; - print < - - - - -END - my $custnum = $cust_bill->custnum; - my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ); - if ( $cust_main ) { - my $cview = popurl(2). "view/cust_main.cgi?". $cust_main->custnum; - my ( $name, $company ) = ( - $cust_main->last. ', '. $cust_main->first, - $cust_main->company, - ); - print <$name - -END - } else { - print <WARNING: couldn't find cust_main.custnum $custnum (cust_bill.invnum $invnum) -END - } - - print ""; - } - $tot_balance = sprintf("%.2f", $tot_balance); - $tot_amount = sprintf("%.2f", $tot_amount); - print "
    + +
    + + +
    + <%= $title %> +

    - <%= $menubar ? "$menubar

    " : '' %> + <%= $menubar !~ /^\s*$/ ? "$menubar

    " : '' %> diff --git a/httemplate/elements/menubar.html b/httemplate/elements/menubar.html index 87a50312c..29facb6b6 100644 --- a/httemplate/elements/menubar.html +++ b/httemplate/elements/menubar.html @@ -2,6 +2,7 @@ my($item, $url, @html); while (@_) { ($item, $url) = splice(@_,0,2); + next if $item =~ /^\s*Main\s+Menu\s*$/i; push @html, qq!$item!; } %> diff --git a/httemplate/elements/select-access_group.html b/httemplate/elements/select-access_group.html new file mode 100644 index 000000000..b05f565ea --- /dev/null +++ b/httemplate/elements/select-access_group.html @@ -0,0 +1,15 @@ +<% + my( $groupnum, %opt ) = @_; + + %opt{'records'} = delete $opt{'access_group'} + if $opt{'access_group'}; + +%><%= include( '/elements/select-table.html', + 'table' => 'access_group', + 'name_col' => 'groupname', + 'value' => $groupnum, + 'empty_label' => '(none)', + #'hashref' => { 'disabled' => '' }, + %opt, + ) +%> diff --git a/httemplate/elements/tr-select-access_group.html b/httemplate/elements/tr-select-access_group.html new file mode 100644 index 000000000..0beec0842 --- /dev/null +++ b/httemplate/elements/tr-select-access_group.html @@ -0,0 +1,22 @@ +<% + my( $groupnum, %opt ) = @_; + + $opt{'access_group'} ||= [ qsearch( 'access_group', {} ) ]; # { disabled=>'' } ) + + #warn "***** tr-select-access_group: \n". Dumper(%opt); +%> + +<% if ( scalar(@{ $opt{'access_group'} }) == 0 ) { %> + + + +<% } else { %> + +
    <%= $opt{'label'} || 'Access group' %> + <%= include( '/elements/select-access_group.html', $groupnum, %opt ) %> +
    CVV2 - (help) + (help)
    ABA/Routing number - (help) + (help)
    BalanceAmountDateContact nameCompany
    $invnum\$$owed\$$charged$pdate$company
    $pager
    ". table(). <       Total
    BalanceTotal
    Amount - \$$tot_balance\$$tot_amount - - - -END - -} - -%> diff --git a/httemplate/search/cust_main-otaker.cgi b/httemplate/search/cust_main-otaker.cgi index 03c2619af..6ac0bde18 100755 --- a/httemplate/search/cust_main-otaker.cgi +++ b/httemplate/search/cust_main-otaker.cgi @@ -1,28 +1,23 @@ - - - Customer Search - - - - Customer Search - -
    -
    - Search for Order taker: - - <% my $sth = dbh->prepare("SELECT DISTINCT otaker FROM cust_main") - or die dbh->errstr; - $sth->execute() or die $sth->errstr; -# my @otakers = map { $_->[0] } @{$sth->selectall_arrayref}; - %> - -

    +<%= include('/elements/header.html', 'Customer Search' ) %> -

    - - +
    +Search for Order taker: + + +<% my $sth = dbh->prepare("SELECT DISTINCT otaker FROM cust_main") + or die dbh->errstr; + $sth->execute() or die $sth->errstr; + #my @otakers = map { $_->[0] } @{$sth->fetchall_arrayref}; +%> + + +

    + +

    + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/cust_main-payinfo.html b/httemplate/search/cust_main-payinfo.html deleted file mode 100755 index b82b610d8..000000000 --- a/httemplate/search/cust_main-payinfo.html +++ /dev/null @@ -1,20 +0,0 @@ - - - Customer Search - - - - Customer Search - -
    -
    - Search for Credit card #: - - - -

    - -

    - - - diff --git a/httemplate/search/cust_main-quickpay.html b/httemplate/search/cust_main-quickpay.html deleted file mode 100755 index 154a64199..000000000 --- a/httemplate/search/cust_main-quickpay.html +++ /dev/null @@ -1,44 +0,0 @@ - - - Quick payment entry - - - - Quick payment entry - -

    - Main Menu

    -
    - - Search for last name: - - using search method: - -

    Search for company: - - using search method: - -

    - -

    - -
    Explanation of search methods: -
      -
    • All - Try all search methods. -
    • Fuzzy - Searches for matches that are close to your text. -
    • Substring - Searches for matches that contain your text. -
    • Exact - Finds exact matches only, but much faster than the other search methods. -
    - - - diff --git a/httemplate/search/cust_main.cgi b/httemplate/search/cust_main.cgi index 36ad39da8..8b70ff490 100755 --- a/httemplate/search/cust_main.cgi +++ b/httemplate/search/cust_main.cgi @@ -220,14 +220,13 @@ if ( scalar(@cust_main) == 1 && ! $cgi->param('referral_custnum') ) { eidiot "No matching customers found!\n"; } else { %> - -<% +<%= include('/elements/header.html', "Customer Search Results", '' ) %> - $total ||= scalar(@cust_main); - print header("Customer Search Results",menubar( - 'Main Menu', popurl(2) - )), "$total matching customers found "; + <% $total ||= scalar(@cust_main); %> + <%= $total %> matching customers found + + <% #begin pager my $pager = ''; if ( $total != scalar(@cust_main) && $maxrecords ) { @@ -368,12 +367,14 @@ END my $pcompany = $company ? qq!$company! : ' '; - print < + - $custnum - $last, $first - $pcompany -END + ><%= $custnum %> + ><%= "$last, $first" %> + ><%= $pcompany %> + + <% if ( defined dbdef->table('cust_main')->column('ship_last') ) { my($ship_last,$ship_first,$ship_company)=( $cust_main->ship_last || $cust_main->getfield('last'), @@ -383,15 +384,18 @@ END my $pship_company = $ship_company ? qq!$ship_company! : ' '; - print <$ship_last, $ship_first - $pship_company -END - } + %> - foreach my $addl_col ( @addl_cols ) { - print ""; - if ( $addl_col eq 'tickets' ) { + ><%= "$ship_last, $ship_first" %> + ><%= $pship_company %> + + <% } + + foreach my $addl_col ( @addl_cols ) { %> + + ALIGN=right> + + <% if ( $addl_col eq 'tickets' ) { if ( @custom_priorities ) { print &itable('', 0); foreach my $priority ( @custom_priorities, '' ) { @@ -461,10 +465,14 @@ END } print ""; } + + %> - print "$pager"; + <%= $pager %> -} + <%= include('/elements/footer.html') %> + +<% } #undef $cache; #does this help? diff --git a/httemplate/search/cust_pay.html b/httemplate/search/cust_pay.html deleted file mode 100755 index 6414cf771..000000000 --- a/httemplate/search/cust_pay.html +++ /dev/null @@ -1,18 +0,0 @@ - - - Check # Search - - - - Check # Search - -

    -
    - Search for check #: - - -

    -
    - - - diff --git a/httemplate/search/cust_pkg_report.cgi b/httemplate/search/cust_pkg_report.cgi index 412c3f79d..d9aada5f4 100755 --- a/httemplate/search/cust_pkg_report.cgi +++ b/httemplate/search/cust_pkg_report.cgi @@ -1,23 +1,22 @@ - - - Packages - - -

    Packages

    -
    - - Return packages with next bill date:

    - - <%= include( '/elements/tr-input-beginning_ending.html' ) %> - <%= include( '/elements/tr-select-agent.html', - $cgi->param('agentnum'), - ) - %> -
    -
    +<%= include('/elements/header.html', 'Packages' ) %> -
    +
    + - - +Return packages with next bill date: +

    + + <%= include( '/elements/tr-input-beginning_ending.html' ) %> + <%= include( '/elements/tr-select-agent.html', + $cgi->param('agentnum'), + ) + %> +
    + +
    + + +
    + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/report_cust_bill.html b/httemplate/search/report_cust_bill.html index a7be76689..f1b7bfa14 100644 --- a/httemplate/search/report_cust_bill.html +++ b/httemplate/search/report_cust_bill.html @@ -1,28 +1,28 @@ - - Invoice report criteria - - -

    Invoice report criteria

    -
    - - - <%= include( '/elements/tr-select-agent.html', - $cgi->param('agentnum'), - 'label' => 'Invoices for agent: ', - ) - %> - <%= include( '/elements/tr-input-beginning_ending.html' ) %> - - - - - - - - -
    Show only open invoices
    Show only the single most recent invoice per-customer
    -
    -
    - - +<%= include('/elements/header.html', 'Invoice report criteria' ) %> +
    + + + + <%= include( '/elements/tr-select-agent.html', + $cgi->param('agentnum'), + 'label' => 'Invoices for agent: ', + ) + %> + <%= include( '/elements/tr-input-beginning_ending.html' ) %> + + + + + + + + +
    Show only open invoices
    Show only the single most recent invoice per-customer
    + +
    + + +
    + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/report_cust_credit.html b/httemplate/search/report_cust_credit.html index 56bbd0ac0..8ca52dc9a 100644 --- a/httemplate/search/report_cust_credit.html +++ b/httemplate/search/report_cust_credit.html @@ -1,36 +1,38 @@ - - - Credit report criteria - - -

    Credit report criteria

    -
    - - - - +<%= include('/elements/header.html', 'Credit report' ) %> + + + + +
    Credits by employee:
    + + + <% my $sth = dbh->prepare("SELECT DISTINCT otaker FROM cust_credit") or die dbh->errstr; $sth->execute or die $sth->errstr; my @otakers = map { $_->[0] } @{$sth->fetchall_arrayref}; %> - - - <%= include( '/elements/tr-select-agent.html', - $cgi->param('agentnum'), - 'label' => 'for agent: ', - ) - %> - <%= include( '/elements/tr-input-beginning_ending.html' ) %> -
    Credits by employee: -
    -
    -
    - - + + + + + <%= include( '/elements/tr-select-agent.html', + $cgi->param('agentnum'), + 'label' => 'for agent: ', + ) + %> + <%= include( '/elements/tr-input-beginning_ending.html' ) %> + + +
    + + + + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/report_cust_pay.html b/httemplate/search/report_cust_pay.html index 5d8b74e77..8adf7dc13 100644 --- a/httemplate/search/report_cust_pay.html +++ b/httemplate/search/report_cust_pay.html @@ -1,38 +1,43 @@ - - - Payment report criteria - - -

    Payment report criteria

    -
    - - - - - - - <%= include( '/elements/tr-select-agent.html', - $cgi->param('agentnum'), - 'label' => 'for agent: ', - ) - %> - <%= include( '/elements/tr-input-beginning_ending.html' ) %> -
    Payments of type: -
    -
    -
    - - +<%= include('/elements/header.html', 'Payment report' ) %> + +
    + + + + + + + + + + <%= include( '/elements/tr-select-agent.html', + $cgi->param('agentnum'), + 'label' => 'for agent: ', + ) + %> + + <%= include( '/elements/tr-input-beginning_ending.html' ) %> + +
    Payments of type: + +
    + +
    + + +
    + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/report_prepaid_income.html b/httemplate/search/report_prepaid_income.html index 57c318eba..4359918f9 100644 --- a/httemplate/search/report_prepaid_income.html +++ b/httemplate/search/report_prepaid_income.html @@ -1,13 +1,13 @@ - - - Prepaid Income (Unearned Revenue) Report - - - - - - -

    Prepaid Income (Unearned Revenue) Report

    +<%= include('/elements/header.html', 'Prepaid Income (Unearned Revenue) Report', + '', + '', + ' + + + + ' +) %> +
    @@ -32,8 +32,6 @@ }); - - - -
    + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/report_tax.html b/httemplate/search/report_tax.html index 7a8ecd4f0..bdeb8e237 100755 --- a/httemplate/search/report_tax.html +++ b/httemplate/search/report_tax.html @@ -1,40 +1,35 @@ - - - Tax Report Criteria - - -

    Tax Report Criteria

    - - -
    - - <%= include( '/elements/tr-select-agent.html' ) %> - - <%= include( '/elements/tr-input-beginning_ending.html' ) %> - - <% my $conf = new FS::Conf; - if ( $conf->exists('enable_taxclasses') ) { - %> - - - - - <% } %> - - <% my @pkg_class = qsearch('pkg_class', {}); - if ( @pkg_class ) { - %> - - - - - <% } %> - -
    Show tax classes
    Show package classes
    - -
    -
    - - - +<%= include('/elements/header.html', 'Tax Report' ) %> +
    + + + + <%= include( '/elements/tr-select-agent.html' ) %> + + <%= include( '/elements/tr-input-beginning_ending.html' ) %> + + <% my $conf = new FS::Conf; + if ( $conf->exists('enable_taxclasses') ) { + %> + + + + + <% } %> + + <% my @pkg_class = qsearch('pkg_class', {}); + if ( @pkg_class ) { + %> + + + + + <% } %> + +
    Show tax classes
    Show package classes
    + +
    + +
    + +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/sqlradius.html b/httemplate/search/sqlradius.html index 8f4878dbc..645505101 100644 --- a/httemplate/search/sqlradius.html +++ b/httemplate/search/sqlradius.html @@ -1,9 +1,5 @@ -<%= include( '/elements/header.html', 'Search RADIUS sessions', '', '', ' - - - - -') %> +<%= include( '/elements/header.html', 'Search RADIUS sessions' ) %> +
    <% #include( '/elements/table.html' ) %> <%= ntable('#cccccc') %> @@ -47,48 +43,10 @@ <% } %> - - From: - - - - - - - - m/d/y - - - To: - - - - - - - - m/d/y -
    (leave one or both dates blank for an open-ended search) - - +<%= include( '/elements/tr-input-beginning_ending.html' ) %> +
    - - - +<%= include('/elements/footer.html') %> diff --git a/httemplate/search/svc_acct.html b/httemplate/search/svc_acct.html deleted file mode 100755 index c504c2f34..000000000 --- a/httemplate/search/svc_acct.html +++ /dev/null @@ -1,19 +0,0 @@ - - - Account Search - - - - Account Search - -

    -
    - Search for username: - - -

    - -

    - - - diff --git a/httemplate/search/svc_domain.cgi b/httemplate/search/svc_domain.cgi index f261ea9f3..b02eea8bd 100755 --- a/httemplate/search/svc_domain.cgi +++ b/httemplate/search/svc_domain.cgi @@ -61,7 +61,7 @@ my $link_cust = sub { $svc_x->custnum ? [ "${p}view/cust_main.cgi?", 'custnum' ] : ''; }; -%><%= include ('elements/search.html', +%><%= include( 'elements/search.html', 'title' => "Domain Search Results", 'name' => 'domains', 'query' => $sql_query, diff --git a/httemplate/search/svc_domain.html b/httemplate/search/svc_domain.html deleted file mode 100755 index b759102f4..000000000 --- a/httemplate/search/svc_domain.html +++ /dev/null @@ -1,19 +0,0 @@ - - - Domain Search - - - - Domain Search - -

    -
    - Search for domain: - - -

    - -

    - - - diff --git a/httemplate/search/svc_external.cgi b/httemplate/search/svc_external.cgi index 8dbb949c8..7968f3c43 100755 --- a/httemplate/search/svc_external.cgi +++ b/httemplate/search/svc_external.cgi @@ -38,17 +38,18 @@ if ( $query eq 'svcnum' ) { } if ( scalar(@svc_external) == 1 ) { - print $cgi->redirect(popurl(2). "view/svc_external.cgi?". $svc_external[0]->svcnum); - #exit; + + %><%= $cgi->redirect(popurl(2). "view/svc_external.cgi?". $svc_external[0]->svcnum) %><% + } elsif ( scalar(@svc_external) == 0 ) { -%> - -<% - eidiot "No matching external services found!\n"; -} else { -%> - -<%= include("/elements/header.html","External Search Results",'') %> + + %><%= include('/elements/header.html', 'External Search Results' ) %> + + No matching external services found + +<% } else { + + %><%= include('/elements/header.html', 'External Search Results', '') %> <%= scalar(@svc_external) %> matching external services found diff --git a/httemplate/view/cust_main/packages.html b/httemplate/view/cust_main/packages.html index ece1b62bb..32e0ee1fc 100755 --- a/httemplate/view/cust_main/packages.html +++ b/httemplate/view/cust_main/packages.html @@ -67,7 +67,7 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { - - + + + + <% foreach my $custnum ( @custnums ) { %> + <% my $cust_main = qsearchs('cust_main', { 'custnum' => $custnum } ); %> + <% next unless $cust_main; %> + + + + + + <% + if ( $bgcolor eq $bgcolor1 ) { + $bgcolor = $bgcolor2; + } else { + $bgcolor = $bgcolor1; + } + %> + + <% } %> + +
    > + > <%=$pkg->{pkgnum}%>: <%=$pkg->{pkg}%> - <%=$pkg->{comment}%>
    <% unless ($pkg->{cancel}) { %> @@ -75,7 +75,7 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { ( <%=pkg_dates_link($pkg)%> | <%=pkg_customize_link($pkg,$cust_main->custnum)%> ) <% } %>
    > + > <% diff --git a/httemplate/view/cust_main/payment_history.html b/httemplate/view/cust_main/payment_history.html index a0bec3906..f0cd993ff 100644 --- a/httemplate/view/cust_main/payment_history.html +++ b/httemplate/view/cust_main/payment_history.html @@ -58,7 +58,10 @@ <% } %> -
    Post credit +
    + +Post credit +
    <% @@ -115,8 +118,10 @@ foreach my $cust_pay ($cust_main->cust_pay) { #completely unapplied $pre = 'Unapplied '; $post = ''; - $apply = qq! (apply)'; + $apply = qq! (apply)!; + } elsif ( scalar(@cust_bill_pay) == 1 && scalar(@cust_pay_refund) == 0 && $cust_pay->unapplied == 0 ) { @@ -151,8 +156,9 @@ foreach my $cust_pay ($cust_main->cust_pay) { $desc .= '  '. '$'. $cust_pay->unapplied. ' unapplied'. - qq! (apply)'. + qq! (apply)!. '
    '; } } @@ -264,8 +270,9 @@ foreach my $cust_credit ($cust_main->cust_credit) { #completely unapplied $pre = 'Unapplied '; $post = ''; - $apply = qq! (apply)'; + $apply = qq! (apply)!; } elsif ( scalar(@cust_credit_bill) == 1 && scalar(@cust_credit_refund) == 0 && $cust_credit->credited == 0 ) { @@ -299,8 +306,9 @@ foreach my $cust_credit ($cust_main->cust_credit) { if ( $cust_credit->credited > 0 ) { $desc .= '  $'. $cust_credit->credited. ' unapplied'. - qq! (apply)'. + qq! (apply)!. '
    '; } } -- cgit v1.2.1 From 6d777ed1fafabab8c308c9ffa24f1dd48f33a9a5 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 15 May 2006 11:05:04 +0000 Subject: more ACL and re-skinning work, now with RT! --- httemplate/elements/freeside.css | 15 +++++++++++++++ httemplate/elements/header.html | 21 ++++++++++++++------- httemplate/elements/xmenu.css | 16 +++++++++++++--- httemplate/search/cust_main.cgi | 9 ++++++++- 4 files changed, 50 insertions(+), 11 deletions(-) create mode 100644 httemplate/elements/freeside.css (limited to 'httemplate') diff --git a/httemplate/elements/freeside.css b/httemplate/elements/freeside.css new file mode 100644 index 000000000..5908e6aab --- /dev/null +++ b/httemplate/elements/freeside.css @@ -0,0 +1,15 @@ +* { + font-family: Arial, Verdana, Helvetica, sans-serif; +} + +A:link IMG, A:visited { border-style: none } +A:focus {text-decoration: underline } + +a:link, a:visited { + /* text-decoration: none; */ + color: #000000; +} +/* a:hover { text-decoration: underline } */ + +/* a:focus { background-color: #ccccee } */ + diff --git a/httemplate/elements/header.html b/httemplate/elements/header.html index 49814577e..0eb5695ce 100644 --- a/httemplate/elements/header.html +++ b/httemplate/elements/header.html @@ -16,6 +16,7 @@ + <% tie my %report_menu, 'Tie::IxHash', @@ -183,10 +184,16 @@ + + @@ -200,7 +207,7 @@ freeside @@ -248,13 +255,13 @@ diff --git a/httemplate/elements/xmenu.css b/httemplate/elements/xmenu.css index 5bb8a0deb..60881b813 100644 --- a/httemplate/elements/xmenu.css +++ b/httemplate/elements/xmenu.css @@ -55,9 +55,14 @@ border: 1px solid white; } -.webfx-menu a:visited, -.webfx-menu a:visited:hover { +.webfx-menu a:visited { color: black; + border: 1px solid white; +} + +.webfx-menu a:hover { + color: black; + border: 1px solid #7e0079; } .webfx-menu a:hover { @@ -98,11 +103,12 @@ /* border: 1px solid #7E0079; */ /* border: 1px solid #000000; */ /* border: none */ + color: white; padding: 2px; font-family: Verdana, Helvetica, Sans-Serif; - font-size: 11px; + /* font-size: 11px; */ /* IE5.0 has the wierdest box model for inline elements */ padding: expression(constExpression(ie50 ? "0px" : "2px")); @@ -132,6 +138,10 @@ height: expression(constExpression(ie50 ? "17px" : "auto")); } +.webfx-menu-bar a:link { + color: white; +} + .webfx-menu-bar a:hover { /* color: black; */ color: white; diff --git a/httemplate/search/cust_main.cgi b/httemplate/search/cust_main.cgi index 8b70ff490..733e5dc15 100755 --- a/httemplate/search/cust_main.cgi +++ b/httemplate/search/cust_main.cgi @@ -186,6 +186,13 @@ if ( $cgi->param('browse') push @cust_main, @{&companysearch}; } + if ( $cgi->param('search_cust') ) { + $sortby = \*company_sort; + $orderby = "ORDER BY LOWER(company || ' ' || last || ' ' || first )"; + warn "smart searching for: ". $cgi->param('search_cust'); + push @cust_main, smart_search( 'search' => $cgi->param('search_cust') ); + } + @cust_main = grep { $_->ncancelled_pkgs || ! $_->all_pkgs } @cust_main if ! $cgi->param('cancelled') && ( @@ -313,7 +320,7 @@ END $conf->config('ticket_system-custom_priority_field-values'); } - print "

    ". $pager. &table(). <
    ". $pager. include('/elements/table-grid.html'). <
    -- cgit v1.2.1 From 64dc1bb0f70ccc0b828cc1d758cd82f040e0ec33 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 15 May 2006 13:57:15 +0000 Subject: move most of the crap on the "main menu" to the sidebar --- httemplate/elements/freeside.css | 2 +- httemplate/elements/header.html | 169 +--------------------- httemplate/elements/menu.html | 298 +++++++++++++++++++++++++++++++++++++++ httemplate/index.html | 204 +-------------------------- 4 files changed, 304 insertions(+), 369 deletions(-) create mode 100644 httemplate/elements/menu.html (limited to 'httemplate') diff --git a/httemplate/elements/freeside.css b/httemplate/elements/freeside.css index 5908e6aab..6f7cadb2e 100644 --- a/httemplate/elements/freeside.css +++ b/httemplate/elements/freeside.css @@ -3,7 +3,7 @@ } A:link IMG, A:visited { border-style: none } -A:focus {text-decoration: underline } +/* A:focus {text-decoration: underline } */ a:link, a:visited { /* text-decoration: none; */ diff --git a/httemplate/elements/header.html b/httemplate/elements/header.html index 0eb5695ce..2be2c7938 100644 --- a/httemplate/elements/header.html +++ b/httemplate/elements/header.html @@ -13,175 +13,8 @@ - - - - - <% - tie my %report_menu, 'Tie::IxHash', - 'Report one' => [ 'there', 'theretip' ], - 'Report too' => [ 'here', 'heretip' ], - ; - - tie my %config_employees, 'Tie::IxHash', - 'View/Edit employees' => [ $fsurl.'browse/access_user.html', 'Setup internal users' ], - 'View/Edit employee groups' => [ $fsurl.'browse/access_group.html', 'Employee groups allow you to control access to the backend' ], - ; - - tie my %config_export_svc_pkg, 'Tie::IxHash', - 'View/Edit exports' => [ $fsurl.'browse/part_export.cgi', 'Provisioning services to external machines, databases and APIs' ], - 'View/Edit service definitions' => [ $fsurl.'browse/part_svc.cgi', 'Services are items you offer to your customers' ], - 'View/Edit package definitions' => [ $fsurl.'browse/part_pkg.cgi', 'One or more services are grouped together into a package and given pricing information. Customers purchase packages, not services' ], - 'View/Edit package classes' => [ $fsurl.'browse/pkg_class.html', 'Package classes define groups of packages, for reporting and convenience purposes.' ], - ; - - tie my %config_agent, 'Tie::IxHash', - 'View/Edit agent types' => [ $fsurl.'browse/agent_type.cgi', 'Agent types define groups of package definitions that you can then assign to particular agents' ], - 'View/Edit agents' => [ $fsurl.'browse/agent.cgi', 'Agents are resellers of your service. Agents may be limited to a subset of your full offerings (via their type)' ], - ; - - tie my %config_billing, 'Tie::IxHash', - 'View/Edit payment gateways' => [ $fsurl.'browse/payment_gateway.html', 'Credit card and electronic check processors' ], - 'View/Edit invoice events' => [ $fsurl.'browse/part_bill_event.cgi', 'Actions for overdue invoices' ], - 'View/Edit prepaid cards' => [ $fsurl.'browse/prepay_credit.html', 'View outstanding cards, generate new cards' ], - 'View/Edit call rates and regions' => [ $fsurl.'browse/rate.cgi', 'Manage rate plans, regions and prefixes for VoIP and call billing' ], - 'View/Edit locales and tax rates' => [ $fsurl.'browse/cust_main_county.cgi', 'Change tax rates, or break down a country into states, or a state into counties and assign different tax rates to each' ], - ; - - tie my %config_dialup, 'Tie::IxHash', - 'View/Edit access numbers' => [ $fsurl.'browse/svc_acct_pop.cgi', 'Points of Presence' ], - ; - - tie my %config_broadband, 'Tie::IxHash', - 'View/Edit routers' => [ $fsurl.'browse/router.cgi', 'Broadband access routers' ], - '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_menu, 'Tie::IxHash', - 'Settings' => [ $fsurl.'config/config-view.cgi', 'XXXconfigittip' ], - 'separator' => '', #its a separator! - 'Employees' => [ \%config_employees, 'XXXtooltip' ], - 'Provisioning, services and packages' - => [ \%config_export_svc_pkg, 'XXXtootip' ], - 'Resellers' => [ \%config_agent, 'XXXtootip' ], - 'Billing' => [ \%config_billing, 'XXXtootip' ], - 'Dialup' => [ \%config_dialup, 'XXXtootip' ], - 'Fixed (username-less) broadband' - => [ \%config_broadband, 'XXXtootip' ], - 'Miscellaneous' => [ \%config_misc, 'XXXtootip' ], - ; - - tie my %menu, 'Tie::IxHash', - 'Home' => [ $fsurl, 'hometip', ], - 'Top item one' => [ 'nowhere_yet', 'nowheretip', ], - 'Top item too' => [ 'nowhere_yet_either', 'eithertip', ], - 'Reports' => [ \%report_menu, 'reportmenutip' ], - 'Configuration' => [ \%config_menu, 'configmenutip' ], - ; - - use vars qw($gmenunum); - $gmenunum = 0; - - sub submenu { - my($submenu, $title) = @_; - my $menunum = $gmenunum++; - - #return two args: html, menuname - - "var myMenu$menunum = new WebFXMenu;\n". - #"myMenu$menunum.useAutoPosition = true;\n". - "myMenu$menunum.emptyText = '$title';\n". - - ( - join("\n", map { - - if ( !ref( $submenu->{$_} ) ) { - - "myMenu$menunum.add(new WebFXMenuSeparator());"; - - } else { - - my($url_or_submenu, $tooltip ) = @{ $submenu->{$_} }; - if ( ref($url_or_submenu) ) { - - my($subhtml, $submenuname ) = submenu($url_or_submenu, $_); #mmm, recursion - - "$subhtml\n". - "myMenu$menunum.add(new WebFXMenuItem(\"$_\", null, \"$tooltip\", $submenuname ));"; - - } else { - - "myMenu$menunum.add(new WebFXMenuItem(\"$_\", \"$url_or_submenu\", \"$tooltip\" ));"; - - } - - } - - } keys %$submenu ) - ). "\n". - "myMenu$menunum.width = 224\n", - - "myMenu$menunum"; - - } - - %> - + <%= include('menu.html', 'freeside_baseurl' => $fsurl ) %> + + + + + diff --git a/httemplate/index.html b/httemplate/index.html index 33083f6e5..95d4580bd 100644 --- a/httemplate/index.html +++ b/httemplate/index.html @@ -4,72 +4,24 @@
    [ Sales / Customer service ] -<% if ( $conf->config('ticket_system') ) { %> - [ Support / Ticketing ] -<% } %> [ Bookkeeping / Collections ] [ Reports ] -[ Sysadmin ]
    - <%= $conf->config('company_name') %> Billing + <%= $conf->config('company_name') || 'ExampleCo' %> Logged in as <%= getotaker %> 
    Preferences 

    - +
    - +
    (bill) name
    Sales / Customer service
    -
    New Customer -
    -
    Customer # or all customers by customer number
    -
    Last name or all customers by last name
    -
    Company or all customers by company
    -<% if ( $conf->exists('address2-search') ) { %> -
    Unit
    -<% } %> -
    Phone #
    -
    Username or all accounts by username or uid
    -
    Domain or all domains
    -
    IP Address or all services by svcnum or address block
    -
    all mail forwards by svcnum
    -
    all virtual hosts by svcnum
    -
    all external services by svcnum
    +
    Username
    +
    Domain
    +
    IP Address




    -<% if ( $conf->config('ticket_system') ) { %> [ Sales / Customer service ] -[ Support / Ticketing ] -[ Bookkeeping / Collections ] -[ Reports ] -[ Sysadmin ] - - - -
    Support/Ticketing
    - <% if ( $conf->config('ticket_system') eq 'RT_Internal' ) { %> -
    Ticketing Main -

    - Reports -
    - -


    - -<% } %> - - -[ Sales / Customer service ] -<% if ( $conf->config('ticket_system') ) { %> - [ Support / Ticketing ] -<% } %> [ Bookkeeping / Collections ] [ Reports ] -[ Sysadmin ]
    Bookkeeping / Collections
    @@ -78,30 +30,12 @@
    Credit card #
    Invoice #
    Check #
    -
    View pending credit card batch

    Packages (by next bill date range) -

    Invoice reports - - Advanced invoice reports

    +
    Invoice event reports - Sales, Credits and Receipts Summary -

    Sales report (by agent, package class and/or date range) -

    Credit report (by employee and/or date range) -

    Payment report (by type and/or date range) -

    Accounts Receivable Aging Summary -

    Prepaid Income (Unearned Revenue) Report -

    Sales Tax Liability Report

    @@ -113,150 +47,20 @@ [ Sales / Customer service ] -<% if ( $conf->config('ticket_system') ) { %> - [ Support / Ticketing ] -<% } %> [ Bookkeeping / Collections ] [ Reports ] -[ Sysadmin ]
    Reports

    RADIUS sessions

    - Auditing pre-Freeside services with no customer record - - Packages - - Package definitions (by number of active packages)

    - Service definitions (by number of active services)

    - Customers - - Zip code distribution

    SQL query: SELECT

    - -


    - -[ Sales / Customer service ] -<% if ( $conf->config('ticket_system') ) { %> - [ Support / Ticketing ] -<% } %> -[ Bookkeeping / Collections ] -[ Reports ] -[ Sysadmin ] - - - -
    Sysadmin
    -
    - - - View pending job queue -
    Batch import customers from CSV file -
    Batch import charges from CSV file -
    Download database dump -



    - Configuration -

    - Employees - - Provisioning, services and packages - - Resellers -
      -
    • View/Edit agent types - - Agent types define groups of package definitions that you can - then assign to particular agents. -
    • View/Edit agents - - Agents are resellers of your service. Agents may be limited - to a subset of your full offerings (via their type). -
    - Billing - - Dialup - - Fixed (username-less) broadband - - Miscellaneous - -
    -
    -















    -















    -















    -















    -















    -















    -















    -















    - <%= include('/elements/footer.html') %> -- cgit v1.2.1 From 50f25b285b2caf77d267ed66f03e56924ad7229f Mon Sep 17 00:00:00 2001 From: jeff Date: Sat, 20 May 2006 20:06:30 +0000 Subject: first stab at BoM download --- httemplate/browse/cust_pay_batch.cgi | 6 +++- httemplate/docs/schema.html | 10 ++++-- httemplate/docs/upgrade10.html | 8 +++++ httemplate/misc/download-batch.cgi | 69 ++++++++++++++++++++++++++++++++++-- 4 files changed, 87 insertions(+), 6 deletions(-) (limited to 'httemplate') diff --git a/httemplate/browse/cust_pay_batch.cgi b/httemplate/browse/cust_pay_batch.cgi index 0f05ecb25..6ee983ab4 100755 --- a/httemplate/browse/cust_pay_batch.cgi +++ b/httemplate/browse/cust_pay_batch.cgi @@ -3,7 +3,9 @@
    Download batch in format


    @@ -11,7 +13,9 @@ Download batch in format
    Format

    @@ -47,7 +51,7 @@ $<%= sprintf("%.2f", $total) %> total in pending batch
    foreach my $cust_pay_batch ( sort { $a->paybatchnum <=> $b->paybatchnum } qsearch('cust_pay_batch', {} ) ) { - my $cardnum = $cust_pay_batch->cardnum; + my $cardnum = $cust_pay_batch->payinfo; #$cardnum =~ s/.{4}$/xxxx/; $cardnum = 'x'x(length($cardnum)-4). substr($cardnum,(length($cardnum)-4)); diff --git a/httemplate/docs/schema.html b/httemplate/docs/schema.html index cdb59a2e9..d9e35efc7 100644 --- a/httemplate/docs/schema.html +++ b/httemplate/docs/schema.html @@ -199,10 +199,16 @@
  • amount
  • _date -
  • cust_pay_batch - Pending batch +
  • pay_batch - Pending batch +
      +
    • batchnum +
    • status +
    +
  • cust_pay_batch - Pending batch members
    • paybatchnum -
    • cardnum +
    • batchnum +
    • payinfo - account number
    • exp - card expiration
    • amount
    • invnum - invoice diff --git a/httemplate/docs/upgrade10.html b/httemplate/docs/upgrade10.html index 7cd1d8e50..2a4b0d975 100644 --- a/httemplate/docs/upgrade10.html +++ b/httemplate/docs/upgrade10.html @@ -46,6 +46,14 @@ DROP INDEX cust_bill_pkg1;
       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;
       
      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. diff --git a/httemplate/misc/download-batch.cgi b/httemplate/misc/download-batch.cgi index 306ef5d63..5a98f1d51 100644 --- a/httemplate/misc/download-batch.cgi +++ b/httemplate/misc/download-batch.cgi @@ -1,16 +1,79 @@ <% +my $conf=new FS::Conf; + #http_header('Content-Type' => 'text/comma-separated-values' ); #IE chokes http_header('Content-Type' => 'text/plain' ); +#need default +my $formatconfig = "batchconfig".$cgi->param('format'); + +die "No batch configuration exists.\n$formatconfig\n" unless $conf->exists($formatconfig); +my $format = $conf->config($formatconfig); + +my $oldAutoCommit = $FS::UID::AutoCommit; +local $FS::UID::AutoCommit = 0; +my $dbh = dbh; + +my $pay_batch = qsearchs('pay_batch', {'status'=>''} ); +die "No pending batch. \n" unless $pay_batch; + +my %batchhash = $pay_batch->hash; +$batchhash{'status'} = 'I'; +my $new = new FS::pay_batch \%batchhash; +my $error = $new->replace($pay_batch); +die "error updating batch status: $error\n" if $error; + +my $batchtotal=0; +my $batchcount=0; + +my (@date)=localtime(); +my $jdate = sprintf("%03d", $date[5] % 100).sprintf("%03d", $date[7]); + +if ($format eq "BoM") { + my($reformat,$origid,$datacenter,$typecode,$shortname,$longname,$mybank,$myacct) = $conf->config('batchconfig'); + printf "A%10s%04u%06u%05u%54s\n",$origid,$pay_batch->batchnum,$jdate,$datacenter,""; + printf "XD%03u%06u%-15s%-30s%09u%-12s \n",$typecode,$jdate,$shortname,$longname,$mybank,$myacct; +}elsif ($format eq "CSV file for TD Canada Trust Merchant PC Batch"){ + 1; +}else{ + die "Unknown format for batch in batchconfig. \n"; +} + + for my $cust_pay_batch ( sort { $a->paybatchnum <=> $b->paybatchnum } - qsearch('cust_pay_batch', {} ) + qsearch('cust_pay_batch', + {'batchnum'=>$pay_batch->batchnum} ) ) { $cust_pay_batch->exp =~ /^\d{2}(\d{2})[\/\-](\d+)[\/\-]\d+$/; my( $mon, $y ) = ( $2, $1 ); $mon = "0$mon" if $mon < 10; my $exp = "$mon$y"; +$batchcount++; +$batchtotal += $cust_pay_batch->amount; + +if ($format eq "BoM") { + my( $account, $aba ) = split( '@', $cust_pay_batch->payinfo ); + printf "D%010u%09u%-12s%-29s%-19s\n",$cust_pay_batch->amount*100,$aba,$account,$cust_pay_batch->payname,$cust_pay_batch->invnum; +}elsif ($format eq "CSV file for TD Canada Trust Merchant PC Batch"){ +%>,,,,<%= $cust_pay_batch->payinfo %>,<%= $exp %>,<%= $cust_pay_batch->amount %>,<%= $cust_pay_batch->paybatchnum %> +<% }else{ + die "I'm already dead, but you did not know that.\n"; +} + +} + +if ($format eq "BoM") { + printf "YD%08u%014u%56s\n",$batchcount,$batchtotal*100,""; + printf "Z%014u%05u%014u%05u%41s\n",$batchtotal*100,$batchcount,"0","0",""; +}elsif ($format eq "CSV file for TD Canada Trust Merchant PC Batch"){ + 1; +} else{ + die "I'm already dead (again), but you did not know that.\n"; +} + +$dbh->commit or die $dbh->errstr if $oldAutoCommit; + +%> -%>,,,,<%= $cust_pay_batch->cardnum %>,<%= $exp %>,<%= $cust_pay_batch->amount %>,<%= $cust_pay_batch->paybatchnum %> -<% } %> -- cgit v1.2.1 From e631aea6e8c9dbc41192948468314afd7b806613 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 22 May 2006 00:45:37 +0000 Subject: 1.7.0? why not! --- httemplate/elements/menu.html | 19 +++---- httemplate/index.html | 117 ++++++++++++++++++++---------------------- 2 files changed, 65 insertions(+), 71 deletions(-) (limited to 'httemplate') diff --git a/httemplate/elements/menu.html b/httemplate/elements/menu.html index 8502c0746..29ef53575 100644 --- a/httemplate/elements/menu.html +++ b/httemplate/elements/menu.html @@ -121,6 +121,7 @@ #
      --> 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' ], @@ -168,17 +169,17 @@ ; tie my %config_menu, 'Tie::IxHash', - 'Settings' => [ $fsurl.'config/config-view.cgi', 'XXXconfigittip' ], + 'Settings' => [ $fsurl.'config/config-view.cgi', '' ], 'separator' => '', #its a separator! - 'Employees' => [ \%config_employees, 'XXXtooltip' ], + 'Employees' => [ \%config_employees, '' ], 'Provisioning, services and packages' - => [ \%config_export_svc_pkg, 'XXXtootip' ], - 'Resellers' => [ \%config_agent, 'XXXtootip' ], - 'Billing' => [ \%config_billing, 'XXXtootip' ], - 'Dialup' => [ \%config_dialup, 'XXXtootip' ], + => [ \%config_export_svc_pkg, '' ], + 'Resellers' => [ \%config_agent, '' ], + 'Billing' => [ \%config_billing, '' ], + 'Dialup' => [ \%config_dialup, '' ], 'Fixed (username-less) broadband' - => [ \%config_broadband, 'XXXtootip' ], - 'Miscellaneous' => [ \%config_misc, 'XXXtootip' ], + => [ \%config_broadband, '' ], + 'Miscellaneous' => [ \%config_misc, '' ], ; tie my %menu, 'Tie::IxHash', @@ -253,7 +254,7 @@ webfxMenuImagePath = "<%=$fsurl%>images/"; webfxMenuUseHover = 1; webfxMenuShowTime = 300; - webfxMenuHideTime = 500; + webfxMenuHideTime = 300; var myBar = new WebFXMenuBar; diff --git a/httemplate/index.html b/httemplate/index.html index 95d4580bd..1a92b45f6 100644 --- a/httemplate/index.html +++ b/httemplate/index.html @@ -1,66 +1,59 @@ <% my $conf = new FS::Conf; %> -<%= include('/elements/header.html', 'Freeside Main Menu' ) %> - -
      - -[ Sales / Customer service ] -[ Bookkeeping / Collections ] -[ Reports ] - - - -
      Sales / Customer service
      -
      Username
      -
      Domain
      -
      IP Address
      -
      -
      - -


      - - -[ Sales / Customer service ] -[ Bookkeeping / Collections ] -[ Reports ] - - - -
      Bookkeeping / Collections
      -
      Quick payment entry -
      -
      Credit card #
      -
      Invoice #
      -
      Check #
      -
      - Invoice event reports - -

      -
      - - - -


      - - - -[ Sales / Customer service ] -[ Bookkeeping / Collections ] -[ Reports ] - - - -
      Reports
      -
      - RADIUS sessions

      -
      SQL query: SELECT
      - -
      -
      - -


      +<%= include('/elements/header.html', 'Billing Main' ) %> + +<% + + my $sth = dbh->prepare( + #"SELECT DISTINCT custnum FROM h_cust_main JOIN cust_main USING ( custnum ) + "SELECT custnum FROM h_cust_main JOIN cust_main USING ( custnum ) + WHERE ( history_action = 'insert' OR history_action = 'replace_new' ) + AND history_user = ? + ORDER BY history_date desc" # LIMIT 10 + ) or die dbh->errstr; + + $sth->execute( getotaker() ) or die $sth->errstr; + + my %saw = (); + my @custnums = grep { !$saw{$_}++ } map $_->[0], @{ $sth->fetchall_arrayref }; + + @custnums = splice(@custnums, 0, 10); + + if ( @custnums ) { + +%> + + <%= include('/elements/table-grid.html') %> + + <% my $bgcolor1 = '#eeeeee'; + my $bgcolor2 = '#ffffff'; + my $bgcolor; + %> + +
  • Customers I recently added or modified
    <%= $custnum %>: <%= $cust_main->name %>
    + +<% } %> <%= include('/elements/footer.html') %> -- cgit v1.2.1 From 3a820c27d5290f9d2761636b2b4fe865caeb0804 Mon Sep 17 00:00:00 2001 From: ivan Date: Fri, 2 Jun 2006 13:20:24 +0000 Subject: add a service search --- httemplate/elements/header.html | 19 +++++++++++++------ httemplate/search/svc_Smart.html | 22 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 httemplate/search/svc_Smart.html (limited to 'httemplate') diff --git a/httemplate/elements/header.html b/httemplate/elements/header.html index 2be2c7938..3aa81be3b 100644 --- a/httemplate/elements/header.html +++ b/httemplate/elements/header.html @@ -21,9 +21,12 @@ if ( what.value = '(cust #, name or company)' ) what.value = ''; } - - @@ -60,37 +67,36 @@ var confirm_cancel = '
    Cancel this customer | +<% } %> - | Cancel this customer +<% if ( $conf->exists('deletecustomers') + && $curuser->access_right('Delete customer') + ) { +%> + Delete this customer | <% } %> -<% -print qq! | !. - 'Delete this customer' - if $conf->exists('deletecustomers'); +<% unless ( $conf->exists('disable_customer_referrals') ) { %> + Refer a new customer | + View this customer's referrals +<% } %> -unless ( $conf->exists('disable_customer_referrals') ) { - print qq! | !, - qq!Refer a new customer!; - print qq! | !, - qq!View this customer's referrals!; -} - -print '

    '; +

    +<% my $signupurl = $conf->config('signupurl'); if ( $signupurl ) { -print "This customer's signup URL: ". - "$signupurl?ref=$custnum

    "; -} - %> + This customer's signup URL: <%= $signupurl %>?ref=<%= $custnum %>

    +<% } %> @@ -135,5 +141,4 @@ Comments <%= include('cust_main/payment_history.html', $cust_main ) %> <% } %> - - +<%= include('/elements/footer.html') %> diff --git a/httemplate/view/cust_main/packages.html b/httemplate/view/cust_main/packages.html index 32e0ee1fc..8312a8663 100755 --- a/httemplate/view/cust_main/packages.html +++ b/httemplate/view/cust_main/packages.html @@ -2,6 +2,8 @@ my( $cust_main ) = @_; my $conf = new FS::Conf; + my $curuser = $FS::CurrentUser::CurrentUser; + my $packages = get_packages($cust_main, $conf); %> @@ -11,13 +13,21 @@ Packages -<%= 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 ) %> <% } %> -Bulk order and cancel packages (preserves services) +<% if ( $curuser->access_right('Bulk change customer packages') ) { %> + Bulk order and cancel packages (preserves services) +<% } %> +

    <% if ( @$packages ) { %> @@ -70,10 +80,19 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) {
    > <%=$pkg->{pkgnum}%>: <%=$pkg->{pkg}%> - <%=$pkg->{comment}%>
    -<% unless ($pkg->{cancel}) { %> - ( <%=pkg_change_link($pkg)%> ) - ( <%=pkg_dates_link($pkg)%> | <%=pkg_customize_link($pkg,$cust_main->custnum)%> ) -<% } %> + + <% 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)%> ) + <% } %> + <% } %> +
    > @@ -182,7 +201,16 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { <% } %> - + <% } else { %> @@ -196,7 +224,13 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { - + <% } else { %> @@ -258,7 +292,19 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { <% if ( $pkg->{freq} ) { %> - + <% } %> @@ -278,14 +324,20 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { print '' if ($cnt > 0); %> - + <% $cnt++; } - if ($svcpart->{count} < $svcpart->{quantity}) { + if ( $svcpart->{count} < $svcpart->{quantity} + && $curuser->access_right('Provision customer services') + ) { print qq!\n! if ($cnt > 0); - print qq! \n\n!; + print qq! \n\n!; } } } @@ -393,7 +445,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 +463,10 @@ sub svc_provision_link { my $link = qq!!. "Provision $svc_nbsp ($num_left)"; - if ( $conf->exists('legacy_link') ) { + if ( $conf->exists('legacy_link') + && $curuser->access_right('View/link unlinked services') + ) + { $link .= '
    '. qq!!. @@ -475,7 +530,11 @@ sub pkg_cancel_link { my $pkg = shift or return ''; qq!!. - qq!Cancel now | !. + qq!Cancel now!; +} + +sub pkg_expire_link { + my $pkg = shift or return ''; qq!Cancel later!; } diff --git a/httemplate/view/cust_main/payment_history.html b/httemplate/view/cust_main/payment_history.html index f0cd993ff..b7621d57a 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,42 +18,48 @@

    Payment History
    -<% if ( $payby{'BILL'} ) { %> +<% if ( $payby{'BILL'} && $curuser->access_right('Post payment') ) { %> <%= $s++ ? ' | ' : '' %> Post check payment <% } %> -<% if ( $payby{'CASH'} ) { %> +<% if ( $payby{'CASH'} && $curuser->access_right('Post payment') ) { %> <%= $s++ ? ' | ' : '' %> Post cash payment <% } %> -<% if ( $payby{'WEST'} ) { %> +<% if ( $payby{'WEST'} && $curuser->access_right('Post payment') ) { %> <%= $s++ ? ' | ' : '' %> Post Western Union payment <% } %> -<% if ( $payby{'CARD'} || $payby{'DCRD'} ) { %> +<% if ( ( $payby{'CARD'} || $payby{'DCRD'} ) + && $curuser->access_right('Process payment') + ) { +%> <%= $s++ ? ' | ' : '' %> Process credit card payment <% } %> -<% if ( $payby{'CHEK'} || $payby{'DCHK'} ) { %> +<% if ( ( $payby{'CHEK'} || $payby{'DCHK'} ) + && $curuser->access_right('Process payment') + ) { +%> <%= $s++ ? ' | ' : '' %> Process electronic check (ACH) payment <% } %> -<% if ( $payby{'MCRD'} ) { %> +<% if ( $payby{'MCRD'} && $curuser->access_right('Post payment') ) { %> <%= $s++ ? ' | ' : '' %> Post manual credit card payment @@ -60,9 +68,13 @@
    -Post credit +<% if ( $curuser->access_right('Post credit') ) { %> -
    + Post credit + +
    + +<% } %> <% #get payment history @@ -75,11 +87,14 @@ foreach my $cust_bill ($cust_main->cust_bill) { : ''; my $post = ( $cust_bill->owed > 0 ) ? '' : ''; my $invnum = $cust_bill->invnum; + my $link = $curuser->access_right('View invoices') + ? qq!! + : ''; push @history, { 'date' => $cust_bill->_date, - 'desc' => qq!!. $pre. + 'desc' => $link. $pre. "Invoice #$invnum (Balance \$". $cust_bill->owed. ')'. - $post. '', + $post. ( $link ? '' : '' ), 'charge' => $cust_bill->charged, }; } @@ -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! (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' + && $conf->exists('cc-void') + && $curuser->acccess_right('Credit card void') + ) + || ( $cust_pay->payby eq 'CHEK' + && $conf->exists('echeck-void') + && $curuser->acccess_right('Echeck void') + ) + ) + ) + { $void = qq! (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! (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! (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 + && $conf->exists('unvoid') + && $curuser->access_right('Unvoid') + ) + { $unvoid = qq! (cust_credit) { } # my $delete = ''; - if ( $cust_credit->closed !~ /^Y/i && $conf->exists('deletecredits') ) { + if ( $cust_credit->closed !~ /^Y/i + && $conf->exists('deletecredits') + && $curuser->access_right('Delete credit') + ) + { $delete = qq! (!. @@ -324,7 +363,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! (!. -- cgit v1.2.1 From b5c26536197f16a3e1ea47c14c94884312c7fd24 Mon Sep 17 00:00:00 2001 From: ivan Date: Mon, 19 Jun 2006 13:09:14 +0000 Subject: fix ACL name for service provisioning and prevent disabled service provisioning from messing up table formatting --- httemplate/view/cust_main/packages.html | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'httemplate') diff --git a/httemplate/view/cust_main/packages.html b/httemplate/view/cust_main/packages.html index 8312a8663..beb67f325 100755 --- a/httemplate/view/cust_main/packages.html +++ b/httemplate/view/cust_main/packages.html @@ -333,12 +333,18 @@ foreach my $pkg (sort pkgsort_pkgnum_cancel @$packages) { <% $cnt++; } - if ( $svcpart->{count} < $svcpart->{quantity} - && $curuser->access_right('Provision customer services') - ) { - print qq!\n! if ($cnt > 0); - print qq! \n\n!; + if ( $svcpart->{count} < $svcpart->{quantity} ) { + print '' if ($cnt > 0); + if ( $curuser->access_right('Provision customer service') ) { + print ''; + } else { + #print ''; + print ''; + } } + } } #end display packages -- cgit v1.2.1 From 6c472b9d7eb5d64026baf188623cc133416253f6 Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 21 Jun 2006 08:42:18 +0000 Subject: speed up the agent type report when there are lots of package definitions --- httemplate/browse/agent_type.cgi | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'httemplate') 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 ]; }; -- cgit v1.2.1 From 262da96c9a051046a22182d0b19e8126623d2207 Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 21 Jun 2006 12:56:23 +0000 Subject: add overlib iframe function --- httemplate/elements/iframecontentmws.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 httemplate/elements/iframecontentmws.js (limited to 'httemplate') diff --git a/httemplate/elements/iframecontentmws.js b/httemplate/elements/iframecontentmws.js new file mode 100644 index 000000000..9df9cf681 --- /dev/null +++ b/httemplate/elements/iframecontentmws.js @@ -0,0 +1,21 @@ +/* + 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) { + alert(src); + return (''); +} -- cgit v1.2.1 From 3f19b759d4cb69bdf92e18b77a4c810d76d1b38d Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 21 Jun 2006 12:57:36 +0000 Subject: adding a header element for popups to replace CGI::header --- httemplate/elements/header-popup.html | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 httemplate/elements/header-popup.html (limited to 'httemplate') 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 section + my $conf = new FS::Conf; +%> + + + + + <%= $title %> + + + + + <%= $head %> + + > + +
    <%= $title %>
    +
    +
    -- cgit v1.2.1 From 265a8a9728e907ccee97ed395e6eca3014deb890 Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 21 Jun 2006 12:58:43 +0000 Subject: need the OLiframecontent sub --- httemplate/view/cust_main.cgi | 1 + 1 file changed, 1 insertion(+) (limited to 'httemplate') diff --git a/httemplate/view/cust_main.cgi b/httemplate/view/cust_main.cgi index e7b3319c7..89ddc38f2 100755 --- a/httemplate/view/cust_main.cgi +++ b/httemplate/view/cust_main.cgi @@ -40,6 +40,7 @@ die "Customer not found!" unless $cust_main; + ', + ); + } - if($vfields{$layer}->{$field}) { - $html .= qq!
    Excluded "; + $html .= qq!
    \n"; - } + + } #foreach my $field (@fields) { + $part_svc->svcpart('') if $clone; #undone $html .= "
    >( <%= pkg_unsuspend_link($pkg) %> | <%= pkg_cancel_link($pkg) %> )> + + <% if ( $curuser->access_right('Unsuspend customer package') ) { %> + ( <%= pkg_unsuspend_link($pkg) %> ) + <% } %> + <% if ( $curuser->access_right('Cancel customer package') ) { %> + ( <%= pkg_cancel_link($pkg) %> ) + <% } %> + +
    >( <%= pkg_cancel_link($pkg) %> )> + + <% if ( $curuser->access_right('Cancel customer package immediately') ) { %> + ( <%= pkg_cancel_link($pkg) %> ) + <% } %> + +
    >( <%= pkg_suspend_link($pkg) %> | <%= pkg_cancel_link($pkg) %> )> + + <% 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) %> ) + <% } %> + +
    <%=svc_link($svcpart,$service)%><%=svc_label_link($svcpart,$service)%>
    ( <%=svc_unprovision_link($service)%> )
    <%=svc_label_link($svcpart,$service)%> + <% if ( $curuser->access_right('Unprovision customer service') ) { %> +
    ( <%=svc_unprovision_link($service)%> ) + <% } %> +
    !.svc_provision_link($pkg, $svcpart, $conf).qq!
    !.svc_provision_link($pkg, $svcpart, $conf, $curuser).qq!
    !.svc_provision_link($pkg, $svcpart, $conf, $curuser).qq!
    '. + svc_provision_link($pkg, $svcpart, $conf, $curuser). + '
     
    !; + + 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!'; + + $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!'; + + } 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!!; + + } else { + + $html .= 'unknown type'. $def->{type}; + } + $html .= "
    "; diff --git a/httemplate/elements/select-table.html b/httemplate/elements/select-table.html index 6c8089b31..36eb4e211 100644 --- a/httemplate/elements/select-table.html +++ b/httemplate/elements/select-table.html @@ -8,11 +8,15 @@ # 'value' => 'current_value', # ##opt - # '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 + # '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 + # # + +
    CELLPADDING=<%= $opt{cellpadding} %> BORDER=1 BORDERCOLOR="#000000" STYLE="border: solid 1px black; empty-cells: show"> -- cgit v1.2.1 From 3a68d152457d4656ccaa41246e52b8584b000e19 Mon Sep 17 00:00:00 2001 From: ivan Date: Tue, 27 Jun 2006 14:19:16 +0000 Subject: going to wikiland --- httemplate/docs/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'httemplate') diff --git a/httemplate/docs/index.html b/httemplate/docs/index.html index bec62e34a..1693b6d9b 100644 --- a/httemplate/docs/index.html +++ b/httemplate/docs/index.html @@ -6,7 +6,7 @@

    Installation and upgrades

      -
    • New Installation +
    • New Installation
    • Installing integrated RT ticketing
    • Upgrading from 1.4.0 to 1.4.1
    • Upgrading from 1.4.1 to 1.4.2 -- cgit v1.2.1 From 947c955be56140c4a10b16345c1b15c44b02070a Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 29 Jun 2006 13:47:44 +0000 Subject: finish at least the automatic provisioning part --- httemplate/browse/inventory_class.html | 2 +- httemplate/edit/part_svc.cgi | 7 ++-- httemplate/edit/svc_acct.cgi | 21 ++++-------- httemplate/edit/svc_broadband.cgi | 9 +---- httemplate/edit/svc_domain.cgi | 9 +---- httemplate/edit/svc_external.cgi | 9 +---- httemplate/edit/svc_forward.cgi | 9 +---- httemplate/edit/svc_www.cgi | 9 +---- httemplate/search/inventory_item.html | 62 ++++++++++++++++++++++++++++++++-- 9 files changed, 75 insertions(+), 62 deletions(-) (limited to 'httemplate') 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/edit/part_svc.cgi b/httemplate/edit/part_svc.cgi index 77011e9dd..0298a5461 100755 --- a/httemplate/edit/part_svc.cgi +++ b/httemplate/edit/part_svc.cgi @@ -179,9 +179,10 @@ my %defs = ( 'condition' => sub { ref($_[0]) && $_[0]->{disable_fixed} }, }, - 'M' => { 'desc' => 'Manual selection from inventory', - 'condition' => $inv_sub, - }, +# 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, }, diff --git a/httemplate/edit/svc_acct.cgi b/httemplate/edit/svc_acct.cgi index 1e87c67ad..4b324a501 100755 --- a/httemplate/edit/svc_acct.cgi +++ b/httemplate/edit/svc_acct.cgi @@ -68,18 +68,9 @@ 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( { + 'usergroup' => sub { @groups = split(',', shift ); }, + } ); } @@ -274,7 +265,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 +367,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]$/ ) { %> @@ -396,7 +387,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]$/ ) { %> 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_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/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() ), ], ) -- cgit v1.2.1 From daaad950e1a8314eddf59a1c7d1b77c355362dc0 Mon Sep 17 00:00:00 2001 From: ivan Date: Thu, 29 Jun 2006 15:19:59 +0000 Subject: percentage late fees too --- httemplate/edit/part_bill_event.cgi | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'httemplate') 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 '. '
      Reason ', 'weight' => 10, }, + 'fee_percent' => { + 'name' => 'Late fee (percentage)', + 'code' => '$cust_main->charge( sprintf(\'%.2f\', $cust_bill->owed * %%%percent%%% / 100 ), \'%%%reason%%%\' );', + 'html' => + 'Percent %'. + '
      Reason ', + 'weight' => 10, + }, 'suspend' => { 'name' => 'Suspend', 'code' => '$cust_main->suspend();', -- cgit v1.2.1 From 1053db7f76169cbbc87840539959a4c362aff242 Mon Sep 17 00:00:00 2001 From: ivan Date: Wed, 12 Jul 2006 00:20:23 +0000 Subject: svc_phone service and CDR billing from imported CDRs --- httemplate/edit/elements/edit.html | 68 +++++++++---- httemplate/edit/elements/svc_Common.html | 98 +++++++++++++++++++ httemplate/edit/part_svc.cgi | 25 ++++- httemplate/edit/process/elements/process.html | 15 ++- httemplate/edit/process/elements/svc_Common.html | 14 +++ httemplate/edit/process/svc_phone.html | 4 + httemplate/edit/svc_phone.cgi | 11 +++ httemplate/elements/menu.html | 22 ++++- httemplate/misc/cdr-import.html | 3 +- httemplate/search/cdr.html | 6 +- httemplate/search/report_cdr.html | 2 +- httemplate/search/svc_phone.cgi | 94 ++++++++++++++++++ httemplate/view/elements/svc_Common.html | 116 +++++++++++++++++++++++ httemplate/view/svc_phone.cgi | 10 ++ 14 files changed, 456 insertions(+), 32 deletions(-) create mode 100644 httemplate/edit/elements/svc_Common.html create mode 100644 httemplate/edit/process/elements/svc_Common.html create mode 100644 httemplate/edit/process/svc_phone.html create mode 100644 httemplate/edit/svc_phone.cgi create mode 100644 httemplate/search/svc_phone.cgi create mode 100644 httemplate/view/elements/svc_Common.html create mode 100644 httemplate/view/svc_phone.cgi (limited to 'httemplate') diff --git a/httemplate/edit/elements/edit.html b/httemplate/edit/elements/edit.html index 6fa2b3b6e..f79cc0b24 100644 --- a/httemplate/edit/elements/edit.html +++ b/httemplate/edit/elements/edit.html @@ -9,25 +9,35 @@ # '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 + # }, # ] # # 'menubar' => '', #menubar arrayref # # #run when re-displaying with an error - # 'error_callback' => sub { my $cgi, $object = @_; }, + # 'error_callback' => sub { my( $cgi, $object ) = @_; }, # # #run when editing - # 'edit_callback' => sub { my $cgi, $object = @_; }, + # '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 = @_; }, + # 'new_callback' => sub { my( $cgi, $object ) = @_; }, + # + # #XXX describe + # 'field_callback' => sub { }, # - # #uninmplemented - # #'html_table_bottom' => '', #string or listref of additinal HTML to - # # #add before
    + # #string or coderef of additional HTML to add before
    + # 'html_table_bottom' => '', # # 'viewall_dir' => '', #'search' or 'browse', defaults to 'search' # @@ -64,13 +74,19 @@ 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'}; @@ -113,16 +129,15 @@ <%= ntable("#cccccc",2) %> -<% foreach my $f ( @$fields ) { +<% foreach my $f ( map { ref($_) ? $_ : {'field'=>$_} } + @$fields + ) { - my( $field, $type); - if ( ref($f) ) { - $field = $f->{'field'}, - $type = $f->{'type'} || 'text', - } else { - $field = $f; - $type = 'text'; - } + &{ $opt{'field_callback'} }( $f ) + if $opt{'field_callback'}; + + my $field = $f->{'field'}; + my $type = $f->{'type'} ||= 'text'; %> @@ -137,16 +152,29 @@ <% #eventually more options for - + <%= $f->{'value'} %> + + + <% } else { %> + + + + + + <% } %> <% } %> +<%= ref( $opt{'html_table_bottom'} ) + ? &{ $opt{'html_table_bottom'} }( $object ) + : $opt{'html_table_bottom'} +%> + <%= 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!!. + qq!!; + }, + + 'debug' => 1, + + %opt #pass through/override params + ) +%> diff --git a/httemplate/edit/part_svc.cgi b/httemplate/edit/part_svc.cgi index 0298a5461..489a2339c 100755 --- a/httemplate/edit/part_svc.cgi +++ b/httemplate/edit/part_svc.cgi @@ -39,11 +39,12 @@ Disable new orders
    Service definitions are the templates for items you offer to your customers. -