use FS::part_pkg_option;
use FS::pkg_class;
use FS::agent;
+use FS::part_pkg_taxrate;
use FS::part_pkg_taxoverride;
use FS::part_pkg_taxproduct;
use FS::part_pkg_link;
+use FS::part_pkg_discount;
@ISA = qw( FS::m2m_Common FS::option_Common );
$DEBUG = 0;
=item agentnum - Optional agentnum (see L<FS::agent>)
+=item fcc_ds0s - Optional DS0 equivalency number for FCC form 477
+
=back
=head1 METHODS
warn " inserting part_pkg_taxoverride records" if $DEBUG;
my %overrides = %{ $options{'tax_overrides'} || {} };
foreach my $usage_class ( keys %overrides ) {
- my @overrides = (grep "$_", split (',', $overrides{$usage_class}) );
+ my $override =
+ ( exists($overrides{$usage_class}) && defined($overrides{$usage_class}) )
+ ? $overrides{$usage_class}
+ : '';
+ my @overrides = (grep "$_", split(',', $override) );
my $error = $self->process_m2m (
'link_table' => 'part_pkg_taxoverride',
'target_table' => 'tax_class',
|| $self->ut_textn('taxclass')
|| $self->ut_enum('disabled', [ '', 'Y' ] )
|| $self->ut_enum('custom', [ '', 'Y' ] )
+ || $self->ut_enum('no_auto', [ '', 'Y' ])
#|| $self->ut_moneyn('setup_cost')
#|| $self->ut_moneyn('recur_cost')
|| $self->ut_floatn('setup_cost')
? $self->ut_foreign_keyn('agentnum', 'agent', 'agentnum' )
: $self->ut_agentnum_acl('agentnum', \@null_agentnum_right)
)
+ || $self->ut_numbern('fcc_ds0s')
|| $self->SUPER::check
;
return $error if $error;
}
}
+sub can_discount { 0; }
sub freqs_href {
- #method, class method or sub? #my $self = shift;
-
- tie my %freq, 'Tie::IxHash',
- '0' => '(no recurring fee)',
- '1h' => 'hourly',
- '1d' => 'daily',
- '2d' => 'every two days',
- '3d' => 'every three days',
- '1w' => 'weekly',
- '2w' => 'biweekly (every 2 weeks)',
- '1' => 'monthly',
- '45d' => 'every 45 days',
- '2' => 'bimonthly (every 2 months)',
- '3' => 'quarterly (every 3 months)',
- '4' => 'every 4 months',
- '137d' => 'every 4 1/2 months (137 days)',
- '6' => 'semiannually (every 6 months)',
- '12' => 'annually',
- '13' => 'every 13 months (annually +1 month)',
- '24' => 'biannually (every 2 years)',
- '36' => 'triannually (every 3 years)',
- '48' => '(every 4 years)',
- '60' => '(every 5 years)',
- '120' => '(every 10 years)',
- ;
-
- \%freq;
-
+ # moved to FS::Misc to make this accessible to other packages
+ # at initialization
+ FS::Misc::pkg_freqs();
}
=item freq_pretty
}
}
-=item add_freq TIMESTAMP
+=item add_freq TIMESTAMP [ FREQ ]
-Adds the frequency of this package to the provided timestamp and returns
-the resulting timestamp, or -1 if the frequency of this package could not be
-parsed (shouldn't happen).
+Adds a billing period of some frequency to the provided timestamp and
+returns the resulting timestamp, or -1 if the frequency could not be
+parsed (shouldn't happen). By default, the frequency of this package
+will be used; to override this, pass a different frequency as a second
+argument.
=cut
sub add_freq {
- my( $self, $date ) = @_;
- my $freq = $self->freq;
+ my( $self, $date, $freq ) = @_;
+ $freq = $self->freq unless $freq;
#change this bit to use Date::Manip? CAREFUL with timezones (see
# mailing list archive)
my ($sec,$min,$hour,$mday,$mon,$year) = (localtime($date) )[0,1,2,3,4,5];
- if ( $self->freq =~ /^\d+$/ ) {
- $mon += $self->freq;
+ if ( $freq =~ /^\d+$/ ) {
+ $mon += $freq;
until ( $mon < 12 ) { $mon -= 12; $year++; }
- } elsif ( $self->freq =~ /^(\d+)w$/ ) {
+ } elsif ( $freq =~ /^(\d+)w$/ ) {
my $weeks = $1;
$mday += $weeks * 7;
- } elsif ( $self->freq =~ /^(\d+)d$/ ) {
+ } elsif ( $freq =~ /^(\d+)d$/ ) {
my $days = $1;
$mday += $days;
- } elsif ( $self->freq =~ /^(\d+)h$/ ) {
+ } elsif ( $freq =~ /^(\d+)h$/ ) {
my $hours = $1;
$hour += $hours;
} else {
map { $_->optionname => $_->optionvalue } $self->part_pkg_option;
}
-=item option OPTIONNAME
+=item option OPTIONNAME [ QUIET ]
-Returns the option value for the given name, or the empty string.
+Returns the option value for the given name, or the empty string. If a true
+value is passed as the second argument, warnings about missing the option
+will be suppressed.
=cut
qsearch({ table => 'part_pkg_link',
hashref => { 'src_pkgpart' => $self->pkgpart,
'link_type' => $type,
+ #protection against infinite recursive links
+ 'dst_pkgpart' => { op=>'!=', value=> $self->pkgpart },
},
order_by => "ORDER BY hidden",
});
} );
}
+=item part_pkg_discount
+
+Returns the package to discount m2m records (see L<FS::part_pkg_discount>)
+for this package.
+
+=cut
+
+sub part_pkg_discount {
+ my $self = shift;
+ qsearch('part_pkg_discount', { 'pkgpart' => $self->pkgpart });
+}
+
=item _rebless
Reblesses the object into the FS::part_pkg::PLAN class (if available), where
#fallback for everything except bulk.pm
sub hide_svc_detail { 0; }
+=item recur_cost_permonth CUST_PKG
+
+recur_cost divided by freq (only supported for monthly and longer frequencies)
+
+=cut
+
+sub recur_cost_permonth {
+ my($self, $cust_pkg) = @_;
+ return 0 unless $self->freq =~ /^\d+$/ && $self->freq > 0;
+ sprintf('%.2f', $self->recur_cost / $self->freq );
+}
+
=item format OPTION DATA
Returns data formatted according to the function 'format' described
"
(
- agentnum IS NOT NULL
- OR
- 0 < ( SELECT COUNT(*)
- FROM type_pkgs
- LEFT JOIN agent_type USING ( typenum )
- LEFT JOIN agent AS typeagent USING ( typenum )
- WHERE type_pkgs.pkgpart = part_pkg.pkgpart
- AND typeagent.agentnum IN ($agentnums)
- )
+ ( agentnum IS NOT NULL AND agentnum IN ($agentnums) )
+ OR ( agentnum IS NULL
+ AND EXISTS ( SELECT 1
+ FROM type_pkgs
+ LEFT JOIN agent_type USING ( typenum )
+ LEFT JOIN agent AS typeagent USING ( typenum )
+ WHERE type_pkgs.pkgpart = part_pkg.pkgpart
+ AND typeagent.agentnum IN ($agentnums)
+ )
+ )
)
";