diff options
author | Jonathan Prykop <jonathan@freeside.biz> | 2015-01-28 19:28:13 -0600 |
---|---|---|
committer | Jonathan Prykop <jonathan@freeside.biz> | 2015-01-28 19:28:13 -0600 |
commit | 92a327b2bc09344a7e0db93f40e34b71547bf075 (patch) | |
tree | 5dd0ea80b997a3a1b003e0dac52463aa20ac96d5 | |
parent | 730a14abf09f1ed8854cfded6f432fee832ea7d8 (diff) | |
parent | 3ed9d0fa90662f037f3fb2f50632ccb34066a979 (diff) |
Merge branch 'master' of git.freeside.biz:/home/git/freeside
-rw-r--r-- | FS/FS/Conf.pm | 2 | ||||
-rw-r--r-- | FS/FS/Report/Tax.pm | 16 | ||||
-rw-r--r-- | FS/FS/Schema.pm | 15 | ||||
-rw-r--r-- | FS/FS/Template_Mixin.pm | 40 | ||||
-rw-r--r-- | FS/FS/contact_email.pm | 1 | ||||
-rw-r--r-- | FS/FS/cust_main.pm | 4 | ||||
-rw-r--r-- | FS/FS/cust_main_note.pm | 1 | ||||
-rw-r--r-- | FS/FS/cust_pay.pm | 9 | ||||
-rw-r--r-- | FS/FS/discount.pm | 7 | ||||
-rw-r--r-- | FS/FS/prospect_main.pm | 5 | ||||
-rwxr-xr-x | httemplate/edit/cust_main_note.cgi | 27 | ||||
-rwxr-xr-x | httemplate/edit/part_pkg.cgi | 13 | ||||
-rw-r--r-- | httemplate/edit/process/bulk-svc_phone.html | 2 | ||||
-rwxr-xr-x | httemplate/edit/process/cust_main_note.cgi | 1 | ||||
-rw-r--r-- | httemplate/search/report_tax.cgi | 7 | ||||
-rw-r--r-- | httemplate/view/cust_main/notes/notes.html | 18 | ||||
-rw-r--r-- | httemplate/view/cust_main/payment_history/voided_invoice.html | 2 | ||||
-rw-r--r-- | httemplate/view/cust_main/payment_history/voided_payment.html | 2 |
18 files changed, 115 insertions, 57 deletions
diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index 279a4dfe8..239e304dd 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -773,7 +773,7 @@ sub reason_type_options { { 'key' => 'log_sent_mail', 'section' => 'notification', - 'description' => 'Enable logging of template-generated email.', + 'description' => 'Enable logging of all sent email.', 'type' => 'checkbox', }, diff --git a/FS/FS/Report/Tax.pm b/FS/FS/Report/Tax.pm index f3f441d21..23c16452e 100644 --- a/FS/FS/Report/Tax.pm +++ b/FS/FS/Report/Tax.pm @@ -41,13 +41,9 @@ sub report_internal { my ($taxname, $country, %breakdown); - # purify taxname properly here, as we're going to include it in lots of - # SQL statements using single quotes only - if ( $opt{taxname} =~ /^([\w\s]+)$/ ) { - $taxname = $1; - } else { - die "taxname required"; # UI prevents this - } + # taxname can contain arbitrary punctuation; escape it properly and + # include $taxname unquoted elsewhere + $taxname = dbh->quote($opt{'taxname'}); if ( $opt{country} =~ /^(\w\w)$/ ) { $country = $1; @@ -103,7 +99,7 @@ sub report_internal { GROUP BY billpkgnum, taxnum"; my $where = "WHERE cust_bill._date >= $beginning AND cust_bill._date <= $ending ". - "AND COALESCE(cust_main_county.taxname,'Tax') = '$taxname' ". + "AND COALESCE(cust_main_county.taxname,'Tax') = $taxname ". "AND cust_main_county.country = '$country'"; # SELECT/GROUP clauses for first-level queries my $select = "SELECT "; @@ -370,14 +366,14 @@ sub report_internal { SELECT 1 FROM cust_tax_exempt_pkg JOIN cust_main_county USING (taxnum) WHERE cust_tax_exempt_pkg.billpkgnum = cust_bill_pkg.billpkgnum - AND COALESCE(cust_main_county.taxname,'Tax') = '$taxname' + AND COALESCE(cust_main_county.taxname,'Tax') = $taxname AND cust_tax_exempt_pkg.creditbillpkgnum IS NULL ) AND NOT EXISTS( SELECT 1 FROM cust_bill_pkg_tax_location JOIN cust_main_county USING (taxnum) WHERE cust_bill_pkg_tax_location.taxable_billpkgnum = cust_bill_pkg.billpkgnum - AND COALESCE(cust_main_county.taxname,'Tax') = '$taxname' + AND COALESCE(cust_main_county.taxname,'Tax') = $taxname ) "; warn "\nOUTSIDE:\n$sql_outside\n" if $DEBUG; diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index ca6d169e5..b7611c154 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -2013,13 +2013,14 @@ sub tables_hashref { 'cust_main_note' => { 'columns' => [ - 'notenum', 'serial', '', '', '', '', - 'custnum', 'int', '', '', '', '', - 'classnum', 'int', 'NULL', '', '', '', - '_date', @date_type, '', '', - 'otaker', 'varchar', 'NULL', 32, '', '', - 'usernum', 'int', 'NULL', '', '', '', - 'comments', 'text', 'NULL', '', '', '', + 'notenum', 'serial', '', '', '', '', + 'custnum', 'int', '', '', '', '', + 'classnum', 'int', 'NULL', '', '', '', + '_date', @date_type, '', '', + 'otaker', 'varchar', 'NULL', 32, '', '', + 'usernum', 'int', 'NULL', '', '', '', + 'comments', 'text', 'NULL', '', '', '', + 'sticky', 'int', '', '', 0, '', ], 'primary_key' => 'notenum', 'unique' => [], diff --git a/FS/FS/Template_Mixin.pm b/FS/FS/Template_Mixin.pm index 1fed7f1b9..9669ac2cf 100644 --- a/FS/FS/Template_Mixin.pm +++ b/FS/FS/Template_Mixin.pm @@ -347,8 +347,8 @@ sub print_generic { if ( $format eq 'latex' && grep { /^%%Detail/ } @invoice_template ) { #change this to a die when the old code is removed - # it's been almost ten years, changing it to a die on the next release. - warn "old-style invoice template $templatefile; ". + # it's been almost ten years, changing it to a die + die "old-style invoice template $templatefile; ". "patch with conf/invoice_latex.diff or use new conf/invoice_latex*\n"; #$old_latex = 'true'; #@invoice_template = _translate_old_latex_format(@invoice_template); @@ -1172,6 +1172,12 @@ sub print_generic { join(', ', map "$_=>".$line_item->{$_}, keys %$line_item). "\n" if $DEBUG > 1; + push @buf, ( [ $line_item->{'description'}, + $money_char. sprintf("%10.2f", $line_item->{'amount'}), + ], + map { [ " ". $_, '' ] } @{$line_item->{'ext_description'}}, + ); + $line_item->{'ref'} = $line_item->{'pkgnum'}; $line_item->{'product_code'} = $line_item->{'pkgpart'} || 'N/A'; # mt()? $line_item->{'section'} = $section; @@ -1184,11 +1190,6 @@ sub print_generic { $line_item->{'ext_description'} ||= []; push @detail_items, $line_item; - push @buf, ( [ $line_item->{'description'}, - $money_char. sprintf("%10.2f", $line_item->{'amount'}), - ], - map { [ " ". $_, '' ] } @{$line_item->{'ext_description'}}, - ); } if ( $section->{'description'} ) { @@ -3448,8 +3449,29 @@ sub _items_cust_bill_pkg { ext_description => \@ext, }; foreach my $cust_bill_pkg_discount (@discounts) { - my $def = $cust_bill_pkg_discount->cust_pkg_discount->discount; - push @ext, &{$escape_function}( $def->description ); + my $discount = $cust_bill_pkg_discount->cust_pkg_discount->discount; + my $discount_desc = $discount->description_short; + + if ($discount->months) { + + # calculate months remaining after this invoice + my $used = FS::Record->scalar_sql( + 'SELECT SUM(months) FROM cust_bill_pkg_discount + JOIN cust_bill_pkg USING (billpkgnum) + JOIN cust_bill USING (invnum) + WHERE pkgdiscountnum = ? AND _date <= ?', + $cust_bill_pkg_discount->pkgdiscountnum, + $self->_date + ); + $used ||= 0; + my $remaining = sprintf('%.2f', $discount->months - $used); + # append "for X months (Y months remaining)" + $discount_desc .= $self->mt(' for [quant,_1,month] ([quant,_2,month] remaining)', + $cust_bill_pkg_discount->months, + $remaining + ); + } # else it's not time-limited + push @ext, &{$escape_function}($discount_desc); } } diff --git a/FS/FS/contact_email.pm b/FS/FS/contact_email.pm index a0ff27393..8d6bbbf6f 100644 --- a/FS/FS/contact_email.pm +++ b/FS/FS/contact_email.pm @@ -2,6 +2,7 @@ package FS::contact_email; use base qw( FS::Record ); use strict; +use FS::Msgcat qw( gettext ); =head1 NAME diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index e4766f52b..1ed1d4ace 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -2139,8 +2139,8 @@ Returns all notes (see L<FS::cust_main_note>) for this customer. sub notes { my($self,$orderby_classnum) = (shift,shift); - my $orderby = "_DATE DESC"; - $orderby = "CLASSNUM ASC, $orderby" if $orderby_classnum; + my $orderby = "sticky DESC, _date DESC"; + $orderby = "classnum ASC, $orderby" if $orderby_classnum; qsearch( 'cust_main_note', { 'custnum' => $self->custnum }, '', diff --git a/FS/FS/cust_main_note.pm b/FS/FS/cust_main_note.pm index 712580764..ee63883d2 100644 --- a/FS/FS/cust_main_note.pm +++ b/FS/FS/cust_main_note.pm @@ -112,6 +112,7 @@ sub check { || $self->ut_numbern('_date') || $self->ut_textn('otaker') || $self->ut_anything('comments') + || $self->ut_numbern('sticky') ; return $error if $error; diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm index 0020a824d..e44278d92 100644 --- a/FS/FS/cust_pay.pm +++ b/FS/FS/cust_pay.pm @@ -945,10 +945,11 @@ sub _upgrade_data { #class method #not the most efficient, but hey, it only has to run once - my $where = "WHERE ( otaker IS NULL OR otaker = '' OR otaker = 'ivan' ) ". - " AND usernum IS NULL ". - " AND 0 < ( SELECT COUNT(*) FROM cust_main ". - " WHERE cust_main.custnum = cust_pay.custnum ) "; + my $where = " WHERE ( otaker IS NULL OR otaker = '' OR otaker = 'ivan' ) + AND usernum IS NULL + AND EXISTS ( SELECT 1 FROM cust_main + WHERE cust_main.custnum = cust_pay.custnum ) + "; my $count_sql = "SELECT COUNT(*) FROM cust_pay $where"; diff --git a/FS/FS/discount.pm b/FS/FS/discount.pm index 0561f9ca0..361e0b4b2 100644 --- a/FS/FS/discount.pm +++ b/FS/FS/discount.pm @@ -173,7 +173,12 @@ sub description_short { my $conf = new FS::Conf; my $money_char = $conf->config('money_char') || '$'; - my $desc = $self->name ? $self->name.': ' : ''; + my $desc; + if ( $self->name ) { + $desc = $self->name . ': '; + } else { + $desc = 'Discount of '; + } $desc .= $money_char. sprintf('%.2f/month', $self->amount) if $self->amount > 0; diff --git a/FS/FS/prospect_main.pm b/FS/FS/prospect_main.pm index f30508d34..b160343de 100644 --- a/FS/FS/prospect_main.pm +++ b/FS/FS/prospect_main.pm @@ -405,6 +405,11 @@ sub search { } +# stub this so that calling ->cust_bill doesn't return an empty string +sub cust_bill { + return; +} + =back =head1 BUGS diff --git a/httemplate/edit/cust_main_note.cgi b/httemplate/edit/cust_main_note.cgi index 61590566c..a089db2d1 100755 --- a/httemplate/edit/cust_main_note.cgi +++ b/httemplate/edit/cust_main_note.cgi @@ -18,17 +18,24 @@ <BR> % } -% if( $FS::CurrentUser::CurrentUser->option('disable_html_editor') ) { - <TEXTAREA NAME="comment_plain" ROWS="12" COLS="60"><% - join '', split /<br \/>| /, $comment - %></TEXTAREA> -% } -% else { -<% include('/elements/htmlarea.html', 'field' => 'comment_html', - 'curr_value' => $comment) %> +% if ( $FS::CurrentUser::CurrentUser->option('disable_html_editor') ) { + <TEXTAREA NAME="comment_plain" ROWS="12" COLS="60"><% + join '', split /<br \/>| /, $comment + %></TEXTAREA> +% } else { + <& /elements/htmlarea.html, 'field' => 'comment_html', + 'curr_value' => $comment + &> % } -<BR><BR> +<BR> + +<& /elements/checkbox.html, 'field' => 'sticky', + 'value' => 1, + 'curr_value' => $sticky, +&> +Sticky note<BR><BR> + <INPUT TYPE="submit" VALUE="<% $notenum ? emt("Apply changes") : emt("Add Note") %>"> </FORM> @@ -42,6 +49,7 @@ my $conf = new FS::Conf; my $comment; my $notenum = ''; my $classnum; +my $sticky = 0; if ( $cgi->param('error') ) { $comment = $cgi->param('comment'); $classnum = $cgi->param('classnum'); @@ -52,6 +60,7 @@ if ( $cgi->param('error') ) { die "no such note: ". $notenum unless $note; $comment = $note->comments; $classnum = $note->classnum; + $sticky = $note->sticky; } $comment =~ s/\r//g; # remove weird line breaks to protect FCKeditor diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi index 778a0265e..1702a6dc7 100755 --- a/httemplate/edit/part_pkg.cgi +++ b/httemplate/edit/part_pkg.cgi @@ -967,8 +967,17 @@ my $html_bottom = sub { 'msg' => q|You must set the 'suspend_credit_type' option in Configuration->Settings to gain access to this option.|, 'are_met' => sub{ my $conf = new FS::conf; - my @suspend_credit_type_conf = qsearch('conf', { 'name' => 'suspend_credit_type' } ); - return 1 if (exists($suspend_credit_type_conf[0]) && $suspend_credit_type_conf[0]->{Hash}{value}); + my @conf_info = qsearch('conf', { 'name' => 'suspend_credit_type' } ); + return 1 if (exists($conf_info[0]) && $conf_info[0]->{Hash}{value}); + return 0; + } + }, + 'unused_credit_cancel' => { + 'msg' => q|You must set the 'cancel_credit_type' option in Configuration->Settings to gain access to this option.|, + 'are_met' => sub{ + my $conf = new FS::conf; + my @conf_info = qsearch('conf', { 'name' => 'cancel_credit_type' } ); + return 1 if (exists($conf_info[0]) && $conf_info[0]->{Hash}{value}); return 0; } } diff --git a/httemplate/edit/process/bulk-svc_phone.html b/httemplate/edit/process/bulk-svc_phone.html index 5a1fbc647..db486de76 100644 --- a/httemplate/edit/process/bulk-svc_phone.html +++ b/httemplate/edit/process/bulk-svc_phone.html @@ -25,7 +25,7 @@ my $num_avail = $1; errorpage("There are only $num_avail available") if $end - $start + 1 > $num_avail; -foreach my $phonenum ( $start .. $end ) { +foreach my $phonenum ( "$start" .. "$end" ) { my $svc_phone = new FS::svc_phone { 'phonenum' => $phonenum, diff --git a/httemplate/edit/process/cust_main_note.cgi b/httemplate/edit/process/cust_main_note.cgi index 227297eef..53e616a43 100755 --- a/httemplate/edit/process/cust_main_note.cgi +++ b/httemplate/edit/process/cust_main_note.cgi @@ -33,6 +33,7 @@ my $new = new FS::cust_main_note ( { _date => time, usernum => $FS::CurrentUser::CurrentUser->usernum, comments => $comment, + sticky => scalar( $cgi->param('sticky') ), } ); my $error; diff --git a/httemplate/search/report_tax.cgi b/httemplate/search/report_tax.cgi index 83f2fc5d3..491cd42c5 100644 --- a/httemplate/search/report_tax.cgi +++ b/httemplate/search/report_tax.cgi @@ -151,7 +151,7 @@ TD.rowhead { font-weight: bold; text-align: left; padding: 0px 3px } <% emt('Out of taxable region') %> </TD> <TD STYLE="text-align: right"> - <A HREF="<% $saleslink %>;out=1;taxname=<% $params{taxname} %>"> + <A HREF="<% $saleslink %>;out=1;taxname=<% encode_entities($params{'taxname'}) %>"> <% $money_sprintf->( $report->{outside } ) %> </A> </TD> @@ -188,8 +188,9 @@ if ( $cgi->param('agentnum') =~ /^(\d+)$/ ) { $agentname = $agent->agentname; } -if ( $cgi->param('taxname') =~ /^([\w ]+)$/ ) { - $params{taxname} = $1; +# allow anything in here; FS::Report::Tax will treat it as unsafe +if ( length($cgi->param('taxname')) ) { + $params{taxname} = $cgi->param('taxname'); } else { die "taxname required"; } diff --git a/httemplate/view/cust_main/notes/notes.html b/httemplate/view/cust_main/notes/notes.html index 6a7a06a02..fa45a68f2 100644 --- a/httemplate/view/cust_main/notes/notes.html +++ b/httemplate/view/cust_main/notes/notes.html @@ -34,6 +34,10 @@ % my $bgcolor1 = '#eeeeee'; % my $bgcolor2 = '#ffffff'; +% my %sticky_color = ( '#eeeeee' => '#ffff66', +% '#ffffff' => '#ffffb8', +% ); +% % my $bgcolor = ''; % my $last_classnum = -1; % my $skipheader = 0; @@ -56,7 +60,7 @@ % ";notenum=$notenum", % 'actionlabel' => emt('Edit customer note'), % 'width' => 616, -% 'height' => 538, #575 +% 'height' => 575, % 'frame' => 'top', % ); % my $clickjs = qq!onclick="$onclick"!; @@ -103,21 +107,23 @@ % $last_classnum = $note->classnum; % } +% my $color = $note->sticky ? $sticky_color{$bgcolor} : $bgcolor; + <TR> - <% note_datestr($note,$conf,$bgcolor) %> - <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <% note_datestr($note,$conf,$color) %> + <TD CLASS="grid" BGCOLOR="<% $color %>"> <% $note->usernum ? $note->access_user->name : $note->otaker %> </TD> % if ($conf->exists('note-classes') && $conf->config('note-classes') == 1) { - <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <TD CLASS="grid" BGCOLOR="<% $color %>"> <% $note->classname %> </TD> % } - <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"> + <TD CLASS="grid" BGCOLOR="<% $color %>"> <% $note->comments | defang %> </TD> % if($edit) { - <TD CLASS="grid" BGCOLOR="<% $bgcolor %>"><% $edit %></TD> + <TD CLASS="grid" BGCOLOR="<% $color %>"><% $edit %></TD> % } </TR> diff --git a/httemplate/view/cust_main/payment_history/voided_invoice.html b/httemplate/view/cust_main/payment_history/voided_invoice.html index f9ff3079a..ba51b3bca 100644 --- a/httemplate/view/cust_main/payment_history/voided_invoice.html +++ b/httemplate/view/cust_main/payment_history/voided_invoice.html @@ -1,5 +1,5 @@ <DEL><% $link %><% $invoice %><% $link ? '</A>' : '' %></DEL> -<I><% mt("voided [_1]", time2str($date_format, $cust_bill_void->void_date) ) |h %> +<I><% mt("voided ([_1]) [_2]", $cust_bill_void->reason, time2str($date_format, $cust_bill_void->void_date) ) |h %> % my $void_user = $cust_bill_void->void_access_user; % if ($void_user) { by <% $void_user->username %></I> diff --git a/httemplate/view/cust_main/payment_history/voided_payment.html b/httemplate/view/cust_main/payment_history/voided_payment.html index a8194a75f..207ab9cdd 100644 --- a/httemplate/view/cust_main/payment_history/voided_payment.html +++ b/httemplate/view/cust_main/payment_history/voided_payment.html @@ -1,5 +1,5 @@ <DEL><% mt("Payment [_1] by [_2]", $info, $cust_pay_void->otaker ) |h %></DEL> -<I><% mt("voided [_1]", time2str($date_format, $cust_pay_void->void_date) ) |h %> +<I><% mt("voided ([_1]) [_2]", $cust_pay_void->reason, time2str($date_format, $cust_pay_void->void_date) ) |h %> % my $void_user = $cust_pay_void->void_access_user; % if ($void_user) { by <% $void_user->username %></I> |