freeside/FS/FS h_cust_svc.pm,NONE,1.1 h_Common.pm,NONE,1.1 h_svc_acct.pm,NONE,1.1 h_svc_broadband.pm,NONE,1.1 h_svc_domain.pm,NONE,1.1 h_svc_external.pm,NONE,1.1 h_svc_forward.pm,NONE,1.1 h_svc_www.pm,NONE,1.1 cust_bill.pm,1.101,1.102 cust_pkg.pm,1.50,1.51 cust_svc.pm,1.46,1.47 cust_main.pm,1.167,1.168 Record.pm,1.91,1.92 svc_acct.pm,1.166,1.167

ivan ivan at pouncequick.420.am
Wed Dec 29 04:00:12 PST 2004


Update of /home/cvs/cvsroot/freeside/FS/FS
In directory pouncequick:/tmp/cvs-serv14192/FS/FS

Modified Files:
	cust_bill.pm cust_pkg.pm cust_svc.pm cust_main.pm Record.pm 
	svc_acct.pm 
Added Files:
	h_cust_svc.pm h_Common.pm h_svc_acct.pm h_svc_broadband.pm 
	h_svc_domain.pm h_svc_external.pm h_svc_forward.pm 
	h_svc_www.pm 
Log Message:
historical (immutable) invoice details about services and other history infrastructure

Index: cust_main.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_main.pm,v
retrieving revision 1.167
retrieving revision 1.168
diff -u -d -r1.167 -r1.168
--- cust_main.pm	20 Dec 2004 10:13:37 -0000	1.167
+++ cust_main.pm	29 Dec 2004 12:00:06 -0000	1.168
@@ -1009,6 +1009,27 @@
   grep { ! $_->susp } $self->ncancelled_pkgs;
 }
 
+=item num_cancelled_pkgs
+
+Returns the number of cancelled packages (see L<FS::cust_pkg>) for this
+customer.
+
+=cut
+
+sub num_cancelled_pkgs {
+  my $self = shift;
+  $self->num_pkgs("cancel IS NOT NULL AND cust_pkg.cancel != 0");
+}
+
+sub num_pkgs {
+  my( $self, $sql ) = @_;
+  my $sth = dbh->prepare(
+    "SELECT COUNT(*) FROM cust_pkg WHERE custnum = ? AND $sql"
+  ) or die dbh->errstr;
+  $sth->execute($self->custnum) or die $sth->errstr;
+  $sth->fetchrow_arrayref->[0];
+}
+
 =item unsuspend
 
 Unsuspends all unflagged suspended packages (see L</unflagged_suspended_pkgs>

--- NEW FILE: h_svc_domain.pm ---
package FS::h_svc_domain;

use strict;
use vars qw( @ISA );
use FS::h_Common;
use FS::svc_domain;

@ISA = qw( FS::h_Common FS::svc_domain );

sub table { 'h_svc_domain' };

=head1 NAME

FS::h_svc_domain - Historical domain objects

=head1 SYNOPSIS

=head1 DESCRIPTION

An FS::h_svc_domain object represents a historical domain.  FS::h_svc_domain
inherits from FS::h_Common and FS::svc_domain.

=head1 BUGS

=head1 SEE ALSO

L<FS::h_Common>, L<FS::svc_domain>, L<FS::Record>, schema.html from the base
documentation.

=cut

1;


Index: Record.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/Record.pm,v
retrieving revision 1.91
retrieving revision 1.92
diff -u -d -r1.91 -r1.92
--- Record.pm	22 Nov 2004 18:20:21 -0000	1.91
+++ Record.pm	29 Dec 2004 12:00:06 -0000	1.92
@@ -180,7 +180,7 @@
   }
 }
 
-=item qsearch TABLE, HASHREF, SELECT, EXTRA_SQL, CACHE_OBJ
+=item qsearch TABLE, HASHREF, SELECT, EXTRA_SQL, CACHE_OBJ, AS
 
 Searches the database for all records matching (at least) the key/value pairs
 in HASHREF.  Returns all the records found as `FS::TABLE' objects if that
@@ -199,7 +199,7 @@
 =cut
 
 sub qsearch {
-  my($stable, $record, $select, $extra_sql, $cache ) = @_;
+  my($stable, $record, $select, $extra_sql, $cache, $as ) = @_;
   #$stable =~ /^([\w\_]+)$/ or die "Illegal table: $table";
   #for jsearch
   $stable =~ /^([\w\s\(\)\.\,\=]+)$/ or die "Illegal table: $stable";
@@ -223,6 +223,7 @@
   }
 
   my $statement = "SELECT $select FROM $stable";
+  $statement .= " AS $as" if $as;
   if ( @real_fields or @virtual_fields ) {
     $statement .= ' WHERE '. join(' AND ',
       ( map {

--- NEW FILE: h_svc_www.pm ---
package FS::h_svc_www;

use strict;
use vars qw( @ISA );
se FS::Record qw(qsearchs);
use FS::h_Common;
use FS::svc_www;
use FS::h_domain_record;

@ISA = qw( FS::h_Common FS::svc_www );

sub table { 'h_svc_www' };

=head1 NAME

FS::h_svc_www - Historical web virtual host objects

=head1 SYNOPSIS

=head1 METHODS

=over 4

=item domain_record

=cut

sub domain_record {
  my $self = shift;
  qsearchs( 'h_domain_record',
            { 'recnum' => $self->recnum },
            FS::h_domain_record->sql_h_search(@_),
          );
}

=back

=head1 DESCRIPTION

An FS::h_svc_www object represents a historical web virtual host.
FS::h_svc_www inherits from FS::h_Common and FS::svc_www.

=head1 BUGS

=head1 SEE ALSO

L<FS::h_Common>, L<FS::svc_www>, L<FS::Record>, schema.html from the base
documentation.

=cut

1;


Index: cust_bill.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_bill.pm,v
retrieving revision 1.101
retrieving revision 1.102
diff -u -d -r1.101 -r1.102
--- cust_bill.pm	11 Dec 2004 20:41:38 -0000	1.101
+++ cust_bill.pm	29 Dec 2004 12:00:05 -0000	1.102
@@ -356,14 +356,13 @@
       'body'    => \@print_text,
     );
     die "can't email invoice: $error\n" if $error;
+    #die "$error\n" if $error;
 
   }
 
-  if ( $conf->config('invoice_latex') ) {
-    @print_text = $self->print_ps('', $template);
-  }
-
   if ( grep { $_ eq 'POST' } @invoicing_list ) { #postal
+    @print_text = $self->print_ps('', $template)
+      if $conf->config('invoice_latex');
     my $lpr = $conf->config('lpr');
     open(LPR, "|$lpr")
       or die "Can't open pipe to $lpr: $!\n";
@@ -796,7 +795,8 @@
         push @buf, [ $description,
                      $money_char. sprintf("%10.2f", $cust_bill_pkg->setup) ];
         push @buf,
-          map { [ "  ". $_->[0]. ": ". $_->[1], '' ] } $cust_pkg->labels;
+          map { [ "  ". $_->[0]. ": ". $_->[1], '' ] }
+              $cust_pkg->h_labels($self->_date);
       }
 
       if ( $cust_bill_pkg->recur != 0 ) {
@@ -806,7 +806,8 @@
           $money_char. sprintf("%10.2f", $cust_bill_pkg->recur)
         ];
         push @buf,
-          map { [ "  ". $_->[0]. ": ". $_->[1], '' ] } $cust_pkg->labels;
+          map { [ "  ". $_->[0]. ": ". $_->[1], '' ] }
+              $cust_pkg->h_labels($cust_bill_pkg->edate, $cust_bill_pkg->sdate);
       }
 
       push @buf, map { [ "  $_", '' ] } $cust_bill_pkg->details;
@@ -1366,45 +1367,32 @@
       my $part_pkg = qsearchs('part_pkg', { pkgpart=>$cust_pkg->pkgpart } );
       my $pkg = $part_pkg->pkg;
 
-      my %labels;
-      #tie %labels, 'Tie::IxHash';
-      push @{ $labels{$_->[0]} }, $_->[1] foreach $cust_pkg->labels;
-      my @ext_description;
-      foreach my $label ( keys %labels ) {
-        my @values = @{ $labels{$label} };
-        my $num = scalar(@values);
-        if ( $num > 5 ) {
-          push @ext_description, "$label ($num)";
-        } else {
-          push @ext_description, map { "$label: $_" } @values;
-        }
-      }
-
       if ( $cust_bill_pkg->setup != 0 ) {
         my $description = $pkg;
         $description .= ' Setup' if $cust_bill_pkg->recur != 0;
-        my @d = @ext_description;
+        my @d = $cust_pkg->h_labels_short($self->_date);
         push @d, $cust_bill_pkg->details if $cust_bill_pkg->recur == 0;
         push @b, {
-          'description'     => $description,
-          #'pkgpart'         => $part_pkg->pkgpart,
-          'pkgnum'          => $cust_pkg->pkgnum,
-          'amount'          => sprintf("%10.2f", $cust_bill_pkg->setup),
-          'ext_description' => \@d,
+          description     => $description,
+          #pkgpart         => $part_pkg->pkgpart,
+          pkgnum          => $cust_pkg->pkgnum,
+          amount          => sprintf("%10.2f", $cust_bill_pkg->setup),
+          ext_description => \@d,
         };
       }
 
       if ( $cust_bill_pkg->recur != 0 ) {
         push @b, {
-          'description'     => "$pkg (" .
+          description     => "$pkg (" .
                                time2str('%x', $cust_bill_pkg->sdate). ' - '.
                                time2str('%x', $cust_bill_pkg->edate). ')',
-          #'pkgpart'         => $part_pkg->pkgpart,
-          'pkgnum'          => $cust_pkg->pkgnum,
-          'amount'          => sprintf("%10.2f", $cust_bill_pkg->recur),
-          'ext_description' => [ @ext_description,
-                                 $cust_bill_pkg->details,
-                               ],
+          #pkgpart         => $part_pkg->pkgpart,
+          pkgnum          => $cust_pkg->pkgnum,
+          amount          => sprintf("%10.2f", $cust_bill_pkg->recur),
+          ext_description => [ $cust_pkg->h_labels_short($cust_bill_pkg->edate,
+                                                         $cust_bill_pkg->sdate),
+                               $cust_bill_pkg->details,
+                             ],
         };
       }
 

--- NEW FILE: h_svc_external.pm ---
package FS::h_svc_external;

use strict;
use vars qw( @ISA );
use FS::h_Common;
use FS::svc_external;

@ISA = qw( FS::h_Common FS::svc_external );

sub table { 'h_svc_external' };

=head1 NAME

FS::h_svc_external - Historical externally tracked service objects

=head1 SYNOPSIS

=head1 DESCRIPTION

An FS::h_svc_external object represents a historical externally tracked service.
FS::h_svc_external inherits from FS::h_Common and FS::svc_external.

=head1 BUGS

=head1 SEE ALSO

L<FS::h_Common>, L<FS::svc_external>, L<FS::Record>, schema.html from the base
documentation.

=cut

1;


Index: cust_pkg.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_pkg.pm,v
retrieving revision 1.50
retrieving revision 1.51
diff -u -d -r1.50 -r1.51
--- cust_pkg.pm	1 Dec 2004 18:49:21 -0000	1.50
+++ cust_pkg.pm	29 Dec 2004 12:00:06 -0000	1.51
@@ -11,6 +11,7 @@
 use FS::type_pkgs;
 use FS::pkg_svc;
 use FS::cust_bill_pkg;
+use FS::h_cust_svc;
 
 # need to 'use' these instead of 'require' in sub { cancel, suspend, unsuspend,
 # setup }
@@ -543,21 +544,50 @@
   #if ( $self->{'_svcnum'} ) {
   #  values %{ $self->{'_svcnum'}->cache };
   #} else {
-    map  { $_->[0] }
-    sort { $b->[1] cmp $a->[1]  or  $a->[2] <=> $b->[2] } 
-    map {
-          my $pkg_svc = qsearchs( 'pkg_svc', { 'pkgpart' => $self->pkgpart,
-                                               'svcpart' => $_->svcpart     } );
-          [ $_,
-            $pkg_svc ? $pkg_svc->primary_svc : '',
-            $pkg_svc ? $pkg_svc->quantity : 0,
-          ];
-        }
-    qsearch( 'cust_svc', { 'pkgnum' => $self->pkgnum } );
+    $self->_sort_cust_svc(
+      [ qsearch( 'cust_svc', { 'pkgnum' => $self->pkgnum } ) ]
+    );
   #}
 
 }
 
+=item h_cust_svc END_TIMESTAMP [ START_TIMESTAMP ] 
+
+Returns historical services for this package created before END TIMESTAMP and
+(optionally) not cancelled before START_TIMESTAMP, as FS::h_cust_svc objects
+(see L<FS::h_cust_svc>).
+
+=cut
+
+sub h_cust_svc {
+  my $self = shift;
+
+  $self->_sort_cust_svc(
+    [ qsearch( 'h_cust_svc',
+               { 'pkgnum' => $self->pkgnum, },
+               FS::h_cust_svc->sql_h_search(@_),
+             )
+    ]
+  );
+}
+
+sub _sort_cust_svc {
+  my( $self, $arrayref ) = @_;
+
+  map  { $_->[0] }
+  sort { $b->[1] cmp $a->[1]  or  $a->[2] <=> $b->[2] } 
+  map {
+        my $pkg_svc = qsearchs( 'pkg_svc', { 'pkgpart' => $self->pkgpart,
+                                             'svcpart' => $_->svcpart     } );
+        [ $_,
+          $pkg_svc ? $pkg_svc->primary_svc : '',
+          $pkg_svc ? $pkg_svc->quantity : 0,
+        ];
+      }
+  @$arrayref;
+
+}
+
 =item num_cust_svc [ SVCPART ]
 
 Returns the number of provisioned services for this package.  If a svcpart is
@@ -604,6 +634,52 @@
 sub labels {
   my $self = shift;
   map { [ $_->label ] } $self->cust_svc;
+}
+
+=item h_labels END_TIMESTAMP [ START_TIMESTAMP ] 
+
+Like the labels method, but returns historical information on services that
+were active as of END_TIMESTAMP and (optionally) not cancelled before
+START_TIMESTAMP.
+
+Returns a list of lists, calling the label method for all (historical) services
+(see L<FS::h_cust_svc>) of this billing item.
+
+=cut
+
+sub h_labels {
+  my $self = shift;
+  map { [ $_->label(@_) ] } $self->h_cust_svc(@_);
+}
+
+=item h_labels_short END_TIMESTAMP [ START_TIMESTAMP ]
+
+Like h_labels, except returns a simple flat list, and shortens long 
+(currently >5) lists of identical services to one line that lists the service
+label and the number of individual services rather than individual items.
+
+=cut
+
+sub h_labels_short {
+  my $self = shift;
+
+  my %labels;
+  #tie %labels, 'Tie::IxHash';
+  push @{ $labels{$_->[0]} }, $_->[1]
+    foreach $self->h_labels(@_);
+  my @labels;
+  foreach my $label ( keys %labels ) {
+    my @values = @{ $labels{$label} };
+    my $num = scalar(@values);
+    if ( $num > 5 ) {
+      push @labels, "$label ($num)";
+    } else {
+      push @labels, map { "$label: $_" } @values;
+    }
+  }
+
+ @labels;
+
 }
 
 =item cust_main

Index: svc_acct.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/svc_acct.pm,v
retrieving revision 1.166
retrieving revision 1.167
diff -u -d -r1.166 -r1.167
--- svc_acct.pm	24 Dec 2004 23:35:18 -0000	1.166
+++ svc_acct.pm	29 Dec 2004 12:00:06 -0000	1.167
@@ -1028,7 +1028,7 @@
 sub domain {
   my $self = shift;
   die "svc_acct.domsvc is null for svcnum ". $self->svcnum unless $self->domsvc;
-  my $svc_domain = $self->svc_domain
+  my $svc_domain = $self->svc_domain(@_)
     or die "no svc_domain.svcnum for svc_acct.domsvc ". $self->domsvc;
   $svc_domain->domain;
 }
@@ -1066,7 +1066,7 @@
 
 sub email {
   my $self = shift;
-  $self->username. '@'. $self->domain;
+  $self->username. '@'. $self->domain(@_);
 }
 
 =item acct_snarf

--- NEW FILE: h_Common.pm ---
package FS::h_Common;

use strict;
use FS::Record qw(dbdef);

=head1 NAME

FS::h_Common - History table "mixin" common base class

=head1 SYNOPSIS

package FS::h_tablename;
@ISA = qw( FS::h_Common FS::tablename ); 

sub table { 'h_table_name'; }

sub insert { return "can't insert history records manually"; }
sub delete { return "can't delete history records"; }
sub replace { return "can't modify history records"; }

=head1 DESCRIPTION

FS::h_Common is intended as a "mixin" base class for history table classes to
inherit from.

=head1 METHODS

=over 4

=item sql_h_search END_TIMESTAMP [ START_TIMESTAMP ] 

Returns an a list consisting of the "SELECT" and "EXTRA_SQL" SQL fragments to
search for the appropriate history records created before END_TIMESTAMP
and (optionally) not cancelled before START_TIMESTAMP.

=cut

sub sql_h_search {
  my( $self, $end ) = ( shift, shift );

  my $table = $self->table;
  my $pkey = dbdef->table($table)->primary_key
    or die "can't (yet) search history table $table without a primary key";

  my $notcancelled = '';
  if ( scalar(@_) && $_[0] ) {
    $notcancelled = "AND 0 = ( SELECT COUNT(*) FROM $table as notdel
                                WHERE notdel.$pkey = maintable.$pkey
                                AND notdel.history_action = 'delete'
                                AND notdel.history_date > maintable.history_date
                                AND notdel.history_date <= $_[0]
                             )";
  }

  (
    "DISTINCT ON ( $pkey ) *",

    "AND history_date <= $end
     AND (    history_action = 'insert'
           OR history_action = 'replace_new'
         )
     $notcancelled
     ORDER BY $pkey ASC, history_date DESC",

     '',

     'maintable',
  );

}

=back

=head1 BUGS

=head1 SEE ALSO

L<FS::Record>, schema.html from the base documentation

=cut

1;


--- NEW FILE: h_svc_broadband.pm ---
package FS::h_svc_broadband;

use strict;
use vars qw( @ISA );
use FS::h_Common;
use FS::svc_broadband;

@ISA = qw( FS::h_Common FS::svc_broadband );

sub table { 'h_svc_broadband' };

=head1 NAME

FS::h_svc_broadband - Historical broadband connection objects

=head1 SYNOPSIS

=head1 DESCRIPTION

An FS::h_svc_broadband object represents a historical broadband connection.
FS::h_svc_broadband inherits from FS::h_Common and FS::svc_broadband.

=head1 BUGS

=head1 SEE ALSO

L<FS::h_Common>, L<FS::svc_broadband>, L<FS::Record>, schema.html from the base
documentation.

=cut

1;


Index: cust_svc.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_svc.pm,v
retrieving revision 1.46
retrieving revision 1.47
diff -u -d -r1.46 -r1.47
--- cust_svc.pm	20 Nov 2004 17:26:53 -0000	1.46
+++ cust_svc.pm	29 Dec 2004 12:00:06 -0000	1.47
@@ -1,8 +1,8 @@
 package FS::cust_svc;
 
 use strict;
-use vars qw( @ISA $ignore_quantity );
-use Carp qw( cluck );
+use vars qw( @ISA $DEBUG $ignore_quantity );
+use Carp qw( carp cluck );
 use FS::Conf;
 use FS::Record qw( qsearch qsearchs dbh );
 use FS::cust_pkg;
@@ -19,6 +19,8 @@
 
 @ISA = qw( FS::Record );
 
+$DEBUG = 1;
+
 $ignore_quantity = 0;
 
 sub _cache {
@@ -276,37 +278,44 @@
 
 sub label {
   my $self = shift;
-  my $svcdb = $self->part_svc->svcdb;
+  carp "FS::cust_svc::label called on $self" if $DEBUG;
   my $svc_x = $self->svc_x
-    or die "can't find $svcdb.svcnum ". $self->svcnum;
+    or die "can't find ". $self->part_svc->svcdb. '.svcnum '. $self->svcnum;
+  $self->_svc_label($svc_x);
+}
+
+sub _svc_label {
+  my( $self, $svc_x ) = ( shift, shift );
+  my $svcdb = $self->part_svc->svcdb;
+
   my $tag;
   if ( $svcdb eq 'svc_acct' ) {
-    $tag = $svc_x->email;
+    $tag = $svc_x->email(@_);
   } elsif ( $svcdb eq 'svc_forward' ) {
     if ( $svc_x->srcsvc ) {
-      my $svc_acct = $svc_x->srcsvc_acct;
-      $tag = $svc_acct->email;
+      my $svc_acct = $svc_x->srcsvc_acct(@_);
+      $tag = $svc_acct->email(@_);
     } else {
       $tag = $svc_x->src;
     }
     $tag .= '->';
     if ( $svc_x->dstsvc ) {
-      my $svc_acct = $svc_x->dstsvc_acct;
-      $tag .= $svc_acct->email;
+      my $svc_acct = $svc_x->dstsvc_acct(@_);
+      $tag .= $svc_acct->email(@_);
     } else {
       $tag .= $svc_x->dst;
     }
   } elsif ( $svcdb eq 'svc_domain' ) {
     $tag = $svc_x->getfield('domain');
   } elsif ( $svcdb eq 'svc_www' ) {
-    my $domain = qsearchs( 'domain_record', { 'recnum' => $svc_x->recnum } );
-    $tag = $domain->zone;
+    my $domain_record = $svc_x->domain_record;
+    $tag = $domain_record->zone;
   } elsif ( $svcdb eq 'svc_broadband' ) {
     $tag = $svc_x->ip_addr;
   } elsif ( $svcdb eq 'svc_external' ) {
     my $conf = new FS::Conf;
     if ( $conf->config('svc_external-display_type') eq 'artera_turbo' ) {
-      $tag = sprintf('%010d', $svc_x->id). '-'. $svc_x->title;
+      $tag = sprintf('%010d', $svc_x->id). '-'. sprintf('%010d', $svc_x->title);
     } else {
       $tag = $svc_x->id. ': '. $svc_x->title;
     }
@@ -314,7 +323,9 @@
     cluck "warning: asked for label of unsupported svcdb; using svcnum";
     $tag = $svc_x->getfield('svcnum');
   }
+
   $self->part_svc->svc, $tag, $svcdb;
+
 }
 
 =item svc_x
@@ -566,7 +577,7 @@
   my @sessions = ();
 
   foreach my $part_export ( @part_export ) {
-    push @sessions, $part_export->usage_sessions( $self->svc_x, $start, $end );
+    push @sessions, $part_export->usage_sessions( $start, $end, $self->svc_x );
   }
 
   \@sessions;

--- NEW FILE: h_svc_acct.pm ---
package FS::h_svc_acct;

use strict;
use vars qw( @ISA );
use FS::Record qw(qsearchs);
use FS::h_Common;
use FS::svc_acct;
use FS::h_svc_domain;

@ISA = qw( FS::h_Common FS::svc_acct );

sub table { 'h_svc_acct' };

=head1 NAME

FS::h_svc_acct - Historical account objects

=head1 SYNOPSIS

=head1 METHODS

=over 4

=item svc_domain

=cut

sub svc_domain {
  my $self = shift;
  qsearchs( 'h_svc_domain',
            { 'svcnum' => $self->domsvc },
            FS::h_svc_domain->sql_h_search(@_),
          );
}

=back

=head1 DESCRIPTION

An FS::h_svc_acct object represents a historical account.  FS::h_svc_acct
inherits from FS::h_Common and FS::svc_acct.

=head1 BUGS

=head1 SEE ALSO

L<FS::h_Common>, L<FS::svc_acct>, L<FS::Record>, schema.html from the base
documentation.

=cut

1;


--- NEW FILE: h_cust_svc.pm ---
package FS::h_cust_svc;

use strict;
use vars qw( @ISA $DEBUG );
use Carp;
use FS::Record qw(qsearchs);
use FS::h_Common;
use FS::cust_svc;

@ISA = qw( FS::h_Common FS::cust_svc );

$DEBUG = 0;

sub table { 'h_cust_svc'; }

=head1 NAME

FS::h_cust_svc - Object method for h_cust_svc objects

=head1 SYNOPSIS

=head1 DESCRIPTION

An FS::h_cust_svc object  represents a historical service.  FS::h_cust_svc
inherits from FS::h_Common and FS::cust_svc.

=head1 METHODS

=over 4

=item label END_TIMESTAMP [ START_TIMESTAMP ] 

Returns a list consisting of:
- The name of this historical service (from part_svc)
- A meaningful identifier (username, domain, or mail alias)
- The table name (i.e. svc_domain) for this historical service

=cut

sub label {
  my $self = shift;
  carp "FS::h_cust_svc::label called on $self" if $DEBUG;
  my $svc_x = $self->h_svc_x(@_)
    or die "can't find h_". $self->part_svc->svcdb. '.svcnum '. $self->svcnum;
  $self->_svc_label($svc_x, @_);
}

=item h_svc_x END_TIMESTAMP [ START_TIMESTAMP ] 

Returns the FS::h_svc_XXX object for this service as of END_TIMESTAMP (i.e. an
FS::h_svc_acct object or FS::h_svc_domain object, etc.) and (optionally) not
cancelled before START_TIMESTAMP.

=cut

#false laziness w/cust_pkg::h_cust_svc
sub h_svc_x {
  my $self = shift;
  my $svcdb = $self->part_svc->svcdb;
  #if ( $svcdb eq 'svc_acct' && $self->{'_svc_acct'} ) {
  #  $self->{'_svc_acct'};
  #} else {
    warn "requiring FS/h_$svcdb.pm" if $DEBUG;
    require "FS/h_$svcdb.pm";
    qsearchs( "h_$svcdb",
              { 'svcnum'       => $self->svcnum, },
              "FS::h_$svcdb"->sql_h_search(@_),
            );
  #}
}

=back

=head1 BUGS

=head1 SEE ALSO

L<FS::h_Common>, L<FS::cust_svc>, L<FS::Record>, schema.html from the base
documentation.

=cut

1;


--- NEW FILE: h_svc_forward.pm ---
package FS::h_svc_forward;

use strict;
use vars qw( @ISA );
se FS::Record qw(qsearchs);
use FS::h_Common;
use FS::svc_forward;
use FS::h_svc_acct;

@ISA = qw( FS::h_Common FS::svc_forward );

sub table { 'h_svc_forward' };

=head1 NAME

FS::h_svc_forward - Historical mail forwarding alias objects

=head1 SYNOPSIS

=head1 METHODS

=over 4

=item srcsvc_acct 

=cut

sub srcsvc_acct {
  my $self = shift;
  qsearchs( 'h_svc_acct',
            { 'svcnum' => $self->srcsvc },
            FS::h_svc_acct->sql_h_search(@_),
          );
}

=item dstsvc_acct

=cut

sub dstsvc_acct {
  my $self = shift;
  qsearchs( 'h_svc_acct',
            { 'svcnum' => $self->dstsvc },
            FS::h_svc_acct->sql_h_search(@_),
          );
}

=back

=head1 DESCRIPTION

An FS::h_svc_forward object represents a historical mail forwarding alias.
FS::h_svc_forward inherits from FS::h_Common and FS::svc_forward.

=head1 BUGS

=head1 SEE ALSO

L<FS::h_Common>, L<FS::svc_forward>, L<FS::Record>, schema.html from the base
documentation.

=cut

1;





More information about the freeside-commits mailing list