package FS::cust_pkg;
-
-use strict;
-use base qw( FS::otaker_Mixin FS::cust_main_Mixin
+use base qw( FS::otaker_Mixin FS::cust_main_Mixin FS::Sales_Mixin
FS::contact_Mixin FS::location_Mixin
FS::m2m_Common FS::option_Common );
+
+use strict;
use vars qw($disable_agentcheck $DEBUG $me);
use Carp qw(cluck);
use Scalar::Util qw( blessed );
use FS::cust_pkg_discount;
use FS::discount;
use FS::UI::Web;
-use Data::Dumper;
+use FS::sales;
# need to 'use' these instead of 'require' in sub { cancel, suspend, unsuspend,
# setup }
|| $self->ut_numbern('pkgpart')
|| $self->ut_foreign_keyn('contactnum', 'contact', 'contactnum' )
|| $self->ut_foreign_keyn('locationnum', 'cust_location', 'locationnum')
+ || $self->ut_foreign_keyn('salesnum', 'sales', 'salesnum')
+ || $self->ut_numbern('quantity')
|| $self->ut_numbern('start_date')
|| $self->ut_numbern('setup')
|| $self->ut_numbern('bill')
Can be set true to adjust the next bill date forward by
the amount of time the account was inactive. This was set true by default
-since 1.4.2 and 1.5.0pre6; however, starting with 1.7.0 this needs to be
-explicitly requested. Price plans for which this makes sense (anniversary-date
-based than prorate or subscription) could have an option to enable this
-behaviour?
+in the past (from 1.4.2 and 1.5.0pre6 through 1.7.0), but now needs to be
+explicitly requested with this option or in the price plan.
=back
New refnum (see L<FS::part_referral>).
+=item quantity
+
+New quantity; if unspecified, the new package will have the same quantity
+as the old.
+
=item cust_pkg
"New" (existing) FS::cust_pkg object. The package's services and other
my $self = shift;
my $opt = ref($_[0]) ? shift : { @_ };
-# my ($custnum, $pkgparts, $remove_pkgnum, $return_cust_pkg, $refnum) = @_;
-#
-
my $conf = new FS::Conf;
# Transactionize this whole mess
my $time = time;
- #$hash{$_} = $self->$_() foreach qw( last_bill bill );
-
- #$hash{$_} = $self->$_() foreach qw( setup );
-
$hash{'setup'} = $time if $self->setup;
$hash{'change_date'} = $time;
$hash{$date} = $self->getfield($date);
}
}
+
# allow $opt->{'locationnum'} = '' to specifically set it to null
# (i.e. customer default location)
$opt->{'locationnum'} = $self->locationnum if !exists($opt->{'locationnum'});
} else {
# Create the new package.
$cust_pkg = new FS::cust_pkg {
- custnum => $custnum,
- pkgpart => ( $opt->{'pkgpart'} || $self->pkgpart ),
- refnum => ( $opt->{'refnum'} || $self->refnum ),
- locationnum => ( $opt->{'locationnum'} ),
+ custnum => $custnum,
+ locationnum => $opt->{'locationnum'},
+ ( map { $_ => ( $opt->{$_} || $self->$_() ) }
+ qw( pkgpart quantity refnum salesnum )
+ ),
%hash,
};
$error = $cust_pkg->insert( 'change' => 1,
=item locationnum
-The pkgpart and locationnum of the new package, with the same
+=item quantity
+
+The pkgpart. locationnum, and quantity of the new package, with the same
meaning as in C<change>.
=back
if $opt->{'pkgpart'} and $opt->{'pkgpart'} != $change_to->pkgpart;
my $new_locationnum = $opt->{'locationnum'}
if $opt->{'locationnum'} and $opt->{'locationnum'} != $change_to->locationnum;
- if ( $new_pkgpart or $new_locationnum ) {
+ my $new_quantity = $opt->{'quantity'}
+ if $opt->{'quantity'} and $opt->{'quantity'} != $change_to->quantity;
+ if ( $new_pkgpart or $new_locationnum or $new_quantity ) {
# it hasn't been billed yet, so in principle we could just edit
# it in place (w/o a package change), but that's bad form.
# So change the package according to the new options...
$self->set('change_to_pkgnum', $err_or_pkg->pkgnum);
$self->set('expire', $date); # in case it's different
$err_or_pkg->set('start_date', $date);
+ $err_or_pkg->set('change_date', '');
+ $err_or_pkg->set('change_pkgnum', '');
$error = $self->replace ||
$err_or_pkg->replace ||
- $err_or_pkg->delete;
+ $change_to->cancel ||
+ $change_to->delete;
} else {
$error = $err_or_pkg;
}
if $opt->{'pkgpart'} and $opt->{'pkgpart'} != $self->pkgpart;
my $new_locationnum = $opt->{'locationnum'}
if $opt->{'locationnum'} and $opt->{'locationnum'} != $self->locationnum;
- return '' unless $new_pkgpart or $new_locationnum; # wouldn't do anything
+ my $new_quantity = $opt->{'quantity'}
+ if $opt->{'quantity'} and $opt->{'quantity'} != $self->quantity;
- my %hash = (
- 'custnum' => $self->custnum,
- 'pkgpart' => ($opt->{'pkgpart'} || $self->pkgpart),
- 'locationnum' => ($opt->{'locationnum'} || $self->locationnum),
- 'start_date' => $date,
- );
- my $new = FS::cust_pkg->new(\%hash);
+ return '' unless $new_pkgpart or $new_locationnum or $new_quantity; # wouldn't do anything
+
+ # allow $opt->{'locationnum'} = '' to specifically set it to null
+ # (i.e. customer default location)
+ $opt->{'locationnum'} = $self->locationnum if !exists($opt->{'locationnum'});
+
+ my $new = FS::cust_pkg->new( {
+ custnum => $self->custnum,
+ locationnum => $opt->{'locationnum'},
+ start_date => $date,
+ map { $_ => ( $opt->{$_} || $self->$_() ) }
+ qw( pkgpart quantity refnum salesnum )
+ } );
$error = $new->insert('change' => 1,
'allow_pkgpart' => ($new_pkgpart ? 0 : 1));
if ( !$error ) {
=item set_quantity QUANTITY
-Change the package's quantity field. This is the one package property
+Change the package's quantity field. This is one of the few package properties
that can safely be changed without canceling and reordering the package
(because it doesn't affect tax eligibility). Returns an error or an
empty string.
sub set_quantity {
my $self = shift;
$self = $self->replace_old; # just to make sure
- my $qty = shift;
- ($qty =~ /^\d+$/ and $qty > 0) or return "bad package quantity $qty";
- $self->set('quantity' => $qty);
+ $self->quantity(shift);
+ $self->replace;
+}
+
+=item set_salesnum SALESNUM
+
+Change the package's salesnum (sales person) field. This is one of the few
+package properties that can safely be changed without canceling and reordering
+the package (because it doesn't affect tax eligibility). Returns an error or
+an empty string.
+
+=cut
+
+sub set_salesnum {
+ my $self = shift;
+ $self = $self->replace_old; # just to make sure
+ $self->salesnum(shift);
$self->replace;
}
use Storable 'thaw';
use MIME::Base64;
+use Data::Dumper;
sub process_bulk_cust_pkg {
my $job = shift;
my $param = thaw(decode_base64(shift));
"cust_main.agentnum = $1";
}
+ ##
+ # parse customer sales person
+ ##
+
+ if ( $params->{'cust_main_salesnum'} =~ /^(\d+)$/ ) {
+ push @where, ($1 > 0) ? "cust_main.salesnum = $1"
+ : 'cust_main.salesnum IS NULL';
+ }
+
+
+ ##
+ # parse sales person
+ ##
+
+ if ( $params->{'salesnum'} =~ /^(\d+)$/ ) {
+ push @where, ($1 > 0) ? "cust_pkg.salesnum = $1"
+ : 'cust_pkg.salesnum IS NULL';
+ }
+
##
# parse custnum
##