X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=SL%2FDN.pm;h=76ee1b834d364fb12f861b1abb656da86efe37e2;hb=3782a90c336bc6c506f572e607c8526cb5e79ea3;hp=46ab23a5b990a91482642d22671a245561706be4;hpb=443e237ff0dbd22131349e65e4a86c3f3c73c7c9;p=kivitendo-erp.git diff --git a/SL/DN.pm b/SL/DN.pm index 46ab23a5b..76ee1b834 100644 --- a/SL/DN.pm +++ b/SL/DN.pm @@ -40,6 +40,7 @@ use SL::DBUtils; use SL::DB::AuthUser; use SL::DB::Default; use SL::DB::Employee; +use SL::File; use SL::GenericTranslations; use SL::IS; use SL::Mailer; @@ -50,8 +51,10 @@ use SL::DB::Language; use SL::TransNumber; use SL::Util qw(trim); use SL::DB; +use SL::Webdav; use File::Copy; +use File::Slurp qw(read_file); use strict; @@ -192,7 +195,8 @@ sub create_invoice_for_fees { AND (d_interest.dunning_id <> ?) AND NOT (d_interest.fee_interest_ar_id ISNULL) ), 0) - AS max_previous_interest + AS max_previous_interest, + d.id AS link_id FROM dunning d WHERE dunning_id = ?|; @values = ($dunning_id, $dunning_id, $dunning_id); @@ -201,6 +205,8 @@ sub create_invoice_for_fees { my ($fee_remaining, $interest_remaining) = (0, 0); my ($fee_total, $interest_total) = (0, 0); + my @link_ids; + while (my $ref = $sth->fetchrow_hashref()) { $fee_remaining += $form->round_amount($ref->{fee}, 2); $fee_remaining -= $form->round_amount($ref->{max_previous_fee}, 2); @@ -208,6 +214,7 @@ sub create_invoice_for_fees { $interest_remaining += $form->round_amount($ref->{interest}, 2); $interest_remaining -= $form->round_amount($ref->{max_previous_interest}, 2); $interest_total += $form->round_amount($ref->{interest}, 2); + push @link_ids, $ref->{link_id}; } $sth->finish(); @@ -271,6 +278,15 @@ sub create_invoice_for_fees { $::myconfig{login}); # employee_id do_query($form, $dbh, $query, @values); + RecordLinks->create_links( + 'dbh' => $dbh, + 'mode' => 'ids', + 'from_table' => 'dunning', + 'from_ids' => \@link_ids, + 'to_table' => 'ar', + 'to_id' => $ar_id, + ); + $query = qq|INSERT INTO acc_trans (trans_id, chart_id, amount, transdate, gldate, taxkey, tax_id, chart_link) VALUES (?, ?, ?, current_date, current_date, 0, @@ -302,11 +318,30 @@ sub save_dunning { my ($self, $myconfig, $form, $rows) = @_; $main::lxdebug->enter_sub(); - my $rc = SL::DB->client->with_transaction(\&_save_dunning, $self, $myconfig, $form, $rows); + $form->{DUNNING_PDFS_STORAGE} = []; + + # Catch any error, either exception or a call to form->error + # and return it to the calling function. + my ($error, $rc); + eval { + local $form->{__ERROR_HANDLER} = sub { die @_ }; + $rc = SL::DB->client->with_transaction(\&_save_dunning, $self, $myconfig, $form, $rows); + 1; + } or do { + $error = $@; + }; - if (!$rc) { - die SL::DB->client->error + # Save PDFs in filemanagement and webdav after transation succeeded, + # because otherwise files in the storage may exists if the transaction + # failed. Ignore all errros. + # Todo: Maybe catch errros and display them as warnings or non fatal errors in the status. + if (!$error && $form->{DUNNING_PDFS_STORAGE} && scalar @{ $form->{DUNNING_PDFS_STORAGE} }) { + _store_pdf_to_webdav_and_filemanagement($_->{dunning_id}, $_->{path}, $_->{name}) for @{ $form->{DUNNING_PDFS_STORAGE} }; } + + $error = 'unknown errror' if !$error && !$rc; + $rc->{error} = $error if $error; + $::lxdebug->leave_sub; return $rc; @@ -326,9 +361,9 @@ sub _save_dunning { my $h_update_ar = prepare_query($form, $dbh, $q_update_ar); my $q_insert_dunning = - qq|INSERT INTO dunning (dunning_id, dunning_config_id, dunning_level, trans_id, - fee, interest, transdate, duedate) - VALUES (?, ?, + qq|INSERT INTO dunning (id, dunning_id, dunning_config_id, dunning_level, trans_id, + fee, interest, transdate, duedate, original_invoice_printed) + VALUES (?, ?, ?, (SELECT dunning_level FROM dunning_config WHERE id = ?), ?, (SELECT SUM(fee) @@ -338,7 +373,8 @@ sub _save_dunning { * (SELECT interest_rate FROM dunning_config WHERE id = ?) / 360, current_date, - current_date + (SELECT payment_terms FROM dunning_config WHERE id = ?))|; + current_date + (SELECT payment_terms FROM dunning_config WHERE id = ?), + ?)|; my $h_insert_dunning = prepare_query($form, $dbh, $q_insert_dunning); my @invoice_ids; @@ -366,17 +402,28 @@ sub _save_dunning { $send_email |= $row->{email}; $print_invoice |= $row->{print_invoice}; + my ($row_id) = selectrow_query($form, $dbh, qq|SELECT nextval('id')|); my $next_config_id = conv_i($row->{next_dunning_config_id}); my $invoice_id = conv_i($row->{invoice_id}); - @values = ($dunning_id, $next_config_id, $next_config_id, - $invoice_id, $next_config_id, $invoice_id, - $next_config_id, $next_config_id); + @values = ($row_id, $dunning_id, $next_config_id, + $next_config_id, $invoice_id, $next_config_id, + $invoice_id, $next_config_id, $next_config_id, + $print_invoice); do_statement($form, $h_insert_dunning, $q_insert_dunning, @values); + + RecordLinks->create_links( + 'dbh' => $dbh, + 'mode' => 'ids', + 'from_table' => 'ar', + 'from_ids' => $invoice_id, + 'to_table' => 'dunning', + 'to_id' => $row_id, + ); } # die this transaction, because for this customer only credit notes are # selected ... - return unless $customer_id; + die "only credit notes are selected for this customer\n" unless $customer_id; $h_update_ar->finish(); $h_insert_dunning->finish(); @@ -391,14 +438,14 @@ sub _save_dunning { $self->print_dunning($myconfig, $form, $dunning_id, $dbh); if ($print_invoice) { - $self->print_original_invoices($myconfig, $form, $_, $dbh) for @invoice_ids; + $self->print_original_invoice($myconfig, $form, $dunning_id, $_) for @invoice_ids; } if ($send_email) { $self->send_email($myconfig, $form, $dunning_id, $dbh); } - return 1; + return ({dunning_id => $dunning_id, print_original_invoice => $print_invoice, send_email => $send_email}); } sub send_email { @@ -440,13 +487,17 @@ sub send_email { } or die $main::locale->text('No email for user with login #1 defined.', $ref->{invoice_employee_login}); } + my $html_template = SL::Template::create(type => 'HTML', form => $form, myconfig => $myconfig); + $html_template->set_tag_style('<%', '%>'); + my $template = SL::Template::create(type => 'PlainText', form => $form, myconfig => $myconfig); my $mail = Mailer->new(); $mail->{bcc} = $form->get_bcc_defaults($myconfig, $form->{bcc}); $mail->{from} = $from; $mail->{to} = $ref->{recipient}; $mail->{subject} = $template->parse_block($ref->{email_subject}); - $mail->{message} = $template->parse_block($ref->{email_body}); + $mail->{message} = $html_template->parse_block($ref->{email_body}); + $mail->{content_type} = 'text/html'; my $sign_backup = $::myconfig{signature}; $::myconfig{signature} = $sign if $sign; $mail->{message} .= $form->create_email_signature(); @@ -458,6 +509,11 @@ sub send_email { $mail->{attachments} = $form->{DUNNING_PDFS_EMAIL}; } + $query = qq|SELECT id FROM dunning WHERE dunning_id = ?|; + my @ids = selectall_array_query($form, $dbh, $query, $dunning_id); + $mail->{record_id} = \@ids; + $mail->{record_type} = 'dunning'; + $mail->send(); $main::lxdebug->leave_sub(); @@ -601,8 +657,9 @@ sub get_invoices { ct.name AS customername, a.customer_id, a.duedate, a.amount - a.paid AS open_amount, a.direct_debit, + pt.description as payment_term, dep.description as departmentname, - + ct.invoice_mail AS cv_email, cfg.dunning_description, cfg.dunning_level, d.transdate AS dunning_date, d.duedate AS dunning_duedate, @@ -620,6 +677,7 @@ sub get_invoices { LEFT JOIN customer ct ON (a.customer_id = ct.id) LEFT JOIN department dep ON (a.department_id = dep.id) + LEFT JOIN payment_terms pt ON (a.payment_id = pt.id) LEFT JOIN dunning_config cfg ON (a.dunning_config_id = cfg.id) LEFT JOIN dunning_config nextcfg ON (nextcfg.id = @@ -700,6 +758,11 @@ sub get_dunning { push(@values, like($form->{$key})); } + if ($form->{dunning_id}) { + $where .= qq| AND da.dunning_id = ?|; + push(@values, conv_i($form->{dunning_id})); + } + if ($form->{dunning_level}) { $where .= qq| AND a.dunning_config_id = ?|; push(@values, conv_i($form->{dunning_level})); @@ -743,13 +806,14 @@ sub get_dunning { } my %sort_columns = ( - 'dunning_description' => [ qw(dn.dunning_description customername invnumber) ], - 'customername' => [ qw(customername invnumber) ], + 'dunning_description' => [ qw(dn.dunning_description da.dunning_id customername invnumber) ], + 'customername' => [ qw(customername da.dunning_id invnumber) ], 'invnumber' => [ qw(a.invnumber) ], 'transdate' => [ qw(a.transdate a.invnumber) ], 'duedate' => [ qw(a.duedate a.invnumber) ], - 'dunning_date' => [ qw(dunning_date a.invnumber) ], - 'dunning_duedate' => [ qw(dunning_duedate a.invnumber) ], + 'dunning_date' => [ qw(dunning_date da.dunning_id a.invnumber) ], + 'dunning_duedate' => [ qw(dunning_duedate da.dunning_id a.invnumber) ], + 'dunning_id' => [ qw(dunning_id a.invnumber) ], 'salesman' => [ qw(salesman) ], ); @@ -760,8 +824,9 @@ sub get_dunning { my $query = qq|SELECT a.id, a.ordnumber, a.invoice, a.transdate, a.invnumber, a.amount, a.language_id, ct.name AS customername, ct.id AS customer_id, a.duedate, da.fee, - da.interest, dn.dunning_description, da.transdate AS dunning_date, + da.interest, dn.dunning_description, dn.dunning_level, da.transdate AS dunning_date, da.duedate AS dunning_duedate, da.dunning_id, da.dunning_config_id, + da.id AS dunning_table_id, e2.name AS salesman FROM ar a JOIN customer ct ON (a.customer_id = ct.id) @@ -783,7 +848,7 @@ sub melt_pdfs { $main::lxdebug->enter_sub(); - my ($self, $myconfig, $form, $copies) = @_; + my ($self, $myconfig, $form, $copies, %params) = @_; # Don't allow access outside of $spool. map { $_ =~ s|.*/||; } @{ $form->{DUNNING_PDFS} }; @@ -799,23 +864,30 @@ sub melt_pdfs { my $in = IO::File->new($::lx_office_conf{applications}->{ghostscript} . " -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=- $inputfiles |"); $form->error($main::locale->text('Could not spawn ghostscript.')) unless $in; - if ($form->{media} eq 'printer') { - $form->get_printer_code($myconfig); - my $out; - if ($form->{printer_command}) { - $out = IO::File->new("| $form->{printer_command}"); - } + my $dunning_filename = $form->get_formname_translation('dunning'); + my $attachment_filename = "${dunning_filename}_${dunning_id}.pdf"; + my $content; + if ($params{return_content}) { + $content = read_file($in); - $::locale->with_raw_io($out, sub { $out->print($_) while <$in> }); + } else { + if ($form->{media} eq 'printer') { + $form->get_printer_code($myconfig); + my $out; + if ($form->{printer_command}) { + $out = IO::File->new("| $form->{printer_command}"); + } - $form->error($main::locale->text('Could not spawn the printer command.')) unless $out; + $form->error($main::locale->text('Could not spawn the printer command.')) unless $out; - } else { - my $dunning_filename = $form->get_formname_translation('dunning'); - print qq|Content-Type: Application/PDF\n| . - qq|Content-Disposition: attachment; filename="${dunning_filename}_${dunning_id}.pdf"\n\n|; + $::locale->with_raw_io($out, sub { $out->print($_) while <$in> }); + + } else { + print qq|Content-Type: Application/PDF\n| . + qq|Content-Disposition: attachment; filename=$attachment_filename\n\n|; - $::locale->with_raw_io(\*STDOUT, sub { print while <$in> }); + $::locale->with_raw_io(\*STDOUT, sub { print while <$in> }); + } } $in->close(); @@ -823,6 +895,7 @@ sub melt_pdfs { map { unlink("$spool/$_") } @{ $form->{DUNNING_PDFS} }; $main::lxdebug->leave_sub(); + return ($attachment_filename, $content) if $params{return_content}; } sub print_dunning { @@ -896,7 +969,7 @@ sub print_dunning { c.country, c.department_1, c.department_2, c.email, c.customernumber, c.greeting, c.contact, c.phone, c.fax, c.homepage, c.email, c.taxincluded, c.business_id, c.taxnumber, c.iban, - c.ustid, + c.ustid, c.currency_id, curr.name as currency, ar.id AS invoice_id, co.* FROM dunning d @@ -904,6 +977,7 @@ sub print_dunning { LEFT JOIN customer c ON (ar.customer_id = c.id) LEFT JOIN contacts co ON (ar.cp_id = co.cp_id) LEFT JOIN employee e ON (ar.salesman_id = e.id) + LEFT JOIN currencies curr ON (c.currency_id = curr.id) WHERE (d.dunning_id = ?) LIMIT 1|; my $ref = selectfirst_hashref_query($form, $dbh, $query, $dunning_id); @@ -971,10 +1045,6 @@ sub print_dunning { delete $form->{tmpfile}; - push @{ $form->{DUNNING_PDFS} }, $filename; - push @{ $form->{DUNNING_PDFS_EMAIL} }, { 'path' => "${spool}/$filename", - 'name' => $form->get_formname_translation('dunning') . "_${dunning_id}.pdf" }; - my $employee_id = ($::instance_conf->get_dunning_creator eq 'invoice_employee') ? $form->{employee_id} : SL::DB::Manager::Employee->current->id; @@ -988,8 +1058,17 @@ sub print_dunning { } $form->{attachment_filename} = $form->get_formname_translation($form->{attachment_type}) . "_${dunning_id}.pdf"; $form->{attachment_id} = $form->{invoice_id}; + + # this generates the file in the spool directory $form->parse_template($myconfig); + push @{ $form->{DUNNING_PDFS} } , $filename; + push @{ $form->{DUNNING_PDFS_EMAIL} } , { 'path' => "${spool}/$filename", + 'name' => $form->get_formname_translation('dunning') . "_${dunning_id}.pdf" }; + push @{ $form->{DUNNING_PDFS_STORAGE} }, { 'dunning_id' => $dunning_id, + 'path' => "${spool}/$filename", + 'name' => $form->get_formname_translation('dunning') . "_${dunning_id}.pdf" }; + $main::lxdebug->leave_sub(); } @@ -1070,7 +1149,7 @@ sub print_invoice_for_fees { $self->set_customer_cvars($myconfig, $form); $self->set_template_options($myconfig, $form); - my $filename = Common::unique_id() . "dunning_invoice_${dunning_id}.pdf"; + my $filename = Common::unique_id() . "dunning_invoice_" . $form->{invnumber} . ".pdf"; my $spool = $::lx_office_conf{paths}->{spool}; $form->{OUT} = "$spool/$filename"; @@ -1079,16 +1158,20 @@ sub print_invoice_for_fees { map { delete $form->{$_} } grep /^[a-z_]+_\d+$/, keys %{ $form }; - $form->{attachment_filename} = $form->get_formname_translation('dunning_invoice') . "_${dunning_id}.pdf"; + my $attachment_filename = $form->get_formname_translation('dunning_invoice') . "_" . $form->{invnumber} . ".pdf"; + $form->{attachment_filename} = $attachment_filename; $form->{attachment_type} = "dunning"; - $form->{attachment_id} = $form->{invoice_id}; + $form->{attachment_id} = $invoice_id; $form->parse_template($myconfig); restore_form($saved_form); - push @{ $form->{DUNNING_PDFS} }, $filename; - push @{ $form->{DUNNING_PDFS_EMAIL} }, { 'filename' => "${spool}/$filename", - 'name' => "dunning_invoice_${dunning_id}.pdf" }; + push @{ $form->{DUNNING_PDFS} }, $filename; + push @{ $form->{DUNNING_PDFS_EMAIL} }, { 'path' => "${spool}/$filename", + 'name' => $attachment_filename }; + push @{ $form->{DUNNING_PDFS_STORAGE} }, { 'dunning_id' => $dunning_id, + 'path' => "${spool}/$filename", + 'name' => $attachment_filename }; $main::lxdebug->leave_sub(); } @@ -1114,8 +1197,8 @@ sub set_customer_cvars { } -sub print_original_invoices { - my ($self, $myconfig, $form, $invoice_id) = @_; +sub print_original_invoice { + my ($self, $myconfig, $form, $dunning_id, $invoice_id) = @_; # get one invoice as object and print to pdf my $invoice = SL::DB::Invoice->new(id => $invoice_id)->load; @@ -1141,6 +1224,7 @@ sub print_original_invoices { longdescription => 'html', partnotes => 'html', notes => 'html', + $print_form->get_variable_content_types_for_cvars, }, ); @@ -1154,11 +1238,58 @@ sub print_original_invoices { my $saved_reicpient_locale = $form->{recipient_locale}; $form->{recipient_locale} = $invoice->language; - push @{ $form->{DUNNING_PDFS} }, $file_name; - push @{ $form->{DUNNING_PDFS_EMAIL} }, { 'path' => "${spool}/$file_name", - 'name' => $form->get_formname_translation('invoice') . "_" . $invoice->invnumber . ".pdf" }; + my $attachment_filename = $form->get_formname_translation('invoice') . "_" . $invoice->invnumber . ".pdf"; + + push @{ $form->{DUNNING_PDFS} }, $file_name; + push @{ $form->{DUNNING_PDFS_EMAIL} }, { 'path' => "${spool}/$file_name", + 'name' => $attachment_filename }; + push @{ $form->{DUNNING_PDFS_STORAGE} }, { 'dunning_id' => $dunning_id, + 'path' => "${spool}/$file_name", + 'name' => $attachment_filename }; $form->{recipient_locale} = $saved_reicpient_locale; } +sub _store_pdf_to_webdav_and_filemanagement { + my ($dunning_id, $path, $name) =@_; + + my @errors; + + if ($::instance_conf->get_doc_storage) { + eval { + SL::File->save( + object_id => $dunning_id, + object_type => 'dunning', + mime_type => 'application/pdf', + source => 'created', + file_type => 'document', + file_name => $name, + file_path => $path, + ); + 1; + } or do { + push @errors, $::locale->text('Storing PDF in storage backend failed: #1', $@); + }; + } + + if ($::instance_conf->get_webdav_documents) { + eval { + my $webdav = SL::Webdav->new( + type => 'dunning', + number => $dunning_id, + ); + my $webdav_file = SL::Webdav::File->new( + webdav => $webdav, + filename => $name, + ); + $webdav_file->store(file => $path); + } or do { + push @errors, $::locale->text('Storing PDF to webdav folder failed: #1', $@); + }; + } + + return @errors; +} + + 1;