Revision ea5d75b5
Von Sven Schöling vor fast 9 Jahren hinzugefügt
SL/Controller/Letter.pm | ||
---|---|---|
1 |
package SL::Controller::Letter; |
|
2 |
|
|
3 |
use strict; |
|
4 |
use parent qw(SL::Controller::Base); |
|
5 |
|
|
6 |
use POSIX qw(strftime); |
|
7 |
use SL::Controller::Helper::GetModels; |
|
8 |
use SL::Controller::Helper::ReportGenerator; |
|
9 |
use SL::DB::Letter; |
|
10 |
use SL::DB::LetterDraft; |
|
11 |
use SL::DB::Employee; |
|
12 |
use SL::Helper::Flash qw(flash); |
|
13 |
use SL::Helper::CreatePDF; |
|
14 |
use SL::Locale::String qw(t8); |
|
15 |
use SL::IS; |
|
16 |
use SL::ReportGenerator; |
|
17 |
|
|
18 |
use Rose::Object::MakeMethods::Generic ( |
|
19 |
'scalar --get_set_init' => [ qw(letter all_employees models) ], |
|
20 |
); |
|
21 |
|
|
22 |
__PACKAGE__->run_before('check_auth_edit'); |
|
23 |
__PACKAGE__->run_before('check_auth_report', only => [ qw(list) ]); |
|
24 |
|
|
25 |
use constant TEXT_CREATED_FOR_VALUES => (qw(presskit fax letter)); |
|
26 |
use constant PAGE_CREATED_FOR_VALUES => (qw(sketch 1 2)); |
|
27 |
|
|
28 |
my %sort_columns = ( |
|
29 |
date => t8('Date'), |
|
30 |
subject => t8('Subject'), |
|
31 |
letternumber => t8('Letternumber'), |
|
32 |
vc_id => t8('Customer'), |
|
33 |
contact => t8('Contact'), |
|
34 |
); |
|
35 |
|
|
36 |
sub action_add { |
|
37 |
my ($self, %params) = @_; |
|
38 |
|
|
39 |
return if $self->load_letter_draft(%params); |
|
40 |
|
|
41 |
$self->letter->employee_id(SL::DB::Manager::Employee->current->id); |
|
42 |
$self->letter->salesman_id(SL::DB::Manager::Employee->current->id); |
|
43 |
|
|
44 |
$self->_display( |
|
45 |
title => t8('Add Letter'), |
|
46 |
language_id => $params{language_id}, |
|
47 |
); |
|
48 |
} |
|
49 |
|
|
50 |
sub action_edit { |
|
51 |
my ($self, %params) = @_; |
|
52 |
|
|
53 |
return $self->action_add |
|
54 |
unless $::form->{letter} || $::form->{draft}; |
|
55 |
|
|
56 |
$self->letter(SL::DB::Letter->new_from_draft($::form->{draft}{id})) |
|
57 |
if $::form->{draft}; |
|
58 |
|
|
59 |
$self->_display( |
|
60 |
title => t8('Edit Letter'), |
|
61 |
); |
|
62 |
} |
|
63 |
|
|
64 |
sub action_save { |
|
65 |
my ($self, %params) = @_; |
|
66 |
|
|
67 |
my $letter = $self->_update; |
|
68 |
|
|
69 |
if (!$self->check_letter($letter)) { |
|
70 |
return $self->_display; |
|
71 |
} |
|
72 |
|
|
73 |
$self->check_number; |
|
74 |
|
|
75 |
if (!$letter->save) { |
|
76 |
flash('error', t8('There was an error saving the letter')); |
|
77 |
return $self->_display; |
|
78 |
} |
|
79 |
|
|
80 |
flash('info', t8('Letter saved!')); |
|
81 |
|
|
82 |
$self->_display; |
|
83 |
} |
|
84 |
|
|
85 |
sub action_update_contacts { |
|
86 |
my ($self) = @_; |
|
87 |
|
|
88 |
my $letter = $self->letter; |
|
89 |
|
|
90 |
if (!$self->letter->vc_id || !$self->letter->customer) { |
|
91 |
return $self->js |
|
92 |
->replaceWith( |
|
93 |
'#letter_cp_id', |
|
94 |
SL::Presenter->get->select_tag('letter.cp_id', [], value_key => 'cp_id', title_key => 'full_name') |
|
95 |
) |
|
96 |
->render; |
|
97 |
} |
|
98 |
|
|
99 |
my $contacts = $letter->customer->contacts; |
|
100 |
|
|
101 |
my $default; |
|
102 |
if ( $letter->contact |
|
103 |
&& $letter->contact->cp_cv_id |
|
104 |
&& $letter->contact->cp_cv_id == $letter->vc_id) { |
|
105 |
$default = $letter->contact->cp_id; |
|
106 |
} else { |
|
107 |
$default = ''; |
|
108 |
} |
|
109 |
|
|
110 |
$self->js |
|
111 |
->replaceWith( |
|
112 |
'#letter_cp_id', |
|
113 |
SL::Presenter->get->select_tag('letter.cp_id', $contacts, default => $default, value_key => 'cp_id', title_key => 'full_name') |
|
114 |
) |
|
115 |
->render; |
|
116 |
} |
|
117 |
|
|
118 |
sub action_save_letter_draft { |
|
119 |
my ($self, %params) = @_; |
|
120 |
|
|
121 |
$self->check_letter; |
|
122 |
|
|
123 |
my $letter_draft = SL::DB::LetterDraft->new_from_letter($self->_update); |
|
124 |
|
|
125 |
if (!$letter_draft->save) { |
|
126 |
flash('error', t8('There was an error saving the letter draft')); |
|
127 |
return $self->_display; |
|
128 |
} |
|
129 |
|
|
130 |
flash('info', t8('Draft for this Letter saved!')); |
|
131 |
|
|
132 |
$self->_display; |
|
133 |
} |
|
134 |
|
|
135 |
sub action_delete { |
|
136 |
my ($self, %params) = @_; |
|
137 |
|
|
138 |
if (!$self->letter->delete) { |
|
139 |
flash('error', t8('An error occured. Letter could not be deleted.')); |
|
140 |
return $self->action_update; |
|
141 |
} |
|
142 |
|
|
143 |
flash_later('info', t8('Letter deleted')); |
|
144 |
$self->redirect_to(action => 'list'); |
|
145 |
} |
|
146 |
|
|
147 |
sub action_delete_letter_drafts { |
|
148 |
my ($self, %params) = @_; |
|
149 |
|
|
150 |
my @ids = grep { /^checked_(.*)/ && $::form->{$_} } keys %$::form; |
|
151 |
|
|
152 |
SL::DB::Manager::LetterDraft->delete_all(query => [ ids => \@ids ]) if @ids; |
|
153 |
|
|
154 |
$self->redirect_to(action => 'add'); |
|
155 |
} |
|
156 |
|
|
157 |
sub action_list { |
|
158 |
my ($self, %params) = @_; |
|
159 |
|
|
160 |
$self->make_filter_summary; |
|
161 |
$self->prepare_report; |
|
162 |
|
|
163 |
my $letters = $self->models->get; |
|
164 |
$self->report_generator_list_objects(report => $self->{report}, objects => $letters); |
|
165 |
|
|
166 |
} |
|
167 |
|
|
168 |
sub action_print_letter { |
|
169 |
my ($self, $old_form) = @_; |
|
170 |
|
|
171 |
my $display_form = $::form->{display_form} || "display_form"; |
|
172 |
my $letter = $self->_update; |
|
173 |
|
|
174 |
$self->export_letter_to_form($letter); |
|
175 |
$::form->{formname} = "letter"; |
|
176 |
$::form->{format} = "pdf"; |
|
177 |
|
|
178 |
my $language_saved = $::form->{language_id}; |
|
179 |
my $greeting_saved = $::form->{greeting}; |
|
180 |
my $cp_id_saved = $::form->{cp_id}; |
|
181 |
|
|
182 |
IS->customer_details(\%::myconfig, $::form); |
|
183 |
|
|
184 |
if (!$cp_id_saved) { |
|
185 |
# No contact was selected. Delete all contact variables because |
|
186 |
# IS->customer_details() and IR->vendor_details() get the default |
|
187 |
# contact anyway. |
|
188 |
map({ delete($::form->{$_}); } grep(/^cp_/, keys(%{ $::form }))); |
|
189 |
} |
|
190 |
|
|
191 |
$::form->{greeting} = $greeting_saved; |
|
192 |
$::form->{language_id} = $language_saved; |
|
193 |
|
|
194 |
if ($::form->{cp_id}) { |
|
195 |
CT->get_contact(\%::myconfig, $::form); |
|
196 |
} |
|
197 |
|
|
198 |
$::form->{cp_contact_formal} = ($::form->{cp_greeting} ? "$::form->{cp_greeting} " : '') . ($::form->{cp_givenname} ? "$::form->{cp_givenname} " : '') . $::form->{cp_name}; |
|
199 |
|
|
200 |
$::form->get_employee_data('prefix' => 'employee', 'id' => $letter->{employee_id}); |
|
201 |
$::form->get_employee_data('prefix' => 'salesman', 'id' => $letter->{salesman_id}); |
|
202 |
|
|
203 |
my %create_params = ( |
|
204 |
template => scalar(SL::Helper::CreatePDF->find_template( |
|
205 |
name => 'letter', |
|
206 |
printer_id => $::form->{printer_id}, |
|
207 |
language_id => $::form->{language_id}, |
|
208 |
formname => 'letter', |
|
209 |
format => 'pdf', |
|
210 |
)), |
|
211 |
variables => $::form, |
|
212 |
return => 'file_name', |
|
213 |
); |
|
214 |
my $pdf_file_name; |
|
215 |
eval { |
|
216 |
$pdf_file_name = SL::Helper::CreatePDF->create_pdf(%create_params); |
|
217 |
|
|
218 |
# set some form defaults for printing webdav copy variables |
|
219 |
if ( $::form->{media} eq 'email') { |
|
220 |
my $mail = Mailer->new; |
|
221 |
my $signature = $::myconfig{signature}; |
|
222 |
$mail->{$_} = $::form->{$_} for qw(cc subject message bcc to); |
|
223 |
$mail->{from} = qq|"$::myconfig{name}" <$::myconfig{email}>|; |
|
224 |
$mail->{fileid} = time() . '.' . $$ . '.'; |
|
225 |
$mail->{attachments} = [{ "filename" => $pdf_file_name, |
|
226 |
"name" => $::form->{attachment_name} }]; |
|
227 |
$mail->{message} .= "\n-- \n$signature"; |
|
228 |
$mail->{message} =~ s/\r//g; |
|
229 |
|
|
230 |
# copy_file_to_webdav was already done via io.pl -> edit_e_mail |
|
231 |
my $err = $mail->send; |
|
232 |
return !$err; |
|
233 |
} |
|
234 |
|
|
235 |
if (!$::form->{printer_id} || $::form->{media} eq 'screen') { |
|
236 |
|
|
237 |
my $file = IO::File->new($pdf_file_name, 'r') || croak("Cannot open file '$pdf_file_name'"); |
|
238 |
my $size = -s $pdf_file_name; |
|
239 |
my $content_type = 'application/pdf'; |
|
240 |
my $attachment_name = $::form->generate_attachment_filename; |
|
241 |
$attachment_name =~ s:.*//::g; |
|
242 |
|
|
243 |
print $::form->create_http_response(content_type => $content_type, |
|
244 |
content_disposition => 'attachment; filename="' . $attachment_name . '"', |
|
245 |
content_length => $size); |
|
246 |
|
|
247 |
$::locale->with_raw_io(\*STDOUT, sub { print while <$file> }); |
|
248 |
$file->close; |
|
249 |
|
|
250 |
Common::copy_file_to_webdav_folder($::form) if $::instance_conf->get_webdav_documents; |
|
251 |
unlink $pdf_file_name; |
|
252 |
return 1; |
|
253 |
} |
|
254 |
|
|
255 |
my $printer = SL::DB::Printer->new(id => $::form->{printer_id})->load; |
|
256 |
my $command = SL::Template::create(type => 'ShellCommand', form => Form->new(''))->parse($printer->printer_command); |
|
257 |
|
|
258 |
open my $out, '|-', $command or die $!; |
|
259 |
binmode $out; |
|
260 |
print $out scalar(read_file($pdf_file_name)); |
|
261 |
close $out; |
|
262 |
Common::copy_file_to_webdav_folder($::form) if $::instance_conf->get_webdav_documents; |
|
263 |
|
|
264 |
flash_later('info', t8('The documents have been sent to the printer \'#1\'.', $printer->printer_description)); |
|
265 |
$self->redirect_to(action => 'edit', id => $letter->{id}, 'printer_id' => $::form->{printer_id}); |
|
266 |
1; |
|
267 |
} or do { |
|
268 |
unlink $pdf_file_name; |
|
269 |
$::form->error(t8("Creating the PDF failed:") . " " . $@); |
|
270 |
}; |
|
271 |
|
|
272 |
} |
|
273 |
|
|
274 |
sub action_update { |
|
275 |
my ($self, $name_selected) = @_; |
|
276 |
|
|
277 |
$self->_display( |
|
278 |
letter => $self->_update, |
|
279 |
); |
|
280 |
} |
|
281 |
|
|
282 |
sub action_skip_draft { |
|
283 |
my ($self) = @_; |
|
284 |
$self->action_add(skip_drafts => 1); |
|
285 |
} |
|
286 |
|
|
287 |
sub action_delete_drafts { |
|
288 |
my ($self) = @_; |
|
289 |
delete_letter_drafts(); |
|
290 |
$self->action_add(skip_drafts => 1); |
|
291 |
} |
|
292 |
|
|
293 |
sub _display { |
|
294 |
my ($self, %params) = @_; |
|
295 |
|
|
296 |
my $letter = $self->letter; |
|
297 |
|
|
298 |
require 'bin/mozilla/io.pl'; |
|
299 |
|
|
300 |
$params{title} ||= t8('Edit Letter'); |
|
301 |
|
|
302 |
$::form->{type} = 'letter'; # needed for print_options |
|
303 |
$::form->{vc} = 'customer'; # needs to be for _get_contacts... |
|
304 |
|
|
305 |
$::request->layout->add_javascripts('customer_or_vendor_selection.js'); |
|
306 |
$::request->layout->add_javascripts('edit_part_window.js'); |
|
307 |
|
|
308 |
$::form->{language_id} ||= $params{language_id}; |
|
309 |
|
|
310 |
$self->render('letter/edit', |
|
311 |
%params, |
|
312 |
TCF => [ map { key => $_, value => t8(ucfirst $_) }, TEXT_CREATED_FOR_VALUES() ], |
|
313 |
PCF => [ map { key => $_, value => t8(ucfirst $_) }, PAGE_CREATED_FOR_VALUES() ], |
|
314 |
letter => $letter, |
|
315 |
employees => $self->all_employees, |
|
316 |
print_options => print_options(inline => 1), |
|
317 |
); |
|
318 |
} |
|
319 |
|
|
320 |
sub _update { |
|
321 |
my ($self, %params) = @_; |
|
322 |
|
|
323 |
my $letter = $self->letter; |
|
324 |
|
|
325 |
$self->check_date; |
|
326 |
$self->set_greetings; |
|
327 |
|
|
328 |
return $letter; |
|
329 |
} |
|
330 |
|
|
331 |
sub prepare_report { |
|
332 |
my ($self) = @_; |
|
333 |
|
|
334 |
my $report = SL::ReportGenerator->new(\%::myconfig, $::form); |
|
335 |
$self->{report} = $report; |
|
336 |
|
|
337 |
my @columns = qw(date subject letternumber vc_id contact date); |
|
338 |
my @sortable = qw(date subject letternumber vc_id contact date); |
|
339 |
|
|
340 |
my %column_defs = ( |
|
341 |
date => { text => t8('Date'), sub => sub { $_[0]->date_as_date } }, |
|
342 |
subject => { text => t8('Subject'), sub => sub { $_[0]->subject }, |
|
343 |
obj_link => sub { $self->url_for(action => 'edit', 'letter.id' => $_[0]->id, callback => $self->models->get_callback) } }, |
|
344 |
letternumber => { text => t8('Letternumber'), sub => sub { $_[0]->letternumber }, |
|
345 |
obj_link => sub { $self->url_for(action => 'edit', 'letter.id' => $_[0]->id, callback => $self->models->get_callback) } }, |
|
346 |
vc_id => { text => t8('Customer'), sub => sub { $_[0]->customer->displayable_name } }, |
|
347 |
contact => { text => t8('Contact'), sub => sub { $_[0]->contact ? $_[0]->contact->full_name : '' } }, |
|
348 |
); |
|
349 |
|
|
350 |
$column_defs{$_}{text} = $sort_columns{$_} for keys %column_defs; |
|
351 |
|
|
352 |
$report->set_options( |
|
353 |
std_column_visibility => 1, |
|
354 |
controller_class => 'Letter', |
|
355 |
output_format => 'HTML', |
|
356 |
top_info_text => t8('Letters'), |
|
357 |
title => t8('Letters'), |
|
358 |
allow_pdf_export => 1, |
|
359 |
allow_csv_export => 1, |
|
360 |
); |
|
361 |
|
|
362 |
$report->set_columns(%column_defs); |
|
363 |
$report->set_column_order(@columns); |
|
364 |
$report->set_export_options(qw(list filter)); |
|
365 |
$report->set_options_from_form; |
|
366 |
|
|
367 |
$self->models->disable_plugin('paginated') if $report->{options}{output_format} =~ /^(pdf|csv)$/i; |
|
368 |
$self->models->finalize; |
|
369 |
$self->models->set_report_generator_sort_options(report => $report, sortable_columns => \@sortable); |
|
370 |
|
|
371 |
$report->set_options( |
|
372 |
raw_top_info_text => $self->render('letter/report_top', { output => 0 }), |
|
373 |
raw_bottom_info_text => $self->render('letter/report_bottom', { output => 0 }, models => $self->models), |
|
374 |
attachment_basename => t8('letters_list') . strftime('_%Y%m%d', localtime time), |
|
375 |
); |
|
376 |
} |
|
377 |
|
|
378 |
sub make_filter_summary { |
|
379 |
my ($self) = @_; |
|
380 |
|
|
381 |
my $filter = $::form->{filter} || {}; |
|
382 |
my @filter_strings; |
|
383 |
|
|
384 |
my $employee = $filter->{employee_id} ? SL::DB::Employee->new(id => $filter->{employee_id})->load->name : ''; |
|
385 |
my $salesman = $filter->{salesman_id} ? SL::DB::Employee->new(id => $filter->{salesman_id})->load->name : ''; |
|
386 |
|
|
387 |
my @filters = ( |
|
388 |
[ $filter->{"letternumber:substr::ilike"}, t8('Number') ], |
|
389 |
[ $filter->{"subject:substr::ilike"}, t8('Subject') ], |
|
390 |
[ $filter->{"body:substr::ilike"}, t8('Body') ], |
|
391 |
[ $filter->{"date:date::ge"}, t8('From Date') ], |
|
392 |
[ $filter->{"date:date::le"}, t8('To Date') ], |
|
393 |
[ $employee, t8('Employee') ], |
|
394 |
[ $salesman, t8('Salesman') ], |
|
395 |
); |
|
396 |
|
|
397 |
my %flags = ( |
|
398 |
); |
|
399 |
my @flags = map { $flags{$_} } @{ $filter->{part}{type} || [] }; |
|
400 |
|
|
401 |
for (@flags) { |
|
402 |
push @filter_strings, $_ if $_; |
|
403 |
} |
|
404 |
for (@filters) { |
|
405 |
push @filter_strings, "$_->[1]: $_->[0]" if $_->[0]; |
|
406 |
} |
|
407 |
|
|
408 |
$self->{filter_summary} = join ', ', @filter_strings; |
|
409 |
} |
|
410 |
|
|
411 |
sub e_mail { |
|
412 |
my $letter = _update(); |
|
413 |
|
|
414 |
$letter->check_number; |
|
415 |
$letter->save; |
|
416 |
|
|
417 |
$::form->{formname} = "letter"; |
|
418 |
$letter->export_to($::form); |
|
419 |
|
|
420 |
$::form->{id} = $letter->{id}; |
|
421 |
edit_e_mail(); |
|
422 |
} |
|
423 |
|
|
424 |
sub load_letter_draft { |
|
425 |
my ($self, %params) = @_; |
|
426 |
|
|
427 |
return 0 if $params{skip_drafts}; |
|
428 |
|
|
429 |
my $letter_drafts = SL::DB::Manager::LetterDraft->get_all; |
|
430 |
|
|
431 |
return unless @$letter_drafts; |
|
432 |
|
|
433 |
$self->render('letter/load_drafts', |
|
434 |
title => t8('Letter Draft'), |
|
435 |
LETTER_DRAFTS => $letter_drafts, |
|
436 |
); |
|
437 |
|
|
438 |
return 1; |
|
439 |
} |
|
440 |
|
|
441 |
sub check_date { |
|
442 |
my ($self) = @_; |
|
443 |
my $letter = $self->letter; |
|
444 |
|
|
445 |
return unless $letter; |
|
446 |
return if $letter->date; |
|
447 |
|
|
448 |
$letter->date(DateTime->today) |
|
449 |
} |
|
450 |
|
|
451 |
sub check_letter { |
|
452 |
my ($self, $letter) = @_; |
|
453 |
|
|
454 |
$letter ||= $self->letter; |
|
455 |
|
|
456 |
my $error; |
|
457 |
|
|
458 |
if (!$letter->subject) { |
|
459 |
flash('error', t8('The subject is missing.')); |
|
460 |
$error = 1; |
|
461 |
} |
|
462 |
if (!$letter->body) { |
|
463 |
flash('error', t8('The body is missing.')); |
|
464 |
$error = 1; |
|
465 |
} |
|
466 |
if (!$letter->employee_id) { |
|
467 |
flash('error', t8('The employee is missing.')); |
|
468 |
$error = 1; |
|
469 |
} |
|
470 |
|
|
471 |
return !$error; |
|
472 |
} |
|
473 |
|
|
474 |
sub check_number { |
|
475 |
my ($self, $letter) = @_; |
|
476 |
|
|
477 |
$letter ||= $self->letter; |
|
478 |
|
|
479 |
return if $letter->letternumber; |
|
480 |
|
|
481 |
$letter->letternumber(SL::TransNumber->new(type => 'letter', id => $self->{id}, number => $self->{letternumber})->create_unique); |
|
482 |
} |
|
483 |
|
|
484 |
sub set_greetings { |
|
485 |
my ($self) = @_; |
|
486 |
my $letter = $self->letter; |
|
487 |
|
|
488 |
return unless $letter; |
|
489 |
return if $letter->greeting; |
|
490 |
|
|
491 |
$letter->greeting(t8('Dear Sir or Madam,')); |
|
492 |
} |
|
493 |
|
|
494 |
sub export_letter_to_form { |
|
495 |
my ($self, $letter) = @_; |
|
496 |
# nope, not pretty. |
|
497 |
|
|
498 |
$letter ||= $self->letter; |
|
499 |
|
|
500 |
for ($letter->meta->columns) { |
|
501 |
if ((ref $_) =~ /Date/i) { |
|
502 |
$::form->{$_->name} = $letter->$_->to_kivitendo; |
|
503 |
} else { |
|
504 |
$::form->{$_->name} = $letter->$_; |
|
505 |
} |
|
506 |
} |
|
507 |
} |
|
508 |
|
|
509 |
sub init_letter { |
|
510 |
my ($self) = @_; |
|
511 |
|
|
512 |
my $letter = SL::DB::Manager::Letter->find_by_or_create(id => $::form->{letter}{id} || 0) |
|
513 |
->assign_attributes(%{ $::form->{letter} }); |
|
514 |
|
|
515 |
if ($letter->cp_id) { |
|
516 |
# $letter->vc_id($letter->contact->cp_cv_id); |
|
517 |
# contacts don't have language_id yet |
|
518 |
# $letter->greeting(GenericTranslations->get( |
|
519 |
# translation_type => 'greetings::' . ($letter->contact->cp_gender eq 'f' ? 'female' : 'male'), |
|
520 |
# language_id => $letter->contact->language_id, |
|
521 |
# allow_fallback => 1 |
|
522 |
# )); |
|
523 |
} |
|
524 |
|
|
525 |
$letter; |
|
526 |
} |
|
527 |
|
|
528 |
sub init_models { |
|
529 |
my ($self) = @_; |
|
530 |
|
|
531 |
SL::Controller::Helper::GetModels->new( |
|
532 |
controller => $self, |
|
533 |
model => 'Letter', |
|
534 |
sorted => { |
|
535 |
_default => { |
|
536 |
by => 'letternumber', |
|
537 |
dir => 1, |
|
538 |
}, |
|
539 |
%sort_columns, |
|
540 |
}, |
|
541 |
with_objects => [ 'contact', 'salesman', 'employee' ], |
|
542 |
); |
|
543 |
} |
|
544 |
|
|
545 |
sub init_all_employees { |
|
546 |
SL::DB::Manager::Employee->get_all(query => [ deleted => 0 ]); |
|
547 |
} |
|
548 |
|
|
549 |
sub check_auth_edit { |
|
550 |
$::auth->assert('sales_letter_edit'); |
|
551 |
} |
|
552 |
|
|
553 |
sub check_auth_report { |
|
554 |
$::auth->assert('sales_letter_report'); |
|
555 |
} |
|
556 |
|
|
557 |
1; |
|
558 |
|
|
559 |
__END__ |
|
560 |
|
|
561 |
=encoding utf-8 |
|
562 |
|
|
563 |
=head1 NAME |
|
564 |
|
|
565 |
SL::Controller::Letter - Letters CRUD and printing |
|
566 |
|
|
567 |
=head1 DESCRIPTION |
|
568 |
|
|
569 |
Simple letter CRUD controller with drafting capabilities. |
|
570 |
|
|
571 |
=head1 TODO |
|
572 |
|
|
573 |
Customer/Vendor switch for dealing with vendor letters |
|
574 |
|
|
575 |
copy to webdav is crap |
|
576 |
|
|
577 |
customer/vendor stuff |
|
578 |
|
|
579 |
=head1 AUTHOR |
|
580 |
|
|
581 |
Sven Schöling E<lt>s.schoeling@linet-services.deE<gt> |
|
582 |
|
|
583 |
=cut |
SL/DB/Letter.pm | ||
---|---|---|
6 | 6 |
use strict; |
7 | 7 |
|
8 | 8 |
use SL::DB::MetaSetup::Letter; |
9 |
use SL::DB::Manager::Letter; |
|
10 |
|
|
11 |
__PACKAGE__->meta->add_relationships( |
|
12 |
customer => { |
|
13 |
type => 'many to one', |
|
14 |
class => 'SL::DB::Customer', |
|
15 |
column_map => { vc_id => 'id' }, |
|
16 |
}, |
|
17 |
|
|
18 |
); |
|
9 | 19 |
|
10 | 20 |
__PACKAGE__->meta->initialize; |
11 | 21 |
|
12 |
# Creates get_all, get_all_count, get_all_iterator, delete_all and update_all. |
|
13 |
__PACKAGE__->meta->make_manager_class; |
|
22 |
sub new_from_draft { |
|
23 |
my ($class, $draft) = @_; |
|
24 |
|
|
25 |
my $self = $class->new; |
|
26 |
|
|
27 |
if (!ref $draft) { |
|
28 |
require SL::DB::LetterDraft; |
|
29 |
$draft = SL::DB::LetterDraft->new(id => $draft)->load; |
|
30 |
} |
|
31 |
|
|
32 |
$self->assign_attributes(map { $_ => $draft->$_ } $draft->meta->columns); |
|
33 |
|
|
34 |
$self->id(undef); |
|
35 |
|
|
36 |
$self; |
|
37 |
} |
|
14 | 38 |
|
15 | 39 |
1; |
SL/DB/LetterDraft.pm | ||
---|---|---|
12 | 12 |
# Creates get_all, get_all_count, get_all_iterator, delete_all and update_all. |
13 | 13 |
__PACKAGE__->meta->make_manager_class; |
14 | 14 |
|
15 |
sub new_from_letter { |
|
16 |
my ($class, $letter) = @_; |
|
17 |
|
|
18 |
my $self = $class->new; |
|
19 |
|
|
20 |
if (!ref $letter) { |
|
21 |
require SL::DB::Draft; |
|
22 |
$letter = SL::DB::Draft->new(id => $letter)->load; |
|
23 |
} |
|
24 |
|
|
25 |
$self->assign_attributes(map { $_ => $letter->$_ } $letter->meta->columns); |
|
26 |
|
|
27 |
$self->id(undef); |
|
28 |
|
|
29 |
$self; |
|
30 |
} |
|
31 |
|
|
15 | 32 |
1; |
SL/DB/Manager/Letter.pm | ||
---|---|---|
1 |
package SL::DB::Manager::Letter; |
|
2 |
|
|
3 |
use strict; |
|
4 |
|
|
5 |
use SL::DB::Helper::Manager; |
|
6 |
use base qw(SL::DB::Helper::Manager); |
|
7 |
|
|
8 |
use SL::DB::Helper::Filtered; |
|
9 |
use SL::DB::Helper::Paginated; |
|
10 |
use SL::DB::Helper::Sorted; |
|
11 |
|
|
12 |
sub object_class { 'SL::DB::Letter' } |
|
13 |
|
|
14 |
__PACKAGE__->make_manager_methods; |
|
15 |
|
|
16 |
sub _sort_spec { |
|
17 |
return ( columns => { SIMPLE => 'ALL', |
|
18 |
customer => [ 'lower(customer.name)', ], |
|
19 |
}, |
|
20 |
default => [ 'date', 1 ], |
|
21 |
nulls => { } |
|
22 |
); |
|
23 |
} |
|
24 |
|
|
25 |
sub default_objects_per_page { 15 } |
|
26 |
|
|
27 |
1; |
SL/Letter.pm | ||
---|---|---|
1 |
#===================================================================== |
|
2 |
# LX-Office ERP |
|
3 |
# Copyright (C) 2008 |
|
4 |
# Based on SQL-Ledger Version 2.1.9 |
|
5 |
# Web http://www.lx-office.org |
|
6 |
# |
|
7 |
#===================================================================== |
|
8 |
# |
|
9 |
# Letter module |
|
10 |
# |
|
11 |
#===================================================================== |
|
12 |
|
|
13 |
package SL::Letter; |
|
14 |
|
|
15 |
use strict; |
|
16 |
use List::Util qw(max); |
|
17 |
|
|
18 |
use SL::Common; |
|
19 |
use SL::CT; |
|
20 |
use SL::DBUtils; |
|
21 |
use SL::MoreCommon; |
|
22 |
use SL::TransNumber; |
|
23 |
use SL::DB::Manager::Customer; |
|
24 |
|
|
25 |
my $DEFINITION = <<SQL; |
|
26 |
Table "public.letter" |
|
27 |
Column | Type | Modifiers |
|
28 |
-------------------+-----------------------------+------------------------------------------ |
|
29 |
id | integer | not null default nextval('id'::regclass) |
|
30 |
vc_id | integer | not null |
|
31 |
letternumber | text | |
|
32 |
jobnumber | text | |
|
33 |
text_created_for | text | |
|
34 |
date | date | |
|
35 |
subject | text | |
|
36 |
greeting | text | |
|
37 |
body | text | |
|
38 |
close | text | |
|
39 |
company_name | text | |
|
40 |
employee_id | integer | |
|
41 |
employee_position | text | |
|
42 |
salesman_id | integer | |
|
43 |
salesman_position | text | |
|
44 |
itime | timestamp without time zone | default now() |
|
45 |
mtime | timestamp without time zone | |
|
46 |
page_created_for | text | |
|
47 |
intnotes | text | |
|
48 |
cp_id | integer | |
|
49 |
reference | text | |
|
50 |
Indexes: |
|
51 |
"letter_pkey" PRIMARY KEY, btree (id) |
|
52 |
Foreign-key constraints: |
|
53 |
"letter_cp_id_fkey" FOREIGN KEY (cp_id) REFERENCES contacts(cp_id) |
|
54 |
"letter_employee_id_fkey" FOREIGN KEY (employee_id) REFERENCES employee(id) |
|
55 |
"letter_salesman_id_fkey" FOREIGN KEY (salesman_id) REFERENCES employee(id) |
|
56 |
SQL |
|
57 |
|
|
58 |
# XXX not working yet |
|
59 |
#sub customer { |
|
60 |
# my $self = shift; |
|
61 |
# |
|
62 |
# die 'not a setter' if @_; |
|
63 |
# |
|
64 |
# return unless $self->{customer_id}; |
|
65 |
# |
|
66 |
# # resolve customer_obj |
|
67 |
#} |
|
68 |
|
|
69 |
sub new { |
|
70 |
my $class = ref $_[0] || $_[0]; shift; |
|
71 |
my %params = @_; |
|
72 |
my $ref = $_[0]; |
|
73 |
|
|
74 |
$ref = ref $_[0] eq 'HASH' ? $ref : \%params; # don't like it either... |
|
75 |
|
|
76 |
my $self = bless $ref, $class; |
|
77 |
|
|
78 |
$self->_lastname_used; |
|
79 |
$self->_resolve_customer; |
|
80 |
$self->set_greetings; |
|
81 |
|
|
82 |
return $self; |
|
83 |
} |
|
84 |
|
|
85 |
sub _create { |
|
86 |
my $self = shift; |
|
87 |
my $dbh = $::form->get_standard_dbh; |
|
88 |
($self->{id}) = selectfirst_array_query($::form, $dbh, "select nextval('id')"); |
|
89 |
|
|
90 |
do_query($::form, $dbh, <<SQL, $self->{id}, $self->{customer_id}); |
|
91 |
INSERT INTO letter (id, vc_id) VALUES (?, ?); |
|
92 |
SQL |
|
93 |
} |
|
94 |
|
|
95 |
sub _create_draft { |
|
96 |
my $self = shift; |
|
97 |
my $dbh = $::form->get_standard_dbh; |
|
98 |
($self->{draft_id}) = selectfirst_array_query($::form, $dbh, "select nextval('id')"); |
|
99 |
|
|
100 |
do_query($::form, $dbh, <<SQL, $self->{draft_id}, $self->{customer_id}); |
|
101 |
INSERT INTO letter_draft (id, vc_id) VALUES (?, ?); |
|
102 |
SQL |
|
103 |
} |
|
104 |
|
|
105 |
|
|
106 |
sub save { |
|
107 |
$::lxdebug->enter_sub; |
|
108 |
|
|
109 |
my $self = shift; |
|
110 |
my %params = @_; |
|
111 |
my $dbh = $::form->get_standard_dbh; |
|
112 |
my ($table, $update_value); |
|
113 |
|
|
114 |
if ($params{draft}) { |
|
115 |
$self->_create_draft unless $self->{draft_id}; |
|
116 |
$table = 'letter_draft'; |
|
117 |
$update_value = 'draft_id'; |
|
118 |
} else { |
|
119 |
$self->_create unless $self->{id}; |
|
120 |
$table = 'letter'; |
|
121 |
$update_value = 'id'; |
|
122 |
} |
|
123 |
|
|
124 |
my %fields = __PACKAGE__->_get_fields; |
|
125 |
my %field_mappings = __PACKAGE__->_get_field_mappings; |
|
126 |
|
|
127 |
delete $fields{id}; |
|
128 |
|
|
129 |
my @update_fields = keys %fields; |
|
130 |
my $set_clause = join ', ', map { "$_ = ?" } @update_fields; |
|
131 |
my @values = map { _escaper($_)->( $self->{ $field_mappings{$_} || $_ } ) } @update_fields, $update_value; |
|
132 |
|
|
133 |
my $query = "UPDATE $table SET $set_clause WHERE id = ?"; |
|
134 |
|
|
135 |
do_query($::form, $dbh, $query, @values); |
|
136 |
|
|
137 |
$dbh->commit; |
|
138 |
|
|
139 |
$::lxdebug->leave_sub; |
|
140 |
} |
|
141 |
|
|
142 |
sub find { |
|
143 |
$::lxdebug->enter_sub; |
|
144 |
|
|
145 |
my $class = ref $_[0] || $_[0]; shift; |
|
146 |
my $myconfig = \%main::myconfig; |
|
147 |
my $form = $main::form; |
|
148 |
my $dbh = $form->get_standard_dbh($myconfig); |
|
149 |
my %params = @_; |
|
150 |
my $letter_table = 'letter'; |
|
151 |
|
|
152 |
$letter_table = 'letter_draft' if $params{draft}; |
|
153 |
%params = %$form if !scalar keys %params; |
|
154 |
|
|
155 |
my (@wheres, @values); |
|
156 |
my $add_token = sub { add_token(\@wheres, \@values, @_) }; |
|
157 |
|
|
158 |
$add_token->(col => 'letter.id', val => $params{id}, esc => 'id' ) if $params{id}; |
|
159 |
$add_token->(col => 'letter.letternumber', val => $params{letternumber}, esc => 'substr') if $params{letternumber}; |
|
160 |
$add_token->(col => 'vc.name', val => $params{customer}, esc => 'substr') if $params{customer}; |
|
161 |
$add_token->(col => 'vc.id', val => $params{customer_id}, esc => 'id' ) if $params{customer_id}; |
|
162 |
$add_token->(col => 'letter.cp_id', val => $params{cp_id}, esc => 'id' ) if $params{cp_id}; |
|
163 |
$add_token->(col => 'ct.cp_name', val => $params{contact}, esc => 'substr') if $params{contact}; |
|
164 |
$add_token->(col => 'letter.subject', val => $params{subject}, esc => 'substr') if $params{subject}; |
|
165 |
$add_token->(col => 'letter.body', val => $params{body}, esc => 'substr') if $params{body}; |
|
166 |
$add_token->(col => 'letter.date', val => $params{date_from}, method => '>=' ) if $params{date_from}; |
|
167 |
$add_token->(col => 'letter.date', val => $params{date_to}, method => '<=' ) if $params{date_to}; |
|
168 |
|
|
169 |
my $query = qq| |
|
170 |
SELECT $letter_table.*, vc.name AS customer, vc.id AS customer_id, ct.cp_name AS contact FROM $letter_table |
|
171 |
LEFT JOIN customer vc ON vc.id = $letter_table.vc_id |
|
172 |
LEFT JOIN contacts ct ON $letter_table.cp_id = ct.cp_id |
|
173 |
|; |
|
174 |
|
|
175 |
if (@wheres) { |
|
176 |
$query .= ' WHERE ' . join ' AND ', @wheres; |
|
177 |
} |
|
178 |
|
|
179 |
my @results = selectall_hashref_query($form, $dbh, $query, @values); |
|
180 |
my @objects = map { $class->new($_) } @results; |
|
181 |
|
|
182 |
$::lxdebug->leave_sub; |
|
183 |
|
|
184 |
return @objects; |
|
185 |
} |
|
186 |
|
|
187 |
sub delete { |
|
188 |
$::lxdebug->enter_sub; |
|
189 |
|
|
190 |
my $self = shift; |
|
191 |
|
|
192 |
do_query($::form, $::form->get_standard_dbh, <<SQL, $self->{id}); |
|
193 |
DELETE FROM letter WHERE id = ? |
|
194 |
SQL |
|
195 |
|
|
196 |
$::form->get_standard_dbh->commit; |
|
197 |
|
|
198 |
$::lxdebug->leave_sub; |
|
199 |
} |
|
200 |
|
|
201 |
sub delete_drafts { |
|
202 |
$::lxdebug->enter_sub; |
|
203 |
|
|
204 |
my $self = shift; |
|
205 |
my @draft_ids = @_; |
|
206 |
|
|
207 |
my $form = $main::form; |
|
208 |
my $myconfig = \%main::myconfig; |
|
209 |
my $dbh = $form->get_standard_dbh($myconfig); |
|
210 |
|
|
211 |
|
|
212 |
return $main::lxdebug->leave_sub() unless (@draft_ids); |
|
213 |
|
|
214 |
my $query = qq|DELETE FROM letter_draft WHERE id IN (| . join(", ", map { "?" } @draft_ids) . qq|)|; |
|
215 |
do_query($form, $dbh, $query, @draft_ids); |
|
216 |
|
|
217 |
$dbh->commit; |
|
218 |
|
|
219 |
$::lxdebug->leave_sub; |
|
220 |
} |
|
221 |
|
|
222 |
|
|
223 |
sub check_number { |
|
224 |
my $self = shift; |
|
225 |
|
|
226 |
return if $self->{letternumber} |
|
227 |
&& $self->{id} |
|
228 |
&& 1 == scalar __PACKAGE__->find(letternumber => $self->{letternumber}); |
|
229 |
|
|
230 |
$self->{letternumber} = SL::TransNumber->new(type => 'letter', id => $self->{id}, number => $self->{letternumber})->create_unique; |
|
231 |
} |
|
232 |
|
|
233 |
sub check_name { |
|
234 |
my $self = shift; |
|
235 |
my %params = @_; |
|
236 |
|
|
237 |
unless ($params{_name_selected}) { |
|
238 |
$::form->{$_} = $self->{$_} for qw(oldcustomer customer selectcustomer customer_id); |
|
239 |
|
|
240 |
if (::check_name('customer')) { |
|
241 |
$self->_set_customer_from($::form); |
|
242 |
} |
|
243 |
} else { |
|
244 |
$self->_set_customer_from($::form); |
|
245 |
} |
|
246 |
} |
|
247 |
|
|
248 |
sub _set_customer_from { |
|
249 |
my $self = shift; |
|
250 |
my $from = shift; |
|
251 |
|
|
252 |
$self->{$_} = $from->{$_} for qw(oldcustomer customer_id customer selectcustomer); |
|
253 |
|
|
254 |
$self; |
|
255 |
} |
|
256 |
|
|
257 |
sub check_date { |
|
258 |
my $self = shift; |
|
259 |
$self->{date} ||= $::form->current_date(\%::myconfig); |
|
260 |
} |
|
261 |
|
|
262 |
sub load { |
|
263 |
my $self = shift; |
|
264 |
my $table = 'letter'; |
|
265 |
my $draft = $self->{draft}; |
|
266 |
$table = 'letter_draft' if $draft; |
|
267 |
|
|
268 |
|
|
269 |
return $self unless $self && $self->{id}; # no id? dont load. |
|
270 |
|
|
271 |
my %mappings = _get_field_mappings(); |
|
272 |
my $mapped_select = join ', ', '*', map { "$_ AS $mappings{$_}" } keys %mappings; |
|
273 |
|
|
274 |
my ($db_letter) = selectfirst_hashref_query($::form, $::form->get_standard_dbh, <<SQL, $self->{id}); |
|
275 |
SELECT $mapped_select FROM $table WHERE id = ? |
|
276 |
SQL |
|
277 |
|
|
278 |
$self->update_from($db_letter); |
|
279 |
$self->_resolve_customer; |
|
280 |
$self->set_greetings; |
|
281 |
$self->{draft_id} = delete $self->{id} if $draft; # set draft if we have one |
|
282 |
|
|
283 |
return $self; |
|
284 |
} |
|
285 |
|
|
286 |
sub update_from { |
|
287 |
my $self = shift; |
|
288 |
my $src = shift; |
|
289 |
my %fields = $self->_get_fields; |
|
290 |
|
|
291 |
$fields{$_} = $src->{$_} for qw{customer_id customer selectcustomer oldcustomer}; # customer stuff |
|
292 |
|
|
293 |
$self->{$_} = $src->{$_} for keys %fields; |
|
294 |
|
|
295 |
return $self; |
|
296 |
} |
|
297 |
|
|
298 |
sub export_to { |
|
299 |
my $self = shift; |
|
300 |
my $form = shift; |
|
301 |
|
|
302 |
my %fields = $self->_get_fields; |
|
303 |
my %field_mappings = $self->_get_field_mappings; |
|
304 |
|
|
305 |
for (keys %fields) { |
|
306 |
$form->{$_} = _escaper($_)->( $self->{ $field_mappings{$_} || $_ } ); |
|
307 |
} |
|
308 |
} |
|
309 |
|
|
310 |
sub language { |
|
311 |
my $self = shift; |
|
312 |
die 'not a setter' if @_; |
|
313 |
|
|
314 |
return unless $self->{cp_id}; |
|
315 |
|
|
316 |
# umetec/cetaq only! |
|
317 |
# contacts have a custom variable called "mailing" |
|
318 |
# it contains either a language code or the string "No" |
|
319 |
|
|
320 |
my $custom_variables = CVar->get_custom_variables( |
|
321 |
module => 'Contacts', |
|
322 |
name_prefix => 'cp', |
|
323 |
trans_id => $self->{cp_id}, |
|
324 |
); |
|
325 |
|
|
326 |
my ($mailing) = grep { $_->{name} eq 'Mailing' } @$custom_variables; |
|
327 |
|
|
328 |
return $mailing->{value} eq 'No' ? undef : $mailing->{value}; |
|
329 |
} |
|
330 |
|
|
331 |
sub set_greetings { |
|
332 |
$::lxdebug->enter_sub; |
|
333 |
|
|
334 |
my $self = shift; |
|
335 |
return $::lxdebug->leave_sub if $self->{greeting}; |
|
336 |
|
|
337 |
# automatically set greetings |
|
338 |
# greetings depend mainly on contact person |
|
339 |
# my $contact = $self->_get_contact; |
|
340 |
|
|
341 |
$self->{greeting} = $::locale->text('Dear Sir or Madam,'); |
|
342 |
|
|
343 |
$::lxdebug->leave_sub; |
|
344 |
} |
|
345 |
|
|
346 |
sub _lastname_used { |
|
347 |
# wrapper for form lastname_used |
|
348 |
# sets customer to last used customer, |
|
349 |
# also used to initalize customer for new objects |
|
350 |
my $self = shift; |
|
351 |
|
|
352 |
return if $self->{customer_id}; |
|
353 |
|
|
354 |
my $saved_form = save_form($::form); |
|
355 |
|
|
356 |
$::form->lastname_used($::form->get_standard_dbh, \%::myconfig, 'customer'); |
|
357 |
|
|
358 |
$self->{customer_id} = $::form->{customer_id}; |
|
359 |
$self->{customer} = $::form->{customer}; |
|
360 |
|
|
361 |
restore_form($saved_form); |
|
362 |
|
|
363 |
return $self; |
|
364 |
} |
|
365 |
|
|
366 |
sub _resolve_customer { |
|
367 |
# used if an object is created with only id. |
|
368 |
my $self = shift; |
|
369 |
|
|
370 |
return unless $self->{customer_id} && !$self->{customer}; |
|
371 |
|
|
372 |
# my ($customer) = CT->find_by_id(cv => 'customer', id => $self->{customer_id}); |
|
373 |
# my ($customer) = CT->find_by_id(cv => 'customer', id => $self->{customer_id}); |
|
374 |
# SL/CVar.pm: : $cfg->{type} eq 'customer' ? (SL::DB::Manager::Customer->find_by(id => 1*$ref->{number_value}) || SL::DB::Customer->new)->name |
|
375 |
$self->{customer} = SL::DB::Manager::Customer->find_by(id => $self->{customer_id})->name; # || SL::DB::Customer->new)->name |
|
376 |
|
|
377 |
|
|
378 |
} |
|
379 |
|
|
380 |
sub _get_definition { |
|
381 |
$DEFINITION; |
|
382 |
} |
|
383 |
|
|
384 |
sub _get_field_mappings { |
|
385 |
return ( |
|
386 |
vc_id => 'customer_id', |
|
387 |
); |
|
388 |
} |
|
389 |
|
|
390 |
sub _get_fields { |
|
391 |
my %fields = _get_definition() =~ /(\w+) \s+ \| \s+ (integer|text|timestamp|numeric|date)/xg; |
|
392 |
} |
|
393 |
|
|
394 |
sub _escaper { |
|
395 |
my $field_name = shift; |
|
396 |
my %fields = __PACKAGE__->_get_fields; |
|
397 |
|
|
398 |
for ($fields{$field_name}) { |
|
399 |
return sub { conv_i(shift) } if /integer/; |
|
400 |
return sub { shift }; |
|
401 |
} |
|
402 |
} |
|
403 |
|
|
404 |
1; |
bin/mozilla/letter.pl | ||
---|---|---|
1 |
#===================================================================== |
|
2 |
# LX-Office ERP |
|
3 |
# Copyright (C) 2008 |
|
4 |
# Based on SQL-Ledger Version 2.1.9 |
|
5 |
# Web http://www.lx-office.org |
|
6 |
# |
|
7 |
#===================================================================== |
|
8 |
# |
|
9 |
# Letter module |
|
10 |
# |
|
11 |
#====================================================================== |
|
12 |
|
|
13 |
use strict; |
|
14 |
use POSIX qw(strftime); |
|
15 |
|
|
16 |
use SL::GenericTranslations; |
|
17 |
use SL::ReportGenerator; |
|
18 |
use SL::Letter; |
|
19 |
use SL::CT; |
|
20 |
use SL::DB::Contact; |
|
21 |
use SL::DB::Default; |
|
22 |
use SL::Helper::CreatePDF; |
|
23 |
use SL::Helper::Flash; |
|
24 |
use SL::Common; |
|
25 |
use Cwd; |
|
26 |
require "bin/mozilla/reportgenerator.pl"; |
|
27 |
require "bin/mozilla/io.pl"; |
|
28 |
require "bin/mozilla/arap.pl"; |
|
29 |
|
|
30 |
use constant TEXT_CREATED_FOR_VALUES => (qw(presskit fax letter)); |
|
31 |
use constant PAGE_CREATED_FOR_VALUES => (qw(sketch 1 2)); |
|
32 |
|
|
33 |
our ($form, %myconfig, $locale, $lxdebug); |
|
34 |
|
|
35 |
# parserhappy(R) |
|
36 |
# $locale->text('Presskit') |
|
37 |
# $locale->text('Sketch') |
|
38 |
# $locale->text('Fax') |
|
39 |
# $locale->text('Letter') |
|
40 |
|
|
41 |
sub add { |
|
42 |
$::lxdebug->enter_sub; |
|
43 |
|
|
44 |
$main::auth->assert('sales_letter_edit'); |
|
45 |
my %params = @_; |
|
46 |
|
|
47 |
return $main::lxdebug->leave_sub if load_letter_draft(); |
|
48 |
|
|
49 |
my $letter = SL::Letter->new(%params); |
|
50 |
|
|
51 |
if (my $cp_id = delete $::form->{contact_id}) { |
|
52 |
my $contact = SL::DB::Manager::Contact->find_by(cp_id => $cp_id); |
|
53 |
$letter->{cp_id} = $contact->cp_id; |
|
54 |
$letter->{vc_id} = $contact->cp_cv_id; |
|
55 |
$letter->{greeting} = GenericTranslations->get( |
|
56 |
translation_type => 'greetings::' . ($contact->{cp_gender} eq 'f' ? 'female' : 'male'), |
|
57 |
language_id => $contact->language_id, |
|
58 |
allow_fallback => 1 |
|
59 |
); |
|
60 |
$params{language_id} = $contact->language_id; |
|
61 |
} |
|
62 |
|
|
63 |
$letter->check_date; |
|
64 |
|
|
65 |
_display( |
|
66 |
letter => $letter, |
|
67 |
title => $locale->text('Add Letter'), |
|
68 |
language_id => $params{language_id}, |
|
69 |
); |
|
70 |
|
|
71 |
$::lxdebug->leave_sub; |
|
72 |
} |
|
73 |
|
|
74 |
sub edit { |
|
75 |
$::lxdebug->enter_sub; |
|
76 |
|
|
77 |
$main::auth->assert('sales_letter_edit'); |
|
78 |
add() unless ($form->{id}); |
|
79 |
|
|
80 |
my $letter = SL::Letter->new( id => $form->{id}, draft => $form->{draft} )->load; |
|
81 |
|
|
82 |
add() unless $letter && ($letter->{id} || $letter->{draft_id}); |
|
83 |
|
|
84 |
_display( |
|
85 |
letter => $letter, |
|
86 |
title => $locale->text('Edit Letter'), |
|
87 |
); |
|
88 |
|
|
89 |
$::lxdebug->leave_sub; |
|
90 |
} |
|
91 |
|
|
92 |
sub save { |
|
93 |
$::lxdebug->enter_sub; |
|
94 |
|
|
95 |
$main::auth->assert('sales_letter_edit'); |
|
96 |
my %params = @_; |
|
97 |
|
|
98 |
|
|
99 |
$::form->error(t8('The subject is missing.')) unless $form->{letter}->{subject}; |
|
100 |
$::form->error(t8('The body is missing.')) unless $form->{letter}->{body}; |
|
101 |
$::form->error(t8('The employee is missing.')) unless $form->{letter}->{employee_id}; |
|
102 |
|
|
103 |
my $letter = _update(); |
|
104 |
|
|
105 |
$letter->check_number; |
|
106 |
$letter->save; |
|
107 |
|
|
108 |
$form->{SAVED_MESSAGE} = $locale->text('Letter saved!'); |
|
109 |
|
|
110 |
_display( |
|
111 |
letter => $letter, |
|
112 |
); |
|
113 |
|
|
114 |
$::lxdebug->leave_sub; |
|
115 |
} |
|
116 |
|
|
117 |
sub save_letter_draft { |
|
118 |
$::lxdebug->enter_sub; |
|
119 |
|
|
120 |
$main::auth->assert('sales_letter_edit'); |
|
121 |
|
|
122 |
$::form->error(t8('The subject is missing.')) unless $form->{letter}->{subject}; |
|
123 |
$::form->error(t8('The body is missing.')) unless $form->{letter}->{body}; |
|
124 |
$::form->error(t8('The employee is missing.')) unless $form->{letter}->{employee_id}; |
|
125 |
$::form->error(t8('Already as letter saved.')) if $form->{letter}->{letternumber}; |
|
126 |
|
|
127 |
my $letter_draft = _update(); |
|
128 |
$letter_draft->{draft_id} = delete $letter_draft->{id}; # if we have one |
|
129 |
$letter_draft->save(draft => '1'); |
|
130 |
$letter_draft->{vergiss_mich_nicht} = 'nicht vergessen'; |
|
131 |
$form->{SAVED_MESSAGE} = $locale->text('Draft for this Letter saved!'); |
|
132 |
|
|
133 |
_display( |
|
134 |
letter => $letter_draft, |
|
135 |
); |
|
136 |
|
|
137 |
$::lxdebug->leave_sub; |
|
138 |
} |
|
139 |
|
|
140 |
sub delete { |
|
141 |
$main::lxdebug->enter_sub(); |
|
142 |
|
|
143 |
$main::auth->assert('sales_letter_edit'); |
|
144 |
# NYI |
|
145 |
$form->{SAVED_MESSAGE} = $locale->text('Not yet implemented!'); |
|
146 |
_display(); |
|
147 |
|
|
148 |
$main::lxdebug->leave_sub(); |
|
149 |
} |
|
150 |
|
|
151 |
sub delete_letter_drafts { |
|
152 |
$main::lxdebug->enter_sub(); |
|
153 |
|
|
154 |
$main::auth->assert('sales_letter_edit'); |
|
155 |
|
|
156 |
my @ids; |
|
157 |
foreach (keys %{$form}) { |
|
158 |
push @ids, $1 if (/^checked_(.*)/ && $form->{$_}); |
|
159 |
} |
|
160 |
|
|
161 |
SL::Letter->delete_drafts(@ids) if (@ids); #->{id}); |
|
162 |
|
|
163 |
add(); |
|
164 |
|
|
165 |
$main::lxdebug->leave_sub(); |
|
166 |
} |
|
167 |
|
|
168 |
sub _display { |
|
169 |
$main::lxdebug->enter_sub(); |
|
170 |
|
|
171 |
$main::auth->assert('sales_letter_edit'); |
|
172 |
my %params = @_; |
|
173 |
|
|
174 |
my $letter = $params{letter}; |
|
175 |
|
|
176 |
my %TMPL_VAR; |
|
177 |
|
|
178 |
$form->{type} = 'letter'; # needed for print_options |
|
179 |
$form->{vc} = 'customer'; # needs to be for _get_contacts... |
|
180 |
$form->{"$form->{vc}_id"} ||= $letter->{customer_id}; |
|
181 |
$form->{jsscript} = 1; |
|
182 |
$form->{javascript} = |
|
183 |
qq|<script type="text/javascript" src="js/customer_or_vendor_selection.js"></script> |
|
184 |
<script type="text/javascript" src="js/edit_part_window.js"></script>|; |
|
185 |
|
|
186 |
$form->get_lists("contacts" => "ALL_CONTACTS", |
|
187 |
"employees" => "ALL_EMPLOYEES", |
|
188 |
"salesmen" => "ALL_SALESMEN", |
|
189 |
"departments" => "ALL_DEPARTMENTS", |
|
190 |
"languages" => "languages", |
|
191 |
"customers" => { key => "ALL_CUSTOMERS", |
|
192 |
limit => $myconfig{vclimit} + 1 }, |
|
193 |
"vc" => 'customer', |
|
194 |
); |
|
195 |
|
|
196 |
$TMPL_VAR{vc_keys} = sub { "$_[0]->{name}--$_[0]->{id}" }; |
|
197 |
$TMPL_VAR{vc_select} = "customer_or_vendor_selection_window('letter.customer', '', 0, 0)"; |
|
198 |
$TMPL_VAR{ct_labels} = sub { ($_[0]->{cp_greeting} ? "$_[0]->{cp_greeting} " : '') . $_[0]->{cp_name} . ($_[0]->{cp_givenname} ? ", $_[0]->{cp_givenname}" : '') }; |
|
199 |
$TMPL_VAR{TCF} = [ map { key => $_, value => $locale->text(ucfirst $_) }, TEXT_CREATED_FOR_VALUES() ]; |
|
200 |
$TMPL_VAR{PCF} = [ map { key => $_, value => $locale->text(ucfirst $_) }, PAGE_CREATED_FOR_VALUES() ]; |
|
201 |
|
|
202 |
$form->header(); |
|
203 |
|
|
204 |
$form->{language_id} ||= $params{language_id}; |
|
205 |
|
|
206 |
print $form->parse_html_template('letter/edit', { |
|
207 |
%params, |
|
208 |
%TMPL_VAR, |
|
209 |
letter => $letter, |
|
210 |
print_options => print_options(inline => 1), |
|
211 |
}); |
|
212 |
|
|
213 |
$main::lxdebug->leave_sub(); |
|
214 |
} |
|
215 |
|
|
216 |
sub search { |
|
217 |
$lxdebug->enter_sub(); |
|
218 |
|
|
219 |
$main::auth->assert('sales_letter_report'); |
|
220 |
|
|
221 |
$form->get_lists("employees" => "EMPLOYEES", |
|
222 |
"salesmen" => "SALESMEN", |
|
223 |
"customers" => "ALL_CUSTOMERS"); |
|
224 |
|
|
225 |
$form->{jsscript} = 1; |
|
226 |
$form->{title} = $locale->text('Letters'); |
|
227 |
|
|
228 |
$form->header(); |
|
229 |
print $form->parse_html_template('letter/search'); |
|
230 |
|
|
231 |
$lxdebug->leave_sub(); |
|
232 |
} |
|
233 |
|
|
234 |
sub report { |
|
235 |
$lxdebug->enter_sub(); |
|
236 |
|
|
237 |
$main::auth->assert('sales_letter_report'); |
|
238 |
|
|
239 |
my %params = @_; |
|
240 |
|
|
241 |
my @report_params = qw(letternumber subject body contact date_from date_to cp_id); |
|
242 |
|
|
243 |
if ($form->{selectcustomer}) { |
|
244 |
push @report_params, 'customer_id'; |
|
245 |
$form->{customer_id} = $form->{customer}; |
|
246 |
} else { |
|
247 |
push @report_params, 'customer'; |
|
248 |
} |
|
249 |
|
|
250 |
report_generator_set_default_sort('date', 1); |
|
251 |
|
|
252 |
%params = (%params, map { $_ => $form->{$_} } @report_params); |
|
253 |
|
|
254 |
my @letters = SL::Letter->find(%params); |
|
255 |
|
|
256 |
$form->{rowcount} = @letters; |
|
257 |
$form->{title} = $locale->text('Letters'); |
|
258 |
|
|
259 |
my %column_defs = ( |
|
260 |
'date' => { 'text' => $locale->text('Date'), }, |
|
261 |
'subject' => { 'text' => $locale->text('Subject'), }, |
|
262 |
'letternumber' => { 'text' => $locale->text('Letternumber'), }, |
|
263 |
'customer' => { 'text' => $locale->text('Customer') }, |
|
264 |
'contact' => { 'text' => $locale->text('Contact') }, |
|
265 |
'date' => { 'text' => $locale->text('Date') }, |
|
266 |
); |
|
267 |
|
|
268 |
my @columns = qw(date subject letternumber customer contact date); |
|
269 |
my $href = build_std_url('action=report', grep { $form->{$_} } @report_params); |
|
270 |
|
|
271 |
my @sortable_columns = qw(date subject letternumber customer contact date); |
|
272 |
|
|
273 |
foreach my $name (@sortable_columns) { |
|
274 |
my $sortdir = $form->{sort} eq $name ? 1 - $form->{sortdir} : $form->{sortdir}; |
|
275 |
$column_defs{$name}->{link} = $href . "&sort=$name&sortdir=$sortdir"; |
|
276 |
} |
|
277 |
|
|
278 |
my @options; |
|
279 |
|
|
280 |
# option line |
|
281 |
|
|
282 |
push @options, $locale->text('Subject') . " : $form->{subject}" if ($form->{subject}); |
|
283 |
push @options, $locale->text('Body') . " : $form->{body}" if ($form->{body}); |
|
284 |
|
|
285 |
my @hidden_report_params = map { +{ 'key' => $_, 'value' => $form->{$_} } } @report_params; |
|
286 |
|
|
287 |
my $report = SL::ReportGenerator->new(\%myconfig, $form, 'std_column_visibility' => 1); |
|
288 |
|
|
289 |
$report->set_columns(%column_defs); |
|
290 |
$report->set_column_order(@columns); |
|
291 |
|
|
292 |
$report->set_export_options('report', @report_params); |
|
293 |
|
|
294 |
$report->set_sort_indicator($form->{sort}, $form->{sortdir}); |
|
295 |
|
|
296 |
$report->set_options('raw_top_info_text' => $form->parse_html_template('letter/report_top', { 'OPTIONS' => \@options }), |
|
297 |
'raw_bottom_info_text' => $form->parse_html_template('letter/report_bottom', { 'HIDDEN' => \@hidden_report_params }), |
|
298 |
'output_format' => 'HTML', |
|
299 |
'title' => $form->{title}, |
|
300 |
'attachment_basename' => $locale->text('letters_list') . strftime('_%Y%m%d', localtime time), |
|
301 |
); |
|
302 |
$report->set_options_from_form(); |
|
303 |
|
|
304 |
my $idx = 0; |
|
305 |
my $callback = build_std_url('action=report', grep { $form->{$_} } @report_params); |
|
306 |
my $edit_url = build_std_url('action=edit', 'callback=' . E($callback)); |
|
307 |
|
|
308 |
foreach my $l (@letters) { |
|
309 |
$idx++; |
|
310 |
|
|
311 |
my $row = { map { $_ => { 'data' => $l->{$_} } } keys %{ $l } }; |
|
312 |
|
|
313 |
$row->{subject}->{link} = $edit_url . '&id=' . Q($l->{id}); |
|
314 |
$row->{letternumber}->{link} = $edit_url . '&id=' . Q($l->{id}); |
|
315 |
|
|
316 |
$report->add_data($row); |
|
317 |
} |
|
318 |
|
|
319 |
$report->generate_with_headers(); |
|
320 |
|
|
321 |
$lxdebug->leave_sub(); |
|
322 |
} |
|
323 |
|
|
324 |
sub print_letter { |
|
325 |
$lxdebug->enter_sub(); |
|
326 |
|
|
327 |
$main::auth->assert('sales_letter_edit'); |
|
328 |
|
|
329 |
my ($old_form) = @_; |
|
330 |
|
|
331 |
my $display_form = $form->{display_form} || "display_form"; |
|
332 |
my $letter = _update(); |
|
333 |
|
|
334 |
$letter->export_to($form); |
|
335 |
$form->{formname} = "letter"; |
|
336 |
$form->{format} = "pdf"; |
|
337 |
|
|
338 |
my $language_saved = $form->{language_id}; |
|
339 |
my $greeting_saved = $form->{greeting}; |
|
340 |
my $cp_id_saved = $form->{cp_id}; |
|
341 |
|
|
342 |
call_sub("customer_details"); |
|
343 |
|
|
344 |
if (!$cp_id_saved) { |
|
345 |
# No contact was selected. Delete all contact variables because |
|
346 |
# IS->customer_details() and IR->vendor_details() get the default |
|
347 |
# contact anyway. |
|
348 |
map({ delete($form->{$_}); } grep(/^cp_/, keys(%{ $form }))); |
|
349 |
} |
|
350 |
|
|
351 |
$form->{greeting} = $greeting_saved; |
|
352 |
$form->{language_id} = $language_saved; |
|
353 |
|
|
354 |
if ($form->{cp_id}) { |
|
355 |
CT->get_contact(\%myconfig, $form); |
|
356 |
} |
|
357 |
|
|
358 |
$form->{cp_contact_formal} = ($form->{cp_greeting} ? "$form->{cp_greeting} " : '') . ($form->{cp_givenname} ? "$form->{cp_givenname} " : '') . $form->{cp_name}; |
|
359 |
|
|
360 |
$form->get_employee_data('prefix' => 'employee', 'id' => $letter->{employee_id}); |
|
361 |
$form->get_employee_data('prefix' => 'salesman', 'id' => $letter->{salesman_id}); |
|
362 |
|
|
363 |
my %create_params = ( |
|
364 |
template => scalar(SL::Helper::CreatePDF->find_template( |
|
365 |
name => 'letter', |
|
366 |
printer_id => $::form->{printer_id}, |
|
367 |
language_id => $::form->{language_id}, |
|
368 |
formname => 'letter', |
|
369 |
format => 'pdf', |
|
370 |
)), |
|
371 |
variables => $::form, |
|
372 |
return => 'file_name', |
|
373 |
); |
|
374 |
my $pdf_file_name; |
|
375 |
eval { |
|
376 |
# catch LaTeX template not found error |
|
377 |
my $tex_templates = $::instance_conf->get_templates . '/letter.tex'; |
|
378 |
die( t8('Please create/copy a template named letter.tex in your client template dir') ) unless (-e $tex_templates); |
|
379 |
|
|
380 |
$pdf_file_name = SL::Helper::CreatePDF->create_pdf(%create_params); |
|
381 |
|
|
382 |
# set some form defaults for printing webdav copy variables |
|
383 |
$form->{tmpfile} = $pdf_file_name; |
|
384 |
$form->{tmpdir} = 'users'; |
|
385 |
$form->{type} = 'letter'; |
|
386 |
$form->{cwd} = getcwd(); |
|
387 |
if ( $::form->{media} eq 'email') { |
|
388 |
my $mail = Mailer->new; |
Auch abrufbar als: Unified diff
Letter Controller rewrite
Jetzt auf einigermassen aktuellem technischen Stand.