From: Sven Schöling Date: Wed, 8 Aug 2012 15:48:29 +0000 (+0200) Subject: Merge branch 'master' of vc.linet-services.de:public/lx-office-erp X-Git-Tag: release-3.0.0beta1~297^2~17 X-Git-Url: http://wagnertech.de/gitweb/gitweb.cgi/mfinanz.git/commitdiff_plain/4ab897fdb1a54cd753ec66ebc8fbd5ffdd883cd6?hp=dc3f6120f9bbacaa028e554d7fa71e481d4497b4 Merge branch 'master' of vc.linet-services.de:public/lx-office-erp --- diff --git a/SL/Controller/CsvImport/Part.pm b/SL/Controller/CsvImport/Part.pm index 6c056d0f9..3be6f2a44 100644 --- a/SL/Controller/CsvImport/Part.pm +++ b/SL/Controller/CsvImport/Part.pm @@ -201,7 +201,7 @@ sub check_existing { if ($self->settings->{article_number_policy} eq 'update_prices') { if ($entry->{part}) { - map { $entry->{part}->$_( $object->$_ ) } qw(sellprice listprice lastcost); + map { $entry->{part}->$_( $object->$_ ) if defined $object->$_ } qw(sellprice listprice lastcost); # merge prices my %prices_by_pricegroup_id = map { $_->pricegroup->id => $_ } $entry->{part}->prices, $object->prices; diff --git a/SL/IR.pm b/SL/IR.pm index d8569acaa..444dffceb 100644 --- a/SL/IR.pm +++ b/SL/IR.pm @@ -210,7 +210,7 @@ sub post_invoice { # update parts table by setting lastcost to current price, don't allow negative values by using abs $query = qq|UPDATE parts SET lastcost = ? WHERE id = ?|; - @values = (abs($form->{"sellprice_$i"}), conv_i($form->{"id_$i"})); + @values = (abs($form->{"sellprice_$i"} / $basefactor), conv_i($form->{"id_$i"})); do_query($form, $dbh, $query, @values); # check if we sold the item already and @@ -338,7 +338,7 @@ sub post_invoice { # update lastcost $query = qq|UPDATE parts SET lastcost = ? WHERE id = ?|; - do_query($form, $dbh, $query, $form->{"sellprice_$i"}, conv_i($form->{"id_$i"})); + do_query($form, $dbh, $query, $form->{"sellprice_$i"} / $basefactor, conv_i($form->{"id_$i"})); } next if $payments_only; diff --git a/SL/SessionFile.pm b/SL/SessionFile.pm index dbed4154b..69997e9a1 100644 --- a/SL/SessionFile.pm +++ b/SL/SessionFile.pm @@ -95,7 +95,7 @@ destroyed or expires use SL::SessionFile; # Create a session file named "customer.csv" (relative names only) - my $sfile = SL::SessionFile->new("customer.csv", "w"); + my $sfile = SL::SessionFile->new('customer.csv', mode => 'w'); $sfile->fh->print("col1;col2;col3\n" . "value1;value2;value3\n"); $sfile->fh->close; diff --git a/SL/System/Process.pm b/SL/System/Process.pm new file mode 100644 index 000000000..0bddfd6b3 --- /dev/null +++ b/SL/System/Process.pm @@ -0,0 +1,61 @@ +package SL::System::Process; + +use strict; + +use parent qw(Rose::Object); + +use English qw(-no_match_vars); +use File::Spec; +use File::Basename; + +sub exe_dir { + my $dir = dirname(File::Spec->rel2abs($PROGRAM_NAME)); + my $system_dir = File::Spec->catdir($dir, 'SL', 'System'); + return $dir if -d $system_dir && -f File::Spec->catfile($system_dir, 'TaskServer.pm'); + + my @dirs = reverse File::Spec->splitdir($dir); + shift @dirs; + $dir = File::Spec->catdir(reverse @dirs); + $system_dir = File::Spec->catdir($dir, 'SL', 'System'); + return File::Spec->curdir unless -d $system_dir && -f File::Spec->catfile($system_dir, 'TaskServer.pm'); + + return $dir; +} + +1; +__END__ + +=pod + +=encoding utf8 + +=head1 NAME + +SL::System::Process - assorted system-relevant functions + +=head1 SYNOPSIS + + # Get base path to Kivitendo scripts + my $path = SL::System::Process->exe_dir; + +=head1 FUNCTIONS + +=over 4 + +=item C + +Returns the absolute path to the directory the Kivitendo executables +(C etc.) and modules (sub-directory C etc.) are located +in. + +=back + +=head1 BUGS + +Nothing here yet. + +=head1 AUTHOR + +Moritz Bunkus Em.bunkus@linet-services.deE + +=cut diff --git a/SL/System/TaskServer.pm b/SL/System/TaskServer.pm new file mode 100644 index 000000000..bceb8f598 --- /dev/null +++ b/SL/System/TaskServer.pm @@ -0,0 +1,185 @@ +package SL::System::TaskServer; + +use strict; + +use parent qw(Rose::Object); + +use Rose::Object::MakeMethods::Generic ( + scalar => [ qw(last_command_output) ], +); + +use File::Slurp; +use File::Spec::Functions qw(:ALL); + +use SL::System::Process; + +use constant { + OK => 0, + ERR_PID_FILE => -1, + ERR_PROCESS => -2, +}; + +sub status { + my ($self) = @_; + + my $pid = $self->_read_pid; + return ERR_PID_FILE unless $pid; + + return kill(0, $pid) ? OK : ERR_PROCESS; +} + +sub is_running { + my ($self) = @_; + + return $self->status == OK; +} + +sub start { + my ($self) = @_; + + return $self->_run_script_command('start'); +} + +sub stop { + my ($self) = @_; + + return $self->_run_script_command('stop'); +} + +sub wake_up { + my ($self) = @_; + + my $pid = $self->_read_pid; + return undef unless $pid; + return kill('ALRM', $pid) ? 1 : undef; +} + +# +# private methods +# + +sub _read_pid { + my ($self) = @_; + + my $exe_dir = SL::System::Process->exe_dir; + my $pid_file_name = join '.', splitdir($exe_dir), 'config.lx_office.conf.pid'; + my $pid_file_path = catfile(catdir($exe_dir, 'users', 'pid'), $pid_file_name); + + return undef unless -f $pid_file_path; + return join('', read_file($pid_file_path)) * 1; +} + +sub _run_script_command { + my ($self, $command) = @_; + + my $exe = catfile(catdir(SL::System::Process->exe_dir, 'scripts'), 'task_server.pl'); + $self->last_command_output(`${exe} ${command}`); + + return $? == 0 ? 1 : undef; +} + +1; +__END__ + +=pod + +=encoding utf8 + +=head1 NAME + +SL::System::TaskServer - programmatic interface to the external task server component + +=head1 SYNOPSIS + + # Create interface + my $task_server = SL->TaskServer->new; + + # Start the server if it is not running + if (!$task_server->is_running) { + $task_server->start; + } + + # Stop it if it is running + if ($task_server->is_running) { + $task_server->stop; + } + +=head1 FUNCTIONS + +=over 4 + +=item C + +Returns C if the server is running. This is done by using +Perl's C function with a "signal" of C<0> for the process ID +which in turn is read from the daemon's PID file. + +If the PID file is not found or if C returns a non-successful +value then a C value is returned. + +=item C + +Returns the output of the last C command executed, e.g. from a +call to L or L. + +=item C + +Starts the task server. Does not check whether or not it is running, +neither before not after trying to start it. + +Returns C<1> if the system command C<./scripts/task_server.pl start> +exits with an exit code of C<0> and C otherwise. + +The command's output can be queried with L. + +=item C + +Queries the task server status. Returns one of these values: + +=over 4 + +=item * + +C or C<0>: the task server is running and signals can be sent to +it. + +=item * + +C or C<-1>: the PID file could not be found or read + +=item * + +C or C<-2>: the PID file could was found and read, but +it's not possible to send signals to the process, e.g. because it is +not running or owned by a different user ID. + +=back + +=item C + +Stops the task server. Does not check whether or not it is running, +neither before not after trying to start it. + +Returns C<1> if the system command C<./scripts/task_server.pl stop> +exits with an exit code of C<0> and C otherwise. + +The command's output can be queried with L. + +=item C + +Sends a signal to the task server process causing it to wake up and +process its job queue immediately. + +Returns C<1> if the signal could be sent and C otherwise. + +=back + +=head1 BUGS + +Nothing here yet. + +=head1 AUTHOR + +Moritz Bunkus Em.bunkus@linet-services.deE + +=cut diff --git a/doc/Lx-Office-Dokumentation.pdf b/doc/Lx-Office-Dokumentation.pdf index 24c0ebc95..fe1d25d67 100644 Binary files a/doc/Lx-Office-Dokumentation.pdf and b/doc/Lx-Office-Dokumentation.pdf differ diff --git a/doc/dokumentation.xml b/doc/dokumentation.xml index 76a5b64a1..5e14aa3a1 100644 --- a/doc/dokumentation.xml +++ b/doc/dokumentation.xml @@ -808,8 +808,8 @@ Alias /url/for/lx-office-erp-fcgid/ /path/to/lx-office-erp/ Kopieren Sie die Datei - scripts/boot/system-v/lx-office-task-server - nach /etc/init.d/lx-office-task-server. Passen + scripts/boot/system-v/kivitendo-server + nach /etc/init.d/kivitendo-server. Passen Sie in der kopierten Datei den Pfad zum Task-Server an (Zeile DAEMON=....). Binden Sie das Script in den Boot-Prozess ein. Dies ist distributionsabhängig: @@ -818,20 +818,20 @@ Alias /url/for/lx-office-erp-fcgid/ /path/to/lx-office-erp/ Debian-basierende Systeme: - update-rc.d lx-office-task-server defaults + update-rc.d kivitendo-task-server defaults # Nur bei Debian Squeeze und neuer: -insserv lx-office-task-server +insserv kivitendo-task-server OpenSuSE und Fedora Core: - chkconfig --add lx-office-task-server + chkconfig --add kivitendo-task-server Danach kann der Task-Server mit dem folgenden Befehl gestartet - werden: /etc/init.d/lx-office-task-server + werden: /etc/init.d/kivitendo-task-server start @@ -839,13 +839,13 @@ insserv lx-office-task-server Upstart-basierende Systeme (z.B. Ubuntu) Kopieren Sie die Datei - scripts/boot/upstart/lx-office-task-server.conf - nach /etc/init/lx-office-task-server.conf. + scripts/boot/upstart/kivitendo-task-server.conf + nach /etc/init/kivitendo-task-server.conf. Passen Sie in der kopierten Datei den Pfad zum Task-Server an (Zeile exec ....). Danach kann der Task-Server mit dem folgenden Befehl gestartet - werden: service lx-office-task-server + werden: service kivitendo-task-server start diff --git a/doc/html/ch02s06.html b/doc/html/ch02s06.html index 0cfc2a9bb..bbcde3205 100644 --- a/doc/html/ch02s06.html +++ b/doc/html/ch02s06.html @@ -31,21 +31,21 @@ zwangsläufig funktioniert, werden auch Start-Scripte mitgeliefert, die anstelle eines symbolischen Links verwendet werden können.

2.6.2.1. SystemV-basierende Systeme (z.B. Debian, OpenSuSE, Fedora Core)

Kopieren Sie die Datei - scripts/boot/system-v/lx-office-task-server - nach /etc/init.d/lx-office-task-server. Passen + scripts/boot/system-v/kivitendo-server + nach /etc/init.d/kivitendo-server. Passen Sie in der kopierten Datei den Pfad zum Task-Server an (Zeile DAEMON=....). Binden Sie das Script in den - Boot-Prozess ein. Dies ist distributionsabhängig:

  • Debian-basierende Systeme:

    update-rc.d lx-office-task-server defaults
    +          Boot-Prozess ein. Dies ist distributionsabhängig:

    • Debian-basierende Systeme:

      update-rc.d kivitendo-task-server defaults
       # Nur bei Debian Squeeze und neuer:
      -insserv lx-office-task-server
    • OpenSuSE und Fedora Core:

      chkconfig --add lx-office-task-server

    Danach kann der Task-Server mit dem folgenden Befehl gestartet - werden: /etc/init.d/lx-office-task-server +insserv kivitendo-task-server

  • OpenSuSE und Fedora Core:

    chkconfig --add kivitendo-task-server

Danach kann der Task-Server mit dem folgenden Befehl gestartet + werden: /etc/init.d/kivitendo-task-server start

2.6.2.2. Upstart-basierende Systeme (z.B. Ubuntu)

Kopieren Sie die Datei - scripts/boot/upstart/lx-office-task-server.conf - nach /etc/init/lx-office-task-server.conf. + scripts/boot/upstart/kivitendo-task-server.conf + nach /etc/init/kivitendo-task-server.conf. Passen Sie in der kopierten Datei den Pfad zum Task-Server an (Zeile exec ....).

Danach kann der Task-Server mit dem folgenden Befehl gestartet - werden: service lx-office-task-server + werden: service kivitendo-task-server start

2.6.3. Wie der Task-Server gestartet und beendet wird

Der Task-Server wird wie folgt kontrolliert:

./scripts/task_server.pl Befehl

Befehl ist dabei eine der folgenden diff --git a/scripts/boot/system-v/kivitendo-task-server b/scripts/boot/system-v/kivitendo-task-server new file mode 100755 index 000000000..cab569610 --- /dev/null +++ b/scripts/boot/system-v/kivitendo-task-server @@ -0,0 +1,49 @@ +#!/bin/sh + +### BEGIN INIT INFO +# Provides: kivitendo-task-server +# Required-Start: $local_fs $remote_fs $network $syslog $named +# Required-Stop: $local_fs $remote_fs $network $syslog $named +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# X-Interactive: true +# Short-Description: Start/stop the Kivitendo task server +### END INIT INFO + +set -e + +# Change this to point to the Kivitendo "task_server.pl" location. +DAEMON="/opt/kivitendo/scripts/task_server.pl" +TOPIC="Kivitendo task server" + +if [ ! -x $DAEMON ] ; then + echo "$TOPIC executable not found" + exit 1 +fi + +case $1 in + start) + echo "Starting the $TOPIC" + $DAEMON start + ;; + stop) + echo "Stopping the $TOPIC" + $DAEMON stop + ;; + restart) + echo "Restarting the $TOPIC" + $DAEMON restart + ;; + status) + if $DAEMON status > /dev/null 2> /dev/null; then + echo "The $TOPIC is running" + else + echo "The $TOPIC is not running" + exit 1 + fi + ;; + *) + echo "Usage: /etc/init.d/kivitendo-task-server {start|stop|reload|status}" + exit 1 + ;; +esac diff --git a/scripts/boot/system-v/lx-office-task-server b/scripts/boot/system-v/lx-office-task-server deleted file mode 100755 index 1beb1d84c..000000000 --- a/scripts/boot/system-v/lx-office-task-server +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh - -### BEGIN INIT INFO -# Provides: lx-office-task-server -# Required-Start: $local_fs $remote_fs $network $syslog $named -# Required-Stop: $local_fs $remote_fs $network $syslog $named -# Default-Start: 2 3 4 5 -# Default-Stop: 0 1 6 -# X-Interactive: true -# Short-Description: Start/stop the Lx-Office task server -### END INIT INFO - -set -e - -# Change this to point to the Lx-Office "task_server.pl" location. -DAEMON="/opt/lx-office/scripts/task_server.pl" -TOPIC="Lx-Office task server" - -if [ ! -x $DAEMON ] ; then - echo "$TOPIC executable not found" - exit 1 -fi - -case $1 in - start) - echo "Starting the $TOPIC" - $DAEMON start - ;; - stop) - echo "Stopping the $TOPIC" - $DAEMON stop - ;; - restart) - echo "Restarting the $TOPIC" - $DAEMON restart - ;; - status) - if $DAEMON status > /dev/null 2> /dev/null; then - echo "The $TOPIC is running" - else - echo "The $TOPIC is not running" - exit 1 - fi - ;; - *) - echo "Usage: /etc/init.d/lx-office-task-server {start|stop|reload|status}" - exit 1 - ;; -esac diff --git a/scripts/boot/upstart/kivitendo-task-server.conf b/scripts/boot/upstart/kivitendo-task-server.conf new file mode 100644 index 000000000..b3666dba0 --- /dev/null +++ b/scripts/boot/upstart/kivitendo-task-server.conf @@ -0,0 +1,11 @@ +# kivitendo-task-server - Task server for Kivitendo + +description "Kivitendo task server" + +start on runlevel [2345] +stop on runlevel [!2345] + +respawn + +# Adjust path +exec /opt/kivitendo/scripts/task_server.pl -f start diff --git a/scripts/boot/upstart/lx-office-task-server.conf b/scripts/boot/upstart/lx-office-task-server.conf deleted file mode 100644 index fa00ba22a..000000000 --- a/scripts/boot/upstart/lx-office-task-server.conf +++ /dev/null @@ -1,12 +0,0 @@ -# lx-office-task-server - Task server for Lx-Office - -description "Lx-Office task server" - -start on runlevel [2345] -stop on runlevel [!2345] - -respawn - -# Adjust path -exec /opt/lx-office/scripts/task_server.pl -f start - diff --git a/scripts/task_server.pl b/scripts/task_server.pl index 2c4a05fd4..8c17ca70a 100755 --- a/scripts/task_server.pl +++ b/scripts/task_server.pl @@ -125,7 +125,16 @@ sub gd_run { } my $seconds = 60 - (localtime)[0]; - sleep($seconds < 30 ? $seconds + 60 : $seconds); + if (!eval { + local $SIG{'ALRM'} = sub { + $::lxdebug->message(0, "Got woken up by SIGALRM") if $lx_office_conf{task_server}->{debug}; + die "Alarm!\n" + }; + sleep($seconds < 30 ? $seconds + 60 : $seconds); + 1; + }) { + die $@ unless $@ eq "Alarm!\n"; + } } } @@ -136,7 +145,7 @@ mkdir($pidbase) if !-d $pidbase; my $file = -f "${cwd}/config/lx_office.conf" ? "${cwd}/config/lx_office.conf" : "${cwd}/config/lx_office.conf.default"; newdaemon(configfile => $file, - progname => 'lx-office-task-server', + progname => 'kivitendo-task-server', pidbase => "${pidbase}/", );