package FS::TemplateItem_Mixin;
use strict;
-use vars qw( $DEBUG $me ); # but NOT $conf
+use vars qw( $DEBUG $me $conf $date_format );
use Carp;
+use Date::Format;
use FS::UID;
use FS::Record qw( qsearch qsearchs dbh );
+use FS::Conf;
use FS::part_pkg;
use FS::cust_pkg;
$DEBUG = 0;
$me = '[FS::TemplateItem_Mixin]';
+FS::UID->install_callback( sub {
+ $conf = new FS::Conf;
+ $date_format = $conf->config('date_format') || '%x'; #/YY
+} );
=item cust_pkg
$part_pkg = $cust_pkg->part_pkg if $cust_pkg;
$part_pkg;
}
+}
+
+=item part_fee
+
+Returns the fee definition for this line item, if there is one.
+
+=cut
+sub part_fee {
+ my $self = shift;
+ $self->feepart
+ ? FS::part_fee->by_key($self->feepart)
+ : '';
}
-=item desc
+=item part_X
+
+Returns L</part_pkg> or L</part_fee>, whichever is applicable (or nothing,
+if called on a tax line item).
+
+=cut
+
+sub part_X {
+ my $self = shift;
+ $self->part_pkg || $self->part_fee;
+}
+
+=item desc LOCALE
Returns a description for this line item. For typical line items, this is the
I<pkg> field of the corresponding B<FS::part_pkg> object (see L<FS::part_pkg>).
my( $self, $locale ) = @_;
if ( $self->pkgnum > 0 ) {
- $self->itemdesc || $self->part_pkg->pkg_locale($locale);
- } else {
+ return $self->itemdesc if $self->itemdesc;
+ my $part_pkg = $self->part_pkg or return 'UNKNOWN';
+ return $part_pkg->pkg_locale($locale);
+
+ } elsif ( $self->feepart ) {
+ return $self->part_fee->itemdesc_locale($locale);
+
+ } else { # by the process of elimination it must be a tax
my $desc = $self->itemdesc || 'Tax';
$desc .= ' '. $self->itemcomment if $self->itemcomment =~ /\S/;
- $desc;
+ return $desc;
+ }
+
+}
+
+=item time_period_pretty PART_PKG, AGENTNUM
+
+Returns a formatted time period for this line item.
+
+=cut
+
+sub time_period_pretty {
+ my( $self, $part_pkg, $agentnum ) = @_;
+
+ #more efficient to look some of this conf stuff up outside the
+ # invoice/template display loop we're called from
+ # (Template_Mixin::_invoice_cust_bill_pkg) and pass them in as options
+
+ return '' if $conf->exists('disable_line_item_date_ranges')
+ || $part_pkg->option('disable_line_item_date_ranges',1)
+ || ! $self->sdate
+ || ! $self->edate;
+
+ my $date_style = '';
+ $date_style = $conf->config( 'cust_bill-line_item-date_style-non_monhtly',
+ $agentnum
+ )
+ if $part_pkg && $part_pkg->freq !~ /^1m?$/;
+ $date_style ||= $conf->config( 'cust_bill-line_item-date_style',
+ $agentnum
+ );
+
+ my $time_period;
+ if ( defined($date_style) && $date_style eq 'month_of' ) {
+ # (now watch, someone's going to make us do Chinese)
+ $time_period = $self->mt('The month of [_1]',
+ $self->time2str_local('%B', $self->sdate)
+ );
+ } elsif ( defined($date_style) && $date_style eq 'X_month' ) {
+ my $desc = $conf->config( 'cust_bill-line_item-date_description',
+ $agentnum
+ );
+ $desc .= ' ' unless $desc =~ /\s$/;
+ $time_period = $desc. $self->time2str_local('%B', $self->sdate);
+ } else {
+ $time_period = $self->time2str_local($date_format, $self->sdate).
+ " - ". $self->time2str_local($date_format, $self->edate);
}
+
+ " ($time_period)";
+
}
=item details [ OPTION => VALUE ... ]
Returns an array of detail information for the invoice line item.
-Currently available options are: I<format>, I<escape_function> and
-I<format_function>.
+Options may include:
-If I<format> is set to html or latex then the array members are improved
-for tabular appearance in those environments if possible.
+I<format>: set to 'html' or 'latex' to have the detail lines formatted for
+inclusion in an HTML table (wrapped in <tr> and <td> elements) or LaTeX table
+(delimited with & and \\ operators).
-If I<escape_function> is set then the array members are processed by this
+I<escape_function>: if present, then the array elements are processed by this
function before being returned.
-I<format_function> overrides the normal HTML or LaTeX function for returning
-formatted CDRs. It can be set to a subroutine which returns an empty list
-to skip usage detail:
+I<format_function>: overrides the normal HTML or LaTeX function for returning
+formatted CDRs.
- 'format_function' => sub { () },
+I<no_usage>: excludes call detail records. The method will still return
+some special-case records like prorate details, and manually created package
+details.
=cut
my $escape_function = $opt{escape_function} || sub { shift };
my $csv = new Text::CSV_XS;
+ my $key = $self->primary_key;
if ( $opt{format_function} ) {
)
}
qsearch ({ 'table' => $self->detail_table,
- 'hashref' => { 'billpkgnum' => $self->billpkgnum },
+ 'hashref' => { $key => $self->get($key) },
'order_by' => 'ORDER BY detailnum',
});
} elsif ( $opt{'no_usage'} ) {
my $sql = "SELECT detail FROM ". $self->detail_table.
- " WHERE billpkgnum = ". $self->billpkgnum.
+ " WHERE " . $key . " = ". $self->get($key).
" AND ( format IS NULL OR format != 'C' ) ".
" ORDER BY detailnum";
my $sth = dbh->prepare($sql) or die dbh->errstr;
}
my $sql = "SELECT format, detail FROM ". $self->detail_table.
- " WHERE billpkgnum = ". $self->billpkgnum.
+ " WHERE " . $key . " = ". $self->get($key).
" ORDER BY detailnum";
my $sth = dbh->prepare($sql) or die dbh->errstr;
$sth->execute or die $sth->errstr;
#avoid the fetchall_arrayref and loop for less memory usage?
-
- map { (defined($_->[0]) && $_->[0] eq 'C')
- ? &{$format_sub}( $_->[1] )
- : &{$escape_function}( $_->[1] );
+ # probably should use a cursor...
+
+ my @return;
+ my $head = 1;
+ map {
+ my $row = $_;
+ if (defined($row->[0]) and $row->[0] eq 'C') {
+ if ($head) {
+ # first CSV row = the format header; localize it but not the others
+ $row->[1] = $self->mt($row->[1]);
+ $head = 0;
}
- @{ $sth->fetchall_arrayref };
+ &{$format_sub}($row->[1]);
+ } else {
+ &{$escape_function}($row->[1]);
+ }
+ } @{ $sth->fetchall_arrayref };
- }
+ } #!$opt{format_function}
}
}
-=item cust_bill_pkg_discount
+=item pkg_discount
-Returns the list of associated cust_bill_pkg_discount objects.
+Returns the list of associated cust_bill_pkg_discount or
+quotation_pkg_discount objects.
=cut
-sub cust_bill_pkg_discount {
+sub pkg_discount {
my $self = shift;
- qsearch( $self->discount_table, { 'billpkgnum' => $self->billpkgnum } );
+ my $pkey = $self->primary_key;
+ qsearch( $self->discount_table, { $pkey => $self->get($pkey) } );
}
1;