sub save_preferences {
$main::lxdebug->enter_sub();
- my ($self, $myconfig, $form, $webdav) = @_;
+ my ($self, $myconfig, $form) = @_;
my $dbh = $form->get_standard_dbh($myconfig);
my $auth = $main::auth;
- if ($auth->can_change_password()
- && defined $form->{new_password}
- && ($form->{new_password} ne '********')) {
- $auth->change_password($form->{login}, $form->{new_password});
-
- $form->{password} = $form->{new_password};
- $auth->set_session_value('password', $form->{password});
- $auth->create_or_refresh_session();
- }
-
$main::lxdebug->leave_sub();
return $rc;
--- /dev/null
+package SL::Auth::PasswordPolicy;
+
+use strict;
+
+use parent qw(Rose::Object);
+
+use constant OK => 0;
+use constant TOO_SHORT => 1;
+use constant TOO_LONG => 2;
+use constant MISSING_LOWERCASE => 4;
+use constant MISSING_UPPERCASE => 8;
+use constant MISSING_DIGIT => 16;
+use constant MISSING_SPECIAL_CHAR => 32;
+use constant INVALID_CHAR => 64;
+use constant WEAK => 128;
+
+use Rose::Object::MakeMethods::Generic
+(
+ 'scalar --get_set_init' => 'config',
+);
+
+sub verify {
+ my ($self, $password, $is_admin) = @_;
+
+ my $cfg = $self->config;
+ return OK() unless $cfg && %{ $cfg };
+ return OK() if $is_admin && $cfg->{disable_policy_for_admin};
+
+ my $result = OK();
+ $result |= TOO_SHORT() if $cfg->{min_length} && (length($password) < $cfg->{min_length});
+ $result |= TOO_LONG() if $cfg->{max_length} && (length($password) > $cfg->{max_length});
+ $result |= MISSING_LOWERCASE() if $cfg->{require_lowercase} && $password !~ m/[a-z]/;
+ $result |= MISSING_UPPERCASE() if $cfg->{require_uppercase} && $password !~ m/[A-Z]/;
+ $result |= MISSING_DIGIT() if $cfg->{require_digit} && $password !~ m/[0-9]/;
+ $result |= MISSING_SPECIAL_CHAR() if $cfg->{require_special_character} && $password !~ $cfg->{special_characters_re};
+ $result |= INVALID_CHAR() if $cfg->{invalid_characters_re} && $password =~ $cfg->{invalid_characters_re};
+
+ if ($cfg->{use_cracklib}) {
+ require Crypt::Cracklib;
+ $result |= WEAK() if !Crypt::Cracklib::check($password);
+ }
+
+ return $result;
+}
+
+sub errors {
+ my ($self, $result) = @_;
+
+ my @errors;
+
+ push @errors, $::locale->text('The password is too short (minimum length: #1).', $self->config->{min_length}) if $result & TOO_SHORT();
+ push @errors, $::locale->text('The password is too long (maximum length: #1).', $self->config->{max_length}) if $result & TOO_LONG();
+ push @errors, $::locale->text('A lower-case character is required.') if $result & MISSING_LOWERCASE();
+ push @errors, $::locale->text('An upper-case character is required.') if $result & MISSING_UPPERCASE();
+ push @errors, $::locale->text('A digit is required.') if $result & MISSING_DIGIT();
+ push @errors, $::locale->text('The password is weak (e.g. it can be found in a dictionary).') if $result & WEAK();
+
+ if ($result & MISSING_SPECIAL_CHAR()) {
+ my $char_list = join ' ', sort split(m//, $self->config->{special_characters});
+ push @errors, $::locale->text('A special character is required (valid characters: #1).', $char_list);
+ }
+
+ if (($result & INVALID_CHAR())) {
+ my $char_list = join ' ', sort split(m//, $self->config->{ $self->config->{invalid_characters} ? 'invalid_characters' : 'valid_characters' });
+ push @errors, $::locale->text('An invalid character was used (invalid characters: #1).', $char_list) if $self->config->{invalid_characters};
+ push @errors, $::locale->text('An invalid character was used (valid characters: #1).', $char_list) if $self->config->{valid_characters};
+ }
+
+ return @errors;
+}
+
+
+sub init_config {
+ my ($self) = @_;
+
+ my %cfg = %{ $::emmvee_conf{password_policy} || {} };
+
+ $cfg{valid_characters} =~ s/[ \n\r]//g if $cfg{valid_characters};
+ $cfg{invalid_characters} =~ s/[ \n\r]//g if $cfg{invalid_characters};
+ $cfg{invalid_characters_re} = '[^' . quotemeta($cfg{valid_characters}) . ']' if $cfg{valid_characters};
+ $cfg{invalid_characters_re} = '[' . quotemeta($cfg{invalid_characters}) . ']' if $cfg{invalid_characters};
+ $cfg{special_characters} = '!@#$%^&*()_+=[]{}<>\'"|\\,;.:?-';
+ $cfg{special_characters_re} = '[' . quotemeta($cfg{special_characters}) . ']';
+
+ map { $cfg{"require_${_}"} = $cfg{"require_${_}"} =~ m/^(?:1|true|t|yes|y)$/i } qw(lowercase uppercase digit special_char);
+
+ $self->config(\%cfg);
+}
+
+1;
+__END__
+
+=pod
+
+=encoding utf8
+
+=head1 NAME
+
+SL::Auth::PasswordPolicy - Verify a given password against the policy
+set in the configuration file
+
+=head1 SYNOPSIS
+
+ my $verifier = SL::Auth::PasswordPolicy->new;
+ my $result = $verifier->verify($password);
+ if ($result != SL::Auth::PasswordPolicy->OK()) {
+ print "Errors: " . join(' ', $verifier->errors($result)) . "\n";
+ }
+
+=head1 CONSTANTS
+
+=over 4
+
+=item C<OK>
+
+Password is OK.
+
+=item C<TOO_SHORT>
+
+The password is too short.
+
+=item C<TOO_LONG>
+
+The password is too long.
+
+=item C<MISSING_LOWERCASE>
+
+The password is missing a lower-case character.
+
+=item C<MISSING_UPPERCASE>
+
+The password is missing an upper-case character.
+
+=item C<MISSING_DIGIT>
+
+The password is missing a digit.
+
+=item C<MISSING_SPECIAL_CHAR>
+
+The password is missing a special character. Special characters are
+the following: ! " # $ % & ' ( ) * + , - . : ; E<lt> = E<gt> ? @ [ \ ]
+^ _ { | }
+
+=item C<INVALID_CHAR>
+
+The password contains an invalid character.
+
+=back
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item C<verify $password, $is_admin>
+
+Checks whether or not the password matches the policy. Returns C<OK()>
+if it does and an error code otherwise (binary or'ed of the error
+constants).
+
+If C<$is_admin> is trueish and the configuration specifies that the
+policy checks are disabled for the administrator then C<verify> will
+always return C<OK()>.
+
+=item C<errors $code>
+
+Returns an array of human-readable strings describing the issues set
+in C<$code> which should be the result of L</verify>.
+
+=back
+
+=head1 BUGS
+
+Nothing here yet.
+
+=head1 AUTHOR
+
+Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
+
+=cut
do_statement($form, $sth, $query, @values);
- my $valid_index = "$params{name_prefix}cvar_$config->{name}$params{name_postfix}_valid";
- $self->save_custom_variables_validity(trans_id => $params{trans_id}, config_id => $config->{id},
- validity => ($params{variables}{$valid_index} || $params{always_valid} ? 1 : 0)
- );
+ if ($params{save_validity}) {
+ my $valid_index = "$params{name_prefix}cvar_$config->{name}$params{name_postfix}_valid";
+ $self->save_custom_variables_validity(trans_id => $params{trans_id},
+ config_id => $config->{id},
+ validity => ($params{variables}{$valid_index} || $params{always_valid} ? 1 : 0)
+ );
+ }
}
$sth->finish();
sub get_first {
shift->get_all(
+ @_,
limit => 1,
)->[0];
}
}
}
- CVar->save_custom_variables('dbh' => $dbh,
- 'module' => 'IC',
- 'trans_id' => $form->{id},
- 'variables' => $form);
+ CVar->save_custom_variables(dbh => $dbh,
+ module => 'IC',
+ trans_id => $form->{id},
+ variables => $form,
+ save_validity => 1);
# commit
my $rc = $dbh->commit;
my ($price, $selectedpricegroup_id) = split(/--/, $form->{"sellprice_pg_$i"});
my $pricegroup_old = $form->{"pricegroup_old_$i"};
+
+ # sellprice has format 13,0000 or 0,00000, can't check for 0 numerically
+ my $sellprice = $form->{"sellprice_$i"};
+ my $pricegroup_id = $form->{"pricegroup_id_$i"};
$form->{"new_pricegroup_$i"} = $selectedpricegroup_id;
$form->{"old_pricegroup_$i"} = $pricegroup_old;
$pkr->{price} = $form->format_amount($myconfig, $pkr->{price}, 5);
if ($selectedpricegroup_id eq undef) {
- if ($pkr->{pricegroup_id} eq $form->{customer_klass}) {
-
+ # new entries in article list, either old invoice was loaded (edit) or a new article was added
+ # Case A: open old invoice, no pricegroup selected
+ # Case B: add new article to invoice, no pricegroup selected
+
+ # to distinguish case A and B the variable pricegroup_id_$i is used
+ # for new articles this variable isn't defined, for loaded articles it is
+ # sellprice can't be used, as it already has 0,00 set
+
+ if ($pkr->{pricegroup_id} eq $form->{"pricegroup_id_$i"} and defined $form->{"pricegroup_id_$i"}) {
+ # Case A
$pkr->{selected} = ' selected';
+ } elsif ($pkr->{pricegroup_id} eq $form->{customer_klass}
+ and not defined $form->{"pricegroup_id_$i"}
+ and $pkr->{price} != 0 # only use customer pricegroup price if it has a value, else use default_sellprice
+ # for the case where pricegroup prices haven't been set
+ ) {
+ # Case B: use default pricegroup of customer
+
+ $pkr->{selected} = ' selected'; # unless $form->{selected};
+
# no customer pricesgroup set
if ($pkr->{price} == $pkr->{default_sellprice}) {
} else {
# this sub should not set anything and only return. --sschoeling, 20090506
-# $form->{"sellprice_$i"} = $pkr->{price};
+# is this correct? put in again... -- grichardson 20110119
+ $form->{"sellprice_$i"} = $pkr->{price};
}
- } elsif ($pkr->{price} == $pkr->{default_sellprice}) {
+ } elsif ($pkr->{price} == $pkr->{default_sellprice} and $pkr->{default_sellprice} != 0) {
$pkr->{price} = $form->{"sellprice_$i"};
$pkr->{selected} = ' selected';
}
- } else {
+ }
+
+ # existing article: pricegroup or price changed
+ if ($selectedpricegroup_id or $selectedpricegroup_id == 0) {
if ($selectedpricegroup_id ne $pricegroup_old) {
+ # pricegroup has changed
if ($pkr->{pricegroup_id} eq $selectedpricegroup_id) {
$pkr->{selected} = ' selected';
}
- } elsif ( ( $form->parse_amount($myconfig, $price_new)
- != $form->parse_amount($myconfig, $form->{"sellprice_$i"}))
- and ($price_new ne 0)) {
+ } elsif (($price_new != $form->{"sellprice_$i"}) and ($price_new ne 0) and defined $price_new) {
+ # sellprice has changed
+ # when loading existing invoices $price_new is NULL
if ($pkr->{pricegroup_id} == 0) {
$pkr->{price} = $form->{"sellprice_$i"};
$pkr->{selected} = ' selected';
}
} elsif ($pkr->{pricegroup_id} eq $selectedpricegroup_id) {
+ # neither sellprice nor pricegroup changed
$pkr->{selected} = ' selected';
- if ( ($pkr->{pricegroup_id} == 0)
- and ($pkr->{price} == $form->{"sellprice_$i"})) {
+ if ( ($pkr->{pricegroup_id} == 0) and ($pkr->{price} == $form->{"sellprice_$i"})) {
# $pkr->{price} = $form->{"sellprice_$i"};
} else {
$pkr->{price} = $form->{"sellprice_$i"};
use Sys::Hostname;
use SL::Auth;
+use SL::Auth::PasswordPolicy;
use SL::Form;
use SL::Iconv;
use SL::Mailer;
$myconfig->save_member();
- if ($main::auth->can_change_password()
- && defined $form->{new_password}
- && ($form->{new_password} ne '********')) {
- $main::auth->change_password($form->{login}, $form->{new_password});
- }
-
$form->{templates} =~ s|.*/||;
$form->{templates} = "$main::templates/$form->{templates}";
$form->{mastertemplates} =~ s|.*/||;
}
}
- $form->redirect($locale->text('User saved!'));
+ if ($main::auth->can_change_password()
+ && defined $form->{new_password}
+ && ($form->{new_password} ne '********')) {
+ my $verifier = SL::Auth::PasswordPolicy->new;
+ my $result = $verifier->verify($form->{new_password}, 1);
+
+ if ($result != SL::Auth::PasswordPolicy->OK()) {
+ $form->error($::locale->text('The settings were saved, but the password was not changed.') . ' ' . join(' ', $verifier->errors($result)));
+ }
+ $main::auth->change_password($form->{login}, $form->{new_password});
+ }
+
+ $form->redirect($locale->text('User saved!'));
}
sub save_user_as_new {
use utf8;
use SL::Auth;
+use SL::Auth::PasswordPolicy;
use SL::AM;
use SL::CA;
use SL::Form;
TODO->save_user_config('login' => $form->{login}, %{ $form->{todo_cfg} || { } });
- $form->redirect($locale->text('Preferences saved!')) if (AM->save_preferences(\%myconfig, \%$form, 0));
+ if (AM->save_preferences(\%myconfig, $form)) {
+ if ($::auth->can_change_password()
+ && defined $form->{new_password}
+ && ($form->{new_password} ne '********')) {
+ my $verifier = SL::Auth::PasswordPolicy->new;
+ my $result = $verifier->verify($form->{new_password});
+
+ if ($result != SL::Auth::PasswordPolicy->OK()) {
+ $form->error($::locale->text('The settings were saved, but the password was not changed.') . ' ' . join(' ', $verifier->errors($result)));
+ }
+
+ $::auth->change_password($form->{login}, $form->{new_password});
+
+ $form->{password} = $form->{new_password};
+ $::auth->set_session_value('password', $form->{password});
+ $::auth->create_or_refresh_session();
+ }
+
+ $form->redirect($locale->text('Preferences saved!'));
+ }
+
$form->error($locale->text('Cannot save preferences!'));
$main::lxdebug->leave_sub();
$form->{exchangerate} = $form->{forex} if $form->{forex};
# format amounts
- $form->{exchangerate} =
- $form->format_amount(\%myconfig, $form->{exchangerate});
-
- if ($form->{exchangerate} == 0) {
- $form->{exchangerate} = "";
- }
-
- $form->{creditlimit} =
- $form->format_amount(\%myconfig, $form->{creditlimit}, 0, "0");
- $form->{creditremaining} =
- $form->format_amount(\%myconfig, $form->{creditremaining}, 0, "0");
+ $form->{exchangerate} = $form->{exchangerate} ? $form->format_amount(\%myconfig, $form->{exchangerate}) : '';
+ $form->{creditlimit} = $form->format_amount(\%myconfig, $form->{creditlimit}, 0, "0");
+ $form->{creditremaining} = $form->format_amount(\%myconfig, $form->{creditremaining}, 0, "0");
$exchangerate = qq|
<input type=hidden name=forex value=$form->{forex}>
if ($item->{selected} && ($pricegroup_id != 0)) {
$form->{"pricegroup_old_$j"} = $pricegroup_id;
$form->{"price_new_$j"} = $price;
- $form->{"sellprice_$j"} = $price;
+ # edit: don't change the sellprice here
+ # $form->{"sellprice_$j"} = $price; # this must only be updated for existing articles, not new ones
}
if ($pricegroup_id == 0) {
$form->{"price_new_$j"} = $form->{"sellprice_$j"};
# for last row and report
# set pricegroup drop down list from report menu
if ($form->{"sellprice_$i"} != 0) {
+ # remember the pricegroup_id in pricegroup_old
+ # but don't overwrite it
$form->{"pricegroup_old_$i"} = $form->{"pricegroup_id_$i"};
my $default_option = $form->{"sellprice_$i"}.'--'.$form->{"pricegroup_id_$i"};
- $column_data{sellprice_pg} = NTI($cgi->popup_menu("sellpricepg_$i", [ $default_option ], $default_option, { $default_option => $form->{"pricegroup_$i"} || '' }));
+ $column_data{sellprice_pg} = NTI($cgi->popup_menu("sellprice_pg_$i", [ $default_option ], $default_option, { $default_option => $form->{"pricegroup_$i"} || '' }));
} else {
$column_data{sellprice_pg} = qq| |;
}
# get pricegroups for parts
IS->get_pricegroups_for_parts(\%myconfig, \%$form);
- set_pricegroup($_) for 1 .. $form->{rowcount};
+
+ # Problem: set_pricegroup resets the sellprice of old invoices to the price
+ # currently defined in the pricegroup, which is a problem if the price has
+ # changed, as the old invoice gets the new price
+ # set_pricegroup must never be called, when an old invoice is initially loaded
+
+ # set_pricegroup($_) for 1 .. $form->{rowcount};
}
$main::lxdebug->leave_sub();
}
$form->{paidaccounts} = 1;
$form->{rowcount}--;
$form->{invdate} = $form->current_date(\%myconfig);
+
+ # remember pricegroups for "use as template"
+ IS->get_pricegroups_for_parts(\%myconfig, \%$form);
+ set_pricegroup($_) for 1 .. $form->{rowcount};
+
&display_form;
$main::lxdebug->leave_sub();
}
+ # show pricegroup in newly loaded invoice when creating invoice from quotation/order
+ IS->get_pricegroups_for_parts(\%myconfig, \%$form);
+ set_pricegroup($_) for 1 .. $form->{rowcount};
+
&display_form;
$main::lxdebug->leave_sub();
use Cwd;
-use vars qw(
-$dbcharset $eur $ghostscript_bin $html2ps_bin $language $latex_bin
-$latex_templates $lizenzen $memberfile $opendocument_templates
-$openofficeorg_daemon $openofficeorg_daemon_port $openofficeorg_writer_bin
-$pg_dump_exe $pg_restore_exe $sendmail $show_best_before $sid $spool $templates
-$use_rdbo $userspath $vertreter $webdav $xvfb_bin
+our qw(
+ $dbcharset $eur $ghostscript_bin $html2ps_bin $language $latex_bin
+ $latex_templates $lizenzen $memberfile $opendocument_templates
+ $openofficeorg_daemon $openofficeorg_daemon_port $openofficeorg_writer_bin
+ $parts_image_css $parts_listing_images $parts_show_image $pg_dump_exe
+ $pg_restore_exe $sendmail $show_best_before $sid $spool $templates
+ $use_rdbo $userspath $vertreter $webdav $xvfb_bin
);
# path to user configuration files
# Zeige Felder für Mindesthaltbarkeitsdatum
$show_best_before = 0;
+## Artikelbilder anzeigen
+# Artikelbild in der Detailansicht anzeigen
+$parts_show_image = 1; # [0|1]
+$parts_image_css = 'border:0;float:left;max-width:250px;margin-top:20px:margin-right:10px;margin-left:10px;'; # [belibige valide css definiton]
+# Artikelbilder per default in den Suchergebnissen anzeigen
+$parts_listing_images = 0; # [0|1]
+
## Support fuer OpenDocument-Vorlagen
# Diese Option legt fest, ob OpenDocument-Vorlagen generell verfuegbar sind.
$opendocument_templates = 1;
use Cwd;
-use vars qw(
+our qw(
$dbcharset $eur $ghostscript_bin $html2ps_bin $language $latex_bin
$latex_templates $lizenzen $memberfile $opendocument_templates
$openofficeorg_daemon $openofficeorg_daemon_port $openofficeorg_writer_bin
$parts_image_css $parts_listing_images $parts_show_image $pg_dump_exe
- $pg_restore_exe $sendmail $show_best_before $sid $spool $templates $userspath
- $vertreter $webdav $xvfb_bin
+ $pg_restore_exe $sendmail $show_best_before $sid $spool $templates
+ $use_rdbo $userspath $vertreter $webdav $xvfb_bin
);
-
# path to user configuration files
$userspath = "users";
# member file
$memberfile = "users/members";
-# Wenn nicht Bilanzierung dann auf 1 setzen
+# Wenn Einnahmen-Überschussrechnung, dann auf 1 setzen
+# Wenn Bilanzierung (z.B. GmbH), dann auf 0 setzen
$eur = 1;
# location of sendmail
$sendmail = '| /usr/sbin/sendmail -t<%if myconfig_email%> -f <%myconfig_email%><%end%>';
# set language for login and admin
+# currently "de" (German), "de_DE" (new German) and "en" (English, not perfect) are available
$language = "de";
# Oracle
$webdav = 0;
$lizenzen = 1;
$vertreter = 0;
+$excel_templates = 0; # Minimalunterstützung für Excel-Druckvorlagen
# Zeige Felder für Mindesthaltbarkeitsdatum
$show_best_before = 0;
$pg_dump_exe = "pg_dump";
$pg_restore_exe = "pg_restore";
+# Rose::DB::Object Environment laden.
+# Die RDBO Klassen bieten für Addon Schreiber sehr einfache Interfaces zu den
+# bestehenden Klassen, haben aber den Nachteil, dass der Start des Programms
+# etwa 2s mehr dauert. Damit fällt die Möglichkeit Lx-Office über CGI zu
+# betreiben weg.
+$use_rdbo = 1;
+
# Globale Debug-Ausgaben (de-)aktivieren? Moegliche Werte sind
# LXDebug::NONE - keine Debugausgaben
# LXDebug::INFO
#
# Beipiel:
# $LXDebug::global_level = LXDebug::TRACE | LXDebug::QUERY;
-$LXDebug::global_level = LXDebug::NONE;
+$LXDebug::global_level = LXDebug->NONE;
# Überwachung der Inhalte von $form aktiviert oder nicht? Wenn ja,
# dann können einzelne Variablen mit
# location of history file for permanent history
history_file = users/console_history
+# Settings used when the user changes his/her password. All options
+# default to no restriction if unset.
+[password_policy]
+# Minimum length in number of characters.
+min_length =
+# Maximum length in number of characters.
+max_length =
+# Require a lowe-case character?
+require_lowercase =
+# Require an upper-case character?
+require_uppercase =
+# Require a digit?
+require_digit =
+# Require a special char? Special chars are the following:
+# ! " # $ % & ' ( ) * + , - . : ; < = > ? @ [ \ ] ^ _ { | }
+require_special_character =
+# Optional list of valid characters. Spaces are ignored. If set then
+# the password must only consist of these characters.
+valid_characters =
+# Optional list of invalid characters. Spaces are ignored.
+invalid_characters =
+# Whether or not to check the policy if the password is set from the
+# user administration.
+disable_policy_for_admin =
+# Whether or not to check for weak passwords with the "cracklib"
+# library. Requires the Perl module "Crypt::Cracklib" to be installed.
+use_cracklib =
+
[debug]
# Use DBIx::Log4perl for logging DBI calls. The string LXDEBUGFILE
# will be replaced by the file name configured for $::lxdebug.
Distribution sollte für die automatische Installation der anderen
zwei Pakete sorgen)
+ Neue Gruppenrechte
+ ------------------
+
+Es wurde ein neues Recht "Druck" eingeführt. Dieses bestimmt, ob die
+Benutzerin das Menü "Druck" zu Gesicht bekommt oder nicht, unabhängig
+davon, wie die Rechte für die einzelnen Unterpunkte gesetzt sind.
+
+Für bereits bestehende Gruppen muss es sofern gewünscht vom
+Administrator manuell gewährt werden.
+
Upgrade auf v2.6.1
==================
# Veränderungen von Lx-Office ERP #
###################################
-
-
-
+2011-02-?? - Release 2.6.2
Größere neue Features:
Das Program läuft jetzt optional unter FastCGI, und damit etwa um
Faktor 10 schneller. Siehe Dokumentation in doc INSTALL.fcgi.
+ - Neues Gruppenrecht "Druck"
+
+ Es wurde ein neues Recht "Druck" eingeführt. Dieses bestimmt, ob
+ die Benutzerin das Menü "Druck" zu Gesicht bekommt oder nicht,
+ unabhängig davon, wie die Rechte für die einzelnen Unterpunkte
+ gesetzt sind.
+
+ Für bereits bestehende Gruppen muss es sofern gewünscht vom
+ Administrator manuell gewährt werden.
+
Kleinere neue Features und Detailverbesserungen:
- Druckvorlage optional auf Excel erweitert, um Variablen die sich nicht in foreach-Schleifen
Liste gefixter Bugs aus dem Bugtracker:
-
- - Bug 1388 - Berichte sind defekt, wenn abweichendes Datumsformat (ISO) eingestellt ist
- - Bug 1395 - Einlagern ueber Lieferschein: Einheiten entsprechen nicht den Standardeinheiten der Artikel
- - Bug 1398 - Im Lagerjournal werden Projektnummern nicht erfasst
- - Bug 1409 - Bei "Erzeugnis fertigen" wird nur der Bestand der letzten Komponente geprüft
- - Bug 1412 - Wenn die Ware ausgewählt werden muss wird der Rabatt verworfen
- - Bug 1421 - Stornorechnungen loeschen bereitet Probleme
- - Bug 1484 - Das Ankreuzfeld 'alle' hat keine Funktion wenn man einen Auswahlliste (multibox) an Lieferanten hat
- Es wird trotzdem nach der Auswahlliste gefiltert und die Option 'alle' wird
- ignoriert auch wenn man auf Erneuern klickt.
- Das Eingabefeld 'Betrag' im oberen Teil der Maske hat in Lx-Office
- keinen Sinn mehr, da nur noch über die Auswahl der offenen
- Kreditorenposten ein Zahlungsausgang veranlasst wird.
- Neu-Aufbau Lx-Office Bildschirm
- Nach einer erfolgreichen Buchung erscheint die Meldung: 'Zahlung gebucht.' und
- die Startseite wird angezeigt. Wünschenwert wäre es, wenn man in
- Zahlungsverkehr bleiben würde, optimalerweise mit vorbelegten Feldern.
- - Bug 1502 - 2. Zahlung buchen, auch wenn die erste Zahlung in einen abgeschlossenen Zeitraum liegt
-
+ - Bugfix 1131: Einkaufslieferscheine: Mengen muessen beim Auslagern manuell in die maske eingetragen werden
+ - Bugfix 1154: Debitoren und Kreditoren werden nicht korrekt gebucht
+ - Bugfix 1185: Preis überschreiben bei Preisgruppe
+ - Bugfix 1220: Zahlungsverkehr - Zahlungseingang: Aufteilung des Rechnungsbetrages
+ - Bugfix 1277: Fehler in der BWA Zuordnung in den SKR03 und dem daraus generierten skr04
+ - Bugfix 1298: SKR04 überarbeitet
+ - Bugfix 1302: Inkonsistenz in Buchungsdaten: In Verkaufsrechnungen wird die Zahlung nicht angezeit, Gegenbuchung fehlt
+ - Bugfix 1367: Feature-Vorschlag: SEPA auch für Lastschriften von Debitoren unterstützen
+ - Bugfix 1370: Umlautfehler beim Erfassen einer Einkaufsrechnung
+ - Bugfix 1375: Übersetzungsdateien im Verzeichnis ""locale/de/"" immer noch in ISO-8859-15 kodiert statt UTF-8
+ - Bugfix 1376: Benutzerdefinierte Variablen sollten auch im mahnsystem zur Verfuegung stehen
+ - Bugfix 1378: leere Buchungen (text, beschreibung und referenz) bei Splittbuchungen
+ - Bugfix 1381: missing files in package
+ - Bugfix 1383: Dienstleistungen in Stammdaten und Lager
+ - Bugfix 1384: Zinsen bei Mahnung falsch berechnet
+ - Bugfix 1387: Englische Eingabemaske bei Aufruf von Deb./Kred.-buchung aus Buchungsjournal
+ - Bugfix 1388: Berichte sind defekt, wenn abweichendes Datumsformat (ISO) eingestellt ist
+ - Bugfix 1389: Bilanz repariert
+ - Bugfix 1393: CSV-Export sollte ohne Tausender-Trenner erfolgen
+ - Bugfix 1395: Einlagern ueber Lieferschein: Einheiten entsprechen nicht den Standardeinheiten der Artikl
+ - Bugfix 1398: Im Lagerjournal werden Projektnummern nicht erfasst
+ - Bugfix 1399: Lieferdaten zu einzelnen Positionen ""verrutschen"" beim Loeschen hoeherer Positionszeilen
+ - Bugfix 1400: Lieferscheine: Usability bei Auslagerung - Positionsindikator
+ - Bugfix 1406: Kunde erfassen
+ - Bugfix 1410: Beschriftung bei Eingabe der Einkaufsrechnung falsch
+ - Bugfix 1412: Wenn die Ware ausgewählt werden muss wird der Rabatt verworfen
+ - Bugfix 1414: Einfügen der \usepackage{textcomp}-Zeile in TeX-Templates ungünstig
+ - Bugfix 1422: Loeschen von Stornos bereitet eine Reihe von Problemen: (3)Gutschriften aus Rechnungen, die einstmals storniert wurden
+ - Bugfix 1429: Debitorenbuchungen 1: Wechsel des Debitoren loescht Bemerkungsfeld nicht
+ - Bugfix 1432: Mahnläufe: Nach manuellem Zurücksetzen der Mahnstufen gibt es ein Chaos bei der weiteren Erzeugung
+ - Bugfix 1439: Sortierkriterium ""Strasse"" in Listenansicht der Lieferanten geht nicht
+ - Bugfix 1440: Eingrenzen der angelegten Waren nach Lieferant liefert immer kein Ergebnis
+ - Bugfix 1445: Kleines Chaos bei Vorlagenbezeichnungen zu Lieferscheinen: picklist, packing_list, sales_delivery_order
+ - Bugfix 1449: Konto 3170 langfristige Verbindlichkeiten SKR04 Aktiva
+ - Bugfix 1451: Menüsetup Alt (seitlich) wird nicht lokalisiert
+ - Bugfix 1452: Fehler bei Lokalisierung der Überschriften und weiterer Beschriftungen
+ - Bugfix 1454: mehrere Rechnungen mit gleicher Rechnungsnummer möglich
+ - Bugfix 1455: Feld wird nach Einlagerung nicht zurückgesetzt.
+ - Bugfix 1456: Lieferanschrift wird im Workflow nicht zuverlässig vom Auftrag in den Lieferschein übernommen
+ - Bugfix 1459: Gruppen bearbteien unter FCGI
+ - Bugfix 1467: System entsperren nicht möglich
+ - Bugfix 1468: Title Javascript setzt den Titel auch, wenn die Informationen nicht verfügbar sind.
+ - Bugfix 1469: Umlaute gehen auf der Startseite kaputt bei update von 2.6.1 auf unstable (August 2010)
+ - Bugfix 1470: Falsche Übersetzung für ""Expenses EU without UStId""
+ - Bugfix 1471: System -> Historien Suchmaschinen gibt folgenden Fehler:
+ - Bugfix 1472: Bei fehlender config/authentication.pl -> Webserver Error 500
+ - Bugfix 1475: Workflow Angebot -> Rechnung wird Angebotsnummer nicht übernommen
+ - Bugfix 1477: Sicherheitsloch bei 2.6er Versionen
+ - Bugfix 1479: Debian Paket bauen schlägt fehl
+ - Bugfix 1480: Filter für Abteilungen ohne Ergebnis
+ - Bugfix 1483: Formelberechnung und Zahlenformat
+ - Bugfix 1484: Zahlungsausgang diverses
+ - Bugfix 1485: Rechnung->neuer Artikel->Speichern->Fehler ""Can't use string ... as a HASH ref ... bin/mozilla/io.pl line 2075""
+ - Bugfix 1487: Wechselkurs wird falsch ausgelesen
+ - Bugfix 1488: Ust-Voranmeldung - Elster-Export nach Taxbird
+ - Bugfix 1491: Nitpicking: Beim ersten Login in eine DB werden im Text HTML Formatierungen ausgegeben, nicht interpretiert
+ - Bugfix 1492: ""Korrekturen im Hauptbuch"" wirft Fehler
+ - Bugfix 1494: undokumentiert -- dependency parent.pm / Dokumentvariable ustid
+ - Bugfix 1495: Ansicht von Artikelbilderen (Suchergebnis/Artikelmaske)
+ - Bugfix 1496: Grad-Symbol (°) verursacht Latex-Fehler
+ - Bugfix 1498: (versehentlicher?) commit der menu.ini mit crm Spalte
+ - Bugfix 1499: Einstellungen ""Nicht rabattierfähig"" ist nicht für Dienstleistungen verfügbar (z.B. Versandkosten)
+ - Bugfix 1502: Bücherkontrolle prüft auch ALTE Zahlungseingänge
+ - Bugfix 1504: UStVa Modul SQL Fehler: ""text >= integer"" nicht erlaubt
+ - Bugfix 1506: Email-Formular: Mailadresse der Firma anstelle des Ansprechpartners
+ - Bugfix 1517: Kreditorrechnung: Wechselkurs bei gleichem Re.-Datum nicht vorhanden
+ - Bugfix 1520: Division-by-Zero-Fehler bei einigen Rechnungsbuchungen
+ - Bugfix 1521: Fix von Bug 1521 bringt neuen Fehler bei Login und Verkaufsmasken
+ - Bugfix 1523: Rabatt geht verloren, wenn Rechnung aus Lieferscheinliste generiert wird
+ - Bugfix 1524: Kundenrabatt geht verloren (wie 1284, aber auch Einkauf)
+ - Bugfix 1528: Vorlagen
+ - Bugfix 1529: falsche Tabellendefinition in Default-request_quotation.tex
+ - Bugfix 1530: Debitorenbuchung: Abfragefehler bei Kontonummer mit ""."" (Punkt) oder Text
+ - Bugfix 1533: Zahlungen in Rechnungsmaske einbuchen scheitert an locale
+ - Bugfix 1535: CSV-Exporte sind nicht mehr UTF8
+ - Bugfix 1536: 'Alte' dbupgrade Skripte die SL::DBUtils verwenden sind defekt
+ - Bugfix 1537: Debitoren: Feld curr in Tabelle ar wird nicht gefüllt
+ - Bugfix 1541: Preisgruppeneintrag in Einkaufsrechungen ??
+ - Bugfix 1547: Kreditorenbuchung in Fremdwährung: Steuerfehler
+ - Bugfix 1550: Sortieren einer Kundenauflistung ""vergisst"" gewählte Filterkriterien
+ - Bugfix 1552: Diverse Probleme mit der Sortierfunktion bei Stammdaten
+ - Bugfix 1553: Diese Kundennummer wird bereits verwendet. - Obwohl keine eingetragen ist
+ - Bugfix 1554: Kein Wechselkurs bei Debitotenbuchung in Fremdwährung unter 1 bei gleichem Datum
+ - Bugfix 1555: Sonderzeichen nicht korrekt escaped (Stückliste beim Erstellen eines Erzeugnisses)
+ - Bugfix 1561: benutzerdefinierte Variable wird unabsichtlich deaktiviert
+ - Bugfix 1562: Fehlender Hinweis im changelog zu gaenderten Rechten Beim Druck
2010-03-24 - Release 2.6.1
'4. Quarter' => '4. Quartal',
'<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ös- und Aufwandskonten für diese vier Steuerzonen sowie aus einem Inventarkonto.',
+ 'A digit is required.' => 'Eine Ziffer ist vorgeschrieben.',
'A group named "Full Access" has been created.' => 'Eine Gruppe namens "Vollzugriff" wurde angelegt.',
'A group with that name does already exist.' => 'Eine Gruppe mit diesem Namen gibt es bereits.',
'A lot of the usability of Lx-Office has been enhanced with javascript. Although it is currently possible to use every aspect of Lx-Office without javascript, we strongly recommend it. In a future version this may change and javascript may be necessary to access advanced features.' => 'Die Bedienung von Lx-Office wurde an vielen Stellen mit Javascript verbessert. Obwohl es derzeit möglich ist, jeden Aspekt von Lx-Office auch ohne Javascript zu benutzen, empfehlen wir es. In einer zukünftigen Version wird Javascript eventuell notwendig sein um weitergehende Features zu benutzen.',
+ 'A lower-case character is required.' => 'Ein Kleinbuchstabe ist vorgeschrieben.',
+ 'A special character is required (valid characters: #1).' => 'Ein Sonderzeichen ist vorgeschrieben (gültige Zeichen: #1).',
'A temporary directory could not be created:' => 'Ein temporäres Verzeichnis konnte nicht erstellt werden:',
'A temporary file could not be created. Please verify that the directory "#1" is writeable by the webserver.' => 'Eine temporäre Datei konnte nicht angelegt werden. Bitte stellen Sie sicher, dass das Verzeichnis "#1" vom Webserver beschrieben werden darf.',
'A temporary file could not be created:' => 'Eine temporäre Datei konnte nicht erstellt werden:',
'Amount' => 'Betrag',
'Amount Due' => 'Betrag fällig',
'Amount has to be greater then zero! Wrong row number: ' => 'Leere Eingabe oder Werte kleiner, gleich null eingegeben. Fehler in Reihe Nummer: ',
+ 'An invalid character was used (invalid characters: #1).' => 'Ein ungültiges Zeichen wurde benutzt (ungültige Zeichen: #1).',
+ 'An invalid character was used (valid characters: #1).' => 'Ein ungültiges Zeichen wurde benutzt (gültige Zeichen: #1).',
+ 'An upper-case character is required.' => 'Ein Großbuchstabe ist vorgeschrieben.',
'Annotations' => 'Anmerkungen',
'Another user with the login #1 does already exist.' => 'Es existiert bereits ein anderer Benutzer mit diesem Login.',
'Ap aging on %s' => 'Offene Verbindlichkeiten zum %s',
'Help Template Variables' => 'Hilfe zu Dokumenten-Variablen',
'Here\'s an example command line:' => 'Hier ist eine Kommandozeile, die als Beispiel dient:',
'Hide by default' => 'Standardmäßig verstecken',
- 'History' => 'Historie',
'History Search' => 'Historien Suche',
'History Search Engine' => 'Historien Suchmaschine',
'Homepage' => 'Homepage',
'The parts have been removed.' => 'Die Waren wurden aus dem Lager entnommen.',
'The parts have been stocked.' => 'Die Artikel wurden eingelagert.',
'The parts have been transferred.' => 'Die Waren wurden umgelagert.',
+ 'The password is too long (maximum length: #1).' => 'Das Passwort ist zu lang (maximale Länge: #1).',
+ 'The password is too short (minimum length: #1).' => 'Das Password ist zu kurz (minimale Länge: #1).',
+ 'The password is weak (e.g. it can be found in a dictionary).' => 'Das Passwort ist schwach (z.B. wenn es in einem Wörterbuch steht).',
'The payments have been posted.' => 'Die Zahlungen wurden gebucht.',
'The pg_dump process could not be started.' => 'Der pg_dump-Prozess konnte nicht gestartet werden.',
'The pg_restore process could not be started.' => 'Der pg_restore-Prozess konnte nicht gestartet werden.',
'The selected warehouse does not exist.' => 'Das ausgewählte Lager existiert nicht.',
'The selected warehouse is empty.' => 'Das ausgewählte Lager ist leer.',
'The session is invalid or has expired.' => 'Sie sind von Lx-Office abgemeldet.',
+ 'The settings were saved, but the password was not changed.' => 'Die Einstellungen wurden gespeichert, aber das Passwort wurde nicht geändert.',
'The source warehouse does not contain any bins.' => 'Das Quelllager enthält keine Lagerplätze.',
'The start date is missing.' => 'Das Startdatum fehlt.',
'The subject is missing.' => 'Der Betreff fehlt.',
my $basedir = "../..";
my $locales_dir = ".";
my $bindir = "$basedir/bin/mozilla";
-my @progdirs = ( "$basedir/SL/Controller", "$basedir/SL/Template/Plugin" );
+my @progdirs = ( "$basedir/SL/Controller", "$basedir/SL/Template/Plugin", "$basedir/SL/Auth" );
my $dbupdir = "$basedir/sql/Pg-upgrade";
my $dbupdir2 = "$basedir/sql/Pg-upgrade2";
my $menufile = "menu.ini";
--- /dev/null
+-- @tag: invalid_entries_in_custom_variables_validity
+-- @description: Ungültige Einträge in custom_variables_validity bereinigen
+-- @depends: release_2_6_1
+-- @charset: utf-8
+DELETE FROM custom_variables_validity
+WHERE trans_id NOT IN (
+ SELECT id
+ FROM parts
+);