]> wagnertech.de Git - mfinanz.git/commitdiff
Merge branch 'merge_chart_link'
authorNiclas Zimmermann <niclas@kivitendo-premium.de>
Tue, 26 Feb 2013 09:09:50 +0000 (10:09 +0100)
committerNiclas Zimmermann <niclas@kivitendo-premium.de>
Tue, 26 Feb 2013 09:09:50 +0000 (10:09 +0100)
12 files changed:
SL/AM.pm
SL/CT.pm
SL/MoreCommon.pm
bin/mozilla/am.pl
bin/mozilla/ct.pl
locale/de/all
locale/en/all
sql/Pg-upgrade2/add_tax_id_to_acc_trans.sql
sql/Pg-upgrade2/tax_constraints.pl [new file with mode: 0644]
templates/webpages/am/edit_tax.html
templates/webpages/ct/search.html
templates/webpages/dbupgrade/tax_constraints.html [new file with mode: 0644]

index c7a88d2df81c26044b7fe66f1e93624e65c16711..5645c4dd79337dbe43bc253ed7c4dc46bc0ddfab 100644 (file)
--- a/SL/AM.pm
+++ b/SL/AM.pm
@@ -1779,7 +1779,9 @@ sub get_tax {
                    taxkey,
                    taxdescription,
                    round(rate * 100, 2) AS rate,
-                   chart_id
+                   chart_id, 
+                   (id IN (SELECT tax_id 
+                           FROM acc_trans)) AS tax_already_used
                  FROM tax
                  WHERE id = ? |;
 
index a32486b59375123d08183a3470c860b1652b5a1f..dd9d627b816e9632eb375bee6353adbe18fdb181 100644 (file)
--- a/SL/CT.pm
+++ b/SL/CT.pm
@@ -614,12 +614,36 @@ sub search {
   my $where = "1 = 1";
   my @values;
 
-  my %allowed_sort_columns =
-    map { $_, 1 } qw(
-      id customernumber vendornumber name contact phone fax email street
-      taxnumber business invnumber ordnumber quonumber zipcode city
+  my %allowed_sort_columns = (
+      "id" => "id",
+      "customernumber" => "customernumber",
+      "vendornumber" => "vendornumber",
+      "name" => "ct.name",
+      "contact" => "contact",
+      "phone" => "phone",
+      "fax" => "fax",
+      "email" => "email",
+      "street" => "street",
+      "taxnumber" => "taxnumber",
+      "business" => "business",
+      "invnumber" => "invnumber",
+      "ordnumber" => "ordnumber",
+      "quonumber" => "quonumber",
+      "zipcode" => "zipcode",
+      "city" => "city",
+      "country" => "country",
+      "salesman" => "e.name"
     );
-  my $sortorder    = $form->{sort} && $allowed_sort_columns{$form->{sort}} ? $form->{sort} : "name";
+
+  my $sortorder;
+  if ( $join_records ) {
+    # in UNION case order by hash key, e.g. salesman
+    # the UNION created an implicit select around the result 
+    $sortorder = $form->{sort} && $allowed_sort_columns{$form->{sort}} ? $form->{sort} : "name";
+  } else {
+    # in not UNION case order by hash value, e.g. e.name
+    $sortorder = $form->{sort} && $allowed_sort_columns{$form->{sort}} ?  $allowed_sort_columns{$form->{sort}} : "ct.name";
+  };
   $form->{sort} = $sortorder;
   my $sortdir   = !defined $form->{sortdir} ? 'ASC' : $form->{sortdir} ? 'ASC' : 'DESC';
 
@@ -659,6 +683,19 @@ sub search {
     push @values, ('%' . $form->{addr_city} . '%') x 2;
   }
 
+  if ($form->{addr_country}) {
+    $where .= " AND ((lower(ct.country) LIKE lower(?))
+                     OR
+                     (ct.id IN (
+                        SELECT trans_id
+                        FROM shipto
+                        WHERE (module = 'CT')
+                          AND (lower(shiptocountry) LIKE lower(?))
+                      ))
+                     )";
+    push @values, ('%' . $form->{addr_country} . '%') x 2;
+  }
+
   if ( $form->{status} eq 'orphaned' ) {
     $where .=
       qq| AND ct.id NOT IN | .
@@ -676,7 +713,7 @@ sub search {
         qq|  WHERE cv.id = a.vendor_id)|;
     }
     $form->{l_invnumber} = $form->{l_ordnumber} = $form->{l_quonumber} = "";
-  }
+  };
 
   if ($form->{obsolete} eq "Y") {
     $where .= qq| AND obsolete|;
@@ -716,10 +753,11 @@ sub search {
   }
 
   my $query =
-    qq|SELECT ct.*, b.description AS business | .
+    qq|SELECT ct.*, b.description AS business, e.name as salesman | .
     (qq|, NULL AS invnumber, NULL AS ordnumber, NULL AS quonumber, NULL AS invid, NULL AS module, NULL AS formtype, NULL AS closed | x!! $join_records) .
     qq|FROM $cv ct | .
     qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
+    qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
     qq|WHERE $where|;
 
   my @saved_values = @values;
@@ -733,13 +771,14 @@ sub search {
       push(@values, @saved_values);
       $query .=
         qq| UNION | .
-        qq|SELECT ct.*, b.description AS business, | .
+        qq|SELECT ct.*, b.description AS business, e.name as salesman, | .
         qq|  a.invnumber, a.ordnumber, a.quonumber, a.id AS invid, | .
         qq|  '$module' AS module, 'invoice' AS formtype, | .
         qq|  (a.amount = a.paid) AS closed | .
         qq|FROM $cv ct | .
         qq|JOIN $ar a ON (a.${cv}_id = ct.id) | .
         qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
+        qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
         qq|WHERE $where AND (a.invoice = '1')|;
     }
 
@@ -747,12 +786,13 @@ sub search {
       push(@values, @saved_values);
       $query .=
         qq| UNION | .
-        qq|SELECT ct.*, b.description AS business,| .
+        qq|SELECT ct.*, b.description AS business, e.name as salesman, | .
         qq|  ' ' AS invnumber, o.ordnumber, o.quonumber, o.id AS invid, | .
         qq|  'oe' AS module, 'order' AS formtype, o.closed | .
         qq|FROM $cv ct | .
         qq|JOIN oe o ON (o.${cv}_id = ct.id) | .
         qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
+        qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
         qq|WHERE $where AND (o.quotation = '0')|;
     }
 
@@ -760,18 +800,19 @@ sub search {
       push(@values, @saved_values);
       $query .=
         qq| UNION | .
-        qq|SELECT ct.*, b.description AS business, | .
+        qq|SELECT ct.*, b.description AS business, e.name as salesman, | .
         qq|  ' ' AS invnumber, o.ordnumber, o.quonumber, o.id AS invid, | .
         qq|  'oe' AS module, 'quotation' AS formtype, o.closed | .
         qq|FROM $cv ct | .
         qq|JOIN oe o ON (o.${cv}_id = ct.id) | .
         qq|LEFT JOIN business b ON (ct.business_id = b.id) | .
+        qq|LEFT JOIN employee e ON (ct.salesman_id = e.id) | .
         qq|WHERE $where AND (o.quotation = '1')|;
     }
   }
 
   $query .= qq| ORDER BY $sortorder|;
-
+  
   $form->{CT} = selectall_hashref_query($form, $dbh, $query, @values);
 
   $main::lxdebug->leave_sub();
index 6fbf87dc48f95984eae3f7a98433a4231f6775f4..dfc5a7d8002d63c7aa637efab70fc25f07b09824 100644 (file)
@@ -171,7 +171,7 @@ sub uri_encode {
 }
 
 sub uri_decode {
-  my $str = $_[0] || '';
+  my $str = $_[0] // '';
 
   $str =~ tr/+/ /;
   $str =~ s/\\$//;
index 2b7cdf8ee900f6044d247d3261a23f56af8d5672..bcb39d258f066a65813f4ca81a272541914ae4be 100644 (file)
@@ -1491,7 +1491,11 @@ sub edit_tax {
 
   $form->header();
 
+  #set readonly if the there are entries in acc_trans with the tax
+  my $readonly = $form->{tax_already_used} ? 'readonly' : '';
+
   my $parameters_ref = {
+    readonly => $readonly, 
   };
 
   # Ausgabe des Templates
@@ -1552,12 +1556,16 @@ sub save_tax {
 
   $main::auth->assert('config');
 
-  $form->isblank("rate", $locale->text('Taxrate missing!'));
-  $form->isblank("taxdescription", $locale->text('Taxdescription  missing!'));
-  $form->isblank("taxkey", $locale->text('Taxkey  missing!'));
+  $form->error($locale->text('Taxkey  missing!')) unless length($form->{taxkey}) != 0;
+  $form->error($locale->text('Taxdescription  missing!')) unless length($form->{taxdescription}) != 0;
+  $form->error($locale->text('Taxrate missing!')) unless length($form->{rate}) != 0;
 
   $form->{rate} = $form->parse_amount(\%myconfig, $form->{rate});
 
+  if ($form->{taxkey} == 0 and $form->{rate} > 0) {
+    $form->error($locale->text('Taxkey 0 is reserved for rate 0'));
+  }
+
   if ( $form->{rate} < 0 || $form->{rate} >= 100 ) {
     $form->error($locale->text('Tax Percent is a number between 0 and 100'));
   }
index ff7eedef6c3615203f76a67647e0992fe7bdf75a..c127b24c91f87c1d8f0ce629e46189387ccb2262 100644 (file)
@@ -161,6 +161,7 @@ sub list_names {
   push @options, $locale->text('Billing/shipping address (city)')    . " : $form->{addr_city}" if $form->{addr_city};
   push @options, $locale->text('Billing/shipping address (zipcode)') . " : $form->{zipcode}"   if $form->{addr_zipcode};
   push @options, $locale->text('Billing/shipping address (street)')  . " : $form->{street}"    if $form->{addr_street};
+  push @options, $locale->text('Billing/shipping address (country)') . " : $form->{country}"   if $form->{addr_country};
 
   if ($form->{business_id}) {
     my $business = SL::DB::Manager::Business->find_by(id => $form->{business_id});
@@ -171,9 +172,9 @@ sub list_names {
   }
 
   my @columns = (
-    'id',        'name',      "$form->{db}number",   'contact',  'phone',
-    'fax',       'email',     'taxnumber',           'street',   'zipcode' , 'city',
-    'business',  'invnumber', 'ordnumber',           'quonumber'
+    'id',        'name',      "$form->{db}number",   'contact',   'phone',
+    'fax',       'email',     'taxnumber',           'street',    'zipcode' , 'city',
+    'business',  'invnumber', 'ordnumber',           'quonumber', 'salesman', 'country' 
   );
 
   my @includeable_custom_variables = grep { $_->{includeable} } @{ $cvar_configs };
@@ -199,6 +200,8 @@ sub list_names {
     'street'            => { 'text' => $locale->text('Street'), },
     'zipcode'           => { 'text' => $locale->text('Zipcode'), },
     'city'              => { 'text' => $locale->text('City'), },
+    'country'           => { 'text' => $locale->text('Country'), },
+    'salesman'          => { 'text' => $locale->text('Salesman'), },
     %column_defs_cvars,
   );
 
index 9e7f46f0ad29ae6f23a68f1580968a08cede9966..15f94b8af395411d5b524f39a1ada804f7c3c7ca 100644 (file)
@@ -20,9 +20,11 @@ $self->{texts} = {
   '*) Since version 2.7 these parameters ares set in the client database and not in the configuration file, details in chapter:' => '*) Seit 2.7 werden Gewinnermittlungsart, Versteuerungsart und Warenbuchungsmethode in der Mandanten-DB gesteuert und nicht mehr in der Konfigurationsdatei, Umstellungs-Details:',
   '*/'                          => '*/',
   '---please select---'         => '---bitte auswählen---',
+  '. Automatically generated.'  => '. Automatisch erzeugt.',
   '...after loggin in'          => '...nach dem Anmelden',
   '...done'                     => '...fertig',
   '...on the TODO list'         => '...auf der Aufgabenliste',
+  '0% tax with taxkey'          => '0% Steuer mit Steuerschlüssel ',
   '1. Quarter'                  => '1. Quartal',
   '2. Quarter'                  => '2. Quartal',
   '3. Quarter'                  => '3. Quartal',
@@ -282,6 +284,7 @@ $self->{texts} = {
   'Bilanz'                      => 'Bilanz',
   'Billing Address'             => 'Rechnungsadresse',
   'Billing/shipping address (city)' => 'Rechnungsadresse (Stadt)',
+  'Billing/shipping address (country)' => 'Rechnungsadresse (Land)',
   'Billing/shipping address (street)' => 'Rechnungsadresse (Straße)',
   'Billing/shipping address (zipcode)' => 'Rechnungsadresse (PLZ)',
   'Bin'                         => 'Lagerplatz',
@@ -1008,6 +1011,7 @@ $self->{texts} = {
   'Income accno'                => 'Erl&ouml;skonto',
   'Incoming Payments'           => 'Zahlungseingänge',
   'Incoming invoice number'     => 'Eingangsrechnungsnummer',
+  'Inconsistency in database'   => 'Unstimmigkeiten in der Datenbank',
   'Incorrect Password!'         => 'Ungültiges Passwort!',
   'Incorrect password!'         => 'Ungültiges Passwort!',
   'Incorrect username or password!' => 'Ungültiger Benutzername oder falsches Passwort!',
@@ -1417,6 +1421,7 @@ $self->{texts} = {
   '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.' => '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.',
   '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&uuml;r die neue Datenbank benutzt wird:',
@@ -1440,6 +1445,7 @@ $self->{texts} = {
   'Please select the destination bank account for the collections:' => 'Bitte wählen Sie das Bankkonto als Ziel für die Einzüge aus:',
   'Please select the source bank account for the transfers:' => 'Bitte wählen Sie das Bankkonto als Quelle für die Überweisungen aus:',
   'Please seletct the dataset you want to delete:' => 'Bitte w&auml;hlen Sie die zu l&ouml;schende Datenbank aus:',
+  'Please set another taxnumber for the following taxes and run the update again:' => 'Bitte wählen Sie ein anderes Steuerautomatik-Konto für die folgenden Steuern aus uns starten Sie dann das Update erneut.',
   'Please specify a description for the warehouse designated for these goods.' => 'Bitte geben Sie den Namen des Ziellagers f&uuml;r die &uuml;bernommenen Daten ein.',
   'Plural'                      => 'Plural',
   'Port'                        => 'Port',
@@ -1858,6 +1864,7 @@ $self->{texts} = {
   'Taxes'                       => 'Steuern',
   'Taxkey'                      => 'Steuerschlüssel',
   'Taxkey  missing!'            => 'Steuerschlüssel fehlt!',
+  'Taxkey 0 is reserved for rate 0' => 'Der Steuerschlüssel 0 darf keinen Steuersatz über 0 haben.',
   'Taxkey_coa'                  => 'Steuerschlüssel',
   'Taxkeys and Taxreport Preferences' => 'Steuerautomatik und UStVA',
   'Taxlink_coa'                 => 'Steuerautomatik',
@@ -2052,7 +2059,9 @@ $self->{texts} = {
   'There are #1 more open invoices from this vendor with other currencies.' => 'Es gibt #1 weitere offene Rechnungen von diesem Lieferanten, die in anderen Währungen ausgestellt wurden.',
   'There are #1 unfinished follow-ups of which #2 are due.' => 'Es gibt #1 Wiedervorlage(n), von denen #2 fällig ist/sind.',
   'There are bookings to the account 3803 after 01.01.2007. If you didn\'t change this account manually to 19% the bookings are probably incorrect.' => 'Das Konto 3803 wurde nach dem 01.01.2007 bebucht. Falls Sie dieses Konto nicht manuell auf 19% gestellt haben sind die Buchungen wahrscheinlich mit falscher Umsatzsteuer gebucht worden.',
+  '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 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.',
@@ -2060,6 +2069,7 @@ $self->{texts} = {
   'There are still transfers not matching the qty of the delivery order. Stock operations can not be changed later. Do you really want to proceed?' => 'Einige der Lagerbewegungen sind nicht vollständig und Lagerbewegungen können nachträglich nicht mehr verändert werden. Wollen Sie wirklich fortfahren?',
   'There are usually three ways to install Perl modules.' => 'Es gibt normalerweise drei Arten, ein Perlmodul zu installieren.',
   'There is already a taxkey 0 with tax rate not 0.' => 'Es existiert bereits ein Steuerschlüssel mit Steuersatz ungleich 0%.',
+  'There is an inconsistancy in your database.' => 'In Ihrer Datenbank sind Unstimmigkeiten vorhanden.',
   'There is at least one sales or purchase invoice for which kivitendo recorded an inventory transaction with taxkeys even though no tax was recorded.' => 'Es gibt mindestens eine Verkaufs- oder Einkaufsrechnung, für die kivitendo eine Warenbestandsbuchung ohne dazugehörige Steuerbuchung durchgeführt hat.',
   'There is at least one transaction for which the user has chosen a logically wrong taxkey.' => 'Es gibt mindestens eine Buchung, bei der ein logisch nicht passender Steuerschlüssel ausgewählt wurde.',
   'There is not enough available of \'#1\' at warehouse \'#2\', bin \'#3\', #4, #5, for the transfer of #6.' => 'Von \'#1\' ist in Lager \'#2\', Lagerplatz \'#3\', #4, #5, nicht gen&uuml;gend eingelagert, um insgesamt #6 auszulagern.',
index 7734f90cf1f78318f1af9d0fa9decc133c4e96ca..3424a015882b6eaf97a6068d0fca86d5db11ab65 100644 (file)
@@ -20,9 +20,11 @@ $self->{texts} = {
   '*) Since version 2.7 these parameters ares set in the client database and not in the lx-erp.conf / lx_office.conf file, details in chapter:' => '',
   '*/'                          => '',
   '---please select---'         => '',
+  '. Automatically generated.'  => '',
   '...after loggin in'          => '',
   '...done'                     => '',
   '...on the TODO list'         => '',
+  '0% tax with taxkey'          => '',
   '1. Quarter'                  => '',
   '2. Quarter'                  => '',
   '3. Quarter'                  => '',
@@ -1814,6 +1816,7 @@ $self->{texts} = {
   'Taxes'                       => '',
   'Taxkey'                      => '',
   'Taxkey  missing!'            => '',
+  'Taxkey 0 is reserved for rate 0' => '',
   'Taxkey_coa'                  => '',
   'Taxkeys and Taxreport Preferences' => '',
   'Taxlink_coa'                 => '',
@@ -1985,13 +1988,17 @@ $self->{texts} = {
   'There are #1 more open invoices from this vendor with other currencies.' => '',
   'There are #1 unfinished follow-ups of which #2 are due.' => '',
   'There are bookings to the account 3803 after 01.01.2007. If you didn\'t change this account manually to 19% the bookings are probably incorrect.' => '',
+  'There are entries in tax where taxkey is NULL.' => '',
   'There are four tax zones.'   => '',
+  'There are invalid taxnumbers in use.' => '',
+  'There are no entries in the background job history.' => '',
   'There are no items in stock.' => '',
   'There are no items on your TODO list at the moment.' => '',
   'There are still entries in the database for which no unit has been assigned.' => '',
   'There are still transfers not matching the qty of the delivery order. Stock operations can not be changed later. Do you really want to proceed?' => '',
   'There are usually three ways to install Perl modules.' => '',
   'There is already a taxkey 0 with tax rate not 0.' => '',
+  'There is an inconsistancy in your database.' => '',
   'There is at least one sales or purchase invoice for which kivitendo recorded an inventory transaction with taxkeys even though no tax was recorded.' => '',
   'There is at least one transaction for which the user has chosen a logically wrong taxkey.' => '',
   'There is not enough available of \'#1\' at warehouse \'#2\', bin \'#3\', #4, #5, for the transfer of #6.' => '',
index 7e8b766c7ba9a08f00d6c409b7353add85b05682..06047b53582fa78d5b26b618a3031674f048e500 100644 (file)
@@ -1,6 +1,6 @@
 -- @tag: add_tax_id_to_acc_trans
 -- @description: Neue Spalte tax_id in der acc_trans
--- @depends: release_2_7_0 
+-- @depends: release_3_0_0 charts_without_taxkey
 -- @charset: utf-8
 
   --Neue Spalte tax_id in acc_trans:
diff --git a/sql/Pg-upgrade2/tax_constraints.pl b/sql/Pg-upgrade2/tax_constraints.pl
new file mode 100644 (file)
index 0000000..70fe83d
--- /dev/null
@@ -0,0 +1,304 @@
+# @tag: tax_constraints
+# @description: Setzt Fremdschlüssel und andere constraints auf die Tabellen tax und taxkeys
+# @depends: release_3_0_0 charts_without_taxkey
+# @charset: utf-8
+
+use utf8;
+use strict;
+use SL::Locale;
+
+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 {
+  #CHECK CONSISTANCY OF tax
+  #update tax.rate and tax.taxdescription in order to set later NOT NULL constraints
+  my $query= <<SQL;
+    UPDATE tax SET rate=0 WHERE rate IS NULL;
+    UPDATE tax SET taxdescription='-' WHERE COALESCE(taxdescription, '') = '';
+SQL
+
+  do_query($query);
+
+  #check automatic tax accounts
+  $query= <<SQL;
+    SELECT count(*) FROM tax WHERE chart_id NOT IN (SELECT id FROM chart);
+SQL
+
+  my ($invalid_tax_account) = $dbh->selectrow_array($query);
+
+  if ($invalid_tax_account > 0){
+    #list all invalid tax accounts
+    $query = <<SQL;
+      SELECT id,
+        taxkey,
+        taxdescription,
+        round(rate * 100, 2) AS rate
+      FROM tax WHERE chart_id NOT IN (SELECT id FROM chart);
+SQL
+
+    my $sth = $dbh->prepare($query);
+    $sth->execute || $main::form->dberror($query);
+
+    $main::form->{TAX} = [];
+    while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
+      push @{ $main::form->{TAX} }, $ref;
+    }
+    $sth->finish;
+
+    $main::form->{invalid_tax_account} = 1;
+    print_error_message();
+    return 0;
+  }
+
+  #check entry tax.taxkey of NOT NULL
+  $query= <<SQL;
+    SELECT count(*) FROM tax WHERE taxkey IS NULL;
+SQL
+
+  my ($taxkey_is_null) = $dbh->selectrow_array($query);
+
+  if ($taxkey_is_null > 0){
+    #list all invalid tax accounts
+    $query = <<SQL;
+      SELECT id,
+        taxdescription,
+        round(rate * 100, 2) AS rate,
+        (SELECT accno FROM chart WHERE id = chart_id) AS taxnumber,
+        (SELECT description FROM chart WHERE id = chart_id) AS account_description
+      FROM tax
+      WHERE taxkey IS NULL;
+SQL
+
+    my $sth = $dbh->prepare($query);
+    $sth->execute || $main::form->dberror($query);
+
+    $main::form->{TAX} = [];
+    while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
+      push @{ $main::form->{TAX} }, $ref;
+    }
+    $sth->finish;
+
+    $main::form->{taxkey_is_null} = 1;
+    print_error_message();
+    return 0;
+  }
+  #END CHECK OF tax
+
+  #CHECK CONSISTANCY OF taxkeys
+  #delete invalide entries in taxkeys
+  $query= <<SQL;
+    DELETE FROM taxkeys
+    WHERE chart_id IS NULL
+    OR chart_id NOT IN (SELECT id FROM chart)
+    OR startdate IS NULL;
+SQL
+
+  do_query($query);
+
+  #There are 3 cases for taxkeys.tax_id and taxkeys.taxkey_id
+  #taxkeys.taxkey_id is NULL and taxkeys.tax_id is not NULL:
+
+  #Update taxkeys.taxkey_id with tax.taxkey
+  $query= <<SQL;
+    UPDATE taxkeys
+    SET taxkey_id = (SELECT t.taxkey
+                        FROM tax t
+                        WHERE t.id=tax_id)
+    WHERE taxkey_id IS NULL
+    AND tax_id IS NOT NULL;
+SQL
+
+  do_query($query);
+
+  #taxkeys.taxkey_id and taxkeys.tax_id are NULL:
+
+  #Set taxkey 0 in this case:
+  $query= <<SQL;
+    UPDATE taxkeys
+    SET taxkey_id = 0, tax_id = (SELECT id FROM tax WHERE taxkey=0)
+    WHERE taxkey_id IS NULL
+    AND tax_id IS NULL;
+SQL
+
+  do_query($query);
+
+  #Last case where taxkeys.taxkey_id is not null and taxkeys.tax_id is null
+
+  #If such entries exist we update with an entry in tax where tax.rate=0
+  #and tax.taxkey corresponds to taxkeys.taxkey_id.
+  #If no entry in tax with rate 0 and taxkey taxkeys.taxkey_id exists
+  #we create one.
+  $query= <<SQL;
+    SELECT DISTINCT taxkey_id
+    FROM taxkeys
+    WHERE taxkey_id IS NOT NULL
+    AND tax_id IS NULL;
+SQL
+
+  my $sth = $dbh->prepare($query);
+  $sth->execute || $main::form->dberror($query);
+
+  $main::form->{TAXID} = [];
+  my $rowcount = 0;
+  while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
+    push @{ $main::form->{TAXID} }, $ref;
+    $rowcount++;
+  }
+  $sth->finish;
+
+  my $insertquery;
+  my $updatequery;
+  my $tax_id;
+  for my $i (0 .. $rowcount-1){
+    $query= qq|
+      SELECT id FROM tax WHERE rate = 0 and taxkey=| . $main::form->{TAXID}[$i]->{taxkey_id} . qq| LIMIT 1
+|;
+    ($tax_id) = $dbh->selectrow_array($query);
+    if ( not $tax_id ){
+      $insertquery=qq|
+        INSERT INTO tax (rate, taxdescription, taxkey) VALUES (0, '| . $::locale->text('0% tax with taxkey') . $main::form->{TAXID}[$i]->{taxkey_id} .  $::locale->text('. Automatically generated.') .
+        qq|', | . $main::form->{TAXID}[$i]->{taxkey_id} . qq|);
+|;
+      do_query($insertquery);
+      ($tax_id) = $dbh->selectrow_array($query);
+      $tax_id || $main::form->dberror($query);
+    }
+    $updatequery = qq|
+      UPDATE taxkeys SET tax_id= | . $tax_id . qq| WHERE taxkey_id = | . $main::form->{TAXID}[$i]->{taxkey_id} . qq| AND tax_id IS NULL
+|;
+    do_query($updatequery);
+  }
+
+  #The triple taxkey_id, chart_id, startdate in taxkeys has to be unique
+  #Select these entries:
+  $query= <<SQL;
+    SELECT DISTINCT tk1.chart_id AS chart_id, tk1.startdate AS startdate
+    FROM taxkeys tk1
+    WHERE (SELECT count(*)
+           FROM taxkeys tk2
+           WHERE tk2.chart_id  = tk1.chart_id
+           AND   tk2.startdate = tk1.startdate) > 1;
+SQL
+
+  $sth = $dbh->prepare($query);
+  $sth->execute || $main::form->dberror($query);
+
+  $main::form->{TAXKEYS} = [];
+  $rowcount = 0;
+  while (my $ref = $sth->fetchrow_hashref("NAME_lc")) {
+    push @{ $main::form->{TAXKEYS} }, $ref;
+    $rowcount++;
+  }
+  $sth->finish;
+
+  for my $i (0 .. $rowcount-1){
+    $query= qq|
+      DELETE FROM taxkeys tk1
+      WHERE (SELECT count(*)
+            FROM taxkeys tk2
+            WHERE tk2.chart_id  = tk1.chart_id
+            AND   tk2.startdate = tk1.startdate) > 1
+      AND NOT tk1.id = (SELECT id
+                        FROM taxkeys
+                        WHERE chart_id  = | . $main::form->{TAXKEYS}[$i]->{chart_id} . qq|
+                        AND   startdate = '| . $main::form->{TAXKEYS}[$i]->{startdate} . qq|'
+                        LIMIT 1)
+|;
+
+    do_query($query);
+  }
+
+  #END CHECK OF taxkeys
+
+  #ADD CONSTRAINTS:
+  #Now the database is consistent, so we can add constraints:
+  #Crate NOT NULL constraint for tax.rate with default value 0
+  $query= <<SQL;
+    ALTER TABLE tax ALTER COLUMN rate SET NOT NULL;
+    ALTER TABLE tax ALTER COLUMN rate SET DEFAULT 0;
+SQL
+
+  do_query($query);
+
+  #Create NOT NULL constraint for tax.description
+  $query= <<SQL;
+    ALTER TABLE tax ALTER COLUMN taxdescription SET NOT NULL;
+SQL
+
+  do_query($query);
+
+  #Create foreign key for tax.chart_id to chart.id
+  $query= <<SQL;
+    ALTER TABLE tax ADD FOREIGN KEY (chart_id) REFERENCES chart(id);
+SQL
+
+  do_query($query);
+
+  #Create NOT NULL constraint for tax.taxkey
+  $query= <<SQL;
+    ALTER TABLE tax ALTER COLUMN taxkey SET NOT NULL;
+SQL
+
+  do_query($query);
+
+  #Create NOT NULL constraint for taxkey.chart_id and foreign key for taxkey.chart_id
+  $query= <<SQL;
+    ALTER TABLE taxkeys ALTER COLUMN chart_id SET NOT NULL;
+    ALTER TABLE taxkeys ADD FOREIGN KEY (chart_id) REFERENCES chart(id);
+SQL
+
+  do_query($query);
+
+  #Create NOT NULL constraint for taxkey.startdate
+  $query= <<SQL;
+    ALTER TABLE taxkeys ALTER COLUMN startdate SET NOT NULL;
+SQL
+
+  do_query($query);
+
+  #Create NOT NULL constraint for taxkey.taxkey_id
+  $query= <<SQL;
+    ALTER TABLE taxkeys ALTER COLUMN taxkey_id SET NOT NULL;
+SQL
+
+  do_query($query);
+
+  #Create NOT NULL constraint for taxkey.tax_id
+  $query= <<SQL;
+    ALTER TABLE taxkeys ALTER COLUMN tax_id SET NOT NULL;
+SQL
+
+  do_query($query);
+
+  #The triple chart_id, taxkey_id, startdate should be unique:
+  $query= <<SQL;
+    CREATE UNIQUE INDEX taxkeys_chartid_startdate ON taxkeys(chart_id, startdate);
+SQL
+
+  do_query($query);
+  #ALL CONSTRAINTS WERE ADDED
+
+  return 1;
+}; # end do_update
+
+
+sub print_error_message {
+  print $main::form->parse_html_template("dbupgrade/tax_constraints");
+}
+
+return do_update();
index 832bd0f2be3f55feca252992c10c8e327100aef9..e153d2f839bf85a1d619798681f244878e90e695 100644 (file)
@@ -9,7 +9,7 @@
   <table width="100%">
    <tr>
     <td>[% 'tax_taxkey' | $T8 %]</td>
-    <td><input name="taxkey" size="2" value="[% HTML.escape(taxkey) %]"></td>
+    <td><input name="taxkey" size="2" value="[% HTML.escape(taxkey) %]" [% readonly %]></td>
    </tr>
 
    <tr>
@@ -19,7 +19,7 @@
 
    <tr>
     <td>[% 'tax_percent' | $T8 %]</td>
-    <td><input name="rate" size="10" value="[% HTML.escape(rate) %]"> %</td>
+    <td><input name="rate" size="10" value="[% HTML.escape(rate) %]" [% readonly %]> %</td>
    </tr>
 
    <tr>
@@ -42,7 +42,7 @@
 
   <input type="submit" class="submit" name="action" value="[% 'Save' | $T8 %]">
 
-  [% IF orphaned %]
+  [% IF orphaned AND NOT tax_already_used %]
   <input type="submit" class="submit" name="action" value="[% 'Delete' | $T8 %]">
   [% END %]
 
index 2d78134fe9562a8a594b53199fb5eb8053228b84..9d3f696aac29a446134aef08d79c3ac5d926067f 100644 (file)
     <th align="right" nowrap>[% 'Billing/shipping address (city)' | $T8 %]</th>
     <td><input name="addr_city" size="35"></td>
    </tr>
+   <tr>
+    <th align="right" nowrap>[% 'Billing/shipping address (country)' | $T8 %]</th>
+    <td><input name="addr_country" size="35"></td>
+   </tr>
+
    [% IF SHOW_BUSINESS_TYPES %]
    <tr>
     <th align="right" nowrap>[% IF IS_CUSTOMER %][% 'Customer type' | $T8 %][% ELSE %][% 'Vendor type' | $T8 %][% END %]</th>
        <td>
         <input name="l_city" id="l_city" type="checkbox" class="checkbox" value="Y" checked>
         <label for="l_city">[% 'City' | $T8 %]</label>
-      </td>
+       </td>
       </tr>
 
       <tr>
         <label for="l_quonumber">[% IF IS_CUSTOMER %][% 'Quotations' | $T8 %][% ELSE %][% 'RFQs' | $T8 %][% END %]</label>
        </td>
        <td>
+        <input name="l_country" id="l_country" type="checkbox" class="checkbox" value="Y" checked>
+        <label for="l_country">[% 'Country' | $T8 %]</label>
+      </td>
+      </tr>
+      [% IF IS_CUSTOMER %]
+      <tr>
+       <td>
+        <input name="l_salesman" id="l_salesman" type="checkbox" class="checkbox" value="Y">
+        <label for="l_salesman">[% 'Salesman' | $T8 %]</label>
        </td>
       </tr>
+      [% END %]
 
       [% CUSTOM_VARIABLES_INCLUSION_CODE %]
 
diff --git a/templates/webpages/dbupgrade/tax_constraints.html b/templates/webpages/dbupgrade/tax_constraints.html
new file mode 100644 (file)
index 0000000..085e9fb
--- /dev/null
@@ -0,0 +1,53 @@
+[%- USE T8 %]
+[% USE HTML %]<div class="listtop">[% 'Inconsistency in database' | $T8 %]</div>
+
+<form name="Form" method="post" action="login.pl">
+<input type="hidden" name="action" value="login">
+
+<p>[% 'There is an inconsistancy in your database.' | $T8 %]</p>
+<p>[% 'Please contact your administrator.' | $T8 %]</p>
+
+[% IF invalid_tax_account %]
+  <p>[% 'There are invalid taxnumbers in use.' | $T8 %]</p>
+  <p>[% 'Please set another taxnumber for the following taxes and run the update again:' | $T8 %]</p>
+  <table>
+    <tr>
+      <th class="listheading">[% 'tax_taxkey' | $T8 %]</th>
+      <th class="listheading">[% 'tax_taxdescription' | $T8 %]</th>
+      <th class="listheading">[% 'tax_rate' | $T8 %]</th>
+    </tr>
+  
+    [% SET row_odd = '1' %][% FOREACH row = TAX %]
+    <tr class="listrow[% IF row_odd %]1[% SET row_odd = '0' %][% ELSE %]0[% SET row_odd = '1' %][% END %]">
+      <td align="right">[% HTML.escape(row.taxkey) %]</td>
+      <td align="left"> [% HTML.escape(row.taxdescription) %]</a></td>
+      <td align="right">[% HTML.escape(row.rate) %] %</td>
+    </tr>
+    [% END %]
+  </table>
+  
+[% END %]
+  
+[% IF taxkey_is_null %]
+  <p>[% 'There are entries in tax where taxkey is NULL.' | $T8 %]</p>
+  <p>[% 'Please define a taxkey for the following taxes and run the update again:' | $T8 %]</p>
+  <table>
+    <tr>
+      <th class="listheading">[% 'tax_taxdescription' | $T8 %]</th>
+      <th class="listheading">[% 'tax_rate' | $T8 %]</th>
+      <th class="listheading">[% 'taxnumber' | $T8 %]</th>
+      <th class="listheading">[% 'account_description' | $T8 %]</th>
+    </tr>
+  
+    [% SET row_odd = '1' %][% FOREACH row = TAX %]
+    <tr class="listrow[% IF row_odd %]1[% SET row_odd = '0' %][% ELSE %]0[% SET row_odd = '1' %][% END %]">
+      <td align="left"> [% HTML.escape(row.taxdescription) %]</a></td>
+      <td align="right">[% HTML.escape(row.rate) %] %</td>
+      <td align="right">[% HTML.escape(row.taxnumber) %]</td>
+      <td>[% HTML.escape(row.account_description) %]</td>
+    </tr>
+    [% END %]
+  </table>
+  
+[% END %]
+</form>