=item cust_event
-Returns the new-style customer billing events (see L<FS::cust_event>) for this invoice.
+Returns the customer billing events (see L<FS::cust_event>) for this invoice.
=cut
=item num_cust_event
-Returns the number of new-style customer billing events (see L<FS::cust_event>) for this invoice.
+Returns the number of customer billing events (see L<FS::cust_event>) for this package.
=cut
#false laziness w/cust_bill.pm
sub num_cust_event {
my $self = shift;
- my $sql =
- "SELECT COUNT(*) FROM cust_event JOIN part_event USING ( eventpart ) ".
- " WHERE tablenum = ? AND eventtable = 'cust_pkg'";
+ my $sql = "SELECT COUNT(*) ". $self->_from_cust_event_where;
+ $self->_prep_ex($sql, $self->pkgnum)->fetchrow_arrayref->[0];
+}
+
+=item exists_cust_event
+
+Returns true if there are customer billing events (see L<FS::cust_event>) for this package. More efficient than using num_cust_event.
+
+=cut
+
+sub exists_cust_event {
+ my $self = shift;
+ my $sql = "SELECT 1 ". $self->_from_cust_event_where. " LIMIT 1";
+ my $row = $self->_prep_ex($sql, $self->pkgnum)->fetchrow_arrayref;
+ $row ? $row->[0] : '';
+}
+
+sub _from_cust_event_where {
+ #my $self = shift;
+ " FROM cust_event JOIN part_event USING ( eventpart ) ".
+ " WHERE tablenum = ? AND eventtable = 'cust_pkg' ";
+}
+
+sub _prep_ex {
+ my( $self, $sql, @args ) = @_;
my $sth = dbh->prepare($sql) or die dbh->errstr. " preparing $sql";
- $sth->execute($self->pkgnum) or die $sth->errstr. " executing $sql";
- $sth->fetchrow_arrayref->[0];
+ $sth->execute(@args) or die $sth->errstr. " executing $sql";
+ $sth;
}
=item cust_svc [ SVCPART ] (old, deprecated usage)
return ('Package does not exist: '.$dest_pkgnum) unless $dest;
foreach my $pkg_svc ( $dest->part_pkg->pkg_svc ) {
- $target{$pkg_svc->svcpart} = $pkg_svc->quantity;
+ $target{$pkg_svc->svcpart} = $pkg_svc->quantity * ( $dest->quantity || 1 );
}
foreach my $cust_svc ($dest->cust_svc) {
=item agentnum
-=item magic
+=item status
-on hold, active, inactive (or one-time charge), suspended, cancel (or cancelled)
+on hold, active, inactive (or one-time charge), suspended, canceled (or cancelled)
-=item status
+=item magic
-on hold, active, inactive (or one-time charge), suspended, cancel (or cancelled)
+Equivalent to "status", except that "canceled"/"cancelled" will exclude
+packages that were changed into a new package with the same pkgpart (i.e.
+location or quantity changes).
=item custom
push @where, FS::cust_pkg->cancelled_sql();
}
+
+ ### special case: "magic" is used in detail links from browse/part_pkg,
+ # where "cancelled" has the restriction "and not replaced with a package
+ # of the same pkgpart". Be consistent with that.
+ ###
+
+ if ( $params->{'magic'} =~ /^cancell?ed$/ ) {
+ my $new_pkgpart = "SELECT pkgpart FROM cust_pkg AS cust_pkg_next ".
+ "WHERE cust_pkg_next.change_pkgnum = cust_pkg.pkgnum";
+ # ...may not exist, if this was just canceled and not changed; in that
+ # case give it a "new pkgpart" that never equals the old pkgpart
+ push @where, "COALESCE(($new_pkgpart), 0) != cust_pkg.pkgpart";
+ }
###
# parse package class