}
if ( $options{'part_pkg_vendor'} ) {
- my($exportnum,$vendor_pkg_id);
- my %options_part_pkg_vendor = $options{'part_pkg_vendor'};
- while(($exportnum,$vendor_pkg_id) = each %options_part_pkg_vendor){
- my $ppv = new FS::part_pkg_vendor( {
- 'pkgpart' => $self->pkgpart,
- 'exportnum' => $exportnum,
- 'vendor_pkg_id' => $vendor_pkg_id,
- } );
- my $error = $ppv->insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "Error inserting part_pkg_vendor record: $error";
- }
+ while ( my ($exportnum, $vendor_pkg_id) =
+ each %{ $options{part_pkg_vendor} }
+ )
+ {
+ my $ppv = new FS::part_pkg_vendor( {
+ 'pkgpart' => $self->pkgpart,
+ 'exportnum' => $exportnum,
+ 'vendor_pkg_id' => $vendor_pkg_id,
+ } );
+ my $error = $ppv->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "Error inserting part_pkg_vendor record: $error";
+ }
}
}
if ( $options->{'part_pkg_vendor'} ) {
my($exportnum,$vendor_pkg_id);
while ( ($exportnum,$vendor_pkg_id)
- = each %{$options->{'part_pkg_vendor'}} ) {
- my $noinsert = 0;
- foreach my $part_pkg_vendor ( @part_pkg_vendor ) {
- if($exportnum == $part_pkg_vendor->exportnum
- && $vendor_pkg_id ne $part_pkg_vendor->vendor_pkg_id) {
- $part_pkg_vendor->vendor_pkg_id($vendor_pkg_id);
- my $error = $part_pkg_vendor->replace;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "Error replacing part_pkg_vendor record: $error";
- }
- $noinsert = 1;
- last;
- }
- elsif($exportnum == $part_pkg_vendor->exportnum
- && $vendor_pkg_id eq $part_pkg_vendor->vendor_pkg_id) {
- $noinsert = 1;
- last;
- }
- }
- unless ( $noinsert ) {
- my $ppv = new FS::part_pkg_vendor( {
- 'pkgpart' => $new->pkgpart,
- 'exportnum' => $exportnum,
- 'vendor_pkg_id' => $vendor_pkg_id,
- } );
- my $error = $ppv->insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "Error inserting part_pkg_vendor record: $error";
- }
- }
- push @current_exportnum, $exportnum;
+ = each %{$options->{'part_pkg_vendor'}} ) {
+ my $noinsert = 0;
+ foreach my $part_pkg_vendor ( @part_pkg_vendor ) {
+ if($exportnum == $part_pkg_vendor->exportnum
+ && $vendor_pkg_id ne $part_pkg_vendor->vendor_pkg_id) {
+ $part_pkg_vendor->vendor_pkg_id($vendor_pkg_id);
+ my $error = $part_pkg_vendor->replace;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "Error replacing part_pkg_vendor record: $error";
+ }
+ $noinsert = 1;
+ last;
+ }
+ elsif($exportnum == $part_pkg_vendor->exportnum
+ && $vendor_pkg_id eq $part_pkg_vendor->vendor_pkg_id) {
+ $noinsert = 1;
+ last;
+ }
+ }
+ unless ( $noinsert ) {
+ my $ppv = new FS::part_pkg_vendor( {
+ 'pkgpart' => $new->pkgpart,
+ 'exportnum' => $exportnum,
+ 'vendor_pkg_id' => $vendor_pkg_id,
+ } );
+ my $error = $ppv->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "Error inserting part_pkg_vendor record: $error";
+ }
+ }
+ push @current_exportnum, $exportnum;
}
}
foreach my $part_pkg_vendor ( @part_pkg_vendor ) {
unless ( grep($_ eq $part_pkg_vendor->exportnum, @current_exportnum) ) {
- my $error = $part_pkg_vendor->delete;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return "Error deleting part_pkg_vendor record: $error";
- }
+ my $error = $part_pkg_vendor->delete;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "Error deleting part_pkg_vendor record: $error";
+ }
}
}
|| $self->ut_enum('disabled', [ '', 'Y' ] )
|| $self->ut_enum('custom', [ '', 'Y' ] )
|| $self->ut_enum('no_auto', [ '', 'Y' ])
+ || $self->ut_enum('recur_show_zero', [ '', 'Y' ])
+ || $self->ut_enum('setup_show_zero', [ '', 'Y' ])
#|| $self->ut_moneyn('setup_cost')
#|| $self->ut_moneyn('recur_cost')
|| $self->ut_floatn('setup_cost')
sub is_free {
my $self = shift;
- unless ( $self->plan ) {
- $self->setup =~ /^\s*0+(\.0*)?\s*$/
- && $self->recur =~ /^\s*0+(\.0*)?\s*$/;
- } elsif ( $self->can('is_free_options') ) {
+ if ( $self->can('is_free_options') ) {
not grep { $_ !~ /^\s*0*(\.0*)?\s*$/ }
map { $self->option($_) }
$self->is_free_options;
sub can_discount { 0; }
+sub can_start_date { 1; }
+
sub freqs_href {
# moved to FS::Misc to make this accessible to other packages
# at initialization
shift->_self_and_linked('bill', @_);
}
+sub self_and_svc_linked {
+ shift->_self_and_linked('svc', @_);
+}
+
sub _self_and_linked {
my( $self, $type, $hidden ) = @_;
$hidden ||= '';
$self;
}
-#fallbacks that eval the setup and recur fields, for backwards compat
-
-sub calc_setup {
- my $self = shift;
- warn 'no price plan class for '. $self->plan. ", eval-ing setup\n";
- $self->_calc_eval('setup', @_);
-}
-
-sub calc_recur {
- my $self = shift;
- warn 'no price plan class for '. $self->plan. ", eval-ing recur\n";
- $self->_calc_eval('recur', @_);
-}
-
-use vars qw( $sdate @details );
-sub _calc_eval {
- #my( $self, $field, $cust_pkg ) = @_;
- my( $self, $field, $cust_pkg, $sdateref, $detailsref ) = @_;
- *sdate = $sdateref;
- *details = $detailsref;
- $self->$field() =~ /^(.*)$/
- or die "Illegal $field (pkgpart ". $self->pkgpart. '): '.
- $self->$field(). "\n";
- my $prog = $1;
- return 0 if $prog =~ /^\s*$/;
- my $value = eval $prog;
- die $@ if $@;
- $value;
-}
+#fatal fallbacks
+sub calc_setup { die 'no calc_setup for '. shift->plan. "\n"; }
+sub calc_recur { die 'no calc_recur for '. shift->plan. "\n"; }
#fallback that return 0 for old legacy packages with no plan
-
sub calc_remain { 0; }
-sub calc_cancel { 0; }
sub calc_units { 0; }
+#fallback for everything not based on flat.pm
+sub recur_temporality { 'upcoming'; }
+sub calc_cancel { 0; }
+
#fallback for everything except bulk.pm
sub hide_svc_detail { 0; }
+#fallback for packages that can't/won't summarize usage
+sub sum_usage { 0; }
+
=item recur_cost_permonth CUST_PKG
recur_cost divided by freq (only supported for monthly and longer frequencies)
my @part_pkg = qsearch({
'table' => 'part_pkg',
'extra_sql' => "WHERE ". join(' OR ',
- ( map "($_ IS NOT NULL AND $_ != '' )",
- qw( plandata setup recur ) ),
'plan IS NULL', "plan = '' ",
),
});
$part_pkg->plan('flat');
}
- if ( length($part_pkg->option('setup_fee')) == 0
- && $part_pkg->setup =~ /^\s*([\d\.]+)\s*$/ ) {
-
- my $opt = new FS::part_pkg_option {
- 'pkgpart' => $part_pkg->pkgpart,
- 'optionname' => 'setup_fee',
- 'optionvalue' => $1,
- };
- my $error = $opt->insert;
- die $error if $error;
-
-
- #} else {
- # die "Can't parse part_pkg.setup for fee; convert pkgnum ".
- # $part_pkg->pkgnum. " manually: ". $part_pkg->setup. "\n";
- }
- $part_pkg->setup('');
-
- if ( length($part_pkg->option('recur_fee')) == 0
- && $part_pkg->recur =~ /^\s*([\d\.]+)\s*$/ ) {
-
- my $opt = new FS::part_pkg_option {
- 'pkgpart' => $part_pkg->pkgpart,
- 'optionname' => 'recur_fee',
- 'optionvalue' => $1,
- };
- my $error = $opt->insert;
- die $error if $error;
-
-
- #} else {
- # die "Can't parse part_pkg.setup for fee; convert pkgnum ".
- # $part_pkg->pkgnum. " manually: ". $part_pkg->setup. "\n";
- }
- $part_pkg->recur('');
-
- $part_pkg->replace; #this should take care of plandata, right?
+ $part_pkg->replace;
}
die $error if $error;
}
}
+
+ # migrate use_disposition_taqua and use_disposition to disposition_in
+ @part_pkg_option = qsearch('part_pkg_option',
+ { 'optionname' => { op => 'LIKE',
+ value => 'use_disposition%',
+ },
+ 'optionvalue' => 1,
+ });
+ my %newopts = map { $_->pkgpart => $_ }
+ qsearch('part_pkg_option', { 'optionname' => 'disposition_in', } );
+ foreach my $old_opt (@part_pkg_option) {
+ my $pkgpart = $old_opt->pkgpart;
+ my $newval = $old_opt->optionname eq 'use_disposition_taqua' ? '100'
+ : 'ANSWERED';
+ my $error = $old_opt->delete;
+ die $error if $error;
+
+ if ( exists($newopts{$pkgpart}) ) {
+ my $opt = $newopts{$pkgpart};
+ $opt->optionvalue($opt->optionvalue.",$newval");
+ $error = $opt->replace;
+ die $error if $error;
+ } else {
+ my $new_opt = new FS::part_pkg_option {
+ 'pkgpart' => $pkgpart,
+ 'optionname' => 'disposition_in',
+ 'optionvalue' => $newval,
+ };
+ $error = $new_opt->insert;
+ die $error if $error;
+ $newopts{$pkgpart} = $new_opt;
+ }
+ }
+
}
=item curuser_pkgs_sql
my $parents = $info{$name}->{'inherit_fields'} || [];
my (%fields, %field_exists, @fieldorder);
foreach my $parent ($name, @$parents) {
+ if ( !exists($info{$parent}) ) {
+ warn "$name tried to inherit from nonexistent '$parent'\n";
+ next;
+ }
%fields = ( # avoid replacing existing fields
%{ $info{$parent}->{'fields'} || {} },
%fields
next if $field_exists{$_};
$field_exists{$_} = 1;
# allow inheritors to remove inherited fields from the fieldorder
- push @fieldorder, $_ if !exists($fields{$_}->{'disabled'});
+ push @fieldorder, $_ if !exists($fields{$_}) or
+ !exists($fields{$_}->{'disabled'});
}
}
$plans{$name}->{'fields'} = \%fields;