Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 4fd8bdbf

Von Moritz Bunkus vor etwa 18 Jahren hinzugefügt

  • ID 4fd8bdbfb46b8b63a7d05457959b98c4956d1dbd
  • Vorgänger 73fb84d7
  • Nachfolger 3c559a20

Neuer Datenbankupgrademechanismus: Die Upgradedateien im neuen Verzeichnis sql/Pg-upgrade2 enthalten Informationen über Abhängigkeiten, die von Lx-Office ausgewertet werden, um die Reihenfolge zu bestimmen, in der Updates angewandt werden. Wird nicht mehr über Versionsnummern geregelt.

Unterschiede anzeigen:

SL/DBUpgrade2.pm
package SL::DBUpgrade2;
require Exporter;
@ISA = qw(Exporter);
@EXPORT = qw(parse_dbupdate_controls sort_dbupdate_controls);
sub parse_dbupdate_controls {
$main::lxdebug->enter_sub();
my ($form, $dbdriver) = @_;
my $locale = $main::locale;
local *IN;
my %all_controls;
my $path = "sql/${dbdriver}-upgrade2";
foreach my $file_name (<$path/*.sql>, <$path/*.pl>) {
next unless (open(IN, $file_name));
my $file = $file_name;
$file =~ s|.*/||;
my $control = {
"priority" => 1000,
"depends" => [],
};
while (<IN>) {
chomp();
next unless (/^(--|\#)\s*\@/);
s/^(--|\#)\s*\@//;
s/\s*$//;
next if ($_ eq "");
my @fields = split(/\s*:\s*/, $_, 2);
next unless (scalar(@fields) == 2);
if ($fields[0] eq "depends") {
push(@{$control->{"depends"}}, split(/\s+/, $fields[1]));
} else {
$control->{$fields[0]} = $fields[1];
}
}
_control_error($form, $file_name,
$locale->text("Missing 'tag' field."))
unless ($control->{"tag"});
_control_error($form, $file_name,
$locale->text("The 'tag' field must only consist of " .
"alphanumeric characters or the carachters " .
"- _ ( )"))
if ($control->{"tag"} =~ /[^a-zA-Z0-9_\(\)\-]/);
_control_error($form, $file_name,
sprintf($locale->text("More than one control file " .
"with the tag '%s' exist."),
$control->{"tag"}))
if (defined($all_controls{$control->{"tag"}}));
_control_error($form, $file_name,
sprintf($locale->text("Missing 'description' field.")))
unless ($control->{"description"});
$control->{"priority"} *= 1;
$control->{"priority"} = 1000 unless ($control->{"priority"});
$control->{"file"} = $file;
map({ delete($control->{$_}); } qw(depth applied));
$all_controls{$control->{"tag"}} = $control;
close(IN);
}
foreach my $control (values(%all_controls)) {
foreach my $dependency (@{$control->{"depends"}}) {
_control_error($form, $control->{"file"},
sprintf($locale->text("Unknown dependency '%s'."),
$dependency))
if (!defined($all_controls{$dependency}));
}
map({ $_->{"loop"} = 0; } values(%all_controls));
_check_for_loops($form, $control->{"file"}, \%all_controls,
$control->{"tag"});
}
map({ _dbupdate2_calculate_depth(\%all_controls, $_->{"tag"}) }
values(%all_controls));
$main::lxdebug->leave_sub();
return \%all_controls;
}
sub _check_for_loops {
my ($form, $file_name, $controls, $tag, @path) = @_;
push(@path, $tag);
_control_error($form, $file_name,
$main::locale->text("Dependency loop detected:") .
" " . join(" -> ", @path))
if ($controls->{$tag}->{"loop"});
$controls->{$tag}->{"loop"} = 1;
map({ _check_for_loops($form, $file_name, $controls, $_, @path); }
@{$controls->{$tag}->{"depends"}});
}
sub _control_error {
my ($form, $file_name, $message) = @_;
my $form = $main::form;
my $locale = $main::locale;
$form->error(sprintf($locale->text("Error in database control file '%s': %s"),
$file_name, $message));
}
sub _dbupdate2_calculate_depth {
$main::lxdebug->enter_sub();
my ($tree, $tag) = @_;
my $node = $tree->{$tag};
return $main::lxdebug->leave_sub() if (defined($node->{"depth"}));
my $max_depth = 0;
foreach $tag (@{$node->{"depends"}}) {
_dbupdate2_calculate_depth($tree, $tag);
my $value = $tree->{$tag}->{"depth"};
$max_depth = $value if ($value > $max_depth);
}
$node->{"depth"} = $max_depth + 1;
$main::lxdebug->leave_sub();
}
sub sort_dbupdate_controls {
return
sort({ $a->{"depth"} != $b->{"depth"} ? $a->{"depth"} <=> $b->{"depth"} :
$a->{"priority"} != $b->{"priority"} ?
$a->{"priority"} <=> $b->{"priority"} :
$a->{"tag"} cmp $b->{"tag"} } values(%{$_[0]}));
}
1;
SL/User.pm
package User;
use SL::DBUpgrade2;
sub new {
$main::lxdebug->enter_sub();
......
'$myconfig{tel}', 'user')|;
$dbh->do($query);
}
$self->create_schema_info_table($form, $dbh);
$dbh->disconnect;
$rc = 0;
if (&update_available($myconfig{"dbdriver"}, $dbversion)) {
my $controls =
parse_dbupdate_controls($form, $myconfig{"dbdriver"});
map { $form->{$_} = $myconfig{$_} }
qw(dbname dbhost dbport dbdriver dbuser dbpasswd dbconnect);
map({ $form->{$_} = $myconfig{$_} }
qw(dbname dbhost dbport dbdriver dbuser dbpasswd dbconnect));
if (update_available($myconfig{"dbdriver"}, $dbversion) ||
update2_available($form, $controls)) {
$form->{"stylesheet"} = "lx-office-erp.css";
$form->{"title"} = $main::locale->text("Dataset upgrade");
......
}
# update the tables
open FH, ">$userspath/nologin" or die "
$!";
open(FH, ">$userspath/nologin") or die("$!");
# required for Oracle
$form->{dbdefault} = $sid;
......
$SIG{QUIT} = 'IGNORE';
$self->dbupdate($form);
$self->dbupdate2($form, $controls);
# remove lock file
unlink "$userspath/nologin";
unlink("$userspath/nologin");
print($form->parse_html_template("dbupgrade/footer"));
......
sub process_query {
$main::lxdebug->enter_sub();
my ($self, $form, $dbh, $filename, $version) = @_;
my ($self, $form, $dbh, $filename, $version_or_control) = @_;
# return unless (-f $filename);
......
}
}
if ($version) {
if (ref($version_or_control) eq "HASH") {
$dbh->do("INSERT INTO schema_info (tag, login) VALUES (" .
$dbh->quote($version_or_control->{"tag"}) . ", " .
$dbh->quote($form->{"login"}) . ")");
} elsif ($version_or_control) {
$dbh->do("UPDATE defaults SET version = " . $dbh->quote($version));
}
$dbh->commit();
......
return ($#upgradescripts > -1);
}
sub create_schema_info_table {
$main::lxdebug->enter_sub();
my ($self, $form, $dbh) = @_;
my $query = "SELECT tag FROM schema_info LIMIT 1";
if (!$dbh->do($query)) {
$query =
"CREATE TABLE schema_info (" .
" tag text, " .
" login text, " .
" itime timestamp DEFAULT now(), " .
" PRIMARY KEY (tag))";
$dbh->do($query) || $form->dberror($query);
}
$main::lxdebug->leave_sub();
}
sub dbupdate {
$main::lxdebug->enter_sub();
......
last if ($version < $mindb);
# apply upgrade
$main::lxdebug->message(DEBUG2, "Appliying Update $upgradescript");
$main::lxdebug->message(DEBUG2, "Applying Update $upgradescript");
if ($file_type eq "sql") {
$self->process_query($form, $dbh, "sql/" . $form->{"dbdriver"} . "-upgrade/$upgradescript", $str_maxdb);
} else {
......
return $rc;
}
sub dbupdate2 {
$main::lxdebug->enter_sub();
my ($self, $form, $controls) = @_;
$form->{sid} = $form->{dbdefault};
my @upgradescripts = ();
my ($query, $sth, $tag);
my $rc = -2;
@upgradescripts = sort_dbupdate_controls($controls);
foreach my $db (split / /, $form->{dbupdate}) {
next unless $form->{$db};
# strip db from dataset
$db =~ s/^db//;
&dbconnect_vars($form, $db);
my $dbh =
DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd})
or $form->dberror;
map({ $_->{"applied"} = 0; } @upgradescripts);
$query = "SELECT tag FROM schema_info";
$sth = $dbh->prepare($query);
$sth->execute() || $form->dberror($query);
while (($tag) = $sth->fetchrow_array()) {
$controls->{$tag}->{"applied"} = 1 if (defined($controls->{$tag}));
}
$sth->finish();
my $all_applied = 1;
foreach (@upgradescripts) {
if (!$_->{"applied"}) {
$all_applied = 0;
last;
}
}
next if ($all_applied);
foreach my $control (@upgradescripts) {
next if ($control->{"applied"});
$control->{"file"} =~ /\.(sql|pl)$/;
my $file_type = $1;
# apply upgrade
$main::lxdebug->message(DEBUG2, "Applying Update $control->{file}");
print($form->parse_html_template("dbupgrade/upgrade_message2",
$control));
if ($file_type eq "sql") {
$self->process_query($form, $dbh, "sql/" . $form->{"dbdriver"} .
"-upgrade2/$control->{file}", $control);
} else {
$self->process_perl_script($form, $dbh, "sql/" . $form->{"dbdriver"} .
"-upgrade2/$control->{file}", $control);
}
}
$rc = 0;
$dbh->disconnect;
}
$main::lxdebug->leave_sub();
return $rc;
}
sub update2_available {
$main::lxdebug->enter_sub();
my ($form, $controls) = @_;
map({ $_->{"applied"} = 0; } values(%{$controls}));
dbconnect_vars($form, $form->{"dbname"});
my $dbh =
DBI->connect($form->{dbconnect}, $form->{dbuser}, $form->{dbpasswd}) ||
$form->dberror;
my ($query, $tag, $sth);
$query = "SELECT tag FROM schema_info";
$sth = $dbh->prepare($query);
$sth->execute() || $form->dberror($query);
while (($tag) = $sth->fetchrow_array()) {
$controls->{$tag}->{"applied"} = 1 if (defined($controls->{$tag}));
}
$sth->finish();
$dbh->disconnect();
map({ $main::lxdebug->leave_sub() and return 1 if (!$_->{"applied"}) }
values(%{$controls}));
$main::lxdebug->leave_sub();
return 0;
}
sub create_config {
$main::lxdebug->enter_sub();
doc/sql-upgrade-dateien.txt
Neuer Mechanismus f?r SQL-Upgradedateien
----------------------------------------
Der alte Mechanismus f?r SQL-Upgradescripte, der auf einer
Versionsnummer beruht und dann in sql/Pg-upgrade nach einem Script f?r
diese Versionsnummer sucht, schr?nkt sehr ein, z.B. was die parallele
Entwicklung im stable- und unstable-Baum betrifft.
Dieser Mechanismus wurde f?r Lx-Office 2.4.1 deutlich erweitert. Es
werden weiterhin alle Scripte aus sql/Pg-upgrade
ausgef?hrt. Zus?tzlich gibt es aber ein zweites Verzeichnis,
sql/Pg-upgrade2. In diesem Verzeichnis muss pro Datenbankupgrade eine
Datei existieren, die neben den eigentlich auszuf?hrenden SQL- oder
Perl-Befehlen einige Kontrollinformationen enth?lt.
Neu sind die Kontrollinformationen, die Abh?ngigkeiten und Priorit?ten
definieren k?nnen werden, sodass Datenbankscripte zwar in einer
sicheren Reihenfolge ausgef?hrt werden (z.B. darf ein "ALTER TABLE"
erst ausgef?hrt werden, wenn die Tabelle mit "CREATE TABLE" angelegt
wurde), diese Reihenfolge aber so flexibel ist, dass man keine
Versionsnummern mehr braucht.
Lx-Office merkt sich dabei, welches der Upgradescripte in
sql/Pg-upgrade2 bereits durchgef?hrt wurde und f?hrt diese nicht
erneut aus. Dazu dient die Tabelle "schema_info", die bei der
Anmeldung automatisch angelegt wird.
Format der Kontrollinformationen
--------------------------------
Die Kontrollinformationen sollten sich am Anfang der jeweiligen
Upgradedatei befinden. Jede Zeile, die Kontrollinformationen enth?lt,
hat dabei das folgende Format:
F?r SQL-Upgradedateien:
-- @key: value
F?r Perl-Upgradedateien:
# @key: value
Leerzeichen vor "value" werden entfern.
Die folgenden Schl?sselworte werden verarbeitet:
* tag: Wird zwingend ben?tigt. Dies ist der "Name" des
Upgrades. Dieser "tag" kann von anderen Kontrolldateien in ihren
Abh?ngigkeiten verwendet werden (Schl?sselwort "depends"). Der "tag"
ist auch der Name, der in der Datenbank eingetragen wird.
Normalerweise sollte die Kontrolldatei genau so hei?en wie der
"tag", nur mit der Endung ".sql" bzw. "pl".
Ein Tag darf nur aus alphanumerischen Zeichen sowie den Zeichen _ -
( ) bestehen. Insbesondere sind Leerzeichen nicht erlaubt und
sollten stattdessen mit Unterstrichen ersetzt werden.
* description: Ben?tigt. Eine Beschreibung, was in diesem Update
passiert. Diese wird dem Benutzer beim eigentlichen Datenbankupdate
angezeigt. W?hrend der Tag in englisch gehalten sein sollte, sollte
die Beschreibung auf Deutsch erfolgen.
* depends: Optional. Eine mit Leerzeichen getrennte Liste von "tags",
von denen dieses Upgradescript abh?ngt. Lx-Office stellt sicher,
dass die in dieser Liste aufgef?hrten Scripte bereits durchgef?hrt
wurden, bevor dieses Script ausgef?hrt wird.
Abh?ngigkeiten werden rekursiv betrachtet. Wenn also ein Script "b"
existiert, das von ?nderungen in "a" abh?ngt, und eine neue
Kontrolldatei f?r "c" erstellt wird, die von ?nderungen in "a" und
"b" abh?ngt, so gen?gt es, in "c" nur den Tag "b" als Abh?ngigkeit
zu definieren.
Es ist nicht erlaubt, sich selbst referenzierende Abh?ngigkeiten zu
definieren (z.B. "a" -> "b", "b" -> "c" und "c" -> "a").
* priority: Optional. Ein Zahlenwert, der die Reihenfolge bestimmt, in
der Scripte ausgef?hrt werden, die die gleichen Abh?ngigkeitstiefen
besitzen. Fehlt dieser Parameter, so wird der Wert 1000 benutzt.
Dies ist reine Kosmetik. F?r echte Reihenfolgen muss "depends"
benutzt werden. Lx-Office sortiert die auszuf?hrenden Scripte zuerst
nach der Abh?ngigkeitstiefe (wenn "z" von "y" abh?ngt und "y" von
"x", so hat "z" eine Abh?ngigkeitstiefe von 2, "y" von 1 und "x" von
0. "x" w?rde hier zuerst ausgef?hrt, dann "y", dann "z"), dann nach
der Priorit?t und bei gleicher Priorit?t alphabetisch nach dem
"tag".
Hilfsscript dbupgrade2_tool.pl
------------------------------
Um die Arbeit mit den Abh?ngigkeiten etwas zu erleichtern, existiert
ein Hilfsscript namens "scripts/dbupgrade2_tool.pl". Es muss aus dem
Lx-Office-ERP-Basisverzeichnis heraus aufgerufen werden. Dieses Tool
liest alle Datenbankupgradescripte aus dem Verzeichnis sql/Pg-upgrade2
aus. Es benutzt daf?r die gleichen Methoden wie Lx-Office selber,
sodass alle Fehlersituationen von der Kommandozeile ?berpr?ft werden
k?nnen.
Wird dem Script kein weiterer Parameter ?bergeben, so wird nur eine
?berpr?fung der Felder und Abh?ngigkeiten vorgenommen. Man kann sich
aber auch Informationen auf verschiedene Art ausgeben lassen:
1. Listenform: "./scripts/dbupgrade2_tool.pl --list"
Gibt eine Liste aller Scripte aus. Die Liste ist in der Reihenfolge
sortiert, in der Lx-Office die Scripte ausf?hren w?rde. Es werden
neben der Listenposition der Tag, die Abh?ngigkeitstiefe und die
Priorit?t ausgegeben.
2. Baumform: "./scripts/dbupgrade2_tool.pl --tree"
Listet alle Tags in Baumform basierend auf den Abh?ngigkeiten
auf. Die "Wurzelknoten" sind dabei die Scripte, von denen keine
anderen abh?ngen. Die Unterknoten sind Scripte, die beim
?bergeordneten Script als Abh?ngigkeit eingetragen sind.
3. Umgekehrte Baumform: "./scripts/dbupgrade2_tool.pl --rtree"
Listet alle Tags in Baumform basierend auf den Abh?ngigkeiten auf.
Die "Wurzelknoten" sind dabei die Scripte mit der geringsten
Abh?ngigkeitstiefe. Die Unterknoten sind Scripte, die das
?bergeordnete Script als Abh?ngigkeit eingetragen haben.
4. Baumform mit Postscriptausgabe: "./scripts/dbupgrade2_tool.pl --graphviz"
Ben?tigt das Tool "graphviz", um mit seiner Hilfe die Baumform aus
3. in eine Postscriptdatei namens "db_dependencies.ps"
auszugeben. Dies ist vermutlich die ?bersichtlichste Form, weil
hierbei jeder Knoten nur einmal ausgegeben wird. Bei den
Textmodusbaumformen hingegen k?nnen Knoten und all ihre
Abh?ngigkeiten mehrfach ausgegeben werden.
5. Scripte, von denen kein anderes Script abh?ngt:
"./scripts/dbupgrade2_tool.pl --nodeps"
Listet die Tags aller Scripte auf, von denen keine anderen Scripte
abh?ngen.
locale/de/admin
'Date Format' => 'Datumsformat',
'Delete' => 'L?schen',
'Delete Dataset' => 'Datenbank l?schen',
'Dependency loop detected:' => 'Schleife in den Abh&auml;ngigkeiten entdeckt:',
'Directory' => 'Verzeichnis',
'Driver' => 'Treiber',
'Dropdown Limit' => 'Auswahllistenbegrenzung',
'E-mail' => 'eMail',
'Edit User' => 'Benutzerdaten bearbeiten',
'Error in database control file \'%s\': %s' => 'Fehler in Datenbankupgradekontrolldatei \'%s\': %s',
'Existing Datasets' => 'existierende Datenbanken',
'Fax' => 'Fax',
'File locked!' => 'Datei gesperrt!',
......
'Login' => 'Anmeldung',
'Login name missing!' => 'Loginname fehlt.',
'Manager' => 'Manager',
'Missing \'description\' field.' => 'Fehlendes Feld \'description\'.',
'Missing \'tag\' field.' => 'Fehlendes Feld \'tag\'.',
'More than one control file with the tag \'%s\' exist.' => 'Es gibt mehr als eine Kontrolldatei mit dem Tag \'%s\'.',
'Multibyte Encoding' => 'Schriftsatz',
'Name' => 'Name',
'New Templates' => 'neue Vorlagen',
......
'Stylesheet' => 'Stilvorlage',
'Supervisor' => 'Supervisor',
'Templates' => 'Vorlagen',
'The \'tag\' field must only consist of alphanumeric characters or the carachters - _ ( )' => 'Das Feld \'tag\' darf nur aus alphanumerischen Zeichen und den Zeichen - _ ( ) bestehen.',
'The following Datasets are not in use and can be deleted' => 'Die folgenden Datenbanken sind nicht in Verwendung und k?nnen gel?scht werden',
'The following Datasets need to be updated' => 'Folgende Datenbanken m?ssen aktualisiert werden',
'The passwords do not match.' => 'Die Passw&ouml;rter stimmen nicht &uuml;berein.',
'This is a preliminary check for existing sources. Nothing will be created or deleted at this stage!' => 'In diesem Schritt werden bestehende Datenbanken gesucht. Es werden noch keine ?nderungen vorgenommen!',
'To add a user to a group edit a name, change the login name and save. A new user with the same variables will then be saved under the new login name.' => 'Um einer Gruppe einen neuen Benutzer hinzuzuf?gen, ?ndern und speichern Sie am einfachsten einen bestehen den Zugriffsnamen. Unter dem neuen Namen wird dann ein Benutzer mit denselben Einstellungen angelegt.',
'Unknown dependency \'%s\'.' => 'Unbekannte Abh&auml;ngigkeit \'%s\'.',
'Unlock System' => 'System entsperren',
'Update Dataset' => 'Datenbank aktualisieren',
'Use Templates' => 'benutze Vorlagen',
locale/de/all
'Ansprechpartner' => '',
'Application Error. No Format given!' => 'Fehler in der Anwendung. Das Format fehlt.',
'Application Error. Wrong Format: ' => 'Fehler in der Anwendung. Falsches Format: ',
'Applying <TMPL_VAR file ESCAPE=HTML>:' => 'F&uuml;hre <TMPL_VAR file ESCAPE=HTML> aus:',
'Apr' => 'Apr',
'April' => 'April',
'Are you sure you want to delete Invoice Number' => 'Soll die Rechnung mit folgender Nummer wirklich gel?scht werden:',
......
'Department deleted!' => 'Abteilung gel?scht.',
'Department saved!' => 'Abteilung gespeichert.',
'Departments' => 'Abteilungen',
'Dependency loop detected:' => 'Schleife in den Abh&auml;ngigkeiten entdeckt:',
'Deposit' => 'Gutschrift',
'Description' => 'Beschreibung',
'Description missing!' => 'Beschreibung fehlt.',
......
'Erl?se EU o. UStId' => 'Erl&ouml;se EU o. UStId',
'Erl?se Inland' => 'Erl&ouml;se Inland',
'Error' => 'Fehler',
'Error in database control file \'%s\': %s' => 'Fehler in Datenbankupgradekontrolldatei \'%s\': %s',
'Error!' => 'Fehler!',
'Exch' => 'Wechselkurs.',
'Exchangerate' => 'Wechselkurs',
......
'Method' => 'Verfahren',
'Microfiche' => 'Mikrofilm',
'Minimum Amount' => 'Mindestbetrag',
'Missing \'description\' field.' => 'Fehlendes Feld \'description\'.',
'Missing \'tag\' field.' => 'Fehlendes Feld \'tag\'.',
'Missing Method!' => 'Fehlender Voranmeldungszeitraum',
'Missing Preferences: Outputroutine disabled' => 'Die Ausgabefunktionen sind wegen unzureichender Voreinstellungen deaktiviert!',
'Missing Tax Authoritys Preferences' => 'Fehlende Angaben zum Finanzamt!',
......
'Model' => 'Modell',
'Monat' => 'Monat',
'Monthly' => 'monatlich',
'More than one control file with the tag \'%s\' exist.' => 'Es gibt mehr als eine Kontrolldatei mit dem Tag \'%s\'.',
'Multibyte Encoding' => 'Schriftsatz',
'MwSt. inkl.' => 'MwSt. inkl.',
'N/A' => 'N.Z.',
......
'Templates' => 'Vorlagen',
'Terms missing in row ' => '+Tage fehlen in Zeile ',
'Terms: Net' => 'Zahlungsziel',
'The \'tag\' field must only consist of alphanumeric characters or the carachters - _ ( )' => 'Das Feld \'tag\' darf nur aus alphanumerischen Zeichen und den Zeichen - _ ( ) bestehen.',
'The base unit does not exist or it is about to be deleted in row %d.' => 'Die Basiseinheit in Zeile %d existiert nicht oder soll gel&ouml;scht werden.',
'The base unit does not exist.' => 'Die Basiseinheit existiert nicht.',
'The base unit relations must not contain loops (e.g. by saying that unit A\'s base unit is B, B\'s base unit is C and C\'s base unit is A) in row %d.' => 'Die Beziehungen der Einheiten d&uuml;rfen keine Schleifen beinhalten (z.B. wenn gesagt wird, dass Einheit As Basiseinheit B, Bs Basiseinheit C und Cs Basiseinheit A ist) in Zeile %d.',
......
'Unit' => 'Einheit',
'Unit of measure' => 'Ma?einheit',
'Units' => 'Einheiten',
'Unknown dependency \'%s\'.' => 'Unbekannte Abh&auml;ngigkeit \'%s\'.',
'Unlock System' => 'System entsperren',
'Until' => 'Bis',
'Update' => 'Erneuern',
locale/de/am
'Department deleted!' => 'Abteilung gel?scht.',
'Department saved!' => 'Abteilung gespeichert.',
'Departments' => 'Abteilungen',
'Dependency loop detected:' => 'Schleife in den Abh&auml;ngigkeiten entdeckt:',
'Description' => 'Beschreibung',
'Description missing!' => 'Beschreibung fehlt.',
'Discount' => 'Rabatt',
......
'Erl?se EU m. UStId' => 'Erl&ouml;se EU m. UStId',
'Erl?se EU o. UStId' => 'Erl&ouml;se EU o. UStId',
'Erl?se Inland' => 'Erl&ouml;se Inland',
'Error in database control file \'%s\': %s' => 'Fehler in Datenbankupgradekontrolldatei \'%s\': %s',
'Expense' => 'Aufwandskonto',
'Expense Account' => 'Aufwandskonto',
'Expense/Asset' => 'Aufwand/Anlagen',
......
'Link' => 'Verkn?pfungen',
'Long Dates' => 'Lange Monatsnamen',
'Long Description' => 'Langtext',
'Missing \'description\' field.' => 'Fehlendes Feld \'description\'.',
'Missing \'tag\' field.' => 'Fehlendes Feld \'tag\'.',
'More than one control file with the tag \'%s\' exist.' => 'Es gibt mehr als eine Kontrolldatei mit dem Tag \'%s\'.',
'Name' => 'Name',
'Netto Terms' => 'Zahlungsziel netto',
'No' => 'Nein',
......
'Template Code' => 'Vorlagenk?rzel',
'Template Code missing!' => 'Vorlagenk?rzel fehlt!',
'Template saved!' => 'Schablone gespeichert!',
'The \'tag\' field must only consist of alphanumeric characters or the carachters - _ ( )' => 'Das Feld \'tag\' darf nur aus alphanumerischen Zeichen und den Zeichen - _ ( ) bestehen.',
'The base unit does not exist or it is about to be deleted in row %d.' => 'Die Basiseinheit in Zeile %d existiert nicht oder soll gel&ouml;scht werden.',
'The base unit does not exist.' => 'Die Basiseinheit existiert nicht.',
'The base unit relations must not contain loops (e.g. by saying that unit A\'s base unit is B, B\'s base unit is C and C\'s base unit is A) in row %d.' => 'Die Beziehungen der Einheiten d&uuml;rfen keine Schleifen beinhalten (z.B. wenn gesagt wird, dass Einheit As Basiseinheit B, Bs Basiseinheit C und Cs Basiseinheit A ist) in Zeile %d.',
......
'UStVA-Nr. 98' => 'Kz. 98',
'Umsatzsteuervoranmeldung' => 'Umsatzsteuervoranmeldung',
'Unit' => 'Einheit',
'Unknown dependency \'%s\'.' => 'Unbekannte Abh&auml;ngigkeit \'%s\'.',
'Value' => 'Wert',
'Variable' => 'Variable',
'Warehouse deleted!' => 'Das Lager wurde gel?scht.',
locale/de/locales.pl
$basedir = "../..";
$bindir = "$basedir/bin/mozilla";
$dbupdir = "$basedir/sql/Pg-upgrade";
$dbupdir2 = "$basedir/sql/Pg-upgrade2";
$menufile = "menu.ini";
$submitsearch = qr/type\s*=\s*[\"\']?submit/i;
......
@dbplfiles = grep { /\.pl$/ } readdir DIR;
closedir DIR;
opendir DIR, $dbupdir2 or die "$!";
@dbplfiles2 = grep { /\.pl$/ } readdir DIR;
closedir DIR;
# slurp the translations in
if (-f 'all') {
require "all";
......
map({ handle_file($_, $bindir); } @progfiles);
map({ handle_file($_, $dbupdir); } @dbplfiles);
map({ handle_file($_, $dbupdir2); } @dbplfiles2);
sub handle_file {
my ($file, $dir) = @_;
locale/de/login
'Database Host' => 'Datenbankcomputer',
'Dataset' => 'Datenbank',
'Dataset upgrade' => 'Datenbankaktualisierung',
'Dependency loop detected:' => 'Schleife in den Abh&auml;ngigkeiten entdeckt:',
'Error in database control file \'%s\': %s' => 'Fehler in Datenbankupgradekontrolldatei \'%s\': %s',
'Incorrect username or password!' => 'Ung?ltiger Benutzername oder falsches Passwort!',
'Licensed to' => 'Lizensiert f?r',
'Login' => 'Anmeldung',
'Login Name' => 'Benutzername',
'Missing \'description\' field.' => 'Fehlendes Feld \'description\'.',
'Missing \'tag\' field.' => 'Fehlendes Feld \'tag\'.',
'More than one control file with the tag \'%s\' exist.' => 'Es gibt mehr als eine Kontrolldatei mit dem Tag \'%s\'.',
'Password' => 'Passwort',
'The \'tag\' field must only consist of alphanumeric characters or the carachters - _ ( )' => 'Das Feld \'tag\' darf nur aus alphanumerischen Zeichen und den Zeichen - _ ( ) bestehen.',
'Unknown dependency \'%s\'.' => 'Unbekannte Abh&auml;ngigkeit \'%s\'.',
'User' => 'Benutzer',
'Version' => 'Version',
'You are logged out!' => 'Auf Wiedersehen!',
locale/de/ustva
'Dauerfristverl?ngerung' => 'Dauerfristverl?ngerung',
'Dec' => 'Dez',
'December' => 'Dezember',
'Dependency loop detected:' => 'Schleife in den Abh&auml;ngigkeiten entdeckt:',
'Description' => 'Beschreibung',
'ELSTER Export nach Taxbird' => 'ELSTER-Export nach Taxbird',
'ELSTER Export nach Winston' => 'ELSTER Export nach Winston',
'ELSTER-Steuernummer: ' => 'ELSTER-Steuernummer: ',
'Error in database control file \'%s\': %s' => 'Fehler in Datenbankupgradekontrolldatei \'%s\': %s',
'Fax' => 'Fax',
'Fax. : ' => 'Fax. : ',
'Fax.: ' => 'Fax.: ',
......
'May' => 'Mai',
'May ' => 'Mai',
'Method' => 'Verfahren',
'Missing \'description\' field.' => 'Fehlendes Feld \'description\'.',
'Missing \'tag\' field.' => 'Fehlendes Feld \'tag\'.',
'Missing Method!' => 'Fehlender Voranmeldungszeitraum',
'Missing Preferences: Outputroutine disabled' => 'Die Ausgabefunktionen sind wegen unzureichender Voreinstellungen deaktiviert!',
'Missing Tax Authoritys Preferences' => 'Fehlende Angaben zum Finanzamt!',
'More than one control file with the tag \'%s\' exist.' => 'Es gibt mehr als eine Kontrolldatei mit dem Tag \'%s\'.',
'Name' => 'Name',
'Nov' => 'Nov',
'November' => 'November',
......
'Tel. : ' => 'Tel. : ',
'Tel.: ' => 'Tel.: ',
'Telefon' => 'Telefon',
'The \'tag\' field must only consist of alphanumeric characters or the carachters - _ ( )' => 'Das Feld \'tag\' darf nur aus alphanumerischen Zeichen und den Zeichen - _ ( ) bestehen.',
'USTVA-Hint: Method' => 'Wenn Sie Ist-Versteuert sind, w?hlen Sie die Einnahmen-/?berschu?-Rechnung aus. Sind Sie Soll-Versteuert und bilanzverpflichtet, dann w?hlen Sie Bilanz aus.',
'USTVA-Hint: Tax Authoritys' => 'Bitte das Bundesland UND die Stadt bzw. den Einzugsbereich Ihres zust?ndigen Finanzamts ausw?hlen.',
'UStVA' => 'UStVA',
'UStVA als PDF-Dokument' => 'UStVa als PDF-Dokument',
'Unknown dependency \'%s\'.' => 'Unbekannte Abh&auml;ngigkeit \'%s\'.',
'Vendor not on file!' => 'Lieferant ist nicht in der Datenbank!',
'Verfahren' => 'Verfahren',
'Verrechnung des Erstattungsbetrages erw?nscht (Zeile 71)' => 'Verrechnung des Erstattungsbetrages erw?nscht (Zeile 71)',
scripts/dbupgrade2_tool.pl
#!/usr/bin/perl
BEGIN {
if (! -d "bin" || ! -d "SL") {
print("This tool must be run from the Lx-Office ERP base directory.\n");
exit(1);
}
}
use DBI;
use Data::Dumper;
use Getopt::Long;
use SL::LXDebug;
$lxdebug = LXDebug->new();
use SL::Form;
use SL::DBUpgrade2;
#######
#######
#######
sub show_help {
print("dbupgrade2_tool.pl [--list] [--tree] [--rtree] [--graphviz]\n" .
" [--nodepds] [--help]\n");
}
sub calc_rev_depends {
map({ $_->{"rev_depends"} = []; } values(%{$controls}));
foreach my $control (values(%{$controls})) {
map({ push(@{$controls->{$_}{"rev_depends"}}, $control->{"tag"}) }
@{$control->{"depends"}});
}
}
sub dump_list {
my @sorted_controls = sort_dbupdate_controls($controls);
print("LIST VIEW\n\n");
print("number tag depth priority\n");
$i = 0;
foreach (@sorted_controls) {
print("$i $_->{tag} $_->{depth} $_->{priority}\n");
$i++;
}
print("\n");
}
sub dump_node {
my ($tag, $depth) = @_;
print(" " x $depth . $tag . "\n");
my $c = $controls->{$tag};
my $num = scalar(@{$c->{"depends"}});
for (my $i = 0; $i < $num; $i++) {
dump_node($c->{"depends"}[$i], $depth + 1);
}
}
sub dump_tree {
print("TREE VIEW\n\n");
calc_rev_depends();
my @sorted_controls = sort_dbupdate_controls($controls);
foreach my $control (@sorted_controls) {
dump_node($control->{"tag"}, "") unless (@{$control->{"rev_depends"}});
}
print("\n");
}
sub dump_node_reverse {
my ($tag, $depth) = @_;
print(" " x $depth . $tag . "\n");
my $c = $controls->{$tag};
my $num = scalar(@{$c->{"rev_depends"}});
for (my $i = 0; $i < $num; $i++) {
dump_node_reverse($c->{"rev_depends"}[$i], $depth + 1);
}
}
sub dump_tree_reverse {
print("REVERSE TREE VIEW\n\n");
calc_rev_depends();
my @sorted_controls = sort_dbupdate_controls($controls);
foreach my $control (@sorted_controls) {
last if ($control->{"depth"} > 1);
dump_node_reverse($control->{"tag"}, "");
}
print("\n");
}
sub dump_graphviz {
print("GRAPHVIZ POSTCRIPT\n\n");
print("Output will be written to db_dependencies.ps\n");
$dot = "|dot -Tps ";
open(OUT, "${dot}> db_dependencies.ps");
print(OUT
"digraph db_dependencies {\n" .
"node [shape=box];\n");
my %ranks;
foreach my $c (values(%{$controls})) {
$ranks{$c->{"depth"}} = [] unless ($ranks{$c->{"depth"}});
push(@{$ranks{$c->{"depth"}}}, $c->{"tag"});
}
foreach (sort(keys(%ranks))) {
print(OUT "{ rank = same; " .
join("", map({ '"' . $_ . '"; ' } @{$ranks{$_}})) .
" }\n");
}
foreach my $c (values(%{$controls})) {
print(OUT "$c->{tag};\n");
foreach my $d (@{$c->{"depends"}}) {
print(OUT "$c->{tag} -> $d;\n");
}
}
print(OUT "}\n");
close(OUT);
}
sub dump_nodeps {
calc_rev_depends();
print("SCRIPTS NO OTHER SCRIPTS DEPEND ON\n\n" .
join("\n",
map({ $_->{"tag"} }
grep({ !@{$_->{"rev_depends"}} }
values(%{$controls})))) .
"\n\n");
}
#######
#######
#######
eval { require "lx-erp.conf"; };
$form = Form->new();
$locale = Locale->new("de", "login");
#######
#######
#######
my ($opt_list, $opt_tree, $opt_rtree, $opt_nodeps, $opt_graphviz, $opt_help);
GetOptions("list" => \$opt_list,
"tree" => \$opt_tree,
"rtree" => \$opt_rtree,
"nodeps" => \$opt_nodeps,
"graphviz" => \$opt_graphviz,
"help" => \$opt_help,
);
if ($opt_help) {
show_help();
exit(0);
}
$controls = parse_dbupdate_controls($form, "Pg");
if ($opt_list) {
dump_list();
}
if ($opt_tree) {
dump_tree();
}
if ($opt_rtree) {
dump_tree_reverse();
}
if ($opt_graphviz) {
dump_graphviz();
}
if ($opt_nodeps) {
dump_nodeps();
}
sql/Pg-upgrade/Pg-upgrade-2.4.0.0-2.4.0.1.sql
ALTER TABLE language ADD COLUMN output_numberformat text;
ALTER TABLE language ADD COLUMN output_dateformat text;
ALTER TABLE language ADD COLUMN output_longdates boolean;
sql/Pg-upgrade/Pg-upgrade-2.4.0.1-2.4.0.2.sql
CREATE TABLE units_language (
unit varchar (20) NOT NULL,
language_id integer NOT NULL,
localized varchar (20),
localized_plural varchar (20),
FOREIGN KEY (unit) REFERENCES units (name),
FOREIGN KEY (language_id) REFERENCES language (id)
);
CREATE INDEX units_name_idx ON units (name);
CREATE INDEX units_language_unit_idx ON units_language (unit);
sql/Pg-upgrade/Pg-upgrade-2.4.0.2-2.4.0.3.sql
update tax set id=0 WHERE taxkey=0;
sql/Pg-upgrade2/README
Bitte lesen Sie die Datei doc/sql-upgrade-dateien.txt, bevor
Sie hier Dateien anlegen.
sql/Pg-upgrade2/language_output_formatting.sql
-- @tag: language_output_formatting
-- @description: Speichern des Ausgabeformates f&uuml;r Zahlen und Datumsangaben bei jeder Sprache.
-- @depends:
ALTER TABLE language ADD COLUMN output_numberformat text;
ALTER TABLE language ADD COLUMN output_dateformat text;
ALTER TABLE language ADD COLUMN output_longdates boolean;
sql/Pg-upgrade2/tax_id_if_taxkey_is_0.sql
-- @tag: tax_id_if_taxkey_is_0
-- @description: Aktualisierung der Spalte tax.id, wenn tax.taxkey = 0 ist.
-- @depends:
UPDATE tax SET id = 0 WHERE taxkey = 0;
sql/Pg-upgrade2/units_translations_and_singular_plural_distinction.sql
-- @tag: units_translations_and_singular_plural_distinction
-- @description: F&uuml;r jede Einheit kann f&uuml;r jede Sprache eine &Uuml;bersetzung sowie eine Unterscheidung zwischen Singular und Plural gespeichert werden.
-- @depends:
CREATE TABLE units_language (
unit varchar (20) NOT NULL,
language_id integer NOT NULL,
localized varchar (20),
localized_plural varchar (20),
FOREIGN KEY (unit) REFERENCES units (name),
FOREIGN KEY (language_id) REFERENCES language (id)
);
CREATE INDEX units_name_idx ON units (name);
CREATE INDEX units_language_unit_idx ON units_language (unit);
templates/webpages/dbupgrade/upgrade_message2_de.html
F&uuml;hre <TMPL_VAR file ESCAPE=HTML> aus: <TMPL_VAR description ESCAPE=HTML><br>
templates/webpages/dbupgrade/upgrade_message2_master.html
<translate>Applying <TMPL_VAR file ESCAPE=HTML>:</translate> <TMPL_VAR description ESCAPE=HTML><br>

Auch abrufbar als: Unified diff