+  if ( $self->controller->profile->get('duplicates', 'no_check') ne 'no_check' ) {
+    $self->check_std_duplicates();
+    $self->check_duplicates();
+  }
+  $self->fix_field_lengths;
+
+  $self->controller->track_progress(progress => 100);
+
+  $::myconfig{numberformat} = $old_numberformat;
+}
+
+sub add_columns {
+  my ($self, @columns) = @_;
+
+  my $h = $self->controller->headers;
+
+  foreach my $column (grep { !$h->{used}->{$_} } @columns) {
+    $h->{used}->{$column} = 1;
+    push @{ $h->{methods} }, $column;
+    push @{ $h->{headers} }, $column;
+  }
+}
+
+sub add_info_columns {
+  my ($self, @columns) = @_;
+
+  my $h = $self->controller->info_headers;
+
+  foreach my $column (grep { !$h->{used}->{ $_->{method} } } map { ref $_ eq 'HASH' ? $_ : { method => $_, header => $_ } } @columns) {
+    $h->{used}->{ $column->{method} } = 1;
+    push @{ $h->{methods} }, $column->{method};
+    push @{ $h->{headers} }, $column->{header};
+  }
+}
+
+sub add_raw_data_columns {
+  my ($self, @columns) = @_;
+
+  my $h = $self->controller->raw_data_headers;
+
+  foreach my $column (grep { !$h->{used}->{$_} } @columns) {
+    $h->{used}->{$column} = 1;
+    push @{ $h->{headers} }, $column;
+  }
+}
+
+sub add_cvar_raw_data_columns {
+  my ($self) = @_;
+
+  map { $self->add_raw_data_columns($_) if exists $self->controller->data->[0]->{raw_data}->{$_} } @{ $self->cvar_columns };
+}
+
+sub init_all_cvar_configs {
+  # Must be overridden by derived specialized importer classes.
+  return [];
+}
+
+sub init_cvar_columns {
+  my ($self) = @_;
+
+  return [ map { "cvar_" . $_->name } (@{ $self->all_cvar_configs }) ];
+}
+
+sub init_all_languages {
+  my ($self) = @_;
+
+  return SL::DB::Manager::Language->get_all;
+}
+
+sub init_all_bank_accounts {
+  my ($self) = @_;
+
+  return SL::DB::Manager::BankAccount->get_all_sorted( query => [ obsolete => 0 ] );
+}
+
+sub init_payment_terms_by {
+  my ($self) = @_;
+
+  my $all_payment_terms = SL::DB::Manager::PaymentTerm->get_all;
+  return { map { my $col = $_; ( $col => { map { ( $_->$col => $_ ) } @{ $all_payment_terms } } ) } qw(id description) };
+}
+
+sub init_delivery_terms_by {
+  my ($self) = @_;
+
+  my $all_delivery_terms = SL::DB::Manager::DeliveryTerm->get_all;
+  return { map { my $col = $_; ( $col => { map { ( $_->$col => $_ ) } @{ $all_delivery_terms } } ) } qw(id description) };
+}
+
+sub init_all_vc {
+  my ($self) = @_;
+
+  return { customers => SL::DB::Manager::Customer->get_all,
+           vendors   => SL::DB::Manager::Vendor->get_all };
+}
+
+sub init_clone_methods {
+  {}
+}
+
+sub force_allow_columns {
+  return ();
+}
+
+sub init_vc_by {
+  my ($self)    = @_;
+
+  my %by_id     = map { ( $_->id => $_ ) } @{ $self->all_vc->{customers} }, @{ $self->all_vc->{vendors} };
+  my %by_number = ( customers => { map { ( $_->customernumber => $_ ) } @{ $self->all_vc->{customers} } },
+                    vendors   => { map { ( $_->vendornumber   => $_ ) } @{ $self->all_vc->{vendors}   } } );
+  my %by_name   = ( customers => { map { ( $_->name           => $_ ) } @{ $self->all_vc->{customers} } },
+                    vendors   => { map { ( $_->name           => $_ ) } @{ $self->all_vc->{vendors}   } } );
+  my %by_gln    = ( customers => { map { ( $_->gln            => $_ ) } grep $_->gln, @{ $self->all_vc->{customers} } },
+                    vendors   => { map { ( $_->gln            => $_ ) } grep $_->gln, @{ $self->all_vc->{vendors}   } } );
+
+  return { id     => \%by_id,
+           number => \%by_number,
+           name   => \%by_name,
+           gln    => \%by_gln };
+}
+
+sub init_vc_counts_by {
+  my ($self) = @_;
+
+  my $vc_counts_by = {};
+
+  $vc_counts_by->{number}->{customers}->{$_->customernumber}++ for @{ $self->all_vc->{customers} };
+  $vc_counts_by->{number}->{vendors}->  {$_->vendornumber}++   for @{ $self->all_vc->{vendors} };
+  $vc_counts_by->{name}->  {customers}->{$_->name}++           for @{ $self->all_vc->{customers} };
+  $vc_counts_by->{name}->  {vendors}->  {$_->name}++           for @{ $self->all_vc->{vendors} };
+  $vc_counts_by->{gln}->   {customers}->{$_->gln}++            for grep $_->gln, @{ $self->all_vc->{customers} };
+  $vc_counts_by->{gln}->   {vendors}->  {$_->gln}++            for grep $_->gln, @{ $self->all_vc->{vendors} };
+
+  return $vc_counts_by;
+}
+
+sub check_vc {
+  my ($self, $entry, $id_column) = @_;
+
+  if ($entry->{object}->$id_column) {
+    $entry->{object}->$id_column(undef) if !$self->vc_by->{id}->{ $entry->{object}->$id_column };
+  }
+
+  my $is_ambiguous;
+  if (!$entry->{object}->$id_column) {
+    my $vc;
+    if ($entry->{raw_data}->{customernumber}) {
+      $vc = $self->vc_by->{number}->{customers}->{ $entry->{raw_data}->{customernumber} };
+      if ($vc && $self->vc_counts_by->{number}->{customers}->{ $entry->{raw_data}->{customernumber} } > 1) {
+        $vc = undef;
+        $is_ambiguous = 1;
+      }
+    } elsif ($entry->{raw_data}->{vendornumber}) {
+      $vc = $self->vc_by->{number}->{vendors}->{ $entry->{raw_data}->{vendornumber} };
+      if ($vc && $self->vc_counts_by->{number}->{vendors}->{ $entry->{raw_data}->{vendornumber} } > 1) {
+        $vc = undef;
+        $is_ambiguous = 1;
+      }
+    }
+
+    $entry->{object}->$id_column($vc->id) if $vc;
+  }
+
+  if (!$entry->{object}->$id_column) {
+    my $vc;
+    if ($entry->{raw_data}->{customer}) {
+      $vc = $self->vc_by->{name}->{customers}->{ $entry->{raw_data}->{customer} };
+      if ($vc && $self->vc_counts_by->{name}->{customers}->{ $entry->{raw_data}->{customer} } > 1) {
+        $vc = undef;
+        $is_ambiguous = 1;
+      }
+    } elsif ($entry->{raw_data}->{vendor}) {
+      $vc = $self->vc_by->{name}->{vendors}->{ $entry->{raw_data}->{vendor} };
+      if ($vc && $self->vc_counts_by->{name}->{vendors}->{ $entry->{raw_data}->{vendor} } > 1) {
+        $vc = undef;
+        $is_ambiguous = 1;
+      }
+    }
+
+    $entry->{object}->$id_column($vc->id) if $vc;
+  }
+
+  if (!$entry->{object}->$id_column) {
+    my $vc;
+    if ($entry->{raw_data}->{customer_gln}) {
+      $vc = $self->vc_by->{gln}->{customers}->{ $entry->{raw_data}->{customer_gln} };
+      if ($vc && $self->vc_counts_by->{gln}->{customers}->{ $entry->{raw_data}->{customer_gln} } > 1) {
+        $vc = undef;
+        $is_ambiguous = 1;
+      }
+    } elsif ($entry->{raw_data}->{vendor_gln}) {
+      $vc = $self->vc_by->{gln}->{vendors}->{ $entry->{raw_data}->{vendor_gln} };
+      if ($vc && $self->vc_counts_by->{gln}->{vendors}->{ $entry->{raw_data}->{vendor_gln} } > 1) {
+        $vc = undef;
+        $is_ambiguous = 1;
+      }
+    }
+    $entry->{object}->$id_column($vc->id) if $vc;
+  }
+
+  if ($entry->{object}->$id_column) {
+    $entry->{info_data}->{vc_name} = $self->vc_by->{id}->{ $entry->{object}->$id_column }->name;
+  } else {
+    if ($is_ambiguous) {
+      push @{ $entry->{errors} }, $::locale->text('Error: Customer/vendor is ambiguous');
+    } else {
+      push @{ $entry->{errors} }, $::locale->text('Error: Customer/vendor not found');
+    }
+  }
+}
+
+sub handle_cvars {
+  my ($self, $entry) = @_;
+
+  my %type_to_column = ( text      => 'text_value',
+                         textfield => 'text_value',
+                         select    => 'text_value',
+                         date      => 'timestamp_value_as_date',
+                         timestamp => 'timestamp_value_as_date',
+                         number    => 'number_value_as_number',
+                         bool      => 'bool_value' );
+
+  my @cvars;
+  my %changed_cvars;
+  foreach my $config (@{ $self->all_cvar_configs }) {
+    next unless exists $entry->{raw_data}->{ "cvar_" . $config->name };
+    my $value  = $entry->{raw_data}->{ "cvar_" . $config->name };
+    my $column = $type_to_column{ $config->type } || die "Program logic error: unknown custom variable storage type";
+
+    my $new_cvar = SL::DB::CustomVariable->new(config_id => $config->id, $column => $value, sub_module => '');
+
+    push @cvars, $new_cvar;
+    $changed_cvars{$config->name} = $new_cvar;
+  }
+
+  # merge existing with new cvars. swap every existing with the imported one, push the rest
+  if (@cvars) {
+    my @orig_cvars = ($entry->{object_to_save} || $entry->{object})->custom_variables;
+    for (@orig_cvars) {
+      $_ = $changed_cvars{ $_->config->name } if $changed_cvars{ $_->config->name };
+      delete $changed_cvars{ $_->config->name };
+    }
+    push @orig_cvars, values %changed_cvars;
+
+    $entry->{object}->custom_variables(\@orig_cvars);
+  }