delete invoices, RT#4048
authorivan <ivan>
Sun, 4 Oct 2009 02:09:15 +0000 (02:09 +0000)
committerivan <ivan>
Sun, 4 Oct 2009 02:09:15 +0000 (02:09 +0000)
FS/FS/AccessRight.pm
FS/FS/Conf.pm
FS/FS/Setup.pm
FS/FS/cust_bill.pm
FS/FS/cust_bill_pkg.pm
FS/bin/freeside-addgroup
bin/mapsecrets2access_user
httemplate/misc/delete-cust_bill.html [new file with mode: 0644]
httemplate/view/cust_bill.cgi
httemplate/view/cust_main/payment_history/invoice.html

index 856a5f5..e90687d 100644 (file)
@@ -139,6 +139,7 @@ assigned to users and/or groups.
 ###
   'View invoices',
   'Resend invoices', #NEWNEW
+  'Delete invoices', #new, but no need to phase in
   'View customer tax exemptions', #yow
   'View customer batched payments', #NEW
 
@@ -216,3 +217,19 @@ sub rights {
   @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;
index e97dc32..6ad3fcb 100644 (file)
@@ -482,7 +482,14 @@ worry that config_items is freeside-specific and icky.
   {
     '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',
   },
 
index e6344e4..e02abcb 100644 (file)
@@ -352,7 +352,7 @@ sub populate_access {
   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,
index 472dc73..e6d0b0d 100644 (file)
@@ -139,7 +139,49 @@ Really, don't use it.
 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
@@ -353,6 +395,16 @@ sub cust_pay {
   #;
 }
 
+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.
@@ -367,6 +419,8 @@ sub cust_bill_pay {
 
 =item cust_credited
 
+=item cust_credit_bill
+
 Returns all applied credits (see L<FS::cust_credit_bill>) for this invoice.
 
 =cut
@@ -378,6 +432,10 @@ sub cust_credited {
   ;
 }
 
+sub cust_credit_bill {
+  shift->cust_credited(@_);
+}
+
 =item tax
 
 Returns the tax amount (see L<FS::cust_bill_pkg>) for this invoice.
index b825b30..89e596d 100644 (file)
@@ -1,7 +1,7 @@
 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;
@@ -12,6 +12,9 @@ use FS::cust_credit_bill_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
@@ -133,13 +136,51 @@ sub insert {
 
 =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
@@ -196,6 +237,7 @@ Returns the package (see L<FS::cust_pkg>) for this invoice line item.
 
 sub cust_pkg {
   my $self = shift;
+  warn "$me $self -> cust_pkg" if $DEBUG;
   qsearchs( 'cust_pkg', { 'pkgnum' => $self->pkgnum } );
 }
 
index 7b30f7d..25c2345 100755 (executable)
@@ -24,7 +24,7 @@ my $error = $access_group->insert;
 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,
index 945f130..d632360 100755 (executable)
@@ -24,7 +24,7 @@ unless ( $supergroup ) {
   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,
diff --git a/httemplate/misc/delete-cust_bill.html b/httemplate/misc/delete-cust_bill.html
new file mode 100644 (file)
index 0000000..3a642b0
--- /dev/null
@@ -0,0 +1,21 @@
+% 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>
index 173d30b..fbb2cf9 100755 (executable)
@@ -2,10 +2,31 @@
   "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;
@@ -36,8 +57,7 @@
 
 % } 
 
-
-% 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;
@@ -149,7 +170,7 @@ my $cust_bill = qsearchs({
   '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;
 
@@ -160,5 +181,3 @@ my $custnum = $cust_bill->custnum;
 my $link = $templatename ? "$templatename-$invnum" : $invnum;
 
 </%init>
-
-
index 0ccdeb8..fe62be6 100644 (file)
@@ -1,9 +1,11 @@
-<% $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) = ('', '');
@@ -18,6 +20,16 @@ my $link = $curuser->access_right('View invoices')
              ? 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>