Revision f87763cd
Von Moritz Bunkus vor mehr als 13 Jahren hinzugefügt
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ß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öschen', |
549 | 545 |
'Delete drafts' => 'Entwürfe löschen', |
550 | 546 |
'Delete group' => 'Gruppe lö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ß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ö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ö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ür Sie anlegen und allen Benutzern Zugriff auf alle Lx-Office-Funktionen gewä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üssen einer Position entweder gar keinen Lagerausgang oder die vollstä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öß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ö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ück', |
828 | 829 |
'Go one step forward' => 'Einen Schritt vorwä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äche an. Lx-Office wird dann die Datenbank und die Tabellen für Sie anlegen.', |
872 | 872 |
'If you yourself want to upgrade the installation then please read the file "doc/UPGRADE" and follow the steps outlined in this file.' => 'Wenn Sie selber die Aktualisierung bzw. Einrichtung übernehmen wollen, so lesen Sie bitte die Datei "doc/UPGRADE" 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ü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ä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ä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ü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ür die Auswahl verfügbaren Einträge enthalten. Die Einträge werden mit \'##\' voneinander getrennt. Beispiel: \'Früh##Normal##Spä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ä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öhe des Textfeldes. Wenn nicht anders angegeben, so werden sie 30 Zeichen breit und fü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
Kunden-/Lieferantenstammdatenimport: zumindest das Testen funktioniert