From: ivan Date: Sun, 4 Oct 2009 02:09:14 +0000 (+0000) Subject: delete invoices, RT#4048 X-Git-Tag: root_of_svc_elec_features~821 X-Git-Url: http://git.freeside.biz/gitweb/?p=freeside.git;a=commitdiff_plain;h=3a02e398ce013116c6ee97fc18472a6f40e0798d delete invoices, RT#4048 --- diff --git a/FS/FS/AccessRight.pm b/FS/FS/AccessRight.pm index fc309fa48..a54d27082 100644 --- a/FS/FS/AccessRight.pm +++ b/FS/FS/AccessRight.pm @@ -150,6 +150,7 @@ tie my %rights, 'Tie::IxHash', 'Customer invoice / financial info rights' => [ 'View invoices', 'Resend invoices', #NEWNEW + 'Delete invoices', #new, but no need to phase in 'View customer tax exemptions', #yow 'Add customer tax adjustment', #new, but no need to phase in 'View customer batched payments', #NEW @@ -285,14 +286,38 @@ tie my %rights, 'Tie::IxHash', =item rights -Returns a list of right names. +Returns the full list of right names. =cut - sub rights { +sub rights { #my $class = shift; map { ref($_) ? $_->{'rightname'} : $_ } map @{ $rights{$_} }, keys %rights; - } +} + +=item default_superuser_rights + +Most (but not all) right names. + +=cut + +sub default_superuser_rights { + my $class = shift; + my %omit = map { $_=>1 } ( + 'Delete customer', + 'Delete invoices', + 'Delete payment', + 'Delete credit', #? + 'Delete refund', #? + 'Time queue', + 'Redownload resolved batches', + 'Raw SQL', + 'Configuration download', + ); + + no warnings 'uninitialized'; + grep { ! $omit{$_} } $class->rights; +} =item rights_info diff --git a/FS/FS/Conf.pm b/FS/FS/Conf.pm index 7112417d5..3b37feacc 100644 --- a/FS/FS/Conf.pm +++ b/FS/FS/Conf.pm @@ -728,7 +728,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', }, diff --git a/FS/FS/Setup.pm b/FS/FS/Setup.pm index cba3c7e3c..edfe912ea 100644 --- a/FS/FS/Setup.pm +++ b/FS/FS/Setup.pm @@ -364,7 +364,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, diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index 79f85c807..55faa36bc 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -160,7 +160,50 @@ 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_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 @@ -460,6 +503,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) for this invoice. @@ -474,6 +527,8 @@ sub cust_bill_pay { =item cust_credited +=item cust_credit_bill + Returns all applied credits (see L) for this invoice. =cut @@ -485,6 +540,10 @@ sub cust_credited { ; } +sub cust_credit_bill { + shift->cust_credited(@_); +} + =item cust_bill_pay_pkgnum PKGNUM Returns all payment applications (see L) for this invoice diff --git a/FS/FS/cust_bill_pkg.pm b/FS/FS/cust_bill_pkg.pm index 96f09c915..9d7aae23c 100644 --- a/FS/FS/cust_bill_pkg.pm +++ b/FS/FS/cust_bill_pkg.pm @@ -1,7 +1,7 @@ package FS::cust_bill_pkg; use strict; -use vars qw( @ISA $DEBUG ); +use vars qw( @ISA $DEBUG $me ); use FS::Record qw( qsearch qsearchs dbdef dbh ); use FS::cust_main_Mixin; use FS::cust_pkg; @@ -12,10 +12,14 @@ use FS::cust_bill_pkg_display; use FS::cust_bill_pay_pkg; use FS::cust_credit_bill_pkg; use FS::cust_tax_exempt_pkg; +use FS::cust_bill_pkg_tax_location; +use FS::cust_bill_pkg_tax_rate_location; +use FS::cust_tax_adjustment; @ISA = qw( FS::cust_main_Mixin FS::Record ); -$DEBUG = 0; +$DEBUG = 2; +$me = '[FS::cust_bill_pkg]'; =head1 NAME @@ -40,30 +44,57 @@ supported: =over 4 -=item billpkgnum - primary key +=item billpkgnum -=item invnum - invoice (see L) +primary key -=item pkgnum - package (see L) or 0 for the special virtual sales tax package, or -1 for the virtual line item (itemdesc is used for the line) +=item invnum -=item pkgpart_override - optional package definition (see L) override -=item setup - setup fee +invoice (see L) -=item recur - recurring fee +=item pkgnum -=item sdate - starting date of recurring fee +package (see L) or 0 for the special virtual sales tax package, or -1 for the virtual line item (itemdesc is used for the line) -=item edate - ending date of recurring fee +=item pkgpart_override -=item itemdesc - Line item description (overrides normal package description) +optional package definition (see L) override -=item quantity - If not set, defaults to 1 +=item setup -=item unitsetup - If not set, defaults to setup +setup fee -=item unitrecur - If not set, defaults to recur +=item recur -=item hidden - If set to Y, indicates data should not appear as separate line item on invoice +recurring fee + +=item sdate + +starting date of recurring fee + +=item edate + +ending date of recurring fee + +=item itemdesc + +Line item description (overrides normal package description) + +=item quantity + +If not set, defaults to 1 + +=item unitsetup + +If not set, defaults to setup + +=item unitrecur + +If not set, defaults to recur + +=item hidden + +If set to Y, indicates data should not appear as separate line item on invoice =back @@ -196,13 +227,65 @@ 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_bill_pkg_display + cust_bill_pkg_tax_location + cust_bill_pkg_tax_rate_location + 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; + } + } + + } + + foreach my $cust_tax_adjustment ( + qsearch('cust_tax_adjustment', { billpkgnum=>$self->billpkgnum }) + ) { + $cust_tax_adjustment->billpkgnum(''); #NULL + my $error = $cust_tax_adjustment->replace; + 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; + + ''; + } #alas, bin/follow-tax-rename @@ -263,6 +346,7 @@ Returns the package (see L) for this invoice line item. sub cust_pkg { my $self = shift; + warn "$me $self -> cust_pkg"; qsearchs( 'cust_pkg', { 'pkgnum' => $self->pkgnum } ); } diff --git a/FS/bin/freeside-addgroup b/FS/bin/freeside-addgroup index 7b30f7d95..25c23455a 100755 --- a/FS/bin/freeside-addgroup +++ b/FS/bin/freeside-addgroup @@ -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, diff --git a/bin/mapsecrets2access_user b/bin/mapsecrets2access_user index 945f130ef..d632360f5 100755 --- a/bin/mapsecrets2access_user +++ b/bin/mapsecrets2access_user @@ -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 index 000000000..3a642b0e9 --- /dev/null +++ b/httemplate/misc/delete-cust_bill.html @@ -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; + + diff --git a/httemplate/view/cust_bill.cgi b/httemplate/view/cust_bill.cgi index 2673e8239..5540221d9 100755 --- a/httemplate/view/cust_bill.cgi +++ b/httemplate/view/cust_bill.cgi @@ -2,10 +2,31 @@ "View this customer (#$display_custnum)" => "${p}view/cust_main.cgi?$custnum", )) %> +% if ( $conf->exists('deleteinvoices') +% && $curuser->access_right('Delete invoices' ) +% ) +% { + + + + Delete this invoice +

+ +% } % 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') % && ! $conf->exists('pkg-balances') % ) % { @@ -37,8 +58,7 @@ % } - -% if ( $FS::CurrentUser::CurrentUser->access_right('Resend invoices') ) { +% if ( $curuser->access_right('Resend invoices') ) { Re-print this invoice @@ -54,10 +74,9 @@ % } - % if ( $conf->exists('invoice_latex') ) { - View typeset invoice + View typeset invoice PDF

% } @@ -83,8 +102,10 @@ <% 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; @@ -105,7 +126,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; @@ -117,5 +138,3 @@ my $display_custnum = $cust_bill->cust_main->display_custnum; my $link = $templatename ? "$templatename-$invnum" : $invnum; - - diff --git a/httemplate/view/cust_main/payment_history.html b/httemplate/view/cust_main/payment_history.html index 0050daf9d..2ac3f2633 100644 --- a/httemplate/view/cust_main/payment_history.html +++ b/httemplate/view/cust_main/payment_history.html @@ -379,7 +379,7 @@ my %opt = ( qw( card_refund-days ) ), ( map { $_ => $conf->exists($_) } - qw( deletepayments deleterefunds pkg-balances ) + qw( deleteinvoices deletepayments deleterefunds pkg-balances ) ) ); diff --git a/httemplate/view/cust_main/payment_history/invoice.html b/httemplate/view/cust_main/payment_history/invoice.html index 39c67396e..c0d32df4d 100644 --- a/httemplate/view/cust_main/payment_history/invoice.html +++ b/httemplate/view/cust_main/payment_history/invoice.html @@ -1,9 +1,11 @@ -<% $link %><% $pre %>Invoice #<% $invnum %> -(Balance $ <% $cust_bill->owed %>)<% $post %><% $link ? '' : '' %><% $events %> +<% $link %><% $pre %>Invoice #<% $cust_bill->display_invnum %> +(Balance $ <% $cust_bill->owed %>)<% $post %><% $link ? '' : '' %><% $delete %><% $events %> <%init> my( $cust_bill, %opt ) = @_; +my $conf = new FS::Conf; + my $curuser = $FS::CurrentUser::CurrentUser; my($pre, $post) = ('', ''); @@ -18,6 +20,15 @@ my $link = $curuser->access_right('View invoices') ? qq!! : ''; +my $delete = ''; +if ( $opt{'deleteinvoices'} && $curuser->access_right('Delete invoices') ) { + $delete = qq! (delete)!; +} + my $events = ''; #1.9 if ( $cust_bill->num_cust_event @@ -26,8 +37,8 @@ if ( $cust_bill->num_cust_event ) ) { $events = - qq!
( View invoice events )'; + qq!
( View invoice events )'; } #