+sub _store_pdf_in_webdav {
+  my ($self, $pdf_file_name, $invoice) = @_;
+
+  return unless $::instance_conf->get_webdav_documents;
+
+  my $form = Form->new('');
+
+  $form->{cwd}              = SL::System::Process->exe_dir;
+  $form->{tmpdir}           = ($pdf_file_name =~ m{(.+)/})[0];
+  $form->{tmpfile}          = ($pdf_file_name =~ m{.+/(.+)})[0];
+  $form->{format}           = 'pdf';
+  $form->{formname}         = 'invoice';
+  $form->{type}             = 'invoice';
+  $form->{vc}               = 'customer';
+  $form->{invnumber}        = $invoice->invnumber;
+  $form->{recipient_locale} = $invoice->language ? $invoice->language->template_code : '';
+
+  Common::copy_file_to_webdav_folder($form);
+}
+
+sub _store_pdf_in_filemanagement {
+  my ($self, $pdf_file, $invoice) = @_;
+
+  return unless $::instance_conf->get_doc_storage;
+
+  # create a form for generate_attachment_filename
+  my $form = Form->new('');
+  $form->{invnumber} = $invoice->invnumber;
+  $form->{type}      = 'invoice';
+  $form->{format}    = 'pdf';
+  $form->{formname}  = 'invoice';
+  $form->{language}  = '_' . $invoice->language->template_code if $invoice->language;
+  my $doc_name       = $form->generate_attachment_filename();
+
+  SL::File->save(object_id   => $invoice->id,
+                 object_type => 'invoice',
+                 mime_type   => 'application/pdf',
+                 source      => 'created',
+                 file_type   => 'document',
+                 file_name   => $doc_name,
+                 file_path   => $pdf_file);
+}
+
+sub _print_invoice {
+  my ($self, $data) = @_;
+
+  my $invoice       = $data->{invoice};
+  my $config        = $data->{config};
+
+  return unless $config->print && $config->printer_id && $config->printer->printer_command;
+
+  my $form = Form->new;
+  $invoice->flatten_to_form($form, format_amounts => 1);
+
+  $form->{printer_code} = $config->printer->template_code;
+  $form->{copies}       = $config->copies;
+  $form->{formname}     = $form->{type};
+  $form->{format}       = 'pdf';
+  $form->{media}        = 'printer';
+  $form->{OUT}          = $config->printer->printer_command;
+  $form->{OUT_MODE}     = '|-';
+
+  $form->{TEMPLATE_DRIVER_OPTIONS} = { };
+  $form->{TEMPLATE_DRIVER_OPTIONS}->{variable_content_types} = $form->get_variable_content_types();
+
+  $form->prepare_for_printing;
+
+  $form->throw_on_error(sub {
+    eval {
+      $form->parse_template(\%::myconfig);
+      push @{ $self->{printed_invoices} }, $invoice;
+      1;
+    } or do {
+      push @{ $self->{job_errors} }, $EVAL_ERROR->error;
+      push @{ $self->{printed_failed} }, [ $invoice, $EVAL_ERROR->error ];
+    };
+  });
+}
+
+sub _email_invoice {
+  my ($self, $data) = @_;
+
+  $data->{config}->load;
+
+  return unless $data->{config}->send_email;
+
+  my @recipients =
+    uniq
+    map  { lc       }
+    grep { $_       }
+    map  { trim($_) }
+    (split(m{,}, $data->{config}->email_recipient_address),
+     $data->{config}->email_recipient_contact   ? ($data->{config}->email_recipient_contact->cp_email) : (),
+     $data->{invoice}->{customer}->invoice_mail ? ($data->{invoice}->{customer}->invoice_mail) : ()
+    );
+
+  return unless @recipients;
+
+  my $language      = $data->{invoice}->language ? $data->{invoice}->language->template_code : undef;
+  my %create_params = (
+    template               => scalar($self->find_template(name => 'invoice', language => $language)),
+    variables              => Form->new(''),
+    return                 => 'file_name',
+    record                 => $data->{invoice},
+    variable_content_types => {
+      longdescription => 'html',
+      partnotes       => 'html',
+      notes           => 'html',
+      $::form->get_variable_content_types_for_cvars,
+    },
+  );
+
+  $data->{invoice}->flatten_to_form($create_params{variables}, format_amounts => 1);
+  $create_params{variables}->prepare_for_printing;
+
+  my $pdf_file_name;
+  my $label = $language && Locale::is_supported($language) ? Locale->new($language)->text('Invoice') : $::locale->text('Invoice');
+
+  eval {
+    $pdf_file_name = $self->create_pdf(%create_params);
+
+    $self->_store_pdf_in_webdav        ($pdf_file_name, $data->{invoice});
+    $self->_store_pdf_in_filemanagement($pdf_file_name, $data->{invoice});
+
+    for (qw(email_subject email_body)) {
+      _replace_vars(
+        object           => $data->{config},
+        invoice          => $data->{invoice},
+        vars             => $data->{time_period_vars},
+        attribute        => $_,
+        attribute_format => 'text'
+      );
+    }
+
+    my $global_bcc = SL::DB::Default->get->global_bcc;
+    my $overall_error;
+
+    for my $recipient (@recipients) {
+      my $mail             = Mailer->new;
+      $mail->{record_id}   = $data->{invoice}->id,
+      $mail->{record_type} = 'invoice',
+      $mail->{from}        = $data->{config}->email_sender || $::lx_office_conf{periodic_invoices}->{email_from};
+      $mail->{to}          = $recipient;
+      $mail->{bcc}         = $global_bcc;
+      $mail->{subject}     = $data->{config}->email_subject;
+      $mail->{message}     = $data->{config}->email_body;
+      $mail->{attachments} = [{
+        path     => $pdf_file_name,
+        name     => sprintf('%s %s.pdf', $label, $data->{invoice}->invnumber),
+      }];
+
+      my $error        = $mail->send;
+
+      if ($error) {
+        push @{ $self->{job_errors} }, $error;
+        push @{ $self->{emailed_failed} }, [ $data->{invoice}, $error ];
+        $overall_error = 1;
+      }
+    }
+
+    push @{ $self->{emailed_invoices} }, $data->{invoice} unless $overall_error;
+
+    1;
+
+  } or do {
+    push @{ $self->{job_errors} }, $EVAL_ERROR;
+    push @{ $self->{emailed_failed} }, [ $data->{invoice}, $EVAL_ERROR ];
+  };
+
+  unlink $pdf_file_name if $pdf_file_name;
+}
+