Revision d83928f0
Von Bernd Bleßmann vor fast 7 Jahren hinzugefügt
SL/Controller/Order.pm | ||
---|---|---|
24 | 24 |
use SL::Controller::Helper::GetModels; |
25 | 25 |
|
26 | 26 |
use List::Util qw(first); |
27 |
use List::UtilsBy qw(sort_by uniq_by); |
|
27 | 28 |
use List::MoreUtils qw(none pairwise first_index); |
28 | 29 |
use English qw(-no_match_vars); |
29 | 30 |
use File::Spec; |
31 |
use Cwd; |
|
30 | 32 |
|
31 | 33 |
use Rose::Object::MakeMethods::Generic |
32 | 34 |
( |
... | ... | |
254 | 256 |
->render($self); |
255 | 257 |
} |
256 | 258 |
|
257 |
$self->{email}->{to} = $self->order->contact->cp_email if $self->order->contact; |
|
258 |
$self->{email}->{to} ||= $self->order->$cv_method->email; |
|
259 |
$self->{email}->{cc} = $self->order->$cv_method->cc; |
|
260 |
$self->{email}->{bcc} = join ', ', grep $_, $self->order->$cv_method->bcc, SL::DB::Default->get->global_bcc; |
|
259 |
my $email_form; |
|
260 |
$email_form->{to} = $self->order->contact->cp_email if $self->order->contact; |
|
261 |
$email_form->{to} ||= $self->order->$cv_method->email; |
|
262 |
$email_form->{cc} = $self->order->$cv_method->cc; |
|
263 |
$email_form->{bcc} = join ', ', grep $_, $self->order->$cv_method->bcc, SL::DB::Default->get->global_bcc; |
|
261 | 264 |
# Todo: get addresses from shipto, if any |
262 | 265 |
|
263 | 266 |
my $form = Form->new; |
... | ... | |
267 | 270 |
$form->{language} = 'de'; |
268 | 271 |
$form->{format} = 'pdf'; |
269 | 272 |
|
270 |
$self->{email}->{subject} = $form->generate_email_subject(); |
|
271 |
$self->{email}->{attachment_filename} = $form->generate_attachment_filename(); |
|
272 |
$self->{email}->{message} = $form->create_email_signature(); |
|
273 |
$email_form->{subject} = $form->generate_email_subject(); |
|
274 |
$email_form->{attachment_filename} = $form->generate_attachment_filename(); |
|
275 |
$email_form->{message} = $form->generate_email_body(); |
|
276 |
$email_form->{js_send_function} = 'kivi.Order.send_email()'; |
|
277 |
|
|
278 |
my %files = $self->_get_files_for_email_dialog(); |
|
279 |
my $dialog_html = $self->render('common/_send_email_dialog', { output => 0 }, |
|
280 |
email_form => $email_form, |
|
281 |
show_bcc => $::auth->assert('email_bcc', 'may fail'), |
|
282 |
FILES => \%files, |
|
283 |
is_customer => $self->cv eq 'customer', |
|
284 |
); |
|
273 | 285 |
|
274 |
my $dialog_html = $self->render('order/tabs/_email_dialog', { output => 0 }); |
|
275 | 286 |
$self->js |
276 | 287 |
->run('kivi.Order.show_email_dialog', $dialog_html) |
277 | 288 |
->reinit_widgets |
... | ... | |
284 | 295 |
sub action_send_email { |
285 | 296 |
my ($self) = @_; |
286 | 297 |
|
287 |
my $mail = Mailer->new; |
|
288 |
$mail->{from} = qq|"$::myconfig{name}" <$::myconfig{email}>|; |
|
289 |
$mail->{$_} = $::form->{email}->{$_} for qw(to cc bcc subject message); |
|
298 |
my $email_form = delete $::form->{email_form}; |
|
299 |
my %field_names = (to => 'email'); |
|
290 | 300 |
|
291 |
my $pdf; |
|
292 |
my @errors = _create_pdf($self->order, \$pdf, {media => 'email'}); |
|
293 |
if (scalar @errors) { |
|
294 |
return $self->js->flash('error', t8('Conversion to PDF failed: #1', $errors[0]))->render($self); |
|
295 |
} |
|
301 |
$::form->{ $field_names{$_} // $_ } = $email_form->{$_} for keys %{ $email_form }; |
|
296 | 302 |
|
297 |
$mail->{attachments} = [{ "content" => $pdf, |
|
298 |
"name" => $::form->{email}->{attachment_filename} }]; |
|
303 |
# for Form::cleanup which may be called in Form::send_email |
|
304 |
$::form->{cwd} = getcwd(); |
|
305 |
$::form->{tmpdir} = $::lx_office_conf{paths}->{userspath}; |
|
299 | 306 |
|
300 |
if (my $err = $mail->send) { |
|
301 |
return $self->js->flash('error', t8('Sending E-mail: ') . $err) |
|
302 |
->render($self); |
|
307 |
$::form->{media} = 'email'; |
|
308 |
|
|
309 |
if (($::form->{attachment_policy} // '') eq 'normal') { |
|
310 |
my $language; |
|
311 |
$language = SL::DB::Language->new(id => $::form->{print_options}->{language_id})->load if $::form->{print_options}->{language_id}; |
|
312 |
|
|
313 |
my $pdf; |
|
314 |
my @errors = _create_pdf($self->order, \$pdf, {media => $::form->{media}, |
|
315 |
format => $::form->{print_options}->{format}, |
|
316 |
formname => $::form->{print_options}->{formname}, |
|
317 |
language => $language, |
|
318 |
groupitems => $::form->{print_options}->{groupitems}}); |
|
319 |
if (scalar @errors) { |
|
320 |
return $self->js->flash('error', t8('Conversion to PDF failed: #1', $errors[0]))->render($self); |
|
321 |
} |
|
322 |
|
|
323 |
my $sfile = SL::SessionFile::Random->new(mode => "w"); |
|
324 |
$sfile->fh->print($pdf); |
|
325 |
$sfile->fh->close; |
|
326 |
|
|
327 |
$::form->{tmpfile} = $sfile->file_name; |
|
328 |
$::form->{tmpdir} = $sfile->get_path; # for Form::cleanup which may be called in Form::send_email |
|
303 | 329 |
} |
304 | 330 |
|
331 |
$::form->send_email(\%::myconfig, 'pdf'); |
|
332 |
|
|
305 | 333 |
# internal notes |
306 | 334 |
my $intnotes = $self->order->intnotes; |
307 | 335 |
$intnotes .= "\n\n" if $self->order->intnotes; |
308 | 336 |
$intnotes .= t8('[email]') . "\n"; |
309 | 337 |
$intnotes .= t8('Date') . ": " . $::locale->format_date_object(DateTime->now_local, precision => 'seconds') . "\n"; |
310 |
$intnotes .= t8('To (email)') . ": " . $mail->{to} . "\n";
|
|
311 |
$intnotes .= t8('Cc') . ": " . $mail->{cc} . "\n" if $mail->{cc};
|
|
312 |
$intnotes .= t8('Bcc') . ": " . $mail->{bcc} . "\n" if $mail->{bcc};
|
|
313 |
$intnotes .= t8('Subject') . ": " . $mail->{subject} . "\n\n";
|
|
314 |
$intnotes .= t8('Message') . ": " . $mail->{message};
|
|
338 |
$intnotes .= t8('To (email)') . ": " . $::form->{email} . "\n";
|
|
339 |
$intnotes .= t8('Cc') . ": " . $::form->{cc} . "\n" if $::form->{cc};
|
|
340 |
$intnotes .= t8('Bcc') . ": " . $::form->{bcc} . "\n" if $::form->{bcc};
|
|
341 |
$intnotes .= t8('Subject') . ": " . $::form->{subject} . "\n\n";
|
|
342 |
$intnotes .= t8('Message') . ": " . $::form->{message};
|
|
315 | 343 |
|
316 | 344 |
$self->js |
317 | 345 |
->val('#order_intnotes', $intnotes) |
318 | 346 |
->run('kivi.Order.close_email_dialog') |
347 |
->flash('info', t8('The email has been sent.')) |
|
319 | 348 |
->render($self); |
320 | 349 |
} |
321 | 350 |
|
... | ... | |
1237 | 1266 |
return @errors; |
1238 | 1267 |
} |
1239 | 1268 |
|
1269 |
sub _get_files_for_email_dialog { |
|
1270 |
my ($self) = @_; |
|
1271 |
|
|
1272 |
my %files = map { ($_ => []) } qw(versions files vc_files part_files); |
|
1273 |
|
|
1274 |
return %files if !$::instance_conf->get_doc_storage; |
|
1275 |
|
|
1276 |
if ($self->order->id) { |
|
1277 |
$files{versions} = [ SL::File->get_all_versions(object_id => $self->order->id, object_type => $self->order->type, file_type => 'document') ]; |
|
1278 |
$files{files} = [ SL::File->get_all( object_id => $self->order->id, object_type => $self->order->type, file_type => 'attachment') ]; |
|
1279 |
$files{vc_files} = [ SL::File->get_all( object_id => $self->order->{$self->cv}->id, object_type => $self->cv, file_type => 'attachment') ]; |
|
1280 |
} |
|
1281 |
|
|
1282 |
my @parts = |
|
1283 |
uniq_by { $_->{id} } |
|
1284 |
map { |
|
1285 |
+{ id => $_->part->id, |
|
1286 |
partnumber => $_->part->partnumber } |
|
1287 |
} @{$self->order->items_sorted}; |
|
1288 |
|
|
1289 |
foreach my $part (@parts) { |
|
1290 |
my @pfiles = SL::File->get_all(object_id => $part->{id}, object_type => 'part'); |
|
1291 |
push @{ $files{part_files} }, map { +{ %{ $_ }, partnumber => $part->{partnumber} } } @pfiles; |
|
1292 |
} |
|
1293 |
|
|
1294 |
foreach my $key (keys %files) { |
|
1295 |
$files{$key} = [ sort_by { lc $_->{db_file}->{file_name} } @{ $files{$key} } ]; |
|
1296 |
} |
|
1297 |
|
|
1298 |
return %files; |
|
1299 |
} |
|
1300 |
|
|
1240 | 1301 |
sub _sales_order_type { |
1241 | 1302 |
'sales_order'; |
1242 | 1303 |
} |
... | ... | |
1354 | 1415 |
|
1355 | 1416 |
Dialog for selecting price and discount sources |
1356 | 1417 |
|
1357 |
=item * C<template/webpages/order/tabs/_email_dialog.html> |
|
1358 |
|
|
1359 |
Email dialog |
|
1360 |
|
|
1361 | 1418 |
=back |
1362 | 1419 |
|
1363 | 1420 |
=item * C<js/kivi.Order.js> |
... | ... | |
1440 | 1497 |
C<show_multi_items_dialog> does not use the currently inserted string for |
1441 | 1498 |
filtering. |
1442 | 1499 |
|
1500 |
=item * |
|
1501 |
|
|
1502 |
The language selected in print or email dialog is not saved when the order is saved. |
|
1503 |
|
|
1443 | 1504 |
=back |
1444 | 1505 |
|
1445 | 1506 |
=head1 To discuss / Nice to have |
js/kivi.Order.js | ||
---|---|---|
114 | 114 |
|
115 | 115 |
var email_dialog; |
116 | 116 |
|
117 |
ns.setup_send_email_dialog = function() { |
|
118 |
kivi.SalesPurchase.show_all_print_options_elements(); |
|
119 |
kivi.SalesPurchase.show_print_options_elements([ 'sendmode', 'media', 'copies', 'remove_draft' ], false); |
|
120 |
|
|
121 |
$('#print_options_form table').first().remove().appendTo('#email_form_print_options'); |
|
122 |
|
|
123 |
var to_focus = $('#email_form_to').val() === '' ? 'to' : 'subject'; |
|
124 |
$('#email_form_' + to_focus).focus(); |
|
125 |
}; |
|
126 |
|
|
127 |
ns.finish_send_email_dialog = function() { |
|
128 |
kivi.SalesPurchase.show_all_print_options_elements(); |
|
129 |
|
|
130 |
$('#email_form_print_options table').first().remove().prependTo('#print_options_form'); |
|
131 |
return true; |
|
132 |
}; |
|
133 |
|
|
117 | 134 |
ns.show_email_dialog = function(html) { |
118 |
var id = 'jqueryui_popup_dialog';
|
|
135 |
var id = 'send_email_dialog';
|
|
119 | 136 |
var dialog_params = { |
120 | 137 |
id: id, |
121 | 138 |
width: 800, |
122 |
height: 500, |
|
139 |
height: 600, |
|
140 |
title: kivi.t8('Send email'), |
|
123 | 141 |
modal: true, |
142 |
beforeClose: kivi.Order.finish_send_email_dialog, |
|
124 | 143 |
close: function(event, ui) { |
125 | 144 |
email_dialog.remove(); |
126 |
},
|
|
145 |
} |
|
127 | 146 |
}; |
128 | 147 |
|
129 | 148 |
$('#' + id).remove(); |
... | ... | |
132 | 151 |
email_dialog.html(html); |
133 | 152 |
email_dialog.dialog(dialog_params); |
134 | 153 |
|
154 |
kivi.Order.setup_send_email_dialog(); |
|
155 |
|
|
135 | 156 |
$('.cancel').click(ns.close_email_dialog); |
136 | 157 |
|
137 | 158 |
return true; |
... | ... | |
139 | 160 |
|
140 | 161 |
ns.send_email = function() { |
141 | 162 |
var data = $('#order_form').serializeArray(); |
142 |
data = data.concat($('#email_form').serializeArray()); |
|
163 |
data = data.concat($('[name^="email_form."]').serializeArray()); |
|
164 |
data = data.concat($('[name^="print_options."]').serializeArray()); |
|
143 | 165 |
data.push({ name: 'action', value: 'Order/send_email' }); |
144 | 166 |
$.post("controller.pl", data, kivi.eval_json_result); |
145 | 167 |
}; |
locale/de/all | ||
---|---|---|
2758 | 2758 |
'Send printout of record' => 'Belegausdruck mitschicken', |
2759 | 2759 |
'Send the last printout created for this record' => 'Den zuletzt erstellen Belegausdruck mitschicken', |
2760 | 2760 |
'Sender' => 'AbsenderIn', |
2761 |
'Sending E-mail: ' => 'E-Mail versenden: ', |
|
2762 | 2761 |
'Sent emails can be optionally stored in the database with or without their attachments.' => 'Gesendete E-Mails können optional mit oder ohne ihre Anhänge in der Datenbank gespeichert werden.', |
2763 | 2762 |
'Sent on' => 'Verschickt am', |
2764 | 2763 |
'Sent payments can only be posted for purchase invoices and sales credit notes.' => 'Gesendete Zahlungen können nur mit Einkaufsrechnungen und Verkaufsgutschriften verbucht werden.', |
locale/en/all | ||
---|---|---|
2715 | 2715 |
'Send printout of record' => '', |
2716 | 2716 |
'Send the last printout created for this record' => '', |
2717 | 2717 |
'Sender' => '', |
2718 |
'Sending E-mail: ' => '', |
|
2719 | 2718 |
'Sent emails can be optionally stored in the database with or without their attachments.' => '', |
2720 | 2719 |
'Sent on' => '', |
2721 | 2720 |
'Sent payments can only be posted for purchase invoices and sales credit notes.' => '', |
templates/webpages/order/tabs/_email_dialog.html | ||
---|---|---|
1 |
[%- USE T8 %][%- USE HTML %][%- USE L %][%- USE LxERP %] |
|
2 |
<h2>[%- 'E-mail' | $T8 %] [%- SELF.type | $T8 %]</h2> |
|
3 |
|
|
4 |
<form method="post" id="email_form" method="POST"> |
|
5 |
<table width="100%"> |
|
6 |
<tr> |
|
7 |
<td> |
|
8 |
<table> |
|
9 |
<tr align="left"> |
|
10 |
<th align="right" nowrap>[% 'To' | $T8 %]</th> |
|
11 |
<td>[% L.input_tag("email.to", SELF.email.to, size=30, class=(SELF.email.to ? '' : 'initial_focus')) %]</td> |
|
12 |
</tr> |
|
13 |
<tr> |
|
14 |
<th align="right" nowrap>[% 'Cc' | $T8 %]</th> |
|
15 |
<td>[% L.input_tag("email.cc", SELF.email.cc, size=30) %]</td> |
|
16 |
</tr> |
|
17 |
[%- IF AUTH.assert('email_bcc', 1) %] |
|
18 |
<tr> |
|
19 |
<th align="right" nowrap>[% 'Bcc' | $T8 %]</th> |
|
20 |
<td>[% L.input_tag("email.bcc", SELF.email.bcc, size=30) %]</td> |
|
21 |
</tr> |
|
22 |
[%- END %] |
|
23 |
<tr> |
|
24 |
<th align="right" nowrap>[% 'Subject' | $T8 %]</th> |
|
25 |
<td>[% L.input_tag('email.subject', SELF.email.subject, size=30, class=(SELF.email.subject ? 'initial_focus' : '')) %]</td> |
|
26 |
</tr> |
|
27 |
<tr> |
|
28 |
<th align="right" nowrap>[% 'Attachment name' | $T8 %]</th> |
|
29 |
<td>[% L.input_tag("email.attachment_filename", SELF.email.attachment_filename, size=30) %]</td> |
|
30 |
</tr> |
|
31 |
</table> |
|
32 |
</td> |
|
33 |
</tr> |
|
34 |
|
|
35 |
<tr> |
|
36 |
<table> |
|
37 |
<tr> |
|
38 |
<th align="left" nowrap>[% 'Message' | $T8 %]</th> |
|
39 |
</tr> |
|
40 |
<tr> |
|
41 |
<td> |
|
42 |
[% L.textarea_tag("email.message", SELF.email.message, wrap="soft", style="width: 350px; height: 150px") %] |
|
43 |
</td> |
|
44 |
</tr> |
|
45 |
</tr> |
|
46 |
|
|
47 |
</table> |
|
48 |
|
|
49 |
<br> |
|
50 |
[% L.hidden_tag('action', 'Order/dispatch') %] |
|
51 |
[% L.button_tag('kivi.Order.send_email()', LxERP.t8('Continue')) %] |
|
52 |
<a href="#" onclick="kivi.Order.close_email_dialog();">[%- LxERP.t8("Cancel") %]</a> |
|
53 |
|
|
54 |
</form> |
Auch abrufbar als: Unified diff
Auftrags-Controller: E-Mail-Dialog aus common verwenden.