use strict;
use vars qw( @ISA $noexport_hack $DEBUG );
+use Carp;
use FS::Record qw( qsearch qsearchs fields dbh );
+use FS::cust_main_Mixin;
use FS::cust_svc;
use FS::part_svc;
use FS::queue;
+use FS::cust_main;
-@ISA = qw( FS::Record );
+@ISA = qw( FS::cust_main_Mixin FS::Record );
$DEBUG = 0;
-#$DEBUG = 1;
=head1 NAME
=cut
+sub new {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = {};
+ bless ($self, $class);
+
+ unless ( defined ( $self->table ) ) {
+ $self->{'Table'} = shift;
+ carp "warning: FS::Record::new called with table name ". $self->{'Table'};
+ }
+
+ #$self->{'Hash'} = shift;
+ my $newhash = shift;
+ $self->{'Hash'} = { map { $_ => $newhash->{$_} } qw(svcnum svcpart) };
+ $self->setdefault;
+ $self->{'Hash'}{$_} = $newhash->{$_}
+ foreach grep { defined($newhash->{$_}) && length($newhash->{$_}) }
+ keys %$newhash;
+
+ foreach my $field ( grep !defined($self->{'Hash'}{$_}), $self->fields ) {
+ $self->{'Hash'}{$field}='';
+ }
+
+ $self->_rebless if $self->can('_rebless');
+
+ $self->{'modified'} = 0;
+
+ $self->_cache($self->{'Hash'}, shift) if $self->can('_cache') && @_;
+
+ $self;
+}
+
sub virtual_fields {
# This restricts the fields based on part_svc_column and the svcpart of
be added to the referenced array.
If I<child_objects> is set to an array reference of FS::tablename objects (for
-example, FS::acct_snarf objects), they will have their svcnum fieldsset and
-will be inserted after this record, but before any exports are run.
+example, FS::acct_snarf objects), they will have their svcnum field set and
+will be inserted after this record, but before any exports are run. Each
+element of the array can also optionally be a two-element array reference
+containing the child object and the name of an alternate field to be filled in
+with the newly-inserted svcnum, for example C<[ $svc_forward, 'srcsvc' ]>
If I<depend_jobnum> is set (to a scalar jobnum or an array reference of
jobnums), all provisioning jobs will have a dependancy on the supplied
}
foreach my $object ( @$objects ) {
- $object->svcnum($self->svcnum);
- $error = $object->insert;
+ my($field, $obj);
+ if ( ref($object) eq 'ARRAY' ) {
+ ($obj, $field) = @$object;
+ } else {
+ $obj = $object;
+ $field = 'svcnum';
+ }
+ $obj->$field($self->svcnum);
+ $error = $obj->insert;
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
return $error;
#new-style exports!
unless ( $noexport_hack ) {
- foreach my $part_export ( $new->cust_svc->part_svc->part_export ) {
- my $error = $part_export->export_replace($new,$old);
+
+ #not quite false laziness, but same pattern as FS::svc_acct::replace and
+ #FS::part_export::sqlradius::_export_replace. List::Compare or something
+ #would be useful but too much of a pain in the ass to deploy
+
+ my @old_part_export = $old->cust_svc->part_svc->part_export;
+ my %old_exportnum = map { $_->exportnum => 1 } @old_part_export;
+ my @new_part_export =
+ $new->svcpart
+ ? qsearchs('part_svc', { svcpart=>$new->svcpart } )->part_export
+ : $new->cust_svc->part_svc->part_export;
+ my %new_exportnum = map { $_->exportnum => 1 } @new_part_export;
+
+ foreach my $delete_part_export (
+ grep { ! $new_exportnum{$_->exportnum} } @old_part_export
+ ) {
+ my $error = $delete_part_export->export_delete($old);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
- return "error exporting to ". $part_export->exporttype.
+ return "error deleting, export to ". $delete_part_export->exporttype.
+ " (transaction rolled back): $error";
+ }
+ }
+
+ foreach my $replace_part_export (
+ grep { $old_exportnum{$_->exportnum} } @new_part_export
+ ) {
+ my $error = $replace_part_export->export_replace($new,$old);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "error exporting to ". $replace_part_export->exporttype.
" (transaction rolled back): $error";
}
}
+
+ foreach my $insert_part_export (
+ grep { ! $old_exportnum{$_->exportnum} } @new_part_export
+ ) {
+ my $error = $insert_part_export->export_insert($new);
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "error inserting export to ". $insert_part_export->exporttype.
+ " (transaction rolled back): $error";
+ }
+ }
+
}
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
#get part_svc
my $svcpart;
- if ( $self->svcnum && qsearchs('cust_svc', {'svcnum'=>$self->svcnum}) ) {
+ if ( $self->get('svcpart') ) {
+ $svcpart = $self->get('svcpart');
+ } elsif ( $self->svcnum && qsearchs('cust_svc', {'svcnum'=>$self->svcnum}) ) {
my $cust_svc = $self->cust_svc;
return "Unknown svcnum" unless $cust_svc;
$svcpart = $cust_svc->svcpart;
- } else {
- $svcpart = $self->getfield('svcpart');
}
my $part_svc = qsearchs( 'part_svc', { 'svcpart' => $svcpart } );
return "Unkonwn svcpart" unless $part_svc;