use SL::Util qw(trim);
use SL::YAML;
use SL::DB::AdditionalBillingAddress;
+use SL::DB::AuthUser;
use SL::DB::History;
use SL::DB::Order;
use SL::DB::Default;
my $groupitems = $::form->{print_options}->{groupitems};
my $printer_id = $::form->{print_options}->{printer_id};
- # only pdf and opendocument by now
- if (none { $format eq $_ } qw(pdf opendocument opendocument_pdf)) {
+ # only PDF, OpenDocument & HTML for now
+ if (none { $format eq $_ } qw(pdf opendocument opendocument_pdf html)) {
return $self->js->flash('error', t8('Format \'#1\' is not supported yet/anymore.', $format))->render;
}
$form->{format} = $format;
$form->{formname} = $formname;
$form->{language} = '_' . $self->order->language->template_code if $self->order->language;
- my $pdf_filename = $form->generate_attachment_filename();
+ my $doc_filename = $form->generate_attachment_filename();
- my $pdf;
- my @errors = $self->generate_pdf(\$pdf, { format => $format,
+ my $doc;
+ my @errors = $self->generate_doc(\$doc, { format => $format,
formname => $formname,
language => $self->order->language,
printer_id => $printer_id,
groupitems => $groupitems });
if (scalar @errors) {
- return $self->js->flash('error', t8('Conversion to PDF failed: #1', $errors[0]))->render;
+ return $self->js->flash('error', t8('Generating the document failed: #1', $errors[0]))->render;
}
if ($media eq 'screen') {
# screen/download
- $self->js->flash('info', t8('The PDF has been created'));
+ $self->js->flash('info', t8('The document has been created.'));
$self->send_file(
- \$pdf,
- type => SL::MIME->mime_type_from_ext($pdf_filename),
- name => $pdf_filename,
+ \$doc,
+ type => SL::MIME->mime_type_from_ext($doc_filename),
+ name => $doc_filename,
js_no_render => 1,
);
my $printer_id = $::form->{print_options}->{printer_id};
SL::DB::Printer->new(id => $printer_id)->load->print_document(
copies => $copies,
- content => $pdf,
+ content => $doc,
);
- $self->js->flash('info', t8('The PDF has been printed'));
+ $self->js->flash('info', t8('The document has been printed.'));
}
- my @warnings = $self->store_pdf_to_webdav_and_filemanagement($pdf, $pdf_filename);
+ my @warnings = $self->store_doc_to_webdav_and_filemanagement($doc, $doc_filename);
if (scalar @warnings) {
$self->js->flash('warning', $_) for @warnings;
}
my $pdf_filename = $form->generate_attachment_filename();
my $pdf;
- my @errors = $self->generate_pdf(\$pdf, { format => $format,
+ my @errors = $self->generate_doc(\$pdf, { format => $format,
formname => $formname,
language => $self->order->language,
});
$email_form->{js_send_function} = 'kivi.Order.send_email()';
my %files = $self->get_files_for_email_dialog();
- $self->{all_employees} = SL::DB::Manager::Employee->get_all(query => [ deleted => 0 ]);
+
+ my @employees_with_email = grep {
+ my $user = SL::DB::Manager::AuthUser->find_by(login => $_->login);
+ $user && !!trim($user->get_config_value('email'));
+ } @{ SL::DB::Manager::Employee->get_all_sorted(query => [ deleted => 0 ]) };
+
my $dialog_html = $self->render('common/_send_email_dialog', { output => 0 },
- email_form => $email_form,
- show_bcc => $::auth->assert('email_bcc', 'may fail'),
- FILES => \%files,
- is_customer => $self->cv eq 'customer',
- ALL_EMPLOYEES => $self->{all_employees},
+ email_form => $email_form,
+ show_bcc => $::auth->assert('email_bcc', 'may fail'),
+ FILES => \%files,
+ is_customer => $self->cv eq 'customer',
+ ALL_EMPLOYEES => \@employees_with_email,
);
$self->js
$::form->{media} = 'email';
if (($::form->{attachment_policy} // '') !~ m{^(?:old_file|no_file)$}) {
- my $pdf;
- my @errors = $self->generate_pdf(\$pdf, {media => $::form->{media},
+ my $doc;
+ my @errors = $self->generate_doc(\$doc, {media => $::form->{media},
format => $::form->{print_options}->{format},
formname => $::form->{print_options}->{formname},
language => $self->order->language,
printer_id => $::form->{print_options}->{printer_id},
groupitems => $::form->{print_options}->{groupitems}});
if (scalar @errors) {
- return $self->js->flash('error', t8('Conversion to PDF failed: #1', $errors[0]))->render($self);
+ return $self->js->flash('error', t8('Generating the document failed: #1', $errors[0]))->render($self);
}
- my @warnings = $self->store_pdf_to_webdav_and_filemanagement($pdf, $::form->{attachment_filename});
+ my @warnings = $self->store_doc_to_webdav_and_filemanagement($doc, $::form->{attachment_filename});
if (scalar @warnings) {
flash_later('warning', $_) for @warnings;
}
my $sfile = SL::SessionFile::Random->new(mode => "w");
- $sfile->fh->print($pdf);
+ $sfile->fh->print($doc);
$sfile->fh->close;
$::form->{tmpfile} = $sfile->file_name;
}
$::form->{id} = $self->order->id; # this is used in SL::Mailer to create a linked record to the mail
- $::form->send_email(\%::myconfig, 'pdf');
+ $::form->send_email(\%::myconfig, $::form->{print_options}->{format});
# internal notes
my $intnotes = $self->order->intnotes;
no_queue => 1,
no_postscript => 1,
no_opendocument => 0,
- no_html => 1},
+ no_html => 0},
);
foreach my $item (@{$self->order->orderitems}) {
$self->get_item_cvpartnumber($_) for @{$self->order->items_sorted};
- $::request->{layout}->use_javascript("${_}.js") for qw(kivi.SalesPurchase kivi.Order kivi.File ckeditor/ckeditor ckeditor/adapters/jquery
- edit_periodic_invoices_config calculate_qty kivi.Validator follow_up show_history);
+ $::request->{layout}->use_javascript("${_}.js") for qw(kivi.Validator kivi.SalesPurchase kivi.Order kivi.File ckeditor/ckeditor ckeditor/adapters/jquery
+ edit_periodic_invoices_config calculate_qty follow_up show_history);
$self->setup_edit_action_bar;
}
}
}
-sub generate_pdf {
- my ($self, $pdf_ref, $params) = @_;
+sub generate_doc {
+ my ($self, $doc_ref, $params) = @_;
my $order = $self->order;
my @errors = ();
if ($print_form->{format} =~ /(opendocument|oasis)/i) {
$template_ext = 'odt';
$template_type = 'OpenDocument';
+ } elsif ($print_form->{format} =~ m{html}i) {
+ $template_ext = 'html';
+ $template_type = 'HTML';
}
# search for the template
eval {
$print_form->prepare_for_printing;
- $$pdf_ref = SL::Helper::CreatePDF->create_pdf(
+ $$doc_ref = SL::Helper::CreatePDF->create_pdf(
format => $print_form->{format},
template_type => $template_type,
template => $template_file,
longdescription => 'html',
partnotes => 'html',
notes => 'html',
+ $::form->get_variable_content_types_for_cvars,
},
);
1;
)->save;
}
-sub store_pdf_to_webdav_and_filemanagement {
+sub store_doc_to_webdav_and_filemanagement {
my ($self, $content, $filename) = @_;
my $order = $self->order;
$webdav_file->store(data => \$content);
1;
} or do {
- push @errors, t8('Storing PDF to webdav folder failed: #1', $@);
+ push @errors, t8('Storing the document to the WebDAV folder failed: #1', $@);
};
}
if ($order->id && $::instance_conf->get_doc_storage) {
eval {
SL::File->save(object_id => $order->id,
object_type => $order->type,
- mime_type => 'application/pdf',
+ mime_type => SL::MIME->mime_type_from_ext($filename),
source => 'created',
file_type => 'document',
file_name => $filename,
file_contents => $content);
1;
} or do {
- push @errors, t8('Storing PDF in storage backend failed: #1', $@);
+ push @errors, t8('Storing the document in the storage backend failed: #1', $@);
};
}
use SL::DBUtils;
use SL::DB::AdditionalBillingAddress;
use SL::DB::Customer;
+ use SL::DB::CustomVariableConfig;
use SL::DB::Default;
use SL::DB::PaymentTerm;
use SL::DB::Vendor;
}
sub get_variable_content_types {
- my %html_variables = (
- longdescription => 'html',
- partnotes => 'html',
- notes => 'html',
- orignotes => 'html',
- notes1 => 'html',
- notes2 => 'html',
- notes3 => 'html',
- notes4 => 'html',
- header_text => 'html',
- footer_text => 'html',
+ my ($self) = @_;
+
+ my %html_variables = (
+ longdescription => 'html',
+ partnotes => 'html',
+ notes => 'html',
+ orignotes => 'html',
+ notes1 => 'html',
+ notes2 => 'html',
+ notes3 => 'html',
+ notes4 => 'html',
+ header_text => 'html',
+ footer_text => 'html',
);
- return \%html_variables;
+
+ return {
+ %html_variables,
+ $self->get_variable_content_types_for_cvars,
+ };
+ }
+
+ sub get_variable_content_types_for_cvars {
+ my ($self) = @_;
+ my $html_configs = SL::DB::Manager::CustomVariableConfig->get_all(where => [ type => 'htmlfield' ]);
+ my %types;
+
+ if (@{ $html_configs }) {
+ my %prefix_by_module = (
+ Contacts => 'cp_cvar_',
+ CT => 'vc_cvar_',
+ IC => 'ic_cvar_',
+ Projects => 'project_cvar_',
+ ShipTo => 'shiptocvar_',
+ );
+
+ foreach my $cfg (@{ $html_configs }) {
+ my $prefix = $prefix_by_module{$cfg->module};
+ $types{$prefix . $cfg->name} = 'html' if $prefix;
+ }
+ }
+
+ return %types;
}
sub current_date {
qq|SELECT h.employee_id, h.itime::timestamp(0) AS itime, h.addition, h.what_done, emp.name, h.snumbers, h.trans_id AS id | .
qq|FROM history_erp h | .
qq|LEFT JOIN employee emp ON (emp.id = h.employee_id) | .
- qq|WHERE (trans_id = | . $trans_id . qq|) $restriction | .
+ qq|WHERE (trans_id = | . $dbh->quote($trans_id) . qq|) $restriction | .
$order;
my $sth = $dbh->prepare($query) || $self->dberror($query);
'CSV Export successful!' => 'CSV-Export erfolgreich!',
'CSV export' => 'CSV-Export',
'CSV export -- options' => 'CSV-Export -- Optionen',
+ 'CSV import: additional billing addresses' => 'CSV-Import: zusätzliche Rechnungsadressen',
'CSV import: ar transactions' => 'CSV Import: Debitorenbuchungen',
'CSV import: bank transactions' => 'CSV Import: Bankbewegungen',
'CSV import: contacts' => 'CSV-Import: Ansprechpersonen',
'Created for' => 'Erstellt für',
'Created on' => 'Erstellt am',
'Creating Documents' => 'Erzeuge Dokumente',
+ 'Creating Factur-X/ZUGFeRD invoices is not enabled for this customer.' => 'Das Erzeugen von Factur-X/ZUGFeRD-Rechnungen ist für diesen Kunden nicht aktiviert.',
'Creating invoices' => 'Erzeuge Rechnungen',
'Creating the PDF failed:' => 'PDF-Erzeugung fehlgeschlagen:',
'Creation Date' => 'Erstelldatum',
'Default Transfer with services' => 'Ein- /Auslagern von Dienstleistungen über Standard-Lagerplatz',
'Default Warehouse' => 'Standard-Lager',
'Default Warehouse with ignoring onhand' => 'Standard-Lager für Auslagern ohne Prüfung auf Bestand',
+ 'Default address flag' => 'Standard-Adresse-Schalter',
'Default article for converting into quotations and orders' => 'Standardartikel für Konvertierung von Pflichtenheften in Angebote und Aufträge',
'Default booking group' => 'Standardbuchungsgruppe',
'Default client' => 'Standardmandant',
'Extended status' => 'Erweiterter Status',
'Extension Of Time' => 'Dauerfristverlängerung',
'Factor' => 'Faktor',
+ 'Factur-X/ZUGFeRD' => 'Factur-X/ZUGFeRD',
'Factur-X/ZUGFeRD import' => 'Factur-X-/ZUGFeRD-Import',
'Factur-X/ZUGFeRD invoice' => 'Factur-X-/ZUGFeRD-Rechnung',
'Factur-X/ZUGFeRD notes for each invoice' => 'Factur-X-/ZUGFeRD-Notizen für jede Rechnung',
'General ledger transactions can only be changed on the day they are posted.' => 'Dialogbuchungen können nur am Buchungstag geändert werden.',
'General settings' => 'Allgemeine Einstellungen',
'Generate and print sales delivery orders' => 'Erzeuge und drucke Lieferscheine',
+ 'Generating the document failed: #1' => 'Das Dokument konnte nicht erzeugt werden: #1',
'Germany' => 'Deutschland',
'Get one order' => 'Hole eine Bestellung',
'Get one order by shopordernumber' => 'Hole eine Bestellung über Shopbestellnummer',
'Groups valid for this client' => 'Für Mandanten gültige Gruppen',
'HTML' => 'HTML',
'HTML Templates' => 'HTML-Vorlagen',
+ 'HTML field' => 'HTML-Feld',
'Handling of WebDAV' => 'Behandlung von WebDAV',
'Hardcopy' => 'Seite drucken',
'Has item type' => 'Hat Regeltypen',
'Lastcost' => 'Einkaufspreis',
'Lastcost (with X being a number)' => 'Einkaufspreis (X ist eine fortlaufende Zahl)',
'Lastname' => 'Nachname',
+ 'Leading and trailing whitespaces have been removed.' => 'Leerzeichen wurden vorne und hinten entfernt',
'Left' => 'Links',
'Letter' => 'Brief',
'Letter Draft' => 'Briefentwurf',
'Storage Type for shopimages' => 'Speichertyp für Shopbilder',
'Storing PDF in storage backend failed: #1' => 'Speichern der PDF-Datei im Datei-Speicher fehlgeschlagen: #1',
'Storing PDF to webdav folder failed: #1' => 'Speichern der PDF im WebDAV Ordner fehlgeschlagen: #1',
+ 'Storing the document in the storage backend failed: #1' => 'Das Ablegen des Dokuments im Dokumentenspeicher schlug fehl: #1',
+ 'Storing the document to the WebDAV folder failed: #1' => 'Das Ablegen des Dokuments im WebDAV-Ordner schlug fehl: #1',
'Storing the emails in the journal is currently disabled in the client configuration.' => 'Das Speichern von versendeten E-Mails ist derzeit in der Mandantenkonfigurierung abgeschaltet.',
'Storno' => 'Storno',
'Storno (one letter abbreviation)' => 'S',
'Text blocks back' => 'Textblöcke hinten',
'Text blocks front' => 'Textblöcke vorne',
'Text field' => 'Textfeld',
- 'Text field variables: \'WIDTH=w HEIGHT=h\' sets the width and height of the text field. They default to 30 and 5 respectively.' => 'Textfelder: \'WIDTH=w HEIGHT=h\' setzen die Breite und die Höhe des Textfeldes. Wenn nicht anders angegeben, so werden sie 30 Zeichen breit und fünf Zeichen hoch dargestellt.',
+ 'Text field and HTML field variables: \'WIDTH=w HEIGHT=h\' sets the width and height of the field in pixels. They default to 225 and 90 respectively.' => 'Textfelder und HTML-Felder: \'WIDTH=w HEIGHT=h\' setzen die Breite und die Höhe des Feldes in Pixeln. Wenn nicht anders angegeben, so werden sie 225 Pixel breit und 90 Pixel hoch dargestellt.',
'Text in CSV File' => 'Spalte in der CSV Datei',
'Text variables: \'MAXLENGTH=n\' sets the maximum entry length to \'n\'.' => 'Textzeilen: \'MAXLENGTH=n\' setzt eine Maximallänge von n Zeichen.',
- 'Text, text field and number variables: The default value will be used as-is.' => 'Textzeilen, Textfelder und Zahlenvariablen: Der Standardwert wird so wie er ist übernommen.',
+ 'Text, text field, HTML field and number variables: The default value will be used as-is.' => 'Textzeilen, Textfelder, HTML-Felder und Zahlenvariablen: Der Standardwert wird so wie er ist übernommen.',
'Texts for invoices' => 'Texte für Rechnungen',
'Texts for quotations & orders' => 'Texte für Angebote & Aufträge',
'That export does not exist.' => 'Dieser Export existiert nicht.',
'The display of (mainly) picker results can be configured. To insert the value of one option use <%Name%>.' => 'Die Anzeigenamen von (hauptsächlich) Auswahl-Ergebnissen (Picker) können konfiguriert werden. Um einen Wert einer Option in die Anzeige aufzunehmen, verwenden Sie <%Name%>.',
'The document has been changed by another user. No mail was sent. Please reopen it in another window and copy the changes to the new window' => 'Die Daten wurden bereits von einem anderen Benutzer verändert. Deshalb ist das Dokument ungültig und es wurde keine E-Mail verschickt. Bitte öffnen Sie das Dokument erneut in einem extra Fenster und übertragen Sie die Daten',
'The document has been changed by another user. Please reopen it in another window and copy the changes to the new window' => 'Die Daten wurden bereits von einem anderen Benutzer verändert. Deshalb ist das Dokument ungültig. Bitte öffnen Sie das Dokument erneut in einem extra Fenster und übertragen Sie die Daten',
+ 'The document has been created.' => 'Das Dokument wurde erzeugt.',
+ 'The document has been printed.' => 'Das Dokument wurde gedruckt.',
'The documents have been sent to the printer \'#1\'.' => 'Die Dokumente sind zum Drucker \'#1\' geschickt',
'The dunnings have been printed.' => 'Die Mahnung(en) wurden gedruckt.',
'The email has been sent.' => 'Die E-Mail wurde verschickt.',
'CSV Export successful!' => '',
'CSV export' => '',
'CSV export -- options' => '',
+ 'CSV import: additional billing addresses' => '',
'CSV import: ar transactions' => '',
'CSV import: bank transactions' => '',
'CSV import: contacts' => '',
'Created for' => '',
'Created on' => '',
'Creating Documents' => '',
+ 'Creating Factur-X/ZUGFeRD invoices is not enabled for this customer.' => '',
'Creating invoices' => '',
'Creating the PDF failed:' => '',
'Creation Date' => '',
'Default Transfer with services' => '',
'Default Warehouse' => '',
'Default Warehouse with ignoring onhand' => '',
+ 'Default address flag' => '',
'Default article for converting into quotations and orders' => '',
'Default booking group' => '',
'Default client' => '',
'Extended status' => '',
'Extension Of Time' => '',
'Factor' => '',
+ 'Factur-X/ZUGFeRD' => '',
'Factur-X/ZUGFeRD import' => '',
'Factur-X/ZUGFeRD invoice' => '',
'Factur-X/ZUGFeRD notes for each invoice' => '',
'Groups valid for this client' => '',
'HTML' => '',
'HTML Templates' => '',
+ 'HTML field' => '',
'Handling of WebDAV' => '',
'Hardcopy' => '',
'Has item type' => '',
'Lastcost' => '',
'Lastcost (with X being a number)' => '',
'Lastname' => '',
+ 'Leading and trailing whitespaces have been removed.' => '',
'Left' => '',
'Letter' => '',
'Letter Draft' => '',
'Text blocks back' => '',
'Text blocks front' => '',
'Text field' => '',
- 'Text field variables: \'WIDTH=w HEIGHT=h\' sets the width and height of the text field. They default to 30 and 5 respectively.' => '',
+ 'Text field and HTML field variables: \'WIDTH=w HEIGHT=h\' sets the width and height of the field in pixels. They default to 225 and 90 respectively.' => '',
'Text in CSV File' => '',
'Text variables: \'MAXLENGTH=n\' sets the maximum entry length to \'n\'.' => '',
- 'Text, text field and number variables: The default value will be used as-is.' => '',
+ 'Text, text field, HTML field and number variables: The default value will be used as-is.' => '',
'Texts for invoices' => '',
'Texts for quotations & orders' => '',
'That export does not exist.' => '',