Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision d62a113d

Von Moritz Bunkus vor etwa 1 Monat hinzugefügt

SEPA: XML-Version beim Download auswählbar

Unterschiede anzeigen:

SL/SEPA/XML.pm
5 5

  
6 6
use Carp;
7 7
use Encode;
8
use List::Util qw(first sum);
9 8
use List::MoreUtils qw(any);
9
use List::Util qw(first sum);
10 10
use POSIX qw(strftime);
11 11
use XML::Writer;
12 12

  
13 13
use SL::Iconv;
14 14
use SL::SEPA::XML::Transaction;
15 15

  
16
use constant V3_0_0 => 3_000_000;
17
use constant V3_8_0 => 3_800_000;
18

  
19
sub get_supported_versions {
20
  return (
21
    versions => [
22
      { id => V3_0_0(), description => "v3.0.0" },
23
      { id => V3_8_0(), description => "v3.8.0" },
24
    ],
25
    default => get_default_version(),
26
  );
27
}
28

  
29
sub get_default_version {
30
  my $today          = DateTime->today_local;
31
  my $cutoff_v3_8_0  = DateTime->new_local(year => 2025, month => 10, day => 1);
32

  
33
  return V3_8_0() if $today >= $cutoff_v3_8_0;
34
  return V3_0_0();
35
}
36

  
37
sub is_version_valid {
38
  shift while @_ && ref($_[0]);
39

  
40
  my $id       = $_[0];
41
  my %versions = get_supported_versions();
42

  
43
  return any { $_->{id} == $id } @{ $versions{versions} };
44
}
45

  
16 46
sub new {
17 47
  my $class = shift;
18 48
  my $self  = {};
......
31 61
  $self->{transactions} = [];
32 62
  $self->{src_charset}  = 'UTF-8';
33 63
  $self->{grouped}      = 0;
64
  $self->{version}      = get_default_version();
34 65

  
35
  map { $self->{$_} = $params{$_} if (exists $params{$_}) } qw(src_charset company creditor_id message_id grouped collection);
66
  map { $self->{$_} = $params{$_} if (exists $params{$_}) } qw(src_charset company creditor_id message_id grouped collection version);
36 67

  
37 68
  $self->{iconv} = SL::Iconv->new($self->{src_charset}, "UTF-8") || croak "Unsupported source charset $self->{src_charset}.";
38 69

  
39 70
  my $missing_parameter = first { !$self->{$_} } qw(company message_id);
40 71
  croak "Missing parameter: $missing_parameter" if ($missing_parameter);
41 72
  croak "Missing parameter: creditor_id"        if !$self->{creditor_id} && $self->{collection};
73
  croak "Invalid parameter: version"            if !is_version_valid($self->{version});
42 74

  
43 75
  map { $self->{$_} = $self->_replace_special_chars($self->{iconv}->convert($self->{$_})) } qw(company message_id creditor_id);
44 76
}
......
124 156
  return substr $string, 0, 35;
125 157
}
126 158

  
159
sub _emit_cdtr_scheme_id {
160
  my ($self, $xml) = @_;
161

  
162
  $xml->startTag('CdtrSchmeId');
163
  $xml->startTag('Id');
164
  $xml->startTag('PrvtId');
165
  $xml->startTag('Othr');
166
  $xml->dataElement('Id', encode('UTF-8', substr($self->{creditor_id}, 0, 35)));
167
  $xml->startTag('SchmeNm');
168
  $xml->dataElement('Prtry', 'SEPA');
169
  $xml->endTag('SchmeNm');
170
  $xml->endTag('Othr');
171
  $xml->endTag('PrvtId');
172
  $xml->endTag('Id');
173
  $xml->endTag('CdtrSchmeId');
174
}
175

  
127 176
sub to_xml {
128 177
  my $self = shift;
129 178

  
......
143 192
  my $is_coll   = $self->{collection};
144 193
  my $cd_src    = $is_coll ? 'Cdtr'              : 'Dbtr';
145 194
  my $cd_dst    = $is_coll ? 'Dbtr'              : 'Cdtr';
146
  my $pain_id   = $is_coll ? 'pain.008.001.08'   : 'pain.001.001.09';
147 195
  my $pain_elmt = $is_coll ? 'CstmrDrctDbtInitn' : 'CstmrCdtTrfInitn';
148 196
  my @pii_base  = (strftime('PII%Y%m%d%H%M%S', @now), rand(1000000000));
197
  my $pain_id   = $is_coll && ($self->{version}  == V3_0_0()) ? 'pain.008.001.02'
198
                : $is_coll && ($self->{version}  == V3_8_0()) ? 'pain.008.001.08'
199
                : !$is_coll && ($self->{version} == V3_0_0()) ? 'pain.001.001.03'
200
                : !$is_coll && ($self->{version} == V3_8_0()) ? 'pain.001.001.09'
201
                :                                               die("programming error: version not handled for pain ID");
202
  my $bic_elt   = $self->{version} == V3_0_0() ? 'BIC'
203
                : $self->{version} == V3_8_0() ? 'BICFI'
204
                :                                die("programming error: version not handled for BIC element name");
149 205

  
150 206
  my $grouped_transactions = $self->_group_transactions();
151 207

  
......
194 250
    }
195 251
    $xml->endTag('PmtTpInf');
196 252

  
197
    if ($is_coll) {
198
      $xml->dataElement('ReqdColltnDt', $master_transaction->get('execution_date'));
253
    if ($self->{version} == V3_0_0()) {
254
      $xml->dataElement($is_coll ? 'ReqdColltnDt' : 'ReqdExctnDt', $master_transaction->get('execution_date'));
255

  
256
    } elsif ($self->{version} == V3_8_0()) {
257
      if ($is_coll) {
258
        $xml->dataElement('ReqdColltnDt', $master_transaction->get('execution_date'));
259
      } else {
260
        $xml->startTag('ReqdExctnDt');
261
        $xml->dataElement('Dt', $master_transaction->get('execution_date'));
262
        $xml->endTag('ReqdExctnDt');
263
      }
264

  
199 265
    } else {
200
      $xml->startTag('ReqdExctnDt');
201
      $xml->dataElement('Dt', $master_transaction->get('execution_date'));
202
      $xml->endTag('ReqdExctnDt');
266
      die("programming error: version not handled for ReqdColl/ExctnDt");
203 267
    }
204 268

  
205 269
    $xml->startTag($cd_src);
......
214 278

  
215 279
    $xml->startTag($cd_src . 'Agt');
216 280
    $xml->startTag('FinInstnId');
217
    $xml->dataElement('BICFI', $master_transaction->get('src_bic', 20));
281
    $xml->dataElement($bic_elt, $master_transaction->get('src_bic', 20));
218 282
    $xml->endTag('FinInstnId');
219 283
    $xml->endTag($cd_src . 'Agt');
220 284

  
221 285
    $xml->dataElement('ChrgBr', 'SLEV');
222 286

  
223
    if ($is_coll) {
224
      $xml->startTag('CdtrSchmeId');
225
      $xml->startTag('Id');
226
      $xml->startTag('PrvtId');
227
      $xml->startTag('Othr');
228
      $xml->dataElement('Id', encode('UTF-8', substr($self->{creditor_id}, 0, 35)));
229
      $xml->startTag('SchmeNm');
230
      $xml->dataElement('Prtry', 'SEPA');
231
      $xml->endTag('SchmeNm');
232
      $xml->endTag('Othr');
233
      $xml->endTag('PrvtId');
234
      $xml->endTag('Id');
235
      $xml->endTag('CdtrSchmeId');
287
    if ($is_coll && ($self->{version}  == V3_8_0())) {
288
      $self->_emit_cdtr_scheme_id($xml);
236 289
    }
237 290

  
238 291
    foreach my $transaction (@{ $transaction_group->{transactions} }) {
......
253 306
        $xml->dataElement('MndtId', $self->_restricted_identification_sepa2($transaction->get('mandator_id')));
254 307
        $xml->dataElement('DtOfSgntr', $self->_restricted_identification_sepa2($transaction->get('date_of_signature')));
255 308

  
309
        if ($self->{version}  == V3_0_0()) {
310
          $self->_emit_cdtr_scheme_id($xml);
311
        }
312

  
256 313
        $xml->endTag('MndtRltdInf');
257 314

  
258 315
        $xml->endTag('DrctDbtTx');
......
267 324

  
268 325
      $xml->startTag("${cd_dst}Agt");
269 326
      $xml->startTag('FinInstnId');
270
      $xml->dataElement('BICFI', $transaction->get('dst_bic', 20));
327
      $xml->dataElement($bic_elt, $transaction->get('dst_bic', 20));
271 328
      $xml->endTag('FinInstnId');
272 329
      $xml->endTag("${cd_dst}Agt");
273 330

  
bin/mozilla/sepa.pl
198 198
                                     'vc'             => $vc);
199 199

  
200 200
    $form->header();
201
    print $form->parse_html_template('sepa/bank_transfer_created', { 'id' => $id, 'vc' => $vc });
201
    my %sepa_versions = SL::SEPA::XML->get_supported_versions;
202
    print $form->parse_html_template('sepa/bank_transfer_created', { 'id' => $id, 'vc' => $vc, sepa_versions => \%sepa_versions });
202 203
  }
203 204

  
204 205
  $main::lxdebug->leave_sub();
......
296 297
  push @options, $form->{l_executed} ? $locale->text('executed') : $locale->text('not yet executed')               if ($form->{l_executed} != $form->{l_not_executed});
297 298
  push @options, $form->{l_closed}   ? $locale->text('closed')   : $locale->text('open')                           if ($form->{l_open}     != $form->{l_closed});
298 299

  
300
  my %sepa_versions = SL::SEPA::XML->get_supported_versions;
301

  
299 302
  $report->set_options('top_info_text'         => join("\n", @options),
300
                       'raw_top_info_text'     => $form->parse_html_template('sepa/bank_transfer_list_top'),
303
                       'raw_top_info_text'     => $form->parse_html_template('sepa/bank_transfer_list_top',    { 'show_buttons' => $open_available, sepa_versions => \%sepa_versions, }),
301 304
                       'raw_bottom_info_text'  => $form->parse_html_template('sepa/bank_transfer_list_bottom', { 'show_buttons' => $open_available, vc => $vc }),
302 305
                       'std_column_visibility' => 1,
303 306
                       'output_format'         => 'HTML',
......
553 556
                                      'message_id'  => $message_id,
554 557
                                      'grouped'     => 1,
555 558
                                      'collection'  => $vc eq 'customer',
559
                                      'version'     => $form->{sepa_xml_version},
556 560
    );
557 561

  
558 562
  foreach my $item (@items) {
locale/de/all
3373 3373
  'SEPA Transfer Amount'        => 'Betrag in offenen SEPA Exporten',
3374 3374
  'SEPA XML Docs for Exports '  => 'SEPA-XML-Dokumente Export-Nummer',
3375 3375
  'SEPA XML download'           => 'SEPA-XML-Download',
3376
  'SEPA XML version'            => 'SEPA-XML-Version',
3376 3377
  'SEPA creditor ID'            => 'SEPA-Kreditoren-Identifikation',
3377 3378
  'SEPA exports'                => 'SEPA-Exporte',
3378 3379
  'SEPA message ID'             => 'SEPA-Nachrichten-ID',
......
3971 3972
  'The PDF has been printed'    => 'Das PDF-Dokument wurde gedruckt.',
3972 3973
  'The Protocol for Host Name seems invalid (expected: http:// or https://)!' => 'Das Protokoll für den Server sieht falsch aus. Erwartet wird "http://" oder "https://".',
3973 3974
  'The Proxy Name seems invalid' => 'Der Hostname des Proxys sieht falsch aus',
3974
  'The SEPA export has been created.' => 'Der SEPA-Export wurde erstellt',
3975
  'The SEPA export has been created.' => 'Der SEPA-Export wurde erstellt.',
3975 3976
  'The SEPA strings have been saved.' => 'Die bei SEPA-Überweisungen verwendeten Begriffe wurden gespeichert.',
3976 3977
  'The SQL query can be parameterized with variables named as follows: <%name%>.' => 'Die SQL-Abfrage kann mittels Variablen wie folgt parametrisiert werden: <%Variablenname%>.',
3977 3978
  'The SQL query does not contain any parameter that need to be configured.' => 'Die SQL-Abfrage enthält keine Parameter, die angegeben werden müssten.',
locale/en/all
3372 3372
  'SEPA Transfer Amount'        => '',
3373 3373
  'SEPA XML Docs for Exports '  => '',
3374 3374
  'SEPA XML download'           => '',
3375
  'SEPA XML version'            => '',
3375 3376
  'SEPA creditor ID'            => '',
3376 3377
  'SEPA exports'                => '',
3377 3378
  'SEPA message ID'             => '',
templates/design40_webpages/sepa/bank_transfer_created.html
1
[% USE T8 %]
2
[% USE HTML %]
3

  
1
[%- USE T8 %]
2
[% USE HTML %][%- USE LxERP -%][%- USE L -%]
4 3
<h1>[% title %]</h1>
5 4

  
6
<p>[% 'The SEPA export has been created.' | $T8 %]</p>
7
<ul>
8
  <li><a href="sepa.pl?action=bank_transfer_download_sepa_xml&id=[% HTML.url(id) %]&vc=[% HTML.url(vc) %]"> [% 'Download SEPA XML export file' | $T8 %] </a></li>
9
  [%- IF INSTANCE_CONF.get_doc_storage %]
10
    <li><a href="sepa.pl?action=bank_transfer_download_sepa_docs&id=[% HTML.url(id) %]&vc=[% HTML.url(vc) %]"> [% 'Download Documents for exported bookings' | $T8 %] </a></li>
11
  [% END %]
12
  <li><a href="sepa.pl?action=bank_transfer_list&l_open=1&l_not_executed=1&vc=[% HTML.url(vc) %]"> [% 'List open SEPA exports' | $T8 %] </a></li>
13
</ul>
5
<p>
6
  [% 'The SEPA export has been created.' | $T8 %]
7
</p>
8

  
9
<h2>[% LxERP.t8('Download SEPA XML export file') %]</h2>
10

  
11
<form method="post" action="sepa.pl">
12
  <p>
13
    [% LxERP.t8("SEPA XML version") %]:
14
    [% L.select_tag('sepa_xml_version', sepa_versions.versions, title_key='description', selected=sepa_versions.default) %]
15
  </p>
16

  
17
  <p>
18
    [% L.hidden_tag('action', 'bank_transfer_download_sepa_xml') %]
19
    [% L.hidden_tag('id', id) %]
20
    [% L.hidden_tag('vc', vc) %]
21

  
22
    [% L.submit_tag('dummy', LxERP.t8('Download')) %]
23
  </p>
24
</form>
25
[%- IF INSTANCE_CONF.get_doc_storage %]
26

  
27
<h2>[% LxERP.t8('Download Documents for exported bookings') %]</h2>
28

  
29
<p>
30
  <a href="sepa.pl?action=bank_transfer_download_sepa_docs&id=[% HTML.url(id) %]&vc=[% HTML.url(vc) %]"> [% 'Download Documents for exported bookings' | $T8 %]</a>
31
</p>
32
[% END %]
33

  
34
<h2>[% LxERP.t8('List open SEPA exports') %]</h2>
35

  
36
<p>
37
  <a href="sepa.pl?action=bank_transfer_list&l_open=1&l_not_executed=1&vc=[% HTML.url(vc) %]">[% 'List open SEPA exports' | $T8 %]</a>
38
</p>
templates/design40_webpages/sepa/bank_transfer_list_top.html
1
[%- USE LxERP -%][%- USE L -%]
1 2
<form action="sepa.pl" method="post" id="form">
3
  [% IF show_buttons %]
4

  
5
    <p>
6
      [% LxERP.t8("SEPA XML version") %]:
7
      [% L.select_tag('sepa_xml_version', sepa_versions.versions, title_key='description', selected=sepa_versions.default) %]
8
    </p>
9
  [% END %]
templates/webpages/sepa/bank_transfer_created.html
1 1
[%- USE T8 %]
2
[% USE HTML %]
2
[% USE HTML %][%- USE LxERP -%][%- USE L -%]
3 3
<h1>[% title %]</h1>
4 4

  
5
 <p>
5
<p>
6 6
  [% 'The SEPA export has been created.' | $T8 %]
7
 </p>
8

  
9
 <p>
10
  <ul>
11
   <li>
12
    <a href="sepa.pl?action=bank_transfer_download_sepa_xml&id=[% HTML.url(id) %]&vc=[% HTML.url(vc) %]">
13
     [% 'Download SEPA XML export file' | $T8 %]
14
    </a>
15
   </li>
16
  [%- IF INSTANCE_CONF.get_doc_storage %]
17
    <li><a href="sepa.pl?action=bank_transfer_download_sepa_docs&id=[% HTML.url(id) %]&vc=[% HTML.url(vc) %]"> [% 'Download Documents for exported bookings' | $T8 %] </a></li>
18
  [% END %]
19
   <li>
20
    <a href="sepa.pl?action=bank_transfer_list&l_open=1&l_not_executed=1&vc=[% HTML.url(vc) %]">
21
     [% 'List open SEPA exports' | $T8 %]
22
    </a>
23
   </li>
24
  </ul>
25
 </p>
7
</p>
26 8

  
9
<h2>[% LxERP.t8('Download SEPA XML export file') %]</h2>
10

  
11
<form method="post" action="sepa.pl">
12
  <p>
13
    [% LxERP.t8("SEPA XML version") %]:
14
    [% L.select_tag('sepa_xml_version', sepa_versions.versions, title_key='description', selected=sepa_versions.default) %]
15
  </p>
16

  
17
  <p>
18
    [% L.hidden_tag('action', 'bank_transfer_download_sepa_xml') %]
19
    [% L.hidden_tag('id', id) %]
20
    [% L.hidden_tag('vc', vc) %]
21

  
22
    [% L.submit_tag('dummy', LxERP.t8('Download')) %]
23
  </p>
24
</form>
25
[%- IF INSTANCE_CONF.get_doc_storage %]
26

  
27
<h2>[% LxERP.t8('Download Documents for exported bookings') %]</h2>
28

  
29
<p>
30
  <a href="sepa.pl?action=bank_transfer_download_sepa_docs&id=[% HTML.url(id) %]&vc=[% HTML.url(vc) %]"> [% 'Download Documents for exported bookings' | $T8 %]</a>
31
</p>
32
[% END %]
33

  
34
<h2>[% LxERP.t8('List open SEPA exports') %]</h2>
35

  
36
<p>
37
  <a href="sepa.pl?action=bank_transfer_list&l_open=1&l_not_executed=1&vc=[% HTML.url(vc) %]">[% 'List open SEPA exports' | $T8 %]</a>
38
</p>
templates/webpages/sepa/bank_transfer_list_top.html
1
[%- USE LxERP -%][%- USE L -%]
1 2
<form action="sepa.pl" method="post" id="form">
3
  [% IF show_buttons %]
4

  
5
    <p>
6
      [% LxERP.t8("SEPA XML version") %]:
7
      [% L.select_tag('sepa_xml_version', sepa_versions.versions, title_key='description', selected=sepa_versions.default) %]
8
    </p>
9
  [% END %]

Auch abrufbar als: Unified diff