From 5f55d797e05b1f29d4d7fbeed0d7b8f67895634c Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Mon, 18 Dec 2017 13:07:28 +0100 Subject: [PATCH] =?utf8?q?CSV-Import:=20Fix=20f=C3=BCr=20reflexive=20Spalt?= =?utf8?q?ennamen=20im=20Mapping?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Wenn eine CSV-Datei für den Bank-Import z.B. die Spalten `currency`, `amount`, `local_bank_number` enthalten, so schlug der Import aus gleich zwei Gründen fehl, wenn in der CSV-Spaten-Zuordnung die Namen alle auf sich selber abgebildet wurden, also `current` → `currency`, `amount` → `amount` und `local_bank_number` → `local_bank_number`. Untersuchung ergab die folgenden zwei Probleme: 1. Fehlermeldung `cannot bind reference` 2. Fehlermeldung `can't locate object method "local_bank_number" via package "SL::DB::BankTransaction"` Es stellte sich heraus, dass beim Speichern der CSV-Spalten in der Datenbank hier kivitendo gedacht hat, dass diese drei genannten Spalten auch als Methoden auf den DB-Objekt aufrufbar wären. Sind sie aber nicht. Schuld war der Mechanismus, der anhand der vorhandenen Spaltennamen-Zuordnungen (`$mapping`) und dem vorhandenen Spaltenprofil (`$profile`) entschieden hat, welche Namen als Methoden anzuerkennen. Im konkreten Fall ist es so, dass es sowohl ein solches Mapping als auch ein solches Profil gibt. In dem Fall darf aber ein Name, der zwar als Mapping existiert, dessen gemappter Name aber im Profil nicht existiert, auch nicht als Methodenname aufgefasst und in die `$specs` aufgenommen werden. Statt dessen muss er als »unbekannte Spalte« behandelt werden. --- SL/Helper/Csv/Dispatcher.pm | 4 ++-- t/helper/csv.t | 28 ++++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/SL/Helper/Csv/Dispatcher.pm b/SL/Helper/Csv/Dispatcher.pm index 418c184df..801e8229f 100644 --- a/SL/Helper/Csv/Dispatcher.pm +++ b/SL/Helper/Csv/Dispatcher.pm @@ -130,7 +130,7 @@ sub parse_profile { sub _parse_profile { my ($self, %params) = @_; - my $profile = $params{profile}; + my $profile = $params{profile} // {}; my $class = $params{class}; my $header = $params{header}; my $mapping = $params{mapping}; @@ -141,7 +141,7 @@ sub _parse_profile { next unless $col; if (exists $mapping->{$col} && $profile->{$mapping->{$col}}) { push @specs, $self->make_spec($col, $profile->{$mapping->{$col}}, $class); - } elsif (exists $mapping->{$col}) { + } elsif (exists $mapping->{$col} && !%{ $profile }) { push @specs, $self->make_spec($col, $mapping->{$col}, $class); } elsif (exists $profile->{$col}) { push @specs, $self->make_spec($col, $profile->{$col}, $class); diff --git a/t/helper/csv.t b/t/helper/csv.t index 99da3d38d..e3247263d 100644 --- a/t/helper/csv.t +++ b/t/helper/csv.t @@ -1,4 +1,4 @@ -use Test::More tests => 84; +use Test::More tests => 86; use lib 't'; use utf8; @@ -809,9 +809,33 @@ $csv->parse; is $csv->get_objects->[0]->sellprice, 4.99, 'case insensitive mapping with profile works'; +# self-mapping with profile +$csv = SL::Helper::Csv->new( + file => \"sellprice\n4,99", # " # make emacs happy + case_insensitive_header => 1, + profile => [{ + profile => { sellprice => 'sellprice_as_number' }, + mapping => { sellprice => 'sellprice' }, + class => 'SL::DB::Part', + }], +); +$csv->parse; +is $csv->get_objects->[0]->sellprice, 4.99, 'self-mapping with profile works'; + +# self-mapping without profile +$csv = SL::Helper::Csv->new( + file => \"sellprice\n4.99", # " # make emacs happy + case_insensitive_header => 1, + profile => [{ + mapping => { sellprice => 'sellprice' }, + class => 'SL::DB::Part', + }], +); +$csv->parse; +is $csv->get_objects->[0]->sellprice, 4.99, 'self-mapping without profile works'; + # vim: ft=perl # set emacs to perl mode # Local Variables: # mode: perl # End: - -- 2.20.1