Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision 72f19f83

Von Moritz Bunkus vor mehr als 9 Jahren hinzugefügt

  • ID 72f19f83681b222d1606d75c90ceedc43bb545f9
  • Vorgänger 7e601869
  • Nachfolger 358a7497

E-Mail-Journal: Journal anzeigen, Eintrag anzeigen, Anhänge herunterladen

Unterschiede anzeigen:

SL/Controller/EmailJournal.pm
1
package SL::Controller::EmailJournal;
2

  
3
use strict;
4

  
5
use parent qw(SL::Controller::Base);
6

  
7
use SL::Controller::Helper::GetModels;
8
use SL::DB::Employee;
9
use SL::DB::EmailJournal;
10
use SL::DB::EmailJournalAttachment;
11
use SL::Helper::Flash;
12
use SL::Locale::String;
13
use SL::System::TaskServer;
14

  
15
use Rose::Object::MakeMethods::Generic
16
(
17
  scalar                  => [ qw(entry) ],
18
  'scalar --get_set_init' => [ qw(models can_view_all filter_summary) ],
19
);
20

  
21
__PACKAGE__->run_before('add_stylesheet');
22

  
23
#
24
# actions
25
#
26

  
27
sub action_list {
28
  my ($self) = @_;
29

  
30
  $self->render('email_journal/list',
31
                title   => $::locale->text('Email journal'),
32
                ENTRIES => $self->models->get,
33
                MODELS  => $self->models);
34
}
35

  
36
sub action_show {
37
  my ($self) = @_;
38

  
39
  my $back_to = $::form->{back_to} || $self->url_for(action => 'list');
40

  
41
  $self->entry(SL::DB::EmailJournal->new(id => $::form->{id})->load);
42

  
43
  if (!$self->can_view_all && ($self->entry->sender_id != SL::DB::Manager::Emplyee->current->id)) {
44
    $::form->error(t8('You do not have permission to access this entry.'));
45
  }
46

  
47
  $self->render('email_journal/show',
48
                title   => $::locale->text('View sent email'),
49
                back_to => $back_to);
50
}
51

  
52
sub action_download_attachment {
53
  my ($self) = @_;
54

  
55
  my $attachment = SL::DB::EmailJournalAttachment->new(id => $::form->{id})->load;
56

  
57
  if (!$self->can_view_all && ($attachment->email_journal->sender_id != SL::DB::Manager::Emplyee->current->id)) {
58
    $::form->error(t8('You do not have permission to access this entry.'));
59
  }
60

  
61
  $self->send_file(\$attachment->content, name => $attachment->name, type => $attachment->mime_type);
62
}
63

  
64
#
65
# filters
66
#
67

  
68
sub add_stylesheet {
69
  $::request->{layout}->use_stylesheet('email_journal.css');
70
}
71

  
72
#
73
# helpers
74
#
75

  
76
sub init_can_view_all { $::auth->assert('admin', 1) }
77

  
78
sub init_models {
79
  my ($self) = @_;
80

  
81
  my @where;
82
  push @where, (sender_id => SL::DB::Manager::Employee->current->id) if !$self->can_view_all;
83

  
84
  SL::Controller::Helper::GetModels->new(
85
    controller        => $self,
86
    query             => \@where,
87
    with_objects      => [ 'sender' ],
88
    sorted            => {
89
      sender          => t8('Sender'),
90
      from            => t8('From'),
91
      recipients      => t8('Recipients'),
92
      subject         => t8('Subject'),
93
      sent_on         => t8('Sent on'),
94
      status          => t8('Status'),
95
      extended_status => t8('Extended status'),
96
    },
97
  );
98
}
99

  
100
sub init_filter_summary {
101
  my ($self)  = @_;
102

  
103
  my $filter  = $::form->{filter} || {};
104
  my @filters = (
105
    [ "from:substr::ilike",       $::locale->text('From')                                         ],
106
    [ "recipients:substr::ilike", $::locale->text('Recipients')                                   ],
107
    [ "sent_on:date::ge",         $::locale->text('Sent on') . " " . $::locale->text('From Date') ],
108
    [ "sent_on:date::le",         $::locale->text('Sent on') . " " . $::locale->text('To Date')   ],
109
  );
110

  
111
  my @filter_strings = grep { $_ }
112
                       map  { $filter->{ $_->[0] } ? $_->[1] . ' ' . $filter->{ $_->[0] } : undef }
113
                       @filters;
114

  
115
  my %status = (
116
    failed  => $::locale->text('failed'),
117
    ok      => $::locale->text('succeeded'),
118
  );
119
  push @filter_strings, $status{ $filter->{'status:eq_ignore_empty'} } if $filter->{'status:eq_ignore_empty'};
120

  
121
  return join ', ', @filter_strings;
122
}
123

  
124
1;
SL/DB/EmailJournal.pm
4 4

  
5 5
use SL::DB::MetaSetup::EmailJournal;
6 6
use SL::DB::Manager::EmailJournal;
7
use SL::DB::Helper::AttrSorted;
7 8

  
8 9
__PACKAGE__->meta->add_relationship(
9 10
  attachments  => {
......
15 16

  
16 17
__PACKAGE__->meta->initialize;
17 18

  
19
__PACKAGE__->attr_sorted('attachments');
20

  
18 21
1;
SL/DB/Manager/EmailJournal.pm
4 4

  
5 5
use parent qw(SL::DB::Helper::Manager);
6 6

  
7
use SL::DB::Helper::Paginated;
8
use SL::DB::Helper::Sorted;
9

  
7 10
sub object_class { 'SL::DB::EmailJournal' }
8 11

  
9 12
__PACKAGE__->make_manager_methods;
10 13

  
14
sub _sort_spec {
15
  return (
16
    default => [ 'sent_on', 1 ],
17
    columns => {
18
      SIMPLE => 'ALL',
19
      sender => 'sender.name',
20
    },
21
  );
22
}
23

  
11 24
1;
css/email_journal.css
1
/* E-Mail-Journal */
2
.email_journal_details tbody pre {
3
  margin: 0px;
4
}
5

  
6
.email_journal_details tbody th {
7
  text-align: right;
8
  vertical-align: top;
9
}
10

  
11
.email_journal_details tbody td {
12
  vertical-align: top;
13
}
locale/de/all
302 302
  'Attach PDF:'                 => 'PDF anhängen',
303 303
  'Attachment'                  => 'als Anhang',
304 304
  'Attachment name'             => 'Name des Anhangs',
305
  'Attachments'                 => 'Dateianhänge',
305 306
  'Attempt to call an undefined sub named \'%s\'' => 'Es wurde versucht, eine nicht definierte Unterfunktion namens \'%s\' aufzurufen.',
306 307
  'Audit Control'               => 'Bücherkontrolle',
307 308
  'Aug'                         => 'Aug',
......
1074 1075
  'Editable'                    => 'Bearbeitbar',
1075 1076
  'Either there are no open invoices, or you have already initiated bank transfers with the open amounts for those that are still open.' => 'Entweder gibt es keine offenen Rechnungen, oder es wurden bereits Überweisungen über die offenen Beträge aller offenen Rechnungen erstellt.',
1076 1077
  'Element disabled'            => 'Element deaktiviert',
1078
  'Email journal'               => 'E-Mail-Journal',
1077 1079
  'Employee'                    => 'Bearbeiter',
1078 1080
  'Employee #1 saved!'          => 'Benutzer #1 gespeichert!',
1079 1081
  'Employee (database ID)'      => 'Bearbeiter (Datenbank-ID)',
......
1184 1186
  'Export date to'              => 'Exportdatum bis',
1185 1187
  'Extend automatically by n months' => 'Automatische Verlängerung um x Monate',
1186 1188
  'Extended'                    => 'Gesamt',
1189
  'Extended status'             => 'Erweiterter Status',
1187 1190
  'Extension Of Time'           => 'Dauerfristverlängerung',
1188 1191
  'Factor'                      => 'Faktor',
1189 1192
  'Factor missing!'             => 'Der Faktor fehlt.',
......
1292 1295
  'Hardcopy'                    => 'Seite drucken',
1293 1296
  'Has item type'               => 'Hat Regeltypen',
1294 1297
  'Has serial number'           => 'Hat eine Serienummer',
1298
  'Headers'                     => 'Kopfzeilen',
1295 1299
  'Heading'                     => 'Überschrift',
1296 1300
  'Help Template Variables'     => 'Hilfe zu Dokumenten-Variablen',
1297 1301
  'Help on column names'        => 'Hilfe zu Spaltennamen',
......
2125 2129
  'Receipt, payment, reconciliation' => 'Zahlungseingang, Zahlungsausgang, Kontenabgleich',
2126 2130
  'Receipts'                    => 'Zahlungseingänge',
2127 2131
  'Receivables'                 => 'Forderungen',
2132
  'Recipients'                  => 'EmpfängerInnen',
2128 2133
  'Reconcile'                   => 'Abgleichen',
2129 2134
  'Reconciliation'              => 'Kontenabgleich',
2130 2135
  'Reconciliation with bank'    => 'Kontenabgleich mit Bank',
......
2344 2349
  'Sellprice for price group \'#1\'' => 'Verkaufspreis für Preisgruppe \'#1\'',
2345 2350
  'Sellprice significant places' => 'Verkaufspreis: Nachkommastellen',
2346 2351
  'Semicolon'                   => 'Semikolon',
2352
  'Send PDF to support contract\'s contact person' => 'PDFs an Ansprechpersonen der Wartungsverträge schicken',
2353
  'Sender'                      => 'AbsenderIn',
2354
  'Sent on'                     => 'Verschickt am',
2347 2355
  'Sep'                         => 'Sep',
2348 2356
  'Separator'                   => 'Trennzeichen',
2349 2357
  'Separator chararacter'       => 'Feldtrennzeichen',
......
2428 2436
  'Since bin is not enforced in the parts data, please specify a bin where goods without a specified bin will be put.' => 'Da Lagerplätze kein Pflichtfeld sind, geben Sie bitte einen Lagerplatz an, in dem Waren ohne spezifizierten Lagerplatz eingelagert werden sollen.',
2429 2437
  'Single quotes'               => 'Einfache Anführungszeichen',
2430 2438
  'Single values in item mode, cumulated values in invoice mode' => 'Einzelwerte im Artikelmodus, kumulierte Werte im Rechnungsmodus',
2439
  'Size'                        => 'Größe',
2431 2440
  'Sketch'                      => 'Skizze',
2432 2441
  'Skip'                        => 'Überspringen',
2433 2442
  'Skip entry'                  => 'Eintrag überspringen',
......
2874 2883
  'There are invalid transactions in your database.' => 'Sie haben ungültige Buchungen in Ihrer Datenbank.',
2875 2884
  'There are invoices which could not be paid by bank transaction #1 (Account number: #2, bank code: #3)!' => 'Einige Rechnungen konnten nicht durch die Bankbewegung #1 (Kontonummer: #2, Bankleitzahl: #3) bezahlt werden!',
2876 2885
  'There are no entries in the background job history.' => 'Es gibt keine Einträge im Hintergrund-Job-Verlauf.',
2886
  'There are no entries that match the filter.' => 'Es gibt keine Einträge, auf die der Filter zutrifft.',
2877 2887
  'There are no items in stock.' => 'Dieser Artikel ist nicht eingelagert.',
2878 2888
  'There are no items on your TODO list at the moment.' => 'Ihre Aufgabenliste enthält momentan keine Einträge.',
2879 2889
  'There are several options you can handle this problem, please select one:' => 'Bitte wählen Sie eine der folgenden Optionen, um mit dem Problem umzugehen:',
......
3131 3141
  'View background job execution result' => 'Verlauf der Hintergrund-Job-Ausführungen anzeigen',
3132 3142
  'View background job history' => 'Hintergrund-Job-Verlauf anzeigen',
3133 3143
  'View background jobs'        => 'Hintergrund-Jobs anzeigen',
3144
  'View sent email'             => 'Verschickte E-Mail anzeigen',
3134 3145
  'View warehouse content'      => 'Lagerbestand ansehen',
3135 3146
  'View/edit all employees sales documents' => 'Bearbeiten/ansehen der Verkaufsdokumente aller Mitarbeiter',
3136 3147
  'Von Konto: '                 => 'von Konto: ',
......
3196 3207
  'You cannot create an invoice for delivery orders from different vendors.' => 'Sie können keine Rechnung aus Lieferscheinen von verschiedenen Lieferanten erstellen.',
3197 3208
  'You cannot modify individual assigments from additional articles to line items.' => 'Eine individuelle Zuordnung der zusätzlichen Artikel zu Positionen kann nicht vorgenommen werden.',
3198 3209
  'You cannot paste function blocks or sub function blocks if there is no section.' => 'Sie können keine Funktionsblöcke oder Unterfunktionsblöcke einfügen, wenn es noch keinen Abschnitt gibt.',
3210
  'You do not have permission to access this entry.' => 'Sie verfügen nicht über die Berechtigung, auf diesen Eintrag zuzugreifen.',
3199 3211
  'You do not have the permissions to access this function.' => 'Sie verfügen nicht über die notwendigen Rechte, um auf diese Funktion zuzugreifen.',
3200 3212
  'You have entered or selected the following shipping address for this customer:' => 'Sie haben die folgende Lieferadresse eingegeben oder ausgewählt:',
3201 3213
  'You have never worked with currencies.' => 'Sie haben noch nie  mit Währungen gearbeitet.',
menus/user/00-erp.yaml
966 966
  module: fu.pl
967 967
  params:
968 968
    action: search
969
- parent: productivity_reports
970
  id: productivity_reports_email_journal
971
  name: Email journal
972
  order: 200
973
  module: controller.pl
974
  params:
975
    action: EmailJournal/list
969 976
- id: system
970 977
  name: System
971 978
  icon: system
templates/webpages/email_journal/_filter.html
1
[%- USE L %][%- USE LxERP %][%- USE HTML %]
2
<form action="controller.pl" method="post">
3
 <div class="filter_toggle">
4
  <a href="#" onClick="javascript:$('.filter_toggle').toggle()">[% LxERP.t8('Show Filter') %]</a>
5
  [% IF SELF.filter_summary %]([% LxERP.t8("Current filter") %]: [% SELF.filter_summary %])[% END %]
6
 </div>
7

  
8
 <div class="filter_toggle" style="display:none">
9
  <a href="#" onClick="javascript:$('.filter_toggle').toggle()">[% LxERP.t8('Hide Filter') %]</a>
10
  <table id="filter_table">
11
   <tr>
12
    <th align="right">[% LxERP.t8("From") %]</th>
13
    <td>[% L.input_tag("filter.from:substr::ilike", filter.from_substr__ilike, size = 20) %]</td>
14
   </tr>
15
   <tr>
16
    <th align="right">[% LxERP.t8("Recipients") %]</th>
17
    <td>[% L.input_tag("filter.recipients:substr::ilike", filter.recipients_substr__ilike, size = 20) %]</td>
18
   </tr>
19
   <tr>
20
    <th align="right">[% LxERP.t8("Sent on") %]</th>
21
    <td>
22
     [% L.date_tag("filter.sent_on:date::ge", filter.sent_on_date__ge) %]
23
     [% LxERP.t8("To Date") %]
24
     [% L.date_tag("filter.sent_on:date::le", filter.sent_on_date__le) %]
25
    </td>
26
   </tr>
27
   <tr>
28
    <th align="right">[% LxERP.t8("Status") %]</th>
29
    <td>[% L.select_tag("filter.status:eq_ignore_empty", [ [ "", "" ], [ "failed", LxERP.t8("failed") ], [ "ok", LxERP.t8("succeeded") ] ], default=filter.status_eq_ignore_empty) %]</td>
30
   </tr>
31
  </table>
32

  
33
  [% L.hidden_tag("action", "EmailJournal/dispatch") %]
34
  [% L.hidden_tag("sort_by", FORM.sort_by) %]
35
  [% L.hidden_tag("sort_dir", FORM.sort_dir) %]
36
  [% L.hidden_tag("page", FORM.page) %]
37
  [% L.submit_tag("action_list", LxERP.t8("Continue"))%]
38

  
39
  <a href="#" onClick="javascript:$('#filter_table input,#filter_table select').val("");">[% LxERP.t8("Reset") %]</a>
40

  
41
 </div>
42

  
43
</form>
templates/webpages/email_journal/list.html
1
[% USE HTML %][% USE L %][% USE LxERP %]
2

  
3
<h1>[% FORM.title %]</h1>
4

  
5
[%- INCLUDE 'common/flash.html' %]
6

  
7
[%- PROCESS 'email_journal/_filter.html' filter=SELF.models.filtered.laundered %]
8

  
9
[% IF !ENTRIES.size %]
10
 <p>
11
  [%- LxERP.t8('There are no entries that match the filter.') %]
12
 </p>
13

  
14
[%- ELSE %]
15
 <table id="email_journal_list" width="100%">
16
  <thead>
17
   <tr class="listheading">
18
    [% IF SELF.can_view_all %]
19
     <th>[% L.sortable_table_header("sender") %]</th>
20
    [% END %]
21
    <th>[% L.sortable_table_header("from") %]</th>
22
    <th>[% L.sortable_table_header("recipients") %]</th>
23
    <th>[% L.sortable_table_header("subject") %]</th>
24
    <th>[% L.sortable_table_header("sent_on") %]</th>
25
    <th>[% L.sortable_table_header("status") %]</th>
26
    <th>[% L.sortable_table_header("extended_status") %]</th>
27
   </tr>
28
  </thead>
29

  
30
  <tbody>
31
  [%- FOREACH entry = ENTRIES %]
32
  <tr class="listrow[% IF entry.status != 'ok' %]_error[% END %]" id="email_journal_id_[% entry.id %]">
33
   [% IF SELF.can_view_all %]
34
    <td>
35
     [% IF entry.sender %]
36
      [% HTML.escape(entry.sender.name) %]
37
     [% ELSE %]
38
      [% LxERP.t8("kivitendo") %]
39
     [% END %]
40
    </td>
41
   [% END %]
42
   <td>
43
    <a href="[% SELF.url_for(action => 'show', id => entry.id, back_to => SELF.get_callback) %]">
44
     [%- HTML.escape(entry.from) %]
45
    </a>
46
   </td>
47
   <td>[%- HTML.escape(entry.recipients) %]</td>
48
   <td>
49
    <a href="[% SELF.url_for(action => 'show', id => entry.id, back_to => SELF.get_callback) %]">
50
     [%- HTML.escape(entry.subject) %]
51
    </a>
52
   </td>
53
   <td>[%- HTML.escape(entry.sent_on.to_lxoffice('precision' => 'second')) %]</td>
54
   <td>
55
    [%- IF entry.status == 'ok' %]
56
     [%- LxERP.t8('succeeded') %]
57
    [% ELSE %]
58
     [%- LxERP.t8('failed') %]
59
    [%- END %]
60
   </td>
61
   <td>[%- HTML.escape(entry.extended_status) %]</td>
62
  </tr>
63
  [%- END %]
64
  </tbody>
65
 </table>
66
[%- END %]
67

  
68
[% L.paginate_controls %]
templates/webpages/email_journal/show.html
1
[% USE HTML %][% USE L %][% USE LxERP %]
2

  
3
 <h1>[% FORM.title %]</h1>
4

  
5
[%- INCLUDE 'common/flash.html' %]
6

  
7
 <table id="email_journal_details" class="email_journal_details">
8
  <tbody>
9
   <tr class="listrow">
10
    <th>[%- LxERP.t8("From") %]</th>
11
    <td>[%- HTML.escape(SELF.entry.from) %]</td>
12
   </tr>
13

  
14
   <tr class="listrow">
15
    <th>[%- LxERP.t8("Recipients") %]</th>
16
    <td>[%- HTML.escape(SELF.entry.recipients) %]</td>
17
   </tr>
18

  
19
   <tr class="listrow">
20
    <th>[%- LxERP.t8("Subject") %]</th>
21
    <td>[%- HTML.escape(SELF.entry.subject) %]</td>
22
   </tr>
23

  
24
   <tr class="listrow">
25
    <th>[%- LxERP.t8("Sent on") %]</th>
26
    <td>[%- HTML.escape(SELF.entry.sent_on.to_lxoffice("precision" => "second")) %]</td>
27
   </tr>
28

  
29
   <tr class="listrow">
30
    <th>[%- LxERP.t8("Status") %]</th>
31
    <td>
32
     [%- IF SELF.entry.status == "ok" %]
33
      [%- LxERP.t8("succeeded") %]
34
     [%- ELSE %]
35
      [%- LxERP.t8("failed") %]
36
     [%- END %]
37
    </td>
38
   </tr>
39

  
40
   <tr class="listrow">
41
    <th>[%- LxERP.t8("Extended status") %]</th>
42
    <td><pre>[%- HTML.escape(SELF.entry.extended_status) %]</pre></td>
43
   </tr>
44

  
45
   <tr class="listrow">
46
    <th>[%- LxERP.t8("Headers") %]</th>
47
    <td><pre>[% HTML.escape(SELF.entry.headers) %]</pre></td>
48
   </tr>
49

  
50
   <tr class="listrow">
51
    <th>[%- LxERP.t8("Body") %]</th>
52
    <td><pre>[% HTML.escape(SELF.entry.body) %]</pre></td>
53
   </tr>
54
 </table>
55

  
56
 [% SET attachments = SELF.entry.attachments_sorted %]
57
 [% IF attachments.size %]
58
  <h2>[% LxERP.t8("Attachments") %]</h2>
59

  
60
  <table id="email_journal_details" class="email_journal_details">
61
   <thead>
62
    <tr>
63
     <th>[% LxERP.t8("Attachment name") %]</th>
64
     <th>[% LxERP.t8("MIME type") %]</th>
65
     <th>[% LxERP.t8("Size") %]</th>
66
    </tr>
67
   </thead>
68

  
69
   <tbody>
70
    [% FOREACH attachment = attachments %]
71
     <tr class="listrow">
72
      <td>[% L.link(SELF.url_for(action="download_attachment", id=attachment.id), attachment.name) %]</td>
73
      <td>[% HTML.escape(attachment.mime_type) %]</td>
74
      <td>[% HTML.escape(LxERP.format_amount(attachment.content.length, 0)) %]</td>
75
     </tr>
76
    [% END %]
77
   </tbody>
78
  </table>
79
 [% END %]
80

  
81
 <p>
82
  <a href="[% back_to %]">[%- LxERP.t8("Back") %]</a>
83
 </p>

Auch abrufbar als: Unified diff