-
- my $sth = $dbh->prepare(
- 'UPDATE cust_main SET referral_custnum = ? WHERE referral_custnum = ?'
- ) or do {
- my $errstr = $dbh->errstr;
- $dbh->rollback if $oldAutoCommit;
- return $errstr;
- };
- $sth->execute($new_custnum, $self->custnum) or do {
- my $errstr = $sth->errstr;
- $dbh->rollback if $oldAutoCommit;
- return $errstr;
- };
-
- #tickets
-
- my $ticket_dbh = '';
- if ($conf->config('ticket_system') eq 'RT_Internal') {
- $ticket_dbh = $dbh;
- } elsif ($conf->config('ticket_system') eq 'RT_External') {
- my ($datasrc, $user, $pass) = $conf->config('ticket_system-rt_external_datasrc');
- $ticket_dbh = DBI->connect($datasrc, $user, $pass, { 'ChopBlanks' => 1 });
- #or die "RT_External DBI->connect error: $DBI::errstr\n";
- }
-
- if ( $ticket_dbh ) {
-
- my $ticket_sth = $ticket_dbh->prepare(
- 'UPDATE Links SET Target = ? WHERE Target = ?'
- ) or do {
- my $errstr = $ticket_dbh->errstr;
- $dbh->rollback if $oldAutoCommit;
- return $errstr;
- };
- $ticket_sth->execute('freeside://freeside/cust_main/'.$new_custnum,
- 'freeside://freeside/cust_main/'.$self->custnum)
- or do {
- my $errstr = $ticket_sth->errstr;
- $dbh->rollback if $oldAutoCommit;
- return $errstr;
- };
-
- }
-
- #delete the customer record
-
- my $error = $self->delete;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- $dbh->commit or die $dbh->errstr if $oldAutoCommit;
- '';
-
-}
-
-=item replace [ OLD_RECORD ] [ INVOICING_LIST_ARYREF ] [ , OPTION => VALUE ... ] ]
-
-Replaces the OLD_RECORD with this one in the database. If there is an error,
-returns the error, otherwise returns false.
-
-To change the customer's address, set the pseudo-fields C<bill_location> and
-C<ship_location>. The address will still only change if at least one of the
-address fields differs from the existing values.
-
-INVOICING_LIST_ARYREF: If you pass an arrarref to the insert method, it will
-be set as the invoicing list (see L<"invoicing_list">). Errors return as
-expected and rollback the entire transaction; it is not necessary to call
-check_invoicing_list first. Here's an example:
-
- $new_cust_main->replace( $old_cust_main, [ $email, 'POST' ] );
-
-Currently available options are: I<tax_exemption>.
-
-The I<tax_exemption> option can be set to an arrayref of tax names or a hashref
-of tax names and exemption numbers. FS::cust_main_exemption records will be
-deleted and inserted as appropriate.
-
-=cut
-
-sub replace {
- my $self = shift;
-
- my $old = ( blessed($_[0]) && $_[0]->isa('FS::Record') )
- ? shift
- : $self->replace_old;
-
- my @param = @_;
-
- warn "$me replace called\n"
- if $DEBUG;
-
- my $curuser = $FS::CurrentUser::CurrentUser;
- if ( $self->payby eq 'COMP'
- && $self->payby ne $old->payby
- && ! $curuser->access_right('Complimentary customer')
- )
- {
- return "You are not permitted to create complimentary accounts.";
- }
-
- local($ignore_expired_card) = 1
- if $old->payby =~ /^(CARD|DCRD)$/
- && $self->payby =~ /^(CARD|DCRD)$/
- && ( $old->payinfo eq $self->payinfo || $old->paymask eq $self->paymask );
-
- local($ignore_banned_card) = 1
- if ( $old->payby =~ /^(CARD|DCRD)$/ && $self->payby =~ /^(CARD|DCRD)$/
- || $old->payby =~ /^(CHEK|DCHK)$/ && $self->payby =~ /^(CHEK|DCHK)$/ )
- && ( $old->payinfo eq $self->payinfo || $old->paymask eq $self->paymask );
-
- return "Invoicing locale is required"
- if $old->locale
- && ! $self->locale
- && $conf->exists('cust_main-require_locale');
-
- local $SIG{HUP} = 'IGNORE';
- local $SIG{INT} = 'IGNORE';
- local $SIG{QUIT} = 'IGNORE';
- local $SIG{TERM} = 'IGNORE';
- local $SIG{TSTP} = 'IGNORE';
- local $SIG{PIPE} = 'IGNORE';
-
- my $oldAutoCommit = $FS::UID::AutoCommit;
- local $FS::UID::AutoCommit = 0;
- my $dbh = dbh;
-
- for my $l (qw(bill_location ship_location)) {
- my $old_loc = $old->$l;
- my $new_loc = $self->$l;
-
- if ( !$new_loc->locationnum ) {
- # changing location
- # If the new location is all empty fields, or if it's identical to
- # the old location in all fields, don't replace.
- my @nonempty = grep { $new_loc->$_ } $self->location_fields;
- next if !@nonempty;
- my @unlike = grep { $new_loc->$_ ne $old_loc->$_ } $self->location_fields;
-
- if ( @unlike or $old_loc->disabled ) {
- warn " changed $l fields: ".join(',',@unlike)."\n"
- if $DEBUG;
- $new_loc->set(custnum => $self->custnum);
-
- # insert it--the old location will be disabled later
- my $error = $new_loc->insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- } else {
- # no fields have changed and $old_loc isn't disabled, so don't change it
- next;
- }
-
- }
- elsif ( $new_loc->custnum ne $self->custnum or $new_loc->prospectnum ) {
- $dbh->rollback if $oldAutoCommit;
- return "$l belongs to customer ".$new_loc->custnum;
- }
- # else the new location belongs to this customer so we're good
-
- # set the foo_locationnum now that we have one.
- $self->set($l.'num', $new_loc->locationnum);
-
- } #for $l
-
- my $error = $self->SUPER::replace($old);
-
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
-
- # now move packages to the new service location
- $self->set('ship_location', ''); #flush cache
- if ( $old->ship_locationnum and # should only be null during upgrade...
- $old->ship_locationnum != $self->ship_locationnum ) {
- $error = $old->ship_location->move_to($self->ship_location);
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
- # don't move packages based on the billing location, but
- # disable it if it's no longer in use
- if ( $old->bill_locationnum and
- $old->bill_locationnum != $self->bill_locationnum ) {
- $error = $old->bill_location->disable_if_unused;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
-
- if ( @param && ref($param[0]) eq 'ARRAY' ) { # INVOICING_LIST_ARYREF
- my $invoicing_list = shift @param;
- $error = $self->check_invoicing_list( $invoicing_list );
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- $self->invoicing_list( $invoicing_list );
- }
-
- if ( $self->exists('tagnum') ) { #so we don't delete these on edit by accident
-
- #this could be more efficient than deleting and re-inserting, if it matters
- foreach my $cust_tag (qsearch('cust_tag', {'custnum'=>$self->custnum} )) {
- my $error = $cust_tag->delete;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
- foreach my $tagnum ( @{ $self->tagnum || [] } ) {
- my $cust_tag = new FS::cust_tag { 'tagnum' => $tagnum,
- 'custnum' => $self->custnum };
- my $error = $cust_tag->insert;
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
-
- }
-
- my %options = @param;
-
- my $tax_exemption = delete $options{'tax_exemption'};
- if ( $tax_exemption ) {