RT# 81961 Repair broken links in POD documentation
[freeside.git] / FS / FS / Template_Mixin.pm
index 30b0444..76680d2 100644 (file)
@@ -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]';
@@ -937,7 +938,9 @@ 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->config_bool('invoice_sections_with_taxes', $cust_main->agentnum);
   my $late_sections;
@@ -1191,7 +1194,8 @@ sub print_generic {
     my %options = ();
     $options{'section'} = $section if $multisection;
     $options{'section_with_taxes'} = 1
-      if $conf->config_bool('invoice_sections_with_taxes', $cust_main->agentnum);
+      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;
@@ -1200,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;
@@ -2021,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
@@ -2035,11 +2058,7 @@ sub balance_due_msg {
     # _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);
@@ -2161,7 +2180,7 @@ notice name instead of "Invoice", optional
 
 =back
 
-Returns an argument list to be passed to L<FS::Misc::send_email>.
+Returns an argument list to be passed to L<FS::Misc/send_email>.
 
 =cut
 
@@ -2228,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 {
 
@@ -2250,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',
   );
 
@@ -2329,7 +2351,11 @@ sub generate_email {
                          '    </title>',
                          '  </head>',
                          '  <body bgcolor="#e8e8e8">',
-                         Encode::encode_utf8($html),
+                         Encode::encode(
+                           'UTF-8',
+                           $html,
+                           Encode::FB_WARN | Encode::LEAVE_SRC
+                         ),
                          '  </body>',
                          '</html>',
                        ],
@@ -2435,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
 
@@ -2446,7 +2472,7 @@ sub mimebuild_pdf {
     'Encoding'    => 'base64',
     'Data'        => [ $self->print_pdf(@_) ],
     'Disposition' => 'attachment',
-    'Filename'    => 'invoice-'. $self->invnum. '.pdf',
+    'Filename'    => $self->pdf_filename,
   );
 }
 
@@ -2461,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 ) = @_;
@@ -2663,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).
@@ -3088,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
@@ -3129,7 +3165,7 @@ 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
@@ -3440,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?
@@ -3474,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,
-                                                              $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)
@@ -3566,8 +3630,15 @@ sub _items_cust_bill_pkg {
             $description = $self->mt('Usage charges');
           }
 
-          $description .= $cust_bill_pkg->time_period_pretty( $part_pkg,
-                                                              $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,
+                          );
 
           my @d = ();
           my @seconds = (); # for display of usage info