From: Sven Schöling Date: Mon, 21 Dec 2015 15:16:39 +0000 (+0100) Subject: Letter Controller rewrite X-Git-Tag: release-3.4.1~466 X-Git-Url: http://wagnertech.de/git?a=commitdiff_plain;h=ea5d75b52e043fb3f0d264056df6007049d6a3fd;p=kivitendo-erp.git Letter Controller rewrite Jetzt auf einigermassen aktuellem technischen Stand. --- diff --git a/SL/Controller/Letter.pm b/SL/Controller/Letter.pm new file mode 100644 index 000000000..f1109d72c --- /dev/null +++ b/SL/Controller/Letter.pm @@ -0,0 +1,583 @@ +package SL::Controller::Letter; + +use strict; +use parent qw(SL::Controller::Base); + +use POSIX qw(strftime); +use SL::Controller::Helper::GetModels; +use SL::Controller::Helper::ReportGenerator; +use SL::DB::Letter; +use SL::DB::LetterDraft; +use SL::DB::Employee; +use SL::Helper::Flash qw(flash); +use SL::Helper::CreatePDF; +use SL::Locale::String qw(t8); +use SL::IS; +use SL::ReportGenerator; + +use Rose::Object::MakeMethods::Generic ( + 'scalar --get_set_init' => [ qw(letter all_employees models) ], +); + +__PACKAGE__->run_before('check_auth_edit'); +__PACKAGE__->run_before('check_auth_report', only => [ qw(list) ]); + +use constant TEXT_CREATED_FOR_VALUES => (qw(presskit fax letter)); +use constant PAGE_CREATED_FOR_VALUES => (qw(sketch 1 2)); + +my %sort_columns = ( + date => t8('Date'), + subject => t8('Subject'), + letternumber => t8('Letternumber'), + vc_id => t8('Customer'), + contact => t8('Contact'), +); + +sub action_add { + my ($self, %params) = @_; + + return if $self->load_letter_draft(%params); + + $self->letter->employee_id(SL::DB::Manager::Employee->current->id); + $self->letter->salesman_id(SL::DB::Manager::Employee->current->id); + + $self->_display( + title => t8('Add Letter'), + language_id => $params{language_id}, + ); +} + +sub action_edit { + my ($self, %params) = @_; + + return $self->action_add + unless $::form->{letter} || $::form->{draft}; + + $self->letter(SL::DB::Letter->new_from_draft($::form->{draft}{id})) + if $::form->{draft}; + + $self->_display( + title => t8('Edit Letter'), + ); +} + +sub action_save { + my ($self, %params) = @_; + + my $letter = $self->_update; + + if (!$self->check_letter($letter)) { + return $self->_display; + } + + $self->check_number; + + if (!$letter->save) { + flash('error', t8('There was an error saving the letter')); + return $self->_display; + } + + flash('info', t8('Letter saved!')); + + $self->_display; +} + +sub action_update_contacts { + my ($self) = @_; + + my $letter = $self->letter; + + if (!$self->letter->vc_id || !$self->letter->customer) { + return $self->js + ->replaceWith( + '#letter_cp_id', + SL::Presenter->get->select_tag('letter.cp_id', [], value_key => 'cp_id', title_key => 'full_name') + ) + ->render; + } + + my $contacts = $letter->customer->contacts; + + my $default; + if ( $letter->contact + && $letter->contact->cp_cv_id + && $letter->contact->cp_cv_id == $letter->vc_id) { + $default = $letter->contact->cp_id; + } else { + $default = ''; + } + + $self->js + ->replaceWith( + '#letter_cp_id', + SL::Presenter->get->select_tag('letter.cp_id', $contacts, default => $default, value_key => 'cp_id', title_key => 'full_name') + ) + ->render; +} + +sub action_save_letter_draft { + my ($self, %params) = @_; + + $self->check_letter; + + my $letter_draft = SL::DB::LetterDraft->new_from_letter($self->_update); + + if (!$letter_draft->save) { + flash('error', t8('There was an error saving the letter draft')); + return $self->_display; + } + + flash('info', t8('Draft for this Letter saved!')); + + $self->_display; +} + +sub action_delete { + my ($self, %params) = @_; + + if (!$self->letter->delete) { + flash('error', t8('An error occured. Letter could not be deleted.')); + return $self->action_update; + } + + flash_later('info', t8('Letter deleted')); + $self->redirect_to(action => 'list'); +} + +sub action_delete_letter_drafts { + my ($self, %params) = @_; + + my @ids = grep { /^checked_(.*)/ && $::form->{$_} } keys %$::form; + + SL::DB::Manager::LetterDraft->delete_all(query => [ ids => \@ids ]) if @ids; + + $self->redirect_to(action => 'add'); +} + +sub action_list { + my ($self, %params) = @_; + + $self->make_filter_summary; + $self->prepare_report; + + my $letters = $self->models->get; + $self->report_generator_list_objects(report => $self->{report}, objects => $letters); + +} + +sub action_print_letter { + my ($self, $old_form) = @_; + + my $display_form = $::form->{display_form} || "display_form"; + my $letter = $self->_update; + + $self->export_letter_to_form($letter); + $::form->{formname} = "letter"; + $::form->{format} = "pdf"; + + my $language_saved = $::form->{language_id}; + my $greeting_saved = $::form->{greeting}; + my $cp_id_saved = $::form->{cp_id}; + + IS->customer_details(\%::myconfig, $::form); + + if (!$cp_id_saved) { + # No contact was selected. Delete all contact variables because + # IS->customer_details() and IR->vendor_details() get the default + # contact anyway. + map({ delete($::form->{$_}); } grep(/^cp_/, keys(%{ $::form }))); + } + + $::form->{greeting} = $greeting_saved; + $::form->{language_id} = $language_saved; + + if ($::form->{cp_id}) { + CT->get_contact(\%::myconfig, $::form); + } + + $::form->{cp_contact_formal} = ($::form->{cp_greeting} ? "$::form->{cp_greeting} " : '') . ($::form->{cp_givenname} ? "$::form->{cp_givenname} " : '') . $::form->{cp_name}; + + $::form->get_employee_data('prefix' => 'employee', 'id' => $letter->{employee_id}); + $::form->get_employee_data('prefix' => 'salesman', 'id' => $letter->{salesman_id}); + + my %create_params = ( + template => scalar(SL::Helper::CreatePDF->find_template( + name => 'letter', + printer_id => $::form->{printer_id}, + language_id => $::form->{language_id}, + formname => 'letter', + format => 'pdf', + )), + variables => $::form, + return => 'file_name', + ); + my $pdf_file_name; + eval { + $pdf_file_name = SL::Helper::CreatePDF->create_pdf(%create_params); + + # set some form defaults for printing webdav copy variables + if ( $::form->{media} eq 'email') { + my $mail = Mailer->new; + my $signature = $::myconfig{signature}; + $mail->{$_} = $::form->{$_} for qw(cc subject message bcc to); + $mail->{from} = qq|"$::myconfig{name}" <$::myconfig{email}>|; + $mail->{fileid} = time() . '.' . $$ . '.'; + $mail->{attachments} = [{ "filename" => $pdf_file_name, + "name" => $::form->{attachment_name} }]; + $mail->{message} .= "\n-- \n$signature"; + $mail->{message} =~ s/\r//g; + + # copy_file_to_webdav was already done via io.pl -> edit_e_mail + my $err = $mail->send; + return !$err; + } + + if (!$::form->{printer_id} || $::form->{media} eq 'screen') { + + my $file = IO::File->new($pdf_file_name, 'r') || croak("Cannot open file '$pdf_file_name'"); + my $size = -s $pdf_file_name; + my $content_type = 'application/pdf'; + my $attachment_name = $::form->generate_attachment_filename; + $attachment_name =~ s:.*//::g; + + print $::form->create_http_response(content_type => $content_type, + content_disposition => 'attachment; filename="' . $attachment_name . '"', + content_length => $size); + + $::locale->with_raw_io(\*STDOUT, sub { print while <$file> }); + $file->close; + + Common::copy_file_to_webdav_folder($::form) if $::instance_conf->get_webdav_documents; + unlink $pdf_file_name; + return 1; + } + + my $printer = SL::DB::Printer->new(id => $::form->{printer_id})->load; + my $command = SL::Template::create(type => 'ShellCommand', form => Form->new(''))->parse($printer->printer_command); + + open my $out, '|-', $command or die $!; + binmode $out; + print $out scalar(read_file($pdf_file_name)); + close $out; + Common::copy_file_to_webdav_folder($::form) if $::instance_conf->get_webdav_documents; + + flash_later('info', t8('The documents have been sent to the printer \'#1\'.', $printer->printer_description)); + $self->redirect_to(action => 'edit', id => $letter->{id}, 'printer_id' => $::form->{printer_id}); + 1; + } or do { + unlink $pdf_file_name; + $::form->error(t8("Creating the PDF failed:") . " " . $@); + }; + +} + +sub action_update { + my ($self, $name_selected) = @_; + + $self->_display( + letter => $self->_update, + ); +} + +sub action_skip_draft { + my ($self) = @_; + $self->action_add(skip_drafts => 1); +} + +sub action_delete_drafts { + my ($self) = @_; + delete_letter_drafts(); + $self->action_add(skip_drafts => 1); +} + +sub _display { + my ($self, %params) = @_; + + my $letter = $self->letter; + + require 'bin/mozilla/io.pl'; + + $params{title} ||= t8('Edit Letter'); + + $::form->{type} = 'letter'; # needed for print_options + $::form->{vc} = 'customer'; # needs to be for _get_contacts... + + $::request->layout->add_javascripts('customer_or_vendor_selection.js'); + $::request->layout->add_javascripts('edit_part_window.js'); + + $::form->{language_id} ||= $params{language_id}; + + $self->render('letter/edit', + %params, + TCF => [ map { key => $_, value => t8(ucfirst $_) }, TEXT_CREATED_FOR_VALUES() ], + PCF => [ map { key => $_, value => t8(ucfirst $_) }, PAGE_CREATED_FOR_VALUES() ], + letter => $letter, + employees => $self->all_employees, + print_options => print_options(inline => 1), + ); +} + +sub _update { + my ($self, %params) = @_; + + my $letter = $self->letter; + + $self->check_date; + $self->set_greetings; + + return $letter; +} + +sub prepare_report { + my ($self) = @_; + + my $report = SL::ReportGenerator->new(\%::myconfig, $::form); + $self->{report} = $report; + + my @columns = qw(date subject letternumber vc_id contact date); + my @sortable = qw(date subject letternumber vc_id contact date); + + my %column_defs = ( + date => { text => t8('Date'), sub => sub { $_[0]->date_as_date } }, + subject => { text => t8('Subject'), sub => sub { $_[0]->subject }, + obj_link => sub { $self->url_for(action => 'edit', 'letter.id' => $_[0]->id, callback => $self->models->get_callback) } }, + letternumber => { text => t8('Letternumber'), sub => sub { $_[0]->letternumber }, + obj_link => sub { $self->url_for(action => 'edit', 'letter.id' => $_[0]->id, callback => $self->models->get_callback) } }, + vc_id => { text => t8('Customer'), sub => sub { $_[0]->customer->displayable_name } }, + contact => { text => t8('Contact'), sub => sub { $_[0]->contact ? $_[0]->contact->full_name : '' } }, + ); + + $column_defs{$_}{text} = $sort_columns{$_} for keys %column_defs; + + $report->set_options( + std_column_visibility => 1, + controller_class => 'Letter', + output_format => 'HTML', + top_info_text => t8('Letters'), + title => t8('Letters'), + allow_pdf_export => 1, + allow_csv_export => 1, + ); + + $report->set_columns(%column_defs); + $report->set_column_order(@columns); + $report->set_export_options(qw(list filter)); + $report->set_options_from_form; + + $self->models->disable_plugin('paginated') if $report->{options}{output_format} =~ /^(pdf|csv)$/i; + $self->models->finalize; + $self->models->set_report_generator_sort_options(report => $report, sortable_columns => \@sortable); + + $report->set_options( + raw_top_info_text => $self->render('letter/report_top', { output => 0 }), + raw_bottom_info_text => $self->render('letter/report_bottom', { output => 0 }, models => $self->models), + attachment_basename => t8('letters_list') . strftime('_%Y%m%d', localtime time), + ); +} + +sub make_filter_summary { + my ($self) = @_; + + my $filter = $::form->{filter} || {}; + my @filter_strings; + + my $employee = $filter->{employee_id} ? SL::DB::Employee->new(id => $filter->{employee_id})->load->name : ''; + my $salesman = $filter->{salesman_id} ? SL::DB::Employee->new(id => $filter->{salesman_id})->load->name : ''; + + my @filters = ( + [ $filter->{"letternumber:substr::ilike"}, t8('Number') ], + [ $filter->{"subject:substr::ilike"}, t8('Subject') ], + [ $filter->{"body:substr::ilike"}, t8('Body') ], + [ $filter->{"date:date::ge"}, t8('From Date') ], + [ $filter->{"date:date::le"}, t8('To Date') ], + [ $employee, t8('Employee') ], + [ $salesman, t8('Salesman') ], + ); + + my %flags = ( + ); + my @flags = map { $flags{$_} } @{ $filter->{part}{type} || [] }; + + for (@flags) { + push @filter_strings, $_ if $_; + } + for (@filters) { + push @filter_strings, "$_->[1]: $_->[0]" if $_->[0]; + } + + $self->{filter_summary} = join ', ', @filter_strings; +} + +sub e_mail { + my $letter = _update(); + + $letter->check_number; + $letter->save; + + $::form->{formname} = "letter"; + $letter->export_to($::form); + + $::form->{id} = $letter->{id}; + edit_e_mail(); +} + +sub load_letter_draft { + my ($self, %params) = @_; + + return 0 if $params{skip_drafts}; + + my $letter_drafts = SL::DB::Manager::LetterDraft->get_all; + + return unless @$letter_drafts; + + $self->render('letter/load_drafts', + title => t8('Letter Draft'), + LETTER_DRAFTS => $letter_drafts, + ); + + return 1; +} + +sub check_date { + my ($self) = @_; + my $letter = $self->letter; + + return unless $letter; + return if $letter->date; + + $letter->date(DateTime->today) +} + +sub check_letter { + my ($self, $letter) = @_; + + $letter ||= $self->letter; + + my $error; + + if (!$letter->subject) { + flash('error', t8('The subject is missing.')); + $error = 1; + } + if (!$letter->body) { + flash('error', t8('The body is missing.')); + $error = 1; + } + if (!$letter->employee_id) { + flash('error', t8('The employee is missing.')); + $error = 1; + } + + return !$error; +} + +sub check_number { + my ($self, $letter) = @_; + + $letter ||= $self->letter; + + return if $letter->letternumber; + + $letter->letternumber(SL::TransNumber->new(type => 'letter', id => $self->{id}, number => $self->{letternumber})->create_unique); +} + +sub set_greetings { + my ($self) = @_; + my $letter = $self->letter; + + return unless $letter; + return if $letter->greeting; + + $letter->greeting(t8('Dear Sir or Madam,')); +} + +sub export_letter_to_form { + my ($self, $letter) = @_; + # nope, not pretty. + + $letter ||= $self->letter; + + for ($letter->meta->columns) { + if ((ref $_) =~ /Date/i) { + $::form->{$_->name} = $letter->$_->to_kivitendo; + } else { + $::form->{$_->name} = $letter->$_; + } + } +} + +sub init_letter { + my ($self) = @_; + + my $letter = SL::DB::Manager::Letter->find_by_or_create(id => $::form->{letter}{id} || 0) + ->assign_attributes(%{ $::form->{letter} }); + + if ($letter->cp_id) { +# $letter->vc_id($letter->contact->cp_cv_id); + # contacts don't have language_id yet +# $letter->greeting(GenericTranslations->get( +# translation_type => 'greetings::' . ($letter->contact->cp_gender eq 'f' ? 'female' : 'male'), +# language_id => $letter->contact->language_id, +# allow_fallback => 1 +# )); + } + + $letter; +} + +sub init_models { + my ($self) = @_; + + SL::Controller::Helper::GetModels->new( + controller => $self, + model => 'Letter', + sorted => { + _default => { + by => 'letternumber', + dir => 1, + }, + %sort_columns, + }, + with_objects => [ 'contact', 'salesman', 'employee' ], + ); +} + +sub init_all_employees { + SL::DB::Manager::Employee->get_all(query => [ deleted => 0 ]); +} + +sub check_auth_edit { + $::auth->assert('sales_letter_edit'); +} + +sub check_auth_report { + $::auth->assert('sales_letter_report'); +} + +1; + +__END__ + +=encoding utf-8 + +=head1 NAME + +SL::Controller::Letter - Letters CRUD and printing + +=head1 DESCRIPTION + +Simple letter CRUD controller with drafting capabilities. + +=head1 TODO + + Customer/Vendor switch for dealing with vendor letters + +copy to webdav is crap + +customer/vendor stuff + +=head1 AUTHOR + +Sven Schöling Es.schoeling@linet-services.deE + +=cut diff --git a/SL/DB/Letter.pm b/SL/DB/Letter.pm index 08657bde4..a7deeaeeb 100644 --- a/SL/DB/Letter.pm +++ b/SL/DB/Letter.pm @@ -6,10 +6,34 @@ package SL::DB::Letter; use strict; use SL::DB::MetaSetup::Letter; +use SL::DB::Manager::Letter; + +__PACKAGE__->meta->add_relationships( + customer => { + type => 'many to one', + class => 'SL::DB::Customer', + column_map => { vc_id => 'id' }, + }, + +); __PACKAGE__->meta->initialize; -# Creates get_all, get_all_count, get_all_iterator, delete_all and update_all. -__PACKAGE__->meta->make_manager_class; +sub new_from_draft { + my ($class, $draft) = @_; + + my $self = $class->new; + + if (!ref $draft) { + require SL::DB::LetterDraft; + $draft = SL::DB::LetterDraft->new(id => $draft)->load; + } + + $self->assign_attributes(map { $_ => $draft->$_ } $draft->meta->columns); + + $self->id(undef); + + $self; +} 1; diff --git a/SL/DB/LetterDraft.pm b/SL/DB/LetterDraft.pm index eb4a4b65f..109010e8f 100644 --- a/SL/DB/LetterDraft.pm +++ b/SL/DB/LetterDraft.pm @@ -12,4 +12,21 @@ __PACKAGE__->meta->initialize; # Creates get_all, get_all_count, get_all_iterator, delete_all and update_all. __PACKAGE__->meta->make_manager_class; +sub new_from_letter { + my ($class, $letter) = @_; + + my $self = $class->new; + + if (!ref $letter) { + require SL::DB::Draft; + $letter = SL::DB::Draft->new(id => $letter)->load; + } + + $self->assign_attributes(map { $_ => $letter->$_ } $letter->meta->columns); + + $self->id(undef); + + $self; +} + 1; diff --git a/SL/DB/Manager/Letter.pm b/SL/DB/Manager/Letter.pm new file mode 100644 index 000000000..8aa2a3445 --- /dev/null +++ b/SL/DB/Manager/Letter.pm @@ -0,0 +1,27 @@ +package SL::DB::Manager::Letter; + +use strict; + +use SL::DB::Helper::Manager; +use base qw(SL::DB::Helper::Manager); + +use SL::DB::Helper::Filtered; +use SL::DB::Helper::Paginated; +use SL::DB::Helper::Sorted; + +sub object_class { 'SL::DB::Letter' } + +__PACKAGE__->make_manager_methods; + +sub _sort_spec { + return ( columns => { SIMPLE => 'ALL', + customer => [ 'lower(customer.name)', ], + }, + default => [ 'date', 1 ], + nulls => { } + ); +} + +sub default_objects_per_page { 15 } + +1; diff --git a/SL/Letter.pm b/SL/Letter.pm deleted file mode 100644 index 1d1b97498..000000000 --- a/SL/Letter.pm +++ /dev/null @@ -1,404 +0,0 @@ -#===================================================================== -# LX-Office ERP -# Copyright (C) 2008 -# Based on SQL-Ledger Version 2.1.9 -# Web http://www.lx-office.org -# -#===================================================================== -# -# Letter module -# -#===================================================================== - -package SL::Letter; - -use strict; -use List::Util qw(max); - -use SL::Common; -use SL::CT; -use SL::DBUtils; -use SL::MoreCommon; -use SL::TransNumber; -use SL::DB::Manager::Customer; - -my $DEFINITION = <{customer_id}; -# -# # resolve customer_obj -#} - -sub new { - my $class = ref $_[0] || $_[0]; shift; - my %params = @_; - my $ref = $_[0]; - - $ref = ref $_[0] eq 'HASH' ? $ref : \%params; # don't like it either... - - my $self = bless $ref, $class; - - $self->_lastname_used; - $self->_resolve_customer; - $self->set_greetings; - - return $self; -} - -sub _create { - my $self = shift; - my $dbh = $::form->get_standard_dbh; - ($self->{id}) = selectfirst_array_query($::form, $dbh, "select nextval('id')"); - - do_query($::form, $dbh, <{id}, $self->{customer_id}); - INSERT INTO letter (id, vc_id) VALUES (?, ?); -SQL -} - -sub _create_draft { - my $self = shift; - my $dbh = $::form->get_standard_dbh; - ($self->{draft_id}) = selectfirst_array_query($::form, $dbh, "select nextval('id')"); - - do_query($::form, $dbh, <{draft_id}, $self->{customer_id}); - INSERT INTO letter_draft (id, vc_id) VALUES (?, ?); -SQL -} - - -sub save { - $::lxdebug->enter_sub; - - my $self = shift; - my %params = @_; - my $dbh = $::form->get_standard_dbh; - my ($table, $update_value); - - if ($params{draft}) { - $self->_create_draft unless $self->{draft_id}; - $table = 'letter_draft'; - $update_value = 'draft_id'; - } else { - $self->_create unless $self->{id}; - $table = 'letter'; - $update_value = 'id'; - } - - my %fields = __PACKAGE__->_get_fields; - my %field_mappings = __PACKAGE__->_get_field_mappings; - - delete $fields{id}; - - my @update_fields = keys %fields; - my $set_clause = join ', ', map { "$_ = ?" } @update_fields; - my @values = map { _escaper($_)->( $self->{ $field_mappings{$_} || $_ } ) } @update_fields, $update_value; - - my $query = "UPDATE $table SET $set_clause WHERE id = ?"; - - do_query($::form, $dbh, $query, @values); - - $dbh->commit; - - $::lxdebug->leave_sub; -} - -sub find { - $::lxdebug->enter_sub; - - my $class = ref $_[0] || $_[0]; shift; - my $myconfig = \%main::myconfig; - my $form = $main::form; - my $dbh = $form->get_standard_dbh($myconfig); - my %params = @_; - my $letter_table = 'letter'; - - $letter_table = 'letter_draft' if $params{draft}; - %params = %$form if !scalar keys %params; - - my (@wheres, @values); - my $add_token = sub { add_token(\@wheres, \@values, @_) }; - - $add_token->(col => 'letter.id', val => $params{id}, esc => 'id' ) if $params{id}; - $add_token->(col => 'letter.letternumber', val => $params{letternumber}, esc => 'substr') if $params{letternumber}; - $add_token->(col => 'vc.name', val => $params{customer}, esc => 'substr') if $params{customer}; - $add_token->(col => 'vc.id', val => $params{customer_id}, esc => 'id' ) if $params{customer_id}; - $add_token->(col => 'letter.cp_id', val => $params{cp_id}, esc => 'id' ) if $params{cp_id}; - $add_token->(col => 'ct.cp_name', val => $params{contact}, esc => 'substr') if $params{contact}; - $add_token->(col => 'letter.subject', val => $params{subject}, esc => 'substr') if $params{subject}; - $add_token->(col => 'letter.body', val => $params{body}, esc => 'substr') if $params{body}; - $add_token->(col => 'letter.date', val => $params{date_from}, method => '>=' ) if $params{date_from}; - $add_token->(col => 'letter.date', val => $params{date_to}, method => '<=' ) if $params{date_to}; - - my $query = qq| - SELECT $letter_table.*, vc.name AS customer, vc.id AS customer_id, ct.cp_name AS contact FROM $letter_table - LEFT JOIN customer vc ON vc.id = $letter_table.vc_id - LEFT JOIN contacts ct ON $letter_table.cp_id = ct.cp_id - |; - - if (@wheres) { - $query .= ' WHERE ' . join ' AND ', @wheres; - } - - my @results = selectall_hashref_query($form, $dbh, $query, @values); - my @objects = map { $class->new($_) } @results; - - $::lxdebug->leave_sub; - - return @objects; -} - -sub delete { - $::lxdebug->enter_sub; - - my $self = shift; - - do_query($::form, $::form->get_standard_dbh, <{id}); - DELETE FROM letter WHERE id = ? -SQL - - $::form->get_standard_dbh->commit; - - $::lxdebug->leave_sub; -} - -sub delete_drafts { - $::lxdebug->enter_sub; - - my $self = shift; - my @draft_ids = @_; - - my $form = $main::form; - my $myconfig = \%main::myconfig; - my $dbh = $form->get_standard_dbh($myconfig); - - - return $main::lxdebug->leave_sub() unless (@draft_ids); - - my $query = qq|DELETE FROM letter_draft WHERE id IN (| . join(", ", map { "?" } @draft_ids) . qq|)|; - do_query($form, $dbh, $query, @draft_ids); - - $dbh->commit; - - $::lxdebug->leave_sub; -} - - -sub check_number { - my $self = shift; - - return if $self->{letternumber} - && $self->{id} - && 1 == scalar __PACKAGE__->find(letternumber => $self->{letternumber}); - - $self->{letternumber} = SL::TransNumber->new(type => 'letter', id => $self->{id}, number => $self->{letternumber})->create_unique; -} - -sub check_name { - my $self = shift; - my %params = @_; - - unless ($params{_name_selected}) { - $::form->{$_} = $self->{$_} for qw(oldcustomer customer selectcustomer customer_id); - - if (::check_name('customer')) { - $self->_set_customer_from($::form); - } - } else { - $self->_set_customer_from($::form); - } -} - -sub _set_customer_from { - my $self = shift; - my $from = shift; - - $self->{$_} = $from->{$_} for qw(oldcustomer customer_id customer selectcustomer); - - $self; -} - -sub check_date { - my $self = shift; - $self->{date} ||= $::form->current_date(\%::myconfig); -} - -sub load { - my $self = shift; - my $table = 'letter'; - my $draft = $self->{draft}; - $table = 'letter_draft' if $draft; - - - return $self unless $self && $self->{id}; # no id? dont load. - - my %mappings = _get_field_mappings(); - my $mapped_select = join ', ', '*', map { "$_ AS $mappings{$_}" } keys %mappings; - - my ($db_letter) = selectfirst_hashref_query($::form, $::form->get_standard_dbh, <{id}); - SELECT $mapped_select FROM $table WHERE id = ? -SQL - - $self->update_from($db_letter); - $self->_resolve_customer; - $self->set_greetings; - $self->{draft_id} = delete $self->{id} if $draft; # set draft if we have one - - return $self; -} - -sub update_from { - my $self = shift; - my $src = shift; - my %fields = $self->_get_fields; - - $fields{$_} = $src->{$_} for qw{customer_id customer selectcustomer oldcustomer}; # customer stuff - - $self->{$_} = $src->{$_} for keys %fields; - - return $self; -} - -sub export_to { - my $self = shift; - my $form = shift; - - my %fields = $self->_get_fields; - my %field_mappings = $self->_get_field_mappings; - - for (keys %fields) { - $form->{$_} = _escaper($_)->( $self->{ $field_mappings{$_} || $_ } ); - } -} - -sub language { - my $self = shift; - die 'not a setter' if @_; - - return unless $self->{cp_id}; - - # umetec/cetaq only! - # contacts have a custom variable called "mailing" - # it contains either a language code or the string "No" - - my $custom_variables = CVar->get_custom_variables( - module => 'Contacts', - name_prefix => 'cp', - trans_id => $self->{cp_id}, - ); - - my ($mailing) = grep { $_->{name} eq 'Mailing' } @$custom_variables; - - return $mailing->{value} eq 'No' ? undef : $mailing->{value}; -} - -sub set_greetings { - $::lxdebug->enter_sub; - - my $self = shift; - return $::lxdebug->leave_sub if $self->{greeting}; - - # automatically set greetings - # greetings depend mainly on contact person -# my $contact = $self->_get_contact; - - $self->{greeting} = $::locale->text('Dear Sir or Madam,'); - - $::lxdebug->leave_sub; -} - -sub _lastname_used { - # wrapper for form lastname_used - # sets customer to last used customer, - # also used to initalize customer for new objects - my $self = shift; - - return if $self->{customer_id}; - - my $saved_form = save_form($::form); - - $::form->lastname_used($::form->get_standard_dbh, \%::myconfig, 'customer'); - - $self->{customer_id} = $::form->{customer_id}; - $self->{customer} = $::form->{customer}; - - restore_form($saved_form); - - return $self; -} - -sub _resolve_customer { - # used if an object is created with only id. - my $self = shift; - - return unless $self->{customer_id} && !$self->{customer}; - -# my ($customer) = CT->find_by_id(cv => 'customer', id => $self->{customer_id}); -# my ($customer) = CT->find_by_id(cv => 'customer', id => $self->{customer_id}); - # SL/CVar.pm: : $cfg->{type} eq 'customer' ? (SL::DB::Manager::Customer->find_by(id => 1*$ref->{number_value}) || SL::DB::Customer->new)->name - $self->{customer} = SL::DB::Manager::Customer->find_by(id => $self->{customer_id})->name; # || SL::DB::Customer->new)->name - - -} - -sub _get_definition { - $DEFINITION; -} - -sub _get_field_mappings { - return ( - vc_id => 'customer_id', - ); -} - -sub _get_fields { - my %fields = _get_definition() =~ /(\w+) \s+ \| \s+ (integer|text|timestamp|numeric|date)/xg; -} - -sub _escaper { - my $field_name = shift; - my %fields = __PACKAGE__->_get_fields; - - for ($fields{$field_name}) { - return sub { conv_i(shift) } if /integer/; - return sub { shift }; - } -} - -1; diff --git a/bin/mozilla/letter.pl b/bin/mozilla/letter.pl deleted file mode 100755 index d9a07423a..000000000 --- a/bin/mozilla/letter.pl +++ /dev/null @@ -1,568 +0,0 @@ -#===================================================================== -# LX-Office ERP -# Copyright (C) 2008 -# Based on SQL-Ledger Version 2.1.9 -# Web http://www.lx-office.org -# -#===================================================================== -# -# Letter module -# -#====================================================================== - -use strict; -use POSIX qw(strftime); - -use SL::GenericTranslations; -use SL::ReportGenerator; -use SL::Letter; -use SL::CT; -use SL::DB::Contact; -use SL::DB::Default; -use SL::Helper::CreatePDF; -use SL::Helper::Flash; -use SL::Common; -use Cwd; -require "bin/mozilla/reportgenerator.pl"; -require "bin/mozilla/io.pl"; -require "bin/mozilla/arap.pl"; - -use constant TEXT_CREATED_FOR_VALUES => (qw(presskit fax letter)); -use constant PAGE_CREATED_FOR_VALUES => (qw(sketch 1 2)); - -our ($form, %myconfig, $locale, $lxdebug); - -# parserhappy(R) -# $locale->text('Presskit') -# $locale->text('Sketch') -# $locale->text('Fax') -# $locale->text('Letter') - -sub add { - $::lxdebug->enter_sub; - - $main::auth->assert('sales_letter_edit'); - my %params = @_; - - return $main::lxdebug->leave_sub if load_letter_draft(); - - my $letter = SL::Letter->new(%params); - - if (my $cp_id = delete $::form->{contact_id}) { - my $contact = SL::DB::Manager::Contact->find_by(cp_id => $cp_id); - $letter->{cp_id} = $contact->cp_id; - $letter->{vc_id} = $contact->cp_cv_id; - $letter->{greeting} = GenericTranslations->get( - translation_type => 'greetings::' . ($contact->{cp_gender} eq 'f' ? 'female' : 'male'), - language_id => $contact->language_id, - allow_fallback => 1 - ); - $params{language_id} = $contact->language_id; - } - - $letter->check_date; - - _display( - letter => $letter, - title => $locale->text('Add Letter'), - language_id => $params{language_id}, - ); - - $::lxdebug->leave_sub; -} - -sub edit { - $::lxdebug->enter_sub; - - $main::auth->assert('sales_letter_edit'); - add() unless ($form->{id}); - - my $letter = SL::Letter->new( id => $form->{id}, draft => $form->{draft} )->load; - - add() unless $letter && ($letter->{id} || $letter->{draft_id}); - - _display( - letter => $letter, - title => $locale->text('Edit Letter'), - ); - - $::lxdebug->leave_sub; -} - -sub save { - $::lxdebug->enter_sub; - - $main::auth->assert('sales_letter_edit'); - my %params = @_; - - - $::form->error(t8('The subject is missing.')) unless $form->{letter}->{subject}; - $::form->error(t8('The body is missing.')) unless $form->{letter}->{body}; - $::form->error(t8('The employee is missing.')) unless $form->{letter}->{employee_id}; - - my $letter = _update(); - - $letter->check_number; - $letter->save; - - $form->{SAVED_MESSAGE} = $locale->text('Letter saved!'); - - _display( - letter => $letter, - ); - - $::lxdebug->leave_sub; -} - -sub save_letter_draft { - $::lxdebug->enter_sub; - - $main::auth->assert('sales_letter_edit'); - - $::form->error(t8('The subject is missing.')) unless $form->{letter}->{subject}; - $::form->error(t8('The body is missing.')) unless $form->{letter}->{body}; - $::form->error(t8('The employee is missing.')) unless $form->{letter}->{employee_id}; - $::form->error(t8('Already as letter saved.')) if $form->{letter}->{letternumber}; - - my $letter_draft = _update(); - $letter_draft->{draft_id} = delete $letter_draft->{id}; # if we have one - $letter_draft->save(draft => '1'); - $letter_draft->{vergiss_mich_nicht} = 'nicht vergessen'; - $form->{SAVED_MESSAGE} = $locale->text('Draft for this Letter saved!'); - - _display( - letter => $letter_draft, - ); - - $::lxdebug->leave_sub; -} - -sub delete { - $main::lxdebug->enter_sub(); - - $main::auth->assert('sales_letter_edit'); - # NYI - $form->{SAVED_MESSAGE} = $locale->text('Not yet implemented!'); - _display(); - - $main::lxdebug->leave_sub(); -} - -sub delete_letter_drafts { - $main::lxdebug->enter_sub(); - - $main::auth->assert('sales_letter_edit'); - - my @ids; - foreach (keys %{$form}) { - push @ids, $1 if (/^checked_(.*)/ && $form->{$_}); - } - - SL::Letter->delete_drafts(@ids) if (@ids); #->{id}); - - add(); - - $main::lxdebug->leave_sub(); -} - -sub _display { - $main::lxdebug->enter_sub(); - - $main::auth->assert('sales_letter_edit'); - my %params = @_; - - my $letter = $params{letter}; - - my %TMPL_VAR; - - $form->{type} = 'letter'; # needed for print_options - $form->{vc} = 'customer'; # needs to be for _get_contacts... - $form->{"$form->{vc}_id"} ||= $letter->{customer_id}; - $form->{jsscript} = 1; - $form->{javascript} = - qq| - |; - - $form->get_lists("contacts" => "ALL_CONTACTS", - "employees" => "ALL_EMPLOYEES", - "salesmen" => "ALL_SALESMEN", - "departments" => "ALL_DEPARTMENTS", - "languages" => "languages", - "customers" => { key => "ALL_CUSTOMERS", - limit => $myconfig{vclimit} + 1 }, - "vc" => 'customer', - ); - - $TMPL_VAR{vc_keys} = sub { "$_[0]->{name}--$_[0]->{id}" }; - $TMPL_VAR{vc_select} = "customer_or_vendor_selection_window('letter.customer', '', 0, 0)"; - $TMPL_VAR{ct_labels} = sub { ($_[0]->{cp_greeting} ? "$_[0]->{cp_greeting} " : '') . $_[0]->{cp_name} . ($_[0]->{cp_givenname} ? ", $_[0]->{cp_givenname}" : '') }; - $TMPL_VAR{TCF} = [ map { key => $_, value => $locale->text(ucfirst $_) }, TEXT_CREATED_FOR_VALUES() ]; - $TMPL_VAR{PCF} = [ map { key => $_, value => $locale->text(ucfirst $_) }, PAGE_CREATED_FOR_VALUES() ]; - - $form->header(); - - $form->{language_id} ||= $params{language_id}; - - print $form->parse_html_template('letter/edit', { - %params, - %TMPL_VAR, - letter => $letter, - print_options => print_options(inline => 1), - }); - - $main::lxdebug->leave_sub(); -} - -sub search { - $lxdebug->enter_sub(); - - $main::auth->assert('sales_letter_report'); - - $form->get_lists("employees" => "EMPLOYEES", - "salesmen" => "SALESMEN", - "customers" => "ALL_CUSTOMERS"); - - $form->{jsscript} = 1; - $form->{title} = $locale->text('Letters'); - - $form->header(); - print $form->parse_html_template('letter/search'); - - $lxdebug->leave_sub(); -} - -sub report { - $lxdebug->enter_sub(); - - $main::auth->assert('sales_letter_report'); - - my %params = @_; - - my @report_params = qw(letternumber subject body contact date_from date_to cp_id); - - if ($form->{selectcustomer}) { - push @report_params, 'customer_id'; - $form->{customer_id} = $form->{customer}; - } else { - push @report_params, 'customer'; - } - - report_generator_set_default_sort('date', 1); - - %params = (%params, map { $_ => $form->{$_} } @report_params); - - my @letters = SL::Letter->find(%params); - - $form->{rowcount} = @letters; - $form->{title} = $locale->text('Letters'); - - my %column_defs = ( - 'date' => { 'text' => $locale->text('Date'), }, - 'subject' => { 'text' => $locale->text('Subject'), }, - 'letternumber' => { 'text' => $locale->text('Letternumber'), }, - 'customer' => { 'text' => $locale->text('Customer') }, - 'contact' => { 'text' => $locale->text('Contact') }, - 'date' => { 'text' => $locale->text('Date') }, - ); - - my @columns = qw(date subject letternumber customer contact date); - my $href = build_std_url('action=report', grep { $form->{$_} } @report_params); - - my @sortable_columns = qw(date subject letternumber customer contact date); - - foreach my $name (@sortable_columns) { - my $sortdir = $form->{sort} eq $name ? 1 - $form->{sortdir} : $form->{sortdir}; - $column_defs{$name}->{link} = $href . "&sort=$name&sortdir=$sortdir"; - } - - my @options; - - # option line - - push @options, $locale->text('Subject') . " : $form->{subject}" if ($form->{subject}); - push @options, $locale->text('Body') . " : $form->{body}" if ($form->{body}); - - my @hidden_report_params = map { +{ 'key' => $_, 'value' => $form->{$_} } } @report_params; - - my $report = SL::ReportGenerator->new(\%myconfig, $form, 'std_column_visibility' => 1); - - $report->set_columns(%column_defs); - $report->set_column_order(@columns); - - $report->set_export_options('report', @report_params); - - $report->set_sort_indicator($form->{sort}, $form->{sortdir}); - - $report->set_options('raw_top_info_text' => $form->parse_html_template('letter/report_top', { 'OPTIONS' => \@options }), - 'raw_bottom_info_text' => $form->parse_html_template('letter/report_bottom', { 'HIDDEN' => \@hidden_report_params }), - 'output_format' => 'HTML', - 'title' => $form->{title}, - 'attachment_basename' => $locale->text('letters_list') . strftime('_%Y%m%d', localtime time), - ); - $report->set_options_from_form(); - - my $idx = 0; - my $callback = build_std_url('action=report', grep { $form->{$_} } @report_params); - my $edit_url = build_std_url('action=edit', 'callback=' . E($callback)); - - foreach my $l (@letters) { - $idx++; - - my $row = { map { $_ => { 'data' => $l->{$_} } } keys %{ $l } }; - - $row->{subject}->{link} = $edit_url . '&id=' . Q($l->{id}); - $row->{letternumber}->{link} = $edit_url . '&id=' . Q($l->{id}); - - $report->add_data($row); - } - - $report->generate_with_headers(); - - $lxdebug->leave_sub(); -} - -sub print_letter { - $lxdebug->enter_sub(); - - $main::auth->assert('sales_letter_edit'); - - my ($old_form) = @_; - - my $display_form = $form->{display_form} || "display_form"; - my $letter = _update(); - - $letter->export_to($form); - $form->{formname} = "letter"; - $form->{format} = "pdf"; - - my $language_saved = $form->{language_id}; - my $greeting_saved = $form->{greeting}; - my $cp_id_saved = $form->{cp_id}; - - call_sub("customer_details"); - - if (!$cp_id_saved) { - # No contact was selected. Delete all contact variables because - # IS->customer_details() and IR->vendor_details() get the default - # contact anyway. - map({ delete($form->{$_}); } grep(/^cp_/, keys(%{ $form }))); - } - - $form->{greeting} = $greeting_saved; - $form->{language_id} = $language_saved; - - if ($form->{cp_id}) { - CT->get_contact(\%myconfig, $form); - } - - $form->{cp_contact_formal} = ($form->{cp_greeting} ? "$form->{cp_greeting} " : '') . ($form->{cp_givenname} ? "$form->{cp_givenname} " : '') . $form->{cp_name}; - - $form->get_employee_data('prefix' => 'employee', 'id' => $letter->{employee_id}); - $form->get_employee_data('prefix' => 'salesman', 'id' => $letter->{salesman_id}); - - my %create_params = ( - template => scalar(SL::Helper::CreatePDF->find_template( - name => 'letter', - printer_id => $::form->{printer_id}, - language_id => $::form->{language_id}, - formname => 'letter', - format => 'pdf', - )), - variables => $::form, - return => 'file_name', - ); - my $pdf_file_name; - eval { - # catch LaTeX template not found error - my $tex_templates = $::instance_conf->get_templates . '/letter.tex'; - die( t8('Please create/copy a template named letter.tex in your client template dir') ) unless (-e $tex_templates); - - $pdf_file_name = SL::Helper::CreatePDF->create_pdf(%create_params); - - # set some form defaults for printing webdav copy variables - $form->{tmpfile} = $pdf_file_name; - $form->{tmpdir} = 'users'; - $form->{type} = 'letter'; - $form->{cwd} = getcwd(); - if ( $::form->{media} eq 'email') { - my $mail = Mailer->new; - my $signature = $::myconfig{signature}; - $mail->{$_} = $::form->{$_} for qw(cc subject message bcc to); - $mail->{from} = qq|"$::myconfig{name}" <$::myconfig{email}>|; - $mail->{fileid} = time() . '.' . $$ . '.'; - $mail->{attachments} = [{ "filename" => $pdf_file_name, - "name" => $::form->{attachment_name} }]; - $mail->{message} .= "\n-- \n$signature"; - $mail->{message} =~ s/\r//g; - - # copy_file_to_webdav was already done via io.pl -> edit_e_mail - my $err = $mail->send; - # TODO - # $self - # ->js - # ->flash($err?'error':'info', - # $err?t8('A mail error occurred: #1', $err): - # t8('The document have been sent to \'#1\'.', $mail->{to})) - # ->render($self); - return $err?0:1; - } - - if (!$::form->{printer_id} || $::form->{media} eq 'screen') { - - my $file = IO::File->new($pdf_file_name, 'r') || croak("Cannot open file '$pdf_file_name'"); - my $size = -s $pdf_file_name; - my $content_type = 'application/pdf'; - my $attachment_name = $::form->generate_attachment_filename; - $attachment_name =~ s:.*//::g; - - print $::form->create_http_response(content_type => $content_type, - content_disposition => 'attachment; filename="' . $attachment_name . '"', - content_length => $size); - - $::locale->with_raw_io(\*STDOUT, sub { print while <$file> }); - $file->close; - Common::copy_file_to_webdav_folder($form) if $::instance_conf->get_webdav_documents; - unlink $pdf_file_name; - return 1; - } - - my $printer = SL::DB::Printer->new(id => $::form->{printer_id})->load; - my $command = SL::Template::create(type => 'ShellCommand', form => Form->new(''))->parse($printer->printer_command); - - open my $out, '|-', $command or die $!; - binmode $out; - print $out scalar(read_file($pdf_file_name)); - close $out; - Common::copy_file_to_webdav_folder($form) if $::instance_conf->get_webdav_documents; - - flash_later('info', t8('The documents have been sent to the printer \'#1\'.', $printer->printer_description)); - my $callback = build_std_url('letter.pl', 'action=edit', 'id=' . $letter->{id}, 'printer_id'); - $::form->redirect; - 1; - } or do { - unlink $pdf_file_name; - $::form->error(t8("Creating the PDF failed:") . " " . $@); - }; - - $lxdebug->leave_sub(); -} - -sub update { - $::lxdebug->enter_sub; - - $main::auth->assert('sales_letter_edit'); - - my $name_selected = shift; - - _display( - letter => _update( - _name_selected => $name_selected, - ), - ); - - $::lxdebug->leave_sub; -} - -sub _update { - $::lxdebug->enter_sub; - - $main::auth->assert('sales_letter_edit'); - - my %params = @_; - - my $from_letter = $::form->{letter}; - - my $letter = SL::Letter->new( id => $from_letter->{id} ) - ->load - ->update_from($from_letter); - - $letter->check_name(%params); - $letter->check_date; - $letter->set_greetings; - - $::lxdebug->leave_sub; - - return $letter; -} - -sub letter_tab { - $::lxdebug->enter_sub; - - $main::auth->assert('sales_letter_edit'); - - my @report_params = qw(letternumber subject contact date); - - my @letters = SL::Letter->find(map { $_ => $form->{$_} } @report_params); - - $::lxdebug->leave_sub; -} - -sub e_mail { - $::lxdebug->enter_sub; - - $main::auth->assert('sales_letter_edit'); - my $letter = _update(); - - $letter->check_number; - $letter->save; - - $form->{formname} = "letter"; - $letter->export_to($::form); - - $::form->{id} = $letter->{id}; - edit_e_mail(); - - $::lxdebug->leave_sub; -} - -sub dispatcher { - $main::lxdebug->enter_sub(); - # dispatch drafts - my $locale = $main::locale; - - - if ($form->{letter_draft_action} eq $locale->text("Skip")) { - $form->{DONT_LOAD_DRAFT} = 1; - add(); - return 1; - } elsif ($form->{letter_draft_action} eq $locale->text("Delete drafts")) { - delete_letter_drafts(); - return 1; - } - - foreach my $action (qw(e_mail print save update save_letter_draft)) { - if ($::form->{"action_${action}"}) { - $::form->{dispatched_action} = $action; - call_sub($action); - return; - } - } - - $::form->error($::locale->text('No action defined.')); - $::lxdebug->leave_sub; -} - -sub continue { - call_sub($form->{nextsub}); -} - - -sub load_letter_draft { - $lxdebug->enter_sub(); - - $main::auth->assert('sales_letter_edit'); - $main::lxdebug->leave_sub() and return 0 if ($form->{DONT_LOAD_DRAFT}); - $form->{title} = $locale->text('Letter Draft'); - $form->{script} = 'letter.pl'; - - my @letter_drafts = SL::Letter->find(draft => 1); - - return unless @letter_drafts; - $form->header(); - print $form->parse_html_template('letter/load_drafts', { LETTER_DRAFTS => \@letter_drafts }); - - return 1; - $lxdebug->leave_sub(); -} - -1; diff --git a/locale/de/all b/locale/de/all index 4c1a5e4f2..7b5b17589 100755 --- a/locale/de/all +++ b/locale/de/all @@ -246,6 +246,7 @@ $self->{texts} = { 'Amount less skonto' => 'Betrag abzgl. Skonto', 'Amount payable' => 'Noch zu bezahlender Betrag', 'Amount payable less discount' => 'Noch zu bezahlender Betrag abzüglich Skonto', + 'An error occured. Letter could not be deleted.' => 'Es ist ein Fehler aufgetreten. Der Brief konnte nicht gelöscht werden.', 'An exception occurred during execution.' => 'Während der Ausführung trat eine Ausnahme auf.', 'An invalid character was used (invalid characters: #1).' => 'Ein ungültiges Zeichen wurde benutzt (ungültige Zeichen: #1).', 'An invalid character was used (valid characters: #1).' => 'Ein ungültiges Zeichen wurde benutzt (gültige Zeichen: #1).', @@ -272,6 +273,7 @@ $self->{texts} = { 'Are you sure you want to delete this business?' => 'Sind Sie sicher, dass Sie diesen Kunden-/Lieferantentyp löschen wollen?', 'Are you sure you want to delete this delivery term?' => 'Wollen Sie diese Lieferbedingungen wirklich löschen?', 'Are you sure you want to delete this department?' => 'Sind Sie sicher, dass Sie diese Abteilung löschen wollen?', + 'Are you sure you want to delete this letter?' => 'Sind Sie sicher, dass Sie diesen Brief löschen wollen?', 'Are you sure you want to delete this payment term?' => 'Wollen Sie diese Zahlungsbedingungen wirklich löschen?', 'Are you sure you want to remove the marked entries from the queue?' => 'Sind Sie sicher, dass die markierten Einträge von der Warteschlange gelöscht werden sollen?', 'Are you sure you want to update the prices' => 'Sind Sie sicher, dass Sie die Preise aktualisieren wollen?', @@ -1533,6 +1535,7 @@ $self->{texts} = { 'Left' => 'Links', 'Letter' => 'Brief', 'Letter Draft' => 'Briefentwurf', + 'Letter deleted' => 'Brief gelöscht', 'Letter saved!' => 'Brief gespeichert!', 'Letternumber' => 'Briefnummer', 'Letters' => 'Briefe', @@ -2954,6 +2957,8 @@ $self->{texts} = { 'There is one or more sections for which no part has been assigned yet; therefore creating the new record is not possible yet.' => 'Es gibt einen oder mehrere Abschnitte ohne Artikelzuweisung; daher kann der neue Beleg noch nicht erstellt werden.', 'There was an error executing the background job.' => 'Bei der Ausführung des Hintergrund-Jobs trat ein Fehler auf.', 'There was an error parsing the csv file: #1 in line #2: #3' => 'Es gab einen Fehler beim Parsen der CSV Datei: "#1" in der Zeile "#2": "#3"', + 'There was an error saving the letter' => 'Ein Fehler ist aufgetreten. Der Brief konnte nicht gespeichert werden.', + 'There was an error saving the letter draft' => 'Ein Fehler ist aufgetreten. Der Briefentwurf konnte nicht gespeichert werden.', 'There you can let kivitendo create the basic tables for you, even in an already existing database.' => 'Dort können Sie kivitendo diese grundlegenden Tabellen erstellen lassen, selbst in einer bereits existierenden Datenbank.', 'Therefore several settings that had to be made for each user in the past have been consolidated into the client configuration.' => 'Dazu wurden gewisse Einstellungen, die vorher bei jedem Benutzer vorgenommen werden mussten, in die Konfiguration eines Mandanten verschoben.', 'Therefore the definition of "kg" with the base unit "g" and a factor of 1000 is valid while defining "g" with a base unit of "kg" and a factor of "0.001" is not.' => 'So ist die Definition von "kg" mit der Basiseinheit "g" und dem Faktor 1000 zulässig, die Definition von "g" mit der Basiseinheit "kg" und dem Faktor "0,001" hingegen nicht.', diff --git a/menus/user/00-erp.yaml b/menus/user/00-erp.yaml index f693a0f16..052853a77 100644 --- a/menus/user/00-erp.yaml +++ b/menus/user/00-erp.yaml @@ -262,9 +262,8 @@ name: Add Letter order: 800 access: sales_letter_edit - module: letter.pl params: - action: add + action: Letter/add - parent: ar id: ar_invoices name: Invoices @@ -376,9 +375,8 @@ name: Letters order: 1100 access: sales_letter_report - module: letter.pl params: - action: search + action: Letter/list - id: ap name: AP icon: ap diff --git a/templates/webpages/letter/edit.html b/templates/webpages/letter/edit.html index 5d6aebfde..1e84de808 100644 --- a/templates/webpages/letter/edit.html +++ b/templates/webpages/letter/edit.html @@ -1,193 +1,150 @@ [%- USE HTML %] [%- USE T8 %] [%- USE L %] -

[% title %]

- -
+[%- USE P %] +[%- USE LxERP %] +

[% title | html %]

+ - - + - + [%- PROCESS 'common/flash.html' %] -

- - [%- IF SAVED_MESSAGE %] - - - - - [%- END %] - - + + + + + + + +
[% SAVED_MESSAGE %]
- - - - - + + - + - - + + + +
[% 'Customer' | $T8 %]: - [%- INCLUDE 'generic/multibox.html' - name = 'letter.customer', - style = 'width:60%', - DATA = ALL_CUSTOMERS, - id_sub = 'vc_keys', - label_key = 'name', - select = vc_select, - limit = MYCONFIG.vclimit, - allow_textbox = 1, - force_textbox = limit_exceeded_all_customer - onChange = "document.getElementById('update_button').click();" -%] + + + - - + + + + + + + + + + +
+ + + + + - - - - - - - - -
[% 'Customer' | $T8 %]:[% P.customer_vendor_picker('letter.vc_id', letter.vc_id, type='customer') %] [%- IF letter.customer_id %] - -[%- END %] - - - -[%- UNLESS MYCONFIG.vclimit < ALL_CUSTOMERS.size %] - + [%- END %] -
[% 'Contact Person' | $T8 %] - [%- INCLUDE 'generic/multibox.html' - name = 'letter.cp_id', - style = 'width:100%', - DATA = ALL_CONTACTS, - id_key = 'cp_id', - label_sub = 'ct_labels', - show_empty = 1 -%] -
[% 'Your Reference' | $T8 %]:
- -
- - - - - - - - - - - -
[% 'Letternumber' | $T8 %]:
[% 'Date' | $T8 %]:[% L.date_tag('letter.date', letter.date, readonly=readonly) %]
- -
[% 'Contact Person' | $T8 %][% L.select_tag('letter.cp_id', letter.cp_id ? letter.customer.contacts : [], value_key='cp_id', title_key='full_name', default=letter.cp_id) %]
[% 'Your Reference' | $T8 %]:
+ +
+ + + + + + + + + + + +
[% 'Letternumber' | $T8 %]:
[% 'Date' | $T8 %]:[% L.date_tag('letter.date_as_date', letter.date_as_date, readonly=readonly) %]
+ +
- - - - - - - - - - - - - - - - - - + + - - - - - - - -
[% 'Subject' | $T8 %]
[% 'Greeting' | $T8 %]
[% 'Body' | $T8 %]
[% 'Internal Notes' | $T8 %]
+ + + + + + + + + + + + + + + + + + - - - - -
[% 'Subject' | $T8 %]
[% 'Greeting' | $T8 %]
[% 'Body' | $T8 %]
[% 'Internal Notes' | $T8 %]
- - - - - - -
- - - - - - - - -
[% 'Employee' | $T8 %]
- [%- INCLUDE 'generic/multibox.html' - name = 'letter.employee_id', - default = letter.employee_id, - style = 'width:70%;font-weight:bold', - DATA = ALL_EMPLOYEES, - id_key = 'id', - label_key = 'name', - limit = vclimit, - show_empty = 1, - allow_textbox = 0, - force_textbox = limit_exceeded_ALL_EMPLOYEES - onChange = "document.getElementById('update_button').click();" -%] -
-
- - - - - - - -
[% 'Salesman' | $T8 %]
- [%- INCLUDE 'generic/multibox.html' - name = 'letter.salesman_id', - default = letter.salesman_id, - style = 'width:70%;font-weight:bold', - DATA = ALL_SALESMEN, - id_key = 'id', - label_key = 'name', - limit = vclimit, - show_empty = 1, - allow_textbox = 0, - force_textbox = limit_exceeded_ALL_SALESMAN - onChange = "document.getElementById('update_button').click();" -%] -
-
-
-
- -

- [% print_options %] -
-

+
+ + + + + + +
+ + + + + + + +
[% 'Employee' | $T8 %]
+ [%- L.select_tag('letter.employee_id', employees, default=letter.employee_id, title_key='safe_name', class='bold', allow_empty=1, style='width:70%') %] +
+
+ + + + + + + +
[% 'Salesman' | $T8 %]
+ [%- L.select_tag('letter.salesman_id', employees, default=letter.salesman_id, title_key='safe_name', class='bold', allow_empty=1, style='width:70%') %] +
+
+
+
+ +

+ [% print_options %] +
- + [%- IF letter.letternumber %] - + [% END %] +[% L.submit_tag('action_delete', LxERP.t8('Delete'), confirm=LxERP.t8('Are you sure you want to delete this letter?')) %] -

+ + + + diff --git a/templates/webpages/letter/load_drafts.html b/templates/webpages/letter/load_drafts.html index 78c04cd80..ceb1d5427 100644 --- a/templates/webpages/letter/load_drafts.html +++ b/templates/webpages/letter/load_drafts.html @@ -2,11 +2,9 @@ [%- USE HTML %]

[% 'Load letter draft' | $T8 %]

-
+ +

[% 'The following drafts have been saved and can be loaded.' | $T8 %]

- - @@ -22,19 +20,19 @@ [% FOREACH row = LETTER_DRAFTS %] - - - + + + [% END %]
- [% 'The following drafts have been saved and can be loaded.' | $T8 %]
[% HTML.escape(row.date) %][% HTML.escape(row.subject) %][% HTML.escape(row.customer) %][% row.date | html %][% row.subject | html %][% row.customer | html %]
- - - - + + + + diff --git a/templates/webpages/letter/report_top.html b/templates/webpages/letter/report_top.html index 548c4ed04..b5ad9a531 100644 --- a/templates/webpages/letter/report_top.html +++ b/templates/webpages/letter/report_top.html @@ -1,10 +1,4 @@ -[%- IF OPTIONS.size %] -

- [%- FOREACH option = OPTIONS %] - [%- option %][% UNLESS loop.last %]
[% END %] - [%- END %] -

-[%- END %] +[%- PROCESS 'letter/search.html' filter=SELF.models.filtered.laundered %] +
- diff --git a/templates/webpages/letter/search.html b/templates/webpages/letter/search.html index 365e7e7d8..4d12934f2 100644 --- a/templates/webpages/letter/search.html +++ b/templates/webpages/letter/search.html @@ -1,65 +1,57 @@ [% USE HTML %] [% USE T8 %] [% USE L %] -

[% title %]

+[% USE LxERP %] + - - +
+[% 'Show Filter' | $T8 %] + [% SELF.filter_summary | html %] +
+
+ +