do_query( $form, $dbh, $query, @values );
$query = undef;
+ my @columns = qw(cp_title cp_givenname cp_name cp_email cp_phone1 cp_phone2 cp_abteilung cp_fax
+ cp_mobile1 cp_mobile2 cp_satphone cp_satfax cp_project cp_privatphone cp_privatemail cp_birthday cp_gender
+ cp_street cp_zipcode cp_city);
+ @values = map { $_ eq 'cp_gender' ? ($form->{$_} eq 'f' ? 'f' : 'm') : $form->{$_} } @columns;
+
if ( $form->{cp_id} ) {
- $query = qq|UPDATE contacts SET | .
- qq|cp_title = ?, | .
- qq|cp_givenname = ?, | .
- qq|cp_name = ?, | .
- qq|cp_email = ?, | .
- qq|cp_phone1 = ?, | .
- qq|cp_phone2 = ?, | .
- qq|cp_abteilung = ?, | .
- qq|cp_fax = ?, | .
- qq|cp_mobile1 = ?, | .
- qq|cp_mobile2 = ?, | .
- qq|cp_satphone = ?, | .
- qq|cp_satfax = ?, | .
- qq|cp_project = ?, | .
- qq|cp_privatphone = ?, | .
- qq|cp_privatemail = ?, | .
- qq|cp_birthday = ?, | .
- qq|cp_gender = ? | .
- qq|WHERE cp_id = ?|;
- @values = (
- $form->{cp_title},
- $form->{cp_givenname},
- $form->{cp_name},
- $form->{cp_email},
- $form->{cp_phone1},
- $form->{cp_phone2},
- $form->{cp_abteilung},
- $form->{cp_fax},
- $form->{cp_mobile1},
- $form->{cp_mobile2},
- $form->{cp_satphone},
- $form->{cp_satfax},
- $form->{cp_project},
- $form->{cp_privatphone},
- $form->{cp_privatemail},
- $form->{cp_birthday},
- $form->{cp_gender} eq 'f' ? 'f' : 'm',
- $form->{cp_id}
- );
+ $query = qq|UPDATE contacts SET | . join(', ', map { "${_} = ?" } @columns) . qq| WHERE cp_id = ?|;
+ push @values, $form->{cp_id};
+
} elsif ( $form->{cp_name} || $form->{cp_givenname} ) {
- $query =
- qq|INSERT INTO contacts ( cp_cv_id, cp_title, cp_givenname, | .
- qq| cp_name, cp_email, cp_phone1, cp_phone2, cp_abteilung, cp_fax, cp_mobile1, | .
- qq| cp_mobile2, cp_satphone, cp_satfax, cp_project, cp_privatphone, cp_privatemail, | .
- qq| cp_birthday, cp_gender) | .
- qq|VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)|;
- @values = (
- $form->{id},
- $form->{cp_title},
- $form->{cp_givenname},
- $form->{cp_name},
- $form->{cp_email},
- $form->{cp_phone1},
- $form->{cp_phone2},
- $form->{cp_abteilung},
- $form->{cp_fax},
- $form->{cp_mobile1},
- $form->{cp_mobile2},
- $form->{cp_satphone},
- $form->{cp_satfax},
- $form->{cp_project},
- $form->{cp_privatphone},
- $form->{cp_privatemail},
- $form->{cp_birthday},
- $form->{cp_gender} eq 'f' ? 'f' : 'm',
- );
+ $query = qq|INSERT INTO contacts (| . join(', ', 'cp_cv_id', @columns) . qq|) VALUES (?, | . join(', ', ('?') x scalar(@columns)) . qq|)|;
+ unshift @values, $form->{id};
}
do_query( $form, $dbh, $query, @values ) if ($query);
'vcnumber' => 'vcnumber, cp_name, cp_givenname',
);
- my %sortcols = map { $_ => 1 } qw(cp_name cp_givenname cp_phone1 cp_phone2 cp_mobile1 cp_email vcname vcnumber);
+ my %sortcols = map { $_ => 1 } qw(cp_name cp_givenname cp_phone1 cp_phone2 cp_mobile1 cp_email cp_street cp_zipcode cp_city vcname vcnumber);
my $order_by = $sortcols{$::form->{sort}} ? $::form->{sort} : 'cp_name';
$::form->{sort} = $order_by;
use SL::DB::Language;
use SL::DB::PaymentTerm;
use SL::DB::Vendor;
+use SL::DB::Contact;
use parent qw(Rose::Object);
use strict;
use SL::Helper::Csv;
+use SL::DB::CustomVariable;
+use SL::DB::CustomVariableConfig;
use parent qw(SL::Controller::CsvImport::Base);
$self->class('SL::DB::Contact');
}
+sub init_all_cvar_configs {
+ my ($self) = @_;
+
+ return SL::DB::Manager::CustomVariableConfig->get_all(where => [ module => 'Contacts' ]);
+}
+
sub check_objects {
my ($self) = @_;
$self->check_name($entry);
$self->check_vc($entry, 'cp_cv_id');
$self->check_gender($entry);
+ $self->handle_cvars($entry);
}
$self->add_info_columns({ header => $::locale->text('Customer/Vendor'), method => 'vc_name' });
+ $self->add_cvar_raw_data_columns;
}
sub check_name {
my ($self) = @_;
$self->SUPER::setup_displayable_columns;
+ $self->add_cvar_columns_to_displayable_columns;
$self->add_displayable_columns({ name => 'cp_abteilung', description => $::locale->text('Department') },
{ name => 'cp_birthday', description => $::locale->text('Birthday') },
# Creates get_all, get_all_count, get_all_iterator, delete_all and update_all.
__PACKAGE__->meta->make_manager_class;
+__PACKAGE__->meta->initialize;
+
sub used {
my ($self) = @_;
__PACKAGE__->meta->make_manager_class;
+__PACKAGE__->meta->initialize;
+
# methods
sub part {
$params{module} ||= _calc_modules_from_overloads(%params) if $params{overloads};
$params{sub_module} ||= '';
- $params{id} ||= 'id';
+ $params{id} ||= _get_primary_key_column($caller_package);
$params{module} || $params{sub_module} or croak 'need param module or sub_module';
custom_variables => {
type => 'one to many',
class => 'SL::DB::CustomVariable',
- column_map => { ($params{id} || 'id') => 'trans_id' },
+ column_map => { $params{id} => 'trans_id' },
query_args => [ sub_module => $params{sub_module}, @module_filter ],
}
);
return [ keys %modules ];
}
+sub _get_primary_key_column {
+ my ($caller_package) = @_;
+ my $meta = $caller_package->meta;
+
+ my $column_name;
+ $column_name = $meta->{primary_key}->{columns}->[0] if $meta->{primary_key} && (ref($meta->{primary_key}->{columns}) eq 'ARRAY') && (1 == scalar(@{ $meta->{primary_key}->{columns} }));
+
+ croak "Unable to retrieve primary key column name: meta information for package $caller_package not set up correctly" unless $column_name;
+
+ return $column_name;
+}
1;
# Update the invoice to reflect the new paid amount.
do_statement($form, @{ $handles{update_arap} }, $orig_item->{amount}, $orig_item->{"${arap}_id"});
+ # Update datepaid of invoice. set_datepaid (which has some extra logic)
+ # finds the date from acc_trans, where the payment has already been
+ # recorded above, so we don't need to explicitly pass
+ # $item->{execution_date}
+ IO->set_datepaid(table => "$arap", id => $orig_item->{"${arap}_id"}, dbh => $dbh);
+
# Update the item to reflect that it has been posted.
do_statement($form, @{ $handles{finish_item} }, $item->{execution_date}, $item_id);
# Bestandteile von Erzeugnissen herausfiltern
$where .= " AND i.assemblyitem is not true ";
- my $sortorder;
+ # filter allowed parameters for mainsort and subsort as passed by POST
+ my @databasefields = qw(description customername country partsgroup business salesman month);
+ my ($mainsort) = grep { /^$form->{mainsort}$/ } @databasefields;
+ my ($subsort) = grep { /^$form->{subsort}$/ } @databasefields;
+ die "illegal parameter for mainsort or subsort" unless $mainsort and $subsort;
+ my $sortorder;
# sorting by month is a special case, we don't want to sort alphabetically by
# month name, so we also extract a numerical month in the from YYYYMM to sort
# by in case of month sorting
if ($form->{mainsort} eq 'month') {
$sortorder .= "nummonth,"
} else {
- $sortorder .= $form->{mainsort} . ",";
+ $sortorder .= $mainsort . ",";
};
if ($form->{subsort} eq 'month') {
$sortorder .= "nummonth,"
} else {
- $sortorder .= $form->{subsort} . ",";
+ $sortorder .= $subsort . ",";
};
$sortorder .= 'ar.transdate,ar.invnumber'; # Default sorting order after mainsort und subsort
-
if ($form->{customer_id}) {
$where .= " AND ar.customer_id = ?";
push(@values, $form->{customer_id});
my $cvar_configs = CVar->get_configs('module' => 'Contacts');
my @columns = qw(
- cp_id vcname vcnumber cp_name cp_givenname cp_street cp_phone1 cp_phone2
+ cp_id vcname vcnumber cp_name cp_givenname cp_street cp_zipcode cp_city cp_phone1 cp_phone2
cp_mobile1 cp_mobile2 cp_email cp_abteilung cp_birthday cp_gender
);
'cp_name' => { 'text' => $::locale->text('Name'), },
'cp_givenname' => { 'text' => $::locale->text('Given Name'), },
'cp_street' => { 'text' => $::locale->text('Street'), },
+ 'cp_zipcode' => { 'text' => $::locale->text('Zipcode'), },
+ 'cp_city' => { 'text' => $::locale->text('City'), },
'cp_phone1' => { 'text' => $::locale->text('Phone1'), },
'cp_phone2' => { 'text' => $::locale->text('Phone2'), },
'cp_mobile1' => { 'text' => $::locale->text('Mobile1'), },
my %queued = map { s|.*/|| } split / /, $form->{queued};
my $filename;
+ my $suffix = ($form->{postscript}) ? '.ps' : '.pdf';
if ($filename = $queued{ $form->{formname} }) {
$form->{queued} =~ s/\Q$form->{formname} $filename\E//;
unlink $::lx_office_conf{paths}->{spool} . "/$filename";
$filename =~ s/\..*$//g;
+ $filename .= $suffix;
+ $form->{OUT} = $::lx_office_conf{paths}->{spool} . "/$filename";
+ $form->{OUT_MODE} = '>';
} else {
- $filename = time;
- $filename .= $$;
+ my $temp_fh;
+ ($temp_fh, $filename) = File::Temp::tempfile(
+ 'kivitendo-spoolXXXXXX',
+ SUFFIX => "$suffix",
+ DIR => $::lx_office_conf{paths}->{spool},
+ );
+ close $temp_fh;
+ $form->{OUT} = "$filename";
+ # use >> for OUT_MODE because file is already created by File::Temp
+ $form->{OUT_MODE} = '>>';
+ # strip directory so that only filename is stored in table status
+ ($filename) = $filename =~ /^$::lx_office_conf{paths}->{spool}\/(.*)/;
}
- $filename .= ($form->{postscript}) ? '.ps' : '.pdf';
- $form->{OUT} = $::lx_office_conf{paths}->{spool} . "/$filename";
- $form->{OUT_MODE} = '>';
-
# add type
$form->{queued} .= " $form->{formname} $filename";
-
$form->{queued} =~ s/^ //;
}
my $queued = $form->{queued};
konsistent bleibt und eine Fehlermeldung ausgegeben. Das Feature kann in der
Konfiguration unter [datev_check] angeschaltet werden.
+- Verkaufsbericht: Sortierung um Land, Warengruppen, Kundentyp, Verkäufer und
+ Monat erweitert, sowie benutzerdefinierte Variablen eingebunden
Experimentelle Features:
'Missing amount' => 'Fehlbetrag',
'Missing parameter #1 in call to sub #2.' => 'Fehlernder Parameter \'#1\' in Funktionsaufruf \'#2\'.',
'Missing parameter (at least one of #1) in call to sub #2.' => 'Fehlernder Parameter (mindestens einer aus \'#1\') in Funktionsaufruf \'#2\'.',
- 'Missing qty' => '',
+ 'Missing qty' => 'Fehlende Stückzahl',
'Missing taxkeys in invoices with taxes.' => 'Fehlende Steuerschlüssel in Rechnungen mit Steuern',
'Missing user id!' => 'Benutzer ID fehlt!',
'Mitarbeiter' => 'Mitarbeiter',
'Recorded Tax' => 'Gespeicherte Steuern',
'Recorded taxkey' => 'Gespeicherter Steuerschlüssel',
'Reference' => 'Referenz',
+ 'Reference / Invoice Number' => 'Referenz / Rechnungsnummer',
'Reference missing!' => 'Referenz fehlt!',
'Release From Stock' => 'Lagerausgang',
'Remaining' => 'Rest',
'Start the correction assistant' => 'Korrekturassistenten starten',
'Startdate_coa' => 'Gültig ab',
'Starting Balance' => 'Eröffnungsbilanzwerte',
- 'Starting with version 2.6.3 the configuration files in "config" have been consolidated.' => '',
+ 'Starting with version 2.6.3 the configuration files in "config" have been consolidated.' => 'Ab Version 2.6.3 wurden die Konfiguration vereinfacht und es gibt nur noch eine Konfigurationsdatei im Verzeichnis config',
'Statement' => 'Sammelrechnung',
'Statement Balance' => 'Sammelrechnungsbilanz',
'Statement sent to' => 'Sammelrechnung verschickt an',
</td>
</tr>
- <tr>
- <th align="left" nowrap>[% 'Gender' | $T8 %]</th>
- <td>
- <select id="cp_gender" name="cp_gender">
- <option value="m"[% IF cp_gender == 'm' %] selected[% END %]>[% 'male' | $T8 %]</option>
- <option value="f"[% IF cp_gender == 'f' %] selected[% END %]>[% 'female' | $T8 %]</option>
- </select>
- </td>
- </tr>
- <tr>
+ <tr>
+ <th align="left" nowrap>[% 'Gender' | $T8 %]</th>
+ <td>
+ <select id="cp_gender" name="cp_gender">
+ <option value="m"[% IF cp_gender == 'm' %] selected[% END %]>[% 'male' | $T8 %]</option>
+ <option value="f"[% IF cp_gender == 'f' %] selected[% END %]>[% 'female' | $T8 %]</option>
+ </select>
+ </td>
+ </tr>
<tr>
<th align="left" nowrap>[% 'Title' | $T8 %]</th>
<td><input id="cp_name" name="cp_name" size="40" maxlength="75" value="[% HTML.escape(cp_name) %]"></td>
</tr>
+ <tr>
+ <th align="left" nowrap>[% 'E-mail' | $T8 %]</th>
+ <td><input id="cp_email" name="cp_email" size="40" value="[% HTML.escape(cp_email) %]"></td>
+ </tr>
+
<tr>
<th align="left" nowrap>[% 'Phone1' | $T8 %]</th>
<td><input id="cp_phone1" name="cp_phone1" size="40" maxlength="75" value="[% HTML.escape(cp_phone1) %]"></td>
</tr>
<tr>
- <th align="left" nowrap>[% 'E-mail' | $T8 %]</th>
- <td><input id="cp_email" name="cp_email" size="40" value="[% HTML.escape(cp_email) %]"></td>
+ <th align="left" nowrap>[% 'Street' | $T8 %]</th>
+ <td><input id="cp_street" name="cp_street" size="40" maxlength="75" value="[% HTML.escape(cp_street) %]"></td>
+ </tr>
+
+ <tr>
+ <th align="left" nowrap>[% 'Zip, City' | $T8 %]</th>
+ <td>
+ <input id="cp_zipcode" name="cp_zipcode" size="5" maxlength="10" value="[% HTML.escape(cp_zipcode) %]">
+ <input id="cp_city" name="cp_city" size="25" maxlength="75" value="[% HTML.escape(cp_city) %]">
+ </td>
</tr>
<tr>
<input name="l.cp_givenname" id="l_cp_givenname" type="checkbox" class="checkbox" value="Y" checked>
<label for="l_cp_givenname">[% 'Given Name' | $T8 %]</label>
</td>
+ </tr>
+ <tr>
<td>
<input name="l.cp_street" id="l_cp_street" type="checkbox" class="checkbox" value="Y">
<label for="l_cp_street">[% 'Street' | $T8 %]</label>
</td>
+ <td>
+ <input name="l.cp_zipcode" id="l_cp_zipcode" type="checkbox" class="checkbox" value="Y">
+ <label for="l_cp_zipcode">[% 'Zipcode' | $T8 %]</label>
+ </td>
+ <td>
+ <input name="l.cp_city" id="l_cp_city" type="checkbox" class="checkbox" value="Y">
+ <label for="l_cp_city">[% 'City' | $T8 %]</label>
+ </td>
</tr>
<tr>
<td>
<td>
<table>
<tr>
- <th align=right>[% 'Reference' | $T8 %]</th>
+ <th align=right>[% 'Reference / Invoice Number' | $T8 %]</th>
<td><input name=reference size=20></td>
<th align=right>[% 'Source' | $T8 %]</th>
<td><input name=source size=20></td>