###
'View invoices',
'Resend invoices', #NEWNEW
+ 'Delete invoices', #new, but no need to phase in
'View customer tax exemptions', #yow
'View customer batched payments', #NEW
@rights;
}
+sub default_superuser_rights {
+ my $class = shift;
+ my %omit = map { $_=>1 } (
+ 'Delete customer',
+ 'Delete invoices',
+ 'Delete payment',
+ 'Delete credit', #?
+ 'Delete refund', #?
+ 'Raw SQL',
+ );
+
+ no warnings 'uninitialized';
+ grep { ! $omit{$_} } $class->rights;
+}
+
+1;
{
'key' => 'deletecustomers',
'section' => 'UI',
- 'description' => 'Enable customer deletions. Be very careful! Deleting a customer will remove all traces that this customer ever existed! It should probably only be used when auditing a legacy database. Normally, you cancel all of a customers\' packages if they cancel service.',
+ 'description' => 'Enable customer deletions. Be very careful! Deleting a customer will remove all traces that the customer ever existed! It should probably only be used when auditing a legacy database. Normally, you cancel all of a customers\' packages if they cancel service.',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'deleteinvoices',
+ 'section' => 'UI',
+ 'description' => 'Enable invoices deletions. Be very careful! Deleting an invoice will remove all traces that the invoice ever existed! Normally, you would apply a credit against the invoice instead.', #invoice voiding?
'type' => 'checkbox',
},
use FS::AccessRight;
use FS::access_right;
- foreach my $rightname ( FS::AccessRight->rights ) {
+ foreach my $rightname ( FS::AccessRight->default_superuser_rights ) {
my $access_right = new FS::access_right {
'righttype' => 'FS::access_group',
'rightobjnum' => 1, #$supergroup->groupnum,
sub delete {
my $self = shift;
return "Can't delete closed invoice" if $self->closed =~ /^Y/i;
- $self->SUPER::delete(@_);
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ foreach my $table (qw(
+ cust_bill_event
+ cust_credit_bill
+ cust_bill_pay
+ cust_bill_pay
+ cust_credit_bill
+ cust_pay_batch
+ cust_bill_pay_batch
+ cust_bill_pkg
+ )) {
+
+ foreach my $linked ( $self->$table() ) {
+ my $error = $linked->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ }
+
+ my $error = $self->SUPER::delete(@_);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ '';
+
}
=item replace OLD_RECORD
#;
}
+sub cust_pay_batch {
+ my $self = shift;
+ qsearch('cust_pay_batch', { 'invnum' => $self->invnum } );
+}
+
+sub cust_bill_pay_batch {
+ my $self = shift;
+ qsearch('cust_bill_pay_batch', { 'invnum' => $self->invnum } );
+}
+
=item cust_bill_pay
Returns all payment applications (see L<FS::cust_bill_pay>) for this invoice.
=item cust_credited
+=item cust_credit_bill
+
Returns all applied credits (see L<FS::cust_credit_bill>) for this invoice.
=cut
;
}
+sub cust_credit_bill {
+ shift->cust_credited(@_);
+}
+
=item tax
Returns the tax amount (see L<FS::cust_bill_pkg>) for this invoice.
package FS::cust_bill_pkg;
use strict;
-use vars qw( @ISA );
+use vars qw( @ISA $DEBUG $me );
use FS::Record qw( qsearch qsearchs dbdef dbh );
use FS::cust_main_Mixin;
use FS::cust_pkg;
@ISA = qw( FS::cust_main_Mixin FS::Record );
+$DEBUG = 0;
+$me = '[FS::cust_bill_pkg]';
+
=head1 NAME
FS::cust_bill_pkg - Object methods for cust_bill_pkg records
=item delete
-Currently unimplemented. I don't remove line items because there would then be
-no record the items ever existed (which is bad, no?)
+Not recommended.
=cut
sub delete {
- return "Can't delete cust_bill_pkg records!";
+ my $self = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ foreach my $table (qw(
+ cust_bill_pkg_detail
+ cust_tax_exempt_pkg
+ cust_bill_pay_pkg
+ cust_credit_bill_pkg
+ )) {
+
+ foreach my $linked ( qsearch($table, { billpkgnum=>$self->billpkgnum }) ) {
+ my $error = $linked->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ }
+
+ my $error = $self->SUPER::delete(@_);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ '';
+
}
=item replace OLD_RECORD
sub cust_pkg {
my $self = shift;
+ warn "$me $self -> cust_pkg" if $DEBUG;
qsearchs( 'cust_pkg', { 'pkgnum' => $self->pkgnum } );
}
die $error if $error;
if ( $opt_s ) {
- foreach my $rightname ( FS::AccessRight->rights ) {
+ foreach my $rightname ( FS::AccessRight->default_superuser_rights ) {
my $access_right = new FS::access_right {
'righttype' => 'FS::access_group',
'rightobjnum' => $access_group->groupnum,
my $error = $supergroup->insert;
die $error if $error;
- foreach my $rightname ( FS::AccessRight->rights ) {
+ foreach my $rightname ( FS::AccessRight->default_superuser_rights ) {
my $access_right = new FS::access_right {
'righttype' => 'FS::access_group',
'rightobjnum' => $supergroup->groupnum,
--- /dev/null
+% if ( $error ) {
+% errorpage($error);
+% } else {
+<% $cgi->redirect($p. "view/cust_main.cgi?". $custnum) %>
+% }
+<%init>
+
+die "access denied"
+ unless $FS::CurrentUser::CurrentUser->access_right('Delete invoices');
+
+#untaint invnum
+my($query) = $cgi->keywords;
+$query =~ /^(\d+)$/ || die "Illegal crednum";
+my $invnum = $1;
+
+my $cust_bill = qsearchs('cust_bill',{'invnum'=>$invnum});
+my $custnum = $cust_bill->custnum;
+
+my $error = $cust_bill->delete;
+
+</%init>
"View this customer (#$custnum)" => "${p}view/cust_main.cgi?$custnum",
)) %>
+% if ( $conf->exists('deleteinvoices')
+% && $curuser->access_right('Delete invoices' )
+% )
+% {
+
+ <SCRIPT TYPE="text/javascript">
+ function areyousure(href, message) {
+ if (confirm(message) == true)
+ window.location.href = href;
+ }
+ </SCRIPT>
+
+ <A HREF = "javascript:areyousure(
+ '<%$p%>misc/delete-cust_bill.html?<% $invnum %>',
+ 'Are you sure you want to delete this invoice?'
+ )"
+ TITLE = "Delete this invoice from the database completely"
+ >Delete this invoice</A>
+ <BR><BR>
+
+% }
% if ( $cust_bill->owed > 0
% && scalar( grep $payby{$_}, qw(BILL CASH WEST MCRD) )
-% && $FS::CurrentUser::CurrentUser->access_right('Post payment')
+% && $curuser->access_right('Post payment')
% )
% {
% my $s = 0;
% }
-
-% if ( $FS::CurrentUser::CurrentUser->access_right('Resend invoices') ) {
+% if ( $curuser->access_right('Resend invoices') ) {
<A HREF="<% $p %>misc/print-invoice.cgi?<% $link %>">Re-print this invoice</A>
% }
-
% if ( $conf->exists('invoice_latex') ) {
- <A HREF="<% $p %>view/cust_bill-pdf.cgi?<% $link %>.pdf">View typeset invoice</A>
+ <A HREF="<% $p %>view/cust_bill-pdf.cgi?<% $link %>.pdf">View typeset invoice PDF</A>
<BR><BR>
% }
% #false laziness with search/cust_bill_event.cgi
<% include('/elements/footer.html') %>
<%init>
+my $curuser = $FS::CurrentUser::CurrentUser;
+
die "access denied"
- unless $FS::CurrentUser::CurrentUser->access_right('View invoices');
+ unless $curuser->access_right('View invoices');
#untaint invnum
my($query) = $cgi->keywords;
'table' => 'cust_bill',
'addl_from' => 'LEFT JOIN cust_main USING ( custnum )',
'hashref' => { 'invnum' => $invnum },
- 'extra_sql' => ' AND '. $FS::CurrentUser::CurrentUser->agentnums_sql,
+ 'extra_sql' => ' AND '. $curuser->agentnums_sql,
});
die "Invoice #$invnum not found!" unless $cust_bill;
my $link = $templatename ? "$templatename-$invnum" : $invnum;
</%init>
-
-
-<% $link %><% $pre %>Invoice #<% $invnum %>
-(Balance $ <% $cust_bill->owed %>)<% $post %><% $link ? '</A>' : '' %><% $events %>
+<% $link %><% $pre %>Invoice #<% $cust_bill->display_invnum %>
+(Balance $ <% $cust_bill->owed %>)<% $post %><% $link ? '</A>' : '' %><% $delete %><% $events %>
<%init>
my( $cust_bill, %opt ) = @_;
+my $conf = new FS::Conf;
+
my $curuser = $FS::CurrentUser::CurrentUser;
my($pre, $post) = ('', '');
? qq!<A HREF="${p}view/cust_bill.cgi?$invnum">!
: '';
+my $delete = '';
+if ( $conf->exists('deleteinvoices')
+ && $curuser->access_right('Delete invoices') ) {
+ $delete = qq! (<A HREF="javascript:areyousure('!.
+ qq!${p}misc/delete-cust_bill.html?$invnum',!.
+ qq!'Are you sure you want to delete this invoice?')"!.
+ qq! TITLE="Delete this invoice from the database completely"!.
+ qq!>delete</A>)!;
+}
+
my $events = '';
</%init>