CSV-Import: Auswahl der Felder für die Duplikat-Prüfung
authorThomas Heck <theck@linet-services.de>
Fri, 24 Aug 2012 13:46:01 +0000 (15:46 +0200)
committerThomas Heck <theck@linet-services.de>
Fri, 24 Aug 2012 13:46:01 +0000 (15:46 +0200)
fixt 1964

SL/Controller/CsvImport/Base.pm
SL/Controller/CsvImport/Contact.pm
SL/Controller/CsvImport/CustomerVendor.pm
SL/Controller/CsvImport/Part.pm
SL/Controller/CsvImport/Project.pm
SL/Controller/CsvImport/Shipto.pm
locale/de/all
templates/webpages/csv_import/form.html

index 694d187..f84d54b 100644 (file)
@@ -39,7 +39,7 @@ sub run {
 
   $self->controller->errors([ $self->csv->errors ]) if $self->csv->errors;
 
-  return if ( !$self->csv->header || $self->csv->errors ) ;
+  return if ( !$self->csv->header || $self->csv->errors );
 
   my $headers         = { headers => [ grep { $profile->{$_} } @{ $self->csv->header } ] };
   $headers->{methods} = [ map { $profile->{$_} } @{ $headers->{headers} } ];
@@ -53,7 +53,10 @@ sub run {
   $self->controller->data([ pairwise { { object => $a, raw_data => $b, errors => [], information => [], info_data => {} } } @objects, @raw_data ]);
 
   $self->check_objects;
-  $self->check_duplicates if $self->controller->profile->get('duplicates', 'no_check') ne 'no_check';
+  if ( $self->controller->profile->get('duplicates', 'no_check') ne 'no_check' ) {
+    $self->check_std_duplicates();
+    $self->check_duplicates();
+  }
   $self->fix_field_lengths;
 
   $::myconfig{numberformat} = $old_numberformat;
@@ -269,6 +272,60 @@ sub check_objects {
 sub check_duplicates {
 }
 
+sub check_std_duplicates {
+  my $self = shift;
+
+  my $duplicates = {};
+
+  my $all_fields = $self->get_duplicate_check_fields();
+
+  foreach my $key (keys(%{ $all_fields })) {
+    if ( $self->controller->profile->get('duplicates_'. $key) && (!exists($all_fields->{$key}->{std_check}) || $all_fields->{$key}->{std_check} )  ) {
+      $duplicates->{$key} = {};
+    }
+  }
+
+  my @duplicates_keys = keys(%{ $duplicates });
+
+  if ( !scalar(@duplicates_keys) ) {
+    return;
+  }
+
+  if ( $self->controller->profile->get('duplicates') eq 'check_db' ) {
+    foreach my $object (@{ $self->existing_objects }) {
+      foreach my $key (@duplicates_keys) {
+        my $value = exists($all_fields->{$key}->{maker}) ? $all_fields->{$key}->{maker}->($object, $self) : $object->$key;
+        $duplicates->{$key}->{$value} = 'db';
+      }
+    }
+  }
+
+  foreach my $entry (@{ $self->controller->data }) {
+    if ( @{ $entry->{errors} } ) {
+      next;
+    }
+
+    my $object = $entry->{object};
+
+    foreach my $key (@duplicates_keys) {
+      my $value = exists($all_fields->{$key}->{maker}) ? $all_fields->{$key}->{maker}->($object, $self) : $object->$key;
+
+      if ( exists($duplicates->{$key}->{$value}) ) {
+        push(@{ $entry->{errors} }, $duplicates->{$key}->{$value} eq 'db' ? $::locale->text('Duplicate in database') : $::locale->text('Duplicate in CSV file'));
+        last;
+      } else {
+        $duplicates->{$key}->{$value} = 'csv';
+      }
+
+    }
+  }
+
+}
+
+sub get_duplicate_check_fields {
+  return {};
+}
+
 sub check_payment {
   my ($self, $entry) = @_;
 
@@ -329,4 +386,3 @@ sub fix_field_lengths {
 
 1;
 
-
index 5d0a1be..b707ae8 100644 (file)
@@ -54,33 +54,24 @@ sub check_gender {
   push @{ $entry->{errors} }, $::locale->text('Error: Gender (cp_gender) missing or invalid') if ($entry->{object}->cp_gender ne 'm') && ($entry->{object}->cp_gender ne 'f');
 }
 
-sub check_duplicates {
-  my ($self, %params) = @_;
-
-  my $normalizer = sub { my $name = $_[0]; $name =~ s/[\s,\.\-]//g; return $name; };
-
-  my %by_id_and_name;
-  if ('check_db' eq $self->controller->profile->get('duplicates')) {
-    foreach my $type (qw(customers vendors)) {
-      foreach my $vc (@{ $self->all_vc->{$type} }) {
-        $by_id_and_name{ $vc->id } = { map { ( $normalizer->($_->cp_name) => 'db' ) } @{ $vc->contacts } };
+sub get_duplicate_check_fields {
+  return {
+    cp_name => {
+      label     => $::locale->text('Name'),
+      default   => 1,
+      maker     => sub {
+        my $o = shift;
+        return join(
+                 '--',
+                 $o->cp_cv_id,
+                 map(
+                   { s/[\s,\.\-]//g; $_ }
+                   $o->cp_name
+                 )
+        );
       }
-    }
-  }
-
-  foreach my $entry (@{ $self->controller->data }) {
-    next if @{ $entry->{errors} };
-
-    my $name = $normalizer->($entry->{object}->cp_name);
-
-    $by_id_and_name{ $entry->{vc}->id } ||= { };
-    if (!$by_id_and_name{ $entry->{vc}->id }->{ $name }) {
-      $by_id_and_name{ $entry->{vc}->id }->{ $name } = 'csv';
-
-    } else {
-      push @{ $entry->{errors} }, $by_id_and_name{ $entry->{vc}->id }->{ $name } eq 'db' ? $::locale->text('Duplicate in database') : $::locale->text('Duplicate in CSV file');
-    }
-  }
+    },
+  };
 }
 
 sub field_lengths {
@@ -125,4 +116,4 @@ sub setup_displayable_columns {
                                 );
 }
 
-1;
+1;
\ No newline at end of file
index e9b2d39..41234bf 100644 (file)
@@ -72,27 +72,18 @@ sub check_objects {
   $self->add_cvar_raw_data_columns;
 }
 
-sub check_duplicates {
-  my ($self, %params) = @_;
-
-  my $normalizer = sub { my $name = $_[0]; $name =~ s/[\s,\.\-]//g; return $name; };
-
-  my %by_name;
-  if ('check_db' eq $self->controller->profile->get('duplicates')) {
-    %by_name = map { ( $normalizer->($_->name) => 'db' ) } @{ $self->existing_objects };
-  }
-
-  foreach my $entry (@{ $self->controller->data }) {
-    next if @{ $entry->{errors} };
-
-    my $name = $normalizer->($entry->{object}->name);
-    if (!$by_name{$name}) {
-      $by_name{$name} = 'csv';
-
-    } else {
-      push @{ $entry->{errors} }, $by_name{$name} eq 'db' ? $::locale->text('Duplicate in database') : $::locale->text('Duplicate in CSV file');
-    }
-  }
+sub get_duplicate_check_fields {
+  return {
+    name => {
+      label     => $::locale->text('Customer Name'),
+      default   => 1,
+      maker     => sub {
+        my $name = shift->name;
+        $name =~ s/[\s,\.\-]//g;
+        return $name;
+      }
+    },
+  };
 }
 
 sub check_name {
@@ -265,4 +256,4 @@ sub setup_displayable_columns {
 # TODO:
 # salesman_id -- Kunden mit Typ 'Verkäufer', falls Vertreter-Modus an ist, ansonsten Employees
 
-1;
+1;
\ No newline at end of file
index d39927a..3c781aa 100644 (file)
@@ -132,29 +132,23 @@ sub check_objects {
   map { $self->add_raw_data_columns("make_${_}", "model_${_}", "lastcost_${_}") } sort { $a <=> $b } keys %{ $self->makemodel_columns };
 }
 
-sub check_duplicates {
-  my ($self, %params) = @_;
-
-  my $normalizer = sub { my $name = $_[0]; $name =~ s/[\s,\.\-]//g; return $name; };
-  my $name_maker = sub { return $normalizer->($_[0]->description) };
-
-  my %by_name;
-  if ('check_db' eq $self->controller->profile->get('duplicates')) {
-    %by_name = map { ( $name_maker->($_) => 'db' ) } @{ $self->existing_objects };
-  }
-
-  foreach my $entry (@{ $self->controller->data }) {
-    next if @{ $entry->{errors} };
-
-    my $name = $name_maker->($entry->{object});
-
-    if (!$by_name{ $name }) {
-      $by_name{ $name } = 'csv';
-
-    } else {
-      push @{ $entry->{errors} }, $by_name{ $name } eq 'db' ? $::locale->text('Duplicate in database') : $::locale->text('Duplicate in CSV file');
-    }
-  }
+sub get_duplicate_check_fields {
+  return {
+    partnumber => {
+      label     => $::locale->text('Part Number'),
+      default   => 0
+    },
+
+    description => {
+      label     => $::locale->text('Description'),
+      default   => 1,
+      maker     => sub {
+        my $desc = shift->description;
+        $desc =~ s/[\s,\.\-]//g;
+        return $desc;
+      }
+    },
+  };
 }
 
 sub check_buchungsgruppe {
@@ -502,4 +496,4 @@ sub setup_displayable_columns {
   }
 }
 
-1;
+1;
\ No newline at end of file
index 8367fbe..6530fb3 100644 (file)
@@ -34,31 +34,14 @@ sub check_objects {
   $self->add_cvar_raw_data_columns;
 }
 
-sub check_duplicates {
-  my $self = shift;
-
-  my %duplicates_by_number;
-
-  if ( $self->controller->profile->get('duplicates') eq 'check_db' ) {
-    foreach my $object (@{$self->existing_objects}) {
-      $duplicates_by_number{$object->{projectnumber}} = 'db';
-    }
-  }
-
-  foreach my $entry (@{ $self->controller->data }) {
-
-    my $object = $entry->{object};
-
-    if ( $duplicates_by_number{$object->projectnumber()} )
-    {
-      push( @{$entry->{errors}},
-            $duplicates_by_number{$object->projectnumber()} eq 'db' ? $::locale->text('Duplicate in database') : $::locale->text('Duplicate in CSV file')
-      );
-    } else {
-      $duplicates_by_number{$object->projectnumber()} = 'csv';
-    }
-
-  }
+sub get_duplicate_check_fields {
+  return {
+    projectnumber => {
+      label     => $::locale->text('Project Number'),
+      default   => 1,
+      std_check => 1
+    },
+  };
 }
 
 sub setup_displayable_columns {
@@ -73,4 +56,4 @@ sub setup_displayable_columns {
                                 );
 }
 
-1;
+1;
\ No newline at end of file
index f46c09d..903c4b2 100644 (file)
@@ -27,34 +27,57 @@ sub check_objects {
   $self->add_info_columns({ header => $::locale->text('Customer/Vendor'), method => 'vc_name' });
 }
 
-sub check_duplicates {
-  my ($self, %params) = @_;
-
-  my $normalizer = sub { my $name = $_[0]; $name =~ s/[\s,\.\-]//g; return $name; };
-  my $name_maker = sub { return $normalizer->($_[0]->shiptoname) . '--' . $normalizer->($_[0]->shiptostreet) };
-
-  my %by_id_and_name;
-  if ('check_db' eq $self->controller->profile->get('duplicates')) {
-    foreach my $type (qw(customers vendors)) {
-      foreach my $vc (@{ $self->all_vc->{$type} }) {
-        $by_id_and_name{ $vc->id } = { map { ( $name_maker->($_) => 'db' ) } @{ $vc->shipto } };
+sub get_duplicate_check_fields {
+  return {
+    shiptoname_and_shiptostreet => {
+      label     => $::locale->text('Name and Street'),
+      default   => 1,
+      maker     => sub {
+        my $o = shift;
+        return join(
+                 '--',
+                 $o->trans_id,
+                 map(
+                   { s/[\s,\.\-]//g; $_ }
+                   $o->shiptoname,
+                   $o->shiptostreet
+                 )
+        );
       }
-    }
-  }
-
-  foreach my $entry (@{ $self->controller->data }) {
-    next if @{ $entry->{errors} };
-
-    my $name = $name_maker->($entry->{object});
-
-    $by_id_and_name{ $entry->{vc}->id } ||= { };
-    if (!$by_id_and_name{ $entry->{vc}->id }->{ $name }) {
-      $by_id_and_name{ $entry->{vc}->id }->{ $name } = 'csv';
-
-    } else {
-      push @{ $entry->{errors} }, $by_id_and_name{ $entry->{vc}->id }->{ $name } eq 'db' ? $::locale->text('Duplicate in database') : $::locale->text('Duplicate in CSV file');
-    }
-  }
+    },
+
+    shiptoname => {
+      label     => $::locale->text('Name'),
+      default   => 1,
+      maker     => sub {
+        my $o = shift;
+        return join(
+                 '--',
+                 $o->trans_id,
+                 map(
+                   { s/[\s,\.\-]//g; $_ }
+                   $o->shiptoname
+                 )
+        );
+      }
+    },
+
+    shiptostreet => {
+      label     => $::locale->text('Street'),
+      default   => 1,
+      maker     => sub {
+        my $o = shift;
+        return join(
+                 '--',
+                 $o->trans_id,
+                 map(
+                   { s/[\s,\.\-]//g; $_ }
+                   $o->shiptostreet
+                 )
+        );
+      }
+    },
+  };
 }
 
 sub field_lengths {
@@ -104,4 +127,4 @@ sub setup_displayable_columns {
                                 );
 }
 
-1;
+1;
\ No newline at end of file
index b3ab54b..dc275c0 100644 (file)
@@ -1174,6 +1174,7 @@ $self->{texts} = {
   'Multibyte Encoding'          => 'Zeichenkodierung',
   'MwSt. inkl.'                 => 'MwSt. inkl.',
   'Name'                        => 'Name',
+  'Name and Street'             => 'Name und Straße',
   'Name missing!'               => 'Name fehlt!',
   'National'                    => 'Inand',
   'National Expenses'           => 'Aufwand Inland',
index e835ed5..eba42f6 100644 (file)
@@ -1,4 +1,7 @@
-[% USE HTML %][% USE LxERP %][% USE L %]
+[%- USE HTML %]
+[%- USE LxERP %]
+[%- USE L %]
+[%- USE T8 %]
 <body>
 
  <div class="listtop">[% FORM.title %]</div>
@@ -6,6 +9,7 @@
  [%- INCLUDE 'common/flash.html' %]
 
  <form method="post" action="controller.pl" enctype="multipart/form-data">
+  [% L.hidden_tag('form_sent', '1') %]
   [% L.hidden_tag('action', 'CsvImport/dispatch') %]
   [% L.hidden_tag('profile.type', SELF.profile.type) %]
 
     </td>
    </tr>
 
-   <tr>
-    <th align="right">[%- LxERP.t8('Check for duplicates') %]:</th>
-    <td colspan="10">
-     [% opts = [ [ 'no_check',  LxERP.t8('Do not check for duplicates') ],
-                 [ 'check_csv', LxERP.t8('Discard duplicate entries in CSV file') ],
-                 [ 'check_db',  LxERP.t8('Discard entries with duplicates in database or CSV file') ] ] %]
-     [% L.select_tag('settings.duplicates', L.options_for_select(opts, default => SELF.profile.get('duplicates')), style => 'width: 300px') %]
-    </td>
-   </tr>
+   [% duplicate_fields = SELF.worker.get_duplicate_check_fields() %]
+   [% IF ( duplicate_fields.size ) %]
+     <tr>
+       <th align="right">[%- LxERP.t8('Check for duplicates') %]:</th>
+
+       <td colspan=10>
+         [% FOREACH key = duplicate_fields.keys %]
+           <input type="checkbox" name="settings.duplicates_[% key | html %]" id="settings.duplicates_[% key | html %]" value="1"[% IF ( SELF.profile.get('duplicates_'_ key) || (duplicate_fields.$key.default && !FORM.form_sent ) ) %] checked="checked"[% END %]\>
+           <label for="settings.duplicates_[% key | html %]">[% duplicate_fields.$key.label | html %]</label>
+         [% END %]
+       </td>
+     </tr>
+
+     <tr>
+       <th align="right"></th>
+
+       <td colspan=10>
+         [% opts = [ [ 'no_check',  LxERP.t8('Do not check for duplicates') ],
+                     [ 'check_csv', LxERP.t8('Discard duplicate entries in CSV file') ],
+                     [ 'check_db',  LxERP.t8('Discard entries with duplicates in database or CSV file') ] ] %]
+         [% L.select_tag('settings.duplicates', L.options_for_select(opts, default => SELF.profile.get('duplicates')), style => 'width: 300px') %]
+       </td>
+     </tr>
+   [% END %]
 
 [%- IF SELF.type == 'parts' %]
  [%- INCLUDE 'csv_import/_form_parts.html' %]
     -->
  </script>
 </body>
-</html>
+</html>
\ No newline at end of file