Beim Speichern von Benutzereinstellungen durch den Benutzer die Webdav-htaccess-Datei...
[kivitendo-erp.git] / bin / mozilla / am.pl
index 9f7d8f5..3bb240f 100644 (file)
@@ -55,6 +55,7 @@ sub delete   { call_sub("delete_$form->{type}"); }
 sub save     { call_sub("save_$form->{type}"); }
 sub edit     { call_sub("edit_$form->{type}"); }
 sub continue { call_sub($form->{"nextsub"}); }
+sub save_as_new { call_sub("save_as_new_$form->{type}"); }
 
 sub add_account {
   $lxdebug->enter_sub();
@@ -98,8 +99,8 @@ sub account_header {
 
   if ( $form->{action} eq 'edit_account') {
     $form->{account_exists} = '1';
-  } 
-  
+  }
+
   $form->{title} = $locale->text("$form->{title} Account");
 
   $form->{"$form->{charttype}_checked"} = "checked";
@@ -108,9 +109,9 @@ sub account_header {
   $form->{select_tax} = "";
 
   my @tax_report_pos = USTVA->report_variables({
-      myconfig   => \%myconfig, 
-      form       => $form, 
-      type       => '', 
+      myconfig   => \%myconfig,
+      form       => $form,
+      type       => '',
       attribute  => 'position',
       calc       => '',
   });
@@ -146,27 +147,27 @@ sub account_header {
         if ($item->{id} == $taxkey_used->{tax_id}) {
           $form->{ACCOUNT_TAXKEYS}[$i]{selecttaxkey} .=
             qq|<option value="$item->{id}" selected="selected">|
-            . sprintf("%.2d", $item->{taxkey}) 
+            . sprintf("%.2d", $item->{taxkey})
             . qq|. $item->{taxdescription} ($item->{rate}) |
-            . $locale->text('Tax-o-matic Account') 
+            . $locale->text('Tax-o-matic Account')
             . qq|: $item->{chart_accno}\n|;
-        } 
+        }
         else {
           $form->{ACCOUNT_TAXKEYS}[$i]{selecttaxkey} .=
             qq|<option value="$item->{id}">|
-            . sprintf("%.2d", $item->{taxkey}) 
+            . sprintf("%.2d", $item->{taxkey})
             . qq|. $item->{taxdescription} ($item->{rate}) |
             . $locale->text('Tax-o-matic Account')
             . qq|: $item->{chart_accno}\n|;
         }
 
       }
-      
+
       # Fill in the USTVA Numbers as select options
       foreach my $item ( '', sort({ $a cmp $b } @tax_report_pos) ) {
         if ($item eq ''){
           $form->{ACCOUNT_TAXKEYS}[$i]{select_tax} .= qq|<option value="" selected="selected">-\n|;
-        } 
+        }
         elsif ( $item eq $taxkey_used->{pos_ustva} ) {
           $form->{ACCOUNT_TAXKEYS}[$i]{select_tax} .= qq|<option value="$item" selected="selected">$item\n|;
         }
@@ -174,13 +175,13 @@ sub account_header {
           $form->{ACCOUNT_TAXKEYS}[$i]{select_tax} .= qq|<option value="$item">$item\n|;
         }
 
-      }      
+      }
 
       $i++;
     }
   }
 
-  # Newaccount Folgekonto 
+  # Newaccount Folgekonto
   if (@{ $form->{NEWACCOUNT} }) {
     if (!$form->{new_chart_valid}) {
       $form->{selectnewaccount} = qq|<option value=""> |. $locale->text('None') .q|</option>|;
@@ -214,7 +215,7 @@ sub account_header {
           14 => "Steuern, Versich., Beiträge",
           15 => "Kfz-Steuern",
           16 => "Kfz-Versicherungen",
-          17 => "Sonst. Fahrtkosten",
+          17 => "Sonst. Fahrzeugkosten",
           18 => "Werbe- und Reisekosten",
           19 => "Instandhaltung u. Werkzeuge",
           20 => "Fachzeitschriften, Bücher",
@@ -287,18 +288,18 @@ sub account_header {
   # this is for our parser only! Do not remove.
   # type=submit $locale->text('Add Account')
   # type=submit $locale->text('Edit Account')
-  
+
   $form->{type} = "account";
 
   # preselections category
+
   $select_category = q|<option value=""> |. $locale->text('None') .q|</option>\n|;
 
   %category = (
       'A'  => $locale->text('Asset'),
       'L'  => $locale->text('Liability'),
       'Q'  => $locale->text('Equity'),
-      'I'  => $locale->text('Revenue'),      
+      'I'  => $locale->text('Revenue'),
       'E'  => $locale->text('Expense'),
       'C'  => $locale->text('Costs'),
   );
@@ -310,7 +311,7 @@ sub account_header {
     }
 
   }
-  
+
   # preselection chart type
   my $select_charttype = q{};
 
@@ -318,7 +319,7 @@ sub account_header {
       'A'  => $locale->text('Account'),
       'H'  => $locale->text('Header'),
   );
-  
+
   foreach $item ( sort({ $a <=> $b } keys %charttype) ) {
     if ($item eq $form->{charttype}) {
       $select_charttype .= qq|<option value="$item" selected="selected">$charttype{$item}\n|;
@@ -330,9 +331,9 @@ sub account_header {
   }
 
   my $ChartTypeIsAccount = ($form->{charttype} eq "A") ? "1":"";
-  
+
   $form->header();
-  
+
   my $parameters_ref = {
     ChartTypeIsAccount         => $ChartTypeIsAccount,
     select_category            => $select_category,
@@ -343,7 +344,7 @@ sub account_header {
     select_bilanz              => $select_bilanz,
     select_eur                 => $select_eur,
   };
-  
+
   # Ausgabe des Templates
   print($form->parse_html_template('am/edit_accounts', $parameters_ref));
 
@@ -373,6 +374,12 @@ sub form_footer {
       . $locale->text('Delete') . qq|">|;
   }
 
+  if ($form->{id} && $form->{type} eq "account") {
+    print qq|
+    <input class=submit type=submit name=action value="|
+      . $locale->text('Save as new') . qq|">|;
+  }
+
   print qq|
 </form>
 
@@ -390,11 +397,41 @@ sub save_account {
 
   $form->isblank("accno",       $locale->text('Account Number missing!'));
   $form->isblank("description", $locale->text('Account Description missing!'));
-  
+
+  if ($form->{charttype} eq 'A'){
+    $form->isblank("category",  $locale->text('Account Type missing!'));
+  }
+
+  $form->redirect($locale->text('Account saved!'))
+    if (AM->save_account(\%myconfig, \%$form));
+  $form->error($locale->text('Cannot save account!'));
+
+  $lxdebug->leave_sub();
+}
+
+sub save_as_new_account {
+  $lxdebug->enter_sub();
+
+  $auth->assert('config');
+
+  $form->isblank("accno",       $locale->text('Account Number missing!'));
+  $form->isblank("description", $locale->text('Account Description missing!'));
+
   if ($form->{charttype} eq 'A'){
     $form->isblank("category",  $locale->text('Account Type missing!'));
   }
 
+  for my $taxkey (0 .. 9) {
+    if ($form->{"taxkey_id_$taxkey"}) {
+      $form->{"taxkey_id_$taxkey"} = "NEW";
+    }
+  }
+
+  $form->{id} = 0;
+  if ($form->{"original_accno"} &&
+      ($form->{"accno"} eq $form->{"original_accno"})) {
+    $form->error($locale->text('Account Number already used!'));
+  }
   $form->redirect($locale->text('Account saved!'))
     if (AM->save_account(\%myconfig, \%$form));
   $form->error($locale->text('Cannot save account!'));
@@ -423,32 +460,32 @@ sub list_account {
     if ($ca->{amount} < 0) {
       $ca->{debit} = $form->format_amount(\%myconfig, -1 * $ca->{amount}, 2);
     }
-    $ca->{heading}   = ( $ca->{charttype} eq 'H' ) ? 1:''; 
+    $ca->{heading}   = ( $ca->{charttype} eq 'H' ) ? 1:'';
     $ca->{link_edit_account} = $link_edit_account . '&id=' . E($ca->{id});
   }
-  
-  # Ajax 
+
+  # Ajax
   my $pjx = new CGI::Ajax('list_account_details' => build_std_url('action=list_account_details'));
 
   # Eneable AJAX debuging
   #$pjx->DEBUG(1);
   #$pjx->JSDEBUG(1);
-    
+
   push(@ { $form->{AJAX} }, $pjx);
 
   $form->{stylesheets} = "list_accounts.css";
   $form->{title}       = $locale->text('Chart of Accounts');
 
   $form->header;
-  
-  
+
+
   my $parameters_ref = {
   #   hidden_variables                => $_hidden_variables_ref,
   };
-  
+
   # Ausgabe des Templates
   print($form->parse_html_template('am/list_accounts', $parameters_ref));
-  
+
   $lxdebug->leave_sub();
 
 }
@@ -839,7 +876,7 @@ sub list_lead {
 |;
 
        $lead = $ref->{lead};
-       
+
     $column_data{description} = qq|<td><a href="am.pl?action=edit_lead&id=$ref->{id}&callback=$callback">$ref->{lead}</td>|;
 
     map { print "$column_data{$_}\n" } @column_index;
@@ -1905,7 +1942,7 @@ sub list_printer {
 |;
 
 
-    $column_data{printer_description} = qq|<td><a href="am.pl?action=edit_printer&id=$ref->{id}&callback=$callback">$ref->{printer_description}"</td>|;
+    $column_data{printer_description} = qq|<td><a href="am.pl?action=edit_printer&id=$ref->{id}&callback=$callback">$ref->{printer_description}</td>|;
     $column_data{printer_command}           = qq|<td align=right>$ref->{printer_command}</td>|;
     $column_data{template_code} =
       qq|<td align=right>$ref->{template_code}</td>|;
@@ -2271,11 +2308,11 @@ sub payment_header {
   <tr>
     <th align=right>| . $locale->text('Skonto Terms') . qq|</th>
     <td><input name=terms_skonto size=10 value="$form->{terms_skonto}"></td>
-  </tr>  
+  </tr>
   <tr>
     <th align=right>| . $locale->text('Skonto') . qq| %</th>
     <td><input name=percent_skonto size=10 value="$form->{percent_skonto}"></td>
-  </tr> 
+  </tr>
   <td colspan=2><hr size=3 noshade></td>
   </tr>
 </table>
@@ -2489,10 +2526,9 @@ sub config {
     };
   }
 
-  $myconfig{show_form_details}              = 1 unless (defined($myconfig{show_form_details}));
-  $form->{"menustyle_$myconfig{menustyle}"} = 1;
-  $form->{CAN_CHANGE_PASSWORD}              = $auth->can_change_password();
-  $form->{todo_cfg}                         = { TODO->get_user_config('login' => $form->{login}) };
+  $myconfig{show_form_details} = 1 unless (defined($myconfig{show_form_details}));
+  $form->{CAN_CHANGE_PASSWORD} = $auth->can_change_password();
+  $form->{todo_cfg}            = { TODO->get_user_config('login' => $form->{login}) };
 
   $form->{title}                            = $locale->text('Edit Preferences for #1', $form->{login});
 
@@ -2509,7 +2545,7 @@ sub save_preferences {
 
   TODO->save_user_config('login' => $form->{login}, %{ $form->{todo_cfg} || { } });
 
-  $form->redirect($locale->text('Preferences saved!')) if (AM->save_preferences(\%myconfig, \%$form, $webdav));
+  $form->redirect($locale->text('Preferences saved!')) if (AM->save_preferences(\%myconfig, \%$form, 0));
   $form->error($locale->text('Cannot save preferences!'));
 
   $lxdebug->leave_sub();
@@ -2524,12 +2560,6 @@ sub audit_control {
 
   AM->closedto(\%myconfig, \%$form);
 
-  if ($form->{revtrans}) {
-    $checked{Y} = "checked";
-  } else {
-    $checked{N} = "checked";
-  }
-
   $form->header;
 
   print qq|
@@ -2543,15 +2573,6 @@ sub audit_control {
   <tr>
     <td>
       <table>
-       <tr>
-         <td>|
-    . $locale->text('Enforce transaction reversal for all dates') . qq|</th>
-         <td><input name=revtrans class=radio type=radio value="1" $checked{Y}> |
-    . $locale->text('Yes')
-    . qq| <input name=revtrans class=radio type=radio value="0" $checked{N}> |
-    . $locale->text('No')
-    . qq|</td>
-       </tr>
        <tr>
          <th>| . $locale->text('Close Books up to') . qq|</th>
          <td><input name=closedto size=11 title="$myconfig{dateformat}" value=$form->{closedto}></td>
@@ -2585,17 +2606,12 @@ sub doclose {
 
   AM->closebooks(\%myconfig, \%$form);
 
-  if ($form->{revtrans}) {
+  if ($form->{closedto}) {
     $form->redirect(
-                 $locale->text('Transaction reversal enforced for all dates'));
+                    $locale->text('Books closed up to') . " "
+                      . $locale->date(\%myconfig, $form->{closedto}, 1));
   } else {
-    if ($form->{closedto}) {
-      $form->redirect(
-                     $locale->text('Transaction reversal enforced up to') . " "
-                       . $locale->date(\%myconfig, $form->{closedto}, 1));
-    } else {
-      $form->redirect($locale->text('Books are open'));
-    }
+    $form->redirect($locale->text('Books are open'));
   }
 
   $lxdebug->leave_sub();
@@ -2606,7 +2622,7 @@ sub edit_units {
 
   $auth->assert('config');
 
-  $units = AM->retrieve_units(\%myconfig, $form, $form->{"unit_type"}, "resolved_");
+  $units = AM->retrieve_units(\%myconfig, $form, "resolved_");
   AM->units_in_use(\%myconfig, $form, $units);
   map({ $units->{$_}->{"BASE_UNIT_DDBOX"} = AM->unit_select_data($units, $units->{$_}->{"base_unit"}, 1); } keys(%{$units}));
 
@@ -2630,12 +2646,12 @@ sub edit_units {
     $i++;
   }
 
-  $units = AM->retrieve_units(\%myconfig, $form, $form->{"unit_type"});
+  $units = AM->retrieve_units(\%myconfig, $form);
   $ddbox = AM->unit_select_data($units, undef, 1);
 
-  my $updownlink = build_std_url("action=swap_units", "unit_type");
+  my $updownlink = build_std_url("action=swap_units");
 
-  $form->{"title"} = sprintf($locale->text("Add and edit %s"), $form->{"unit_type"} eq "dimension" ? $locale->text("dimension units") : $locale->text("service units"));
+  $form->{"title"} = $locale->text("Add and edit units");
   $form->header();
   print($form->parse_html_template("am/edit_units",
                                    { "UNITS"               => \@unit_list,
@@ -2652,7 +2668,7 @@ sub add_unit {
   $auth->assert('config');
 
   $form->isblank("new_name", $locale->text("The name is missing."));
-  $units = AM->retrieve_units(\%myconfig, $form, $form->{"unit_type"});
+  $units = AM->retrieve_units(\%myconfig, $form);
   $all_units = AM->retrieve_units(\%myconfig, $form);
   $form->show_generic_error($locale->text("A unit with this name does already exist.")) if ($all_units->{$form->{"new_name"}});
 
@@ -2675,7 +2691,7 @@ sub add_unit {
          });
   }
 
-  AM->add_unit(\%myconfig, $form, $form->{"new_name"}, $base_unit, $factor, $form->{"unit_type"}, \@languages);
+  AM->add_unit(\%myconfig, $form, $form->{"new_name"}, $base_unit, $factor, \@languages);
 
   $form->{"saved_message"} = $locale->text("The unit has been saved.");
 
@@ -2709,7 +2725,7 @@ sub save_unit {
 
   $auth->assert('config');
 
-  $old_units = AM->retrieve_units(\%myconfig, $form, $form->{"unit_type"}, "resolved_");
+  $old_units = AM->retrieve_units(\%myconfig, $form, "resolved_");
   AM->units_in_use(\%myconfig, $form, $old_units);
 
   @languages = AM->language(\%myconfig, $form, 1);
@@ -2775,7 +2791,7 @@ sub save_unit {
     }
   }
 
-  AM->save_units(\%myconfig, $form, $form->{"unit_type"}, $new_units, \@delete_units);
+  AM->save_units(\%myconfig, $form, $new_units, \@delete_units);
 
   $form->{"saved_message"} = $locale->text("The units have been saved.");
 
@@ -2785,118 +2801,81 @@ sub save_unit {
 }
 
 sub show_history_search {
-       $lxdebug->enter_sub();
-       
+  $lxdebug->enter_sub();
+
   $auth->assert('config');
 
-       $form->{title} = $locale->text("History Search");
-    $form->header();
-    
-    print $form->parse_html_template("common/search_history");
-       
-       $lxdebug->leave_sub();
+  $form->{title} = $locale->text("History Search");
+  $form->header();
+
+  print $form->parse_html_template("common/search_history");
+
+  $lxdebug->leave_sub();
 }
 
 sub show_am_history {
-       $lxdebug->enter_sub();
-
-  $auth->assert('config');
-
-       my %search = ( "Artikelnummer" => "parts",
-                                  "Kundennummer"  => "customer",
-                                  "Lieferantennummer" => "vendor",
-                                  "Projektnummer" => "project",
-                                  "Buchungsnummer" => "oe",
-                                  "Eingangsrechnungnummer" => "ap",
-                                  "Ausgangsrechnungnummer" => "ar",
-           "Mahnungsnummer" => "dunning"
-               );
-       my %searchNo = ( "Artikelnummer" => "partnumber",
-                                    "Kundennummer"  => "customernumber",
-                                    "Lieferantennummer" => "vendornumber",
-                                    "Projektnummer" => "projectnummer",
-                                    "Buchungsnummer" => "ordnumber",
-                                    "Eingangsrechnungnummer" => "invnumber",
-                                    "Ausgangsrechnungnummer" => "invnumber",
-             "Mahnungsnummer" => "dunning_id"
-               );
-       
-       my $restriction;
-       my $tempNo = 0;
-       foreach(split(/\,/, $form->{einschraenkungen})) {
-               if($tempNo == 0) {
-                       $restriction .= " AND addition = '" . $_ . "'";
-                       $tempNo = 1;
-               } 
-               else {
-                       $restriction .= " OR addition = '" . $_ . "'";
-               }
-       }
-       $restriction .= (($form->{transdate} ne "" && $form->{reqdate} ne "") 
-                                               ? qq| AND st.itime::date >= '| . $form->{transdate} . qq|' AND st.itime::date <= '| . $form->{reqdate} . qq|'|
-                                               : (($form->{transdate} ne "" && $form->{reqdate} eq "") 
-                                                       ? qq| AND st.itime::date >= '| . $form->{transdate} . qq|'|
-                                                       : ($form->{transdate} eq "" && $form->{reqdate} ne "") 
-                                                               ? qq| AND st.itime::date <= '| . $form->{reqdate} . qq|'|
-                                                               : ""
-                                                       )
-                                               );
-  $restriction .= ($form->{mitarbeiter} eq "" ? "" 
-          : ($form->{mitarbeiter} =~ /^[0-9]*$/  
-            ? " AND employee_id = " . $form->{mitarbeiter} 
-            : " AND employee_id = " . &get_employee_id($form->{mitarbeiter}, $dbh)));
-  
-       my $dbh = $form->dbconnect(\%myconfig);
-       my $query = qq|SELECT trans_id AS id FROM history_erp | . 
-                ($form->{'searchid'} ? 
-                  qq| WHERE snumbers = '| . $searchNo{$form->{'what2search'}} . qq|_| . $form->{'searchid'} . qq|'| : 
-                  qq| WHERE snumbers ~ '^| . $searchNo{$form->{'what2search'}} . qq|'|);
-
-  my $sth = $dbh->prepare($query);
-       
-       $sth->execute() || $form->dberror($query);
-  
-  $form->{title} = $locale->text("History Search");
-       $form->header();
-       
-  my $i = 1;
-  my $daten = qq||;
-  while(my $hash_ref = $sth->fetchrow_hashref()){
-    if($i) {
-      $daten .= $hash_ref->{id};
-      $i = 0;
-    }
-    else {
-      $daten .= " OR trans_id = " . $hash_ref->{id};
-    }
+  $lxdebug->enter_sub();
+
+  $auth->assert('config');
+
+  my $callback     = build_std_url(qw(action einschraenkungen fromdate todate mitarbeiter searchid what2search));
+  $form->{order} ||= 'h.itime--1';
+
+  my %search = ( "Artikelnummer"          => "parts",
+                 "Kundennummer"           => "customer",
+                 "Lieferantennummer"      => "vendor",
+                 "Projektnummer"          => "project",
+                 "Buchungsnummer"         => "oe",
+                 "Eingangsrechnungnummer" => "ap",
+                 "Ausgangsrechnungnummer" => "ar",
+                 "Mahnungsnummer"         => "dunning"
+    );
+  my %searchNo = ( "Artikelnummer"          => "partnumber",
+                   "Kundennummer"           => "customernumber",
+                   "Lieferantennummer"      => "vendornumber",
+                   "Projektnummer"          => "projectnummer",
+                   "Buchungsnummer"         => "ordnumber",
+                   "Eingangsrechnungnummer" => "invnumber",
+                   "Ausgangsrechnungnummer" => "invnumber",
+                   "Mahnungsnummer"         => "dunning_id"
+    );
+
+  my $dbh = $form->dbconnect(\%myconfig);
+
+  my $restriction  = qq| AND (| . join(' OR ', map { " addition = " . $dbh->quote($_) } split(m/\,/, $form->{einschraenkungen})) . qq|)| if $form->{einschraenkungen};
+  $restriction    .= qq| AND h.itime::date >= | . conv_dateq($form->{fromdate})                                                          if $form->{fromdate};
+  $restriction    .= qq| AND h.itime::date <= | . conv_dateq($form->{todate})                                                            if $form->{todate};
+  if ($form->{mitarbeiter} =~ m/^\d+$/) {
+    $restriction  .= qq| AND employee_id = |    . $form->{mitarbeiter};
+  } elsif ($form->{mitarbeiter}) {
+    $restriction  .= qq| AND employee_id = (SELECT id FROM employee WHERE name ILIKE | . $dbh->quote('%' . $form->{mitarbeiter} . '%') . qq|)|;
   }
-  
+
+  my $query = qq|SELECT trans_id AS id FROM history_erp | .
+    (  $form->{'searchid'} ? qq| WHERE snumbers = '|  . $searchNo{$form->{'what2search'}} . qq|_| . $form->{'searchid'} . qq|'|
+     :                       qq| WHERE snumbers ~ '^| . $searchNo{$form->{'what2search'}} . qq|'|);
+
+  my @ids    = selectall_array_query($form, $dbh, $query);
+  my $daten .= shift @ids;
+  $daten    .= join '', map { " OR trans_id = $_" } @ids;
+
   my ($sort, $sortby) = split(/\-\-/, $form->{order});
   $sort =~ s/.*\.(.*)$/$1/;
 
-       print $form->parse_html_template("common/show_history", 
-    {"DATEN" => $form->get_history($dbh, $daten, $restriction, $form->{order}),
-     "SUCCESS" => ($form->get_history($dbh, $daten, $restriction, $form->{order}) ne "0"),
-     "NONEWWINDOW" => 1,
-     uc($sort) => 1,
-     uc($sort)."BY" => $sortby
-    });
-       $dbh->disconnect();
-  $lxdebug->leave_sub();
-}
-
-sub get_employee_id {
-       $lxdebug->enter_sub();
+  $form->{title} = $locale->text("History Search");
+  $form->header();
 
-  $auth->assert('config');
+  print $form->parse_html_template("common/show_history",
+                                   { "DATEN"          => $form->get_history($dbh, $daten, $restriction, $form->{order}),
+                                     "SUCCESS"        => ($form->get_history($dbh, $daten, $restriction, $form->{order}) ne "0"),
+                                     "NONEWWINDOW"    => 1,
+                                     uc($sort)        => 1,
+                                     uc($sort) . "BY" => $sortby,
+                                     'callback'       => $callback,
+                                   });
+  $dbh->disconnect();
 
-       my $query = qq|SELECT id FROM employee WHERE name = '| . $_[0] . qq|'|;
-       my $sth = $_[1]->prepare($query);
-       $sth->execute() || $form->dberror($query);
-       my $return = $sth->fetch();
-       $sth->finish();
-       return ${$return}[0];
-       $lxdebug->leave_sub();
+  $lxdebug->leave_sub();
 }
 
 sub swap_units {
@@ -2905,9 +2884,7 @@ sub swap_units {
   $auth->assert('config');
 
   my $dir = $form->{"dir"} eq "down" ? "down" : "up";
-  my $unit_type = $form->{"unit_type"} eq "dimension" ?
-    "dimension" : "service";
-  AM->swap_units(\%myconfig, $form, $dir, $form->{"name"}, $unit_type);
+  AM->swap_units(\%myconfig, $form, $dir, $form->{"name"});
 
   edit_units();
 
@@ -2926,11 +2903,11 @@ sub add_tax {
   _get_taxaccount_selection();
 
   $form->header();
-  
+
   my $parameters_ref = {
 #    ChartTypeIsAccount         => $ChartTypeIsAccount,
   };
-  
+
   # Ausgabe des Templates
   print($form->parse_html_template('am/edit_tax', $parameters_ref));
 
@@ -2950,10 +2927,10 @@ sub edit_tax {
   $form->{rate} = $form->format_amount(\%myconfig, $form->{rate}, 2);
 
   $form->header();
-  
+
   my $parameters_ref = {
   };
-  
+
   # Ausgabe des Templates
   print($form->parse_html_template('am/edit_tax', $parameters_ref));
 
@@ -2974,7 +2951,7 @@ sub list_tax {
   $form->{title} = $locale->text('Tax-O-Matic');
 
   $form->header();
-  
+
   # Ausgabe des Templates
   print($form->parse_html_template('am/list_tax', $parameters_ref));
 
@@ -3010,7 +2987,7 @@ sub save_tax {
 
   if ( $form->{rate} <= 0.99 && $form->{rate} > 0 ) {
     $form->error($locale->text('Tax Percent is a number between 0 and 100'));
-  }  
+  }
 
   AM->save_tax(\%myconfig, \%$form);
   $form->redirect($locale->text('Tax saved!'));
@@ -3136,3 +3113,130 @@ sub swap_price_factors {
   $lxdebug->leave_sub();
 }
 
+sub add_warehouse {
+  $lxdebug->enter_sub();
+
+  $auth->assert('config');
+
+  $form->{title}      = $locale->text('Add Warehouse');
+  $form->{callback} ||= build_std_url('action=add_warehouse');
+  $form->{fokus}      = 'description';
+
+  $form->header();
+  print $form->parse_html_template('am/edit_warehouse');
+
+  $lxdebug->leave_sub();
+}
+
+sub edit_warehouse {
+  $lxdebug->enter_sub();
+
+  $auth->assert('config');
+
+  AM->get_warehouse(\%myconfig, $form);
+
+  $form->get_lists('employees' => 'EMPLOYEES');
+
+  $form->{title}      = $locale->text('Edit Warehouse');
+  $form->{callback} ||= build_std_url('action=list_warehouses');
+  $form->{fokus}      = 'description';
+
+  $form->header();
+  print $form->parse_html_template('am/edit_warehouse');
+
+  $lxdebug->leave_sub();
+}
+
+sub list_warehouses {
+  $lxdebug->enter_sub();
+
+  $auth->assert('config');
+
+  AM->get_all_warehouses(\%myconfig, $form);
+
+  my $previous;
+  foreach my $current (@{ $form->{WAREHOUSES} }) {
+    if ($previous) {
+      $previous->{next_id}    = $current->{id};
+      $current->{previous_id} = $previous->{id};
+    }
+
+    $previous = $current;
+  }
+
+  $form->{callback} = build_std_url('action=list_warehouses');
+  $form->{title}    = $locale->text('Warehouses');
+  $form->{url_base} = build_std_url('callback');
+
+  $form->header();
+  print $form->parse_html_template('am/list_warehouses');
+
+  $lxdebug->leave_sub();
+}
+
+sub save_warehouse {
+  $lxdebug->enter_sub();
+
+  $auth->assert('config');
+
+  $form->isblank("description", $locale->text('Description missing!'));
+
+  $form->{number_of_new_bins} = $form->parse_amount(\%myconfig, $form->{number_of_new_bins});
+
+  AM->save_warehouse(\%myconfig, $form);
+
+  $form->{callback} .= '&saved_message=' . E($locale->text('Warehouse saved.')) if ($form->{callback});
+
+  $form->redirect($locale->text('Warehouse saved.'));
+
+  $lxdebug->leave_sub();
+}
+
+sub swap_warehouses {
+  $lxdebug->enter_sub();
+
+  $auth->assert('config');
+
+  AM->swap_sortkeys(\%myconfig, $form, 'warehouse');
+  list_warehouses();
+
+  $lxdebug->leave_sub();
+}
+
+sub delete_warehouse {
+  $lxdebug->enter_sub();
+
+  $auth->assert('config');
+
+  if (!$form->{confirmed}) {
+    $form->{title} = $locale->text('Confirmation');
+
+    $form->header();
+    print $form->parse_html_template('am/confirm_delete_warehouse');
+    exit 0;
+  }
+
+  if (AM->delete_warehouse(\%myconfig, $form)) {
+    $form->{callback} .= '&saved_message=' . E($locale->text('Warehouse deleted.')) if ($form->{callback});
+    $form->redirect($locale->text('Warehouse deleted.'));
+
+  } else {
+    $form->error($locale->text('The warehouse could not be deleted because it has already been used.'));
+  }
+
+  $lxdebug->leave_sub();
+}
+
+sub save_bin {
+  $lxdebug->enter_sub();
+
+  $auth->assert('config');
+
+  AM->save_bins(\%myconfig, $form);
+
+  $form->{callback} .= '&saved_message=' . E($locale->text('Bins saved.')) if ($form->{callback});
+
+  $form->redirect($locale->text('Bins saved.'));
+
+  $lxdebug->leave_sub();
+}