Update-Script für constraints in der acc_trans
authorNiclas Zimmermann <niclas@kivitendo-premium.de>
Fri, 8 Mar 2013 16:23:59 +0000 (17:23 +0100)
committerNiclas Zimmermann <niclas@kivitendo-premium.de>
Fri, 8 Mar 2013 16:23:59 +0000 (17:23 +0100)
Fügt NOT-NULL constraints für die Spalten chart_id und trans_id in
der acc_trans hinzu. Falls NULL-Einträge vorhanden sind, wird das
Update mit Fehlermeldung abgebrochen.

Weiterhin wird eine Dependency in add_chart_link_to_acc_trans
hinzugefügt. Hier gab es durch NULL-Werte in acc_trans.chart_id
Probleme.

locale/de/all
sql/Pg-upgrade2/acc_trans_constraints.pl [new file with mode: 0644]
sql/Pg-upgrade2/add_chart_link_to_acc_trans.sql
templates/webpages/dbupgrade/acc_trans_constraints.html [new file with mode: 0644]

index 7b56114..3621d81 100644 (file)
@@ -958,6 +958,7 @@ $self->{texts} = {
   'Help'                        => 'Hilfe',
   'Help Template Variables'     => 'Hilfe zu Dokumenten-Variablen',
   'Help on column names'        => 'Hilfe zu Spaltennamen',
+  'Here'                        => 'Hier',
   'Here\'s an example command line:' => 'Hier ist eine Kommandozeile, die als Beispiel dient:',
   'Hide Filter'                 => 'Filter verbergen',
   'Hide by default'             => 'Standardm&auml;&szlig;ig verstecken',
@@ -1035,6 +1036,7 @@ $self->{texts} = {
   'Invalid follow-up ID.'       => 'Ung&uuml;ltige Wiedervorlage-ID.',
   'Invalid quantity.'           => 'Die Mengenangabe ist ung&uuml;ltig.',
   'Invalid request type \'#1\'' => 'Ungültiger Request-Typ \'#1\'',
+  'Invalid transactions'        => 'Ungültige Buchungen',
   'Invdate'                     => 'Rechnungsdatum',
   'Invdate from'                => 'Rechnungen von',
   'Inventory'                   => 'Inventar',
@@ -1425,6 +1427,7 @@ $self->{texts} = {
   'Please Check the bank information for each customer:' => 'Bitte überprüfen Sie die Bankinformationen der Kunden:',
   'Please Check the bank information for each vendor:' => 'Bitte überprüfen Sie die Kontoinformationen der Lieferanten:',
   'Please ask your administrator to create warehouses and bins.' => 'Bitten Sie Ihren Administrator, dass er Lager und Lagerpl&auml;tze anlegt.',
+  'Please contact your administrator or a service provider.' => 'Bitte kontaktieren Sie Ihren Administrator oder einen Dienstleister.',
   'Please contact your administrator.' => 'Bitte wenden Sie sich an Ihren Administrator.',
   'Please define a taxkey for the following taxes and run the update again:' => 'Bitte definieren Sie einen Steuerschlüssel für die folgenden Steuern und starten Sie dann das Update erneut:',
   'Please enter a profile name.' => 'Bitte geben Sie einen Profilnamen an.',
@@ -1977,6 +1980,7 @@ $self->{texts} = {
   'The following old files whose settings have to be merged manually into the new configuration file "config/kivitendo.conf" still exist:' => 'Es existieren noch die folgenden alten Dateien, deren Einstellungen manuell in die neue Konfiguratsdatei "config/kivitendo.conf" migriert werden müssen:',
   'The following transaction contains wrong taxes:' => 'Die folgende Buchung enthält falsche Steuern:',
   'The following transaction contains wrong taxkeys:' => 'Die folgende Buchung enthält falsche Steuerschlüssel:',
+  'The following transactions are concerned:' => 'Die folgenden Buchungen sind betroffen:',
   'The following units are unknown.' => 'Die folgenden Einheiten sind unbekannt.',
   'The following units exist already:' => 'Die folgenden Einheiten existieren bereits:',
   'The following users have been migrated into the authentication database:' => 'Die folgenden Benutzer wurden in die Authentifizierungsdatenbank migriert:',
@@ -2072,6 +2076,7 @@ $self->{texts} = {
   'There are entries in tax where taxkey is NULL.' => 'In der Datenbank sind Steuern ohne Steuerschlüssel vorhanden (in der Tabelle tax Spalte taxkey).',
   'There are four tax zones.'   => 'Es gibt vier Steuerzonen.',
   'There are invalid taxnumbers in use.' => 'Es werden ungültige Steuerautomatik-Konten benutzt.',
+  'There are invalid transactions in your database.' => 'Sie haben ungültige Buchungen in Ihrer Datenbank.',
   'There are no entries in the background job history.' => 'Es gibt keine Einträge im Hintergrund-Job-Verlauf.',
   'There are no items in stock.' => 'Dieser Artikel ist nicht eingelagert.',
   'There are no items on your TODO list at the moment.' => 'Ihre Aufgabenliste enth&auml;lt momentan keine Eintr&auml;ge.',
@@ -2099,6 +2104,7 @@ $self->{texts} = {
   'This group will be called &quot;Full Access&quot;.' => 'Diese Gruppe wird &quot;Vollzugriff&quot; genannt.',
   'This installation uses an unknown chart of accounts (&quot;#1&quot;). This database upgrade cannot create standard buchungsgruppen automatically.' => 'Diese Installation benutzt einen unbekannten Kontenrahmen (&quot;#1&quot;). Dieses Datenbankupgrade kann die Standardbuchungsgruppen nicht automatisch anlegen.',
   '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 &Auml;nderungen vorgenommen!',
+  'This is a very critical problem.' => 'Dieses Problem ist sehr schwerwiegend.',
   'This list is capped at 15 items to keep it fast. If you need a full list, please use reports.' => 'Diese Liste ist auf 15 Zeilen begrenzt. Wenn Sie eine vollständige Liste benötigen, erstellen Sie bitte einen Bericht.',
   'This means that the user has created an AP transaction and chosen a taxkey for sales taxes, or that he has created an AR transaction and chosen a taxkey for input taxes.' => 'Das bedeutet, dass ein Benutzer eine Kreditorenbuchung angelegt und in ihr einen Umsatzsteuer-Steuerschlüssel verwendet oder eine Debitorenbuchung mit Vorsteuer-Steuerschlüssel angelegt hat.',
   'This module can help you identify and correct such entries by analyzing the general ledger and presenting you likely solutions but also allowing you to fix problems yourself.' => 'Dieses Modul kann Ihnen helfen, problematische Einträge im Hauptbuch zu identifizieren und teilweise zu beheben. Dabei werden je nach Problem mögliche Lösungen aufgezeigt, wobei Sie die entscheiden können, welche Probleme automatisch gelöst werden sollen.',
@@ -2144,6 +2150,8 @@ $self->{texts} = {
   'Transaction has already been cancelled!' => 'Diese Buchung wurde bereits storniert.',
   'Transaction has been split on both the credit and the debit side' => 'Sowohl auf der Soll- als auch auf der Haben-Seite gesplittete Buchung',
   'Transaction posted!'         => 'Buchung verbucht!',
+  'Transactions without account:' => 'Buchungen ohne Konto:',
+  'Transactions without reference:' => 'Buchungen ohne Referenz:',
   'Transactions, AR transactions, AP transactions' => 'Dialogbuchen, Debitorenrechnungen, Kreditorenrechnungen',
   'Transdate'                   => 'Belegdatum',
   'Transfer'                    => 'Umlagern',
@@ -2537,6 +2545,7 @@ $self->{texts} = {
   'wrongformat'                 => 'Falsches Format',
   'yearly'                      => 'jährlich',
   'yes'                         => 'ja',
+  'you can find professional help.' => 'finden Sie professionelle Hilfe.',
 };
 
 1;
diff --git a/sql/Pg-upgrade2/acc_trans_constraints.pl b/sql/Pg-upgrade2/acc_trans_constraints.pl
new file mode 100644 (file)
index 0000000..7d57efb
--- /dev/null
@@ -0,0 +1,159 @@
+# @tag: acc_trans_constraints
+# @description: Fügt NOT-NULL-Constraints ein für die Spalten
+# @depends:
+# @charset: UTF-8
+
+use utf8;
+use strict;
+
+die("This script cannot be run from the command line.") unless ($main::form);
+
+sub mydberror {
+  my ($msg) = @_;
+  die($dbup_locale->text("Database update error:") . "<br>$msg<br>" . $DBI::errstr);
+}
+
+sub do_query {
+  my ($query, $may_fail) = @_;
+
+  if (!$dbh->do($query)) {
+    mydberror($query) unless ($may_fail);
+    $dbh->rollback();
+    $dbh->begin_work();
+  }
+}
+
+sub do_update {
+  my $query = qq|SELECT count(*) FROM acc_trans WHERE chart_id IS NULL|;
+  my ($no_chart_id) = $dbh->selectrow_array($query);
+  $query = qq|SELECT count(*) FROM acc_trans WHERE trans_id IS NULL|;
+  my ($no_trans_id) = $dbh->selectrow_array($query);
+
+  $form->{no_chart_id}=$no_chart_id;
+  $form->{no_trans_id}=$no_trans_id;
+
+  if ($no_chart_id > 0 or $no_trans_id > 0){
+    #list all invalid transactions where only chart_id is null:
+    $query = qq|SELECT acc.acc_trans_id,
+                  acc.gldate,
+                  acc.transdate,
+                  ABS(acc.amount) AS amount,
+                  acc.trans_id,
+                  acc.source,
+                  gl.reference,
+                  gl.description,
+                  gl.notes,
+                  e.name,
+                  e.login AS user,
+                  p.projectnumber,
+                  p.description AS projectdescription
+                FROM acc_trans acc
+                JOIN gl ON (gl.id=acc.trans_id)
+                LEFT JOIN employee e ON (gl.employee_id=e.id)
+                LEFT JOIN project p ON (p.id=acc.project_id)
+                WHERE acc.chart_id IS NULL
+
+                UNION
+
+                SELECT acc.acc_trans_id,
+                  acc.gldate,
+                  acc.transdate,
+                  ABS(acc.amount) AS amount,
+                  acc.trans_id,
+                  acc.source,
+                  a.invnumber AS reference,
+                  c.name AS description,
+                  a.notes,
+                  e.name,
+                  e.login AS user,
+                  p.projectnumber,
+                  p.description AS projectdescription
+                FROM acc_trans acc
+                JOIN ar a ON (a.id=acc.trans_id)
+                LEFT JOIN employee e ON (a.employee_id=e.id)
+                LEFT JOIN customer c ON (a.customer_id=c.id)
+                LEFT JOIN project p ON (p.id=acc.project_id)
+                WHERE acc.chart_id IS NULL
+
+                UNION
+
+                SELECT acc.acc_trans_id,
+                  acc.gldate,
+                  acc.transdate,
+                  ABS(acc.amount) AS amount,
+                  acc.trans_id,
+                  acc.source,
+                  a.invnumber AS reference,
+                  v.name AS description,
+                  a.notes,
+                  e.name,
+                  e.login AS user,
+                  p.projectnumber,
+                  p.description AS projectdescription
+                FROM acc_trans acc
+                JOIN ap a ON (a.id=acc.trans_id)
+                LEFT JOIN employee e ON (a.employee_id=e.id)
+                LEFT JOIN vendor v ON (a.vendor_id=v.id)
+                LEFT JOIN project p ON (p.id=acc.project_id)
+                WHERE acc.chart_id IS NULL;|;
+
+    my $sth = $dbh->prepare($query);
+    $sth->execute || $main::form->dberror($query);
+
+    $main::form->{NO_CHART_ID} = [];
+    while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
+      map {$ref->{$_} = $::locale->{iconv_utf8}->convert($ref->{$_})} keys %$ref;
+      push @{ $main::form->{NO_CHART_ID} }, $ref;
+    }
+    $sth->finish;
+
+    #List all invalid transactions where trans_id is null:
+    $query = qq|SELECT acc.acc_trans_id,
+                  acc.gldate,
+                  acc.transdate,
+                  ABS(acc.amount) AS amount,
+                  acc.source,
+                  c.accno,
+                  c.description,
+                  c.category,
+                  p.projectnumber,
+                  p.description AS projectdescription
+                FROM acc_trans acc
+                LEFT JOIN chart c ON (c.id=acc.chart_id)
+                LEFT JOIN project p ON (p.id=acc.project_id)
+                WHERE acc.trans_id IS NULL;|;
+
+    $sth = $dbh->prepare($query);
+    $sth->execute || $main::form->dberror($query);
+
+    $main::form->{NO_TRANS_ID} = [];
+    while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
+      map {$ref->{$_} = $::locale->{iconv_utf8}->convert($ref->{$_})} keys %$ref;
+      $ref->{category} = ($ref->{category} eq 'A') ? $::locale->text('Account Category A')
+        : ($ref->{category} eq 'E') ? $::locale->text('Account Category E')
+        : ($ref->{category} eq 'L') ? $::locale->text('Account Category L')
+        : ($ref->{category} eq 'I') ? $::locale->text('Account Category I')
+        : ($ref->{category} eq 'Q') ? $::locale->text('Account Category Q')
+        : ($ref->{category} eq 'C') ? $::locale->text('Account Category C')
+        : ($ref->{category} eq 'G') ? $::locale->text('Account Category G')
+        : $::locale->text('Unknown Category') . ': ' . $ref->{category};
+      push @{ $main::form->{NO_TRANS_ID} }, $ref;
+    }
+    $sth->finish;
+
+    print_error_message();
+    return 0;
+  }
+
+  $query = qq|ALTER TABLE acc_trans ALTER COLUMN chart_id SET NOT NULL;|;
+  $query .= qq|ALTER TABLE acc_trans ALTER COLUMN trans_id SET NOT NULL;|;
+
+  do_query($query);
+  return 1;
+}
+
+sub print_error_message {
+  print $main::form->parse_html_template("dbupgrade/acc_trans_constraints");
+}
+
+return do_update();
index a1ae058..78696ef 100644 (file)
@@ -1,6 +1,6 @@
 -- @tag: add_chart_link_to_acc_trans
 -- @description: Neue Spalte chart_link in der acc_trans
--- @depends: release_3_0_0 
+-- @depends: release_3_0_0 acc_trans_constraints
 
 --Spalte link in der chart updaten:
 UPDATE chart SET link = '' WHERE link IS NULL;
diff --git a/templates/webpages/dbupgrade/acc_trans_constraints.html b/templates/webpages/dbupgrade/acc_trans_constraints.html
new file mode 100644 (file)
index 0000000..389b1d0
--- /dev/null
@@ -0,0 +1,89 @@
+[%- USE T8 %]
+[%- USE L %]
+[% USE HTML %]<div class="listtop">[% 'Invalid transactions' | $T8 %]</div>
+
+<form name="Form" method="post" action="login.pl">
+<input type="hidden" name="action" value="login">
+
+<p>[% 'There are invalid transactions in your database.' | $T8 %]</p>
+<p>[% 'The following transactions are concerned:' | $T8 %]</p>
+
+[% IF no_chart_id %]
+  <p>[% 'Transactions without account:' | $T8 %]</p>
+  <table>
+    <tr>
+      <th class="listheading">[% 'Database ID' | $T8 %]</th>
+      <th class="listheading">[% 'Booking Date' | $T8 %]</th>
+      <th class="listheading">[% 'Invoice Date' | $T8 %]</th>
+      <th class="listheading">[% 'Amount' | $T8 %]</th>
+      <th class="listheading">[% 'Buchungsnummer' | $T8 %]</th>
+      <th class="listheading">[% 'Source' | $T8 %]</th>
+      <th class="listheading">[% 'Reference / Invoice Number' | $T8 %]</th>
+      <th class="listheading">[% 'Description' | $T8 %]</th>
+      <th class="listheading">[% 'Notes' | $T8 %]</th>
+      <th class="listheading">[% 'Employee' | $T8 %]</th>
+      <th class="listheading">[% 'User' | $T8 %]</th>
+      <th class="listheading">[% 'Project Number' | $T8 %]</th>
+      <th class="listheading">[% 'Project Description' | $T8 %]</th>
+    </tr>
+
+    [% SET row_odd = '1' %][% FOREACH row = NO_CHART_ID %]
+    <tr class="listrow[% IF row_odd %]1[% SET row_odd = '0' %][% ELSE %]0[% SET row_odd = '1' %][% END %]">
+      <td align="left">[% HTML.escape(row.acc_trans_id) %]</td>
+      <td align="left">[% HTML.escape(row.gldate) %]</td>
+      <td align="left">[% HTML.escape(row.transdate) %]</td>
+      <td align="left">[% HTML.escape(row.amount) %]</td>
+      <td align="left">[% HTML.escape(row.trans_id) %]</td>
+      <td align="left">[% HTML.escape(row.source) %]</td>
+      <td align="left">[% HTML.escape(row.reference) %]</td>
+      <td align="left">[% HTML.escape(row.description) %]</td>
+      <td align="left">[% HTML.escape(row.notes) %]</td>
+      <td align="left">[% HTML.escape(row.name) %]</td>
+      <td align="left">[% HTML.escape(row.user) %]</td>
+      <td align="left">[% HTML.escape(row.projectnumber) %]</td>
+      <td align="left">[% HTML.escape(row.projectdescription) %]</td>
+    </tr>
+    [% END %]
+  </table>
+
+[% END %]
+
+[% IF no_trans_id %]
+  <p>[% 'Transactions without reference:' | $T8 %]</p>
+  <table>
+    <tr>
+      <th class="listheading">[% 'Database ID' | $T8 %]</th>
+      <th class="listheading">[% 'Booking Date' | $T8 %]</th>
+      <th class="listheading">[% 'Invoice Date' | $T8 %]</th>
+      <th class="listheading">[% 'Amount' | $T8 %]</th>
+      <th class="listheading">[% 'Source' | $T8 %]</th>
+      <th class="listheading">[% 'Account Number' | $T8 %]</th>
+      <th class="listheading">[% 'Description' | $T8 %]</th>
+      <th class="listheading">[% 'Account Type' | $T8 %]</th>
+      <th class="listheading">[% 'Project Number' | $T8 %]</th>
+      <th class="listheading">[% 'Project Description' | $T8 %]</th>
+    </tr>
+
+    [% SET row_odd = '1' %][% FOREACH row = NO_TRANS_ID %]
+    <tr class="listrow[% IF row_odd %]1[% SET row_odd = '0' %][% ELSE %]0[% SET row_odd = '1' %][% END %]">
+      <td align="left">[% HTML.escape(row.acc_trans_id) %]</td>
+      <td align="left">[% HTML.escape(row.gldate) %]</td>
+      <td align="left">[% HTML.escape(row.transdate) %]</td>
+      <td align="left">[% HTML.escape(row.amount) %]</td>
+      <td align="left">[% HTML.escape(row.source) %]</td>
+      <td align="left">[% HTML.escape(row.accno) %]</td>
+      <td align="left">[% HTML.escape(row.description) %]</td>
+      <td align="left">[% HTML.escape(row.category) %]</td>
+      <td align="left">[% HTML.escape(row.projectnumber) %]</td>
+      <td align="left">[% HTML.escape(row.projectdescription) %]</td>
+    </tr>
+    [% END %]
+  </table>
+
+[% END %]
+
+<p>[% 'This is a very critical problem.' | $T8 %]</p>
+<p>[% 'Please contact your administrator or a service provider.' | $T8 %]</p>
+<p><a href="http://www.kivitendo.de/partner.html" target="_blank">[% 'Here' | $T8 %]</a> [% 'you can find professional help.' | $T8 %]</p>
+
+</form>