move from otaker to proper usernum FK
[freeside.git] / FS / FS / cust_pkg.pm
index 5cdca09..e9cc7d9 100644 (file)
@@ -1,17 +1,18 @@
 package FS::cust_pkg;
 
 use strict;
-use vars qw(@ISA $disable_agentcheck $DEBUG $me);
+use base qw( FS::otaker_Mixin FS::cust_main_Mixin FS::location_Mixin
+             FS::m2m_Common FS::option_Common FS::Record );
+use vars qw($disable_agentcheck $DEBUG $me);
 use Carp qw(cluck);
 use Scalar::Util qw( blessed );
 use List::Util qw(max);
 use Tie::IxHash;
+use Time::Local qw( timelocal_nocheck );
 use MIME::Entity;
 use FS::UID qw( getotaker dbh );
 use FS::Misc qw( send_email );
 use FS::Record qw( qsearch qsearchs );
-use FS::m2m_Common;
-use FS::cust_main_Mixin;
 use FS::cust_svc;
 use FS::part_pkg;
 use FS::cust_main;
@@ -40,8 +41,6 @@ use FS::svc_forward;
 # for sending cancel emails in sub cancel
 use FS::Conf;
 
-@ISA = qw( FS::m2m_Common FS::cust_main_Mixin FS::option_Common FS::Record );
-
 $DEBUG = 0;
 $me = '[FS::cust_pkg]';
 
@@ -157,9 +156,9 @@ date
 
 date
 
-=item otaker
+=item usernum
 
-order taker (assigned automatically if null, see L<FS::UID>)
+order taker (see L<FS::access_user>)
 
 =item manual_flag
 
@@ -252,6 +251,26 @@ an optional queue name for ticket additions
 sub insert {
   my( $self, %options ) = @_;
 
+  if ( $self->part_pkg->option('start_1st', 1) && !$self->start_date ) {
+    my ($sec,$min,$hour,$mday,$mon,$year) = (localtime(time) )[0,1,2,3,4,5];
+    $mon += 1 unless $mday == 1;
+    until ( $mon < 12 ) { $mon -= 12; $year++; }
+    $self->start_date( timelocal_nocheck(0,0,0,1,$mon,$year) );
+  }
+
+  my $expire_months = $self->part_pkg->option('expire_months', 1);
+  if ( $expire_months && !$self->expire ) {
+    my $start = $self->start_date || $self->setup || time;
+
+    #false laziness w/part_pkg::add_freq
+    my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($start) )[0,1,2,3,4,5];
+    $mon += $expire_months;
+    until ( $mon < 12 ) { $mon -= 12; $year++; }
+
+    #$self->expire( timelocal_nocheck($sec,$min,$hour,$mday,$mon,$year) );
+    $self->expire( timelocal_nocheck(0,0,0,$mday,$mon,$year) );
+  }
+
   local $SIG{HUP} = 'IGNORE';
   local $SIG{INT} = 'IGNORE';
   local $SIG{QUIT} = 'IGNORE';
@@ -277,15 +296,7 @@ sub insert {
                     );
 
   if ( $self->discountnum ) {
-    #XXX new/custom discount case
-    my $cust_pkg_discount = new FS::cust_pkg_discount {
-      'pkgnum'      => $self->pkgnum,
-      'discountnum' => $self->discountnum,
-      'months_used' => 0,
-      'end_date'    => '', #XXX
-      'otaker'      => $self->otaker,
-    };
-    my $error = $cust_pkg_discount->insert;
+    my $error = $self->insert_discount();
     if ( $error ) {
       $dbh->rollback if $oldAutoCommit;
       return $error;
@@ -304,14 +315,18 @@ sub insert {
   my $conf = new FS::Conf;
 
   if ( $conf->config('ticket_system') && $options{ticket_subject} ) {
-    eval '
-      use lib ( "/opt/rt3/local/lib", "/opt/rt3/lib" );
-      use RT;
-    ';
-    die $@ if $@;
-
-    RT::LoadConfig();
-    RT::Init();
+
+    #eval '
+    #  use lib ( "/opt/rt3/local/lib", "/opt/rt3/lib" );
+    #  use RT;
+    #';
+    #die $@ if $@;
+    #
+    #RT::LoadConfig();
+    #RT::Init();
+    use FS::TicketSystem;
+    FS::TicketSystem->init();
+
     my $q = new RT::Queue($RT::SystemUser);
     $q->Load($options{ticket_queue}) if $options{ticket_queue};
     my $t = new RT::Ticket($RT::SystemUser);
@@ -409,7 +424,7 @@ sub replace {
       : { @_ };
 
   #return "Can't (yet?) change pkgpart!" if $old->pkgpart != $new->pkgpart;
-  return "Can't change otaker!" if $old->otaker ne $new->otaker;
+  #return "Can't change otaker!" if $old->otaker ne $new->otaker;
 
   #allow this *sigh*
   #return "Can't change setup once it exists!"
@@ -509,6 +524,7 @@ sub check {
     || $self->ut_numbern('cancel')
     || $self->ut_numbern('adjourn')
     || $self->ut_numbern('expire')
+    || $self->ut_enum('no_auto', [ '', 'Y' ])
   ;
   return $error if $error;
 
@@ -548,8 +564,6 @@ sub check {
   }
 
   $self->otaker(getotaker) unless $self->otaker;
-  $self->otaker =~ /^(\w{1,32})$/ or return "Illegal otaker";
-  $self->otaker($1);
 
   if ( $self->dbdef_table->column('manual_flag') ) {
     $self->manual_flag('') if $self->manual_flag eq ' ';
@@ -1701,7 +1715,9 @@ sub extra_part_svc {
 
 #seems to benchmark slightly faster...
   qsearch( {
-    'select'      => 'DISTINCT ON (svcpart) part_svc.*',
+    #'select'      => 'DISTINCT ON (svcpart) part_svc.*',
+    #MySQL doesn't grok DISINCT ON
+    'select'      => 'DISTINCT part_svc.*',
     'table'       => 'part_svc',
     'addl_from'   =>
       'LEFT JOIN pkg_svc  ON (     pkg_svc.svcpart   = part_svc.svcpart 
@@ -1943,41 +1959,24 @@ sub cust_main {
   qsearchs( 'cust_main', { 'custnum' => $self->custnum } );
 }
 
+#these subs are in location_Mixin.pm now... unfortunately the POD doesn't mixin
+
 =item cust_location
 
 Returns the location object, if any (see L<FS::cust_location>).
 
-=cut
-
-sub cust_location {
-  my $self = shift;
-  return '' unless $self->locationnum;
-  qsearchs( 'cust_location', { 'locationnum' => $self->locationnum } );
-}
-
 =item cust_location_or_main
 
 If this package is associated with a location, returns the locaiton (see
 L<FS::cust_location>), otherwise returns the customer (see L<FS::cust_main>).
 
-=cut
-
-sub cust_location_or_main {
-  my $self = shift;
-  $self->cust_location || $self->cust_main;
-}
-
 =item location_label [ OPTION => VALUE ... ]
 
 Returns the label of the location object (see L<FS::cust_location>).
 
 =cut
 
-sub location_label {
-  my $self = shift;
-  my $object = $self->cust_location_or_main;
-  $object->location_label(@_);
-}
+#end of subs in location_Mixin.pm now... unfortunately the POD doesn't mixin
 
 =item seconds_since TIMESTAMP
 
@@ -2303,6 +2302,44 @@ sub insert_reason {
   $cust_pkg_reason->insert;
 }
 
+=item insert_discount
+
+Associates this package with a discount (see L<FS::cust_pkg_discount>, possibly
+inserting a new discount on the fly (see L<FS::discount>).
+
+Available options are:
+
+=over 4
+
+=item discountnum
+
+=back
+
+If there is an error, returns the error, otherwise returns false.
+
+=cut
+
+sub insert_discount {
+  #my ($self, %options) = @_;
+  my $self = shift;
+
+  my $cust_pkg_discount = new FS::cust_pkg_discount {
+    'pkgnum'      => $self->pkgnum,
+    'discountnum' => $self->discountnum,
+    'months_used' => 0,
+    'end_date'    => '', #XXX
+    'otaker'      => $self->otaker,
+    #for the create a new discount case
+    '_type'       => $self->discountnum__type,
+    'amount'      => $self->discountnum_amount,
+    'percent'     => $self->discountnum_percent,
+    'months'      => $self->discountnum_months,
+    #'disabled'    => $self->discountnum_disabled,
+  };
+
+  $cust_pkg_discount->insert;
+}
+
 =item set_usage USAGE_VALUE_HASHREF 
 
 USAGE_VALUE_HASHREF is a hashref of svc_acct usage columns and the amounts
@@ -2358,10 +2395,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
@@ -3090,6 +3124,12 @@ sub bulk_change {
   '';
 }
 
+# Used by FS::Upgrade to migrate to a new database.
+sub _upgrade_data {  # class method
+  my ($class, %opts) = @_;
+  $class->_upgrade_otaker(%opts);
+}
+
 =back
 
 =head1 BUGS