Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision f87763cd

Von Moritz Bunkus vor mehr als 13 Jahren hinzugefügt

  • ID f87763cd84d89aafc4c4110ba42d041b02ce4371
  • Vorgänger 0389fbc6
  • Nachfolger 7b81cb26

Kunden-/Lieferantenstammdatenimport: zumindest das Testen funktioniert

Unterschiede anzeigen:

SL/Controller/CsvImport.pm
6 6
use SL::DB::CsvImportProfile;
7 7
use SL::Helper::Flash;
8 8
use SL::SessionFile;
9
use SL::Controller::CsvImport::CustomerVendor;
9 10

  
10 11
use List::MoreUtils qw(none);
11 12

  
......
13 14

  
14 15
use Rose::Object::MakeMethods::Generic
15 16
(
16
 scalar => [ qw(type profile file all_profiles all_charsets sep_char all_sep_chars quote_char all_quote_chars escape_char all_escape_chars all_buchungsgruppen) ],
17
 scalar => [ qw(type profile file all_profiles all_charsets sep_char all_sep_chars quote_char all_quote_chars escape_char all_escape_chars all_buchungsgruppen
18
                import_status errors headers data num_imported) ],
17 19
);
18 20

  
19 21
__PACKAGE__->run_before('check_auth');
......
128 130
  $self->profile_from_form;
129 131

  
130 132
  if ($::form->{file}) {
131
    my $file = SL::SessionFile->new($self->csv_file_name, "w");
133
    my $file = SL::SessionFile->new($self->csv_file_name, mode => '>');
132 134
    $file->fh->print($::form->{file});
133 135
    $file->fh->close;
134 136
  }
135 137

  
136
  my $file = SL::SessionFile->new($self->csv_file_name, "w");
138
  my $file = SL::SessionFile->new($self->csv_file_name, mode => '<', encoding => $self->profile->get('charset'));
137 139
  if (!$file->fh) {
138 140
    flash('error', $::locale->text('No file has been uploaded yet.'));
139 141
    return $self->action_new;
140 142
  }
141 143

  
142
  # do the import thingy...
144
  my $worker = $self->{type} eq 'customers_vendors' ? SL::Controller::CsvImport::CustomerVendor->new(controller => $self, file => $file)
145
    :                                                 die "Program logic error";
146

  
147
  $worker->run;
148
  $worker->save_objects if !$params{test};
149

  
150
  $self->import_status($params{test} ? 'tested' : 'imported');
151

  
143 152
  $self->action_new;
144 153
}
145 154

  
SL/Controller/CsvImport/Base.pm
1
package SL::Controller::CsvImport::Base;
2

  
3
use strict;
4

  
5
use SL::Helper::Csv;
6

  
7
use parent qw(Rose::Object);
8

  
9
use Rose::Object::MakeMethods::Generic
10
(
11
 scalar                  => [ qw(controller file csv) ],
12
 'scalar --get_set_init' => [ qw(profile existing_objects class manager_class) ],
13
);
14

  
15
sub run {
16
  my ($self) = @_;
17

  
18
  $::lxdebug->dump(0, "file", $self->file);
19
  $::lxdebug->dump(0, "profile", $self->controller->profile);
20
  my $profile = $self->profile;
21
  $self->csv(SL::Helper::Csv->new(file                   => $self->file->file_name,
22
                                  encoding               => $self->controller->profile->get('charset'),
23
                                  class                  => $self->class,
24
                                  profile                => $profile,
25
                                  ignore_unknown_columns => 1,
26
                                  map { ( $_ => $self->controller->profile->get($_) ) } qw(sep_char escape_char quote_char),
27
                                 ));
28
  $self->csv->parse;
29

  
30
  $self->controller->errors([ $self->csv->errors ]) if $self->csv->errors;
31

  
32
  $::lxdebug->dump(0, "err", $self->csv->errors);
33

  
34
  return unless $self->csv->header;
35

  
36
  my $headers         = { headers => [ grep { $profile->{$_} } @{ $self->csv->header } ] };
37
  $headers->{methods} = [ map { $profile->{$_} } @{ $headers->{headers} } ];
38
  $self->controller->headers($headers);
39

  
40
  $self->controller->data([ map { { object => $_, errors => [] } } $self->csv->get_objects ]);
41

  
42
  $self->check_objects;
43
  $self->check_duplicates if $self->controller->profile->get('duplicates', 'no_check') ne 'no_check';
44
}
45

  
46
sub init_profile {
47
  my ($self) = @_;
48

  
49
  eval "require " . $self->class;
50

  
51
  my %profile;
52
  for my $col ($self->class->meta->columns) {
53
    my $name = $col->isa('Rose::DB::Object::Metadata::Column::Numeric')   ? "$col\_as_number"
54
      :        $col->isa('Rose::DB::Object::Metadata::Column::Date')      ? "$col\_as_date"
55
      :        $col->isa('Rose::DB::Object::Metadata::Column::Timestamp') ? "$col\_as_date"
56
      :                                                                     $col->name;
57

  
58
    $profile{$col} = $name;
59
  }
60

  
61
  $self->profile(\%profile);
62
}
63

  
64
sub init_existing_objects {
65
  my ($self) = @_;
66

  
67
  eval "require " . $self->class;
68
  $self->existing_objects($self->manager_class->get_all);
69
}
70

  
71
sub init_class {
72
  die "class not set";
73
}
74

  
75
sub init_manager_class {
76
  my ($self) = @_;
77

  
78
  $self->class =~ m/^SL::DB::(.+)/;
79
  $self->manager_class("SL::DB::Manager::" . $1);
80
}
81

  
82
sub check_objects {
83
}
84

  
85
sub check_duplicates {
86
}
87

  
88
sub save_objects {
89
  my ($self, %params) = @_;
90

  
91
  my $data = $params{data} || $self->controller->data;
92

  
93
  foreach my $entry (@{ $data }) {
94
    if (!$entry->{object}->save) {
95
      push @{ $entry->{errors} }, $::locale->text('Error when saving: #1', $entry->{object}->db->error);
96
    } else {
97
      $self->controller->num_imported($self->controller->num_imported + 1);
98
    }
99
  }
100
}
101

  
102
1;
SL/Controller/CsvImport/CustomerVendor.pm
1
package SL::Controller::CsvImport::CustomerVendor;
2

  
3
use strict;
4

  
5
use SL::Helper::Csv;
6

  
7
use parent qw(SL::Controller::CsvImport::Base);
8

  
9
use Rose::Object::MakeMethods::Generic
10
(
11
 scalar => [ qw(table) ],
12
);
13

  
14
sub run {
15
  my ($self) = @_;
16

  
17
  $self->table($self->controller->profile->get('table') eq 'customer' ? 'customer' : 'vendor');
18
  $self->class('SL::DB::' . ucfirst($self->table));
19

  
20
  $self->SUPER::run;
21
}
22

  
23
sub check_objects {
24
  my ($self) = @_;
25

  
26
  my $numbercolumn  = $self->controller->profile->get('table') . "number";
27
  my %vcs_by_number = map { ( $_->$numbercolumn => 1 ) } @{ $self->existing_objects };
28

  
29
  foreach my $entry (@{ $self->controller->data }) {
30
    my $object = $entry->{object};
31

  
32
    my $name =  $object->name;
33
    $name    =~ s/^\s+//;
34
    $name    =~ s/\s+$//;
35
    if (!$name) {
36
      push @{ $entry->{errors} }, $::locale->text('Error: Name missing');
37
      next;
38
    }
39

  
40
    if ($vcs_by_number{ $object->$numbercolumn }) {
41
      $entry->{object}->$numbercolumn('####');
42
    } else {
43
      $vcs_by_number{ $object->$numbercolumn } = $object;
44
    }
45
  }
46
}
47

  
48
sub check_duplicates {
49
  my ($self, %params) = @_;
50

  
51
  my $normalizer = sub { my $name = $_[0]; $name =~ s/[\s,\.\-]//g; return $name; };
52

  
53
  my %by_name;
54
  if ('check_db' eq $self->controller->profile->get('duplicates')) {
55
    %by_name = map { ( $normalizer->($_->name) => 1 ) } @{ $self->existing_objects };
56
  }
57

  
58
  foreach my $entry (@{ $self->controller->data }) {
59
    next if @{ $entry->{errors} };
60

  
61
    my $name = $normalizer->($entry->{object}->name);
62
    if (!$by_name{$name}) {
63
      $by_name{$name} = 1;
64

  
65
    } else {
66
      push @{ $entry->{errors} }, $::locale->text('Duplicate');
67
    }
68
  }
69
}
70

  
71
sub save_objects {
72
  my ($self, %params) = @_;
73

  
74
  my $numbercolumn   = $self->table . 'number';
75
  my $with_number    = [ grep { $_->{object}->$numbercolumn ne '####' } @{ $self->controller->data } ];
76
  my $without_number = [ grep { $_->{object}->$numbercolumn eq '####' } @{ $self->controller->data } ];
77

  
78
  map { $_->{object}->$numbercolumn('') } @{ $without_number };
79

  
80
  $self->SUPER::save_objects(data => $with_number);
81
  $self->SUPER::save_objects(data => $without_number);
82
}
83

  
84
1;
SL/DB/Customer.pm
32 32
  my ($self) = @_;
33 33

  
34 34
  $self->create_trans_number if $self->customernumber eq '';
35
  return 1;
35 36
}
36 37

  
37 38
sub short_address {
SL/DB/Vendor.pm
31 31
  my ($self) = @_;
32 32

  
33 33
  $self->create_trans_number if $self->vendornumber eq '';
34
  return 1;
34 35
}
35 36

  
36 37
1;
locale/de/all
182 182
  'Ap aging on %s'              => 'Offene Verbindlichkeiten zum %s',
183 183
  'Application Error. No Format given' => 'Fehler in der Anwendung. Das Ausgabeformat fehlt.',
184 184
  'Application Error. Wrong Format' => 'Fehler in der Anwendung. Falsches Format: ',
185
  'Applying #1:'                => 'Führe #1 aus:',
186
  'Approximately #1 prices will be updated.' => 'Ungefähr #1 Preise werden aktualisiert.',
187
  'Apply Filter'                => 'Filtern',
188 185
  'Apply to all parts'          => 'Bei allen Artikeln setzen',
189 186
  'Apply to parts without buchungsgruppe' => 'Bei allen Artikeln ohne gültige Buchungsgruppe setzen',
187
  'Applying #1:'                => 'Führe #1 aus:',
190 188
  'Approximately #1 prices will be updated.' => 'Ungefähr #1 Preise werden aktualisiert.',
191 189
  'Apr'                         => 'Apr',
192 190
  'April'                       => 'April',
......
281 279
  'Birthday'                    => 'Geburtstag',
282 280
  'Bis'                         => 'bis',
283 281
  'Bis Konto: '                 => 'bis Konto: ',
282
  'Block'                       => 'Block',
284 283
  'Body'                        => 'Text',
285 284
  'Body:'                       => 'Text:',
286 285
  'Books are open'              => 'Die Bücher sind geöffnet.',
......
371 370
  'Chartaccounts connected to this Tax:' => 'Konten, die mit dieser Steuer verknüpft sind:',
372 371
  'Check'                       => 'Scheck',
373 372
  'Check Details'               => 'Bitte Angaben überprüfen',
374
  'Check the number format.'    => 'Prüfen Sie das Format der Zahlen.',
375 373
  'Check for duplicates'        => 'Dublettencheck',
376 374
  'Checks'                      => 'Schecks',
377 375
  'Choose Customer'             => 'Endkunde wählen:',
......
388 386
  'Close Window'                => 'Fenster Schlie&szlig;en',
389 387
  'Closed'                      => 'Geschlossen',
390 388
  'Collective Orders only work for orders from one customer!' => 'Sammelaufträge funktionieren nur für Aufträge von einem Kunden!',
391
  'Column'                      => 'Spalte',
392
  'Column definitions can be found here:' => 'Die einzelnen Spaltendefinitionen sind hier verzeichnet:',
393 389
  'Comma'                       => 'Komma',
394 390
  'Comment'                     => 'Kommentar',
395 391
  'Company'                     => 'Firma',
......
548 544
  'Delete delivery order'       => 'Lieferschein l&ouml;schen',
549 545
  'Delete drafts'               => 'Entwürfe löschen',
550 546
  'Delete group'                => 'Gruppe l&ouml;schen',
551
  'Delete transaction'          => 'Buchung löschen',
552 547
  'Delete profile'              => 'Profil löschen',
548
  'Delete transaction'          => 'Buchung löschen',
553 549
  'Delivered'                   => 'Geliefert',
554 550
  'Delivery Date'               => 'Lieferdatum',
555 551
  'Delivery Order'              => 'Lieferschein',
......
579 575
  'Dimension unit'              => 'Ma&szlig;einheit',
580 576
  'Directory'                   => 'Verzeichnis',
581 577
  'Discard duplicate entries in CSV file' => 'Doppelte Einträge in CSV-Datei verwerfen',
582
  'Discard entries with duplicates in database and CSV file' => 'Einträge aus CSV-Datei verwerfen, die es bereits in der Datenbank gibt',
578
  'Discard entries with duplicates in database or CSV file' => 'Einträge aus CSV-Datei verwerfen, die es bereits in der Datenbank oder der CSV-Datei gibt',
583 579
  'Discount'                    => 'Rabatt',
584 580
  'Display'                     => 'Anzeigen',
585 581
  'Display file'                => 'Datei anzeigen',
586 582
  'Display options'             => 'Anzeigeoptionen',
583
  'Do not check for duplicates' => 'Nicht nach Dubletten suchen',
584
  'Do not set default buchungsgruppe' => 'Nie Standardbuchungsgruppe setzen',
587 585
  'Do you really want to close the following SEPA exports? No payment will be recorded for bank collections that haven\'t been marked as executed yet.' => 'Wollen Sie wirklich die folgenden SEPA-Exporte abschließen? Für Überweisungen, die noch nicht gebucht wurden, werden dann keine Zahlungen verbucht.',
588 586
  'Do you really want to close the following SEPA exports? No payment will be recorded for bank transfers that haven\'t been marked as executed yet.' => 'Wollen Sie wirklich die folgenden SEPA-Exporte abschließen? Für Überweisungen, die noch nicht gebucht wurden, werden dann keine Zahlungen verbucht.',
589 587
  'Do you really want to delete AP transaction #1?' => 'Wollen Sie wirklich die Kreditorenbuchung #1 löschen?',
......
591 589
  'Do you really want to delete GL transaction #1?' => 'Wollen Sie wirklich die Dialogbuchung #1 löschen?',
592 590
  'Do you really want to delete this group?' => 'Gruppe wirklich l&ouml;schen?',
593 591
  'Do you really want to delete this object?' => 'Wollen Sie dieses Objekt wirklich löschen?',
594
  'Do not check for duplicates' => 'Nicht nach Dubletten suchen',
595
  'Do not set default buchungsgruppe' => 'Nie Standardbuchungsgruppe setzen',
596
  'Do you really want to delete this record?' => 'Wollen Sie diesen Beleg wirklich löschen?',
597 592
  'Do you really want to delete this warehouse?' => 'Wollen Sie dieses Lager wirklich l&ouml;schen?',
598 593
  'Do you want Lx-Office to create a group for access to all functions?' => 'Wollen Sie, dass Lx-Office eine Gruppe mit Zugriff auf alle Funktionen anlegt?',
599 594
  'Do you want to <b>limit</b> your search?' => 'Wollen Sie Ihre Suche <b>spezialisieren</b>?',
......
627 622
  'Dunning number'              => 'Mahnungsnummer',
628 623
  'Dunning overview'            => 'Mahnungsübersicht',
629 624
  'Dunnings'                    => 'Mahnungen',
625
  'Duplicate'                   => 'Duplikat',
630 626
  'During this user migration Lx-Office can create such a group for you and grant all users access to all of Lx-Office\'s functions.' => 'Im Rahmen dieser Benutzerdatenmigration kann Lx-Office eine solche Gruppe f&uuml;r Sie anlegen und allen Benutzern Zugriff auf alle Lx-Office-Funktionen gew&auml;hren.',
631 627
  'E-mail'                      => 'eMail',
632 628
  'E-mail Statement to'         => 'Fälligkeitsabrechnung als eMail an',
......
728 724
  'Error in position #1: You must either assign no transfer at all or the full quantity of #2 #3.' => 'Fehler in Position #1: Sie m&uuml;ssen einer Position entweder gar keinen Lagerausgang oder die vollst&auml;ndige im Lieferschein vermerkte Menge von #2 #3 zuweisen.',
729 725
  'Error in row #1: The quantity you entered is bigger than the stocked quantity.' => 'Fehler in Zeile #1: Die angegebene Menge ist gr&ouml;&szlig;er als die vorhandene Menge.',
730 726
  'Error message from the database driver:' => 'Fehlermeldung des Datenbanktreibers:',
727
  'Error when saving: #1'       => 'Fehler beim Speichern: #2',
731 728
  'Error!'                      => 'Fehler!',
729
  'Error: Name missing'         => 'Fehler: Name fehlt',
730
  'Errors'                      => 'Fehler',
732 731
  'Ertrag'                      => 'Ertrag',
733 732
  'Ertrag prozentual'           => 'Ertrag prozentual',
734 733
  'Escape character'            => 'Escape-Zeichen',
......
806 805
  'Foreign Revenues'            => 'Erl&ouml;se Ausland',
807 806
  'Form details (second row)'   => 'Formulardetails (zweite Positionszeile)',
808 807
  'Formula'                     => 'Formel',
808
  'Found #1 errors.'            => '#1 Fehler gefunden.',
809
  'Found #1 objects to import.' => '#1 zu importierende Objekte gefunden.',
809 810
  'Free report period'          => 'Freier Zeitraum',
810 811
  'Free-form text'              => 'Textzeile',
811 812
  'Fristsetzung'                => 'Fristsetzung',
......
826 827
  'Given Name'                  => 'Vorname',
827 828
  'Go one step back'            => 'Einen Schritt zur&uuml;ck',
828 829
  'Go one step forward'         => 'Einen Schritt vorw&auml;rts',
829
  'Gogogo'                      => '',
830 830
  'Greeting'                    => 'Anrede',
831 831
  'Greetings'                   => 'Anreden',
832 832
  'Group'                       => 'Warengruppe',
......
871 871
  'If you want to set up the authentication database yourself then log in to the administration panel. Lx-Office will then create the database and tables for you.' => 'Wenn Sie die Authentifizierungsdatenbank selber einrichten wollen, so melden Sie sich an der Administrationsoberfl&auml;che an. Lx-Office wird dann die Datenbank und die Tabellen f&uuml;r Sie anlegen.',
872 872
  'If you yourself want to upgrade the installation then please read the file &quot;doc/UPGRADE&quot; and follow the steps outlined in this file.' => 'Wenn Sie selber die Aktualisierung bzw. Einrichtung &uuml;bernehmen wollen, so lesen Sie bitte die Datei &quot;doc/UPGRADE&quot; und folgen Sie den dort beschriebenen Schritten.',
873 873
  'Image'                       => 'Grafik',
874
  'Import'                      => 'Import',
874 875
  'Import CSV'                  => 'CSV-Import',
875
  'Import Help'                 => 'Importhilfe',
876 876
  'Import file'                 => 'Import-Datei',
877
  'Import preview'              => 'Import-Vorschau',
877 878
  'Import profiles'             => 'Import-Profil',
879
  'Import result'               => 'Import-Ergebnis',
878 880
  'In Lx-Office 2.4.0 the administrator has to enter a list of units in the administrative section.' => 'In Lx-Office 2.4.0 muss der Administrator in den Systemeinstellungen eine Liste von verwendbaren Einheiten angeben.',
879 881
  'In order to do that hit the button "Delete transaction".' => 'Drücken Sie dafür auf den Button "Buchung löschen".',
880 882
  'In the latter case the tables needed by Lx-Office will be created in that database.' => 'In letzterem Fall werden die von Lx-Office benötigten Tabellen in dieser existierenden Datenbank angelegt.',
......
990 992
  'Licenses'                    => 'Lizenzen',
991 993
  'Limit part selection'        => 'Artikelauswahl eingrenzen',
992 994
  'Line Total'                  => 'Zeilensumme',
995
  'Line and column'             => 'Zeile und Spalte',
993 996
  'Line endings'                => 'Zeilenumbr&uuml;che',
994 997
  'List'                        => 'Anzeigen',
995 998
  'List Accounting Groups'      => 'Buchungsgruppen anzeigen',
......
1233 1236
  'Part Notes'                  => 'Bemerkungen',
1234 1237
  'Part Number'                 => 'Artikelnummer',
1235 1238
  'Part Number missing!'        => 'Artikelnummer fehlt!',
1236
  'Partnumber'                  => '',
1237 1239
  'Partnumber must not be set to empty!' => 'Die Artikelnummer darf nicht auf leer ge&auml;ndert werden.',
1238 1240
  'Partnumber not unique!'      => 'Artikelnummer bereits vorhanden!',
1239 1241
  'Parts'                       => 'Waren',
......
1272 1274
  'Please ask your administrator to create warehouses and bins.' => 'Bitten Sie Ihren Administrator, dass er Lager und Lagerpl&auml;tze anlegt.',
1273 1275
  'Please enter a license key.' => 'Bitte geben Sie einen Lizenzschlüssel an.',
1274 1276
  'Please enter a number of licenses.' => 'Bitte geben Sie die Anzahl Lizenzschlüssel an.',
1275
  'Please enter the login for the new user.' => 'Bitte geben Sie das Login für den neuen Benutzer ein.',
1276 1277
  'Please enter a profile name.' => 'Bitte geben Sie einen Profilnamen an.',
1278
  'Please enter the login for the new user.' => 'Bitte geben Sie das Login für den neuen Benutzer ein.',
1277 1279
  'Please enter the name of the database that will be used as the template for the new database:' => 'Bitte geben Sie den Namen der Datenbank an, die als Vorlage f&uuml;r die neue Datenbank benutzt wird:',
1278 1280
  'Please enter the name of the dataset you want to restore the backup in.' => 'Bitte geben Sie den Namen der Datenbank ein, in der Sie die Sicherung wiederherstellen wollen.',
1279 1281
  'Please enter the sales tax identification number.' => 'Bitte geben Sie die Umsatzsteueridentifikationsnummer an.',
......
1520 1522
  'Selection'                   => 'Auswahlbox',
1521 1523
  'Selection fields: The option field must contain the available options for the selection. Options are separated by \'##\', for example \'Early##Normal##Late\'.' => 'Auswahlboxen: Das Optionenfeld muss die f&uuml;r die Auswahl verf&uuml;gbaren Eintr&auml;ge enthalten. Die Eintr&auml;ge werden mit \'##\' voneinander getrennt. Beispiel: \'Fr&uuml;h##Normal##Sp&auml;t\'.',
1522 1524
  'Sell Price'                  => 'Verkaufspreis',
1523
  'Sell prices have fallen below the minimum sell price. PDF export and email deactivated until the quotation has been approved.' => 'Verkaufspreise liegen teilweise unter dem Mindestverkaufspreis. PDF-Export und E-Mail deaktiviert, bis das Angebot freigegeben wurde.',
1524
  'Sellprice'                   => 'Verkaufspreis',
1525 1525
  'Sellprice adjustment'        => 'Verkaufspreis: Preisanpassung',
1526 1526
  'Sellprice significant places' => 'Verkaufspreis: Nachkommastellen',
1527 1527
  'Semicolon'                   => 'Semikolon',
1528
  'Send documents'              => 'Dokumente verschicken',
1529 1528
  'Send the backup via Email'   => 'Die Sicherungsdatei per Email verschicken',
1530 1529
  'Sep'                         => 'Sep',
1531 1530
  'Separator'                   => 'Trennzeichen',
......
1541 1540
  'Services'                    => 'Dienstleistungen',
1542 1541
  'Set Language Values'         => 'Spracheinstellungen',
1543 1542
  'Set eMail text'              => 'eMail Text eingeben',
1543
  'Settings'                    => 'Einstellungen',
1544 1544
  'Setup Menu'                  => 'Menü-Variante',
1545 1545
  'Setup Templates'             => 'Vorlagen auswählen',
1546
  'Settings'                    => 'Einstellungen',
1547 1546
  'Ship to'                     => 'Lieferadresse',
1548 1547
  'Ship via'                    => 'Transportmittel',
1549 1548
  'Shipping Address'            => 'Lieferadresse',
......
1563 1562
  'Show your TODO list after loggin in' => 'Aufgabenliste nach dem Anmelden anzeigen',
1564 1563
  'Signature'                   => 'Unterschrift',
1565 1564
  'Since bin is not enforced in the parts data, please specify a bin where goods without a specified bin will be put.' => 'Da Lagerpl&auml;tze kein Pflichtfeld sind, geben Sie bitte einen Lagerplatz an, in dem Waren ohne spezifizierten Lagerplatz eingelagert werden sollen.',
1566
  'Skip'                        => 'Überspringen',
1567 1565
  'Single quotes'               => 'Einfache Anführungszeichen',
1566
  'Skip'                        => 'Überspringen',
1568 1567
  'Skonto'                      => 'Skonto',
1569 1568
  'Skonto Terms'                => 'Zahlungsziel Skonto',
1570 1569
  'Sold'                        => 'Verkauft',
......
1661 1660
  'Template database'           => 'Datenbankvorlage',
1662 1661
  'Templates'                   => 'Vorlagen',
1663 1662
  'Terms missing in row '       => '+Tage fehlen in Zeile ',
1663
  'Test and preview'            => 'Test und Vorschau',
1664 1664
  'Test connection'             => 'Verbindung testen',
1665 1665
  'Text field'                  => 'Textfeld',
1666 1666
  'Text field variables: \'WIDTH=w HEIGHT=h\' sets the width and height of the text field. They default to 30 and 5 respectively.' => 'Textfelder: \'WIDTH=w HEIGHT=h\' setzen die Breite und die H&ouml;he des Textfeldes. Wenn nicht anders angegeben, so werden sie 30 Zeichen breit und f&uuml;nf Zeichen hoch dargestellt.',
......
1923 1923
  'Update prices of existing entries' => 'Preise von vorhandenen Artikeln aktualisieren',
1924 1924
  'Update?'                     => 'Aktualisieren?',
1925 1925
  'Updated'                     => 'Erneuert am',
1926
  'Use'                         => 'Verwendung',
1927 1926
  'Uploaded on #1, size #2 kB'  => 'Am #1 hochgeladen, Größe #2 kB',
1928 1927
  'Use As Template'             => 'Als Vorlage verwenden',
1929 1928
  'Use Templates'               => 'Benutze Vorlagen',
......
2144 2143
  'order'                       => 'Reihenfolge',
2145 2144
  'our vendor number at customer' => 'Unsere Lieferanten-Nr. beim Kunden',
2146 2145
  'part_list'                   => 'warenliste',
2147
  'pick_list'                   => 'Sammelliste',
2148 2146
  'percental'                   => 'prozentual',
2147
  'pick_list'                   => 'Sammelliste',
2149 2148
  'plural first char'           => 'P',
2150 2149
  'pos_bilanz'                  => 'Bilanz',
2151 2150
  'pos_bwa'                     => 'BWA',
templates/webpages/csv_import/_data.html
1
[% USE LxERP %]
2

  
3
[%- IF SELF.errors %]
4
 [%- PROCESS 'csv_import/_errors.html' %]
5
[%- END %]
6

  
7
[%- IF SELF.import_status == 'imported' %]
8
 [%- PROCESS 'csv_import/_result.html' %]
9
[%- END %]
10

  
11
[%- PROCESS 'csv_import/_preview.html' %]
12

  
templates/webpages/csv_import/_errors.html
1
[% USE LxERP %]
2

  
3
 <h3>[%- LxERP.t8('Errors') %]</h3>
4

  
5
 <p>[%- LxERP.t8('Found #1 errors.', SELF.errors.size) %]</p>
6

  
7
 <table>
8
  <tr class="listheading">
9
   <th>[%- LxERP.t8('Line and column') %]</th>
10
   <th>[%- LxERP.t8('Block') %]</th>
11
   <th>[%- LxERP.t8('Error') %]</th>
12
  </tr>
13
  [% FOREACH err = SELF.errors %]
14
   <tr>
15
    <td>[% err.4 %]:[% err.3 %]</td>
16
    <td>[% err.0 %]</td>
17
    <td>[% err.2 %]</td>
18
   </tr>
19
  [% END %]
20
 </table>
21
[% END %]
templates/webpages/csv_import/_form_customers_vendors.html
1
[% USE LxERP %]
2
[% USE L %]
3

  
1 4
<tr>
2 5
 <th align="right">[%- LxERP.t8('Target table') %]:</th>
3 6
 <td colspan="10">
templates/webpages/csv_import/_form_parts.html
1
[% USE LxERP %]
2
[% USE L %]
1 3
<tr>
2 4
 <th align="right">[%- LxERP.t8('Parts with existing part numbers') %]:</th>
3 5
 <td colspan="10">
templates/webpages/csv_import/_preview.html
1
[% USE HTML %]
2
[% USE LxERP %]
3

  
4
<h3>
5
 [%- IF SELF.import_status == 'tested' %]
6
  [%- LxERP.t8('Import preview') %]
7
 [%- ELSE %]
8
  [%- LxERP.t8('Import result') %]
9
 [%- END %]
10
</h3>
11

  
12
<p>[%- LxERP.t8('Found #1 objects to import.', SELF.data.size || 0) %]</p>
13

  
14
[% IF SELF.data.size %]
15
 <table>
16
  <tr class="listheading">
17
   [%- FOREACH column = SELF.headers.headers %]
18
    <th>[%- HTML.escape(column) %]</th>
19
   [%- END %]
20
   <th>[%- LxERP.t8('Notes') %]</th>
21
  </tr>
22

  
23
  [%- FOREACH row = SELF.data %]
24
  <tr class="[% IF row.errors.size %]redrow[% ELSE %]listrow[% END %][% loop.count % 2 %]">
25
   [%- FOREACH method = SELF.headers.methods %]
26
    <td>[%- HTML.escape(row.object.$method) %]</td>
27
   [%- END %]
28
   <td>
29
    [%- FOREACH error = row.errors %][%- HTML.escape(error) %][% UNLESS loop.last %]<br>[%- END %][%- END %]
30
   </td>
31
  </tr>
32
  [%- END %]
33

  
34
 </table>
35
[%- END %]
templates/webpages/csv_import/_result.html
1
[% USE LxERP %]
2

  
3
<p>[%- LxERP.t8('Found #1 objects to import.', SELF.data.size || 0) %]</p>
templates/webpages/csv_import/form.html
112 112
   <tr>
113 113
    <th align="right">[%- LxERP.t8('Check for duplicates') %]:</th>
114 114
    <td colspan="10">
115
     [% opts = [ [ 'no_check', LxERP.t8('Do not check for duplicates') ],
115
     [% opts = [ [ 'no_check',  LxERP.t8('Do not check for duplicates') ],
116 116
                 [ 'check_csv', LxERP.t8('Discard duplicate entries in CSV file') ],
117
                 [ 'check_db',  LxERP.t8('Discard entries with duplicates in database and CSV file') ] ] %]
117
                 [ 'check_db',  LxERP.t8('Discard entries with duplicates in database or CSV file') ] ] %]
118 118
     [% L.select_tag('settings.duplicates', L.options_for_select(opts, default => SELF.profile.get('duplicates')), style => 'width: 300px') %]
119 119
    </td>
120 120
   </tr>
......
139 139

  
140 140
  </table>
141 141

  
142
  [% L.submit_tag('action_test', LxERP.t8('Gogogo')) %]
142
  [% L.submit_tag('action_test', LxERP.t8('Test and preview')) %]
143
  [% IF SELF.import_status && SELF.data.size %]
144
   [% L.submit_tag('action_import', LxERP.t8('Import')) %]
145
  [%- END %]
143 146

  
144 147
 </form>
145 148

  
149
 [%- IF SELF.import_status %]
150
  [%- PROCESS 'csv_import/_data.html' %]
151
 [%- END %]
152

  
146 153
 <script type="text/javascript">
147 154
  <!--
148 155
    $(document).ready(function() {

Auch abrufbar als: Unified diff