use FS::cust_credit_bill_pkg;
use FS::discount_plan;
use FS::cust_bill_void;
+use FS::reason;
+use FS::reason_type;
use FS::L10N;
$DEBUG = 0;
}
-=item void
+=item void [ REASON ]
Voids this invoice: deletes the invoice and adds a record of the voided invoice
to the FS::cust_bill_void table (and related tables starting from
my $self = shift;
my $reason = scalar(@_) ? shift : '';
+ unless (ref($reason) || !$reason) {
+ $reason = FS::reason->new_or_existing(
+ 'class' => 'I',
+ 'type' => 'Invoice void',
+ 'reason' => $reason
+ );
+ }
+
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
local $SIG{QUIT} = 'IGNORE';
my $cust_bill_void = new FS::cust_bill_void ( {
map { $_ => $self->get($_) } $self->fields
} );
- $cust_bill_void->reason($reason);
+ $cust_bill_void->reasonnum($reason->reasonnum) if $reason;
my $error = $cust_bill_void->insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
}
}
- $error = $self->delete;
+ $error = $self->_delete;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
}
-=item delete
-
-This method now works but you probably shouldn't use it. Instead, apply a
-credit against the invoice, or use the new void method.
-
-Using this method to delete invoices outright is really, really bad. There
-would be no record you ever posted this invoice, and there are no check to
-make sure charged = 0 or that there are no associated cust_bill_pkg records.
-
-Really, don't use it.
-
-=cut
-
-sub delete {
+# removed docs entirely and renamed method to _delete to further indicate it is
+# internal-only and discourage use
+#
+# =item delete
+#
+# DO NOT USE THIS METHOD. Instead, apply a credit against the invoice, or use
+# the B<void> method.
+#
+# This is only for internal use by V<void>, which is what you should be using.
+#
+# DO NOT USE THIS METHOD. Whatever reason you think you have is almost certainly
+# wrong. Use B<void>, that's what it is for. Really. This means you.
+#
+# =cut
+
+sub _delete {
my $self = shift;
return "Can't delete closed invoice" if $self->closed =~ /^Y/i;
foreach my $table (qw(
cust_credit_bill
- cust_bill_pay
- cust_pay_batch
cust_bill_pay_batch
+ cust_bill_pay
cust_bill_batch
cust_bill_pkg
)) {
#cust_event # problematic
+ #cust_pay_batch # unnecessary
foreach my $linked ( $self->$table() ) {
my $error = $linked->delete;
my $self = qsearchs('cust_bill', { 'invnum' => $opt{invnum} } )
or die "invalid invoice number: " . $opt{invnum};
- if ( $opt{mode} ) {
- $self->set('mode', $opt{mode});
- }
+ $self->set('mode', $opt{mode})
+ if $opt{mode};
my %args = map {$_ => $opt{$_}}
grep { $opt{$_} }
eval qq("$subject");
}
+sub pdf_filename {
+ my $self = shift;
+ 'Invoice-'. $self->invnum. '.pdf';
+}
+
=item lpr_data HASHREF
Returns the postscript or plaintext for this invoice as an arrayref.
batchnum => $bill_batch->batchnum,
invnum => $self->invnum,
});
+ if ( $self->mode ) {
+ $opt->{mode} ||= $self->mode;
+ $opt->{mode} = $opt->{mode}->modenum if ref $opt->{mode};
+ }
return $cust_bill_batch->insert($opt);
}
my %opt = @_;
my $escape = $opt{escape} || sub { $_[0] };
+ my $money_char = $opt{money_char};
my $invnum = $self->invnum;
my @classes = qsearch({
'table' => 'usage_class',
- 'select' => 'classnum, classname, SUM(amount) AS amount',
+ 'select' => 'classnum, classname, SUM(amount) AS amount,'.
+ ' COUNT(*) AS calls, SUM(duration) AS duration',
'addl_from' => ' LEFT JOIN cust_bill_pkg_detail USING (classnum)' .
' LEFT JOIN cust_bill_pkg USING (billpkgnum)',
'extra_sql' => " WHERE cust_bill_pkg.invnum = $invnum".
my @l;
my $section = {
description => &{$escape}($self->mt('Usage Summary')),
- no_subtotal => 1,
usage_section => 1,
+ subtotal => 0,
};
foreach my $class (@classes) {
+ $section->{subtotal} += $class->get('amount');
push @l, {
'description' => &{$escape}($class->classname),
- 'amount' => sprintf('%.2f', $class->amount),
+ 'amount' => $money_char.sprintf('%.2f', $class->get('amount')),
+ 'quantity' => $class->get('calls'),
+ 'duration' => $class->get('duration'),
'usage_classnum' => $class->classnum,
'section' => $section,
};
}
+ $section->{subtotal} = $money_char.sprintf('%.2f', $section->{subtotal});
return @l;
}
my ($previous_charges_desc, $new_charges_desc, $new_charges_amount);
if ( $conf->exists('previous_balance-exclude_from_total') ) {
- # can we do some caching on this stuff? it's going to change infrequently
- # in production
+ # if enabled, specifically add a line for the previous balance total
$previous_charges_desc = $self->mt(
$conf->config('previous_balance-text') || 'Previous Balance'
);
total_amount => sprintf('%.2f',$pr_total)
};
}
+ }
+
+ if ( $conf->exists('previous_balance-exclude_from_total')
+ or !$self->enable_previous ) {
+ # show new charges only
+
$new_charges_desc = $self->mt(
$conf->config('previous_balance-text-total_new_charges')
|| 'Total New Charges'
$new_charges_amount = $self->charged;
} else {
+ # show new charges + previous invoice total
$new_charges_desc = $self->mt('Total Charges');
- $new_charges_amount = sprintf('%.2f',$self->charged + $pr_total);
+ if ( $self->enable_previous ) {
+ $new_charges_amount = sprintf('%.2f', $self->charged + $pr_total);
+ } else {
+ $new_charges_amount = sprintf('%.2f', $self->charged);
+ }
}
( $header, grep { $_ ne $header } @details );
}
+=item cust_pay_batch
+
+Returns all L<FS::cust_pay_batch> records linked to this invoice. Deprecated,
+will be removed.
+
+=cut
+
+sub cust_pay_batch {
+ carp "FS::cust_bill->cust_pay_batch is deprecated";
+ my $self = shift;
+ qsearch('cust_pay_batch', { 'invnum' => $self->invnum });
+}
=back
}
+# this is called from search/cust_bill.html and given all its search
+# parameters, so it needs to perform the same search.
+
sub re_X {
# spool_invoice ftp_invoice fax_invoice print_invoice
my($method, $job, %param ) = @_;
}
#some false laziness w/search/cust_bill.html
- my $distinct = '';
- my $orderby = 'ORDER BY cust_bill._date';
-
- my $extra_sql = ' WHERE '. FS::cust_bill->search_sql_where(\%param);
-
- my $addl_from = 'LEFT JOIN cust_main USING ( custnum )';
-
- my @cust_bill = qsearch( {
- #'select' => "cust_bill.*",
- 'table' => 'cust_bill',
- 'addl_from' => $addl_from,
- 'hashref' => {},
- 'extra_sql' => $extra_sql,
- 'order_by' => $orderby,
- 'debug' => 1,
- } );
+ $param{'order_by'} = 'cust_bill._date';
+
+ my $query = FS::cust_bill->search(\%param);
+ delete $query->{'count_query'};
+ delete $query->{'count_addl'};
+
+ $query->{debug} = 1; # was in here before, is obviously useful
+
+ my @cust_bill = qsearch( $query );
$method .= '_invoice' unless $method eq 'email' || $method eq 'print';