diff options
Diffstat (limited to 'httemplate')
-rw-r--r-- | httemplate/graph/money_time.cgi | 58 | ||||
-rw-r--r-- | httemplate/search/cust_bill_pay.html | 131 | ||||
-rwxr-xr-x | httemplate/search/cust_credit.html | 16 | ||||
-rw-r--r-- | httemplate/search/cust_credit_refund.html | 130 | ||||
-rwxr-xr-x | httemplate/search/cust_pay.cgi | 255 | ||||
-rw-r--r-- | httemplate/search/cust_refund.html | 7 | ||||
-rwxr-xr-x | httemplate/search/elements/cust_pay_or_refund.html | 258 |
7 files changed, 579 insertions, 276 deletions
diff --git a/httemplate/graph/money_time.cgi b/httemplate/graph/money_time.cgi index b996380b6..fbc31c068 100644 --- a/httemplate/graph/money_time.cgi +++ b/httemplate/graph/money_time.cgi @@ -25,27 +25,40 @@ if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { my $agentname = $agent ? $agent->agent.' ' : ''; -my @items = qw( invoiced netsales credits netcredits payments receipts ); +my @items = qw( invoiced netsales + credits netcredits + payments receipts + refunds netrefunds + cashflow netcashflow + ); if ( $cgi->param('12mo') == 1 ) { @items = map $_.'_12mo', @items; } my %label = ( - 'invoiced' => 'Gross Sales', - 'netsales' => 'Net Sales', - 'credits' => 'Gross Credits', - 'netcredits' => 'Net Credits', - 'payments' => 'Gross Receipts', - 'receipts' => 'Net Receipts', + 'invoiced' => 'Gross Sales', + 'netsales' => 'Net Sales', + 'credits' => 'Gross Credits', + 'netcredits' => 'Net Credits', + 'payments' => 'Gross Receipts', + 'receipts' => 'Net Receipts', + 'refunds' => 'Gross Refunds', + 'netrefunds' => 'Net Refunds', + 'cashflow' => 'Gross Cashflow', + 'netcashflow' => 'Net Cashflow', ); my %graph_suffix = ( - 'invoiced' => ' (invoiced)', - 'netsales' => ' (invoiced - applied credits)', - 'credits' => ' (credited)', - 'netcredits' => ' (applied credits)', - 'payments' => ' (payments)', - 'receipts' => '/Cashflow (payments - refunds)', + 'invoiced' => ' (invoiced)', + 'netsales' => ' (invoiced - applied credits)', + 'credits' => ' (credited)', + 'netcredits' => ' (applied credits)', + 'payments' => ' (payments)', + 'receipts' => ' (applied payments)', + 'refunds' => ' (refunds)', + 'netrefunds' => ' (applied refunds)', + 'cashflow' => ' (payments - refunds)', + 'netcashflow' => ' (applied payments - applied refunds)', ); my %graph_label = map { $_ => $label{$_}.$graph_suffix{$_} } keys %label; @@ -56,12 +69,16 @@ $graph_label{$_.'_12mo'} = $graph_label{$_}. " (previous 12 months)" foreach keys %graph_label; my %color = ( - 'invoiced' => '9999ff', #light blue - 'netsales' => '0000cc', #blue - 'credits' => 'ff9999', #light red - 'netcredits' => 'cc0000', #red - 'payments' => '99cc99', #light green - 'receipts' => '00cc00', #green + 'invoiced' => '9999ff', #light blue + 'netsales' => '0000cc', #blue + 'credits' => 'ff9999', #light red + 'netcredits' => 'cc0000', #red + 'payments' => '99cc99', #light green + 'receipts' => '00cc00', #green + 'refunds' => 'ffcc99', #light orange + 'netrefunds' => 'ff9900', #orange + 'cashflow' => '99cc33', #light olive + 'netcashflow' => '339900', #olive ); $color{$_.'_12mo'} = $color{$_} foreach keys %color; @@ -72,6 +89,9 @@ my %link = ( 'credits' => "${p}search/cust_credit.html?agentnum=$agentnum;", 'netcredits' => "${p}search/cust_credit_bill.html?agentnum=$agentnum;", 'payments' => "${p}search/cust_pay.cgi?magic=_date;agentnum=$agentnum;", + 'receipts' => "${p}search/cust_bill_pay.html?agentnum=$agentnum;", + 'refunds' => "${p}search/cust_refund.html?magic=_date;agentnum=$agentnum;", + 'netrefunds' => "${p}search/cust_credit_refund.html?agentnum=$agentnum;", ); # XXX link 12mo? diff --git a/httemplate/search/cust_bill_pay.html b/httemplate/search/cust_bill_pay.html new file mode 100644 index 000000000..3c390e706 --- /dev/null +++ b/httemplate/search/cust_bill_pay.html @@ -0,0 +1,131 @@ +<% include( 'elements/search.html', + 'title' => $title, + 'name' => 'net payments', + 'query' => $sql_query, + 'count_query' => $count_query, + 'count_addl' => [ '$%.2f total paid (net)', ], + 'header' => [ 'Net applied', + 'to Invoice', + 'Payment', + 'By', + FS::UI::Web::cust_header(), + ], + 'fields' => [ + sub { $money_char. sprintf('%.2f', shift->amount ) }, + sub { my $cbp = shift; + '#'.$cbp->invnum. ' '. + time2str('%b %d %Y', $cbp->cust_bill_date ). + " ($money_char". + sprintf('%.2f', $cbp->cust_bill_amount). + ")" + }, + sub { my $cbp = shift; + $cbp->cust_pay->payby_payinfo_pretty. ' '. + time2str('%b %d %Y', $cbp->_date ). + " ($money_char". + sprintf('%.2f', $cbp->cust_pay_paid ). + ")" + }, + sub { shift->cust_pay->otaker }, + \&FS::UI::Web::cust_fields, + ], + 'align' => 'rrrl'.FS::UI::Web::cust_aligns(), + 'links' => [ + '', + $cust_bill_link, + $cust_pay_link, + '', + ( map { $_ ne 'Cust. Status' ? $cust_link : '' } + FS::UI::Web::cust_header() + ), + ], + 'color' => [ + '', + '', + '', + '', + FS::UI::Web::cust_colors(), + ], + 'style' => [ + '', + '', + '', + '', + FS::UI::Web::cust_styles(), + ], + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Financial reports'); + +my $conf = new FS::Conf; +my $money_char = $conf->config('money_char') || '$'; + +my $title = 'Net Payment Search Results'; + +my @search = (); + +if ( $cgi->param('agentnum') && $cgi->param('agentnum') =~ /^(\d+)$/ ) { + push @search, "agentnum = $1"; + my $agent = qsearchs('agent', { 'agentnum' => $1 } ); + die "unknown agentnum $1" unless $agent; + $title = $agent->agent. " $title"; +} + +my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi); +push @search, "cust_bill._date >= $beginning ", + "cust_bill._date <= $ending"; + +#here is the agent virtualization +push @search, $FS::CurrentUser::CurrentUser->agentnums_sql; + +my $where = 'WHERE '. join(' AND ', @search); +# +my $count_query = 'SELECT COUNT(*), SUM(amount) + FROM cust_bill_pay + LEFT JOIN cust_bill USING ( invnum ) + LEFT JOIN cust_main USING ( custnum ) '. + $where; + +my $sql_query = { + 'table' => 'cust_bill_pay', + 'select' => join(', ', + 'cust_bill_pay.*', + 'cust_pay.paid AS cust_pay_paid', + 'cust_bill._date AS cust_bill_date', + #'cust_bill.charged AS cust_bill_charged', + 'cust_pay.custnum AS custnum', + 'cust_main.custnum AS cust_main_custnum', + FS::UI::Web::cust_sql_fields(), + ), + 'hashref' => {}, + 'extra_sql' => $where, + 'addl_from' => 'LEFT JOIN cust_bill USING ( invnum ) + LEFT JOIN cust_pay USING ( paynum ) + LEFT JOIN cust_main ON ( cust_bill.custnum = cust_main.custnum )', +}; + +my $cust_bill_link = sub { + my $cust_bill_pay = shift; + $cust_bill_pay->invnum + ? [ "${p}view/cust_bill.cgi?", 'invnum' ] + : ''; +}; + +my $cust_pay_link = sub { + my $cust_bill_pay = shift; + $cust_bill_pay->paynum + ? [ "${p}view/cust_pay.html?paynum=", 'paynum' ] + : ''; +}; + +my $cust_link = sub { + my $cust_credit_bill = shift; + $cust_credit_bill->cust_main_custnum + ? [ "${p}view/cust_main.cgi?", 'cust_main_custnum' ] + : ''; +}; + +</%init> diff --git a/httemplate/search/cust_credit.html b/httemplate/search/cust_credit.html index 2c59297be..9a14dceca 100755 --- a/httemplate/search/cust_credit.html +++ b/httemplate/search/cust_credit.html @@ -7,42 +7,42 @@ #'redirect' => $link, 'header' => [ 'Amount', 'Date', - FS::UI::Web::cust_header(), 'By', - 'Reason' + 'Reason', + FS::UI::Web::cust_header(), ], 'fields' => [ #'crednum', sub { sprintf('$%.2f', shift->amount ) }, sub { time2str('%b %d %Y', shift->_date ) }, - \&FS::UI::Web::cust_fields, 'otaker', 'reason', + \&FS::UI::Web::cust_fields, ], #'align' => 'rrrllll', - 'align' => 'rr'.FS::UI::Web::cust_aligns().'ll', + 'align' => 'rrll'.FS::UI::Web::cust_aligns(), 'links' => [ '', '', + '', + '', ( map { $_ ne 'Cust. Status' ? $clink : '' } FS::UI::Web::cust_header() ), - '', - '', ], 'color' => [ '', '', - FS::UI::Web::cust_colors(), '', '', + FS::UI::Web::cust_colors(), ], 'style' => [ '', '', - FS::UI::Web::cust_styles(), '', '', + FS::UI::Web::cust_styles(), ], ) %> diff --git a/httemplate/search/cust_credit_refund.html b/httemplate/search/cust_credit_refund.html new file mode 100644 index 000000000..d9abe2e00 --- /dev/null +++ b/httemplate/search/cust_credit_refund.html @@ -0,0 +1,130 @@ +<% include( 'elements/search.html', + 'title' => $title, + 'name' => 'net refunds', + 'query' => $sql_query, + 'count_query' => $count_query, + 'count_addl' => [ '$%.2f total refunded (net)', ], + 'header' => [ 'Net applied', + 'to Credit', + 'Refund', + 'By', + FS::UI::Web::cust_header(), + ], + 'fields' => [ + sub { $money_char. sprintf('%.2f', shift->amount ) }, + sub { my $ccr = shift; + '#'.$ccr->crednum. ' '. + time2str('%b %d %Y', $ccr->cust_credit_date ). + " ($money_char". + sprintf('%.2f', $ccr->cust_credit_amount). + ")" + }, + sub { my $ccr = shift; + time2str('%b %d %Y', $ccr->_date ). + " ($money_char". + sprintf('%.2f', $ccr->cust_refund_refund ). + ")" + }, + sub { shift->cust_refund->otaker }, + \&FS::UI::Web::cust_fields, + ], + 'align' => 'rrrl'.FS::UI::Web::cust_aligns(), + 'links' => [ + '', + '', + '', + '', + ( map { $_ ne 'Cust. Status' ? $cust_link : '' } + FS::UI::Web::cust_header() + ), + ], + 'color' => [ + '', + '', + '', + '', + FS::UI::Web::cust_colors(), + ], + 'style' => [ + '', + '', + '', + '', + FS::UI::Web::cust_styles(), + ], + ) +%> +<%init> + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Financial reports'); + +my $conf = new FS::Conf; +my $money_char = $conf->config('money_char') || '$'; + +my $title = 'Net Refund Search Results'; + +my @search = (); + +if ( $cgi->param('agentnum') && $cgi->param('agentnum') =~ /^(\d+)$/ ) { + push @search, "agentnum = $1"; + my $agent = qsearchs('agent', { 'agentnum' => $1 } ); + die "unknown agentnum $1" unless $agent; + $title = $agent->agent. " $title"; +} + +my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi); +push @search, "cust_credit._date >= $beginning ", + "cust_credit._date <= $ending"; + +#here is the agent virtualization +push @search, $FS::CurrentUser::CurrentUser->agentnums_sql; + +my $where = 'WHERE '. join(' AND ', @search); +# +my $count_query = 'SELECT COUNT(*), SUM(cust_credit_refund.amount) + FROM cust_credit_refund + LEFT JOIN cust_credit USING ( crednum ) + LEFT JOIN cust_main USING ( custnum ) '. + $where; + +my $sql_query = { + 'table' => 'cust_credit_refund', + 'select' => join(', ', + 'cust_credit_refund.*', + 'cust_refund.refund AS cust_refund_refund', + 'cust_credit._date AS cust_credit_date', + 'cust_credit.amount AS cust_credit_amnount', + 'cust_refund.custnum AS custnum', + 'cust_main.custnum AS cust_main_custnum', + FS::UI::Web::cust_sql_fields(), + ), + 'hashref' => {}, + 'extra_sql' => $where, + 'addl_from' => 'LEFT JOIN cust_credit USING ( crednum ) + LEFT JOIN cust_refund USING ( refundnum ) + LEFT JOIN cust_main ON ( cust_credit.custnum = cust_main.custnum )', +}; + +#my $cust_credit_link = sub { +# my $cust_credit_refund = shift; +# $cust_credit_refund->crednum +# ? [ "${p}view/cust_credit.cgi?", 'credum' ] +# : ''; +#}; + +#my $cust_refund_link = sub { +# my $cust_credit_refund = shift; +# $cust_credit_refund->refundnum +# ? [ "${p}view/cust_refund.cgi?", 'refundnum' ] +# : ''; +#}; + +my $cust_link = sub { + my $cust_credit_refund = shift; + $cust_credit_refund->cust_main_custnum + ? [ "${p}view/cust_main.cgi?", 'cust_main_custnum' ] + : ''; +}; + +</%init> diff --git a/httemplate/search/cust_pay.cgi b/httemplate/search/cust_pay.cgi index 80a611d97..65bd39e19 100755 --- a/httemplate/search/cust_pay.cgi +++ b/httemplate/search/cust_pay.cgi @@ -1,250 +1,7 @@ -<% include( 'elements/search.html', - 'title' => $title, - 'name' => 'payments', - 'query' => $sql_query, - 'count_query' => $count_query, - 'count_addl' => [ '$%.2f total paid', ], - 'header' => [ 'Payment', - 'Amount', - 'Date', - 'By', - FS::UI::Web::cust_header(), - ], - 'fields' => [ - sub { - my $cust_pay = shift; - if ( $cust_pay->payby eq 'CARD' ) { - 'Card #'. $cust_pay->paymask; - } elsif ( $cust_pay->payby eq 'CHEK' ) { - 'E-check acct#'. $cust_pay->payinfo; - } elsif ( $cust_pay->payby eq 'BILL' ) { - 'Check #'. $cust_pay->payinfo; - } elsif ( $cust_pay->payby eq 'PREP' ) { - 'Prepaid card #'. $cust_pay->payinfo; - } elsif ( $cust_pay->payby eq 'CASH' ) { - 'Cash '. $cust_pay->payinfo; - } elsif ( $cust_pay->payby eq 'WEST' ) { - 'Western Union'; #. $cust_pay->payinfo; - } elsif ( $cust_pay->payby eq 'MCRD' ) { - 'Manual credit card'; #. $cust_pay->payinfo; - } else { - $cust_pay->payby. ' '. $cust_pay->payinfo; - } - }, - sub { sprintf('$%.2f', shift->paid ) }, - sub { time2str('%b %d %Y', shift->_date ) }, - sub { my $o = shift->otaker; - $o = 'auto billing' if $o eq 'fs_daily'; - $o = 'customer self-service' if $o eq 'fs_selfservice'; - $o; - }, - \&FS::UI::Web::cust_fields, - ], - #'align' => 'lrrrll', - 'align' => 'rrrc'.FS::UI::Web::cust_aligns(), - 'links' => [ - $link, - $link, - $link, - '', - ( map { $_ ne 'Cust. Status' ? $cust_link : '' } - FS::UI::Web::cust_header() - ), - ], - 'color' => [ - '', - '', - '', - '', - FS::UI::Web::cust_colors(), - ], - 'style' => [ - '', - '', - '', - '', - FS::UI::Web::cust_styles(), - ], - ) +<% include( 'elements/cust_pay_or_refund.html', + 'thing' => 'pay', + 'amount_field' => 'paid', + 'name_singular' => 'payment', + 'name_verb' => 'paid', + ) %> -<%init> - -die "access denied" - unless $FS::CurrentUser::CurrentUser->access_right('Financial reports'); - -my $title = 'Payment Search Results'; -my( $count_query, $sql_query ); -if ( $cgi->param('magic') ) { - - my @search = (); - my $orderby; - if ( $cgi->param('magic') eq '_date' ) { - - - if ( $cgi->param('agentnum') && $cgi->param('agentnum') =~ /^(\d+)$/ ) { - push @search, "agentnum = $1"; # $search{'agentnum'} = $1; - my $agent = qsearchs('agent', { 'agentnum' => $1 } ); - die "unknown agentnum $1" unless $agent; - $title = $agent->agent. " $title"; - } - - if ( $cgi->param('payby') ) { - $cgi->param('payby') =~ - /^(CARD|CHEK|BILL|PREP|CASH|WEST|MCRD)(-(VisaMC|Amex|Discover|Maestro))?$/ - or die "illegal payby ". $cgi->param('payby'); - push @search, "cust_pay.payby = '$1'"; - if ( $3 ) { - - my $cardtype = $3; - - my $search; - if ( $cardtype eq 'VisaMC' ) { - #avoid posix regexes for portability - $search = - " ( ( substring(cust_pay.payinfo from 1 for 1) = '4' ". - " AND substring(cust_pay.payinfo from 1 for 4) != '4936' ". - " AND substring(cust_pay.payinfo from 1 for 6) ". - " NOT SIMILAR TO '49030[2-9]' ". - " AND substring(cust_pay.payinfo from 1 for 6) ". - " NOT SIMILAR TO '49033[5-9]' ". - " AND substring(cust_pay.payinfo from 1 for 6) ". - " NOT SIMILAR TO '49110[1-2]' ". - " AND substring(cust_pay.payinfo from 1 for 6) ". - " NOT SIMILAR TO '49117[4-9]' ". - " AND substring(cust_pay.payinfo from 1 for 6) ". - " NOT SIMILAR TO '49118[1-2]' ". - " )". - " OR substring(cust_pay.payinfo from 1 for 2) = '51' ". - " OR substring(cust_pay.payinfo from 1 for 2) = '52' ". - " OR substring(cust_pay.payinfo from 1 for 2) = '53' ". - " OR substring(cust_pay.payinfo from 1 for 2) = '54' ". - " OR substring(cust_pay.payinfo from 1 for 2) = '54' ". - " OR substring(cust_pay.payinfo from 1 for 2) = '55' ". - " OR substring(cust_pay.payinfo from 1 for 2) = '36' ". #Diner's int'l processed as Visa/MC inside US - " ) "; - } elsif ( $cardtype eq 'Amex' ) { - $search = - " ( substring(cust_pay.payinfo from 1 for 2 ) = '34' ". - " OR substring(cust_pay.payinfo from 1 for 2 ) = '37' ". - " ) "; - } elsif ( $cardtype eq 'Discover' ) { - $search = - " ( substring(cust_pay.payinfo from 1 for 4 ) = '6011' ". - " OR substring(cust_pay.payinfo from 1 for 2 ) = '65' ". - " OR substring(cust_pay.payinfo from 1 for 3 ) = '622' ". #China Union Pay processed as Discover outside CN - " ) "; - } elsif ( $cardtype eq 'Maestro' ) { - $search = - " ( substring(cust_pay.payinfo from 1 for 2 ) = '63' ". - " OR substring(cust_pay.payinfo from 1 for 2 ) = '67' ". - " OR substring(cust_pay.payinfo from 1 for 6 ) = '564182' ". - " OR substring(cust_pay.payinfo from 1 for 4 ) = '4936' ". - " OR substring(cust_pay.payinfo from 1 for 6 ) ". - " SIMILAR TO '49030[2-9]' ". - " OR substring(cust_pay.payinfo from 1 for 6 ) ". - " SIMILAR TO '49033[5-9]' ". - " OR substring(cust_pay.payinfo from 1 for 6 ) ". - " SIMILAR TO '49110[1-2]' ". - " OR substring(cust_pay.payinfo from 1 for 6 ) ". - " SIMILAR TO '49117[4-9]' ". - " OR substring(cust_pay.payinfo from 1 for 6 ) ". - " SIMILAR TO '49118[1-2]' ". - " ) "; - } else { - die "unknown card type $cardtype"; - } - - my $masksearch = $search; - $masksearch =~ s/cust_pay\.payinfo/cust_pay.paymask/gi; - - push @search, - "( $search OR ( cust_pay.paymask IS NOT NULL AND $masksearch ) )"; - - } - } - - if ( $cgi->param('payinfo') ) { - $cgi->param('payinfo') =~ /^\s*(\d+)\s*$/ - or die "illegal payinfo ". $cgi->param('payinfo'); - push @search, "cust_pay.payinfo = '$1'"; - } - - my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi); - push @search, "_date >= $beginning ", - "_date <= $ending"; - - push @search, FS::UI::Web::parse_lt_gt($cgi, 'paid' ); - - $orderby = '_date'; - - } elsif ( $cgi->param('magic') eq 'paybatch' ) { - - $cgi->param('paybatch') =~ /^([\w\/\:\-\.]+)$/ - or die "illegal paybatch: ". $cgi->param('paybatch'); - - push @search, "paybatch = '$1'"; - - $orderby = "LOWER(company || ' ' || last || ' ' || first )"; - - } else { - die "unknown search magic: ". $cgi->param('magic'); - } - - #here is the agent virtualization - push @search, $FS::CurrentUser::CurrentUser->agentnums_sql; - - my $search = ' WHERE '. join(' AND ', @search); - - $count_query = "SELECT COUNT(*), SUM(paid) ". - "FROM cust_pay LEFT JOIN cust_main USING ( custnum )". - $search; - - $sql_query = { - 'table' => 'cust_pay', - 'select' => join(', ', - 'cust_pay.*', - 'cust_main.custnum as cust_main_custnum', - FS::UI::Web::cust_sql_fields(), - ), - 'hashref' => {}, - 'extra_sql' => "$search ORDER BY $orderby", - 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )', - }; - -} else { - - #hmm... is this still used? - - $cgi->param('payinfo') =~ /^\s*(\d+)\s*$/ or die "illegal payinfo"; - my $payinfo = $1; - - $cgi->param('payby') =~ /^(\w+)$/ or die "illegal payby"; - my $payby = $1; - - $count_query = "SELECT COUNT(*), SUM(paid) FROM cust_pay". - " WHERE payinfo = '$payinfo' AND payby = '$payby'". - " AND ". $FS::CurrentUser::CurrentUser->agentnums_sql; - - $sql_query = { - 'table' => 'cust_pay', - 'hashref' => { 'payinfo' => $payinfo, - 'payby' => $payby }, - 'extra_sql' => $FS::CurrentUser::CurrentUser->agentnums_sql. - " ORDER BY _date", - }; - -} - -my $link = ''; -$link = [ "${p}view/cust_pay.html?paynum=", 'paynum' ] - if $FS::CurrentUser::CurrentUser->access_right('View invoices'); #XXX for now - #later# if $FS::CurrentUser::CurrentUser->access_right('View customer payments'); - -my $cust_link = sub { - my $cust_pay = shift; - $cust_pay->cust_main_custnum - ? [ "${p}view/cust_main.cgi?", 'custnum' ] - : ''; -}; - -</%init> diff --git a/httemplate/search/cust_refund.html b/httemplate/search/cust_refund.html new file mode 100644 index 000000000..e31e088eb --- /dev/null +++ b/httemplate/search/cust_refund.html @@ -0,0 +1,7 @@ +<% include( 'elements/cust_pay_or_refund.html', + 'thing' => 'refund', + 'amount_field' => 'refund', + 'name_singular' => 'refund', + 'name_verb' => 'refunded', + ) +%> diff --git a/httemplate/search/elements/cust_pay_or_refund.html b/httemplate/search/elements/cust_pay_or_refund.html new file mode 100755 index 000000000..cd1e19ded --- /dev/null +++ b/httemplate/search/elements/cust_pay_or_refund.html @@ -0,0 +1,258 @@ +<%doc> + +Examples: + + include( 'elements/cust_pay_or_refund.html', + 'thing' => 'pay', + 'amount_field' => 'paid', + 'name_singular' => 'payment', + 'name_verb' => 'paid', + ) + + include( 'elements/cust_pay_or_refund.html', + 'thing' => 'refund', + 'amount_field' => 'refund', + 'name_singular' => 'refund', + 'name_verb' => 'refunded', + ) + +</%doc> +<% include( 'search.html', + 'title' => $title, + 'name_singular' => $name_singular, + 'query' => $sql_query, + 'count_query' => $count_query, + 'count_addl' => [ '$%.2f total '.$opt{name_verb}, ], + 'header' => [ "\u$name_singular", + 'Amount', + 'Date', + 'By', + FS::UI::Web::cust_header(), + ], + 'fields' => [ + 'payby_payinfo_pretty', + sub { sprintf('$%.2f', shift->$amount_field() ) }, + sub { time2str('%b %d %Y', shift->_date ) }, + sub { my $o = shift->otaker; + $o = 'auto billing' if $o eq 'fs_daily'; + $o = 'customer self-service' if $o eq 'fs_selfservice'; + $o; + }, + \&FS::UI::Web::cust_fields, + ], + #'align' => 'lrrrll', + 'align' => 'rrrc'.FS::UI::Web::cust_aligns(), + 'links' => [ + $link, + $link, + $link, + '', + ( map { $_ ne 'Cust. Status' ? $cust_link : '' } + FS::UI::Web::cust_header() + ), + ], + 'color' => [ + '', + '', + '', + '', + FS::UI::Web::cust_colors(), + ], + 'style' => [ + '', + '', + '', + '', + FS::UI::Web::cust_styles(), + ], + ) +%> +<%init> + +my %opt = @_; + +die "access denied" + unless $FS::CurrentUser::CurrentUser->access_right('Financial reports'); + +my $thing = $opt{'thing'}; +my $amount_field = $opt{'amount_field'}; +my $name_singular = $opt{'name_singular'}; + +my $title = "\u$name_singular Search Results"; +my( $count_query, $sql_query ); +if ( $cgi->param('magic') ) { + + my @search = (); + my $orderby; + if ( $cgi->param('magic') eq '_date' ) { + + + if ( $cgi->param('agentnum') && $cgi->param('agentnum') =~ /^(\d+)$/ ) { + push @search, "agentnum = $1"; # $search{'agentnum'} = $1; + my $agent = qsearchs('agent', { 'agentnum' => $1 } ); + die "unknown agentnum $1" unless $agent; + $title = $agent->agent. " $title"; + } + + if ( $cgi->param('payby') ) { + $cgi->param('payby') =~ + /^(CARD|CHEK|BILL|PREP|CASH|WEST|MCRD)(-(VisaMC|Amex|Discover|Maestro))?$/ + or die "illegal payby ". $cgi->param('payby'); + push @search, "cust_$thing.payby = '$1'"; + if ( $3 ) { + + my $cardtype = $3; + + my $search; + if ( $cardtype eq 'VisaMC' ) { + #avoid posix regexes for portability + $search = + " ( ( substring(cust_$thing.payinfo from 1 for 1) = '4' ". + " AND substring(cust_$thing.payinfo from 1 for 4) != '4936' ". + " AND substring(cust_$thing.payinfo from 1 for 6) ". + " NOT SIMILAR TO '49030[2-9]' ". + " AND substring(cust_$thing.payinfo from 1 for 6) ". + " NOT SIMILAR TO '49033[5-9]' ". + " AND substring(cust_$thing.payinfo from 1 for 6) ". + " NOT SIMILAR TO '49110[1-2]' ". + " AND substring(cust_$thing.payinfo from 1 for 6) ". + " NOT SIMILAR TO '49117[4-9]' ". + " AND substring(cust_$thing.payinfo from 1 for 6) ". + " NOT SIMILAR TO '49118[1-2]' ". + " )". + " OR substring(cust_$thing.payinfo from 1 for 2) = '51' ". + " OR substring(cust_$thing.payinfo from 1 for 2) = '52' ". + " OR substring(cust_$thing.payinfo from 1 for 2) = '53' ". + " OR substring(cust_$thing.payinfo from 1 for 2) = '54' ". + " OR substring(cust_$thing.payinfo from 1 for 2) = '54' ". + " OR substring(cust_$thing.payinfo from 1 for 2) = '55' ". + " OR substring(cust_$thing.payinfo from 1 for 2) = '36' ". #Diner's int'l processed as Visa/MC inside US + " ) "; + } elsif ( $cardtype eq 'Amex' ) { + $search = + " ( substring(cust_$thing.payinfo from 1 for 2 ) = '34' ". + " OR substring(cust_$thing.payinfo from 1 for 2 ) = '37' ". + " ) "; + } elsif ( $cardtype eq 'Discover' ) { + $search = + " ( substring(cust_$thing.payinfo from 1 for 4 ) = '6011' ". + " OR substring(cust_$thing.payinfo from 1 for 2 ) = '65' ". + " OR substring(cust_$thing.payinfo from 1 for 3 ) = '622' ". #China Union Pay processed as Discover outside CN + " ) "; + } elsif ( $cardtype eq 'Maestro' ) { + $search = + " ( substring(cust_$thing.payinfo from 1 for 2 ) = '63' ". + " OR substring(cust_$thing.payinfo from 1 for 2 ) = '67' ". + " OR substring(cust_$thing.payinfo from 1 for 6 ) = '564182' ". + " OR substring(cust_$thing.payinfo from 1 for 4 ) = '4936' ". + " OR substring(cust_$thing.payinfo from 1 for 6 ) ". + " SIMILAR TO '49030[2-9]' ". + " OR substring(cust_$thing.payinfo from 1 for 6 ) ". + " SIMILAR TO '49033[5-9]' ". + " OR substring(cust_$thing.payinfo from 1 for 6 ) ". + " SIMILAR TO '49110[1-2]' ". + " OR substring(cust_$thing.payinfo from 1 for 6 ) ". + " SIMILAR TO '49117[4-9]' ". + " OR substring(cust_$thing.payinfo from 1 for 6 ) ". + " SIMILAR TO '49118[1-2]' ". + " ) "; + } else { + die "unknown card type $cardtype"; + } + + my $masksearch = $search; + $masksearch =~ s/cust_$thing\.payinfo/cust_$thing.paymask/gi; + + push @search, + "( $search OR ( cust_$thing.paymask IS NOT NULL AND $masksearch ) )"; + + } + } + + if ( $cgi->param('payinfo') ) { + $cgi->param('payinfo') =~ /^\s*(\d+)\s*$/ + or die "illegal payinfo ". $cgi->param('payinfo'); + push @search, "cust_$thing.payinfo = '$1'"; + } + + my($beginning, $ending) = FS::UI::Web::parse_beginning_ending($cgi); + push @search, "_date >= $beginning ", + "_date <= $ending"; + + push @search, FS::UI::Web::parse_lt_gt($cgi, $amount_field ); + + $orderby = '_date'; + + } elsif ( $cgi->param('magic') eq 'paybatch' ) { + + $cgi->param('paybatch') =~ /^([\w\/\:\-\.]+)$/ + or die "illegal paybatch: ". $cgi->param('paybatch'); + + push @search, "paybatch = '$1'"; + + $orderby = "LOWER(company || ' ' || last || ' ' || first )"; + + } else { + die "unknown search magic: ". $cgi->param('magic'); + } + + #here is the agent virtualization + push @search, $FS::CurrentUser::CurrentUser->agentnums_sql; + + my $search = ' WHERE '. join(' AND ', @search); + + $count_query = "SELECT COUNT(*), SUM($amount_field) ". + "FROM cust_$thing LEFT JOIN cust_main USING ( custnum )". + $search; + + $sql_query = { + 'table' => "cust_$thing", + 'select' => join(', ', + "cust_$thing.*", + 'cust_main.custnum as cust_main_custnum', + FS::UI::Web::cust_sql_fields(), + ), + 'hashref' => {}, + 'extra_sql' => "$search ORDER BY $orderby", + 'addl_from' => 'LEFT JOIN cust_main USING ( custnum )', + }; + +} else { + + #hmm... is this still used? + + $cgi->param('payinfo') =~ /^\s*(\d+)\s*$/ or die "illegal payinfo"; + my $payinfo = $1; + + $cgi->param('payby') =~ /^(\w+)$/ or die "illegal payby"; + my $payby = $1; + + $count_query = "SELECT COUNT(*), SUM($amount_field) FROM cust_$thing". + " WHERE payinfo = '$payinfo' AND payby = '$payby'". + " AND ". $FS::CurrentUser::CurrentUser->agentnums_sql; + + $sql_query = { + 'table' => "cust_$thing", + 'hashref' => { 'payinfo' => $payinfo, + 'payby' => $payby }, + 'extra_sql' => $FS::CurrentUser::CurrentUser->agentnums_sql. + " ORDER BY _date", + }; + +} + +my $link = ''; +if ( $thing eq 'pay' ) { #XXX no refund receipts yet + $link = [ "${p}view/cust_pay.html?paynum=", 'paynum' ] + if $FS::CurrentUser::CurrentUser->access_right('View invoices'); #XXX for now + #later# if $FS::CurrentUser::CurrentUser->access_right('View customer payments'); +} + +my $cust_link = sub { + my $cust_thing = shift; + $cust_thing->cust_main_custnum + ? [ "${p}view/cust_main.cgi?", 'custnum' ] + : ''; +}; + +</%init> |