for my $recipient (@recipients) {
my $mail = Mailer->new;
+ $mail->{record_id} = $data->{invoice}->id,
+ $mail->{record_type} = 'invoice',
$mail->{from} = $data->{config}->email_sender || $::lx_office_conf{periodic_invoices}->{email_from};
$mail->{to} = $recipient;
$mail->{bcc} = $global_bcc;
name => $params{email}->{attachment_filename} }];
$mail->{message} .= "\n-- \n$signature";
$mail->{message} =~ s/\r//g;
-
+ $mail->{record_id} = $letter->id;
$mail->send;
unlink $result{file_name};
{ title => t8('Purchase delivery order'), type => 'purchase_delivery_order', model => 'DeliveryOrder', number => 'donumber', },
{ title => t8('Purchase Invoice'), type => 'purchase_invoice', model => 'PurchaseInvoice', number => 'invnumber', },
{ title => t8('Letter'), type => 'letter', model => 'Letter', number => 'letternumber', description => 'subject', description_title => t8('Subject'), date => 'date', project => undef },
+ { title => t8('Email'), type => 'email_journal', model => 'EmailJournal', number => 'id', description => 'subject', description_title => t8('Subject'), },
);
my @link_types = map { +{ %link_type_defaults, %{ $_ } } } @link_type_specifics;
__PACKAGE__->attr_sorted('attachments');
+sub compare_to {
+ my ($self, $other) = @_;
+
+ return -1 if $self->sent_on && !$other->sent_on;
+ return 1 if !$self->sent_on && $other->sent_on;
+
+ my $result = 0;
+ $result = $other->sent_on <=> $self->sent_on;
+ return $result || ($self->id <=> $other->id);
+}
+
1;
+
+__END__
+
+=pod
+
+=encoding utf8
+
+=head1 NAME
+
+SL::DB::EmailJournal - RDBO model for email journal
+
+=head1 SYNOPSIS
+
+This is a standard Rose::DB::Object based model and can be used as one.
+
+=head1 METHODS
+
+=over 4
+
+=item C<compare_to $self, $other>
+
+Compares C<$self> with C<$other> and returns the newer entry.
+
+=back
+
+=cut
+
}
# don't use rose retrieval here. too slow.
- # instead use recursive sql to get all the linked record_links entrys, and retrieve the objects from there
+ # instead use recursive sql to get all the linked record_links entries and retrieve the objects from there
my $query = <<"";
WITH RECURSIVE record_links_rec_${wanted}(id, from_table, from_id, to_table, to_id, depth, path, cycle) AS (
SELECT id, from_table, from_id, to_table, to_id,
'SL::DB::RequirementSpec' => sub { $_[0]->id },
'SL::DB::Letter' => sub { $_[0]->letternumber },
'SL::DB::ShopOrder' => sub { $_[0]->shop_ordernumber },
+ 'SL::DB::EmailJournal' => sub { $_[0]->id },
UNKNOWN => '9999999999999999',
);
my $number_xtor = sub {
'SL::DB::PurchaseInvoice' => 150,
'SL::DB::Letter' => 200,
'SL::DB::ShopOrder' => 250,
+ 'SL::DB::EmailJournal' => 300,
UNKNOWN => 999,
);
my $score_xtor = sub {
smtp => 'SL::Mailer::SMTP',
);
+my %type_to_table = (
+ sales_quotation => 'oe',
+ request_quotation => 'oe',
+ sales_order => 'oe',
+ purchase_order => 'oe',
+ invoice => 'ar',
+ credit_note => 'ar',
+ purchase_invoice => 'ap',
+ letter => 'letter',
+ purchase_delivery_order => 'delivery_orders',
+ sales_delivery_order => 'delivery_orders',
+);
+
sub new {
my ($type, %params) = @_;
my $self = { %params };
$error = $@ if !$ok;
+ # create journal and link to record
$self->{journalentry} = $self->_store_in_journal;
+ $self->_create_record_link if $self->{journalentry};
return $ok ? '' : ($error || "undefined error");
}
return $jentry->id;
}
+
+sub _create_record_link {
+ my ($self) = @_;
+
+ # check for custom/overloaded types and ids (form != controller)
+ my $record_type = $self->{record_type} || $::form->{type};
+ my $record_id = $self->{record_id} || $::form->{id};
+
+ # you may send mails for unsaved objects (no record_id => unlinkable case)
+ if ($self->{journalentry} && $record_id && exists($type_to_table{$record_type})) {
+ RecordLinks->create_links(
+ mode => 'ids',
+ from_table => $type_to_table{$record_type},
+ from_ids => $record_id,
+ to_table => 'email_journal',
+ to_id => $self->{journalentry},
+ );
+ }
+}
+
1;
+
+
+__END__
+
+=pod
+
+=encoding utf8
+
+=head1 NAME
+
+SL::Mailer - Base class for sending mails from kivitendo
+
+=head1 SYNOPSIS
+
+ package SL::BackgroundJob::CreatePeriodicInvoices;
+
+ use SL::Mailer;
+
+ my $mail = Mailer->new;
+ $mail->{from} = $config{periodic_invoices}->{email_from};
+ $mail->{to} = $email;
+ $mail->{subject} = $config{periodic_invoices}->{email_subject};
+ $mail->{content_type} = $filename =~ m/.html$/ ? 'text/html' : 'text/plain';
+ $mail->{message} = $output;
+
+ $mail->send;
+
+=head1 OVERVIEW
+
+Mail can be send from kivitendo via the sendmail command or the smtp protocol.
+
+
+=head1 INTERNAL DATA TYPES
+
+
+=over 2
+
+=item C<%mail_delivery_modules>
+
+ Currently two modules are supported either smtp or sendmail.
+
+=item C<%type_to_table>
+
+ Due to the lack of a single global mapping for $form->{type},
+ type is mapped to the corresponding database table. All types which
+ implement a mail action are currently mapped and should be mapped.
+ Type is either the value of the old form or the newer controller
+ based object type.
+
+=back
+
+=head1 FUNCTIONS
+
+=over 4
+
+=item C<new>
+
+=item C<_create_driver>
+
+=item C<_cleanup_addresses>
+
+=item C<_create_address_headers>
+
+=item C<_create_message_id>
+
+=item C<_create_attachment_part>
+
+=item C<_create_message>
+
+=item C<send>
+
+ If a mail was send successfully the internal functions _store_in_journal
+ is called if email journaling is enabled. If _store_in_journal was executed
+ successfully and the calling form is already persistent (database id) a
+ record_link will be created.
+
+=item C<_all_recipients>
+
+=item C<_store_in_journal>
+
+=item C<_create_record_link $self->{journalentry}, $::form->{id}, $self->{record_id}>
+
+
+ If $self->{journalentry} and either $self->{record_id} or $::form->{id} (checked in
+ this order) exists a record link from record to email journal is created.
+ Will fail silently if record_link creation wasn't successful (same behaviour as
+ _store_in_journal).
+
+=item C<validate>
+
+=back
+
+=head1 BUGS
+
+Nothing here yet.
+
+=head1 AUTHOR
+
+=cut
$output .= _sepa_transfer_list( $groups{sepa_transfers}, %params) if $groups{sepa_transfers};
$output .= _letter_list( $groups{letters}, %params) if $groups{letters};
+ $output .= _email_journal_list( $groups{email_journals}, %params) if $groups{email_journals};
$output = SL::Presenter->get->render('presenter/record/grouped_record_list', %params, output => $output);
gl_transactions => sub { (ref($_[0]) eq 'SL::DB::GLTransaction') },
bank_transactions => sub { (ref($_[0]) eq 'SL::DB::BankTransaction') && $_[0]->id },
letters => sub { (ref($_[0]) eq 'SL::DB::Letter') && $_[0]->id },
+ email_journals => sub { (ref($_[0]) eq 'SL::DB::EmailJournal') && $_[0]->id },
);
my %groups;
);
}
+sub _email_journal_list {
+ my ($list, %params) = @_;
+
+ return record_list(
+ $list,
+ title => $::locale->text('Email'),
+ type => 'email_journal',
+ columns => [
+ [ $::locale->text('Sent on'), sub { $_[0]->sent_on->to_kivitendo(precision => 'seconds') } ],
+ [ $::locale->text('Subject'), sub { $_[0]->presenter->email_journal(display => 'table-cell') } ],
+ [ $::locale->text('Status'), 'status' ],
+ [ $::locale->text('From'), 'from' ],
+ [ $::locale->text('To'), 'recipients' ],
+ ],
+ %params,
+ );
+}
+
+
1;
__END__