Revision f87763cd
Von Moritz Bunkus vor mehr als 13 Jahren hinzugefügt
SL/Controller/CsvImport.pm | ||
---|---|---|
use SL::DB::CsvImportProfile;
|
||
use SL::Helper::Flash;
|
||
use SL::SessionFile;
|
||
use SL::Controller::CsvImport::CustomerVendor;
|
||
|
||
use List::MoreUtils qw(none);
|
||
|
||
... | ... | |
|
||
use Rose::Object::MakeMethods::Generic
|
||
(
|
||
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) ],
|
||
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
|
||
import_status errors headers data num_imported) ],
|
||
);
|
||
|
||
__PACKAGE__->run_before('check_auth');
|
||
... | ... | |
$self->profile_from_form;
|
||
|
||
if ($::form->{file}) {
|
||
my $file = SL::SessionFile->new($self->csv_file_name, "w");
|
||
my $file = SL::SessionFile->new($self->csv_file_name, mode => '>');
|
||
$file->fh->print($::form->{file});
|
||
$file->fh->close;
|
||
}
|
||
|
||
my $file = SL::SessionFile->new($self->csv_file_name, "w");
|
||
my $file = SL::SessionFile->new($self->csv_file_name, mode => '<', encoding => $self->profile->get('charset'));
|
||
if (!$file->fh) {
|
||
flash('error', $::locale->text('No file has been uploaded yet.'));
|
||
return $self->action_new;
|
||
}
|
||
|
||
# do the import thingy...
|
||
my $worker = $self->{type} eq 'customers_vendors' ? SL::Controller::CsvImport::CustomerVendor->new(controller => $self, file => $file)
|
||
: die "Program logic error";
|
||
|
||
$worker->run;
|
||
$worker->save_objects if !$params{test};
|
||
|
||
$self->import_status($params{test} ? 'tested' : 'imported');
|
||
|
||
$self->action_new;
|
||
}
|
||
|
SL/Controller/CsvImport/Base.pm | ||
---|---|---|
package SL::Controller::CsvImport::Base;
|
||
|
||
use strict;
|
||
|
||
use SL::Helper::Csv;
|
||
|
||
use parent qw(Rose::Object);
|
||
|
||
use Rose::Object::MakeMethods::Generic
|
||
(
|
||
scalar => [ qw(controller file csv) ],
|
||
'scalar --get_set_init' => [ qw(profile existing_objects class manager_class) ],
|
||
);
|
||
|
||
sub run {
|
||
my ($self) = @_;
|
||
|
||
$::lxdebug->dump(0, "file", $self->file);
|
||
$::lxdebug->dump(0, "profile", $self->controller->profile);
|
||
my $profile = $self->profile;
|
||
$self->csv(SL::Helper::Csv->new(file => $self->file->file_name,
|
||
encoding => $self->controller->profile->get('charset'),
|
||
class => $self->class,
|
||
profile => $profile,
|
||
ignore_unknown_columns => 1,
|
||
map { ( $_ => $self->controller->profile->get($_) ) } qw(sep_char escape_char quote_char),
|
||
));
|
||
$self->csv->parse;
|
||
|
||
$self->controller->errors([ $self->csv->errors ]) if $self->csv->errors;
|
||
|
||
$::lxdebug->dump(0, "err", $self->csv->errors);
|
||
|
||
return unless $self->csv->header;
|
||
|
||
my $headers = { headers => [ grep { $profile->{$_} } @{ $self->csv->header } ] };
|
||
$headers->{methods} = [ map { $profile->{$_} } @{ $headers->{headers} } ];
|
||
$self->controller->headers($headers);
|
||
|
||
$self->controller->data([ map { { object => $_, errors => [] } } $self->csv->get_objects ]);
|
||
|
||
$self->check_objects;
|
||
$self->check_duplicates if $self->controller->profile->get('duplicates', 'no_check') ne 'no_check';
|
||
}
|
||
|
||
sub init_profile {
|
||
my ($self) = @_;
|
||
|
||
eval "require " . $self->class;
|
||
|
||
my %profile;
|
||
for my $col ($self->class->meta->columns) {
|
||
my $name = $col->isa('Rose::DB::Object::Metadata::Column::Numeric') ? "$col\_as_number"
|
||
: $col->isa('Rose::DB::Object::Metadata::Column::Date') ? "$col\_as_date"
|
||
: $col->isa('Rose::DB::Object::Metadata::Column::Timestamp') ? "$col\_as_date"
|
||
: $col->name;
|
||
|
||
$profile{$col} = $name;
|
||
}
|
||
|
||
$self->profile(\%profile);
|
||
}
|
||
|
||
sub init_existing_objects {
|
||
my ($self) = @_;
|
||
|
||
eval "require " . $self->class;
|
||
$self->existing_objects($self->manager_class->get_all);
|
||
}
|
||
|
||
sub init_class {
|
||
die "class not set";
|
||
}
|
||
|
||
sub init_manager_class {
|
||
my ($self) = @_;
|
||
|
||
$self->class =~ m/^SL::DB::(.+)/;
|
||
$self->manager_class("SL::DB::Manager::" . $1);
|
||
}
|
||
|
||
sub check_objects {
|
||
}
|
||
|
||
sub check_duplicates {
|
||
}
|
||
|
||
sub save_objects {
|
||
my ($self, %params) = @_;
|
||
|
||
my $data = $params{data} || $self->controller->data;
|
||
|
||
foreach my $entry (@{ $data }) {
|
||
if (!$entry->{object}->save) {
|
||
push @{ $entry->{errors} }, $::locale->text('Error when saving: #1', $entry->{object}->db->error);
|
||
} else {
|
||
$self->controller->num_imported($self->controller->num_imported + 1);
|
||
}
|
||
}
|
||
}
|
||
|
||
1;
|
SL/Controller/CsvImport/CustomerVendor.pm | ||
---|---|---|
package SL::Controller::CsvImport::CustomerVendor;
|
||
|
||
use strict;
|
||
|
||
use SL::Helper::Csv;
|
||
|
||
use parent qw(SL::Controller::CsvImport::Base);
|
||
|
||
use Rose::Object::MakeMethods::Generic
|
||
(
|
||
scalar => [ qw(table) ],
|
||
);
|
||
|
||
sub run {
|
||
my ($self) = @_;
|
||
|
||
$self->table($self->controller->profile->get('table') eq 'customer' ? 'customer' : 'vendor');
|
||
$self->class('SL::DB::' . ucfirst($self->table));
|
||
|
||
$self->SUPER::run;
|
||
}
|
||
|
||
sub check_objects {
|
||
my ($self) = @_;
|
||
|
||
my $numbercolumn = $self->controller->profile->get('table') . "number";
|
||
my %vcs_by_number = map { ( $_->$numbercolumn => 1 ) } @{ $self->existing_objects };
|
||
|
||
foreach my $entry (@{ $self->controller->data }) {
|
||
my $object = $entry->{object};
|
||
|
||
my $name = $object->name;
|
||
$name =~ s/^\s+//;
|
||
$name =~ s/\s+$//;
|
||
if (!$name) {
|
||
push @{ $entry->{errors} }, $::locale->text('Error: Name missing');
|
||
next;
|
||
}
|
||
|
||
if ($vcs_by_number{ $object->$numbercolumn }) {
|
||
$entry->{object}->$numbercolumn('####');
|
||
} else {
|
||
$vcs_by_number{ $object->$numbercolumn } = $object;
|
||
}
|
||
}
|
||
}
|
||
|
||
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) => 1 ) } @{ $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} = 1;
|
||
|
||
} else {
|
||
push @{ $entry->{errors} }, $::locale->text('Duplicate');
|
||
}
|
||
}
|
||
}
|
||
|
||
sub save_objects {
|
||
my ($self, %params) = @_;
|
||
|
||
my $numbercolumn = $self->table . 'number';
|
||
my $with_number = [ grep { $_->{object}->$numbercolumn ne '####' } @{ $self->controller->data } ];
|
||
my $without_number = [ grep { $_->{object}->$numbercolumn eq '####' } @{ $self->controller->data } ];
|
||
|
||
map { $_->{object}->$numbercolumn('') } @{ $without_number };
|
||
|
||
$self->SUPER::save_objects(data => $with_number);
|
||
$self->SUPER::save_objects(data => $without_number);
|
||
}
|
||
|
||
1;
|
SL/DB/Customer.pm | ||
---|---|---|
my ($self) = @_;
|
||
|
||
$self->create_trans_number if $self->customernumber eq '';
|
||
return 1;
|
||
}
|
||
|
||
sub short_address {
|
SL/DB/Vendor.pm | ||
---|---|---|
my ($self) = @_;
|
||
|
||
$self->create_trans_number if $self->vendornumber eq '';
|
||
return 1;
|
||
}
|
||
|
||
1;
|
locale/de/all | ||
---|---|---|
'Ap aging on %s' => 'Offene Verbindlichkeiten zum %s',
|
||
'Application Error. No Format given' => 'Fehler in der Anwendung. Das Ausgabeformat fehlt.',
|
||
'Application Error. Wrong Format' => 'Fehler in der Anwendung. Falsches Format: ',
|
||
'Applying #1:' => 'Führe #1 aus:',
|
||
'Approximately #1 prices will be updated.' => 'Ungefähr #1 Preise werden aktualisiert.',
|
||
'Apply Filter' => 'Filtern',
|
||
'Apply to all parts' => 'Bei allen Artikeln setzen',
|
||
'Apply to parts without buchungsgruppe' => 'Bei allen Artikeln ohne gültige Buchungsgruppe setzen',
|
||
'Applying #1:' => 'Führe #1 aus:',
|
||
'Approximately #1 prices will be updated.' => 'Ungefähr #1 Preise werden aktualisiert.',
|
||
'Apr' => 'Apr',
|
||
'April' => 'April',
|
||
... | ... | |
'Birthday' => 'Geburtstag',
|
||
'Bis' => 'bis',
|
||
'Bis Konto: ' => 'bis Konto: ',
|
||
'Block' => 'Block',
|
||
'Body' => 'Text',
|
||
'Body:' => 'Text:',
|
||
'Books are open' => 'Die Bücher sind geöffnet.',
|
||
... | ... | |
'Chartaccounts connected to this Tax:' => 'Konten, die mit dieser Steuer verknüpft sind:',
|
||
'Check' => 'Scheck',
|
||
'Check Details' => 'Bitte Angaben überprüfen',
|
||
'Check the number format.' => 'Prüfen Sie das Format der Zahlen.',
|
||
'Check for duplicates' => 'Dublettencheck',
|
||
'Checks' => 'Schecks',
|
||
'Choose Customer' => 'Endkunde wählen:',
|
||
... | ... | |
'Close Window' => 'Fenster Schließen',
|
||
'Closed' => 'Geschlossen',
|
||
'Collective Orders only work for orders from one customer!' => 'Sammelaufträge funktionieren nur für Aufträge von einem Kunden!',
|
||
'Column' => 'Spalte',
|
||
'Column definitions can be found here:' => 'Die einzelnen Spaltendefinitionen sind hier verzeichnet:',
|
||
'Comma' => 'Komma',
|
||
'Comment' => 'Kommentar',
|
||
'Company' => 'Firma',
|
||
... | ... | |
'Delete delivery order' => 'Lieferschein löschen',
|
||
'Delete drafts' => 'Entwürfe löschen',
|
||
'Delete group' => 'Gruppe löschen',
|
||
'Delete transaction' => 'Buchung löschen',
|
||
'Delete profile' => 'Profil löschen',
|
||
'Delete transaction' => 'Buchung löschen',
|
||
'Delivered' => 'Geliefert',
|
||
'Delivery Date' => 'Lieferdatum',
|
||
'Delivery Order' => 'Lieferschein',
|
||
... | ... | |
'Dimension unit' => 'Maßeinheit',
|
||
'Directory' => 'Verzeichnis',
|
||
'Discard duplicate entries in CSV file' => 'Doppelte Einträge in CSV-Datei verwerfen',
|
||
'Discard entries with duplicates in database and CSV file' => 'Einträge aus CSV-Datei verwerfen, die es bereits in der Datenbank gibt',
|
||
'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',
|
||
'Discount' => 'Rabatt',
|
||
'Display' => 'Anzeigen',
|
||
'Display file' => 'Datei anzeigen',
|
||
'Display options' => 'Anzeigeoptionen',
|
||
'Do not check for duplicates' => 'Nicht nach Dubletten suchen',
|
||
'Do not set default buchungsgruppe' => 'Nie Standardbuchungsgruppe setzen',
|
||
'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.',
|
||
'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.',
|
||
'Do you really want to delete AP transaction #1?' => 'Wollen Sie wirklich die Kreditorenbuchung #1 löschen?',
|
||
... | ... | |
'Do you really want to delete GL transaction #1?' => 'Wollen Sie wirklich die Dialogbuchung #1 löschen?',
|
||
'Do you really want to delete this group?' => 'Gruppe wirklich löschen?',
|
||
'Do you really want to delete this object?' => 'Wollen Sie dieses Objekt wirklich löschen?',
|
||
'Do not check for duplicates' => 'Nicht nach Dubletten suchen',
|
||
'Do not set default buchungsgruppe' => 'Nie Standardbuchungsgruppe setzen',
|
||
'Do you really want to delete this record?' => 'Wollen Sie diesen Beleg wirklich löschen?',
|
||
'Do you really want to delete this warehouse?' => 'Wollen Sie dieses Lager wirklich löschen?',
|
||
'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?',
|
||
'Do you want to <b>limit</b> your search?' => 'Wollen Sie Ihre Suche <b>spezialisieren</b>?',
|
||
... | ... | |
'Dunning number' => 'Mahnungsnummer',
|
||
'Dunning overview' => 'Mahnungsübersicht',
|
||
'Dunnings' => 'Mahnungen',
|
||
'Duplicate' => 'Duplikat',
|
||
'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.',
|
||
'E-mail' => 'eMail',
|
||
'E-mail Statement to' => 'Fälligkeitsabrechnung als eMail an',
|
||
... | ... | |
'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.',
|
||
'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.',
|
||
'Error message from the database driver:' => 'Fehlermeldung des Datenbanktreibers:',
|
||
'Error when saving: #1' => 'Fehler beim Speichern: #2',
|
||
'Error!' => 'Fehler!',
|
||
'Error: Name missing' => 'Fehler: Name fehlt',
|
||
'Errors' => 'Fehler',
|
||
'Ertrag' => 'Ertrag',
|
||
'Ertrag prozentual' => 'Ertrag prozentual',
|
||
'Escape character' => 'Escape-Zeichen',
|
||
... | ... | |
'Foreign Revenues' => 'Erlöse Ausland',
|
||
'Form details (second row)' => 'Formulardetails (zweite Positionszeile)',
|
||
'Formula' => 'Formel',
|
||
'Found #1 errors.' => '#1 Fehler gefunden.',
|
||
'Found #1 objects to import.' => '#1 zu importierende Objekte gefunden.',
|
||
'Free report period' => 'Freier Zeitraum',
|
||
'Free-form text' => 'Textzeile',
|
||
'Fristsetzung' => 'Fristsetzung',
|
||
... | ... | |
'Given Name' => 'Vorname',
|
||
'Go one step back' => 'Einen Schritt zurück',
|
||
'Go one step forward' => 'Einen Schritt vorwärts',
|
||
'Gogogo' => '',
|
||
'Greeting' => 'Anrede',
|
||
'Greetings' => 'Anreden',
|
||
'Group' => 'Warengruppe',
|
||
... | ... | |
'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.',
|
||
'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.',
|
||
'Image' => 'Grafik',
|
||
'Import' => 'Import',
|
||
'Import CSV' => 'CSV-Import',
|
||
'Import Help' => 'Importhilfe',
|
||
'Import file' => 'Import-Datei',
|
||
'Import preview' => 'Import-Vorschau',
|
||
'Import profiles' => 'Import-Profil',
|
||
'Import result' => 'Import-Ergebnis',
|
||
'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.',
|
||
'In order to do that hit the button "Delete transaction".' => 'Drücken Sie dafür auf den Button "Buchung löschen".',
|
||
'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.',
|
||
... | ... | |
'Licenses' => 'Lizenzen',
|
||
'Limit part selection' => 'Artikelauswahl eingrenzen',
|
||
'Line Total' => 'Zeilensumme',
|
||
'Line and column' => 'Zeile und Spalte',
|
||
'Line endings' => 'Zeilenumbrüche',
|
||
'List' => 'Anzeigen',
|
||
'List Accounting Groups' => 'Buchungsgruppen anzeigen',
|
||
... | ... | |
'Part Notes' => 'Bemerkungen',
|
||
'Part Number' => 'Artikelnummer',
|
||
'Part Number missing!' => 'Artikelnummer fehlt!',
|
||
'Partnumber' => '',
|
||
'Partnumber must not be set to empty!' => 'Die Artikelnummer darf nicht auf leer geändert werden.',
|
||
'Partnumber not unique!' => 'Artikelnummer bereits vorhanden!',
|
||
'Parts' => 'Waren',
|
||
... | ... | |
'Please ask your administrator to create warehouses and bins.' => 'Bitten Sie Ihren Administrator, dass er Lager und Lagerplätze anlegt.',
|
||
'Please enter a license key.' => 'Bitte geben Sie einen Lizenzschlüssel an.',
|
||
'Please enter a number of licenses.' => 'Bitte geben Sie die Anzahl Lizenzschlüssel an.',
|
||
'Please enter the login for the new user.' => 'Bitte geben Sie das Login für den neuen Benutzer ein.',
|
||
'Please enter a profile name.' => 'Bitte geben Sie einen Profilnamen an.',
|
||
'Please enter the login for the new user.' => 'Bitte geben Sie das Login für den neuen Benutzer ein.',
|
||
'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:',
|
||
'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.',
|
||
'Please enter the sales tax identification number.' => 'Bitte geben Sie die Umsatzsteueridentifikationsnummer an.',
|
||
... | ... | |
'Selection' => 'Auswahlbox',
|
||
'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\'.',
|
||
'Sell Price' => 'Verkaufspreis',
|
||
'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.',
|
||
'Sellprice' => 'Verkaufspreis',
|
||
'Sellprice adjustment' => 'Verkaufspreis: Preisanpassung',
|
||
'Sellprice significant places' => 'Verkaufspreis: Nachkommastellen',
|
||
'Semicolon' => 'Semikolon',
|
||
'Send documents' => 'Dokumente verschicken',
|
||
'Send the backup via Email' => 'Die Sicherungsdatei per Email verschicken',
|
||
'Sep' => 'Sep',
|
||
'Separator' => 'Trennzeichen',
|
||
... | ... | |
'Services' => 'Dienstleistungen',
|
||
'Set Language Values' => 'Spracheinstellungen',
|
||
'Set eMail text' => 'eMail Text eingeben',
|
||
'Settings' => 'Einstellungen',
|
||
'Setup Menu' => 'Menü-Variante',
|
||
'Setup Templates' => 'Vorlagen auswählen',
|
||
'Settings' => 'Einstellungen',
|
||
'Ship to' => 'Lieferadresse',
|
||
'Ship via' => 'Transportmittel',
|
||
'Shipping Address' => 'Lieferadresse',
|
||
... | ... | |
'Show your TODO list after loggin in' => 'Aufgabenliste nach dem Anmelden anzeigen',
|
||
'Signature' => 'Unterschrift',
|
||
'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.',
|
||
'Skip' => 'Überspringen',
|
||
'Single quotes' => 'Einfache Anführungszeichen',
|
||
'Skip' => 'Überspringen',
|
||
'Skonto' => 'Skonto',
|
||
'Skonto Terms' => 'Zahlungsziel Skonto',
|
||
'Sold' => 'Verkauft',
|
||
... | ... | |
'Template database' => 'Datenbankvorlage',
|
||
'Templates' => 'Vorlagen',
|
||
'Terms missing in row ' => '+Tage fehlen in Zeile ',
|
||
'Test and preview' => 'Test und Vorschau',
|
||
'Test connection' => 'Verbindung testen',
|
||
'Text field' => 'Textfeld',
|
||
'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.',
|
||
... | ... | |
'Update prices of existing entries' => 'Preise von vorhandenen Artikeln aktualisieren',
|
||
'Update?' => 'Aktualisieren?',
|
||
'Updated' => 'Erneuert am',
|
||
'Use' => 'Verwendung',
|
||
'Uploaded on #1, size #2 kB' => 'Am #1 hochgeladen, Größe #2 kB',
|
||
'Use As Template' => 'Als Vorlage verwenden',
|
||
'Use Templates' => 'Benutze Vorlagen',
|
||
... | ... | |
'order' => 'Reihenfolge',
|
||
'our vendor number at customer' => 'Unsere Lieferanten-Nr. beim Kunden',
|
||
'part_list' => 'warenliste',
|
||
'pick_list' => 'Sammelliste',
|
||
'percental' => 'prozentual',
|
||
'pick_list' => 'Sammelliste',
|
||
'plural first char' => 'P',
|
||
'pos_bilanz' => 'Bilanz',
|
||
'pos_bwa' => 'BWA',
|
templates/webpages/csv_import/_data.html | ||
---|---|---|
[% USE LxERP %]
|
||
|
||
[%- IF SELF.errors %]
|
||
[%- PROCESS 'csv_import/_errors.html' %]
|
||
[%- END %]
|
||
|
||
[%- IF SELF.import_status == 'imported' %]
|
||
[%- PROCESS 'csv_import/_result.html' %]
|
||
[%- END %]
|
||
|
||
[%- PROCESS 'csv_import/_preview.html' %]
|
||
|
templates/webpages/csv_import/_errors.html | ||
---|---|---|
[% USE LxERP %]
|
||
|
||
<h3>[%- LxERP.t8('Errors') %]</h3>
|
||
|
||
<p>[%- LxERP.t8('Found #1 errors.', SELF.errors.size) %]</p>
|
||
|
||
<table>
|
||
<tr class="listheading">
|
||
<th>[%- LxERP.t8('Line and column') %]</th>
|
||
<th>[%- LxERP.t8('Block') %]</th>
|
||
<th>[%- LxERP.t8('Error') %]</th>
|
||
</tr>
|
||
[% FOREACH err = SELF.errors %]
|
||
<tr>
|
||
<td>[% err.4 %]:[% err.3 %]</td>
|
||
<td>[% err.0 %]</td>
|
||
<td>[% err.2 %]</td>
|
||
</tr>
|
||
[% END %]
|
||
</table>
|
||
[% END %]
|
templates/webpages/csv_import/_form_customers_vendors.html | ||
---|---|---|
[% USE LxERP %]
|
||
[% USE L %]
|
||
|
||
<tr>
|
||
<th align="right">[%- LxERP.t8('Target table') %]:</th>
|
||
<td colspan="10">
|
templates/webpages/csv_import/_form_parts.html | ||
---|---|---|
[% USE LxERP %]
|
||
[% USE L %]
|
||
<tr>
|
||
<th align="right">[%- LxERP.t8('Parts with existing part numbers') %]:</th>
|
||
<td colspan="10">
|
templates/webpages/csv_import/_preview.html | ||
---|---|---|
[% USE HTML %]
|
||
[% USE LxERP %]
|
||
|
||
<h3>
|
||
[%- IF SELF.import_status == 'tested' %]
|
||
[%- LxERP.t8('Import preview') %]
|
||
[%- ELSE %]
|
||
[%- LxERP.t8('Import result') %]
|
||
[%- END %]
|
||
</h3>
|
||
|
||
<p>[%- LxERP.t8('Found #1 objects to import.', SELF.data.size || 0) %]</p>
|
||
|
||
[% IF SELF.data.size %]
|
||
<table>
|
||
<tr class="listheading">
|
||
[%- FOREACH column = SELF.headers.headers %]
|
||
<th>[%- HTML.escape(column) %]</th>
|
||
[%- END %]
|
||
<th>[%- LxERP.t8('Notes') %]</th>
|
||
</tr>
|
||
|
||
[%- FOREACH row = SELF.data %]
|
||
<tr class="[% IF row.errors.size %]redrow[% ELSE %]listrow[% END %][% loop.count % 2 %]">
|
||
[%- FOREACH method = SELF.headers.methods %]
|
||
<td>[%- HTML.escape(row.object.$method) %]</td>
|
||
[%- END %]
|
||
<td>
|
||
[%- FOREACH error = row.errors %][%- HTML.escape(error) %][% UNLESS loop.last %]<br>[%- END %][%- END %]
|
||
</td>
|
||
</tr>
|
||
[%- END %]
|
||
|
||
</table>
|
||
[%- END %]
|
templates/webpages/csv_import/_result.html | ||
---|---|---|
[% USE LxERP %]
|
||
|
||
<p>[%- LxERP.t8('Found #1 objects to import.', SELF.data.size || 0) %]</p>
|
templates/webpages/csv_import/form.html | ||
---|---|---|
<tr>
|
||
<th align="right">[%- LxERP.t8('Check for duplicates') %]:</th>
|
||
<td colspan="10">
|
||
[% opts = [ [ 'no_check', LxERP.t8('Do not check for duplicates') ],
|
||
[% 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 and 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>
|
||
... | ... | |
|
||
</table>
|
||
|
||
[% L.submit_tag('action_test', LxERP.t8('Gogogo')) %]
|
||
[% L.submit_tag('action_test', LxERP.t8('Test and preview')) %]
|
||
[% IF SELF.import_status && SELF.data.size %]
|
||
[% L.submit_tag('action_import', LxERP.t8('Import')) %]
|
||
[%- END %]
|
||
|
||
</form>
|
||
|
||
[%- IF SELF.import_status %]
|
||
[%- PROCESS 'csv_import/_data.html' %]
|
||
[%- END %]
|
||
|
||
<script type="text/javascript">
|
||
<!--
|
||
$(document).ready(function() {
|
Auch abrufbar als: Unified diff
Kunden-/Lieferantenstammdatenimport: zumindest das Testen funktioniert