summaryrefslogtreecommitdiff
path: root/FS
diff options
context:
space:
mode:
authorivan <ivan>2010-02-06 02:57:12 +0000
committerivan <ivan>2010-02-06 02:57:12 +0000
commit942c8b05b17b119a3dad84d7035c76b481dc5b99 (patch)
treeafa91e2825c0c289bfab329a36c274b393c91248 /FS
parent50aae8bb98effd9b9cc4736aa6d3333245d349d8 (diff)
discount reporting, RT#6679
Diffstat (limited to 'FS')
-rw-r--r--FS/FS.pm2
-rw-r--r--FS/FS/Mason.pm2
-rw-r--r--FS/FS/Report/Table/Monthly.pm47
-rw-r--r--FS/FS/Schema.pm14
-rw-r--r--FS/FS/cust_bill_pkg.pm15
-rw-r--r--FS/FS/cust_bill_pkg_discount.pm158
-rw-r--r--FS/FS/cust_main.pm4
-rw-r--r--FS/FS/cust_pkg.pm5
-rw-r--r--FS/FS/cust_pkg_discount.pm21
-rw-r--r--FS/FS/part_pkg/flat.pm11
-rw-r--r--FS/MANIFEST2
-rw-r--r--FS/t/cust_bill_pkg_discount.t5
12 files changed, 278 insertions, 8 deletions
diff --git a/FS/FS.pm b/FS/FS.pm
index bfa23af..67c2cd2 100644
--- a/FS/FS.pm
+++ b/FS/FS.pm
@@ -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 d812e81..f20ea64 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 fa9949d..9e7a288 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 ad094d7..19c2e8e 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 cd049d1..cb070d7 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 0000000..e7dd5f2
--- /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 590e32f..d4ce0fd 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 acc73df..c3734b5 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 8dd00de..1b97bba 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 e5fc089..b825dde 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 a92b9dd..7152345 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 0000000..74923e1
--- /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";