Revision d63305ba
Von Jan Büren vor mehr als 6 Jahren hinzugefügt
SL/BackgroundJob/CreatePeriodicInvoices.pm | ||
---|---|---|
404 | 404 |
|
405 | 405 |
for my $recipient (@recipients) { |
406 | 406 |
my $mail = Mailer->new; |
407 |
$mail->{record_id} = $data->{invoice}->id, |
|
408 |
$mail->{record_type} = 'invoice', |
|
407 | 409 |
$mail->{from} = $data->{config}->email_sender || $::lx_office_conf{periodic_invoices}->{email_from}; |
408 | 410 |
$mail->{to} = $recipient; |
409 | 411 |
$mail->{bcc} = $global_bcc; |
SL/Controller/Letter.pm | ||
---|---|---|
246 | 246 |
name => $params{email}->{attachment_filename} }]; |
247 | 247 |
$mail->{message} .= "\n-- \n$signature"; |
248 | 248 |
$mail->{message} =~ s/\r//g; |
249 |
|
|
249 |
$mail->{record_id} = $letter->id; |
|
250 | 250 |
$mail->send; |
251 | 251 |
unlink $result{file_name}; |
252 | 252 |
|
SL/Controller/RecordLinks.pm | ||
---|---|---|
49 | 49 |
{ title => t8('Purchase delivery order'), type => 'purchase_delivery_order', model => 'DeliveryOrder', number => 'donumber', }, |
50 | 50 |
{ title => t8('Purchase Invoice'), type => 'purchase_invoice', model => 'PurchaseInvoice', number => 'invnumber', }, |
51 | 51 |
{ title => t8('Letter'), type => 'letter', model => 'Letter', number => 'letternumber', description => 'subject', description_title => t8('Subject'), date => 'date', project => undef }, |
52 |
{ title => t8('Email'), type => 'email_journal', model => 'EmailJournal', number => 'id', description => 'subject', description_title => t8('Subject'), }, |
|
52 | 53 |
); |
53 | 54 |
|
54 | 55 |
my @link_types = map { +{ %link_type_defaults, %{ $_ } } } @link_type_specifics; |
SL/DB/EmailJournal.pm | ||
---|---|---|
18 | 18 |
|
19 | 19 |
__PACKAGE__->attr_sorted('attachments'); |
20 | 20 |
|
21 |
sub compare_to { |
|
22 |
my ($self, $other) = @_; |
|
23 |
|
|
24 |
return -1 if $self->sent_on && !$other->sent_on; |
|
25 |
return 1 if !$self->sent_on && $other->sent_on; |
|
26 |
|
|
27 |
my $result = 0; |
|
28 |
$result = $other->sent_on <=> $self->sent_on; |
|
29 |
return $result || ($self->id <=> $other->id); |
|
30 |
} |
|
31 |
|
|
21 | 32 |
1; |
33 |
|
|
34 |
__END__ |
|
35 |
|
|
36 |
=pod |
|
37 |
|
|
38 |
=encoding utf8 |
|
39 |
|
|
40 |
=head1 NAME |
|
41 |
|
|
42 |
SL::DB::EmailJournal - RDBO model for email journal |
|
43 |
|
|
44 |
=head1 SYNOPSIS |
|
45 |
|
|
46 |
This is a standard Rose::DB::Object based model and can be used as one. |
|
47 |
|
|
48 |
=head1 METHODS |
|
49 |
|
|
50 |
=over 4 |
|
51 |
|
|
52 |
=item C<compare_to $self, $other> |
|
53 |
|
|
54 |
Compares C<$self> with C<$other> and returns the newer entry. |
|
55 |
|
|
56 |
=back |
|
57 |
|
|
58 |
=cut |
|
59 |
|
SL/DB/Helper/LinkedRecords.pm | ||
---|---|---|
210 | 210 |
} |
211 | 211 |
|
212 | 212 |
# don't use rose retrieval here. too slow. |
213 |
# instead use recursive sql to get all the linked record_links entrys, and retrieve the objects from there
|
|
213 |
# instead use recursive sql to get all the linked record_links entries and retrieve the objects from there
|
|
214 | 214 |
my $query = <<""; |
215 | 215 |
WITH RECURSIVE record_links_rec_${wanted}(id, from_table, from_id, to_table, to_id, depth, path, cycle) AS ( |
216 | 216 |
SELECT id, from_table, from_id, to_table, to_id, |
... | ... | |
313 | 313 |
'SL::DB::RequirementSpec' => sub { $_[0]->id }, |
314 | 314 |
'SL::DB::Letter' => sub { $_[0]->letternumber }, |
315 | 315 |
'SL::DB::ShopOrder' => sub { $_[0]->shop_ordernumber }, |
316 |
'SL::DB::EmailJournal' => sub { $_[0]->id }, |
|
316 | 317 |
UNKNOWN => '9999999999999999', |
317 | 318 |
); |
318 | 319 |
my $number_xtor = sub { |
... | ... | |
343 | 344 |
'SL::DB::PurchaseInvoice' => 150, |
344 | 345 |
'SL::DB::Letter' => 200, |
345 | 346 |
'SL::DB::ShopOrder' => 250, |
347 |
'SL::DB::EmailJournal' => 300, |
|
346 | 348 |
UNKNOWN => 999, |
347 | 349 |
); |
348 | 350 |
my $score_xtor = sub { |
SL/Mailer.pm | ||
---|---|---|
45 | 45 |
smtp => 'SL::Mailer::SMTP', |
46 | 46 |
); |
47 | 47 |
|
48 |
my %type_to_table = ( |
|
49 |
sales_quotation => 'oe', |
|
50 |
request_quotation => 'oe', |
|
51 |
sales_order => 'oe', |
|
52 |
purchase_order => 'oe', |
|
53 |
invoice => 'ar', |
|
54 |
credit_note => 'ar', |
|
55 |
purchase_invoice => 'ap', |
|
56 |
letter => 'letter', |
|
57 |
purchase_delivery_order => 'delivery_orders', |
|
58 |
sales_delivery_order => 'delivery_orders', |
|
59 |
); |
|
60 |
|
|
48 | 61 |
sub new { |
49 | 62 |
my ($type, %params) = @_; |
50 | 63 |
my $self = { %params }; |
... | ... | |
263 | 276 |
|
264 | 277 |
$error = $@ if !$ok; |
265 | 278 |
|
279 |
# create journal and link to record |
|
266 | 280 |
$self->{journalentry} = $self->_store_in_journal; |
281 |
$self->_create_record_link if $self->{journalentry}; |
|
267 | 282 |
|
268 | 283 |
return $ok ? '' : ($error || "undefined error"); |
269 | 284 |
} |
... | ... | |
303 | 318 |
return $jentry->id; |
304 | 319 |
} |
305 | 320 |
|
321 |
|
|
322 |
sub _create_record_link { |
|
323 |
my ($self) = @_; |
|
324 |
|
|
325 |
# check for custom/overloaded types and ids (form != controller) |
|
326 |
my $record_type = $self->{record_type} || $::form->{type}; |
|
327 |
my $record_id = $self->{record_id} || $::form->{id}; |
|
328 |
|
|
329 |
# you may send mails for unsaved objects (no record_id => unlinkable case) |
|
330 |
if ($self->{journalentry} && $record_id && exists($type_to_table{$record_type})) { |
|
331 |
RecordLinks->create_links( |
|
332 |
mode => 'ids', |
|
333 |
from_table => $type_to_table{$record_type}, |
|
334 |
from_ids => $record_id, |
|
335 |
to_table => 'email_journal', |
|
336 |
to_id => $self->{journalentry}, |
|
337 |
); |
|
338 |
} |
|
339 |
} |
|
340 |
|
|
306 | 341 |
1; |
342 |
|
|
343 |
|
|
344 |
__END__ |
|
345 |
|
|
346 |
=pod |
|
347 |
|
|
348 |
=encoding utf8 |
|
349 |
|
|
350 |
=head1 NAME |
|
351 |
|
|
352 |
SL::Mailer - Base class for sending mails from kivitendo |
|
353 |
|
|
354 |
=head1 SYNOPSIS |
|
355 |
|
|
356 |
package SL::BackgroundJob::CreatePeriodicInvoices; |
|
357 |
|
|
358 |
use SL::Mailer; |
|
359 |
|
|
360 |
my $mail = Mailer->new; |
|
361 |
$mail->{from} = $config{periodic_invoices}->{email_from}; |
|
362 |
$mail->{to} = $email; |
|
363 |
$mail->{subject} = $config{periodic_invoices}->{email_subject}; |
|
364 |
$mail->{content_type} = $filename =~ m/.html$/ ? 'text/html' : 'text/plain'; |
|
365 |
$mail->{message} = $output; |
|
366 |
|
|
367 |
$mail->send; |
|
368 |
|
|
369 |
=head1 OVERVIEW |
|
370 |
|
|
371 |
Mail can be send from kivitendo via the sendmail command or the smtp protocol. |
|
372 |
|
|
373 |
|
|
374 |
=head1 INTERNAL DATA TYPES |
|
375 |
|
|
376 |
|
|
377 |
=over 2 |
|
378 |
|
|
379 |
=item C<%mail_delivery_modules> |
|
380 |
|
|
381 |
Currently two modules are supported either smtp or sendmail. |
|
382 |
|
|
383 |
=item C<%type_to_table> |
|
384 |
|
|
385 |
Due to the lack of a single global mapping for $form->{type}, |
|
386 |
type is mapped to the corresponding database table. All types which |
|
387 |
implement a mail action are currently mapped and should be mapped. |
|
388 |
Type is either the value of the old form or the newer controller |
|
389 |
based object type. |
|
390 |
|
|
391 |
=back |
|
392 |
|
|
393 |
=head1 FUNCTIONS |
|
394 |
|
|
395 |
=over 4 |
|
396 |
|
|
397 |
=item C<new> |
|
398 |
|
|
399 |
=item C<_create_driver> |
|
400 |
|
|
401 |
=item C<_cleanup_addresses> |
|
402 |
|
|
403 |
=item C<_create_address_headers> |
|
404 |
|
|
405 |
=item C<_create_message_id> |
|
406 |
|
|
407 |
=item C<_create_attachment_part> |
|
408 |
|
|
409 |
=item C<_create_message> |
|
410 |
|
|
411 |
=item C<send> |
|
412 |
|
|
413 |
If a mail was send successfully the internal functions _store_in_journal |
|
414 |
is called if email journaling is enabled. If _store_in_journal was executed |
|
415 |
successfully and the calling form is already persistent (database id) a |
|
416 |
record_link will be created. |
|
417 |
|
|
418 |
=item C<_all_recipients> |
|
419 |
|
|
420 |
=item C<_store_in_journal> |
|
421 |
|
|
422 |
=item C<_create_record_link $self->{journalentry}, $::form->{id}, $self->{record_id}> |
|
423 |
|
|
424 |
|
|
425 |
If $self->{journalentry} and either $self->{record_id} or $::form->{id} (checked in |
|
426 |
this order) exists a record link from record to email journal is created. |
|
427 |
Will fail silently if record_link creation wasn't successful (same behaviour as |
|
428 |
_store_in_journal). |
|
429 |
|
|
430 |
=item C<validate> |
|
431 |
|
|
432 |
=back |
|
433 |
|
|
434 |
=head1 BUGS |
|
435 |
|
|
436 |
Nothing here yet. |
|
437 |
|
|
438 |
=head1 AUTHOR |
|
439 |
|
|
440 |
=cut |
SL/Presenter/Record.pm | ||
---|---|---|
65 | 65 |
$output .= _sepa_transfer_list( $groups{sepa_transfers}, %params) if $groups{sepa_transfers}; |
66 | 66 |
|
67 | 67 |
$output .= _letter_list( $groups{letters}, %params) if $groups{letters}; |
68 |
$output .= _email_journal_list( $groups{email_journals}, %params) if $groups{email_journals}; |
|
68 | 69 |
|
69 | 70 |
$output = SL::Presenter->get->render('presenter/record/grouped_record_list', %params, output => $output); |
70 | 71 |
|
... | ... | |
193 | 194 |
gl_transactions => sub { (ref($_[0]) eq 'SL::DB::GLTransaction') }, |
194 | 195 |
bank_transactions => sub { (ref($_[0]) eq 'SL::DB::BankTransaction') && $_[0]->id }, |
195 | 196 |
letters => sub { (ref($_[0]) eq 'SL::DB::Letter') && $_[0]->id }, |
197 |
email_journals => sub { (ref($_[0]) eq 'SL::DB::EmailJournal') && $_[0]->id }, |
|
196 | 198 |
); |
197 | 199 |
|
198 | 200 |
my %groups; |
... | ... | |
554 | 556 |
); |
555 | 557 |
} |
556 | 558 |
|
559 |
sub _email_journal_list { |
|
560 |
my ($list, %params) = @_; |
|
561 |
|
|
562 |
return record_list( |
|
563 |
$list, |
|
564 |
title => $::locale->text('Email'), |
|
565 |
type => 'email_journal', |
|
566 |
columns => [ |
|
567 |
[ $::locale->text('Sent on'), sub { $_[0]->sent_on->to_kivitendo(precision => 'seconds') } ], |
|
568 |
[ $::locale->text('Subject'), sub { $_[0]->presenter->email_journal(display => 'table-cell') } ], |
|
569 |
[ $::locale->text('Status'), 'status' ], |
|
570 |
[ $::locale->text('From'), 'from' ], |
|
571 |
[ $::locale->text('To'), 'recipients' ], |
|
572 |
], |
|
573 |
%params, |
|
574 |
); |
|
575 |
} |
|
576 |
|
|
577 |
|
|
557 | 578 |
1; |
558 | 579 |
|
559 | 580 |
__END__ |
Auch abrufbar als: Unified diff
Verknüpfte Belege um die Verknüpfung 'E-Mail Journal' erweitert.
Falls das E-Mail-Journal aktiviert ist wird zusätzlich zu der
archivierten E-Mail auch die Verknüpfung vom Beleg zu der E-Mail mitgespeichert
und ist im Beleg zusätzlich direkt anwählbar.
Etwas mehr Details im POD vom Mailer.pm, die Implementierung orientiert
sich überwiegend an der Erweiterung der Verknüpfung von Letter.pm, bzw. dem ShopConnector.