+ ' WHERE ' . join(' AND ', grep $_, @where);
+}
+
+=item setup_pkg: The number of packages with setup dates in the period.
+
+This excludes packages created by package changes. Options:
+
+- refnum: Limit to customers with this advertising source.
+- classnum: Limit to packages with this class.
+- towernum: Limit to packages that have a broadband service with this tower.
+- zip: Limit to packages with this service location zip code.
+
+Except for zip, any of these can be an arrayref to allow multiple values for
+the field.
+
+=item susp_pkg: The number of suspended packages that were last suspended
+in the period. Options are as for setup_pkg.
+
+=item cancel_pkg: The number of packages with cancel dates in the period.
+Excludes packages that were canceled to be changed to a new package. Options
+are as for setup_pkg.
+
+=cut
+
+sub setup_pkg {
+ my $self = shift;
+ my $sql = 'SELECT COUNT(*) FROM cust_pkg
+ LEFT JOIN part_pkg USING (pkgpart)
+ LEFT JOIN cust_main USING (custnum)'.
+ $self->pkg_field_where('setup', @_) .
+ ' AND change_pkgnum IS NULL';
+
+ $self->scalar_sql($sql);
+}
+
+sub susp_pkg {
+ # number of currently suspended packages that were suspended in the period
+ my $self = shift;
+ my $sql = 'SELECT COUNT(*) FROM cust_pkg
+ LEFT JOIN part_pkg USING (pkgpart)
+ LEFT JOIN cust_main USING (custnum) '.
+ $self->pkg_field_where('susp', @_);
+
+ $self->scalar_sql($sql);
+}
+
+sub cancel_pkg {
+ # number of packages canceled in the period and not changed to another
+ # package
+ my $self = shift;
+ my $sql = 'SELECT COUNT(*) FROM cust_pkg
+ LEFT JOIN part_pkg USING (pkgpart)
+ LEFT JOIN cust_main USING (custnum)
+ LEFT JOIN cust_pkg changed_to_pkg ON(
+ cust_pkg.pkgnum = changed_to_pkg.change_pkgnum
+ ) '.
+ $self->pkg_field_where('cancel', @_) .
+ ' AND changed_to_pkg.pkgnum IS NULL';
+
+ $self->scalar_sql($sql);