Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision ba40069b

Von Moritz Bunkus vor fast 4 Jahren hinzugefügt

  • ID ba40069b4f465cd51d509ab280d1c6e61652bda9
  • Vorgänger f24cf1f5
  • Nachfolger 04e34508

Factur-X/ZUGFeRD: in »Factur-X/ZUGFeRD« umbenannt

Mit ZUGFeRD-Standard Version 2.1.1 ist der offizielle Name des
EU-Standards schlicht Factur-X. ZUGFeRD ist nur noch der tolerierte
alte Name.

In der Oberfläche ist nun überall von »Factur-X/ZUGFeRD« die Rede.

Im Quellcode heißen die Module hingegen weiterhin `SL::…::ZUGFeRD`,
weil die Umstellung ansonsten zu groß und irgendwo auch nicht so nötig
ist.

Es ändern sich auch die ganzen Namen in den Metadaten des PDFs und der
XML-Datei:

• Namensraum in der für Factur-X/ZUGFeRD relevanten XML-Elemente in
den XMP-Metadaten im PDF
• Name des Dateianhangs der Rechnungs-XML im PDF (»factur-x.xml«)
• Standard-Identifier in der Rechnungs-XML

Unterschiede anzeigen:

SL/Controller/ClientConfig.pm
21 21
use SL::DB::Helper::AccountingPeriod qw(get_balance_startdate_method_options);
22 22
use SL::Helper::ShippedQty;
23 23
use SL::VATIDNr;
24
use SL::ZUGFeRD;
24 25

  
25 26
__PACKAGE__->run_before('check_auth');
26 27

  
27 28
use Rose::Object::MakeMethods::Generic (
28 29
  'scalar --get_set_init' => [ qw(defaults all_warehouses all_weightunits all_languages all_currencies all_templates all_price_sources h_unit_name available_quick_search_modules available_shipped_qty_item_identity_fields
29
                                  all_project_statuses all_project_types
30
                                  all_project_statuses all_project_types zugferd_settings
30 31
                                  posting_options payment_options accounting_options inventory_options profit_options balance_startdate_method_options
31 32
                                  displayable_name_specs_by_module) ],
32 33
);
......
166 167
sub init_h_unit_name     { first { SL::DB::Manager::Unit->find_by(name => $_) } qw(Std h Stunde)                         }
167 168
sub init_all_project_types    { SL::DB::Manager::ProjectType->get_all_sorted                                             }
168 169
sub init_all_project_statuses { SL::DB::Manager::ProjectStatus->get_all_sorted                                           }
170
sub init_zugferd_settings     { \@SL::ZUGFeRD::customer_settings                                                         }
169 171

  
170 172
sub init_posting_options {
171 173
  [ { title => t8("never"),           value => 0           },
SL/Controller/CustomerVendor.pm
11 11
use SL::Locale::String;
12 12
use SL::Util qw(trim);
13 13
use SL::Webdav;
14
use SL::ZUGFeRD;
14 15
use SL::Controller::Helper::GetModels;
15 16
use SL::Controller::Helper::ReportGenerator;
16 17
use SL::Controller::Helper::ParseFilter;
......
40 41
use Data::Dumper;
41 42

  
42 43
use Rose::Object::MakeMethods::Generic (
43
  'scalar --get_set_init' => [ qw(customer_models vendor_models) ],
44
  'scalar --get_set_init' => [ qw(customer_models vendor_models zugferd_settings) ],
44 45
);
45 46

  
46 47
# safety
......
1235 1236
  );
1236 1237
}
1237 1238

  
1239
sub init_zugferd_settings {
1240
  return [
1241
    [ -1, t8('Use settings from client configuration') ],
1242
    @SL::ZUGFeRD::customer_settings,
1243
  ],
1244
}
1245

  
1238 1246
sub _new_customer_vendor_object {
1239 1247
  my ($self) = @_;
1240 1248

  
SL/Controller/SimpleSystemSetting.pm
35 35
      { method => 'bank',                                      title => t8('Bank'), },
36 36
      { method => 'bank_code',                                 title => t8('Bank code'), },
37 37
      { method => 'bic',                                       title => t8('BIC'), },
38
      {                                                        title => t8('Use for ZUGFeRD'), formatter => sub { $_[0]->use_for_zugferd ? t8('yes') : t8('no') } },
38
      {                                                        title => t8('Use for Factur-X/ZUGFeRD'), formatter => sub { $_[0]->use_for_zugferd ? t8('yes') : t8('no') } },
39 39
      { method => 'reconciliation_starting_date_as_date',      title => t8('Date'),    align => 'right' },
40 40
      { method => 'reconciliation_starting_balance_as_number', title => t8('Balance'), align => 'right' },
41 41
    ],
SL/Controller/ZUGFeRD.pm
17 17
  my ($self, %params) = @_;
18 18

  
19 19
  $self->setup_zugferd_action_bar;
20
  $self->render('zugferd/form', title => $::locale->text('ZUGFeRD import'));
20
  $self->render('zugferd/form', title => $::locale->text('Factur-X/ZUGFeRD import'));
21 21
}
22 22

  
23 23
sub action_import_zugferd {
......
31 31
  if ($info->{result} != SL::ZUGFeRD::RES_OK()) {
32 32
    # An error occurred; log message from parser:
33 33
    $::lxdebug->message(LXDebug::DEBUG1(), "Could not extract ZUGFeRD data, error message: " . $info->{message});
34
    die t8("Could not extract ZUGFeRD data, data and error message:") . $info->{message};
34
    die t8("Could not extract Factur-X/ZUGFeRD data, data and error message:") . $info->{message};
35 35
  }
36 36
  # valid ZUGFeRD metadata
37 37
  my $dom   = XML::LibXML->load_xml(string => $info->{invoice_xml});
38 38

  
39 39
  # 1. check if ZUGFeRD SellerTradeParty has a VAT-ID
40 40
  my $ustid = $dom->findnodes('//ram:SellerTradeParty/ram:SpecifiedTaxRegistration')->string_value;
41
  die t8("No VAT Info for this ZUGFeRD invoice," .
42
         " please ask your vendor to add this for his ZUGFeRD data.") unless $ustid;
41
  die t8("No VAT Info for this Factur-X/ZUGFeRD invoice," .
42
         " please ask your vendor to add this for his Factur-X/ZUGFeRD data.") unless $ustid;
43 43

  
44 44
  $ustid = SL::VATIDNr->normalize($ustid);
45 45

  
SL/DB/Helper/PDF_A.pm
58 58
      },
59 59
      zugferd              => {
60 60
        conformance_level  => 'EXTENDED',
61
        document_file_name => 'ZUGFeRD-invoice.xml',
61
        document_file_name => 'factur-x.xml',
62 62
        document_type      => 'INVOICE',
63 63
        version            => '1.0',
64 64
      },
SL/DB/Helper/ZUGFeRD.pm
14 14
use SL::Helper::ISO4217;
15 15
use SL::Helper::UNECERecommendation20;
16 16
use SL::VATIDNr;
17
use SL::ZUGFeRD qw(:PROFILES);
17 18

  
18 19
use Carp;
19 20
use Encode qw(encode);
......
24 25

  
25 26
my @line_names = qw(LineOne LineTwo LineThree);
26 27

  
28
my %standards_ids = (
29
  PROFILE_FACTURX_EXTENDED() => 'urn:cen.eu:en16931:2017#conformant#urn:factur-x.eu:1p0:extended',
30
sub _is_profile {
31
  my ($self, @profiles) = @_;
32
  return any { $self->{_zugferd}->{profile} == $_ } @profiles;
33
}
34

  
27 35
sub _u8 {
28 36
  my ($value) = @_;
29 37
  return encode('UTF-8', $value // '');
......
340 348
  #   <rsm:ExchangedDocumentContext>
341 349
  $params{xml}->startTag("rsm:ExchangedDocumentContext");
342 350

  
343
  if ($self->customer->create_zugferd_invoices_for_this_customer == 2) {
351
  if ($self->{_zugferd}->{test_mode}) {
344 352
    $params{xml}->startTag("ram:TestIndicator");
345 353
    $params{xml}->dataElement("udt:Indicator", "true");
346 354
    $params{xml}->endTag;
347 355
  }
348 356

  
349 357
  $params{xml}->startTag("ram:GuidelineSpecifiedDocumentContextParameter");
350
  $params{xml}->dataElement("ram:ID", "urn:cen.eu:en16931:2017#conformant#urn:zugferd.de:2p0:extended");
358
  $params{xml}->dataElement("ram:ID", $standards_ids{ $self->{_zugferd}->{profile} });
351 359
  $params{xml}->endTag;
352 360
  $params{xml}->endTag;
353 361
  #   </rsm:ExchangedDocumentContext>
......
608 616
    $result{bank_account} = scalar(@{ $bank_accounts }) == 1 ? $bank_accounts->[0] : first { $_->use_for_zugferd } @{ $bank_accounts };
609 617

  
610 618
    if (!$result{bank_account}) {
611
      SL::X::ZUGFeRDValidation->throw(message => $prefix . $::locale->text('No bank account flagged for ZUGFeRD usage was found.'));
619
      SL::X::ZUGFeRDValidation->throw(message => $prefix . $::locale->text('No bank account flagged for Factur-X/ZUGFeRD usage was found.'));
612 620
    }
613 621
  }
614 622

  
......
617 625

  
618 626
sub create_zugferd_data {
619 627
  my ($self)        = @_;
628
  $self->{_zugferd} = { SL::ZUGFeRD->convert_customer_setting($self->customer->create_zugferd_invoices_for_this_customer) };
629

  
630
  if (!$standards_ids{ $self->{_zugferd}->{profile} }) {
631
    croak "Profile '" . $self->{_zugferd}->{profile} . "' is not supported";
632
  }
620 633

  
621 634
  my $output        = '';
622 635

  
......
655 668

  
656 669
  return {
657 670
    conformance_level  => 'EXTENDED',
658
    document_file_name => 'ZUGFeRD-invoice.xml',
671
    document_file_name => 'factur-x.xml',
659 672
    document_type      => 'INVOICE',
660 673
    version            => '1.0',
661 674
  };
SL/Helper/CreatePDF.pm
281 281
    pdf_a           => $record->create_pdf_a_print_options(zugferd_xmp_data => $record->create_zugferd_xmp_data),
282 282
    pdf_attachments => [
283 283
      { source       => $xmlfile,
284
        name         => 'ZUGFeRD-invoice.xml',
285
        description  => $::locale->text('ZUGFeRD invoice'),
284
        name         => 'factur-x.xml',
285
        description  => $::locale->text('Factur-X/ZUGFeRD invoice'),
286 286
        relationship => '/Alternative',
287 287
        mime_type    => 'text/xml',
288 288
      }
SL/Template/LaTeX.pm
394 394
  my ($self, $file) = @_;
395 395

  
396 396
  # { source      => $xmlfile,
397
  #   name        => 'ZUGFeRD-invoice.xml',
398
  #   description => $::locale->text('ZUGFeRD invoice'), }
397
  #   name        => 'factur-x.xml',
398
  #   description => $::locale->text('Factur-X/ZUGFeRD invoice'), }
399 399

  
400 400
  my $file_name  =  blessed($file->{source}) && $file->{source}->can('filename') ? $file->{source}->filename : "" . $file->{source}->filename;
401 401
  my $embed_name =  $file->{name} // $file_name;
SL/ZUGFeRD.pm
9 9
use List::Util qw(first);
10 10
use XML::LibXML;
11 11

  
12
use SL::Locale::String qw(t8);
13

  
14
use parent qw(Exporter);
15
our @EXPORT_PROFILES = qw(PROFILE_FACTURX_EXTENDED);
16
our @EXPORT_OK       = (@EXPORT_PROFILES);
17
our %EXPORT_TAGS     = (PROFILES => \@EXPORT_PROFILES);
18

  
19
use constant PROFILE_FACTURX_EXTENDED => 0;
20

  
12 21
use constant RES_OK                              => 0;
13 22
use constant RES_ERR_FILE_OPEN                   => 1;
14 23
use constant RES_ERR_NO_XMP_METADATA             => 2;
......
16 25
use constant RES_ERR_NOT_ZUGFERD                 => 4;
17 26
use constant RES_ERR_UNSUPPORTED_ZUGFERD_VERSION => 5;
18 27

  
28
our @customer_settings = (
29
  [ 0,                                  t8('Do not create Factur-X/ZUGFeRD invoices')                                    ],
30
  [ PROFILE_FACTURX_EXTENDED() * 2 + 1, t8('Create with profile \'Factur-X 1.0.05/ZUGFeRD 2.1.1 extended\'')             ],
31
  [ PROFILE_FACTURX_EXTENDED() * 2 + 2, t8('Create with profile \'Factur-X 1.0.05/ZUGFeRD 2.1.1 extended\' (test mode)') ],
32
);
33

  
34
sub convert_customer_setting {
35
  my ($class, $customer_setting) = @_;
36

  
37
  return () if ($customer_setting <= 0) || ($customer_setting >= scalar(@customer_settings));
38

  
39
  return (
40
    profile   => int(($customer_setting - 1) / 2),
41
    test_mode => ($customer_setting - 1) % 2,
42
  );
43
}
44

  
19 45
sub _extract_zugferd_invoice_xml {
20 46
  my $doc        = shift;
21 47
  my $names_dict = $doc->getValue($doc->getRootDict->{Names}) or return {};
......
109 135
    next unless $ns;
110 136

  
111 137
    if ($ns->getData =~ m{urn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0}) {
112
      $zugferd_version = '2p0';
138
      $zugferd_version = 'zugferd:2p0';
139
      last;
140
    }
141

  
142
    if ($ns->getData =~ m{urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0}) {
143
      $zugferd_version = 'factur-x:1p0';
113 144
      last;
114 145
    }
115 146

  
116
    if ($ns->getData =~ m{zugferd}i) {
147
    if ($ns->getData =~ m{zugferd|factur-x}i) {
117 148
      $zugferd_version = 'unsupported';
118 149
      last;
119 150
    }
......
122 153
  if (!$zugferd_version) {
123 154
    return {
124 155
      result  => RES_ERR_NOT_ZUGFERD(),
125
      message => $::locale->text('The XMP metadata does not declare the ZUGFeRD data.'),
156
      message => $::locale->text('The XMP metadata does not declare the Factur-X/ZUGFeRD data.'),
126 157
    };
127 158
  }
128 159

  
129
  if ($zugferd_version !~ m{^2p}) {
160
  if ($zugferd_version eq 'unsupported') {
130 161
    return {
131 162
      result  => RES_ERR_UNSUPPORTED_ZUGFERD_VERSION(),
132
      message => $::locale->text('The ZUGFeRD version used is not supported.'),
163
      message => $::locale->text('The Factur-X/ZUGFeRD version used is not supported.'),
133 164
    };
134 165
  }
135 166

  
......
138 169
  if (!defined $invoice_xml) {
139 170
    return {
140 171
      result  => RES_ERR_NO_XML_INVOICE(),
141
      message => $::locale->text('The ZUGFeRD XML invoice was not found.'),
172
      message => $::locale->text('The Factur-X/ZUGFeRD XML invoice was not found.'),
142 173
    };
143 174
  }
144 175

  
......
159 190

  
160 191
=head1 NAME
161 192

  
162
SL::ZUGFeRD - Helper functions for dealing with PDFs containing ZUGFeRD invoice data
193
SL::ZUGFeRD - Helper functions for dealing with PDFs containing Factur-X/ZUGFeRD invoice data
163 194

  
164 195
=head1 SYNOPSIS
165 196

  
......
182 213

  
183 214
=item C<extract_from_pdf> C<$file_name>
184 215

  
185
Opens an existing PDF in the file system and tries to extract ZUGFeRD
186
invoice data from it. First it'll parse the XMP metadata and look for
187
the ZUGFeRD declaration inside. If the declaration isn't found or the
188
declared version isn't 2p0, an error is returned.
216
Opens an existing PDF in the file system and tries to extract
217
Factur-X/ZUGFeRD invoice data from it. First it'll parse the XMP
218
metadata and look for the Factur-X/ZUGFeRD declaration inside. If the
219
declaration isn't found or the declared version isn't 2p0, an error is
220
returned.
189 221

  
190 222
Otherwise it'll continue to look through all embedded files in the
191 223
PDF. The first embedded XML file with a root node of
......
198 230

  
199 231
=item C<RES_OK> (0): parsing was OK; the returned hash will also
200 232
contain the keys C<xmp_metadata> and C<invoice_xml> which will contain
201
the XML text of the metadata & the ZUGFeRD invoice.
233
the XML text of the metadata & the Factur-X/ZUGFeRD invoice.
202 234

  
203 235
=item C<RES_ERR_…> (all values E<gt> 0): parsing failed; the hash will
204 236
also contain a key C<message> which contains a human-readable
bin/mozilla/ct.pl
58 58
use SL::ReportGenerator;
59 59
use SL::Locale::String qw(t8);
60 60
use SL::MoreCommon qw(uri_encode);
61
use SL::ZUGFeRD;
61 62

  
62 63
require "bin/mozilla/common.pl";
63 64
require "bin/mozilla/reportgenerator.pl";
......
69 70

  
70 71
sub _zugferd_settings {
71 72
  return ([ -1, $::locale->text('Use settings from client configuration') ],
72
          [  0, $::locale->text('Do not create ZUGFeRD invoices') ],
73
          [  1, $::locale->text('Create ZUGFeRD invoices') ],
74
          [  2, $::locale->text('Create ZUGFeRD invoices in test mode') ]);
73
          @SL::ZUGFeRD::customer_settings);
75 74
}
76 75

  
77 76
sub search {
......
164 163
  push @options, $locale->text('Billing/shipping address (country)') . " : $form->{addr_country}" if $form->{addr_country};
165 164
  push @options, $locale->text('Billing/shipping address (GLN)')     . " : $form->{addr_gln}"     if $form->{addr_gln};
166 165
  push @options, $locale->text('Quick Search')                       . " : $form->{all}"          if $form->{all};
167
  push @options, $locale->text('ZUGFeRD settings')                   . " : $zugferd_filter"       if $zugferd_filter;
166
  push @options, $locale->text('Factur-X/ZUGFeRD settings')          . " : $zugferd_filter"       if $zugferd_filter;
168 167

  
169 168
  if ($form->{business_id}) {
170 169
    my $business = SL::DB::Manager::Business->find_by(id => $form->{business_id});
......
232 231
    'creditlimit'       => { 'text' => $locale->text('Credit Limit'), },
233 232
    'ustid'             => { 'text' => $locale->text('VAT ID'), },
234 233
    'commercial_court'  => { 'text' => $locale->text('Commercial court'), },
235
    create_zugferd_invoices => { text => $locale->text('ZUGFeRD settings'), },
234
    create_zugferd_invoices => { text => $locale->text('Factur-X/ZUGFeRD settings'), },
236 235
    %column_defs_cvars,
237 236
  );
238 237

  
bin/mozilla/generictranslations.pl
227 227

  
228 228
  setup_generictranslations_edit_zugferd_notes_action_bar();
229 229

  
230
  $::form->{title} = $::locale->text('Edit ZUGFeRD notes');
230
  $::form->{title} = $::locale->text('Edit Factur-X/ZUGFeRD notes');
231 231
  $::form->header;
232 232
  print $::form->parse_html_template('generictranslations/edit_zugferd_notes');
233 233
}
......
248 248
    );
249 249
  }
250 250

  
251
  $::form->{message} = $::locale->text('The ZUGFeRD notes have been saved.');
251
  $::form->{message} = $::locale->text('The Factur-X/ZUGFeRD notes have been saved.');
252 252

  
253 253
  edit_zugferd_notes();
254 254
}
bin/mozilla/io.pl
2166 2166
    $form->{TEMPLATE_DRIVER_OPTIONS}->{pdf_a}           = $record->create_pdf_a_print_options(zugferd_xmp_data => $record->create_zugferd_xmp_data);
2167 2167
    $form->{TEMPLATE_DRIVER_OPTIONS}->{pdf_attachments} = [
2168 2168
      { source       => $xmlfile,
2169
        name         => 'ZUGFeRD-invoice.xml',
2170
        description  => $::locale->text('ZUGFeRD invoice'),
2169
        name         => 'factur-x.xml',
2170
        description  => $::locale->text('Factur-X/ZUGFeRD invoice'),
2171 2171
        relationship => '/Alternative',
2172 2172
        mime_type    => 'text/xml',
2173 2173
      }
doc/dokumentation.xml
7261 7261
			</orderedlist>
7262 7262

  
7263 7263
			<para>Wenn diese Voraussetzungen erfüllt sind, kann die Rechnung
7264
			über „Finanzbuchhaltung“ → „ZUGFeRD Import“ über die „Durchsuchen“
7264
			über „Finanzbuchhaltung“ → „Factur-X-/ZUGFeRD-Import“ über die „Durchsuchen“
7265 7265
			Schaltfläche ausgewählt werden und über die Schaltfläche „Import“
7266 7266
			eingeladen werden. Es öffnet sich daraufhin die Kreditorenbuchung.
7267 7267
			Die auslesbaren Daten aus dem eingebetteten XML der PDF Datei
locale/de/all
701 701
  'Cost Center'                 => 'Kostenstelle',
702 702
  'Costs'                       => 'Kosten',
703 703
  'Could not create new project #1' => 'Neues Projekt #1 kann nicht angelegt werden',
704
  'Could not extract ZUGFeRD data, data and error message:' => 'Konnte keine ZUGFeRD Daten extrahieren, folgende Fehlermeldung und das PDF:',
704
  'Could not extract Factur-X/ZUGFeRD data, data and error message:' => 'Konnte keine Factur-X-/ZUGFeRD-Daten extrahieren, folgende Fehlermeldung und das PDF:',
705 705
  'Could not find an entry for this part in the pricegroup.' => 'Konnte keine Eintrag für diesen Artikel in der Preisgruppe finden.',
706 706
  'Could not load class #1 (#2): "#3"' => 'Konnte Klasse #1 (#2) nicht laden: "#3"',
707 707
  'Could not load class #1, #2' => 'Konnte Klasse #1 nicht laden: "#2"',
......
722 722
  'Create Date'                 => 'Erstelldatum',
723 723
  'Create HTML'                 => 'HTML erzeugen',
724 724
  'Create PDF'                  => 'PDF erzeugen',
725
  'Create ZUGFeRD invoices'     => 'ZUGFeRD-Rechnungen erzeugen',
726
  'Create ZUGFeRD invoices in test mode' => 'ZUGFeRD-Rechnungen im Testmodus erzeugen',
727 725
  'Create a new background job' => 'Einen neuen Hintergrund-Job anlegen',
728 726
  'Create a new client'         => 'Einen neuen Mandanten anlegen',
729 727
  'Create a new delivery term'  => 'Neue Lieferbedingungen anlegen',
......
777 775
  'Create new version'          => 'Neue Version anlegen',
778 776
  'Create one from the context menu by right-clicking on this text.' => 'Erstellen Sie einen aus dem Kontextmenü, indem Sie auf diesen Text rechtsklicken.',
779 777
  'Create order'                => 'Auftrag erstellen',
780
  'Create sales invoices with ZUGFeRD data' => 'Verkaufsrechnungen mit ZUGFeRD-Daten erzeugen',
778
  'Create sales invoices with Factur-X/ZUGFeRD data' => 'Verkaufsrechnungen mit Factur-X-/ZUGFeRD-Daten erzeugen',
781 779
  'Create tables'               => 'Tabellen anlegen',
780
  'Create with profile \'Factur-X 1.0.05/ZUGFeRD 2.1.1 extended\'' => 'Mit Profil »Factur-X 1.0.05/ZUGFeRD 2.1.1 extended«',
781
  'Create with profile \'Factur-X 1.0.05/ZUGFeRD 2.1.1 extended\' (test mode)' => 'Mit Profil »Factur-X 1.0.05/ZUGFeRD 2.1.1 extended« (Test-Modus)',
782 782
  'Created by'                  => 'Erstellt von',
783 783
  'Created for'                 => 'Erstellt für',
784 784
  'Created on'                  => 'Erstellt am',
......
1048 1048
  'Displayable Name Preferences' => 'Einstellungen für Anzeigenamen',
1049 1049
  'Do not change the tax rate of taxkey 0.' => 'Ändern Sie nicht den Steuersatz vom Steuerschlüssel 0.',
1050 1050
  'Do not check for duplicates' => 'Nicht nach Dubletten suchen',
1051
  'Do not create ZUGFeRD invoices' => 'Keine ZUGFeRD-Rechnungen erzeugen',
1051
  'Do not create Factur-X/ZUGFeRD invoices' => 'Keine Factur-X-/ZUGFeRD-Rechnungen erzeugen',
1052 1052
  'Do not link to a project.'   => 'Nicht mit einem Projekt verknüpfen.',
1053 1053
  'Do not modify this position' => 'Diese Position nicht verändern',
1054 1054
  'Do not run the task server for this client' => 'Task-Server nicht für diesen Mandanten ausführen',
......
1170 1170
  'Edit Dunning'                => 'Mahnungen konfigurieren',
1171 1171
  'Edit Dunning Process Config' => 'Mahnwesenkonfiguration bearbeiten',
1172 1172
  'Edit Employee #1'            => 'Benutzer #1 bearbeiten',
1173
  'Edit Factur-X/ZUGFeRD notes' => 'Factur-X-/ZUGFeRD-Notizen bearbeiten',
1173 1174
  'Edit Follow-Up'              => 'Wiedervorlage bearbeiten',
1174 1175
  'Edit Follow-Up for #1'       => 'Wiedervorlage für #1 bearbeiten',
1175 1176
  'Edit General Ledger Transaction' => 'Buchung im Hauptbuch bearbeiten',
......
1194 1195
  'Edit Vendor'                 => 'Lieferant editieren',
1195 1196
  'Edit Vendor Invoice'         => 'Einkaufsrechnung bearbeiten',
1196 1197
  'Edit Warehouse'              => 'Lager bearbeiten',
1197
  'Edit ZUGFeRD notes'          => 'ZUGFeRD-Notizen bearbeiten',
1198 1198
  'Edit acceptance status'      => 'Abnahmestatus bearbeiten',
1199 1199
  'Edit additional articles'    => 'Zusätzliche Artikel bearbeiten',
1200 1200
  'Edit all drafts'             => 'Entwürfe von allen Benutzern bearbeiten',
......
1432 1432
  'Extended status'             => 'Erweiterter Status',
1433 1433
  'Extension Of Time'           => 'Dauerfristverlängerung',
1434 1434
  'Factor'                      => 'Faktor',
1435
  'Factur-X/ZUGFeRD import'     => 'Factur-X-/ZUGFeRD-Import',
1436
  'Factur-X/ZUGFeRD invoice'    => 'Factur-X-/ZUGFeRD-Rechnung',
1437
  'Factur-X/ZUGFeRD notes for each invoice' => 'Factur-X-/ZUGFeRD-Notizen für jede Rechnung',
1438
  'Factur-X/ZUGFeRD settings'   => 'Factur-X-/ZUGFeRD-Einstellungen',
1435 1439
  'Fax'                         => 'Fax',
1436 1440
  'Features'                    => 'Features',
1437 1441
  'Feb'                         => 'Feb',
......
1618 1622
  'If disabled purchase invoices can only be created by conversion from existing requests for quotations, purchase orders and purchase delivery orders.' => 'Falls deaktiviert, so können Einkaufsrechnungen nur durch Umwandlung aus bestehenden Preisanfragen, Lieferantenaufträgen und Einkaufslieferscheinen angelegt werden.',
1619 1623
  'If disabled sales orders cannot be converted into sales invoices directly.' => 'Falls deaktiviert, so können Verkaufsaufträge nicht direkt in Verkaufsrechnungen umgewandelt werden.',
1620 1624
  'If disabled sales quotations cannot be converted into sales invoices directly.' => 'Falls deaktiviert, so können Verkaufsangebote nicht direkt in Verkaufsrechnungen umgewandelt werden.',
1621
  'If enabled ZUGFeRD-conformant sales invoice PDFs will be created.' => 'Falls aktiviert, werden ZUGFeRD-konforme PDFs für Verkaufsrechnungen erzeugt.',
1625
  'If enabled Factur-X/ZUGFeRD conformant sales invoice PDFs will be created.' => 'Falls aktiviert, werden Factur-X-/ZUGFeRD-konforme PDFs für Verkaufsrechnungen erzeugt.',
1622 1626
  'If enabled a column will be shown in sales and purchase orders that lists both the amount and the value not shipped yet for each item.' => 'Falls eingeschaltet, wird für jede Position in Auftragsbestätigungen und Lieferantenaufträgen eine Spalte mit noch nicht gelieferter Menge und Wert angezeigt.',
1623 1627
  'If enabled a warning will be shown in purchase delivery orders on workflow to invoices if positions are not stocked in.' => 'Falls aktiviert, wird eine Warnung beim Workflow von Einkaufslieferscheinen zu Rechnungen ausgegeben, wenn die Positionen noch nicht eingelagert sind.',
1624 1628
  'If enabled a warning will be shown in sales and purchase orders if there are two or more positions of the same part (new controller only).' => 'Falls eingeschaltet, wird eine Warnung angezeigt, wenn der Auftrag mehrere gleiche Artikel enthält (nur neuer Controller).',
......
1636 1640
  'If the counted quantity differs more than this threshold from the quantity in the database, a warning will be shown. Set to 0 to switch of this feature.' => 'Wenn die gezählte Menge mehr als diesen Schwellenwert von der Menge in der Datenbank abweicht, wird eine Warnmeldung angezeigt. Setzen Sie den Schwellenwert auf 0, um dieses Feature abzuschalten.',
1637 1641
  'If the database user listed above does not have the right to create a database then enter the name and password of the superuser below:' => 'Falls der oben genannte Datenbankbenutzer nicht die Berechtigung zum Anlegen neuer Datenbanken hat, so können Sie hier den Namen und das Passwort des Datenbankadministratoraccounts angeben:',
1638 1642
  'If the default transfer out always succeed use this bin for negative stock quantity.' => 'Standardlagerplatz für Auslagern ohne Prüfung auf Bestand',
1639
  'If the test mode is enabled, the ZUGFeRD invoices will be flagged so that they\'re only fit to be used for testing purposes.' => 'Wenn der Testmodus aktiviert ist, werden ZUGFeRD-Rechnungen so markiert, dass sie nur für Testzwecke dienen dürfen.',
1643
  'If the test mode is enabled, the Factur-X/ZUGFeRD invoices will be flagged so that they\'re only fit to be used for testing purposes.' => 'Wenn der Testmodus aktiviert ist, werden Factur-X-/ZUGFeRD-Rechnungen so markiert, dass sie nur für Testzwecke dienen dürfen.',
1640 1644
  'If yes, delivery order positions are considered "delivered" only if they have been stocked out of the inventory. Otherwise saving the delivery order is considered delivered.' => 'Wenn diese Option aktiviert ist, gelten Lieferscheinpositionen nur dann als geliefert wenn sie im Lieferschein ausgelagert wurden, und die Ware aus dem Lager ausgebucht wurde. Andernfalls gilt das Speichern des Lieferscheins als Lieferung.',
1641 1645
  'If you enter values for the part number and / or part description then only those bins containing parts whose part number or part description match your input will be shown.' => 'Wenn Sie für die Artikelnummer und / oder die Beschreibung etwas eingeben, so werden nur die Lagerplätze angezeigt, in denen Waren eingelagert sind, die Ihre Suchbegriffe enthalten.',
1642 1646
  'If you have not chosen for example the category revenue for a tax and you choose an revenue account to create a transfer in the general ledger, this tax will not be displayed in the tax dropdown.' => 'Wenn Sie z.B. die Kategory Erlös für eine Steuer nicht gewählt haben und ein Erlöskonto beim Erstellen einer Dialogbuchung wählen, wird diese Steuer auch nicht im Dropdown-Menü für die Steuern angezeigt.',
......
1658 1662
  'Import AR from Scanner or Email' => 'Verkaufsbelege importieren vom Scanner oder von Email',
1659 1663
  'Import CSV'                  => 'CSV-Import',
1660 1664
  'Import Status'               => 'Import Status',
1665
  'Import a Factur-X/ZUGFeRD file:' => 'Eine Factur-X-/ZUGFeRD-Datei importieren',
1661 1666
  'Import a MT940 file:'        => 'Laden Sie eine MT940 Datei hoch:',
1662
  'Import a ZUGFeRD file:'      => 'Eine ZUGFeRD-Datei importieren',
1663 1667
  'Import all'                  => 'Importiere Alle',
1664 1668
  'Import documents from #1'    => 'Importiere Dateien von Quelle \'#1\'',
1665 1669
  'Import file'                 => 'Import-Datei',
......
2044 2048
  'No Journal'                  => 'Kein Journal',
2045 2049
  'No Shopdescription'          => 'Keine Shop-Artikelbeschreibung',
2046 2050
  'No Shopimages'               => 'Keine Shop-Bilder',
2047
  'No VAT Info for this ZUGFeRD invoice, please ask your vendor to add this for his ZUGFeRD data.' => 'Konnte keine UST-ID für diese ZUGFeRD Rechnungen finden, bitte fragen Sie bei Ihren Lieferanten nach, ob dieses Feld im ZUGFeRD Datensatz gesetzt wird.',
2051
  'No VAT Info for this Factur-X/ZUGFeRD invoice, please ask your vendor to add this for his Factur-X/ZUGFeRD data.' => 'Konnte keine UST-ID für diese Factur-X-/ZUGFeRD-Rechnungen finden, bitte fragen Sie bei Ihren Lieferanten nach, ob dieses Feld im Factur-X-/ZUGFeRD-Datensatz gesetzt wird.',
2048 2052
  'No Vendor was found matching the search parameters.' => 'Zu dem Suchbegriff wurde kein Händler gefunden',
2049 2053
  'No action defined.'          => 'Keine Aktion definiert.',
2050 2054
  'No article has been selected yet.' => 'Es wurde noch kein Artikel ausgewählt.',
......
2053 2057
  'No background job has been created yet.' => 'Es wurden noch keine Hintergrund-Jobs angelegt.',
2054 2058
  'No bank account chosen!'     => 'Kein Bankkonto ausgewählt!',
2055 2059
  'No bank account configured for bank code/BIC #1, account number/IBAN #2.' => 'Kein Bankkonto für BLZ/BIC #1, Kontonummer/IBAN #2 konfiguriert.',
2056
  'No bank account flagged for ZUGFeRD usage was found.' => 'Es wurde kein Bankkonto gefunden, das für Nutzung mit ZUGFeRD markiert ist.',
2060
  'No bank account flagged for Factur-X/ZUGFeRD usage was found.' => 'Es wurde kein Bankkonto gefunden, das für Nutzung mit Factur-X/ZUGFeRD markiert ist.',
2057 2061
  'No bank information has been entered in this customer\'s master data entry. You cannot create bank collections unless you enter bank information.' => 'Für diesen Kunden wurden in seinen Stammdaten keine Kontodaten hinterlegt. Solange dies nicht geschehen ist, können Sie keine Überweisungen für den Lieferanten anlegen.',
2058 2062
  'No bank information has been entered in this vendor\'s master data entry. You cannot create bank transfers unless you enter bank information.' => 'Für diesen Lieferanten wurden in seinen Stammdaten keine Kontodaten hinterlegt. Solange dies nicht geschehen ist, können Sie keine Überweisungen für den Lieferanten anlegen.',
2059 2063
  'No bins have been added to this warehouse yet.' => 'Es wurden zu diesem Lager noch keine Lagerplätze angelegt.',
......
3233 3237
  'The AR transaction #1 has been deleted.' => 'Die Debitorenbuchung #1 wurde gelöscht.',
3234 3238
  'The Bins in Inventory were only a information text field.' => 'Die Lagerplätze unter Stammdaten/Waren sind nur ein informatives Textfeld.',
3235 3239
  'The Bins in master data were only a information text field.' => 'Die Lagerplätze unter Stammdaten/Waren sind nur ein informatives Textfeld.',
3240
  'The Factur-X/ZUGFeRD XML invoice was not found.' => 'Die Factur-X-/ZUGFeRD-XML-Rechnungsdaten wurden nicht gefunden.',
3241
  'The Factur-X/ZUGFeRD notes have been saved.' => 'Die Factur-X-/ZUGFeRD-Notizen wurden gespeichert.',
3242
  'The Factur-X/ZUGFeRD version used is not supported.' => 'Die verwendete Factur-X-/ZUGFeRD-Version wird nicht unterstützt.',
3236 3243
  'The GL transaction #1 has been deleted.' => 'Die Dialogbuchung #1 wurde gelöscht.',
3237 3244
  'The Geierlein path has not been set in the configuration.' => 'Der Geierlein-Pfad wurde in der Konfigurationsdatei nicht gesetzt.',
3238 3245
  'The IBAN \'#1\' is not valid as IBANs in #2 must be exactly #3 characters long.' => 'Die IBAN \'#1\' ist ungültig, da IBANs in #2 genau #3 Zeichen lang sein müssen.',
......
3251 3258
  'The VAT ID number in the client configuration is invalid.' => 'Die UStID-Nummer in der Mandantenkonfiguraiton ist ungültig.',
3252 3259
  'The VAT registration number is missing in the client configuration.' => 'Die Umsatzsteuer-ID-Nummer fehlt in der Mandantenkonfiguration.',
3253 3260
  'The WebDAV feature has been used.' => 'Das WebDAV-Feature wurde benutzt.',
3254
  'The XMP metadata does not declare the ZUGFeRD data.' => 'Die XMP-Metadaten enthalten keine ZUGFeRD-Deklaration.',
3255
  'The ZUGFeRD XML invoice was not found.' => 'Die ZUGFeRD-XML-Rechnungsdaten wurden nicht gefunden.',
3261
  'The XMP metadata does not declare the Factur-X/ZUGFeRD data.' => 'Die XMP-Metadaten enthalten keine Factur-X-/ZUGFeRD-Deklaration.',
3256 3262
  'The ZUGFeRD invoice data cannot be generated because the data validation failed.' => 'Die ZUGFeRD-Rechnungsdaten können nicht erzeugt werden, da die Validierung fehlschlug.',
3257
  'The ZUGFeRD notes have been saved.' => 'Die ZUGFeRD-Notizen wurden gespeichert.',
3258
  'The ZUGFeRD version used is not supported.' => 'Die verwendete ZUGFeRD-Version wird nicht unterstützt.',
3259 3263
  'The abbreviation is missing.' => 'Abkürzung fehlt',
3260 3264
  'The access rights a user has within a client instance is still governed by his group membership.' => 'Welche Zugriffsrechte ein Benutzer innerhalb eines Mandanten hat, wird weiterhin über Gruppenmitgliedschaften geregelt.',
3261 3265
  'The access rights have been saved.' => 'Die Zugriffsrechte wurden gespeichert.',
......
3877 3881
  'Use default warehouse for assembly transfer' => 'Zum Fertigen Standardlager des Bestandteils verwenden',
3878 3882
  'Use existing templates'      => 'Vorhandene Druckvorlagen verwenden',
3879 3883
  'Use fill up when calculating shipped quantities?' => 'Sollen nicht verlinkte Positionen abgeglichen werden?',
3880
  'Use for ZUGFeRD'             => 'Nutzung mit ZUGFeRD',
3884
  'Use for Factur-X/ZUGFeRD'    => 'Nutzung mit Factur-X/ZUGFeRD',
3881 3885
  'Use linked items'            => 'Verknüpfte Positionen verwenden',
3882 3886
  'Use master default bin for Default Transfer, if no default bin for the part is configured' => 'Standardlagerplatz für Ein- / Auslagern über Standard-Lagerplatz, falls für die Ware kein expliziter Lagerplatz konfiguriert ist',
3883 3887
  'Use settings from client configuration' => 'Einstellungen aus Mandantenkonfiguration folgen',
......
4077 4081
  'Your download does not exist anymore. Please re-run the DATEV export assistant.' => 'Ihr Download existiert nicht mehr. Bitte starten Sie den DATEV-Exportassistenten erneut.',
4078 4082
  'Your import is being processed.' => 'Ihr Import wird verarbeitet',
4079 4083
  'Your target quantity will be added to the stocked quantity.' => 'Ihre gezählte Zielmenge wird zum Lagerbestand hinzugezählt.',
4080
  'ZUGFeRD import'              => 'ZUGFeRD Import',
4081
  'ZUGFeRD invoice'             => 'ZUGFeRD-Rechnung',
4082
  'ZUGFeRD notes for each invoice' => 'ZUGFeRD-Notizen für jede Rechnung',
4083
  'ZUGFeRD settings'            => 'ZUGFeRD-Einstellungen',
4084 4084
  'Zeitraum'                    => 'Zeitraum',
4085 4085
  'Zero amount posting!'        => 'Buchung ohne Wert',
4086 4086
  'Zip'                         => 'PLZ',
4087 4087
  'Zip, City'                   => 'PLZ, Ort',
4088 4088
  'Zipcode'                     => 'PLZ',
4089 4089
  'Zipcode and city'            => 'PLZ und Stadt',
4090
  'ZugFeRD Import'              => 'ZUGFeRD Import',
4091 4090
  '[email]'                     => '[email]',
4092 4091
  'absolute'                    => 'absolut',
4093 4092
  'account_description'         => 'Beschreibung',
menus/user/00-erp.yaml
643 643
    action: YearEndTransactions/form
644 644
- parent: general_ledger
645 645
  id: zugferd_import
646
  name: ZugFeRD Import
646
  name: Factur-X/ZUGFeRD import
647 647
  icon: cbob
648 648
  order: 485
649 649
  access: ap_transactions
......
1283 1283
    action: edit_sepa_strings
1284 1284
- parent: system_languages_and_translations
1285 1285
  id: system_languages_and_translations_zugferd_notes
1286
  name: ZUGFeRD notes for each invoice
1286
  name: Factur-X/ZUGFeRD notes for each invoice
1287 1287
  order: 450
1288 1288
  module: generictranslations.pl
1289 1289
  params:
templates/pdf/pdf_a_metadata.xmp
57 57
     </rdf:li>
58 58
[% IF zugferd %]
59 59
     <rdf:li rdf:parseType="Resource">
60
      <pdfaSchema:schema>ZUGFeRD PDFA Extension Schema</pdfaSchema:schema>
61
      <pdfaSchema:namespaceURI>urn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0#</pdfaSchema:namespaceURI>
60
      <pdfaSchema:schema>Factur-X PDFA Extension Schema</pdfaSchema:schema>
61
      <pdfaSchema:namespaceURI>urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#</pdfaSchema:namespaceURI>
62 62
      <pdfaSchema:prefix>fx</pdfaSchema:prefix>
63 63
      <pdfaSchema:property>
64 64
       <rdf:Seq>
......
78 78
         <pdfaProperty:name>Version</pdfaProperty:name>
79 79
         <pdfaProperty:valueType>Text</pdfaProperty:valueType>
80 80
         <pdfaProperty:category>external</pdfaProperty:category>
81
         <pdfaProperty:description>The actual version of the ZUGFeRD data</pdfaProperty:description>
81
         <pdfaProperty:description>The actual version of the Factur-X/ZUGFeRD data</pdfaProperty:description>
82 82
        </rdf:li>
83 83
        <rdf:li rdf:parseType="Resource">
84 84
         <pdfaProperty:name>ConformanceLevel</pdfaProperty:name>
85 85
         <pdfaProperty:valueType>Text</pdfaProperty:valueType>
86 86
         <pdfaProperty:category>external</pdfaProperty:category>
87
         <pdfaProperty:description>The conformance level of the ZUGFeRD data</pdfaProperty:description>
87
         <pdfaProperty:description>The conformance level of the Factur-X/ZUGFeRD data</pdfaProperty:description>
88 88
        </rdf:li>
89 89
       </rdf:Seq>
90 90
      </pdfaSchema:property>
......
124 124
  </rdf:Description>
125 125

  
126 126
[% IF zugferd %]
127
  <rdf:Description xmlns:fx="urn:zugferd:pdfa:CrossIndustryDocument:invoice:2p0#"
127
  <rdf:Description xmlns:fx="urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#"
128 128
                   fx:ConformanceLevel="[% zugferd.conformance_level | xml %]"
129 129
                   fx:DocumentFileName="[% zugferd.document_file_name | xml %]"
130 130
                   fx:DocumentType="[% zugferd.document_type | xml %]"
templates/webpages/client_config/_features.html
251 251
  </tr>
252 252
  <tr>
253 253
  <tr>
254
   <td align="right">[% LxERP.t8("Create sales invoices with ZUGFeRD data") %]</td>
255
   <td>[% L.select_tag("defaults.create_zugferd_invoices", [ [ 0, LxERP.t8('Do not create ZUGFeRD invoices') ], [ 1, LxERP.t8('Create ZUGFeRD invoices') ], [ 2, LxERP.t8('Create ZUGFeRD invoices in test mode') ] ],
256
                       default=SELF.defaults.create_zugferd_invoices) %]</td>
254
   <td align="right">[% LxERP.t8("Create sales invoices with Factur-X/ZUGFeRD data") %]</td>
255
   <td>[% L.select_tag("defaults.create_zugferd_invoices", SELF.zugferd_settings, default=SELF.defaults.create_zugferd_invoices) %]</td>
257 256
   <td>
258
     [% LxERP.t8("If enabled ZUGFeRD-conformant sales invoice PDFs will be created.") %]
259
     [% LxERP.t8("If the test mode is enabled, the ZUGFeRD invoices will be flagged so that they're only fit to be used for testing purposes.") %]
257
     [% LxERP.t8("If enabled Factur-X/ZUGFeRD conformant sales invoice PDFs will be created.") %]
258
     [% LxERP.t8("If the test mode is enabled, the Factur-X/ZUGFeRD invoices will be flagged so that they're only fit to be used for testing purposes.") %]
260 259
   </td>
261 260
  </tr>
262 261

  
templates/webpages/ct/search.html
63 63

  
64 64
[% IF IS_CUSTOMER %]
65 65
   <tr>
66
     <th align="right" nowrap>[% LxERP.t8("ZUGFeRD settings") %]</th>
66
     <th align="right" nowrap>[% LxERP.t8("Factur-X/ZUGFeRD settings") %]</th>
67 67
     <td>[% L.select_tag('create_zugferd_invoices', ZUGFERD_SETTINGS, with_empty = 1) %]</td>
68 68
   </tr>
69 69
[% END %]
templates/webpages/customer_vendor/tabs/billing.html
380 380
      <td>
381 381
        [% L.checkbox_tag('cv.order_lock', checked = SELF.cv.order_lock, for_submit=1) %]
382 382
      </td>
383
      <th align="right">[% LxERP.t8("Create sales invoices with ZUGFeRD data") %]</th>
384
      <td>[% L.select_tag("cv.create_zugferd_invoices",
385
                          [ [ -1, LxERP.t8('Use settings from client configuration') ],
386
                            [ 0, LxERP.t8('Do not create ZUGFeRD invoices') ],
387
                            [ 1, LxERP.t8('Create ZUGFeRD invoices') ],
388
                            [ 2, LxERP.t8('Create ZUGFeRD invoices in test mode') ] ],
389
                          default=SELF.cv.create_zugferd_invoices) %]</td>
383
      <th align="right">[% LxERP.t8("Create sales invoices with Factur-X/ZUGFeRD data") %]</th>
384
      <td>[% L.select_tag("cv.create_zugferd_invoices", SELF.zugferd_settings, default=SELF.cv.create_zugferd_invoices) %]</td>
390 385
     </tr>
391 386
    [% END %]
392 387
  </table>
templates/webpages/generictranslations/edit_zugferd_notes.html
14 14

  
15 15
   <tr>
16 16
    <th class="listheading">&nbsp;</th>
17
    <th class="listheading">[% 'ZUGFeRD notes for each invoice' | $T8 %]</th>
17
    <th class="listheading">[% 'Factur-X/ZUGFeRD notes for each invoice' | $T8 %]</th>
18 18
   </tr>
19 19

  
20 20
   [%- FOREACH language = LANGUAGES %]
templates/webpages/simple_system_setting/_bank_account_form.html
32 32
  <td>[% P.chart.picker('object.chart_id', SELF.object.chart_id, type='AR_paid,AP_paid', category='A,L,Q', choose=1, style=style, "data-validate"="required", "data-title"=LxERP.t8("Chart")) %]</td>
33 33
 </tr>
34 34
 <tr>
35
  <th align="right">[% LxERP.t8('Use for ZUGFeRD') %]</th>
35
  <th align="right">[% LxERP.t8('Use for Factur-X/ZUGFeRD') %]</th>
36 36
  <td>[% L.checkbox_tag('object.use_for_zugferd', checked = SELF.object.use_for_zugferd, for_submit=1) %]</td>
37 37
 </tr>
38 38
 <tr>
templates/webpages/zugferd/form.html
6 6
 <div class="listtop">[% FORM.title %]</div>
7 7

  
8 8
 <p>
9
 [% "Import a ZUGFeRD file:" | $T8 %]
9
 [% "Import a Factur-X/ZUGFeRD file:" | $T8 %]
10 10
 </p>
11 11

  
12 12
 <form method="post" action="controller.pl" enctype="multipart/form-data" id="form">
13 13
    [% L.input_tag('file', '', type => 'file', accept => '.pdf') %]
14 14
 </form>
15

  

Auch abrufbar als: Unified diff