Merge branch 'master' of github.com:kivitendo/kivitendo-erp
authorJan Büren <jan@kivitendo-premium.de>
Thu, 30 May 2013 11:38:24 +0000 (13:38 +0200)
committerJan Büren <jan@kivitendo-premium.de>
Thu, 30 May 2013 11:38:24 +0000 (13:38 +0200)
Conflicts:
SL/DB/MetaSetup/Default.pm
locale/de/all

1  2 
SL/AM.pm
SL/DB/MetaSetup/Default.pm
SL/DO.pm
SL/IR.pm
SL/IS.pm
SL/InstanceConfiguration.pm
SL/OE.pm
bin/mozilla/ic.pl
locale/de/all

diff --combined SL/AM.pm
+++ b/SL/AM.pm
@@@ -40,6 -40,7 +40,7 @@@ package AM
  use Carp;
  use Data::Dumper;
  use Encode;
+ use List::MoreUtils qw(any);
  use SL::DBUtils;
  
  use strict;
@@@ -207,14 -208,15 +208,15 @@@ sub save_account 
    # connect to database, turn off AutoCommit
    my $dbh = $form->dbconnect_noauto($myconfig);
  
-   # sanity check, can't have AR with AR_...
-   if ($form->{AR} || $form->{AP} || $form->{IC}) {
-     map { delete $form->{$_} }
-       qw(AR_amount AR_tax AR_paid AP_amount AP_tax AP_paid IC_sale IC_cogs IC_taxpart IC_income IC_expense IC_taxservice);
+   for (qw(AR_include_in_dropdown AP_include_in_dropdown summary_account)) {
+     $form->{$form->{$_}} = $form->{$_} if $form->{$_};
    }
  
-   for (qw(AR_include_in_dropdown AP_include_in_dropdown)) {
-     $form->{$form->{$_}} = $form->{$_} if $form->{$_};
+   # sanity check, can't have AR with AR_...
+   if ($form->{AR} || $form->{AP} || $form->{IC}) {
+     if (any { $form->{$_} } qw(AR_amount AR_tax AR_paid AP_amount AP_tax AP_paid IC_sale IC_cogs IC_taxpart IC_income IC_expense IC_taxservice)) {
+       $form->error($::locale->text('It is not allowed that a summary account occurs in a drop-down menu!'));
+     }
    }
  
    $form->{link} = "";
@@@ -1060,10 -1062,6 +1062,6 @@@ sub save_defaults 
    my %accnos;
    map { ($accnos{$_}) = split(m/--/, $form->{$_}) } qw(inventory_accno income_accno expense_accno fxgain_accno fxloss_accno ar_paid_accno);
  
-   $form->{curr}  =~ s/ //g;
-   my @currencies =  grep { $_ ne '' } split m/:/, $form->{curr};
-   my $currency   =  join ':', @currencies;
    # these defaults are database wide
  
    my $query =
          assemblynumber     = ?,
          sdonumber          = ?,
          pdonumber          = ?,
-         curr               = ?,
          businessnumber     = ?,
          weightunit         = ?,
          language_id        = ?|;
                  $form->{articlenumber},   $form->{servicenumber},
                  $form->{assemblynumber},
                  $form->{sdonumber},       $form->{pdonumber},
-                 $currency,
                  $form->{businessnumber},  $form->{weightunit},
                  conv_i($form->{language_id}));
    do_query($form, $dbh, $query, @values);
  
+   $main::lxdebug->message(0, "es gibt rowcount: " . $form->{rowcount});
+   for my $i (1..$form->{rowcount}) {
+     if ($form->{"curr_$i"} ne $form->{"old_curr_$i"}) {
+       $query = qq|UPDATE currencies SET name = ? WHERE name = ?|;
+       do_query($form, $dbh, $query, $form->{"curr_$i"}, $form->{"old_curr_$i"});
+     }
+   }
+   if (length($form->{new_curr}) > 0) {
+     $query = qq|INSERT INTO currencies (name) VALUES (?)|;
+     do_query($form, $dbh, $query, $form->{new_curr});
+   }
    $dbh->commit();
  
    $main::lxdebug->leave_sub();
@@@ -1118,7 -1128,7 +1128,7 @@@ sub save_preferences 
  
    my $dbh = $form->get_standard_dbh($myconfig);
  
-   my ($currency, $businessnumber) = selectrow_query($form, $dbh, qq|SELECT curr, businessnumber FROM defaults|);
+   my ($businessnumber) = selectrow_query($form, $dbh, qq|SELECT businessnumber FROM defaults|);
  
    # update name
    my $query = qq|UPDATE employee SET name = ? WHERE login = ?|;
  
    my $rc = $dbh->commit();
  
-   # save first currency in myconfig
-   $currency               =~ s/:.*//;
-   $form->{currency}       =  $currency;
    $form->{businessnumber} =  $businessnumber;
  
    $myconfig = User->new(login => $form->{login});
@@@ -1286,6 -1292,15 +1292,15 @@@ sub defaultaccounts 
    }
  
    $sth->finish;
+   #Get currencies:
+   $query              = qq|SELECT name AS curr FROM currencies ORDER BY id|;
+   $form->{CURRENCIES} = selectall_hashref_query($form, $dbh, $query);
+   #Which of them is the default currency?
+   $query = qq|SELECT name AS defaultcurrency FROM currencies WHERE id = (SELECT currency_id FROM defaults LIMIT 1);|;
+   ($form->{defaultcurrency}) = selectrow_query($form, $dbh, $query);
    $dbh->disconnect;
  
    $main::lxdebug->leave_sub();
@@@ -2101,10 -2116,9 +2116,10 @@@ sub get_warehouse 
    map { $form->{$_} = $ref->{$_} } keys %{ $ref };
  
    $query = qq|SELECT b.*, EXISTS
 -                (SELECT i.warehouse_id
 -                 FROM inventory i
 +                (SELECT i.warehouse_id, p.warehouse_id
 +                 FROM inventory i, parts p
                   WHERE i.bin_id = b.id
 +                 OR    p.bin_id = b.id
                   LIMIT 1)
                  AS in_use
                FROM bin b
@@@ -20,7 -20,6 +20,6 @@@ __PACKAGE__->meta->setup
      weightunit                          => { type => 'varchar', length => 5 },
      businessnumber                      => { type => 'text' },
      version                             => { type => 'varchar', length => 8 },
-     curr                                => { type => 'text' },
      closedto                            => { type => 'date' },
      revtrans                            => { type => 'boolean', default => 'false' },
      ponumber                            => { type => 'text' },
      ar_show_mark_as_paid                => { type => 'boolean', default => 'true' },
      ap_show_mark_as_paid                => { type => 'boolean', default => 'true' },
      assemblynumber                      => { type => 'text' },
 +    warehouse_id                        => { type => 'integer' },
 +    bin_id                              => { type => 'integer' },
+     currency_id                         => { type => 'integer', not_null => 1 },
    ],
  
    primary_key_columns => [ 'id' ],
  
+   allow_inline_column_values => 1,
    foreign_keys => [
 +    bin => {
 +      class       => 'SL::DB::Bin',
 +      key_columns => { bin_id => 'id' },
 +    },
 +
 +    warehouse => {
 +      class       => 'SL::DB::Warehouse',
 +      key_columns => { warehouse_id => 'id' },
++
+     currency => {
+       class       => 'SL::DB::Currency',
+       key_columns => { currency_id => 'id' },
      },
    ],
  );
diff --combined SL/DO.pm
+++ b/SL/DO.pm
@@@ -229,7 -229,7 +229,7 @@@ sub save 
      $query = qq|SELECT nextval('id')|;
      ($form->{id}) = selectrow_query($form, $dbh, $query);
  
-     $query = qq|INSERT INTO delivery_orders (id, donumber, employee_id) VALUES (?, '', ?)|;
+     $query = qq|INSERT INTO delivery_orders (id, donumber, employee_id, currency_id) VALUES (?, '', ?, (SELECT currency_id FROM defaults LIMIT 1))|;
      do_query($form, $dbh, $query, $form->{id}, conv_i($form->{employee_id}));
    }
  
           shippingpoint = ?, shipvia = ?, notes = ?, intnotes = ?, closed = ?,
           delivered = ?, department_id = ?, language_id = ?, shipto_id = ?,
           globalproject_id = ?, employee_id = ?, salesman_id = ?, cp_id = ?, transaction_description = ?,
-          is_sales = ?, taxzone_id = ?, taxincluded = ?, terms = ?, curr = ?
+          is_sales = ?, taxzone_id = ?, taxincluded = ?, terms = ?, currency_id = (SELECT id FROM currencies WHERE name = ?)
         WHERE id = ?|;
  
    @values = ($form->{donumber}, $form->{ordnumber},
               conv_i($form->{salesman_id}), conv_i($form->{cp_id}),
               $form->{transaction_description},
               $form->{type} =~ /^sales/ ? 't' : 'f',
-              conv_i($form->{taxzone_id}), $form->{taxincluded} ? 't' : 'f', conv_i($form->{terms}), substr($form->{currency}, 0, 3),
+              conv_i($form->{taxzone_id}), $form->{taxincluded} ? 't' : 'f', conv_i($form->{terms}), $form->{currency},
               conv_i($form->{id}));
    do_query($form, $dbh, $query, @values);
  
@@@ -618,7 -618,7 +618,7 @@@ sub retrieve 
           d.description AS department, dord.language_id,
           dord.shipto_id,
           dord.globalproject_id, dord.delivered, dord.transaction_description,
-          dord.taxzone_id, dord.taxincluded, dord.terms, dord.curr AS currency
+          dord.taxzone_id, dord.taxincluded, dord.terms, (SELECT cu.name FROM currencies cu WHERE cu.id=dord.currency_id) AS currency
         FROM delivery_orders dord
         JOIN ${vc} cv ON (dord.${vc}_id = cv.id)
         LEFT JOIN employee e ON (dord.employee_id = e.id)
    }
    $sth->finish();
  
-   # remove any trailing whitespace
-   $form->{currency} =~ s/\s*$//;
    $form->{donumber_array} =~ s/\s*$//g;
  
    $form->{saved_donumber} = $form->{donumber};
    $query =
      qq|SELECT doi.id AS delivery_order_items_id,
           p.partnumber, p.assembly, p.listprice, doi.description, doi.qty,
 -         doi.sellprice, doi.parts_id AS id, doi.unit, doi.discount, p.bin, p.notes AS partnotes,
 +         doi.sellprice, doi.parts_id AS id, doi.unit, doi.discount, p.notes AS partnotes,
           doi.reqdate, doi.project_id, doi.serialnumber, doi.lastcost,
           doi.ordnumber, doi.transdate, doi.cusordnumber, doi.longdescription,
           doi.price_factor_id, doi.price_factor, doi.marge_price_factor, doi.pricegroup_id,
diff --combined SL/IR.pm
+++ b/SL/IR.pm
@@@ -57,6 -57,7 +57,7 @@@ sub post_invoice 
    # connect to database, turn off autocommit
    my $dbh = $provided_dbh ? $provided_dbh : $form->dbconnect_noauto($myconfig);
    $form->{defaultcurrency} = $form->get_default_currency($myconfig);
+   my $defaultcurrency = $form->{defaultcurrency};
  
    my $ic_cvar_configs = CVar->get_configs(module => 'IC',
                                            dbh    => $dbh);
  
    my $all_units = AM->retrieve_units($myconfig, $form);
  
+ #markierung
    if (!$payments_only) {
      if ($form->{id}) {
        &reverse_invoice($dbh, $form);
      } else {
        ($form->{id}) = selectrow_query($form, $dbh, qq|SELECT nextval('glid')|);
-       do_query($form, $dbh, qq|INSERT INTO ap (id, invnumber) VALUES (?, '')|, $form->{id});
+       do_query($form, $dbh, qq|INSERT INTO ap (id, invnumber, currency_id) VALUES (?, '', (SELECT id FROM currencies WHERE name=?))|, $form->{id}, $form->{currency});
      }
    }
  
-   my ($currencies)    = selectfirst_array_query($form, $dbh, qq|SELECT curr FROM defaults|);
-   my $defaultcurrency = (split m/:/, $currencies)[0];
    if ($form->{currency} eq $defaultcurrency) {
      $form->{exchangerate} = 1;
    } else {
                  orddate      = ?, quodate     = ?, vendor_id     = ?, amount      = ?,
                  netamount    = ?, paid        = ?, duedate       = ?,
                  invoice      = ?, taxzone_id  = ?, notes         = ?, taxincluded = ?,
-                 intnotes     = ?, curr        = ?, storno_id     = ?, storno      = ?,
+                 intnotes     = ?, storno_id   = ?, storno        = ?,
                  cp_id        = ?, employee_id = ?, department_id = ?,
                  globalproject_id = ?, direct_debit = ?
                WHERE id = ?|;
        conv_date($form->{orddate}), conv_date($form->{quodate}),     conv_i($form->{vendor_id}),               $amount,
                  $netamount,                  $form->{paid},      conv_date($form->{duedate}),
              '1',                             $taxzone_id,                  $form->{notes},          $form->{taxincluded} ? 't' : 'f',
-                 $form->{intnotes},           $form->{currency},     conv_i($form->{storno_id}),     $form->{storno}      ? 't' : 'f',
+                 $form->{intnotes},           conv_i($form->{storno_id}),     $form->{storno}      ? 't' : 'f',
           conv_i($form->{cp_id}),      conv_i($form->{employee_id}), conv_i($form->{department_id}),
           conv_i($form->{globalproject_id}),
                  $form->{direct_debit} ? 't' : 'f',
@@@ -925,8 -924,7 +924,7 @@@ sub retrieve_invoice 
                 (SELECT c.accno FROM chart c WHERE d.income_accno_id = c.id)    AS income_accno,
                 (SELECT c.accno FROM chart c WHERE d.expense_accno_id = c.id)   AS expense_accno,
                 (SELECT c.accno FROM chart c WHERE d.fxgain_accno_id = c.id)    AS fxgain_accno,
-                (SELECT c.accno FROM chart c WHERE d.fxloss_accno_id = c.id)    AS fxloss_accno,
-                d.curr AS currencies
+                (SELECT c.accno FROM chart c WHERE d.fxloss_accno_id = c.id)    AS fxloss_accno
                 $q_invdate
                 FROM defaults d|;
    $ref = selectfirst_hashref_query($form, $dbh, $query);
    $query = qq|SELECT cp_id, invnumber, transdate AS invdate, duedate,
                  orddate, quodate, globalproject_id,
                  ordnumber, quonumber, paid, taxincluded, notes, taxzone_id, storno, gldate,
-                 intnotes, curr AS currency, direct_debit
+                 intnotes, (SELECT cu.name FROM currencies cu WHERE cu.id=ap.currency_id) AS currency, direct_debit
                FROM ap
                WHERE id = ?|;
    $ref = selectfirst_hashref_query($form, $dbh, $query, conv_i($form->{id}));
    map { $form->{$_} = $ref->{$_} } keys %$ref;
  
-   # remove any trailing whitespace
-   $form->{currency} =~ s/\s*$//;
    $form->{exchangerate}  = $form->get_exchangerate($dbh, $form->{currency}, $form->{invdate}, "sell");
  
    # get shipto
          i.id AS invoice_id,
          i.description, i.longdescription, i.qty, i.fxsellprice AS sellprice, i.parts_id AS id, i.unit, i.deliverydate, i.project_id, i.serialnumber,
          i.price_factor_id, i.price_factor, i.marge_price_factor, i.discount,
 -        p.partnumber, p.inventory_accno_id AS part_inventory_accno_id, p.bin, pr.projectnumber, pg.partsgroup
 +        p.partnumber, p.inventory_accno_id AS part_inventory_accno_id,  pr.projectnumber, pg.partsgroup
  
          FROM invoice i
          JOIN parts p ON (i.parts_id = p.id)
@@@ -1093,21 -1088,19 +1088,19 @@@ sub get_vendor 
           v.id AS vendor_id, v.name AS vendor, v.discount as vendor_discount,
           v.creditlimit, v.terms, v.notes AS intnotes,
           v.email, v.cc, v.bcc, v.language_id, v.payment_id,
-          v.street, v.zipcode, v.city, v.country, v.taxzone_id, v.curr, v.direct_debit,
+          v.street, v.zipcode, v.city, v.country, v.taxzone_id, cu.name AS curr, v.direct_debit,
           $duedate + COALESCE(pt.terms_netto, 0) AS duedate,
           b.description AS business
         FROM vendor v
         LEFT JOIN business b       ON (b.id = v.business_id)
         LEFT JOIN payment_terms pt ON (v.payment_id = pt.id)
+        LEFT JOIN currencies cu    ON (v.currency_id = cu.id)
         WHERE 1=1 $where|;
    my $ref = selectfirst_hashref_query($form, $dbh, $query, @values);
    map { $params->{$_} = $ref->{$_} } keys %$ref;
  
-   # remove any trailing whitespace
-   $form->{curr} =~ s/\s*$//;
-   # use vendor currency if not empty
-   $form->{currency} = $form->{curr} if $form->{curr};
+   # use vendor currency
+   $form->{currency} = $form->{curr};
  
    $params->{creditremaining} = $params->{creditlimit};
  
    $query = qq|SELECT o.amount,
                  (SELECT e.sell
                   FROM exchangerate e
-                  WHERE (e.curr = o.curr)
+                  WHERE (e.currency_id = o.currency_id)
                     AND (e.transdate = o.transdate)) AS exch
                FROM oe o
                WHERE (o.vendor_id = ?) AND (o.quotation = '0') AND (o.closed = '0')|;
@@@ -1234,7 -1227,7 +1227,7 @@@ sub retrieve_item 
    my $query =
      qq|SELECT
           p.id, p.partnumber, p.description, p.lastcost AS sellprice, p.listprice,
 -         p.unit, p.assembly, p.bin, p.onhand, p.formel,
 +         p.unit, p.assembly, p.onhand, p.formel,
           p.notes AS partnotes, p.notes AS longdescription, p.not_discountable,
           p.inventory_accno_id, p.price_factor_id,
  
@@@ -1393,9 -1386,10 +1386,10 @@@ sub vendor_details 
    # fax and phone and email as vendor*
    my $query =
      qq|SELECT ct.*, cp.*, ct.notes as vendornotes, phone as vendorphone, fax as vendorfax, email as vendoremail,
-          ct.curr AS currency
+          cu.name AS currency
         FROM vendor ct
         LEFT JOIN contacts cp ON (ct.id = cp.cp_cv_id)
+        LEFT JOIN currencies cu ON (ct.currency_id = cu.id)
         WHERE (ct.id = ?) $contact
         ORDER BY cp.cp_id
         LIMIT 1|;
    }
  
    map { $form->{$_} = $ref->{$_} } keys %$ref;
-   # remove any trailing whitespace
-   $form->{currency} =~ s/\s*$// if ($form->{currency});
  
    my $custom_variables = CVar->get_custom_variables('dbh'      => $dbh,
                                                      'module'   => 'CT',
diff --combined SL/IS.pm
+++ b/SL/IS.pm
@@@ -458,9 -458,10 +458,10 @@@ sub customer_details 
    my $query =
      qq|SELECT ct.*, cp.*, ct.notes as customernotes,
           ct.phone AS customerphone, ct.fax AS customerfax, ct.email AS customeremail,
-          ct.curr AS currency
+          cu.name AS currency
         FROM customer ct
         LEFT JOIN contacts cp on ct.id = cp.cp_cv_id
+        LEFT JOIN currencies cu ON (ct.currency_id = cu.id)
         WHERE (ct.id = ?) $where
         ORDER BY cp.cp_id
         LIMIT 1|;
  
    map { $form->{$_} = $ref->{$_} } keys %$ref;
  
-   # remove any trailing whitespace
-   $form->{currency} =~ s/\s*$// if ($form->{currency});
    if ($form->{delivery_customer_id}) {
      $query =
        qq|SELECT *, notes as customernotes
@@@ -536,6 -534,8 +534,8 @@@ sub post_invoice 
    }
  
    $form->{defaultcurrency} = $form->get_default_currency($myconfig);
+   my $defaultcurrency = $form->{defaultcurrency};
    # Seit neuestem wird die department_id schon übergeben UND $form->department nicht mehr
    # korrekt zusammengebaut. Sehr wahrscheinlich beim Umstieg auf T8 kaputt gegangen
    # Ich lass den Code von 2005 erstmal noch stehen ;-) jb 03-2011
        $query = qq|SELECT nextval('glid')|;
        ($form->{"id"}) = selectrow_query($form, $dbh, $query);
  
-       $query = qq|INSERT INTO ar (id, invnumber) VALUES (?, ?)|;
-       do_query($form, $dbh, $query, $form->{"id"}, $form->{"id"});
+       $query = qq|INSERT INTO ar (id, invnumber, currency_id) VALUES (?, ?, (SELECT id FROM currencies WHERE name=?))|;
+       do_query($form, $dbh, $query, $form->{"id"}, $form->{"id"}, $form->{currency});
  
        if (!$form->{invnumber}) {
          $form->{invnumber} =
    my ($netamount, $invoicediff) = (0, 0);
    my ($amount, $linetotal, $lastincomeaccno);
  
-   my ($currencies)    = selectfirst_array_query($form, $dbh, qq|SELECT curr FROM defaults|);
-   my $defaultcurrency = (split m/:/, $currencies)[0];
    if ($form->{currency} eq $defaultcurrency) {
      $form->{exchangerate} = 1;
    } else {
                  amount      = ?, netamount     = ?, paid          = ?,
                  duedate     = ?, deliverydate  = ?, invoice       = ?, shippingpoint = ?,
                  shipvia     = ?, terms         = ?, notes         = ?, intnotes      = ?,
-                 curr        = ?, department_id = ?, payment_id    = ?, taxincluded   = ?,
+                 currency_id = (SELECT id FROM currencies WHERE name = ?),
+                 department_id = ?, payment_id    = ?, taxincluded   = ?,
                  type        = ?, language_id   = ?, taxzone_id    = ?, shipto_id     = ?,
                  employee_id = ?, salesman_id   = ?, storno_id     = ?, storno        = ?,
                  cp_id       = ?, marge_total   = ?, marge_percent = ?,
@@@ -1559,8 -1557,7 +1557,7 @@@ sub retrieve_invoice 
           (SELECT c.accno FROM chart c WHERE d.income_accno_id = c.id)    AS income_accno,
           (SELECT c.accno FROM chart c WHERE d.expense_accno_id = c.id)   AS expense_accno,
           (SELECT c.accno FROM chart c WHERE d.fxgain_accno_id = c.id)    AS fxgain_accno,
-          (SELECT c.accno FROM chart c WHERE d.fxloss_accno_id = c.id)    AS fxloss_accno,
-          d.curr AS currencies
+          (SELECT c.accno FROM chart c WHERE d.fxloss_accno_id = c.id)    AS fxloss_accno
           ${query_transdate}
         FROM defaults d|;
  
             a.orddate, a.quodate, a.globalproject_id,
             a.transdate AS invdate, a.deliverydate, a.paid, a.storno, a.gldate,
             a.shippingpoint, a.shipvia, a.terms, a.notes, a.intnotes, a.taxzone_id,
-            a.duedate, a.taxincluded, a.curr AS currency, a.shipto_id, a.cp_id,
+            a.duedate, a.taxincluded, (SELECT cu.name FROM currencies cu WHERE cu.id=a.currency_id) AS currency, a.shipto_id, a.cp_id,
             a.employee_id, a.salesman_id, a.payment_id,
             a.language_id, a.delivery_customer_id, a.delivery_vendor_id, a.type,
             a.transaction_description, a.donumber, a.invnumber_for_credit_note,
      $ref = selectfirst_hashref_query($form, $dbh, $query, $id);
      map { $form->{$_} = $ref->{$_} } keys %{ $ref };
  
-     # remove any trailing whitespace
-     $form->{currency} =~ s/\s*$//;
      $form->{exchangerate} = $form->get_exchangerate($dbh, $form->{currency}, $form->{invdate}, "buy");
  
      # get shipto
             i.description, i.longdescription, i.qty, i.fxsellprice AS sellprice, i.discount, i.parts_id AS id, i.unit, i.deliverydate AS reqdate,
             i.project_id, i.serialnumber, i.id AS invoice_pos, i.pricegroup_id, i.ordnumber, i.transdate, i.cusordnumber, i.subtotal, i.lastcost,
             i.price_factor_id, i.price_factor, i.marge_price_factor,
 -           p.partnumber, p.assembly, p.bin, p.notes AS partnotes, p.inventory_accno_id AS part_inventory_accno_id, p.formel, p.listprice,
 +           p.partnumber, p.assembly, p.notes AS partnotes, p.inventory_accno_id AS part_inventory_accno_id, p.formel, p.listprice,
             pr.projectnumber, pg.partsgroup, prg.pricegroup
  
           FROM invoice i
@@@ -1758,13 -1752,14 +1752,14 @@@ sub get_customer 
           c.id AS customer_id, c.name AS customer, c.discount as customer_discount, c.creditlimit, c.terms,
           c.email, c.cc, c.bcc, c.language_id, c.payment_id,
           c.street, c.zipcode, c.city, c.country,
-          c.notes AS intnotes, c.klass as customer_klass, c.taxzone_id, c.salesman_id, c.curr,
+          c.notes AS intnotes, c.klass as customer_klass, c.taxzone_id, c.salesman_id, cu.name AS curr,
           c.taxincluded_checked, c.direct_debit,
           $duedate + COALESCE(pt.terms_netto, 0) AS duedate,
           b.discount AS tradediscount, b.description AS business
         FROM customer c
         LEFT JOIN business b ON (b.id = c.business_id)
         LEFT JOIN payment_terms pt ON ($payment_id (c.payment_id = pt.id))
+        LEFT JOIN currencies cu ON (c.currency_id=cu.id)
         WHERE c.id = ?|;
    push @values, $cid;
    $ref = selectfirst_hashref_query($form, $dbh, $query, @values);
  
    map { $form->{$_} = $ref->{$_} } keys %$ref;
  
-   # remove any trailing whitespace
-   $form->{curr} =~ s/\s*$//;
-   # use customer currency if not empty
-   $form->{currency} = $form->{curr} if $form->{curr};
+   # use customer currency
+   $form->{currency} = $form->{curr};
  
    $query =
      qq|SELECT sum(amount - paid) AS dunning_amount
    $query =
      qq|SELECT o.amount,
           (SELECT e.buy FROM exchangerate e
-           WHERE e.curr = o.curr
+           WHERE e.currency_id = o.currency_id
              AND e.transdate = o.transdate)
         FROM oe o
         WHERE o.customer_id = ?
@@@ -1946,7 -1938,7 +1938,7 @@@ sub retrieve_item 
           c3.new_chart_id AS expense_new_chart,
           date($transdate) - c3.valid_from AS expense_valid,
  
 -         p.unit, p.assembly, p.bin, p.onhand,
 +         p.unit, p.assembly, p.onhand,
           p.notes AS partnotes, p.notes AS longdescription,
           p.not_discountable, p.formel, p.payment_id AS part_payment_id,
           p.price_factor_id,
@@@ -15,9 -15,9 +15,9 @@@ sub init 
  
    $self->{data} = selectfirst_hashref_query($::form, $::form->get_standard_dbh, qq|SELECT * FROM defaults|);
  
-   my $curr            =  $self->{data}->{curr} || '';
-   $curr               =~ s/\s+//g;
-   $self->{currencies} =  [ split m/:/, $curr ];
+   #To get all currencies and the default currency:
+   ($self->{data}->{curr}) = selectrow_query($::form, $::form->get_standard_dbh, qq|SELECT name AS curr FROM currencies WHERE id = (SELECT currency_id FROM defaults)|);
+   $self->{currencies}     = [ map { $_->{name} } selectall_hashref_query($::form, $::form->get_standard_dbh, qq|SELECT name FROM currencies ORDER BY id|) ];
  
    return $self;
  }
  sub get_default_currency {
    my ($self) = @_;
  
-   return ($self->get_currencies)[0];
+   return $self->{data}->{curr};
  }
  
  sub get_currencies {
    my ($self) = @_;
  
-   return $self->{currencies} ? @{ $self->{currencies} } : ();
+   return @{ $self->{currencies} };
  }
  
  sub get_accounting_method {
@@@ -144,16 -144,6 +144,16 @@@ sub get_purchase_delivery_order_show_de
    return $self->{data}->{purchase_delivery_order_show_delete};
  }
  
 +sub get_default_warehouse_id {
 +  my ($self) = @_;
 +  return ($self->{data}->{warehouse_id});
 +}
 +
 +sub get_default_bin_id {
 +  my ($self) = @_;
 +  return ($self->{data}->{bin_id});
 +}
 +
  1;
  
  __END__
@@@ -266,14 -256,6 +266,14 @@@ corresponding record type (true or fals
  Returns the default behavior for showing the delete button for the
  corresponding record type (true or false).
  
 +=item C<get_default_warehouse_id>
 +
 +Returns the default warehouse_id
 +
 +=item C<get_default_bin_id>
 +
 +Returns the default bin_id
 +
  =back
  
  =head1 BUGS
diff --combined SL/OE.pm
+++ b/SL/OE.pm
@@@ -91,7 -91,7 +91,7 @@@ sub transactions 
      qq|JOIN $vc ct ON (o.${vc}_id = ct.id) | .
      qq|LEFT JOIN employee e ON (o.employee_id = e.id) | .
      qq|LEFT JOIN employee s ON (o.salesman_id = s.id) | .
-     qq|LEFT JOIN exchangerate ex ON (ex.curr = o.curr | .
+     qq|LEFT JOIN exchangerate ex ON (ex.currency_id = o.currency_id | .
      qq|  AND ex.transdate = o.transdate) | .
      qq|LEFT JOIN project pr ON (o.globalproject_id = pr.id) | .
      qq|$periodic_invoices_joins | .
@@@ -311,7 -311,7 +311,7 @@@ sub save 
      $query = qq|SELECT nextval('id')|;
      ($form->{id}) = selectrow_query($form, $dbh, $query);
  
-     $query = qq|INSERT INTO oe (id, ordnumber, employee_id) VALUES (?, '', ?)|;
+     $query = qq|INSERT INTO oe (id, ordnumber, employee_id, currency_id) VALUES (?, '', ?, (SELECT currency_id FROM defaults))|;
      do_query($form, $dbh, $query, $form->{id}, $form->{employee_id});
    }
  
      qq|UPDATE oe SET
           ordnumber = ?, quonumber = ?, cusordnumber = ?, transdate = ?, vendor_id = ?,
           customer_id = ?, amount = ?, netamount = ?, reqdate = ?, taxincluded = ?,
-          shippingpoint = ?, shipvia = ?, notes = ?, intnotes = ?, curr = ?, closed = ?,
+          shippingpoint = ?, shipvia = ?, notes = ?, intnotes = ?, currency_id = (SELECT id FROM currencies WHERE name=?), closed = ?,
           delivered = ?, proforma = ?, quotation = ?, department_id = ?, language_id = ?,
           taxzone_id = ?, shipto_id = ?, payment_id = ?, delivery_vendor_id = ?, delivery_customer_id = ?,
           globalproject_id = ?, employee_id = ?, salesman_id = ?, cp_id = ?, transaction_description = ?, marge_total = ?, marge_percent = ?
               $amount, $netamount, conv_date($reqdate),
               $form->{taxincluded} ? 't' : 'f', $form->{shippingpoint},
               $form->{shipvia}, $form->{notes}, $form->{intnotes},
-              substr($form->{currency}, 0, 3), $form->{closed} ? 't' : 'f',
+              $form->{currency}, $form->{closed} ? 't' : 'f',
               $form->{delivered} ? "t" : "f", $form->{proforma} ? 't' : 'f',
               $quotation, conv_i($form->{department_id}),
               conv_i($form->{language_id}), conv_i($form->{taxzone_id}),
@@@ -759,14 -759,13 +759,13 @@@ sub retrieve 
                       (SELECT c.accno FROM chart c WHERE d.income_accno_id    = c.id) AS income_accno,
                       (SELECT c.accno FROM chart c WHERE d.expense_accno_id   = c.id) AS expense_accno,
                       (SELECT c.accno FROM chart c WHERE d.fxgain_accno_id    = c.id) AS fxgain_accno,
-                      (SELECT c.accno FROM chart c WHERE d.fxloss_accno_id    = c.id) AS fxloss_accno,
-               d.curr AS currencies
+                      (SELECT c.accno FROM chart c WHERE d.fxloss_accno_id    = c.id) AS fxloss_accno
                $query_add
                FROM defaults d|;
    my $ref = selectfirst_hashref_query($form, $dbh, $query);
    map { $form->{$_} = $ref->{$_} } keys %$ref;
  
-   ($form->{currency}) = split(/:/, $form->{currencies}) unless ($form->{currency});
+   $form->{currency} = $form->get_default_currency($myconfig);
  
    # set reqdate if this is an invoice->order conversion. If someone knows a better check to ensure
    # we come from invoices, feel free.
      $query =
        qq|SELECT o.cp_id, o.ordnumber, o.transdate, o.reqdate,
             o.taxincluded, o.shippingpoint, o.shipvia, o.notes, o.intnotes,
-            o.curr AS currency, e.name AS employee, o.employee_id, o.salesman_id,
+            (SELECT cu.name FROM currencies cu WHERE cu.id=o.currency_id) AS currency, e.name AS employee, o.employee_id, o.salesman_id,
             o.${vc}_id, cv.name AS ${vc}, o.amount AS invtotal,
             o.closed, o.reqdate, o.quonumber, o.department_id, o.cusordnumber,
             d.description AS department, o.payment_id, o.language_id, o.taxzone_id,
      if ($ref) {
        map { $form->{$_} = $ref->{$_} } keys %$ref;
  
-       # remove any trailing whitespace
-       $form->{currency} =~ s/\s*$//;
        $form->{saved_xyznumber} = $form->{$form->{type} =~ /_quotation$/ ? "quonumber" : "ordnumber"};
  
        # set all entries for multiple ids blank that yield different information
             c3.accno AS expense_accno,   c3.new_chart_id AS expense_new_chart,   date($transdate) - c3.valid_from as expense_valid,
             oe.ordnumber AS ordnumber_oe, oe.transdate AS transdate_oe, oe.cusordnumber AS cusordnumber_oe,
             p.partnumber, p.assembly, p.listprice, o.description, o.qty,
 -           o.sellprice, o.parts_id AS id, o.unit, o.discount, p.bin, p.notes AS partnotes, p.inventory_accno_id AS part_inventory_accno_id,
 +           o.sellprice, o.parts_id AS id, o.unit, o.discount, p.notes AS partnotes, p.inventory_accno_id AS part_inventory_accno_id,
             o.reqdate, o.project_id, o.serialnumber, o.ship, o.lastcost,
             o.ordnumber, o.transdate, o.cusordnumber, o.subtotal, o.longdescription,
             o.price_factor_id, o.price_factor, o.marge_price_factor,
diff --combined bin/mozilla/ic.pl
@@@ -1489,8 -1489,7 +1489,7 @@@ sub link_part 
    IC->create_links("IC", \%myconfig, \%$form);
  
    # currencies
-   map({ $form->{selectcurrency} .= "<option>$_\n" }
-       split(/:/, $form->{currencies}));
+   map({ $form->{selectcurrency} .= "<option>$_\n" } $::form->get_all_currencies());
  
    # parts and assemblies have the same links
    my $item = $form->{item};
@@@ -1586,20 -1585,7 +1585,20 @@@ sub form_header 
  
    $form->get_lists('price_factors' => 'ALL_PRICE_FACTORS',
                     'partsgroup'    => 'all_partsgroup',
 -                   'vendors'       => 'ALL_VENDORS',);
 +                   'vendors'       => 'ALL_VENDORS',
 +                   'warehouses'    => { 'key'    => 'WAREHOUSES',
 +                                        'bins'   => 'BINS', });
 +  # leerer wert für Lager und Lagerplatz korrekt einstellt
 +  # ID 0 sollte in Ordnung sein, da der Zähler sowieso höher ist
 +  my $no_default_bin_entry = { 'id' => '0', description => '--', 'BINS' => [ { id => '0', description => ''} ] };
 +  push @ { $form->{WAREHOUSES} }, $no_default_bin_entry;
 +  if (my $max = scalar @{ $form->{WAREHOUSES} }) {
 +
 +    my $default_warehouse_id = $::instance_conf->get_default_warehouse_id;
 +    my $default_bin_id       = $::instance_conf->get_default_bin_id;
 +    $form->{warehouse_id} ||= $default_warehouse_id || $form->{WAREHOUSES}->[$max -1]->{id};
 +    $form->{bin_id}       ||= $default_bin_id       ||  $form->{WAREHOUSES}->[$max -1]->{BINS}->[0]->{id};
 +  }
  
  
    IC->retrieve_buchungsgruppen(\%myconfig, $form);
@@@ -1860,11 -1846,6 +1859,11 @@@ sub save 
    $form->error($locale->text('Description must not be empty!')) unless $form->{description};
    $form->error($locale->text('Partnumber must not be set to empty!')) if $form->{id} && !$form->{partnumber};
  
 +  # undef warehouse_id if the empty value is selected
 +  if ( ($form->{warehouse_id} == 0) && ($form->{bin_id} == 0) ) {
 +    undef $form->{warehouse_id};
 +    undef $form->{bin_id};
 +  }
    # save part
    if (IC->save(\%myconfig, \%$form) == 3) {
      $form->error($locale->text('Partnumber not unique!'));
diff --combined locale/de/all
@@@ -18,6 -18,7 +18,7 @@@ $self->{texts} = 
    '#1 h'                        => '#1 h',
    '#1 of #2 importable objects were imported.' => '#1 von #2 importierbaren Objekten wurden importiert.',
    '#1 prices were updated.'     => '#1 Preise wurden aktualisiert.',
+   '(recommended) Insert the used currencies in the system. You can simply change the name of the currencies by editing the textfields above. Do not use a name of a currency that is already in use.' => '(empfohlen) Fügen Sie die verwaisten Währungen in Ihr System ein. Sie können den Namen der Währung einfach ändern, indem Sie die Felder oben bearbeiten. Benutzen Sie keine Namen von Währungen, die Sie bereits benutzen.',
    '* there are restrictions for the perpetual method, look at chapter "Bemerkungen zu Bestandsmethode"  in' => ' für die Bestandsmethode gibt es Einschränkungen, siehe Kapitel "Bemerkungen zu Bestandsmethode"  in',
    '*) 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:',
    '*/'                          => '*/',
    '2. Quarter'                  => '2. Quartal',
    '3. Quarter'                  => '3. Quartal',
    '4. Quarter'                  => '4. Quartal',
 +  '<b> I DO CARE!</b> Please check create warehouse and bins and define a name for the warehouse (Bins will be created automatically) and then continue' => '<b>ICH KÜMMER MICH</b> Bitte haken Sie Lager und Lagerplätze erzeugen an (Automatisches Zuweisen der Lagerplätze) und vergeben einen Namen für dieses Lager (Lagerplätze werden automatisch übernommen). Danach auf weiter.',
 +  '<b> I DO CARE!</b> Please click back and cancel the update and come back after there has been at least one warehouse defined with bin(s).:' => '<b>ICH KÜMMER MICH</b> Brechen Sie das Update ab und legen selber mindestens ein Lager mit Lagerplätzen unter dem Menü System / Lager an.',
 +  '<b> I DO NOT CARE</b> Please click continue and the following data (see list) will be deleted:' => '<b>IST MIR EGAL</b> Mit einem Klick auf Weiter (rot) werden keine Daten übernommen, bzw. migriert und die folgende Information in der untenstehenden Liste wird gelöscht.',
 +  '<b>Automatically create new bins</b> in the following new warehouse ' => '<b>Automatisches Zuweisen der Lagerplätze</b> im folgenden neuem Lager:',
 +  '<b>Automatically create new bins</b> in the following warehouse if not selected in the list above' => '<b>Automatisches Zuweisen der Lagerplätze</b> im folgenden Lager, falls keine andere Zuweisung oben ausgewählt ist. ',
 +  '<b>Default Bins Migration !READ CAREFULLY!</b>' => 'Standardlagerplatz Migraition !AUFMERKSAM LESEN!',
    '<b>What</b> do you want to look for?' => '<b>Wonach</b> wollen Sie suchen?',
    'A Buchungsgruppe consists of a descriptive name and the account numbers for the income and expense accounts for those four tax zones as well as the inventory account number.' => 'Eine Buchungsgruppe besteht aus einem deskriptiven Namen, den Erl&ouml;s- und Aufwandskonten f&uuml;r diese vier Steuerzonen sowie aus einem Inventarkonto.',
    'A digit is required.'        => 'Eine Ziffer ist vorgeschrieben.',
@@@ -71,7 -66,6 +72,7 @@@
    'ASSETS'                      => 'AKTIVA',
    'ATTENTION! If you enabled this feature you can not simply turn it off again without taking care that best_before fields are emptied in the database.' => 'ACHTUNG! Wenn Sie diese Einstellung aktivieren, dann können Sie sie später nicht ohne Weiteres deaktivieren, ohne dafür zu sorgen, dass die Felder der Mindeshaltbarkeitsdaten in der Datenbank leer gemacht werden.',
    'ATTENTION! You can not simply change it from periodic to perpetual once you started posting.' => 'ACHTUNG! Es kann nicht ohne Weiteres im laufenden Betrieb von der Aufwandsmethode zur Bestandsmethode gewechselt werden.',
 +  'AUTOMATICALLY MATCH BINS'    => 'LAGERPLÄTZE AUTOMATISCH ZUWEISEN',
    'Abort'                       => 'Abbrechen',
    'Abrechnungsnummer'           => 'Abrechnungsnummer',
    'Abteilung'                   => 'Abteilung',
    'Both'                        => 'Beide',
    'Bottom'                      => 'Unten',
    'Bought'                      => 'Gekauft',
+   'Break up the update and contact a service provider.' => 'Diese Option bricht das Update ab. Bitte kontaktieren Sie Ihren Administrator oder beauftragen einen Dienstleister.',
    'Buchungsdatum'               => 'Buchungsdatum',
    'Buchungsgruppe'              => 'Buchungsgruppe',
    'Buchungsgruppe (database ID)' => 'Buchungsgruppe (Datenbank-ID)',
    'Cash'                        => 'Zahlungsverkehr',
    'Cc'                          => 'Cc',
    'Cc E-mail'                   => 'CC (E-Mail)',
 +  'Change default bin for this parts' => 'Standardlagerplatz für diese Waren ändern',
    'Change kivitendo installation settings (all menu entries beneath \'System\')' => 'Ver&auml;ndern der kivitendo-Installationseinstellungen (Men&uuml;punkte unterhalb von \'System\')',
    'Change representative to'    => 'Vertreter ändern in',
    'Changes in this block are only sensible if the account is NOT a summary account AND there exists one valid taxkey. To select both Receivables and Payables only make sense for Payment / Receipt (i.e. account cash).' => 'Es ist nur sinnvoll Änderungen vorzunehmen, wenn das Konto KEIN Sammelkonto ist und wenn ein gültiger Steuerschlüssel für das Konto existiert. Gleichzeitig Haken bei Forderungen und Verbindlichkeiten zu setzen, macht auch NUR für den Zahlungsein- und Ausgang (bspw. Bank oder Kasse) Sinn.',
    'Curr'                        => 'Währung',
    'Currencies'                  => 'W&auml;hrungen',
    'Currency'                    => 'Währung',
+   'Currency (database ID)'      => 'Währung (Datenbank-ID)',
    'Current / Next Level'        => 'Aktuelles / Nächstes Mahnlevel',
    'Current Earnings'            => 'Gewinn',
    'Current assets account'      => 'Konto für Umlaufvermögen',
    'Decrease'                    => 'Verringern',
    'Default (no language selected)' => 'Standard (keine Sprache ausgewählt)',
    'Default Accounts'            => 'Standardkonten',
 +  'Default Bin'                 => 'Standard-Lagerplatz',
 +  'Default Customer/Vendor Language' => 'Standard-Kunden-/Lieferantensprache',
 +  'Default Warehouse'           => 'Standard-Lager',
+   'Default Customer/Vendor Language' => 'Standard-Kunden-/Lieferantensprache',
    'Default buchungsgruppe'      => 'Standardbuchungsgruppe',
+   'Default currency'            => 'Standardwährung',
+   'Default currency missing!'   => 'Standardwährung fehlt!',
    'Default output medium'       => 'Standardausgabekanal',
    'Default printer'             => 'Standarddrucker',
    'Default template format'     => 'Standardvorlagenformat',
    'End date'                    => 'Enddatum',
    'Enter a description for this new draft.' => 'Geben Sie eine Beschreibung f&uuml;r diesen Entwurf ein.',
    'Enter longdescription'       => 'Langtext eingeben',
-   'Enter the abbreviations separated by a colon (i.e CAD:USD:EUR) for your native and foreign currencies' => 'Geben Sie Ihre und weitere Währungen als Abkürzungen durch Doppelpunkte getrennt ein (z.B. EUR:USD:CAD)',
    'Enter the requested execution date or leave empty for the quickest possible execution:' => 'Geben Sie das jeweils gewünschte Ausführungsdatum an, oder lassen Sie das Feld leer für die schnellstmögliche Ausführung:',
    'Entries for which automatic conversion failed:' => 'Einträge, für die die automatische Umstellung fehlschlug:',
    'Entries for which automatic conversion succeeded:' => 'Einträge, für die die automatische Umstellung erfolgreich war:',
    'Error: Customer/vendor not found' => 'Fehler: Kunde/Lieferant nicht gefunden',
    'Error: Gender (cp_gender) missing or invalid' => 'Fehler: Geschlecht (cp_gender) fehlt oder ungültig',
    'Error: Invalid business'     => 'Fehler: Kunden-/Lieferantentyp ungültig',
+   'Error: Invalid currency'     => 'Fehler: ungültige Währung',
    'Error: Invalid language'     => 'Fehler: Sprache ungültig',
    'Error: Invalid part type'    => 'Fehler: Artikeltyp ungültig',
    'Error: Invalid parts group'  => 'Fehler: Warengruppe ungültig',
    'From'                        => 'Von',
    'From Date'                   => 'Von',
    'From this version on a new feature is available.' => 'Ab dieser Version ist ein neues Feature verfügbar.',
+   'From this version on it is necessary to name a default value.' => 'Ab dieser Version benötigt kivitendo eine Standardwährung.',
    'From this version on the partnumber of services, articles and assemblies have to be unique.' => 'Ab dieser Version müssen Artikelnummern eindeutig vergeben werden.',
    'From this version on the taxkey 0 must have a tax rate of 0 (for DATEV compatibility).' => 'Ab dieser Version muss der Steuerschlüssel 0 einen Steuersatz von 0% haben (auf Grund der DATEV-Kompatibilität).',
    'Full Access'                 => 'Vollzugriff',
    'ID-Nummer'                   => 'ID-Nummer (intern)',
    'II'                          => 'II',
    'III'                         => 'III',
-   'IMPORTANT NOTE: You cannot safely change currencies, IF you have already booking entries!' => 'WICHTIGER HINWEIS: Falls schon Buchungen im Mandanten vorhanden sind, kann man nicht mehr UNKRITISCH neue oder andere Währungen konfigurieren!',
    'IV'                          => 'IV',
    'If checked the taxkey will not be exported in the DATEV Export, but only IF chart taxkeys differ from general ledger taxkeys' => 'Falls angehakt wird der DATEV-Steuerschlüssel bei Buchungen auf dieses Konto nicht beim DATEV-Export mitexportiert, allerdings nur wenn zusätzlich der Konto-Steuerschlüssel vom Buchungs (Hauptbuch) Steuerschlüssel abweicht',
    'If the article type is set to \'mixed\' then a column called \'type\' must be present.' => 'Falls der Artikeltyp auf \'gemischt\' gestellt wird, muss eine Spalte namens \'type\' vorhanden sein.',
    'If you want to change any of these parameters then press the &quot;Back&quot; button, edit the file &quot;config/kivitendo.conf&quot; and login into the admin module again.' => 'Wenn Sie einen der Parameter &auml;ndern wollen, so dr&uuml;cken Sie auf den &quot;Zur&uuml;ck&quot;-Button, bearbeiten Sie die Datei &quot;config/kivitendo.conf&quot;, und melden Sie sich erneut im Administrationsbereich an.',
    'If you want to delete such a dataset you have to edit the user(s) that are using the dataset in question and have them use another dataset.' => 'Wenn Sie eine solche Datenbank l&ouml;schen wollen, so m&uuml;ssen Sie zuerst die Benutzer bearbeiten, die die fragliche Datenbank benutzen, und sie so &auml;ndern, dass sie eine andere Datenbank benutzen.',
    'If you want to set up the authentication database yourself then log in to the administration panel. kivitendo will then create the database and tables for you.' => 'Wenn Sie die Authentifizierungs-Datenbank selber einrichten wollen, so melden Sie sich im Administrationsbereich an. kivitendo wird dann die Datenbank und die erforderlichen Tabellen für Sie anlegen.',
 +  'If your old bins match exactly Bins in the Warehouse CLICK on <b>AUTOMATICALLY MATCH BINS</b>.' => 'Falls die alte Lagerplatz-Beschreibung in Stammdaten genau mit einem Lagerplatz in einem vorhandenem Lager übereinstimmt, KLICK auf <b>LAGERPLÄTZE AUTOMATISCH ZUORDNEN</b>',
    'Illegal characters have been removed from the following fields: #1' => 'Ungültige Zeichen wurden aus den folgenden Feldern entfernt: #1',
    'Image'                       => 'Grafik',
    'Import'                      => 'Import',
    'Invoices, Credit Notes & AR Transactions' => 'Rechnungen, Gutschriften & Debitorenbuchungen',
    'Is Searchable'               => 'Durchsuchbar',
    'Is this a summary account to record' => 'Sammelkonto für',
+   'It is not allowed that a summary account occurs in a drop-down menu!' => 'Ein Sammelkonto darf nicht in Aufklappmenüs aufgenommen werden!',
    'It is possible that even after such a correction there is something wrong with this transaction (e.g. taxes that don\'t match the selected taxkey). Therefore you should re-run the general ledger analysis.' => 'Auch nach einer Korrektur kann es mit dieser Buchung noch weitere Probleme geben (z.B. nicht zum Steuerschlüssel passende Steuern), weshalb ein erneutes Ausführen der Hauptbuchanalyse empfohlen wird.',
    'It is possible to do this automatically for some Buchungsgruppen, but not for all.' => 'Es ist m&ouml;glich, dies f&uuml;r einige, aber nicht f&uuml;r alle Buchungsgruppen automatisch zu erledigen.',
    'It is possible to do this automatically for some units, but for others the user has to chose the new unit.' => 'Das ist f&uuml;r einige Einheiten automatisch m&ouml;glich, aber bei anderen muss der Benutzer die neue Einheit ausw&auml;hlen.',
    'Marked as paid'              => 'Als bezahlt markiert',
    'Marked entries printed!'     => 'Markierte Einträge wurden gedruckt!',
    'Master Data'                 => 'Stammdaten',
 +  'Master Data Bin Text Deleted' => 'Gelöschte Stammdaten Freitext-Lagerplätze',
    'Max. Dunning Level'          => 'höchste Mahnstufe',
    'May'                         => 'Mai',
    'May '                        => 'Mai',
    'No data was found.'          => 'Es wurden keine Daten gefunden.',
    'No databases have been found on this server.' => 'Auf diesem Server wurden keine Datenbanken gefunden.',
    'No datasets have been selected.' => 'Es wurden keine Datenbanken ausgew&auml;hlt.',
+   'No default currency'         => 'Keine Standardwährung',
    'No department has been created yet.' => 'Es wurde noch keine Abteilung erfasst.',
    'No dunnings have been selected for printing.' => 'Es wurden keine Mahnungen zum Drucken ausgew&auml;hlt.',
    'No entries were found which had no unit assigned to them.' => 'Es wurden keine Eintr&auml;ge gefunden, denen keine Einheit zugeordnet war.',
    'No problems were recognized.' => 'Es wurden keine Probleme gefunden.',
    'No report with id #1'        => 'Es gibt keinen Report mit der Id #1',
    'No shipto selected to delete' => 'Keine Lieferadresse zum Löschen ausgewählt',
+   'No summary account'          => 'Kein Sammelkonto',
    'No transaction selected!'    => 'Keine Transaktion ausgewählt',
    'No transfers were executed in this export.' => 'In diesem SEPA-Export wurden keine Überweisungen ausgeführt.',
    'No unknown units where found.' => 'Es wurden keine unbekannten Einheiten gefunden.',
    'Orders / Delivery Orders deleteable' => 'Aufträge / Lieferscheine löschbar',
    'Orientation'                 => 'Seitenformat',
    'Orphaned'                    => 'Nie benutzt',
+   'Orphaned currencies'         => 'Verwaiste Währungen',
    'Other users\' follow-ups'    => 'Wiedervorlagen anderer Benutzer',
    'Other values are ignored.'   => 'Andere Eingaben werden ignoriert.',
    'Others'                      => 'Andere',
    'Otherwise all users will only have access to their own settings.' => 'Andernfalls haben alle Benutzer nur Zugriff auf ihre Einstellungen.',
    'Otherwise the variable is only available for printing.' => 'Andernfalls steht die Variable nur beim Ausdruck zur Verfügung.',
 +  'Otherwise you can simply check create warehouse and bins and define a name for the warehouse (Bins will be created automatically) and then continue' => 'Andernfalls einfach Lager und Lagerplätze erschaffen anhaken und einen Namen für das Lager vergeben (Lagerplätze werden dann automatisch hinzugefügt) danach auf weiter',
    'Out of balance transaction!' => 'Buchung ist nicht ausgeglichen!',
    'Out of balance!'             => 'Summen stimmen nicht berein!',
    'Output Number Format'        => 'Zahlenformat (Ausgabe)',
    '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 currency you are working with.' => 'Bitte geben Sie die Währung an, mit der Sie arbeiten.',
    '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:',
    '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.',
    'Removed spoolfiles!'         => 'Druckdateien entfernt!',
    'Removing marked entries from queue ...' => 'Markierte Einträge werden von der Warteschlange entfernt ...',
    'Rename the group'            => 'Gruppe umbenennen',
+   'Replace the orphaned currencies by other not orphaned currencies. To do so, please delete the currency in the textfields above and replace it by another currency. You could loose or change unintentionally exchangerates. Go on very carefully since you could destroy transactions.' => 'Ersetze die Währungen durch andere gültige Währungen. Wenn Sie sich hierfür entscheiden, ersetzen Sie bitte alle Währungen, die oben angegeben sind, durch Währungen, die in Ihrem System ordnungsgemäß eingetragen sind. Alle eingetragenen Wechselkurse für die verwaiste Währung werden dabei gelöscht. Bitte gehen Sie sehr vorsichtig vor, denn die betroffenen Buchungen können unter Umständen kaputt gehen.',
    'Report Positions'            => 'Berichte',
    'Report about warehouse contents' => 'Lagerbestand anzeigen',
    'Report about warehouse transactions' => 'Lagerbuchungen anzeigen',
    'Text variables: \'MAXLENGTH=n\' sets the maximum entry length to \'n\'.' => 'Textzeilen: \'MAXLENGTH=n\' setzt eine Maximall&auml;nge von n Zeichen.',
    'Text, text field and number variables: The default value will be used as-is.' => 'Textzeilen, Textfelder und Zahlenvariablen: Der Standardwert wird so wie er ist &uuml;bernommen.',
    'That export does not exist.' => 'Dieser Export existiert nicht.',
+   'That is why kivitendo could not find a default currency.' => 'Daher konnte kivitendo keine Standardwährung finden.',
    '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 AP transaction #1 has been deleted.' => 'Die Kreditorenbuchung #1 wurde gelöscht.',
    'The AR transaction #1 has been deleted.' => 'Die Debitorenbuchung #1 wurde gelöscht.',
 +  'The Bins in Inventory were only a information text field.' => 'Die Lagerplätze unter Stammdaten/Waren, sind nur ein informatives Textfeld.',
 +  'The Bins in master data were only a information text field.' => 'Die Lagerplätze unter Stammdaten/Waren, sind nur ein informatives Textfeld.',
    'The GL transaction #1 has been deleted.' => 'Die Dialogbuchung #1 wurde gelöscht.',
    'The LDAP server "#1:#2" is unreachable. Please check config/kivitendo.conf.' => 'Der LDAP-Server "#1:#2" ist nicht erreichbar. Bitte &uuml;berpr&uuml;fen Sie die Angaben in config/kivitendo.conf.',
    'The SEPA export has been created.' => 'Der SEPA-Export wurde erstellt',
    'The follow-up date is missing.' => 'Das Wiedervorlagedatum fehlt.',
    'The following Buchungsgruppen have already been created:' => 'Die folgenden Buchungsgruppen wurden bereits angelegt:',
    'The following Datasets need to be updated' => 'Folgende Datenbanken müssen aktualisiert werden',
+   'The following currencies have been used, but they are not defined:' => 'Die folgenden Währungen wurden benutzt, sind aber nicht ordnungsgemäß in der Datenbank eingetragen:',
    'The following drafts have been saved and can be loaded.' => 'Die folgenden Entw&uuml;rfe wurden gespeichert und k&ouml;nnen geladen werden.',
    '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:',
    'There are #1 more open invoices for this customer with other currencies.' => 'Es gibt #1 weitere offene Rechnungen für diesen Kunden, die in anderen Währungen ausgestellt wurden.',
    '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 Bins defined in your Inventory.' => 'Unter Stammdaten/Waren sind Lagerplätze defininert',
 +  'There are Bins defined in your master data.' => 'Unter Stammdaten/Waren sind Lagerplätze defininert',
    '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 double partnumbers in your database.' => 'In ihrer Datenbank befinden sich mehrfach vergebene Artikelnummern.',
    '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 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.',
+   'There are several options you can handle this problem, please select one:' => 'Bitte wählen Sie eine der folgenden Optionen, um mit dem Problem umzugehen:',
    'There are still entries in the database for which no unit has been assigned.' => 'Es gibt noch Eintr&auml;ge in der Datenbank, f&uuml;r die keine Einheit zugeordnet ist.',
    '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 undefined currencies in your system.' => 'In Ihrer Datenbank wurden Währungen benutzt, die nicht ordnungsgemäß in den Währungen eingetragen wurden.',
    '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.',
    'This customer number is already in use.' => 'Diese Kundennummer wird bereits verwendet.',
    'This feature especially prevents mistakes by mixing up prior tax and sales tax.' => 'Dieses Feature vermeidet insbesondere Verwechslungen von Umsatz- und Vorsteuer.',
    'This group will be called &quot;Full Access&quot;.' => 'Diese Gruppe wird &quot;Vollzugriff&quot; genannt.',
 +  'This has been changed in this version, therefore please change the "old" bins to some real warehouse bins.' => 'Das wurde in dieser Version umgestellt, bitte ändern Sie die Freitext-Lagerplätze auf wirkliche Lagerplätze.',
 +  'This has been changed in this version.' => 'Ab dieser Version ist dies nicht mehr so.',
    '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 is the default bin for parts' => 'Standard-Lagerplatz für Stammdaten/Waren',
    '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.',
    'This upgrade script tries to map all existing parts in the database to the newly created Buchungsgruppen.' => 'Dieses Upgradescript versucht, bei allen bestehenden Artikeln neu erstellte Buchungsgruppen zuzuordnen.',
    'This upgrade script tries to map all existing units in the database to the newly created units.' => 'Dieses Update-Script versucht, alle bestehenden Einheiten automatisch in die neuen Einheiten umzuwandeln.',
    'This vendor number is already in use.' => 'Diese Lieferantennummer wird bereits verwendet.',
 +  'Three Options:'              => 'Drei Optionen:',
    'Time period for the analysis:' => 'Analysezeitraum:',
    'Timestamp'                   => 'Uhrzeit',
    'Title'                       => 'Titel',
    'Unbalanced Ledger'           => 'Bilanzfehler',
    'Unchecked custom variables will not appear in orders and invoices.' => 'Unmarkierte Variablen werden für diesen Artikel nicht in Aufträgen und Rechnungen angezeigt.',
    'Unfinished follow-ups'       => 'Nicht erledigte Wiedervorlagen',
 +  'Unfortunately you have no warehouse defined.' => 'Leider, gibt es kein Lager in diesem Mandanten.',
    'Unit'                        => 'Einheit',
    'Unit (if missing or empty default unit will be used)' => 'Einheit (falls nicht vorhanden oder leer wird die Standardeinheit benutzt)',
    'Unit missing.'               => 'Die Einheit fehlt.',
    'You cannot create an invoice for delivery orders from different vendors.' => 'Sie können keine Rechnung aus Lieferscheinen von verschiedenen Lieferanten erstellen.',
    'You do not have the permissions to access this function.' => 'Sie verf&uuml;gen nicht &uuml;ber die notwendigen Rechte, um auf diese Funktion zuzugreifen.',
    'You have entered or selected the following shipping address for this customer:' => 'Sie haben die folgende Lieferadresse eingegeben oder ausgew&auml;hlt:',
+   'You have never worked with currencies.' => 'Sie haben noch nie  mit Währungen gearbeitet.',
    'You have not added bank accounts yet.' => 'Sie haben noch keine Bankkonten angelegt.',
    'You have not selected any delivery order.' => 'Sie haben keinen Lieferschein ausgewählt.',
    'You have not selected any export.' => 'Sie haben keinen Export ausgewählt.',