Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision dfdfb88c

Von Tamino Steinert vor 6 Monaten hinzugefügt

  • ID dfdfb88c555d5b4f0be25b551e4bc2aa709b111b
  • Vorgänger 6aa91d87

EmailJournal: Komplexer Bericht mit komplexen Filter

Unterschiede anzeigen:

SL/Controller/EmailJournal.pm
use parent qw(SL::Controller::Base);
use SL::ReportGenerator;
use SL::Controller::Helper::ReportGenerator;
use SL::ZUGFeRD;
use SL::Controller::ZUGFeRD;
use SL::Controller::Helper::GetModels;
......
use SL::DB::EmailJournal;
use SL::DB::EmailJournalAttachment;
use SL::Presenter::EmailJournal;
use SL::Presenter::Filter::EmailJournal;
use SL::Presenter::Record qw(grouped_record_list);
use SL::Presenter::Tag qw(html_tag div_tag button_tag);
use SL::Helper::Flash;
......
my ($self) = @_;
$::auth->assert('email_journal');
# default filter
$::form->{filter} ||= {"obsolete:eq_ignore_empty" => 0};
if ( $::instance_conf->get_email_journal == 0 ) {
flash('info', $::locale->text('Storing the emails in the journal is currently disabled in the client configuration.'));
flash('info', t8('Storing the emails in the journal is currently disabled in the client configuration.'));
}
$::form->{filter} ||= {
'obsolete:eq_ignore_empty' => 0,
};
$self->setup_list_action_bar;
my @record_types_with_info = $self->get_record_types_with_info();
my %record_types_to_text = $self->get_record_types_to_text();
$self->render('email_journal/list',
title => $::locale->text('Email journal'),
ENTRIES => $self->models->get,
MODELS => $self->models,
RECORD_TYPES_WITH_INFO => \@record_types_with_info,
RECORD_TYPES_TO_TEXT => \%record_types_to_text,
);
my $report = $self->prepare_report;
$self->report_generator_list_objects(
report => $report,
objects => $self->models->get,
);
}
sub action_show {
......
return $customer_vendor;
}
sub prepare_report {
my ($self) = @_;
my %record_types_to_text = $self->get_record_types_to_text();
my @record_types_with_info = $self->get_record_types_with_info();
my $report = SL::ReportGenerator->new(\%::myconfig, $::form);
my $callback = $self->models->get_callback;
my @columns_order = qw(
id
sender
from
recipients
subject
sent_on
attachment_names
has_unprocessed_attachments
unprocessed_attachment_names
status
extended_status
record_type
linked_to
obsolete
);
my @default_columns = qw(
from
recipients
subject
sent_on
);
my %column_defs = (
id => {
obj_link => sub {$self->url_for(
action => 'show', id => $_[0]->id, callback => $callback
)},
sub => sub { $_[0]->id },
},
sender => {
sub => sub { $_[0]->sender ? $_[0]->sender->name : '' },
},
from => {
obj_link => sub {$self->url_for(
action => 'show', id => $_[0]->id, callback => $callback
)},
sub => sub { $_[0]->from },
},
recipients => {
obj_link => sub {$self->url_for(
action => 'show', id => $_[0]->id, callback => $callback
)},
sub => sub { $_[0]->recipients },
},
subject => {
obj_link => sub {$self->url_for(
action => 'show', id => $_[0]->id, callback => $callback
)},
sub => sub { $_[0]->subject },
},
sent_on => {
obj_link => sub {$self->url_for(
action => 'show', id => $_[0]->id, callback => $callback
)},
sub => sub { $_[0]->sent_on->to_kivitendo(precision => 'minute') },
},
attachment_names => {
sub => sub {join(', ',
map {$_->name}
sort {$a->position <=> $b->position}
@{$_[0]->attachments}
)},
},
has_unprocessed_attachments => {
sub => sub { $_[0]->has_unprocessed_attachments }
},
unprocessed_attachment_names => {
sub => sub {join(', ',
map {$_->name}
sort {$a->position <=> $b->position}
grep {$_->processed == 0}
@{$_[0]->attachments}
)},
},
status => {
sub => sub { SL::Presenter::EmailJournal::entry_status($_[0]) },
},
extended_status => {
sub => sub { $_[0]->extended_status },
},
record_type => {
sub => sub { $record_types_to_text{$_[0]->record_type} },
},
linked_to => {
raw_data => sub {
SL::Presenter::Record::simple_grouped_record_list($_[0]->linked_records)
}
},
obsolete => {
sub => sub { $_[0]->obsolete_as_bool_yn }
},
);
$column_defs{$_}->{text} ||=
t8( $self->models->get_sort_spec->{$_}->{title} || $_ )
for keys %column_defs;
# make all sortable
my @sortable = keys %column_defs;
unless ($::form->{active_in_report}) {
$::form->{active_in_report}->{$_} = 1 foreach @default_columns;
}
$column_defs{$_}->{visible} = $::form->{active_in_report}->{"$_"} || 0
foreach keys %column_defs;
my $filter_html = SL::Presenter::Filter::EmailJournal::filter(
$::form->{filter},
active_in_report => $::form->{active_in_report},
record_types_with_info => \@record_types_with_info,
);
$self->models->disable_plugin('paginated')
if $report->{options}{output_format} =~ /^(pdf|csv)$/i;
$self->models->add_additional_url_params(
active_in_report => $::form->{active_in_report}
);
$self->models->finalize; # for filter laundering
$report->set_options(
std_column_visibility => 1,
controller_class => 'EmailJournal',
output_format => 'HTML',
raw_top_info_text => $self->render(
'email_journal/_report_top',
{ output => 0 },
FILTER_HTML => $filter_html,
),
raw_bottom_info_text => $self->render(
'email_journal/_report_bottom',
{ output => 0 },
models => $self->models
),
title => t8('Email journal'),
allow_pdf_export => 1,
allow_csv_export => 1,
);
$report->set_columns(%column_defs);
$report->set_column_order(@columns_order);
$report->set_export_options('list', qw(filter active_in_report));
$report->set_options_from_form;
$self->models->set_report_generator_sort_options(
report => $report,
sortable_columns => \@sortable
);
return $report;
}
sub add_js {
$::request->{layout}->use_javascript("${_}.js") for qw(
kivi.EmailJournal
......
query => \@where,
with_objects => [ 'sender' ],
sorted => {
_default => {
by => 'sent_on',
dir => 0,
},
sender => t8('Sender'),
from => t8('From'),
recipients => t8('Recipients'),
subject => t8('Subject'),
attachments => t8('Attachments'),
attachment_names => t8('Attachments'),
has_unprocessed_attachments => t8('Has unprocessed attachments'),
unprocessed_attachment_names => t8('Unprocessed Attachments'),
sent_on => t8('Sent on'),
status => t8('Status'),
extended_status => t8('Extended status'),
record_type => t8('Record Type'),
obsolete => t8('Obsolete'),
linked_to => t8('Linked to'),
has_unprocessed_attachments => t8('Has unprocessed attachments'),
},
);
}
SL/DB/Manager/EmailJournal.pm
)
)} => \'TRUE';
},
unprocessed_attachment_names => sub {
my ($key, $value, $prefix) = @_;
return (
and => [
'attachments.name' => $value,
'attachments.processed' => 0,
],
'attachments'
)
},
has_unprocessed_attachments => sub {
my ($key, $value, $prefix) = @_;
......
AND record_links.to_id = email_journal.id
)
)},
attachment => qq{(
attachment_names => qq{(
SELECT STRING_AGG(
email_journal_attachments.name,
', '
ORDER BY email_journal_attachments.position ASC
)
FROM email_journal_attachments
WHERE
email_journal_attachments.email_journal_id = email_journal.id
)},
unprocessed_attachment_names => qq{(
SELECT STRING_AGG(
email_journal_attachments.name,
', '
......
FROM email_journal_attachments
WHERE
email_journal_attachments.email_journal_id = email_journal.id
AND email_journal_attachments.processed = FALSE
)},
has_unprocessed_attachments => qq{(
SELECT count(*)
SL/Presenter/Filter/EmailJournal.pm
package SL::Presenter::Filter::EmailJournal;
use parent SL::Presenter::Filter;
use strict;
use SL::Locale::String qw(t8);
use Params::Validate qw(:all);
sub get_default_filter_elements {
my $filter = shift @_;
my %params = validate_with(
params => \@_,
spec => {
record_types_with_info => {
type => ARRAYREF
},
},
);
my %default_filter_elements = ( # {{{
id => {
'position' => 1,
'text' => t8("ID"),
'input_type' => 'input_tag',
'input_name' => 'filter.id:number',
'input_default' => $filter->{'id:number'},
'report_id' => 'id',
'active' => 0,
},
sender => {
'position' => 2,
'text' => t8("Sender"),
'input_type' => 'input_tag',
'input_name' => 'filter.sender.name:substr::ilike',
'input_default' => $filter->{sender}->{'name:substr::ilike'},
'report_id' => 'sender',
'active' => $::auth->assert('email_employee_readall', 1),
},
from => {
'position' => 3,
'text' => t8("From"),
'input_type' => 'input_tag',
'input_name' => 'filter.from:substr::ilike',
'input_default' => $filter->{'from:substr::ilike'},
'report_id' => 'from',
'active' => 1,
},
recipients => {
'position' => 4,
'text' => t8("Recipients"),
'input_type' => 'input_tag',
'input_name' => 'filter.recipients:substr::ilike',
'input_default' => $filter->{'recipients:substr::ilike'},
'report_id' => 'recipients',
'active' => 1,
},
subject => {
'position' => 5,
'text' => t8("Subject"),
'input_type' => 'input_tag',
'input_name' => 'filter.subject:substr::ilike',
'input_default' => $filter->{'subject:substr::ilike'},
'report_id' => 'subject',
'active' => 1,
},
sent_on => {
'position' => 6,
'text' => t8("Sent on"),
'input_type' => 'date_tag',
'input_name' => 'sent_on',
'input_default_ge' => $filter->{'sent_on' . ':date::ge'},
'input_default_le' => $filter->{'sent_on' . ':date::le'},
'report_id' => 'sent_on',
'active' => 1,
},
attachment_names => {
'position' => 7,
'text' => t8("Attachments"),
'input_type' => 'input_tag',
'input_name' => 'filter.attachments.name:substr::ilike',
'input_default' => $filter->{attachments}->{'name:substr::ilike'},
'report_id' => 'attachment_names',
'active' => 1,
},
'has_unprocessed_attachments' => {
'position' => 8,
'text' => t8("Has unprocessed attachments"),
'input_type' => 'yes_no_tag',
'input_name' => 'filter.has_unprocessed_attachments:eq_ignore_empty',
'input_default' => $filter->{'has_unprocessed_attachments:eq_ignore_empty'},
'report_id' => 'has_unprocessed_attachments',
'active' => 1,
},
unprocessed_attachment_names => {
'position' => 9,
'text' => t8("Unprocessed Attachments"),
'input_type' => 'input_tag',
'input_name' => 'filter.unprocessed_attachment_names:substr::ilike',
'input_default' => $filter->{'unprocessed_attachment_names:substr::ilike'},
'report_id' => 'unprocessed_attachment_names',
'active' => 1,
},
status => {
'position' => 10,
'text' => t8("Status"),
'input_type' => 'select_tag',
'input_values' => [
[ "", "" ],
[ "send_failed", t8("send failed") ],
[ "sent", t8("sent") ],
[ "imported", t8("imported") ]
],
'input_name' => 'filter.status',
'input_default' => $filter->{'status'},
'report_id' => 'status',
'active' => 1,
},
extended_status => {
'position' => 11,
'text' => t8("Extended status"),
'input_type' => 'input_tag',
'input_name' => 'filter.extended_status:substr::ilike',
'input_default' => $filter->{'extended_status:substr::ilike'},
'report_id' => 'extended_status',
'active' => 1,
},
record_type => {
'position' => 12,
'text' => t8("Record Type"),
'input_type' => 'select_tag',
'input_values' => [
map {[
$_->{record_type} => $_->{text},
]}
grep {!$_->{is_template}}
{},
{text=> t8("Catch-all"), record_type => 'catch_all'},
@{$params{record_types_with_info}}
],
'input_name' => 'filter.record_type:eq_ignore_empty',
'input_default' => $filter->{'record_type:eq_ignore_empty'},
'report_id' => 'record_type',
'active' => 1,
},
'linked' => {
'position' => 13,
'text' => t8("Linked"),
'input_type' => 'yes_no_tag',
'input_name' => 'filter.linked_to:eq_ignore_empty',
'input_default' => $filter->{'linked_to:eq_ignore_empty'},
'report_id' => 'linked_to',
'active' => 1,
},
'obsolete' => {
'position' => 14,
'text' => t8("Obsolete"),
'input_type' => 'yes_no_tag',
'input_name' => 'filter.obsolete:eq_ignore_empty',
'input_default' => $filter->{'obsolete:eq_ignore_empty'},
'report_id' => 'obsolete',
'active' => 1,
},
); # }}}
return \%default_filter_elements;
}
sub filter {
my $filter = shift @_;
die "filter has to be a hash ref" if ref $filter ne 'HASH';
my %params = validate_with(
params => \@_,
spec => {
record_types_with_info => {
type => ARRAYREF
},
},
allow_extra => 1,
);
my $filter_elements = get_default_filter_elements($filter,
record_types_with_info => delete $params{record_types_with_info},
);
return SL::Presenter::Filter::create_filter($filter_elements, %params);
}
1;
__END__
=pod
=encoding utf8
=head1 NAME
SL::Presenter::Filter::EmailJournal - Presenter module for a generic filter on
EmailJournal.
=head1 SYNOPSIS
# in EmailJournal Controller
my $filter_html = SL::Presenter::Filter::EmailJournal::filter(
$::form->{filter},
active_in_report => $::form->{active_in_report}
record_types_with_info => \@record_types_with_info,
);
=head1 FUNCTIONS
=over 4
=item C<filter $filter, %params>
Returns a rendered version (actually an instance of
L<SL::Presenter::EscapedText>) of a filter form for email journal.
C<$filter> should be the C<filter> value of the last C<$::form>. This is used to
get the previous values of the input fields.
C<%params> can include:
=over 2
= item * record_types_with_info
Is used to set the drop down for record type.
=back
Other C<%params> fields get forwarded to
C<SL::Presenter::Filter::create_filter>.
=back
=head1 BUGS
Nothing here yet.
=head1 AUTHOR
Tamino Steinert E<lt>tamino.steinert@tamino.stE<gt>
=cut
locale/de/all
'There are mulitple vendors selected' => 'Es sind mehrere Lieferanten ausgewählt',
'There are no documents in the WebDAV directory at the moment.' => 'Es befinden sich im WebDAV-Verzeichnis momentan keine Dokumente.',
'There are no entries in the background job history.' => 'Es gibt keine Einträge im Hintergrund-Job-Verlauf.',
'There are no entries that match the filter.' => 'Es gibt keine Einträge, auf die der Filter zutrifft.',
'There are no items in stock.' => 'Dieser Artikel ist nicht eingelagert.',
'There are no items on your TODO list at the moment.' => 'Ihre Aufgabenliste enthält momentan keine Einträge.',
'There are no items selected' => 'Es wurden keine Positionen ausgewählt',
......
'Unlink bank transactions' => 'Bankverbuchung(en) rückgängig machen',
'Unlock System' => 'System entsperren',
'Unprocessed' => 'Nicht verarbeitet',
'Unprocessed Attachments' => 'Nicht verarbeitete Anhänge',
'Unsuccessfully executed:\n' => 'Erfolglos ausgeführt:',
'Unsupported image type (supported types: #1)' => 'Nicht unterstützter Bildtyp (unterstützte Typen: #1)',
'Until' => 'Bis',
locale/en/all
'There are mulitple vendors selected' => '',
'There are no documents in the WebDAV directory at the moment.' => '',
'There are no entries in the background job history.' => '',
'There are no entries that match the filter.' => '',
'There are no items in stock.' => '',
'There are no items on your TODO list at the moment.' => '',
'There are no items selected' => '',
......
'Unlink bank transactions' => '',
'Unlock System' => '',
'Unprocessed' => '',
'Unprocessed Attachments' => '',
'Unsuccessfully executed:\n' => '',
'Unsupported image type (supported types: #1)' => '',
'Until' => '',
templates/design40_webpages/email_journal/_filter.html
[% USE L %]
[% USE LxERP %]
[% USE HTML %]
[% BLOCK filter_toggle_panel %]
<table id="filter_table" class="tbl-horizontal">
<tbody>
<tr>
<th>[% LxERP.t8("From") %]</th>
<td>[% L.input_tag("filter.from:substr::ilike", filter.from_substr__ilike, size = 20) %]
</td>
</tr>
<tr>
<th>[% LxERP.t8("Recipients") %]</th>
<td>[% L.input_tag("filter.recipients:substr::ilike", filter.recipients_substr__ilike, size = 20) %]
</td>
</tr>
<tr>
<th>[% LxERP.t8("Sent on") %]</th>
<td>[% L.date_tag("filter.sent_on:date::ge", filter.sent_on_date__ge) %] [% LxERP.t8("To Date") %] [% L.date_tag("filter.sent_on:date::le", filter.sent_on_date__le) %]
</td>
</tr>
<tr>
<th>[% LxERP.t8("Status") %]</th>
<td>[% L.select_tag("filter.status:eq_ignore_empty", [
[ "", "" ],
[ "send_failed", LxERP.t8("send failed") ],
[ "sent", LxERP.t8("sent") ],
[ "imported", LxERP.t8("imported") ]
], default=filter.status_eq_ignore_empty) %]
</td>
</tr>
<tr>
<th>[% LxERP.t8("Record Type") %]</th>
<td>
[%
SET record_type_options = [];
record_type_options.push({text=LxERP.t8("Catch-all"), record_type='catch_all'});
FOREACH record_info = RECORD_TYPES_WITH_INFO;
IF (!record_info.is_template);
record_type_options.push(record_info);
END;
END;
%]
[% L.select_tag("filter.record_type:eq_ignore_empty",
record_type_options,
title_key = 'text', value_key = 'record_type',
with_empty=1, default=filter.record_type_eq_ignore_empty) %]
</td>
</tr>
<tr>
<th>[% LxERP.t8("Obsolete") %]</th>
<td>[% L.yes_no_tag("filter.obsolete:eq_ignore_empty",
filter.obsolete, with_empty=1,
default=filter.obsolete_eq_ignore_empty
) %]
</td>
</tr>
<tr>
<th>[% LxERP.t8("Linked") %]</th>
<td>[% L.yes_no_tag("filter.linked_to:eq_ignore_empty",
filter.linked_to, with_empty=1,
default=filter.linked_to_eq_ignore_empty
) %]
</td>
</tr>
<tr>
<th>[% LxERP.t8("Has unprocessed attachments") %]</th>
<td>[% L.yes_no_tag("filter.has_unprocessed_attachments:eq_ignore_empty",
filter.has_unprocessed_attachments, with_empty=1,
default=filter.has_unprocessed_attachments_eq_ignore_empty
) %]
</td>
</tr>
</tbody>
</table>
[% L.hidden_tag("sort_by", FORM.sort_by) %]
[% L.hidden_tag("sort_dir", FORM.sort_dir) %]
[% L.hidden_tag("page", FORM.page) %]
<div class="buttons">[% L.button_tag('$("#filter_form").resetForm()', LxERP.t8('Reset')) %]</div>
[% END %]
<div class="wrapper">
<form action="controller.pl" method="post" id="filter_form">
[% INCLUDE common/toggle_panel.html %]
</div>
</form>
</div>
templates/design40_webpages/email_journal/_report_bottom.html
[% USE L %]
[%- L.paginate_controls(models=models) %]
templates/design40_webpages/email_journal/_report_top.html
[% USE L %]
[% BLOCK filter_toggle_panel %]
[%- FILTER_HTML %]
[% END %]
<div class="wrapper">
[% SET display_status = 'open' %]
[% INCLUDE 'common/toggle_panel.html' %]
</div><!-- /.wrapper -->
templates/design40_webpages/email_journal/list.html
[% USE HTML %]
[% USE L %]
[% USE P %]
[% USE LxERP %]
<h1>[% FORM.title %]</h1>
[% INCLUDE 'common/flash.html' %]
[% PROCESS 'email_journal/_filter.html' filter=SELF.models.filtered.laundered %]
[% IF !ENTRIES.size %]
<p>[% LxERP.t8('There are no entries that match the filter.') %]</p>
[% ELSE %]
<table id="email_journal_list" class="tbl-list wi-moderate">
<thead>
<tr>
[% IF SELF.can_view_all %]
<th>[% L.sortable_table_header("sender") %]</th>
[% END %]
<th>[% L.sortable_table_header("from") %]</th>
<th>[% L.sortable_table_header("recipients") %]</th>
<th>[% L.sortable_table_header("subject") %]</th>
<th>[% L.sortable_table_header("sent_on") %]</th>
<th>[% L.sortable_table_header("attachments") %]</th>
<th>[% L.sortable_table_header("status") %]</th>
<th>[% L.sortable_table_header("extended_status") %]</th>
<th>[% L.sortable_table_header("record_type") %]</th>
<th>[% L.sortable_table_header("obsolete") %]</th>
<th>[% L.sortable_table_header("linked_to") %]</th>
<th>[% L.sortable_table_header("has_unprocessed_attachments") %]</th>
</tr>
</thead>
<tbody>
[% FOREACH entry = ENTRIES %]
<tr id="email_journal_id_[% entry.id %]" [% IF entry.status == 'send_failed' %] class="listrow_error" [% END %]>
[% IF SELF.can_view_all %]
<td>[% IF entry.sender %] [% HTML.escape(entry.sender.name) %] [% ELSE %] [% LxERP.t8("kivitendo") %] [% END %]</td>
[% END %]
[% action_show_link = SELF.url_for(
action => 'show', id => entry.id,
back_to => SELF.models.get_callback(),
) %]
<td><a href="[% action_show_link %]"> [% HTML.escape(entry.from) %] </a></td>
<td>[% HTML.escape(entry.recipients) %]</td>
<td><a href="[% action_show_link %]"> [% HTML.escape(entry.subject) %] </a></td>
<td>[% HTML.escape(entry.sent_on.to_lxoffice('precision' => 'second')) %]</td>
<td>
[% FOREACH attachment = entry.attachments %]
<span>[% HTML.escape(attachment.name) %]</span>
[% END %]
</td>
<td> [% P.email_journal.entry_status(entry) %] </td>
<td>[% HTML.escape(entry.extended_status) %]</td>
<td>[% HTML.escape(RECORD_TYPES_TO_TEXT.${entry.record_type}) %]</td>
<td>[% HTML.escape(entry.obsolete_as_bool_yn) %]</td>
<td>
[% P.record.simple_grouped_record_list(entry.linked_records) %]
</td>
<td>[% HTML.escape(entry.has_unprocessed_attachments) %]</td>
</tr>
[% END %]
</tbody>
</table>
[% END %]
[% L.paginate_controls %]
templates/webpages/email_journal/_filter.html
[%- USE L %][%- USE LxERP %][%- USE HTML %]
<form action="controller.pl" method="post" id="filter_form">
<div class="filter_toggle">
<a href="#" onClick="javascript:$('.filter_toggle').toggle()">[% LxERP.t8('Show Filter') %]</a>
[% IF SELF.filter_summary %]([% LxERP.t8("Current filter") %]: [% SELF.filter_summary %])[% END %]
</div>
<div class="filter_toggle" style="display:none">
<a href="#" onClick="javascript:$('.filter_toggle').toggle()">[% LxERP.t8('Hide Filter') %]</a>
<table id="filter_table">
<tr>
<th align="right">[% LxERP.t8("From") %]</th>
<td>[% L.input_tag("filter.from:substr::ilike", filter.from_substr__ilike, size = 20) %]</td>
</tr>
<tr>
<th align="right">[% LxERP.t8("Recipients") %]</th>
<td>[% L.input_tag("filter.recipients:substr::ilike", filter.recipients_substr__ilike, size = 20) %]</td>
</tr>
<tr>
<th align="right">[% LxERP.t8("Sent on") %]</th>
<td>
[% L.date_tag("filter.sent_on:date::ge", filter.sent_on_date__ge) %]
[% LxERP.t8("To Date") %]
[% L.date_tag("filter.sent_on:date::le", filter.sent_on_date__le) %]
</td>
</tr>
<tr>
<th align="right">[% LxERP.t8("Status") %]</th>
<td>[% L.select_tag("filter.status:eq_ignore_empty", [
[ "", "" ],
[ "send_failed", LxERP.t8("send failed") ],
[ "sent", LxERP.t8("sent") ],
[ "imported", LxERP.t8("imported") ]
], default=filter.status_eq_ignore_empty) %]</td>
</tr>
<tr>
<th align="right">[% LxERP.t8("Record Type") %]</th>
<td>
[%
SET record_type_options = [];
record_type_options.push({text=LxERP.t8("Catch-all"), record_type='catch_all'});
FOREACH record_info = RECORD_TYPES_WITH_INFO;
IF (!record_info.is_template);
record_type_options.push(record_info);
END;
END;
%]
[% L.select_tag("filter.record_type:eq_ignore_empty",
record_type_options,
title_key = 'text', value_key = 'record_type',
with_empty=1, default=filter.record_type_eq_ignore_empty) %]
</td>
</tr>
<tr>
<th align="right">[% LxERP.t8("Obsolete") %]</th>
<td>[% L.yes_no_tag("filter.obsolete:eq_ignore_empty",
filter.obsolete, with_empty=1,
default=filter.obsolete_eq_ignore_empty
) %]
</td>
<tr>
<th align="right">[% LxERP.t8("Linked") %]</th>
<td>[% L.yes_no_tag("filter.linked_to:eq_ignore_empty",
filter.linked_to, with_empty=1,
default=filter.linked_to_eq_ignore_empty
) %]
</td>
</tr>
<tr>
<th>[% LxERP.t8("Has unprocessed attachments") %]</th>
<td>[% L.yes_no_tag("filter.has_unprocessed_attachments:eq_ignore_empty",
filter.has_unprocessed_attachments, with_empty=1,
default=filter.has_unprocessed_attachments_eq_ignore_empty
) %]
</td>
</tr>
</table>
[% L.hidden_tag("sort_by", FORM.sort_by) %]
[% L.hidden_tag("sort_dir", FORM.sort_dir) %]
[% L.hidden_tag("page", FORM.page) %]
[% L.button_tag('$("#filter_form").resetForm()', LxERP.t8('Reset')) %]
</div>
</form>
templates/webpages/email_journal/_report_bottom.html
[% USE L %]
[%- L.paginate_controls(models=models) %]
templates/webpages/email_journal/_report_top.html
[% USE L %]
[% FILTER_HTML %]
templates/webpages/email_journal/list.html
[% USE HTML %][% USE L %][% USE P %][% USE LxERP %]
<h1>[% FORM.title %]</h1>
[%- INCLUDE 'common/flash.html' %]
[%- PROCESS 'email_journal/_filter.html' filter=SELF.models.filtered.laundered %]
[% IF !ENTRIES.size %]
<p>
[%- LxERP.t8('There are no entries that match the filter.') %]
</p>
[%- ELSE %]
<table id="email_journal_list" width="100%">
<thead>
<tr class="listheading">
[% IF SELF.can_view_all %]
<th>[% L.sortable_table_header("sender") %]</th>
[% END %]
<th>[% L.sortable_table_header("from") %]</th>
<th>[% L.sortable_table_header("recipients") %]</th>
<th>[% L.sortable_table_header("subject") %]</th>
<th>[% L.sortable_table_header("sent_on") %]</th>
<th>[% L.sortable_table_header("attachments") %]</th>
<th>[% L.sortable_table_header("status") %]</th>
<th>[% L.sortable_table_header("extended_status") %]</th>
<th>[% L.sortable_table_header("record_type") %]</th>
<th>[% L.sortable_table_header("obsolete") %]</th>
<th>[% L.sortable_table_header("linked_to") %]</th>
<th>[% L.sortable_table_header("has_unprocessed_attachments") %]</th>
</tr>
</thead>
<tbody>
[%- FOREACH entry = ENTRIES %]
<tr class="listrow[% IF entry.status == 'send_failed' %]_error[% END %]" id="email_journal_id_[% entry.id %]">
[% IF SELF.can_view_all %]
<td>
[% IF entry.sender %]
[% HTML.escape(entry.sender.name) %]
[% ELSE %]
[% LxERP.t8("kivitendo") %]
[% END %]
</td>
[% END %]
[% action_show_link = SELF.url_for(
action => 'show', id => entry.id,
back_to => SELF.models.get_callback(),
) %]
<td><a href="[% action_show_link %]">[%- HTML.escape(entry.from) %]</a></td>
<td>[%- HTML.escape(entry.recipients) %]</td>
<td><a href="[% action_show_link %]">[%- HTML.escape(entry.subject) %]</a></td>
<td>[%- HTML.escape(entry.sent_on.to_lxoffice('precision' => 'second')) %]</td>
<td>
[% FOREACH attachment = entry.attachments %]
<span>[% HTML.escape(attachment.name) %]</span>
[% END %]
</td>
<td> [% P.email_journal.entry_status(entry) %] </td>
<td>[%- HTML.escape(entry.extended_status) %]</td>
<td>[% HTML.escape(RECORD_TYPES_TO_TEXT.${entry.record_type}) %]</td>
<td>[% HTML.escape(entry.obsolete_as_bool_yn) %]</td>
<td>
[% P.record.simple_grouped_record_list(entry.linked_records) %]
</td>
<td>[% HTML.escape(entry.has_unprocessed_attachments) %]</td>
</tr>
[%- END %]
</tbody>
</table>
[%- END %]
[% L.paginate_controls %]

Auch abrufbar als: Unified diff