X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=blobdiff_plain;f=FS%2FFS%2FTemplate_Mixin.pm;h=76680d2704778697b0c5504c65235db16f840b55;hp=99019e91e588ed3401c56a14642eec4b236dead2;hb=17a8b72b78ba455b58d53731fe557a471e0f2947;hpb=d9f02dd085aef4e8d8579cd34be0c6991ccf4f44 diff --git a/FS/FS/Template_Mixin.pm b/FS/FS/Template_Mixin.pm index 99019e91e..76680d270 100644 --- a/FS/FS/Template_Mixin.pm +++ b/FS/FS/Template_Mixin.pm @@ -26,6 +26,7 @@ use FS::pkg_category; use FS::pkg_class; use FS::invoice_mode; use FS::L10N; +use FS::Log; $DEBUG = 0; $me = '[FS::Template_Mixin]'; @@ -299,7 +300,7 @@ before that line item (quotations only) =item template -Dprecated. Used as a suffix for a configuration template. Please +Deprecated. Used as a suffix for a configuration template. Please don't use this, it deprecated in favor of more flexible alternatives. =back @@ -831,7 +832,7 @@ sub print_generic { $invoice_data{'previous_credits'} = []; } - if ( $conf->exists('invoice_usesummary', $agentnum) ) { + if ( $conf->config_bool('invoice_usesummary', $agentnum) ) { $invoice_data{'summarypage'} = $summarypage = 1; } @@ -937,9 +938,11 @@ sub print_generic { my $unsquelched = $params{unsquelch_cdr} || $cust_main->squelch_cdr ne 'Y'; my $multisection = $self->has_sections; - $invoice_data{'multisection'} = $multisection; + if ( $multisection ) { + $invoice_data{multisection} = $conf->config($tc.'sections_method') || 1; + } my $section_with_taxes = 1 - if $conf->exists('invoice_sections_with_taxes'); + if $conf->config_bool('invoice_sections_with_taxes', $cust_main->agentnum); my $late_sections; my $extra_sections = []; my $extra_lines = (); @@ -1190,6 +1193,9 @@ sub print_generic { my %options = (); $options{'section'} = $section if $multisection; + $options{'section_with_taxes'} = 1 + if $multisection + && $conf->config_bool('invoice_sections_with_taxes', $cust_main->agentnum); $options{'format'} = $format; $options{'escape_function'} = $escape_function; $options{'no_usage'} = 1 unless $unsquelched; @@ -1198,6 +1204,8 @@ sub print_generic { $options{'skip_usage'} = scalar(@$extra_sections) && !grep{$section == $_} @$extra_sections; $options{'preref_callback'} = $params{'preref_callback'}; + $options{'disable_line_item_date_ranges'} = + $conf->exists('disable_line_item_date_ranges'); warn "$me searching for line items\n" if $DEBUG > 1; @@ -1377,7 +1385,7 @@ sub print_generic { $tax_section->{'description'} = $self->mt($tax_description); $tax_section->{'summarized'} = ''; - if ( $conf->exists('invoice_sections_with_taxes')) { + if ( $conf->config_bool('invoice_sections_with_taxes', $cust_main->agentnum) ) { # remove tax section if taxes are itemized within other sections @sections = grep{ $_ ne $tax_section } @sections; @@ -2019,6 +2027,23 @@ sub due_date2str { $self->due_date ? $self->time2str_local(shift, $self->due_date) : ''; } +=item invoice_pay_by_msg + + displays the invoice_pay_by_msg or default Please pay by [_1] if empty. + +=cut + +sub invoice_pay_by_msg { + my $self = shift; + my $msg = ''; + my $please_pay_by = + $self->conf->config('invoice_pay_by_msg', $self->agentnum) + || 'Please pay by [_1]'; + $msg .= ' - ' . $self->mt($please_pay_by, $self->due_date2str('short')) . ' '; + + $msg; +} + =item balance_due_msg =cut @@ -2028,16 +2053,12 @@ sub balance_due_msg { my $msg = $self->mt('Balance Due'); return $msg unless $self->terms; # huh? if ( !$self->conf->exists('invoice_show_prior_due_date') - or $self->conf->exists('invoice_sections') ) { - # if enabled, the due date is shown with Total New Charges (see + || $self->has_sections ) { + # if enabled, the due date is shown with Total New Charges (see # _items_total) and not here # (yes, or if invoice_sections is enabled; this is just for compatibility) if ( $self->due_date ) { - my $please_pay_by = - $self->conf->config('invoice_pay_by_msg', $self->agentnum) - || 'Please pay by [_1]'; - $msg .= ' - ' . $self->mt($please_pay_by, $self->due_date2str('short')). - ' ' + $msg .= $self->invoice_pay_by_msg unless $self->conf->config_bool('invoice_omit_due_date',$self->agentnum); } elsif ( $self->terms ) { $msg .= ' - '. $self->mt($self->terms); @@ -2159,7 +2180,7 @@ notice name instead of "Invoice", optional =back -Returns an argument list to be passed to L. +Returns an argument list to be passed to L. =cut @@ -2226,13 +2247,12 @@ sub generate_email { if (!@text) { - if ( $conf->config($tc.'template') ) { + if ( $conf->exists($tc.'template') ) { warn "$me generating plain text invoice" if $DEBUG; - # 'print_text' argument is no longer used - @text = map Encode::encode_utf8($_), $self->print_text(\%args); + @text = $self->print_text(\%args); } else { @@ -2248,7 +2268,11 @@ sub generate_email { 'Encoding' => 'quoted-printable', 'Charset' => 'UTF-8', #'Encoding' => '7bit', - 'Data' => \@text, + 'Data' => [ + map + { Encode::encode('UTF-8', $_, Encode::FB_WARN | Encode::LEAVE_SRC ) } + @text + ], 'Disposition' => 'inline', ); @@ -2327,7 +2351,11 @@ sub generate_email { ' ', ' ', ' ', - Encode::encode_utf8($html), + Encode::encode( + 'UTF-8', + $html, + Encode::FB_WARN | Encode::LEAVE_SRC + ), ' ', '', ], @@ -2433,7 +2461,7 @@ sub generate_email { =item mimebuild_pdf Returns a list suitable for passing to MIME::Entity->build(), representing -this invoice as PDF attachment. +this quotation or invoice as PDF attachment. =cut @@ -2444,7 +2472,7 @@ sub mimebuild_pdf { 'Encoding' => 'base64', 'Data' => [ $self->print_pdf(@_) ], 'Disposition' => 'attachment', - 'Filename' => 'invoice-'. $self->invnum. '.pdf', + 'Filename' => $self->pdf_filename, ); } @@ -2459,7 +2487,7 @@ use CAM::PDF; use IO::Socket::SSL; use LWP::UserAgent; use HTTP::Request::Common qw( POST ); -use JSON::XS; +use Cpanel::JSON::XS; use MIME::Base64; sub postal_mail_fsinc { my ( $self, %opt ) = @_; @@ -2661,7 +2689,13 @@ sub _items_sections { foreach my $display ($cust_bill_pkg->cust_bill_pkg_display) { next if ( $display->summary && $opt{summary} ); - my $section = $display->section; + #my $section = $display->section; + #false laziness with the method, but for efficiency inside this loop + my $section = $display->get('section'); + if ( !$section && !$cust_bill_pkg->hidden ) { + $section = $cust_bill_pkg->get('categoryname'); #cust_bill->cust_bill_pkg added it (XXX quotations / quotation_section) + } + my $type = $display->type; # Set $section = undef if we're sectioning by location and this # line item _has_ a location (i.e. isn't a fee). @@ -3086,6 +3120,10 @@ sub _items_fee { my @cust_bill_pkg = grep { $_->feepart } $self->cust_bill_pkg; my $escape_function = $options{escape_function}; + my $locale = $self->cust_main + ? $self->cust_main->locale + : $self->prospect_main->locale; + my @items; foreach my $cust_bill_pkg (@cust_bill_pkg) { # cache this, so we don't look it up again in every section @@ -3127,11 +3165,11 @@ sub _items_fee { $self->mt('from invoice #[_1] on [_2]', $_, $base_invnums{$_}) ); } - my $desc = $part_fee->itemdesc_locale($self->cust_main->locale); + my $desc = $part_fee->itemdesc_locale($locale); # but not escape the base description line my @pkg_tax = $cust_bill_pkg->_pkg_tax_list - if $self->conf->exists('invoice_sections_with_taxes'); + if $options{section_with_taxes}; push @items, { feepart => $cust_bill_pkg->feepart, @@ -3275,6 +3313,8 @@ sub _items_cust_bill_pkg { my $cust_main = $self->cust_main;#for per-agent cust_bill-line_item-ate_style + my $agentnum = $self->agentnum; + # for location labels: use default location on the invoice date my $default_locationnum; if ( $conf->exists('invoice-all_pkg_addresses') ) { @@ -3377,7 +3417,7 @@ sub _items_cust_bill_pkg { ); my @pkg_tax = $cust_bill_pkg->_pkg_tax_list - if $self->conf->exists('invoice_sections_with_taxes'); + if $opt{section_with_taxes}; if ( ref($cust_bill_pkg) eq 'FS::quotation_pkg' ) { # XXX this should be pulled out into quotation_pkg @@ -3436,6 +3476,27 @@ sub _items_cust_bill_pkg { if $DEBUG > 1; my $cust_pkg = $cust_bill_pkg->cust_pkg; + + unless ( $cust_pkg ) { + # There is no related row in cust_pkg for this cust_bill_pkg.pkgnum. + # This invoice may have been broken by an unusual combination + # of manually editing package dates, and aborted package changes + # when the manually edited dates used are nonsensical. + + my $error = sprintf + 'cust_bill_pkg(billpkgnum:%s) '. + 'is missing related row in cust_pkg(pkgnum:%s)! '. + 'cust_bill(invnum:%s) is corrupted by bad database data, '. + 'and should be investigated', + $cust_bill_pkg->billpkgnum, + $cust_bill_pkg->pkgnum, + $cust_bill_pkg->invnum; + + FS::Log->new('FS::cust_bill_pkg')->critical( $error ); + warn $error; + next; + } + my $part_pkg = $cust_pkg->part_pkg; # which pkgpart to show for display purposes? @@ -3470,8 +3531,15 @@ sub _items_cust_bill_pkg { || ($discount_show_always and $cust_bill_pkg->unitrecur > 0) || $cust_bill_pkg->recur_show_zero; - $description .= $cust_bill_pkg->time_period_pretty( $part_pkg, - $self->agentnum ) + my $disable_date_ranges = + $opt{disable_line_item_date_ranges} + || $part_pkg->option('disable_line_item_date_ranges', 1); + + $description .= $cust_bill_pkg->time_period_pretty( + $part_pkg, + $agentnum, + disable_date_ranges => $disable_date_ranges, + ) if $part_pkg->is_prepaid #for prepaid, "display the validity period # triggered by the recurring charge freq # (RT#26274) @@ -3562,10 +3630,15 @@ sub _items_cust_bill_pkg { $description = $self->mt('Usage charges'); } - my $part_pkg = $cust_pkg->part_pkg; + my $disable_date_ranges = + $opt{disable_line_item_date_ranges} + || $part_pkg->option('disable_line_item_date_ranges', 1); - $description .= $cust_bill_pkg->time_period_pretty( $part_pkg, - $self->agentnum ); + $description .= $cust_bill_pkg->time_period_pretty( + $part_pkg, + $agentnum, + disable_date_ranges => $disable_date_ranges, + ); my @d = (); my @seconds = (); # for display of usage info @@ -3885,8 +3958,8 @@ sub has_sections { return 0 unless $self->invnum > 0; - $agentnum ||= $self->cust_main->agentnum; - return 1 if $self->conf->exists('invoice_sections', $agentnum); + $agentnum ||= $self->agentnum; + return 1 if $self->conf->config_bool('invoice_sections', $agentnum); return 1 if $self->conf->exists('sections_by_location', $agentnum); my $location_min = $self->conf->config(