5 use List::Util qw(first);
10 use SL::DB::FollowUpCreatedForEmployee;
14 use SL::Template::PlainText;
19 my ($self, %params) = @_;
20 $main::lxdebug->enter_sub();
22 my $is_new = !$params{id};
24 my $rc = SL::DB->client->with_transaction(\&_save, $self, %params);
26 FU->send_email_notification(%params) if ($is_new);
28 $::lxdebug->leave_sub;
36 my $myconfig = \%main::myconfig;
37 my $form = $main::form;
39 my $dbh = $params{dbh} || SL::DB->client->dbh;
43 ($params{id}) = selectrow_query($form, $dbh, qq|SELECT nextval('follow_up_id')|);
45 $query = qq|INSERT INTO follow_ups (created_by, note_id, follow_up_date, id)
46 VALUES ((SELECT id FROM employee WHERE login = ?), ?, ?, ?)|;
48 push @values, $::myconfig{login};
51 $query = qq|UPDATE follow_ups SET note_id = ?, follow_up_date = ? WHERE id = ?|;
54 $params{note_id} = Notes->save('id' => $params{note_id},
55 'trans_id' => $params{id},
56 'trans_module' => 'fu',
57 'subject' => $params{subject},
58 'body' => $params{body},
61 do_query($form, $dbh, $query, @values, conv_i($params{note_id}), $params{follow_up_date}, conv_i($params{id}));
63 $params{done} = 1 if (!defined $params{done});
65 do_query($form, $dbh, qq|INSERT INTO follow_up_done (follow_up_id, employee_id) VALUES (?, (SELECT id FROM employee WHERE login = ?))|,
66 conv_i($params{id}), $::myconfig{login});
68 do_query($form, $dbh, qq|DELETE FROM follow_up_done WHERE follow_up_id = ?|, conv_i($params{id}));
71 do_query($form, $dbh, qq|DELETE FROM follow_up_links WHERE follow_up_id = ?|, conv_i($params{id}));
73 $query = qq|INSERT INTO follow_up_links (follow_up_id, trans_id, trans_type, trans_info) VALUES (?, ?, ?, ?)|;
74 my $sth = prepare_query($form, $dbh, $query);
76 foreach my $link (@{ $params{LINKS} }) {
77 do_statement($form, $sth, $query, conv_i($params{id}), conv_i($link->{trans_id}), $link->{trans_type}, $link->{trans_info});
82 do_query($form, $dbh, qq|DELETE FROM follow_up_created_for_employees WHERE follow_up_id = ?|, conv_i($params{id}));
84 $query = qq|INSERT INTO follow_up_created_for_employees (follow_up_id, employee_id) VALUES (?, ?)|;
85 $sth = prepare_query($form, $dbh, $query);
87 foreach my $employee_id (@{ $params{created_for_employees} }) {
88 do_statement($form, $sth, $query, conv_i($params{id}), $employee_id);
95 $main::lxdebug->enter_sub();
100 Common::check_params(\%params, 'id');
102 my $myconfig = \%main::myconfig;
103 my $form = $main::form;
105 my ($done) = selectrow_query($::form, SL::DB->client->dbh, qq|SELECT id FROM follow_up_done WHERE follow_up_id = ?|, conv_i($params{id}));
107 SL::DB->client->with_transaction(sub {
108 do_query($form, SL::DB->client->dbh, qq|INSERT INTO follow_up_done (follow_up_id, employee_id) VALUES (?, (SELECT id FROM employee WHERE login = ?))|,
109 conv_i($params{id}), $myconfig->{login});
111 }) or do { die SL::DB->client->error };
114 $main::lxdebug->leave_sub();
118 $main::lxdebug->enter_sub();
123 Common::check_params(\%params, 'id');
125 my $myconfig = \%main::myconfig;
126 my $form = $main::form;
128 SL::DB->client->with_transaction(sub {
129 my $dbh = SL::DB->client->dbh;
131 my $id = conv_i($params{id});
133 do_query($form, $dbh, qq|DELETE FROM follow_up_links WHERE follow_up_id = ?|, $id);
134 do_query($form, $dbh, qq|DELETE FROM follow_ups WHERE id = ?|, $id);
135 do_query($form, $dbh, qq|DELETE FROM notes WHERE (trans_id = ?) AND (trans_module = 'fu')|, $id);
137 }) or do { die SL::DB->client->error };
139 $main::lxdebug->leave_sub();
143 $main::lxdebug->enter_sub();
148 Common::check_params(\%params, 'id');
150 my $myconfig = \%main::myconfig;
151 my $form = $main::form;
153 my $dbh = $form->get_standard_dbh($myconfig);
154 my ($query, @values);
156 my ($employee_id) = selectrow_query($form, $dbh, qq|SELECT id FROM employee WHERE login = ?|, $::myconfig{login});
157 $query = qq|SELECT fu.*, n.subject, n.body, n.created_by,
158 follow_up_done.follow_up_id AS done,
159 date_trunc('second', follow_up_done.done_at) AS done_at,
160 COALESCE(done_by.name, done_by.login) AS done_by_employee_name
162 LEFT JOIN notes n ON (fu.note_id = n.id)
163 LEFT JOIN follow_up_created_for_employees ON (follow_up_created_for_employees.follow_up_id = fu.id)
164 LEFT JOIN follow_up_done ON (follow_up_done.follow_up_id = fu.id)
165 LEFT JOIN employee done_by ON (follow_up_done.employee_id = done_by.id)
167 AND ( (fu.created_by = ?) OR (follow_up_created_for_employees.employee_id = ?)
168 OR (fu.created_by IN (SELECT DISTINCT what FROM follow_up_access WHERE who = ?)))|;
169 my $ref = selectfirst_hashref_query($form, $dbh, $query, conv_i($params{id}), $employee_id, $employee_id, $employee_id);
172 $main::lxdebug->leave_sub();
176 $ref->{LINKS} = $self->retrieve_links(%{ $ref });
178 $main::lxdebug->leave_sub();
184 $main::lxdebug->enter_sub();
189 Common::check_params(\%params, qw(id));
191 my $myconfig = \%main::myconfig;
192 my $form = $main::form;
194 my $dbh = $form->get_standard_dbh($myconfig);
196 my $query = qq|SELECT ful.trans_id, ful.trans_type, ful.trans_info, fu.note_id
197 FROM follow_up_links ful
198 LEFT JOIN follow_ups fu ON (ful.follow_up_id = fu.id)
199 WHERE ful.follow_up_id = ?
202 my $links = selectall_hashref_query($form, $dbh, $query, conv_i($params{id}));
204 foreach my $link_ref (@{ $links }) {
205 my $link_details = FU->link_details(%{ $link_ref });
206 map { $link_ref->{$_} = $link_details->{$_} } keys %{ $link_details} if ($link_details);
209 $main::lxdebug->leave_sub();
215 $main::lxdebug->enter_sub();
220 my $myconfig = \%main::myconfig;
221 my $form = $main::form;
223 my $dbh = $form->get_standard_dbh($myconfig);
224 my ($query, $where, $where_user);
226 my ($employee_id) = selectrow_query($form, $dbh, qq|SELECT id FROM employee WHERE login = ?|, $::myconfig{login});
228 my @values_user = ();
230 if ($params{trans_id}) {
231 $where .= qq| AND fu.id IN (select follow_up_id from follow_up_links where trans_id = ?)|;
232 # $where .= qq| AND (ful.follow_up_id = fu.id) AND (ful.trans_id = ?))|;
233 # $where .= qq| AND EXISTS (SELECT * FROM follow_up_links ful
234 # WHERE (ful.follow_up_id = fu.id) AND (ful.trans_id = ?))|;
235 push @values, conv_i($params{trans_id});
238 if ($params{due_only}) {
239 $where .= qq| AND (fu.follow_up_date <= current_date)|;
242 if ($params{done} ne $params{not_done}) {
243 my $not = $params{not_done} ? 'NOT' : '';
244 $where .= qq| AND $not EXISTS (SELECT id FROM follow_up_done WHERE follow_up_id = fu.id)|;
247 if ($params{not_id}) {
248 $where .= qq| AND (fu.id <> ?)|;
249 push @values, conv_i($params{not_id});
252 foreach my $item (qw(subject body)) {
253 next unless ($params{$item});
254 $where .= qq| AND (n.${item} ILIKE ?)|;
255 push @values, like($params{$item});
258 if ($params{reference}) {
259 $where .= qq| AND EXISTS (SELECT ful.follow_up_id
260 FROM follow_up_links ful
261 WHERE (ful.follow_up_id = fu.id)
262 AND (ful.trans_info ILIKE ?)
264 push @values, like($params{reference});
267 if ($params{follow_up_date_from}) {
268 $where .= qq| AND (fu.follow_up_date >= ?)|;
269 push @values, conv_date($params{follow_up_date_from});
271 if ($params{follow_up_date_to}) {
272 $where .= qq| AND (fu.follow_up_date <= ?)|;
273 push @values, conv_date($params{follow_up_date_to});
276 if ($params{itime_from}) {
277 $where .= qq| AND (date_trunc('DAY', fu.itime) >= ?)|;
278 push @values, conv_date($params{itime_from});
280 if ($params{itime_to}) {
281 $where .= qq| AND (date_trunc('DAY', fu.itime) <= ?)|;
282 push @values, conv_date($params{itime_to});
284 if ($params{created_for}) {
285 $where .= qq| AND follow_up_created_for_employees.employee_id = ?|;
286 push @values, conv_i($params{created_for});
289 if ($params{all_users} || $params{trans_id}) { # trans_id only for documents?
290 $where_user = qq|OR (fu.created_by IN (SELECT DISTINCT what FROM follow_up_access WHERE who = ?))|;
291 push @values_user, $employee_id;
296 if ($form->{sort} ne 'title') {
298 'follow_up_date' => [ qw(fu.follow_up_date fu.id) ],
299 'created_on' => [ qw(created_on fu.id) ],
300 'subject' => [ qw(n.subject) ],
303 my $sortdir = !defined $form->{sortdir} ? 'ASC' : $form->{sortdir} ? 'ASC' : 'DESC';
304 my $sortkey = $sort_columns{$form->{sort}} ? $form->{sort} : 'follow_up_date';
305 $order_by = 'ORDER BY ' . join(', ', map { "$_ $sortdir" } @{ $sort_columns{$sortkey} });
308 $query = qq|SELECT DISTINCT fu.*, n.subject, n.body, n.created_by,
309 fu.follow_up_date <= current_date AS due,
310 fu.itime::DATE AS created_on,
311 COALESCE(eby.name, eby.login) AS created_by_name,
312 follow_up_done.follow_up_id AS done
314 LEFT JOIN notes n ON (fu.note_id = n.id)
315 LEFT JOIN employee eby ON (n.created_by = eby.id)
316 LEFT JOIN follow_up_created_for_employees ON (follow_up_created_for_employees.follow_up_id = fu.id)
317 LEFT JOIN follow_up_done ON (follow_up_done.follow_up_id = fu.id)
318 WHERE ((fu.created_by = ?) OR (follow_up_created_for_employees.employee_id = ?)
323 my $follow_ups = selectall_hashref_query($form, $dbh, $query, $employee_id, $employee_id, @values_user, @values);
325 if (!scalar @{ $follow_ups }) {
326 $main::lxdebug->leave_sub();
330 foreach my $fu (@{ $follow_ups }) {
331 $fu->{LINKS} = $self->retrieve_links(%{ $fu });
333 my $fu_created_for_employees = SL::DB::Manager::FollowUpCreatedForEmployee->get_all(
334 where => [follow_up_id => $fu->{id}],
335 with_obects => ['employee']);
336 $fu->{created_for_user_name} = join "\n", map { $_->employee->safe_name } @{$fu_created_for_employees};
339 if ($form->{sort} eq 'title') {
340 my $dir_factor = !defined $form->{sortdir} ? 1 : $form->{sortdir} ? 1 : -1;
341 $follow_ups = [ map { $_->[1] }
342 sort { ($a->[0] cmp $b->[0]) * $dir_factor }
343 map { my $fu = $follow_ups->[$_]; [ @{ $fu->{LINKS} } ? lc($fu->{LINKS}->[0]->{title}) : '', $fu ] }
344 (0 .. scalar(@{ $follow_ups }) - 1) ];
347 $main::lxdebug->leave_sub();
353 $main::lxdebug->enter_sub();
358 Common::check_params(\%params, qw(trans_id trans_type));
360 my $myconfig = \%main::myconfig;
361 my $form = $main::form;
362 my $locale = $main::locale;
364 my $q_id = $form->quote($params{trans_id});
367 if ($params{trans_type} eq 'customer') {
369 'url' => 'controller.pl?action=CustomerVendor/edit&db=customer&id=' . $form->quote($params{trans_id}) . '¬e_id=' . $form->quote($params{note_id}),
370 'title' => $locale->text('Customer') . " '$params{trans_info}'",
373 } elsif ($params{trans_type} eq 'vendor') {
375 'url' => 'controller.pl?action=CustomerVendor/edit&db=vendor&id=' . $params{trans_id} . '¬e_id=' . $form->quote($params{note_id}),
376 'title' => $locale->text('Vendor') . " '$params{trans_info}'",
379 } elsif ($params{trans_type} eq 'sales_quotation') {
381 'url' => 'controller.pl?action=Order/edit&type=sales_quotation&id=' . $params{trans_id},
382 'title' => $locale->text('Sales quotation') . " $params{trans_info}",
385 } elsif ($params{trans_type} eq 'sales_order_intake') {
386 my $script = 'controller.pl';
387 my $action = 'Order/edit';
389 'url' => $script . '?action=' . $action . '&type=sales_quotation_intake&id=' . $params{trans_id},
390 'title' => $locale->text('Order Intake') . " $params{trans_info}",
393 } elsif ($params{trans_type} eq 'sales_delivery_order') {
396 'url' => 'controller.pl?action=DeliveryOrder/edit&id=' . $params{trans_id} . '&edit_note_id=' . $form->quote($params{note_id}),
397 'title' => $locale->text('Sales delivery order') .' '. $params{trans_info},
400 } elsif ($params{trans_type} eq 'purchase_delivery_order') {
403 'url' => 'controller.pl?action=DeliveryOrder/edit&id=' . $params{trans_id} . '&edit_note_id=' . $form->quote($params{note_id}),
404 'title' => $locale->text('Purchase delivery order') .' '. $params{trans_info},
407 } elsif ($params{trans_type} eq 'sales_order') {
409 'url' => 'controller.pl?action=Order/edit&type=sales_order&id=' . $params{trans_id},
410 'title' => $locale->text('Sales Order') . " $params{trans_info}",
413 } elsif ($params{trans_type} eq 'sales_reclamation') {
414 my $script = 'controller.pl';
415 my $action = 'Reclamation/edit';
417 'url' => $script . '?action=' . $action . '&type=sales_reclamation&id=' . $params{trans_id},
418 'title' => $locale->text('Sales Reclamation') . " $params{trans_info}",
421 } elsif ($params{trans_type} eq 'sales_invoice') {
423 'url' => 'is.pl?action=edit&type=invoice&id=' . $params{trans_id},
424 'title' => $locale->text('Sales Invoice') . " $params{trans_info}",
427 } elsif ($params{trans_type} eq 'purchase_invoice') {
429 'url' => 'ir.pl?action=edit&type=purchase_invoice&id=' . $params{trans_id},
430 'title' => $locale->text('Purchase Invoice') . " $params{trans_info}",
433 } elsif ($params{trans_type} eq 'credit_note') {
435 'url' => 'is.pl?action=edit&type=credit_note&id=' . $params{trans_id},
436 'title' => $locale->text('Credit Note') . " $params{trans_info}",
439 } elsif ($params{trans_type} eq 'dunning') {
441 'url' => 'dn.pl?action=print_dunning&format=pdf&media=screen&dunning_id=' . $params{trans_id},
442 'title' => $locale->text('Dunning') . " $params{trans_info}",
445 } elsif ($params{trans_type} eq 'request_quotation') {
447 'url' => 'controller.pl?action=Order/edit&type=request_quotation&id=' . $params{trans_id},
448 'title' => $locale->text('Request quotation') . " $params{trans_info}",
451 } elsif ($params{trans_type} eq 'purchase_quotation_intake') {
452 my $script = 'controller.pl';
453 my $action = 'Order/edit';
455 'url' => $script . '?action=' . $action . '&type=purchase_quotation_intake&id=' . $params{trans_id},
456 'title' => $locale->text('Quotation Intake') . " $params{trans_info}",
459 } elsif ($params{trans_type} eq 'purchase_order') {
461 'url' => 'controller.pl?action=Order/edit&type=purchase_order&id=' . $params{trans_id},
462 'title' => $locale->text('Purchase Order') . " $params{trans_info}",
465 } elsif ($params{trans_type} eq 'purchase_reclamation') {
466 my $script = 'controller.pl';
467 my $action = 'Reclamation/edit';
469 'url' => $script . '?action=' . $action . '&type=purchase_reclamation&id=' . $params{trans_id},
470 'title' => $locale->text('Purchase Reclamation') . " $params{trans_info}",
473 } elsif ($params{trans_type} eq 'vendor_invoice') {
475 'url' => 'ir.pl?action=edit&type=invoice&id=' . $params{trans_id},
476 'title' => $locale->text('Vendor Invoice') . " $params{trans_info}",
479 } elsif ($params{trans_type} eq 'ar_transaction') {
481 'url' => 'ar.pl?action=edit&id=' . $params{trans_id},
482 'title' => $locale->text('AR Transaction') . " $params{trans_info}",
485 } elsif ($params{trans_type} eq 'ap_transaction') {
487 'url' => 'ap.pl?action=edit&id=' . $params{trans_id},
488 'title' => $locale->text('AP Transaction') . " $params{trans_info}",
491 } elsif ($params{trans_type} eq 'gl_transaction') {
493 'url' => 'gl.pl?action=edit&id=' . $params{trans_id},
494 'title' => $locale->text('GL Transaction') . " $params{trans_info}",
499 $main::lxdebug->leave_sub();
504 sub save_access_rights {
505 $main::lxdebug->enter_sub();
510 Common::check_params(\%params, 'access');
512 my $myconfig = \%main::myconfig;
513 my $form = $main::form;
515 SL::DB->client->with_transaction(sub {
516 my $dbh = SL::DB->client->dbh;
518 my ($id) = selectrow_query($form, $dbh, qq|SELECT id FROM employee WHERE login = ?|, $::myconfig{login});
520 do_query($form, $dbh, qq|DELETE FROM follow_up_access WHERE what = ?|, $id);
522 my $query = qq|INSERT INTO follow_up_access (who, what) VALUES (?, ?)|;
523 my $sth = prepare_query($form, $dbh, $query);
525 while (my ($who, $access_allowed) = each %{ $params{access} }) {
526 next unless ($access_allowed);
528 do_statement($form, $sth, $query, conv_i($who), $id);
533 }) or do { die SL::DB->client->error };
535 $main::lxdebug->leave_sub();
538 sub retrieve_access_rights {
539 $main::lxdebug->enter_sub();
544 my $myconfig = \%main::myconfig;
545 my $form = $main::form;
547 my $dbh = $form->get_standard_dbh($myconfig);
549 my $sth = prepare_execute_query($form, $dbh, qq|SELECT who FROM follow_up_access WHERE what = (SELECT id FROM employee WHERE login = ?)|, $::myconfig{login});
552 while (my $ref = $sth->fetchrow_hashref()) {
553 $access->{$ref->{who}} = 1;
558 $main::lxdebug->leave_sub();
563 sub send_email_notification {
564 $main::lxdebug->enter_sub();
565 my ($self, %params) = @_;
567 my $notify_cfg = $main::lx_office_conf{follow_up_notify};
569 || !$notify_cfg->{email_subject}
570 || !$notify_cfg->{email_from}
571 || !$notify_cfg->{email_template}) {
572 $main::lxdebug->leave_sub();
576 my $employee = SL::DB::Manager::Employee->current;
578 my @for_employees_ids = @{$params{created_for_employees}};
580 my $placeholders = join ', ', map {'?'} @for_employees_ids;
584 WHERE id in ($placeholders)
587 my $dbh = $employee->dbh;
588 my $hash_key = 'login';
589 my $hashref = $dbh->selectall_hashref(
590 $query, $hash_key, undef, @for_employees_ids
592 my @logins = keys %$hashref;
594 foreach my $login (@logins) {
595 my %recipient = $main::auth->read_user(
599 if (!$recipient{follow_up_notify_by_email} || !$recipient{email}) {
603 my %template_params = (
604 follow_up_subject => $params{subject},
605 follow_up_body => $params{body},
606 follow_up_date => $params{follow_up_date},
607 creator_name => $employee->name || $::form->{login},
608 recipient_name => $recipient{name} || $recipient{login},
611 my $template = Template->new({ENCODING => 'utf8'});
613 my $body_file = $notify_cfg->{email_template};
614 my $content_type = $body_file =~ m/.html$/ ? 'text/html' : 'text/plain';
617 $template->process($body_file, \%template_params, \$message)
618 || die $template->error;
620 my $param_form = Form->new();
621 $param_form->{$_} = $template_params{$_} for keys %template_params;
623 my $mail = Mailer->new();
624 $mail->{from} = $notify_cfg->{email_from};
625 $mail->{to} = $recipient{email};
626 $mail->{subject} = SL::Template::PlainText->new(form => $param_form)
627 ->substitute_vars($notify_cfg->{email_subject});
628 $mail->{content_type} = $content_type;
629 $mail->{message} = $message;
630 $mail->{charset} = 'UTF-8';
635 $main::lxdebug->leave_sub();