diff options
author | ivan <ivan> | 2010-02-06 02:57:12 +0000 |
---|---|---|
committer | ivan <ivan> | 2010-02-06 02:57:12 +0000 |
commit | 942c8b05b17b119a3dad84d7035c76b481dc5b99 (patch) | |
tree | afa91e2825c0c289bfab329a36c274b393c91248 /FS | |
parent | 50aae8bb98effd9b9cc4736aa6d3333245d349d8 (diff) |
discount reporting, RT#6679
Diffstat (limited to 'FS')
-rw-r--r-- | FS/FS.pm | 2 | ||||
-rw-r--r-- | FS/FS/Mason.pm | 2 | ||||
-rw-r--r-- | FS/FS/Report/Table/Monthly.pm | 47 | ||||
-rw-r--r-- | FS/FS/Schema.pm | 14 | ||||
-rw-r--r-- | FS/FS/cust_bill_pkg.pm | 15 | ||||
-rw-r--r-- | FS/FS/cust_bill_pkg_discount.pm | 158 | ||||
-rw-r--r-- | FS/FS/cust_main.pm | 4 | ||||
-rw-r--r-- | FS/FS/cust_pkg.pm | 5 | ||||
-rw-r--r-- | FS/FS/cust_pkg_discount.pm | 21 | ||||
-rw-r--r-- | FS/FS/part_pkg/flat.pm | 11 | ||||
-rw-r--r-- | FS/MANIFEST | 2 | ||||
-rw-r--r-- | FS/t/cust_bill_pkg_discount.t | 5 |
12 files changed, 278 insertions, 8 deletions
@@ -228,6 +228,8 @@ L<FS::cust_pkg_detail> - Customer package details class L<FS:;cust_pkg_discount> - Customer package discount class +L<FS:;cust_bill_pkg_discount> - Customer package discount line item application class + L<FS:;discount> - Discount class L<FS::reason_type> - Reason type class diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm index d812e8184..f20ea647a 100644 --- a/FS/FS/Mason.pm +++ b/FS/FS/Mason.pm @@ -228,6 +228,8 @@ if ( -e $addl_handler_use_file ) { use FS::contact; use FS::svc_pbx; use FS::discount; + use FS::cust_pkg_discount; + use FS::cust_bill_pkg_discount; # Sammath Naur if ( $FS::Mason::addl_handler_use ) { diff --git a/FS/FS/Report/Table/Monthly.pm b/FS/FS/Report/Table/Monthly.pm index fa9949d49..9e7a2882f 100644 --- a/FS/FS/Report/Table/Monthly.pm +++ b/FS/FS/Report/Table/Monthly.pm @@ -417,6 +417,53 @@ sub cust_bill_pkg_detail { } +sub cust_bill_pkg_discount { + my( $self, $speriod, $eperiod, $agentnum, %opt ) = @_; + + #my $where = ''; + #my $comparison = ''; + #if ( $opt{'classnum'} =~ /^(\d+)$/ ) { + # if ( $1 == 0 ) { + # $comparison = "IS NULL"; + # } else { + # $comparison = "= $1"; + # } + # + # if ( $opt{'use_override'} ) { + # $where = "( + # part_pkg.classnum $comparison AND pkgpart_override IS NULL OR + # override.classnum $comparison AND pkgpart_override IS NOT NULL + # )"; + # } else { + # $where = "part_pkg.classnum $comparison"; + # } + #} + + $agentnum ||= $opt{'agentnum'}; + + my $total_sql = + " SELECT COALESCE( SUM( cust_bill_pkg_discount.amount ), 0 ) "; + + #$total_sql .= + # " / CASE COUNT(cust_pkg.*) WHEN 0 THEN 1 ELSE COUNT(cust_pkg.*) END " + # if $opt{average_per_cust_pkg}; + + $total_sql .= + " FROM cust_bill_pkg_discount + LEFT JOIN cust_bill_pkg USING ( billpkgnum ) + LEFT JOIN cust_bill USING ( invnum ) + LEFT JOIN cust_main USING ( custnum ) + WHERE ". $self->in_time_period_and_agent($speriod, $eperiod, $agentnum); + # LEFT JOIN cust_pkg_discount USING ( pkgdiscountnum ) + # LEFT JOIN discount USING ( discountnum ) + # LEFT JOIN cust_pkg USING ( pkgnum ) + # LEFT JOIN part_pkg USING ( pkgpart ) + # LEFT JOIN part_pkg AS override ON pkgpart_override = override.pkgpart + + return $self->scalar_sql($total_sql); + +} + sub setup_pkg { shift->pkg_field( @_, 'setup' ); } sub susp_pkg { shift->pkg_field( @_, 'susp' ); } sub cancel_pkg { shift->pkg_field( @_, 'cancel'); } diff --git a/FS/FS/Schema.pm b/FS/FS/Schema.pm index ad094d7c1..19c2e8e58 100644 --- a/FS/FS/Schema.pm +++ b/FS/FS/Schema.pm @@ -1317,12 +1317,26 @@ sub tables_hashref { 'months_used', 'decimal', 'NULL', '', '', '', 'end_date', @date_type, '', '', 'otaker', 'varchar', '', 32, '', '', + 'disabled', 'char', 'NULL', 1, '', '', ], 'primary_key' => 'pkgdiscountnum', 'unique' => [], 'index' => [ [ 'pkgnum' ], [ 'discountnum' ] ], }, + 'cust_bill_pkg_discount' => { + 'columns' => [ + 'billpkgdiscountnum', 'serial', '', '', '', '', + 'billpkgnum', 'int', '', '', '', '', + 'pkgdiscountnum', 'int', '', '', '', '', + 'amount', @money_type, '', '', + 'months', 'decimal', 'NULL', '', '', '', + ], + 'primary_key' => 'billpkgdiscountnum', + 'unique' => [], + 'index' => [ [ 'billpkgnum' ], [ 'pkgdiscountnum' ] ], + }, + 'discount' => { 'columns' => [ 'discountnum', 'serial', '', '', '', '', diff --git a/FS/FS/cust_bill_pkg.pm b/FS/FS/cust_bill_pkg.pm index cd049d121..cb070d77a 100644 --- a/FS/FS/cust_bill_pkg.pm +++ b/FS/FS/cust_bill_pkg.pm @@ -174,6 +174,17 @@ sub insert { } } + if ( $self->get('discounts') ) { + foreach my $cust_bill_pkg_discount ( @{$self->get('discounts')} ) { + $cust_bill_pkg_discount->billpkgnum($self->billpkgnum); + $error = $cust_bill_pkg_discount->insert; + if ( $error ) { + $dbh->rollback if $oldAutoCommit; + return "error inserting cust_bill_pkg_discount: $error"; + } + } + } + if ( $self->_cust_tax_exempt_pkg ) { foreach my $cust_tax_exempt_pkg ( @{$self->_cust_tax_exempt_pkg} ) { $cust_tax_exempt_pkg->billpkgnum($self->billpkgnum); @@ -763,10 +774,10 @@ sub cust_bill_pkg_display { my $type = $opt{type} if exists $opt{type}; my @result; - if ( scalar( $self->get('display') ) ) { + if ( $self->get('display') ) { @result = grep { defined($type) ? ($type eq $_->type) : 1 } @{ $self->get('display') }; - }else{ + } else { my $hashref = { 'billpkgnum' => $self->billpkgnum }; $hashref->{type} = $type if defined($type); diff --git a/FS/FS/cust_bill_pkg_discount.pm b/FS/FS/cust_bill_pkg_discount.pm new file mode 100644 index 000000000..e7dd5f22f --- /dev/null +++ b/FS/FS/cust_bill_pkg_discount.pm @@ -0,0 +1,158 @@ +package FS::cust_bill_pkg_discount; + +use strict; +use base qw( FS::cust_main_Mixin FS::Record ); +use FS::Record qw( qsearch qsearchs ); +use FS::cust_bill_pkg; +use FS::cust_pkg_discount; + +=head1 NAME + +FS::cust_bill_pkg_discount - Object methods for cust_bill_pkg_discount records + +=head1 SYNOPSIS + + use FS::cust_bill_pkg_discount; + + $record = new FS::cust_bill_pkg_discount \%hash; + $record = new FS::cust_bill_pkg_discount { 'column' => 'value' }; + + $error = $record->insert; + + $error = $new_record->replace($old_record); + + $error = $record->delete; + + $error = $record->check; + +=head1 DESCRIPTION + +An FS::cust_bill_pkg_discount object represents the slice of a customer +applied to a line item. FS::cust_bill_pkg_discount inherits from +FS::Record. The following fields are currently supported: + +=over 4 + +=item billpkgdiscountnum + +primary key + +=item billpkgnum + +Line item (see L<FS::cust_bill_pkg>) + +=item pkgdiscountnum + +Customer discount (see L<FS::cust_pkg_discount>) + +=item amount + +Amount discounted from the line itme. + +=item months + +Number of months of discount this represents. + +=back + +=head1 METHODS + +=over 4 + +=item new HASHREF + +Creates a new record. To add the record to the database, see L<"insert">. + +Note that this stores the hash reference, not a distinct copy of the hash it +points to. You can ask the object for a copy with the I<hash> method. + +=cut + +# the new method can be inherited from FS::Record, if a table method is defined + +sub table { 'cust_bill_pkg_discount'; } + +=item insert + +Adds this record to the database. If there is an error, returns the error, +otherwise returns false. + +=cut + +# the insert method can be inherited from FS::Record + +=item delete + +Delete this record from the database. + +=cut + +# the delete method can be inherited from FS::Record + +=item replace OLD_RECORD + +Replaces the OLD_RECORD with this one in the database. If there is an error, +returns the error, otherwise returns false. + +=cut + +# the replace method can be inherited from FS::Record + +=item check + +Checks all fields to make sure this is a valid record. If there is +an error, returns the error, otherwise returns false. Called by the insert +and replace methods. + +=cut + +sub check { + my $self = shift; + + my $error = + $self->ut_numbern('billpkgdiscountnum') + || $self->ut_foreign_key('billpkgnum', 'cust_bill_pkg', 'billpkgnum' ) + || $self->ut_foreign_key('pkgdiscountnum', 'cust_pkg_discount', 'pkgdiscountnum' ) + || $self->ut_money('amount') + || $self->ut_float('months') + ; + return $error if $error; + + $self->SUPER::check; +} + +=item cust_bill_pkg + +Returns the associated line item (see L<FS::cust_bill_pkg>). + +=cut + +sub cust_bill_pkg { + my $self = shift; + qsearchs( 'cust_bill_pkg', { 'billpkgnum' => $self->billpkgnum } ) ; +} + +=item cust_pkg_discount + +Returns the associated customer discount (see L<FS::cust_pkg_discount>). + +=cut + +sub cust_pkg_discount { + my $self = shift; + qsearchs( 'cust_pkg_discount', { 'pkgdiscountnum' => $self->pkgdiscountnum }); +} + + +=back + +=head1 BUGS + +=head1 SEE ALSO + +L<FS::Record>, schema.html from the base documentation. + +=cut + +1; + diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 590e32ff2..d4ce0fd67 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -3065,7 +3065,7 @@ sub _make_lines { my $old_cust_pkg = new FS::cust_pkg \%hash; my @details = (); - + my @discounts = (); my $lineitems = 0; $cust_pkg->pkgpart($part_pkg->pkgpart); @@ -3150,6 +3150,7 @@ sub _make_lines { ); my %param = ( 'precommit_hooks' => $precommit_hooks, 'increment_next_bill' => $increment_next_bill, + 'discounts' => \@discounts, ); my $method = $options{cancel} ? 'calc_cancel' : 'calc_recur'; @@ -3229,6 +3230,7 @@ sub _make_lines { 'unitrecur' => $unitrecur, 'quantity' => $cust_pkg->quantity, 'details' => \@details, + 'discounts' => \@discounts, 'hidden' => $part_pkg->hidden, }; diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index acc73dfda..c3734b54e 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -2388,10 +2388,7 @@ sub cust_pkg_discount { sub cust_pkg_discount_active { my $self = shift; - grep { my $d = $_->discount; - ! $d->months || $_->months_used < $d->months; # XXX also end date - } - $self->cust_pkg_discount; + grep { $_->status eq 'active' } $self->cust_pkg_discount; } =back diff --git a/FS/FS/cust_pkg_discount.pm b/FS/FS/cust_pkg_discount.pm index 8dd00de89..1b97bba03 100644 --- a/FS/FS/cust_pkg_discount.pm +++ b/FS/FS/cust_pkg_discount.pm @@ -1,7 +1,7 @@ package FS::cust_pkg_discount; use strict; -use base qw( FS::Record ); +use base qw( FS::cust_main_Mixin FS::Record ); use FS::Record qw( dbh qsearchs ); # qsearch ); use FS::cust_pkg; use FS::discount; @@ -165,6 +165,7 @@ sub check { || $self->ut_float('months_used') #actually decimal, but this will do || $self->ut_numbern('end_date') || $self->ut_text('otaker') + || $self->ut_enum('disabled', [ '', 'Y' ] ) ; return $error if $error; @@ -207,6 +208,24 @@ sub increment_months_used { $self->replace(); } +=item status + +=cut + +sub status { + my $self = shift; + my $discount = $self->discount; + + if ( $self->disabled ne 'Y' + and ( ! $discount->months || $self->months_used < $discount->months ) + #XXX also end date + ) { + 'active'; + } else { + 'expired'; + } +} + =back =head1 BUGS diff --git a/FS/FS/part_pkg/flat.pm b/FS/FS/part_pkg/flat.pm index e5fc089c4..b825dded6 100644 --- a/FS/FS/part_pkg/flat.pm +++ b/FS/FS/part_pkg/flat.pm @@ -11,6 +11,7 @@ use List::Util qw(min); # max); use FS::UI::bytecount; use FS::Conf; use FS::part_pkg; +use FS::cust_bill_pkg_discount; @ISA = qw(FS::part_pkg); @@ -190,6 +191,16 @@ sub calc_discount { $amount *= $months; $amount = sprintf('%.2f', $amount); + next unless $amount > 0; + + #record details in cust_bill_pkg_discount + my $cust_bill_pkg_discount = new FS::cust_bill_pkg_discount { + 'pkgdiscountnum' => $cust_pkg_discount->pkgdiscountnum, + 'amount' => $amount, + 'months' => $months, + }; + push @{ $param->{'discounts'} }, $cust_bill_pkg_discount; + #add details on discount to invoice my $conf = new FS::Conf; my $money_char = $conf->config('money_char') || '$'; diff --git a/FS/MANIFEST b/FS/MANIFEST index a92b9ddd7..71523458a 100644 --- a/FS/MANIFEST +++ b/FS/MANIFEST @@ -480,3 +480,5 @@ FS/discount.pm t/discount.t FS/cust_pkg_discount.pm t/cust_pkg_discount.t +FS/cust_bill_pkg_discount.pm +t/cust_bill_pkg_discount.t diff --git a/FS/t/cust_bill_pkg_discount.t b/FS/t/cust_bill_pkg_discount.t new file mode 100644 index 000000000..74923e1b0 --- /dev/null +++ b/FS/t/cust_bill_pkg_discount.t @@ -0,0 +1,5 @@ +BEGIN { $| = 1; print "1..1\n" } +END {print "not ok 1\n" unless $loaded;} +use FS::cust_bill_pkg_discount; +$loaded=1; +print "ok 1\n"; |