edi4r 0.9.4.1 → 0.9.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/AuthorCopyright +3 -3
- data/{ChangeLog → Changelog} +60 -0
- data/README +15 -10
- data/Tutorial +2 -3
- data/VERSION +1 -1
- data/bin/edi2xml.rb +12 -16
- data/bin/editool.rb +9 -5
- data/bin/sedas2eancom02.rb +1385 -0
- data/bin/xml2edi.rb +7 -12
- data/data/edifact/iso9735/SDCD.20000.csv +1 -0
- data/data/edifact/iso9735/SDCD.3for2.csv +1 -0
- data/data/edifact/iso9735/SDED.20000.csv +6 -0
- data/data/edifact/iso9735/SDED.30000.csv +43 -43
- data/data/edifact/iso9735/SDED.3for2.csv +6 -0
- data/data/edifact/iso9735/SDED.40000.csv +129 -129
- data/data/edifact/iso9735/SDED.40100.csv +130 -130
- data/data/edifact/iso9735/SDMD.20000.csv +6 -0
- data/data/edifact/iso9735/SDMD.30000.csv +6 -6
- data/data/edifact/iso9735/SDMD.3for2.csv +6 -0
- data/data/edifact/iso9735/SDMD.40000.csv +17 -17
- data/data/edifact/iso9735/SDMD.40100.csv +17 -17
- data/data/edifact/iso9735/SDSD.20000.csv +5 -0
- data/data/edifact/iso9735/SDSD.3for2.csv +5 -0
- data/data/edifact/untdid/EDMD.d01b.csv +1 -1
- data/data/sedas/EDCD..csv +0 -0
- data/data/sedas/EDED..csv +859 -0
- data/data/sedas/EDMD..csv +16 -0
- data/data/sedas/EDSD..csv +44 -0
- data/lib/edi4r.rb +147 -67
- data/lib/edi4r/ansi_x12-rexml.rb +91 -0
- data/lib/edi4r/ansi_x12.rb +1684 -0
- data/lib/edi4r/diagrams.rb +75 -14
- data/lib/edi4r/edifact-rexml.rb +4 -3
- data/lib/edi4r/edifact.rb +505 -202
- data/lib/edi4r/rexml.rb +13 -7
- data/lib/edi4r/sedas.rb +854 -0
- data/lib/edi4r/standards.rb +150 -33
- data/test/damaged_file.edi +1 -0
- data/test/eancom2webedi.rb +1 -0
- data/test/groups.edi +1 -1
- data/test/test_basics.rb +16 -9
- data/test/test_edi_split.rb +30 -0
- data/test/test_loopback.rb +7 -2
- data/test/test_rexml.rb +34 -2
- data/test/test_service_messages.rb +190 -0
- data/test/test_streaming.rb +167 -0
- data/test/test_tut_examples.rb +3 -1
- data/test/webedi2eancom.rb +1 -0
- metadata +121 -77
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 991135e53b123b05465006a77510f27a07315f26
|
4
|
+
data.tar.gz: 3c08cc53d955354fc119c52589a5a86e0a51e6bb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 0bc5dd2fec9955e8549b5553280fcbe56066c35a1648299324405be92b96b99598f5da24978e41487be2cd9be95c1e9f67746d0a31cb7a5186a326c1d095c286
|
7
|
+
data.tar.gz: 6a20a3bad4528be17d24ddef2c7e873c3bb45d2e55b327deaed82e51d562b04b5ebcaf47752f5bf7242f1a5743c8116d786fedd0b2e0f5788d4582bf73b5c938
|
data/AuthorCopyright
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
== Author
|
2
2
|
|
3
|
-
Heinz W. Werntges,
|
4
|
-
(edi@
|
3
|
+
Heinz W. Werntges, RheinMain University of Applied Sciences, Wiesbaden
|
4
|
+
(edi-ai-dcsm@hs-rm.de)
|
5
5
|
|
6
6
|
== Copyright
|
7
7
|
|
8
|
-
Copyright (c) 2006 Heinz W. Werntges.
|
8
|
+
Copyright (c) 2006, 2015 Heinz W. Werntges.
|
9
9
|
Licensed under the same terms as Ruby.
|
10
10
|
|
data/{ChangeLog → Changelog}
RENAMED
@@ -1,5 +1,65 @@
|
|
1
1
|
= Change log
|
2
2
|
|
3
|
+
== 0.9.6.2
|
4
|
+
=== Tested with Ruby 2.2.1, some RDoc links fixed
|
5
|
+
|
6
|
+
== 0.9.6.1
|
7
|
+
|
8
|
+
=== Service messages, subset support
|
9
|
+
* Master data for CONTRL, AUTACK and KEYMAN fixed now, new test added
|
10
|
+
* Master data fix: Elimination of non-ASCII chars so Ruby 1.9 does not need -E
|
11
|
+
* Subsets now tolerated (warning & fallback to plain EDIFACT)
|
12
|
+
* More support for subset EANCOM (prepared for master data)
|
13
|
+
|
14
|
+
== 0.9.6.0
|
15
|
+
|
16
|
+
=== Adjustments for Ruby 1.9.2
|
17
|
+
* Encodings added, minor patches required, some typos fixed
|
18
|
+
* Some dead files removed
|
19
|
+
* XML: FPI in doctype declaration adapted to new organization name
|
20
|
+
* Tests: Rakefile replaces Makefile, works for both Ruby 1.8 & 1.9 now
|
21
|
+
|
22
|
+
== 0.9.5.3
|
23
|
+
|
24
|
+
=== Adjustments for Ruby 1.8.7
|
25
|
+
* Changed when cond: ... to when cond then ...
|
26
|
+
* Removed "break" from a case/when block
|
27
|
+
* Corrected expectations in tests for edi_split
|
28
|
+
* Adjusted a test that calls ruby on the cmd line to accept versions (prep for 1.9.x)
|
29
|
+
|
30
|
+
== 0.9.5.2
|
31
|
+
|
32
|
+
=== Misc improvements & bug fixes
|
33
|
+
* Two bugs fixed re. ANSI msg and msg_group initialization
|
34
|
+
* ANSI getters/setters "rXX" in test use now.
|
35
|
+
* Support for 270, 271, 276, 277 added, including test cases
|
36
|
+
|
37
|
+
== 0.9.5.1
|
38
|
+
|
39
|
+
=== News
|
40
|
+
* First limited support for UN/EDIFACT Subsets
|
41
|
+
* Basic support for SEDAS (as source, not target standard)
|
42
|
+
* Basic support for ANSI X12 (just 837, 997 for V4.01)
|
43
|
+
* Support for processing arbitrarily large interchanges through classes
|
44
|
+
EDI::E::StreamingParser and StreamingBuilder
|
45
|
+
* New testcase: test_streaming.rb (large, proprietary testfiles not provided)
|
46
|
+
* peek(): Now featuring ":deep_peek" (group and message structure)
|
47
|
+
* 0.9.5.1: X12 835 supported, test suite: x12 cases added
|
48
|
+
|
49
|
+
=== Changes
|
50
|
+
* Interchange.peek: Now supporting parameters. New: deep_peek
|
51
|
+
* Interchange.parse & Interchange.peek re-implemented based on StreamingBuilder
|
52
|
+
* MsgGroup::E::add() may now prevent auto-validation
|
53
|
+
* Class EDI::Time introduced, base class Time not modified anymore
|
54
|
+
|
55
|
+
=== Misc improvements & bug fixes
|
56
|
+
* EDI::Bzip2Reader::getc() added (needed by new streaming parser)
|
57
|
+
* EDI::Collection::find() added
|
58
|
+
* EDI::Collection::[]: Now accepting also Regex objects
|
59
|
+
* standards.rb: EDIFACT version & release: to_s enforced (bug report by Marius Z., SV1 issue)
|
60
|
+
* 0.9.5.1: EDI::logger available now!
|
61
|
+
|
62
|
+
|
3
63
|
== 0.9.4.1
|
4
64
|
|
5
65
|
=== News
|
data/README
CHANGED
@@ -3,9 +3,10 @@
|
|
3
3
|
This is Ruby gem <b>edi4r</b> version
|
4
4
|
:include:VERSION
|
5
5
|
|
6
|
-
Edi4r was created to greatly simplify the creation and processing of data
|
7
|
-
Electronic Data Interchange (EDI). In particular, it supports the
|
8
|
-
syntax (ISO 9573) and optionally SAP IDocs.
|
6
|
+
Edi4r was created to greatly simplify the creation and processing of data
|
7
|
+
for Electronic Data Interchange (EDI). In particular, it supports the
|
8
|
+
UN/EDIFACT syntax (ISO 9573) and optionally SAP IDocs.
|
9
|
+
Limited support is offered for ANSI X.12 and SEDAS.
|
9
10
|
|
10
11
|
== Installation
|
11
12
|
|
@@ -13,10 +14,14 @@ Install it as any other Ruby gem, e.g.:
|
|
13
14
|
|
14
15
|
sudo gem install edi4r-<version>.gem
|
15
16
|
|
17
|
+
With administrator privileges and network access, just type:
|
18
|
+
|
19
|
+
gem install edi4r
|
20
|
+
|
21
|
+
|
16
22
|
== Usage
|
17
23
|
|
18
|
-
require '
|
19
|
-
require_gem 'edi4r'
|
24
|
+
require 'edi4r' # Older installations: require_gem 'edi4r'
|
20
25
|
require 'edi4r/edifact' # optional
|
21
26
|
|
22
27
|
# Build a UN/EDIFACT interchange from its character representation in a file:
|
@@ -49,15 +54,15 @@ Install it as any other Ruby gem, e.g.:
|
|
49
54
|
|
50
55
|
== See also
|
51
56
|
|
52
|
-
* Background[link:
|
57
|
+
* Background[link:EDI.html] info about data structure and classes.
|
53
58
|
|
54
|
-
* A Tutorial[link:
|
59
|
+
* A Tutorial[link:Tutorial.html] for examples of use.
|
55
60
|
|
56
|
-
* A
|
61
|
+
* A Changelog[link:Changelog.html] is maintained since version 0.8
|
57
62
|
|
58
|
-
* Finally, see TO-DO[link:
|
63
|
+
* Finally, see TO-DO[link:TO-DO.html] for the current wish list.
|
59
64
|
|
60
|
-
* This code is put under the Ruby license, see COPYING[link:
|
65
|
+
* This code is put under the Ruby license, see COPYING[link:COPYING.html] for details.
|
61
66
|
|
62
67
|
:include:AuthorCopyright
|
63
68
|
|
data/Tutorial
CHANGED
@@ -9,7 +9,6 @@
|
|
9
9
|
|
10
10
|
=== Require statements
|
11
11
|
|
12
|
-
require "rubygems"
|
13
12
|
require "edi4r" # Try require_gem if this fails on your site
|
14
13
|
require "edi4r/edifact"
|
15
14
|
require "edi4r-tdid" # Try require_gem if this fails on your site
|
@@ -58,7 +57,7 @@ at any other location. If you need to do that, hold your messages
|
|
58
57
|
in an array, sort them any way you like, and finally add them
|
59
58
|
to the interchange in the desired sequence.
|
60
59
|
|
61
|
-
Note that each
|
60
|
+
Note that each message gets validated by default when you add it to
|
62
61
|
the interchange. If your message needs to be completed only later,
|
63
62
|
you may disable validation by calling:
|
64
63
|
|
@@ -596,7 +595,7 @@ To be supplied later; currently just a room to collect keywords to cover.
|
|
596
595
|
Segments: T-nodes, ordinal number, index, occurrence, max. occurrence
|
597
596
|
empty?, required?
|
598
597
|
|
599
|
-
=== More
|
598
|
+
=== More advanced features
|
600
599
|
|
601
600
|
Validation: warnings and exceptions (logging?)
|
602
601
|
Add-ons to class Time
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.9.
|
1
|
+
0.9.6.2
|
data/bin/edi2xml.rb
CHANGED
@@ -1,17 +1,11 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
# $Id: edi2xml.rb,v 1.1 2006/08/01 11:20:24 werntges Exp $
|
4
|
-
|
5
|
-
# $Log: edi2xml.rb,v $
|
6
|
-
# Revision 1.1 2006/08/01 11:20:24 werntges
|
7
|
-
# Initial revision
|
8
|
-
#
|
2
|
+
# -*- encoding: ISO-8859-1 -*-
|
9
3
|
#
|
10
|
-
# Author: Heinz W. Werntges (edi@
|
4
|
+
# Author: Heinz W. Werntges (edi@cs.hs-rm.de)
|
11
5
|
#
|
12
6
|
# License: This code is put under the Ruby license
|
13
7
|
#
|
14
|
-
# Copyright (c) 2006 Heinz W. Werntges,
|
8
|
+
# Copyright (c) 2006, 2011 Heinz W. Werntges, Hochschule RheinMain, Wiesbaden
|
15
9
|
#
|
16
10
|
|
17
11
|
# SYNOPSIS:
|
@@ -30,10 +24,12 @@
|
|
30
24
|
#
|
31
25
|
|
32
26
|
require "rubygems"
|
33
|
-
|
34
|
-
|
35
|
-
#
|
27
|
+
require "edi4r"
|
28
|
+
require "edi4r-tdid"
|
29
|
+
#require "edi4r-idoc"
|
36
30
|
require "edi4r/edifact"
|
31
|
+
require "edi4r/ansi_x12"
|
32
|
+
require "edi4r/sedas"
|
37
33
|
require "edi4r/rexml"
|
38
34
|
|
39
35
|
require "getoptlong"
|
@@ -44,7 +40,7 @@ def output( ic )
|
|
44
40
|
fail "DIN 16557 applies only to UN/EDIFACT data" unless ic.syntax=='E'
|
45
41
|
ic.to_din16557_4.write($stdout,0)
|
46
42
|
else
|
47
|
-
ic.to_xml.write($stdout
|
43
|
+
ic.to_xml.write($stdout)
|
48
44
|
end
|
49
45
|
end
|
50
46
|
|
@@ -54,12 +50,12 @@ def usage_and_exit
|
|
54
50
|
Usage:
|
55
51
|
#$0 [-D] [files ...]
|
56
52
|
#$0 [-D] -z edifile.gz [files ...] (Zlib required)
|
57
|
-
#$0 -s E|I [-D] (reads from stdin, E)difact or SAP I)doc)
|
53
|
+
#$0 -s A|E|I [-D] (reads from stdin, A)NSI X12, E)difact or SAP I)doc)
|
58
54
|
Options:
|
59
55
|
-d Activates debug mode by setting $DEBUG=true
|
60
56
|
-D Generate DIN 16557-4 output.
|
61
|
-
-s k Set standard key, k=E for UN/EDIFACT (default) or k=I for SAP IDOC
|
62
|
-
(currently only E supported).
|
57
|
+
-s k Set standard key, k=E for UN/EDIFACT (default), k=A fir ANSI X12, or k=I for SAP IDOC
|
58
|
+
(currently only E and A supported).
|
63
59
|
-z Require Zlib. You may then pass gzipped files directly.
|
64
60
|
Note that Zlib is not always available.
|
65
61
|
EOT
|
data/bin/editool.rb
CHANGED
@@ -1,14 +1,13 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# -*- encoding: ISO-8859-1 -*-
|
2
3
|
#
|
3
4
|
# Tool to validate, list and analyze EDI data, based on EDI4R
|
4
5
|
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
# Author: Heinz W. Werntges (edi@informatik.fh-wiesbaden.de)
|
6
|
+
# Author: Heinz W. Werntges (edi@cs.hs-rm.de)
|
8
7
|
#
|
9
8
|
# License: This code is put under the Ruby license
|
10
9
|
#
|
11
|
-
# Copyright (c) 2006 Heinz W. Werntges,
|
10
|
+
# Copyright (c) 2006, 2011 Heinz W. Werntges, RheinMain University of Applied Sciences, Wiesbaden
|
12
11
|
#
|
13
12
|
|
14
13
|
if $DEBUG # Include statement during test setup:
|
@@ -16,7 +15,7 @@ if $DEBUG # Include statement during test setup:
|
|
16
15
|
require 'edi4r'
|
17
16
|
require 'edi4r/edifact'
|
18
17
|
require "edi4r/rexml"
|
19
|
-
|
18
|
+
require "edi4r-tdid"
|
20
19
|
else # Regular include statements:
|
21
20
|
require "rubygems"
|
22
21
|
require "edi4r"
|
@@ -25,6 +24,7 @@ else # Regular include statements:
|
|
25
24
|
rescue LoadError # Ignore error
|
26
25
|
end
|
27
26
|
require "edi4r/edifact"
|
27
|
+
require "edi4r/ansi_x12"
|
28
28
|
require "edi4r/rexml"
|
29
29
|
require "edi4r-tdid"
|
30
30
|
end
|
@@ -63,6 +63,10 @@ def report_peek_result( ic_stub, fname )
|
|
63
63
|
end
|
64
64
|
puts "%15.15s\t%13s\t%13s\t%14s\t%s" % params
|
65
65
|
|
66
|
+
when 'A'
|
67
|
+
params = [fname, h.dI06, h.dI07, h.dI12, h.dI14=='T']
|
68
|
+
puts "%15.15s\t%13s\t%13s\t%14s\t%s" % params
|
69
|
+
|
66
70
|
when 'I'
|
67
71
|
puts "%15.15s\tSAP IDocs not supported yet" % [fname]
|
68
72
|
|
@@ -0,0 +1,1385 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Inter-Standard converter module SEDAS --> EANCOM'02
|
4
|
+
#
|
5
|
+
# Inhouse format: GS1 Germany's SEDAS V5 (April 1993)
|
6
|
+
# Output format: EANCOM'02 INVOIC, according to GS1 Germany'
|
7
|
+
# recommendations for application
|
8
|
+
# (EDI-Anwendungsempfehlungen V 2.0 (INVOIC) in EANCOM 2002 S3)
|
9
|
+
# and the general EANCOM 2002 (INVOIC) documentation
|
10
|
+
# Comments:
|
11
|
+
#
|
12
|
+
# Inhouse and output format were selected, because they represent typical
|
13
|
+
# data structures and tasks for users, and because documentation of
|
14
|
+
# these formats is freely available.
|
15
|
+
#
|
16
|
+
# $Id: sedas2eancom02.rb,v 1.3 2007/04/12 21:54:27 werntges Exp $
|
17
|
+
#
|
18
|
+
# Author: Heinz W. Werntges (edi@informatik.fh-wiesbaden.de)
|
19
|
+
#
|
20
|
+
# License: This code is put under the Ruby license
|
21
|
+
#
|
22
|
+
# Copyright (c) 2007 Heinz W. Werntges, FH Wiesbaden
|
23
|
+
#
|
24
|
+
|
25
|
+
# Include statement during test setup:
|
26
|
+
#if $DEBUG
|
27
|
+
# $:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
28
|
+
#else
|
29
|
+
require 'rubygems'
|
30
|
+
#end
|
31
|
+
|
32
|
+
require 'edi4r'
|
33
|
+
require 'edi4r/edifact'
|
34
|
+
require 'edi4r/sedas'
|
35
|
+
require 'logger'
|
36
|
+
|
37
|
+
|
38
|
+
#
|
39
|
+
# Helper methods
|
40
|
+
#
|
41
|
+
# bbbbbbb 00000 c
|
42
|
+
# 1313131 31313 1
|
43
|
+
|
44
|
+
def bbn_to_gln( bbn )
|
45
|
+
bbn = "%07d" % bbn
|
46
|
+
raise "Keine bbn: #{bbn}" unless bbn =~ /\d{7}/
|
47
|
+
gln = bbn + '0' * (13-bbn.length)
|
48
|
+
sum = i = 0
|
49
|
+
gln.split('').reverse_each do |c|
|
50
|
+
sum += c.hex * ((i&1==1) ? 3 : 1)
|
51
|
+
i += 1
|
52
|
+
end
|
53
|
+
sum %= 10
|
54
|
+
return gln if sum==0
|
55
|
+
gln[-1] = ?9+1 - sum
|
56
|
+
gln
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_value( komma_kz, field )
|
60
|
+
case komma_kz # Nr. 4
|
61
|
+
when 0: nil
|
62
|
+
when 1: field.to_i
|
63
|
+
when 2: field.to_i / 10.0
|
64
|
+
when 3: field.to_i / 100.0
|
65
|
+
when 4: field.to_i / 1000.0
|
66
|
+
when 5: field.to_i / 10000.0
|
67
|
+
else raise ArgumentError, "Unzulaessiges Komma-KZ: #{komma_kz}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def qkey_to_qualifier6411( qkey ) # Nr. 5
|
72
|
+
case qkey
|
73
|
+
when nil: nil # not given - don't fill qualifier
|
74
|
+
when 0: nil # empty - should not occur, consider a raise()
|
75
|
+
when 11: nil # PCE
|
76
|
+
when 12: 'KGM'
|
77
|
+
when 13: 'LTR'
|
78
|
+
when 14: 'MTR'
|
79
|
+
when 15: nil # PCE (Anzahl Display/Sortimentseinheiten)
|
80
|
+
when 16: nil # PCE (Anzahl gesamt in den Display/Sortimentseinheiten)
|
81
|
+
# FIXME: 15, 16 nicht spezifiziert - Sonderbehandlung erforderlich?
|
82
|
+
else raise "QTY/PRI: Unbekannter 'Mengenschluessel: '#{qkey}'"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class EDI::E::Message
|
87
|
+
@@curr_year = Time.now.year.to_s # For add_dtm()
|
88
|
+
|
89
|
+
# d2380: Expect Fixnum or String, JMMTT or JJMMTT if d.2379.nil?
|
90
|
+
def add_dtm( data )
|
91
|
+
return nil if data[:d2380].nil? || data[:d2380] =~ /^\s*$/
|
92
|
+
dtm = self.new_segment("DTM")
|
93
|
+
dtm.cC507.d2005 = data[:d2005]
|
94
|
+
if data[:d2379].nil? # Auto-format
|
95
|
+
if data[:digits]==5 # Expected: 5 or 6
|
96
|
+
d = @@curr_year[0,3] + "%05d" % data[:d2380].to_i
|
97
|
+
else
|
98
|
+
d = @@curr_year[0,2] + "%06d" % (data[:d2380].to_i % 1000000)
|
99
|
+
end
|
100
|
+
dtm.cC507.d2380 = d
|
101
|
+
dtm.cC507.d2379 = 102
|
102
|
+
raise ArgumentError, "Datumsformat nicht 102!" if dtm.cC507.d2380.size != 8
|
103
|
+
else # User takes full control
|
104
|
+
dtm.cC507.d2380 = data[:d2380]
|
105
|
+
dtm.cC507.d2379 = data[:d2379]
|
106
|
+
end
|
107
|
+
self.add(dtm)
|
108
|
+
end
|
109
|
+
|
110
|
+
def add_nad( data )
|
111
|
+
return nil if (data[:d3039].nil? || data[:d3039] =~ /^\s*$/) && data[:d3036_1].nil?
|
112
|
+
seg = self.new_segment('NAD')
|
113
|
+
seg.d3035 = data[:d3035]
|
114
|
+
if data[:d3039].nil? || data[:d3039] =~ /^\s*$/
|
115
|
+
seg.cC080.a3036[0].value = data[:d3036_1].strip
|
116
|
+
seg.d3164 = data[:d3164].strip
|
117
|
+
seg.cC059.a3042[0].value = data[:d3042_1].strip
|
118
|
+
seg.d3251 = data[:d3251]
|
119
|
+
else
|
120
|
+
seg.cC082.d3039 = bbn_to_gln(data[:d3039])
|
121
|
+
seg.cC082.d3055 = 9
|
122
|
+
end
|
123
|
+
self.add seg
|
124
|
+
end
|
125
|
+
|
126
|
+
def add_rff( data )
|
127
|
+
return nil if data[:d1154].nil? || data[:d1154] =~ /^\s*$/
|
128
|
+
seg = self.new_segment('RFF')
|
129
|
+
seg.cC506.d1153 = data[:d1153]
|
130
|
+
if data[:d1154].is_a? Fixnum
|
131
|
+
seg.cC506.d1154 = data[:d1154]
|
132
|
+
else
|
133
|
+
seg.cC506.d1154 = data[:d1154].strip
|
134
|
+
end
|
135
|
+
self.add seg
|
136
|
+
end
|
137
|
+
|
138
|
+
def add_tax( data )
|
139
|
+
seg = self.new_segment("TAX")
|
140
|
+
return nil unless data[:ust_kz]
|
141
|
+
case kz=data[:ust_kz]
|
142
|
+
when 0: return nil # skip!
|
143
|
+
when 1,6: seg.cC243.d5278, seg.d5305 = 0, 'E' # 0%
|
144
|
+
when 2,7: seg.cC243.d5278, seg.d5305 = 7, 'S' # 7%
|
145
|
+
when 3: seg.cC243.d5278, seg.d5305 = 19, 'S' # 19%
|
146
|
+
when 8: seg.cC243.d5278, seg.d5305 = 16, 'S' # 16%
|
147
|
+
$log.warn("add_tax: USt-Kz 8! pos_nr=#{data[:pos_nr]}")
|
148
|
+
else raise "TAX: Unbekanntes Umsatzsteuer-Kennzeichen: '#{kz}' (pos_nr=#{data[:pos_nr]})"
|
149
|
+
end
|
150
|
+
seg.cC241.d5153= 'VAT'
|
151
|
+
seg.d5283 = 7
|
152
|
+
self.add seg
|
153
|
+
end
|
154
|
+
|
155
|
+
def add_pat( data )
|
156
|
+
seg = self.new_segment("PAT")
|
157
|
+
seg.d4279 = data[:d4279]
|
158
|
+
seg.cC112.d2475 = data[:d2475]
|
159
|
+
seg.cC112.d2009 = data[:d2009]
|
160
|
+
seg.cC112.d2151 = data[:d2151]
|
161
|
+
seg.cC112.d2152 = data[:d2152]
|
162
|
+
self.add seg
|
163
|
+
end
|
164
|
+
|
165
|
+
def add_alc( data )
|
166
|
+
seg = self.new_segment("ALC")
|
167
|
+
seg.d5463 = data[:d5463] || 'A'
|
168
|
+
seg.cC214.d7161 = data[:d7161] || 'DI'
|
169
|
+
seg.d1227 = data[:d1227]
|
170
|
+
self.add seg
|
171
|
+
end
|
172
|
+
|
173
|
+
def add_lin( data )
|
174
|
+
seg = self.new_segment("LIN")
|
175
|
+
return nil if data[:d7140].nil?
|
176
|
+
seg.d1082 = data[:d1082]
|
177
|
+
seg.cC212.d7140 = bbn_to_gln( data[:d7140] )
|
178
|
+
seg.cC212.d7143 = data[:d7143] || 'SRV'
|
179
|
+
if data[:c829_d1082]
|
180
|
+
seg.cC829.d5495 = data[:c829_d5495] || 1
|
181
|
+
seg.cC829.d1082 = data[:c829_d1082]
|
182
|
+
end
|
183
|
+
self.add seg
|
184
|
+
end
|
185
|
+
|
186
|
+
def add_pia( data )
|
187
|
+
seg = self.new_segment("PIA")
|
188
|
+
return nil if data[:d4347].nil?
|
189
|
+
seg.d4347 = data[:d4347] # e.g., 1
|
190
|
+
cde = seg.aC212[0]
|
191
|
+
cde.d7140 =
|
192
|
+
data[:d7140].respond_to?(:strip) ? data[:d7140].strip : data[:d7140]
|
193
|
+
cde.d7143 = data[:d7143]
|
194
|
+
cde.d3055 = data[:d3055]
|
195
|
+
self.add seg
|
196
|
+
end
|
197
|
+
|
198
|
+
def add_imd( data )
|
199
|
+
seg = self.new_segment("IMD")
|
200
|
+
return nil if data[:d7077].nil?
|
201
|
+
seg.d7077 = data[:d7077]
|
202
|
+
seg.cC272.d7081 = data[:d7081]
|
203
|
+
seg.cC272.d3055 = data[:d7081_3055]
|
204
|
+
seg.cC273.d7009 = data[:d7009]
|
205
|
+
seg.cC273.d3055 = data[:d7009_3055]
|
206
|
+
seg.cC273.a7008[0].value =
|
207
|
+
data[:d7008_1].respond_to?(:strip) ? data[:d7008_1].strip : data[:d7008_1]
|
208
|
+
self.add seg
|
209
|
+
end
|
210
|
+
|
211
|
+
def add_qty( data )
|
212
|
+
seg = self.new_segment("QTY")
|
213
|
+
return nil if data[:qkey]==0
|
214
|
+
seg.cC186.d6411 = qkey_to_qualifier6411( data[:qkey] )
|
215
|
+
seg.cC186.d6063 = data[:d6063]
|
216
|
+
seg.cC186.d6060 = data[:d6060]
|
217
|
+
self.add seg
|
218
|
+
end
|
219
|
+
|
220
|
+
def add_pri( data )
|
221
|
+
seg = self.new_segment("PRI")
|
222
|
+
case data[:pkey]
|
223
|
+
when nil: return nil # FIXME: Check! / Don't use this DE
|
224
|
+
when 0, 9: return nil # empty or w/o charge
|
225
|
+
when 1:
|
226
|
+
when 2: seg.cC509.d5284 = 100
|
227
|
+
when 3: seg.cC509.d5284 = 1000
|
228
|
+
else raise "PRI: Unbekannter 'Preisschluessel: '#{data[:pkey]}'"
|
229
|
+
end
|
230
|
+
seg.cC509.d5125 = data[:d5125]
|
231
|
+
seg.cC509.d6411 = qkey_to_qualifier6411( data[:qkey] )
|
232
|
+
seg.cC509.d5118 = data[:d5118]
|
233
|
+
self.add seg
|
234
|
+
end
|
235
|
+
|
236
|
+
def add_moa( data )
|
237
|
+
seg = self.new_segment("MOA")
|
238
|
+
seg.cC516.d5025 = data[:d5025]
|
239
|
+
seg.cC516.d5004 = data[:d5004]
|
240
|
+
self.add seg
|
241
|
+
end
|
242
|
+
|
243
|
+
def add_pcd( data )
|
244
|
+
seg = self.new_segment("PCD")
|
245
|
+
seg.cC501.d5245 = data[:d5245]
|
246
|
+
seg.cC501.d5482 = data[:d5482]
|
247
|
+
self.add seg
|
248
|
+
end
|
249
|
+
|
250
|
+
def add_rte( data )
|
251
|
+
seg = self.new_segment("RTE")
|
252
|
+
seg.cC128.d5419 = data[:d5419]
|
253
|
+
seg.cC128.d5420 = data[:d5420]
|
254
|
+
self.add seg
|
255
|
+
end
|
256
|
+
|
257
|
+
end
|
258
|
+
|
259
|
+
|
260
|
+
Verkettung01_Felder = Struct.new(:v_nad_by, :v_nad_ds,
|
261
|
+
:v_nad_su_va, :v_nad_su_fc, :v_nad_by_va,
|
262
|
+
:ls_a_kz, :ls_a_nr1, :ls_a_nr2)
|
263
|
+
|
264
|
+
Verkettung02_Felder = Struct.new(:empty, :ust_prozentsatz,
|
265
|
+
:preisschluessel, :komma_kz_p, :grundpreis,
|
266
|
+
:mengenschluessel, :komma_kz_m, :menge)
|
267
|
+
|
268
|
+
|
269
|
+
class SEDAS_to_EANCOM02_Map_INVOIC
|
270
|
+
include EDI
|
271
|
+
|
272
|
+
attr_accessor :with_ung
|
273
|
+
|
274
|
+
|
275
|
+
def map_00_to_unb( s00 )
|
276
|
+
unb = @ic.header
|
277
|
+
unb.cS002.d0004 = bbn_to_gln( s00.bbn_absender_dt )
|
278
|
+
unb.cS002.d0007 = 14
|
279
|
+
unb.cS003.d0010 = bbn_to_gln( s00.bbn_empfaenger_dt )
|
280
|
+
unb.cS003.d0007 = 14
|
281
|
+
unb.cS004.d0017 = s00.datum_erstellung
|
282
|
+
unb.cS004.d0019 = '0000'
|
283
|
+
unb.d0035 = 1 if s00.dateistatus =~ /[KT]/
|
284
|
+
unb.cS005.d0022 = s00.datei_archiv_nr.strip
|
285
|
+
unb.d0020 = s00.lfd_nr_dt_empfaenger
|
286
|
+
$ung_0048 = {} # Reset store for uniqueness check of UNG ref numbers
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
def map_01_to_ung( s01 )
|
291
|
+
grp = @ic.new_msggroup( @msg_params )
|
292
|
+
ung = grp.header
|
293
|
+
ung.cS006.d0040 = bbn_to_gln( s01.bbn_absender )
|
294
|
+
ung.cS006.d0007 = 14
|
295
|
+
ung.cS007.d0044 = bbn_to_gln( s01.bbn_empfaenger )
|
296
|
+
ung.cS007.d0007 = 14
|
297
|
+
ung.cS004.d0017 = s01.datum_erstellung
|
298
|
+
ung.cS004.d0019 = '0000'
|
299
|
+
log_nr = s01.log_nr
|
300
|
+
warn "SA01: Log-Nr. #{log_nr} bereits verwendet!" if $ung_0048[log_nr]
|
301
|
+
ung.d0048 = log_nr
|
302
|
+
$ung_0048[log_nr]=true
|
303
|
+
@ic.add grp
|
304
|
+
@p = grp
|
305
|
+
end
|
306
|
+
|
307
|
+
|
308
|
+
def map_12_to_325( s_msg, master_data )
|
309
|
+
@msg = @p.new_message( @msg_params )
|
310
|
+
item_counter = 1
|
311
|
+
|
312
|
+
# Lookahead / out-of-sequence segments first:
|
313
|
+
#
|
314
|
+
ftx_in_header = []
|
315
|
+
# 08 for SA 12/22, 15/25
|
316
|
+
s_msg[/[12][25]08/].each do |seg|
|
317
|
+
ftx = @msg.new_segment("FTX")
|
318
|
+
ftx.d4451 = 'ZZZ'
|
319
|
+
ftx.cC108.a4440[0].value = seg.freitext.strip
|
320
|
+
ftx.d3453 = 'DE'
|
321
|
+
ftx_in_header << ftx
|
322
|
+
end
|
323
|
+
# 08 for SA 14/24, 17/27
|
324
|
+
s_msg[/[12][47]08/].each do |seg|
|
325
|
+
ftx = @msg.new_segment("FTX")
|
326
|
+
ftx.d4451 = 'SUR'
|
327
|
+
ftx.cC108.a4440[0].value = seg.freitext.strip
|
328
|
+
ftx.d3453 = 'DE'
|
329
|
+
ftx_in_header << ftx
|
330
|
+
end
|
331
|
+
|
332
|
+
s01 = Verkettung01_Felder.new
|
333
|
+
if seg=s_msg[/[12][25]01/].first # 1201, 2201, 1501, 2501
|
334
|
+
s01.v_nad_by = seg.bbn_rechnungsempfaenger
|
335
|
+
s01.v_nad_ds = seg.bbn_warenlieferant
|
336
|
+
s01.v_nad_su_va = seg.ust_ident_nr_lieferant
|
337
|
+
s01.v_nad_su_fc = seg.steuer_nr
|
338
|
+
s01.v_nad_by_va = seg.ust_ident_nr_erwerber
|
339
|
+
s01.ls_a_kz = seg.ls_auftrag_kz
|
340
|
+
s01.ls_a_nr1 = seg.ls_auftrag_nr_1
|
341
|
+
s01.ls_a_nr2 = seg.ls_auftrag_nr_2
|
342
|
+
else
|
343
|
+
s01.ls_a_kz = 0
|
344
|
+
end
|
345
|
+
|
346
|
+
# Naming convention:
|
347
|
+
#
|
348
|
+
# shd = SEDAS header record, e.g. a SA12/22 or a SA15/25
|
349
|
+
# str = SEDAS trailer record, e.g. a SA14/24 or a SA17/27
|
350
|
+
#
|
351
|
+
shd = s_msg[/[12][25]00/].first # Must exist due to SEDAS msg definition!
|
352
|
+
all_str = s_msg[/[12][47]00/] # Expect one per VAT rate, one at least
|
353
|
+
|
354
|
+
ls_auftrag_array = [[shd.ls_auftrag_kz_1, shd.ls_auftrag_nr_1, 1],
|
355
|
+
[shd.ls_auftrag_kz_2, shd.ls_auftrag_nr_2, 2],
|
356
|
+
[shd.ls_auftrag_kz_3, shd.ls_auftrag_nr_3, 3],
|
357
|
+
[shd.ls_auftrag_kz_4, shd.ls_auftrag_nr_4, 4],
|
358
|
+
[shd.ls_auftrag_kz_5, shd.ls_auftrag_nr_5, 5]]
|
359
|
+
|
360
|
+
summe_131 = 0 # Evtl. erst Skonto addieren, siehe ALC (EAB)
|
361
|
+
|
362
|
+
# BGM
|
363
|
+
#
|
364
|
+
bgm = @msg.new_segment("BGM")
|
365
|
+
bgm.cC002.d1001 = 325
|
366
|
+
bgm.cC106.d1004 = shd.beleg_nr
|
367
|
+
bgm.d1225 = 9
|
368
|
+
@msg.add(bgm)
|
369
|
+
|
370
|
+
# All DTM
|
371
|
+
#
|
372
|
+
@msg.add_dtm(:d2005=> 137, :digits=> 5, :d2380=>shd.datum_liefernachweis)
|
373
|
+
@msg.add_dtm(:d2005=> 35, :d2380=> shd.lieferdatum)
|
374
|
+
[
|
375
|
+
[shd.ls_auftrag_kz, shd.ls_auftrag_nr, shd.auftrags_nr_besteller, 1],
|
376
|
+
[s01.ls_a_kz, s01.ls_a_nr1, s01.ls_a_nr2, 2]
|
377
|
+
].each do |a|
|
378
|
+
kz, nr1, nr2, no = a
|
379
|
+
next unless kz==2 # Lieferdatum von-bis (0JJMMTT)
|
380
|
+
dt = if nr1.is_a? String
|
381
|
+
@curr_year[0,2]+nr1[1,6]+@curr_year[0,2]+nr2[1,6]
|
382
|
+
else
|
383
|
+
@curr_year[0,2]+"%06d" % nr1 + @curr_year[0,2]+"%06d" % nr2
|
384
|
+
end
|
385
|
+
@msg.add_dtm( :d2005=>35, :d2380=>dt, :d2379=>718 ) # CCYYMMDD-CCYYMMDD
|
386
|
+
end
|
387
|
+
|
388
|
+
# All FTX
|
389
|
+
#
|
390
|
+
ftx_in_header.each {|obj| @msg.add(obj)}
|
391
|
+
|
392
|
+
# SG1: RFF-DTM
|
393
|
+
#
|
394
|
+
case q=shd.s_rechnung_kz # Nr. 2, Anmerkung 2
|
395
|
+
when 0 # empty - skip
|
396
|
+
when 6,8
|
397
|
+
@msg.add_rff( :d1153=>'IV', :d1154=> shd.s_rechnung_nr )
|
398
|
+
@msg.add_dtm( :d2005=> 171, :d2380=> shd.datum_s_beleg )
|
399
|
+
when 7,9
|
400
|
+
@msg.add_rff( :d1153=>'IV', :d1154=> shd.s_rechnung_nr )
|
401
|
+
else
|
402
|
+
raise "Kennzeichen S.-Rechnung: ungueltig: #{q}"
|
403
|
+
end
|
404
|
+
|
405
|
+
[
|
406
|
+
[shd.ls_auftrag_kz, shd.ls_auftrag_nr, shd.auftrags_nr_besteller, 1],
|
407
|
+
[s01.ls_a_kz, s01.ls_a_nr1, s01.ls_a_nr2, 2]
|
408
|
+
].each do |a|
|
409
|
+
kz, nr1, nr2, no = a
|
410
|
+
case kz # Nr. 3, Anmerkung 1
|
411
|
+
when nil # treat as empty, should not occur
|
412
|
+
$log.warn("ls_auftrag_kz (#{no}) fehlt!")
|
413
|
+
when 0 # empty - skip
|
414
|
+
when 1
|
415
|
+
@msg.add_rff( :d1153=>'DQ', :d1154=> nr1 )
|
416
|
+
@msg.add_rff( :d1153=>'ON', :d1154=> nr2 )
|
417
|
+
when 2 # skip - treated earlier (DTM)
|
418
|
+
when 3
|
419
|
+
@msg.add_rff( :d1153=>'ON', :d1154=> nr1 )
|
420
|
+
when 4
|
421
|
+
@msg.add_rff( :d1153=>'DQ', :d1154=> nr1 )
|
422
|
+
else
|
423
|
+
raise "Kennzeichen LS/Auftrag (#{no}) ungueltig (Anm. 1): '#{kz}'"
|
424
|
+
end
|
425
|
+
end
|
426
|
+
|
427
|
+
ls_auftrag_array.each do |a|
|
428
|
+
kz, nr1, no = a
|
429
|
+
case kz # Nr. 3, Anmerkung 3
|
430
|
+
when 0 # empty - skip
|
431
|
+
when 5 # Lieferscheinnummer
|
432
|
+
@msg.add_rff( :d1153=>'DQ', :d1154=> nr1 )
|
433
|
+
when 6 # Auftragsnummer
|
434
|
+
@msg.add_rff( :d1153=>'ON', :d1154=> nr1 )
|
435
|
+
else
|
436
|
+
raise "Kennzeichen LS/Auftrag (#{no}) ungueltig (Anm. 3): '#{kz}'"
|
437
|
+
end
|
438
|
+
end # each
|
439
|
+
|
440
|
+
# SG2: NAD-RFF
|
441
|
+
#
|
442
|
+
@msg.add_nad( :d3035=>'SU', :d3039=> shd.bbn_lieferant )
|
443
|
+
@msg.add_rff( :d1153=>'VA', :d1154=> s01.v_nad_su_va )
|
444
|
+
@msg.add_rff( :d1153=>'FC', :d1154=> s01.v_nad_su_fc )
|
445
|
+
|
446
|
+
bbn = s01.v_nad_by
|
447
|
+
bbn = shd.bbn_rechnungsempfaenger if bbn.nil? || bbn == 0
|
448
|
+
@msg.add_nad( :d3035=>'BY', :d3039=> bbn )
|
449
|
+
@msg.add_rff( :d1153=>'VA', :d1154=> s01.v_nad_by_va )
|
450
|
+
|
451
|
+
case kz=shd.warenempfaenger_kz
|
452
|
+
when 1
|
453
|
+
bbn = shd.bbn_warenempfaenger.to_s + "%06d" % shd.interne_nr
|
454
|
+
@msg.add_nad( :d3035=>'DP', :d3039=> bbn )
|
455
|
+
when 2
|
456
|
+
s51 = master_data['51'].find{|s| s.refpos_nr == shd.positions_nr}
|
457
|
+
raise "Sorry - SA51 fehlt fuer pos_nr={shd.positions_nr}" unless s51
|
458
|
+
@msg.add_nad( :d3035=>'DP', :d3036_1=> s51.name_warenempfaenger,
|
459
|
+
:d3164=> s51.ort,
|
460
|
+
:d3042_1=> s51.strasse_postfach,
|
461
|
+
:d3251=> s51.plz_1==0 ? s51.plz_2.strip : s51.plz_1 )
|
462
|
+
# @msg.add_rff( :d1153=>'IA', :d1154=> shd.interne_nr )
|
463
|
+
when 3
|
464
|
+
bbn = shd.bbn_warenempfaenger
|
465
|
+
@msg.add_nad( :d3035=>'DP', :d3039=> bbn )
|
466
|
+
else
|
467
|
+
raise "Warenempfaenger-bbs: 'Kennzeichen' ungueltig: '#{kz}'"
|
468
|
+
end
|
469
|
+
|
470
|
+
# TAX-MOA SG6
|
471
|
+
#
|
472
|
+
all_str.each {|s| @msg.add_tax( :ust_kz=> s.ust_kz, :pos_nr=> s.positions_nr ) }
|
473
|
+
|
474
|
+
# ALC-MOA SG16
|
475
|
+
#
|
476
|
+
all_str.each do |s|
|
477
|
+
kz, betrag = s.fracht_verpackung_kz, s.fracht_verpackung
|
478
|
+
next if kz == 0
|
479
|
+
params = {}
|
480
|
+
params[:d5463] = betrag > 0 ? 'C' : 'A'
|
481
|
+
params[:d7161] = case kz
|
482
|
+
when 1: 'FC'
|
483
|
+
when 2: 'PC'
|
484
|
+
when 3: 'IN'
|
485
|
+
when 4,5,6,7: 'SH'
|
486
|
+
else raise "'Fracht/Verpackungs-Kennzeichen' ungueltig: '#{kz}'"
|
487
|
+
end
|
488
|
+
@msg.add_alc( params )
|
489
|
+
@msg.add_moa( :d5025=> 8, :d5004=> betrag.abs/100.0 )
|
490
|
+
end
|
491
|
+
|
492
|
+
all_str.each do |s|
|
493
|
+
betrag = s.skonto
|
494
|
+
next if betrag == 0
|
495
|
+
@msg.add_alc( :d5463=> 'A', :d1227=> 1, :d7161=> 'EAB' )
|
496
|
+
@msg.add_moa( :d5025=> 8, :d5004=> betrag.abs/100.0 )
|
497
|
+
summe_131 += betrag
|
498
|
+
warn "Skonto positiv: #{s.skonto}, pos_nr=#{s.positions_nr}" if betrag>0
|
499
|
+
end
|
500
|
+
|
501
|
+
all_str.each do |s| # Also see code at item level, SG39
|
502
|
+
[[s.rabatt_kz_1, s.nachweisrabatt_1, 1],
|
503
|
+
[s.rabatt_kz_2, s.nachweisrabatt_2, 2],
|
504
|
+
[s.rabatt_kz_3, s.nachweisrabatt_3, 3],
|
505
|
+
[s.rabatt_kz_4, s.nachweisrabatt_4, 4]].each do |a|
|
506
|
+
kz, betrag, no = a
|
507
|
+
next if kz == 0
|
508
|
+
|
509
|
+
params = {
|
510
|
+
:d5463=> betrag < 0 ? 'A' : 'C',
|
511
|
+
:d7161=> 'DI', :d1227=> kz%10 - 1
|
512
|
+
}
|
513
|
+
params[:d1227] = nil unless params[:d1227].between?(1,4)
|
514
|
+
@msg.add_alc( params )
|
515
|
+
|
516
|
+
case (kz - kz%10)/10
|
517
|
+
when 1..4, 6
|
518
|
+
@msg.add_moa( :d5025=> 8, :d5004=> betrag.abs/100.0 )
|
519
|
+
when 5
|
520
|
+
@msg.add_moa( :d5025=> 8, :d5004=> betrag.abs/100.0 )
|
521
|
+
pri_aab.d5125 = 'AAA' if pri_aab # Why?
|
522
|
+
when 7
|
523
|
+
@msg.add_pcd( :d5245=> 3, :d5482=> betrag.abs/10000.0 )
|
524
|
+
when 8
|
525
|
+
@msg.add_rte( :d5419=> 1, :d5420=> betrag.abs/10000.0 )
|
526
|
+
else
|
527
|
+
raise "ALC: Unbekanntes 'Rabatt-Kennzeichen: '#{kz}'"
|
528
|
+
end
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
# Items: Map elsewhere
|
533
|
+
#
|
534
|
+
s_msg[/[12][36]00/].each do |s|
|
535
|
+
map_12_to_325_item( s.descendants_and_self, item_counter, master_data )
|
536
|
+
item_counter += 2
|
537
|
+
end
|
538
|
+
|
539
|
+
# Trailer
|
540
|
+
#
|
541
|
+
uns = @msg.new_segment("UNS")
|
542
|
+
uns.d0081 = 'S'
|
543
|
+
@msg.add(uns)
|
544
|
+
|
545
|
+
# MOA SG50
|
546
|
+
#
|
547
|
+
summe_402, summe_79, summe_77 = 0,0.0, 0
|
548
|
+
# summe_131: siehe oben
|
549
|
+
all_str.each do |s|
|
550
|
+
if s.b_vereinbarung_kz_1 == 2 # Nr. 24
|
551
|
+
summe_402 += s.b_vereinbarung_1
|
552
|
+
end
|
553
|
+
summe_131 += s.nachweisrabatt_gesamt
|
554
|
+
summe_77 += s.nachweis_endbetrag
|
555
|
+
if s.warenwert_kz == 1 # Nr. 11: 1=Warenwert
|
556
|
+
summe_79 += to_value( s.komma_kz, s.warenbetrag_menge )
|
557
|
+
end
|
558
|
+
end
|
559
|
+
@msg.add_moa( :d5025=> 402, :d5004=> summe_402/100.0 ) if summe_402 != 0
|
560
|
+
@msg.add_moa( :d5025=> 131, :d5004=> summe_131/100.0 ) if summe_131 != 0
|
561
|
+
@msg.add_moa( :d5025=> 79, :d5004=> summe_79 )
|
562
|
+
@msg.add_moa( :d5025=> 77, :d5004=> summe_77 /100.0 ) if summe_77 != 0
|
563
|
+
|
564
|
+
# TAX-MOA SG52, only if more than 1 STR record found
|
565
|
+
#
|
566
|
+
all_str.each do |s|
|
567
|
+
@msg.add_tax( :ust_kz=> s.ust_kz, :pos_nr=> s.positions_nr )
|
568
|
+
if s.warenwert_kz == 1 # Nr. 11: 1=Warenwert
|
569
|
+
@msg.add_moa( :d5025=> 79, :d5004=> s.warenbetrag_menge/100.0 )
|
570
|
+
end
|
571
|
+
betrag = s.nachweisrabatt_gesamt + s.skonto
|
572
|
+
@msg.add_moa( :d5025=> 131, :d5004=> betrag/100.0 ) if betrag != 0
|
573
|
+
end if all_str.size > 1
|
574
|
+
|
575
|
+
@p.add @msg, false
|
576
|
+
end
|
577
|
+
|
578
|
+
|
579
|
+
def map_12_to_325_item( segments, item_counter, master_data )
|
580
|
+
# Lookahead / out-of-sequence segments first:
|
581
|
+
ftx_in_item = []
|
582
|
+
segments.find_all{|seg| seg.name=~/[12][36]08/}.each do |seg|
|
583
|
+
ftx = @msg.new_segment("FTX")
|
584
|
+
ftx.d4451 = 'ZZZ'
|
585
|
+
ftx.cC108.a4440[0].value = seg.freitext.strip
|
586
|
+
ftx.d3453 = 'DE'
|
587
|
+
ftx_in_item << ftx
|
588
|
+
end
|
589
|
+
|
590
|
+
s02 = Verkettung02_Felder.new
|
591
|
+
if seg=segments.find{|s| s.name=~/[12][36]02/} # just 0..1 expected
|
592
|
+
s02.ust_prozentsatz = seg.ust_prozentsatz
|
593
|
+
s02.preisschluessel = seg.preisschluessel
|
594
|
+
s02.komma_kz_p = seg.komma_kz_p
|
595
|
+
s02.grundpreis = seg.grundpreis
|
596
|
+
s02.mengenschluessel = seg.mengenschluessel
|
597
|
+
s02.komma_kz_m = seg.komma_kz_m
|
598
|
+
s02.menge = seg.menge
|
599
|
+
s02.empty = false
|
600
|
+
else
|
601
|
+
s02.empty = true
|
602
|
+
end
|
603
|
+
|
604
|
+
# Now do the serial mapping
|
605
|
+
segments.each do |seg|
|
606
|
+
|
607
|
+
seg_id = seg.name
|
608
|
+
seg_id += ' ' + seg.sg_name if seg.sg_name
|
609
|
+
case seg_id
|
610
|
+
when /[12][36]00 SG1/
|
611
|
+
# FIXME: Linear search - consider a hash for fast lookup via ean.
|
612
|
+
s5000 = master_data.find{|s| s.name=='5000' && s.ean==seg.ean}
|
613
|
+
raise "SA 50 fehlt fuer EAN #{seg.ean}, pos_nr=#{seg.positions_nr}" unless s5000
|
614
|
+
|
615
|
+
@msg.add_lin( :d1082=> item_counter, :d7140=> seg.ean)
|
616
|
+
|
617
|
+
# PIA
|
618
|
+
#
|
619
|
+
@msg.add_pia( :d4347=> 1, :d7140=> s5000.artikel_nr, :d7143=> 'SA')
|
620
|
+
|
621
|
+
# IMD
|
622
|
+
#
|
623
|
+
@msg.add_imd( :d7077=> 'C', :d7009=> 'IN', :d7009_3055=> 9)
|
624
|
+
@msg.add_imd( :d7077=> 'A', :d7008_1=> s5000.langtext)
|
625
|
+
|
626
|
+
# QTY
|
627
|
+
#
|
628
|
+
if s02.empty || s02.mengenschluessel == 0 || s02.komma_kz_m == 0
|
629
|
+
mengenschluessel, komma_kz_m, menge =
|
630
|
+
seg.mengenschluessel, seg.komma_kz_m, seg.menge
|
631
|
+
else
|
632
|
+
mengenschluessel, komma_kz_m, menge =
|
633
|
+
s02.mengenschluessel, s02.komma_kz_m, s02.menge
|
634
|
+
end
|
635
|
+
if s02.empty || s02.preisschluessel == 0 || s02.komma_kz_p == 0
|
636
|
+
preisschluessel, komma_kz_p, grundpreis =
|
637
|
+
seg.preisschluessel, seg.komma_kz_p, seg.grundpreis
|
638
|
+
else
|
639
|
+
preisschluessel, komma_kz_p, grundpreis =
|
640
|
+
s02.preisschluessel, s02.komma_kz_p, s02.grundpreis
|
641
|
+
end
|
642
|
+
@msg.add_qty( :d6063=> preisschluessel == 9 ? 192 : 47, # w/o charge?
|
643
|
+
:d6060=> to_value( komma_kz_m, menge ),
|
644
|
+
:qkey=> mengenschluessel )
|
645
|
+
|
646
|
+
# All FTX
|
647
|
+
#
|
648
|
+
ftx_in_item.each {|obj| @msg.add(obj)}
|
649
|
+
|
650
|
+
# MOA
|
651
|
+
#
|
652
|
+
betrag = seg.artikelrabatt_gesamt
|
653
|
+
@msg.add_moa( :d5025=> 131, :d5004=> betrag/100.0 ) if betrag != 0
|
654
|
+
betrag = seg.warenwert
|
655
|
+
@msg.add_moa( :d5025=> 203, :d5004=> betrag/100.0 ) if betrag != 0
|
656
|
+
if seg.b_vereinbarung_kz_2 == 3
|
657
|
+
@msg.add_moa( :d5025=> 204, :d5004=> seg.b_vereinbarung_2/10.0 )
|
658
|
+
end
|
659
|
+
|
660
|
+
# PRI
|
661
|
+
#
|
662
|
+
pri_aab =
|
663
|
+
@msg.add_pri(:d5125=>'AAB', :d5118=>to_value( komma_kz_p,grundpreis),
|
664
|
+
:pkey=>preisschluessel, :qkey=>mengenschluessel )
|
665
|
+
if seg.schluessel_kz == 1
|
666
|
+
@msg.add_pri( :d5125=>'AAE',
|
667
|
+
:d5118=>to_value( seg.komma_kz, seg.sondereintrag ) )
|
668
|
+
# :pkey=>preisschluessel, :qkey=>mengenschluessel)
|
669
|
+
elsif seg.schluessel_kz == 3
|
670
|
+
@msg.add_pri( :d5125=>'AAA',
|
671
|
+
:d5118=>to_value( seg.komma_kz, seg.sondereintrag ) )
|
672
|
+
end
|
673
|
+
|
674
|
+
# RFF-DTM SG30
|
675
|
+
#
|
676
|
+
if seg.b_vereinbarung_kz_2 == 5
|
677
|
+
@msg.add_rff( :d1153=>'AAK', :d1154=> seg.b_vereinbarung_2 )
|
678
|
+
end
|
679
|
+
|
680
|
+
# TAX-MOA
|
681
|
+
#
|
682
|
+
@msg.add_tax( :ust_kz=> seg.umsatzsteuer_kz, :pos_nr=> seg.positions_nr )
|
683
|
+
|
684
|
+
|
685
|
+
# ALC SG39
|
686
|
+
#
|
687
|
+
[[seg.rabatt_kz_1, seg.artikelrabatt_1, 1],
|
688
|
+
[seg.rabatt_kz_2, seg.artikelrabatt_2, 2],
|
689
|
+
[seg.rabatt_kz_3, seg.artikelrabatt_3, 3],
|
690
|
+
[seg.rabatt_kz_4, seg.artikelrabatt_4, 4]].each do |a|
|
691
|
+
kz, betrag, no = a
|
692
|
+
next if kz == 0
|
693
|
+
|
694
|
+
params = {
|
695
|
+
:d5463=> betrag < 0 ? 'A' : 'C',
|
696
|
+
:d7161=> 'DI', :d1227=> kz%10 - 1
|
697
|
+
}
|
698
|
+
params[:d1227] = nil unless params[:d1227].between?(1,4)
|
699
|
+
@msg.add_alc( params )
|
700
|
+
|
701
|
+
case (kz - kz%10)/10
|
702
|
+
when 1..4, 6
|
703
|
+
@msg.add_moa( :d5025=> 8, :d5004=> betrag.abs/100.0 )
|
704
|
+
when 5
|
705
|
+
@msg.add_moa( :d5025=> 8, :d5004=> betrag.abs/100.0 )
|
706
|
+
pri_aab.d5125 = 'AAA' if pri_aab # Why?
|
707
|
+
when 7
|
708
|
+
@msg.add_pcd( :d5245=> 3, :d5482=> betrag.abs/10000.0 )
|
709
|
+
when 8
|
710
|
+
@msg.add_rte( :d5419=> 1, :d5420=> betrag.abs/10000.0 )
|
711
|
+
else
|
712
|
+
raise "ALC: Unbekanntes 'Rabatt-Kennzeichen: '#{kz}'"
|
713
|
+
end
|
714
|
+
end
|
715
|
+
|
716
|
+
# Sub-line info
|
717
|
+
#
|
718
|
+
@msg.add_lin( :d1082=> item_counter+1,
|
719
|
+
:d7140=> s5000.kleinste_ean,
|
720
|
+
:c829_d1082 => item_counter )
|
721
|
+
|
722
|
+
@msg.add_pia( :d4347=> 1, :d7140=> "%04d" % s5000.klassifikation,
|
723
|
+
:d7143=> 'GN')
|
724
|
+
@msg.add_imd( :d7077=> 'C', :d7009=> 'CU', :d7009_3055=> 9)
|
725
|
+
@msg.add_qty( :d6063=> 59, :d6060=> s5000.menge_ean )
|
726
|
+
|
727
|
+
|
728
|
+
when /[12][36]0[28] SG1/
|
729
|
+
# ignored here - handled by lookahead section
|
730
|
+
|
731
|
+
else
|
732
|
+
raise "Segment-Id #{seg_id} hier nicht erwartet!"
|
733
|
+
end
|
734
|
+
end
|
735
|
+
end
|
736
|
+
|
737
|
+
|
738
|
+
def map_15_to_38x( s_msg, master_data )
|
739
|
+
@msg = @p.new_message( @msg_params )
|
740
|
+
item_counter = 1
|
741
|
+
|
742
|
+
# Lookahead / out-of-sequence segments first:
|
743
|
+
#
|
744
|
+
ftx_in_header = []
|
745
|
+
# 08 for SA 12/22, 15/25
|
746
|
+
s_msg[/[12][25]08/].each do |seg|
|
747
|
+
ftx = @msg.new_segment("FTX")
|
748
|
+
ftx.d4451 = 'ZZZ'
|
749
|
+
ftx.cC108.a4440[0].value = seg.freitext.strip
|
750
|
+
ftx.d3453 = 'DE'
|
751
|
+
ftx_in_header << ftx
|
752
|
+
end
|
753
|
+
# 08 for SA 14/24, 17/27
|
754
|
+
s_msg[/[12][47]08/].each do |seg|
|
755
|
+
ftx = @msg.new_segment("FTX")
|
756
|
+
ftx.d4451 = 'SUR'
|
757
|
+
ftx.cC108.a4440[0].value = seg.freitext.strip
|
758
|
+
ftx.d3453 = 'DE'
|
759
|
+
ftx_in_header << ftx
|
760
|
+
end
|
761
|
+
|
762
|
+
s01 = Verkettung01_Felder.new
|
763
|
+
if seg=s_msg[/[12][25]01/].first # 1201, 2201, 1501, 2501
|
764
|
+
s01.v_nad_by = seg.bbn_rechnungsempfaenger
|
765
|
+
s01.v_nad_ds = seg.bbn_warenlieferant
|
766
|
+
s01.v_nad_su_va = seg.ust_ident_nr_lieferant
|
767
|
+
s01.v_nad_su_fc = seg.steuer_nr
|
768
|
+
s01.v_nad_by_va = seg.ust_ident_nr_erwerber
|
769
|
+
s01.ls_a_kz = seg.ls_auftrag_kz
|
770
|
+
s01.ls_a_nr1 = seg.ls_auftrag_nr_1
|
771
|
+
s01.ls_a_nr2 = seg.ls_auftrag_nr_2
|
772
|
+
else
|
773
|
+
s01.ls_a_kz = 0
|
774
|
+
end
|
775
|
+
|
776
|
+
# Naming convention:
|
777
|
+
#
|
778
|
+
# shd = SEDAS header record, e.g. a SA12/22 or a SA15/25
|
779
|
+
# str = SEDAS trailer record, e.g. a SA14/24 or a SA17/27
|
780
|
+
#
|
781
|
+
shd = s_msg[/[12][25]00/].first # Must exist due to SEDAS msg definition!
|
782
|
+
all_str = s_msg[/[12][47]00/] # Expect one per VAT rate, one at least
|
783
|
+
|
784
|
+
ls_auftrag_array = [[shd.ls_auftrag_kz_1, shd.ls_auftrag_nr_1, 1],
|
785
|
+
[shd.ls_auftrag_kz_2, shd.ls_auftrag_nr_2, 2],
|
786
|
+
[shd.ls_auftrag_kz_3, shd.ls_auftrag_nr_3, 3],
|
787
|
+
[shd.ls_auftrag_kz_4, shd.ls_auftrag_nr_4, 4],
|
788
|
+
[shd.ls_auftrag_kz_5, shd.ls_auftrag_nr_5, 5]]
|
789
|
+
|
790
|
+
summe_77 = all_str.inject(0){|sum, s| sum + s.endbetrag}
|
791
|
+
summe_131 = 0 # Evtl. erst Skonto addieren, siehe ALC (EAB)
|
792
|
+
vz = summe_77<=>0 # Vorzeichen, Unterscheidung Rechnung(+1)/Gutschrift(-1)
|
793
|
+
|
794
|
+
# BGM
|
795
|
+
#
|
796
|
+
bgm = @msg.new_segment("BGM")
|
797
|
+
bgm.cC002.d1001 = (vz < 0) ? 381 : 380
|
798
|
+
bgm.cC106.d1004 = shd.beleg_nr
|
799
|
+
bgm.d1225 = 9
|
800
|
+
@msg.add(bgm)
|
801
|
+
|
802
|
+
# All DTM
|
803
|
+
#
|
804
|
+
@msg.add_dtm(:d2005=> 137, :digits=> 5, :d2380=>shd.datum_rechnung)
|
805
|
+
if shd.lieferdatum==0
|
806
|
+
warn "Re-Nr #{shd.beleg_nr}, Pos-Nr #{shd.positions_nr}: " +
|
807
|
+
"Lieferdatum fehlt - verwende Belegdatum!"
|
808
|
+
@msg.add_dtm(:d2005=> 35, :d2380=> shd.datum_rechnung)
|
809
|
+
else
|
810
|
+
@msg.add_dtm(:d2005=> 35, :d2380=> shd.lieferdatum)
|
811
|
+
end
|
812
|
+
|
813
|
+
[
|
814
|
+
[shd.ls_auftrag_kz, shd.ls_auftrag_nr, shd.auftrags_nr_besteller, 1],
|
815
|
+
[s01.ls_a_kz, s01.ls_a_nr1, s01.ls_a_nr2, 2]
|
816
|
+
].each do |a|
|
817
|
+
kz, nr1, nr2, no = a
|
818
|
+
next unless kz==2 # Lieferdatum von-bis (0JJMMTT)
|
819
|
+
dt = if nr1.is_a? String
|
820
|
+
@curr_year[0,2]+nr1[1,6]+@curr_year[0,2]+nr2[1,6]
|
821
|
+
else
|
822
|
+
@curr_year[0,2]+"%06d" % nr1 + @curr_year[0,2]+"%06d" % nr2
|
823
|
+
end
|
824
|
+
@msg.add_dtm( :d2005=>35, :d2380=>dt, :d2379=>718 ) # CCYYMMDD-CCYYMMDD
|
825
|
+
end
|
826
|
+
|
827
|
+
# ALI
|
828
|
+
#
|
829
|
+
# Anmerkung 18:
|
830
|
+
if shd.b_vereinbarung_kz_1==6 || shd.b_vereinbarung_kz_2==6
|
831
|
+
ali = @msg.new_segment("ALI")
|
832
|
+
bgm.a4183[0].value = 15
|
833
|
+
@msg.add ali
|
834
|
+
end
|
835
|
+
# FIXME: Trap case "b_vereinbarung_kz_x != 1 or 6
|
836
|
+
|
837
|
+
# All FTX
|
838
|
+
#
|
839
|
+
ftx_in_header.each {|obj| @msg.add(obj)}
|
840
|
+
|
841
|
+
# SG1: RFF-DTM
|
842
|
+
#
|
843
|
+
case q=shd.reli_zahlungsempfaenger_kz # Nr. 2, Anmerkung 17
|
844
|
+
when 0 # empty - skip
|
845
|
+
when 1
|
846
|
+
@msg.add_rff( :d1153=>'ABO', :d1154=> shd.rz_eintrag_1 )
|
847
|
+
@msg.add_dtm( :d2005=> 171, :d2380=> shd.rz_eintrag_2 )
|
848
|
+
when 2
|
849
|
+
@msg.add_rff( :d1153=>'ABO', :d1154=> shd.rz_eintrag_1 )
|
850
|
+
when 6
|
851
|
+
@msg.add_rff( :d1153=>'IV', :d1154=> shd.rz_eintrag_1 )
|
852
|
+
@msg.add_dtm( :d2005=> 171, :d2380=> shd.rz_eintrag_2 )
|
853
|
+
when 7
|
854
|
+
@msg.add_rff( :d1153=>'IV', :d1154=> shd.rz_eintrag_1 )
|
855
|
+
else
|
856
|
+
raise "S.-Rechnung: 'Kennzeichen' ungueltig: #{q}"
|
857
|
+
end
|
858
|
+
|
859
|
+
[
|
860
|
+
[shd.ls_auftrag_kz, shd.ls_auftrag_nr, shd.auftrags_nr_besteller, 1],
|
861
|
+
[s01.ls_a_kz, s01.ls_a_nr1, s01.ls_a_nr2, 2]
|
862
|
+
].each do |a|
|
863
|
+
kz, nr1, nr2, no = a
|
864
|
+
case kz # Nr. 3, Anmerkung 1
|
865
|
+
when nil # treat as empty, should not occur
|
866
|
+
$log.warn("ls_auftrag_kz (#{no}) fehlt!")
|
867
|
+
when 0 # empty - skip
|
868
|
+
when 1
|
869
|
+
@msg.add_rff( :d1153=>'DQ', :d1154=> nr1 )
|
870
|
+
@msg.add_rff( :d1153=>'ON', :d1154=> nr2 )
|
871
|
+
when 2 # skip - treated earlier (DTM)
|
872
|
+
when 3
|
873
|
+
@msg.add_rff( :d1153=>'ON', :d1154=> nr1 )
|
874
|
+
when 4
|
875
|
+
@msg.add_rff( :d1153=>'DQ', :d1154=> nr1 )
|
876
|
+
else
|
877
|
+
raise "Kennzeichen LS/Auftrag (#{no}) ungueltig (Anm. 1): '#{kz}'"
|
878
|
+
end
|
879
|
+
end
|
880
|
+
|
881
|
+
ls_auftrag_array.each do |a|
|
882
|
+
kz, nr1, no = a
|
883
|
+
case kz # Nr. 3, Anmerkung 3
|
884
|
+
when 0 # empty - skip
|
885
|
+
when 5 # Lieferscheinnummer
|
886
|
+
@msg.add_rff( :d1153=>'DQ', :d1154=> nr1 )
|
887
|
+
when 6 # Auftragsnummer
|
888
|
+
@msg.add_rff( :d1153=>'ON', :d1154=> nr1 )
|
889
|
+
else
|
890
|
+
raise "Kennzeichen LS/Auftrag (#{no}) ungueltig (Anm. 3): '#{kz}'"
|
891
|
+
end
|
892
|
+
end # each
|
893
|
+
|
894
|
+
# SG2: NAD-RFF
|
895
|
+
#
|
896
|
+
@msg.add_nad( :d3035=>'SU', :d3039=> shd.bbn_lieferant )
|
897
|
+
@msg.add_rff( :d1153=>'VA', :d1154=> s01.v_nad_su_va )
|
898
|
+
@msg.add_rff( :d1153=>'FC', :d1154=> s01.v_nad_su_fc )
|
899
|
+
|
900
|
+
bbn = s01.v_nad_by
|
901
|
+
bbn = shd.bbn_rechnungsempfaenger if bbn.nil? || bbn == 0
|
902
|
+
@msg.add_nad( :d3035=>'BY', :d3039=> bbn )
|
903
|
+
@msg.add_rff( :d1153=>'VA', :d1154=> s01.v_nad_by_va )
|
904
|
+
# Anmerkung 18:
|
905
|
+
@msg.add_rff( :d1153=>'YC1',:d1154=> shd.b_vereinbarung_1 ) if
|
906
|
+
shd.b_vereinbarung_kz_1 == 1
|
907
|
+
@msg.add_rff( :d1153=>'YC1',:d1154=> shd.b_vereinbarung_2 ) if
|
908
|
+
shd.b_vereinbarung_kz_2 == 1
|
909
|
+
|
910
|
+
case kz=shd.warenempfaenger_kz
|
911
|
+
when 1
|
912
|
+
bbn = shd.bbn_warenempfaenger.to_s + "%06d" % shd.interne_nr
|
913
|
+
@msg.add_nad( :d3035=>'DP', :d3039=> bbn )
|
914
|
+
when 2
|
915
|
+
s51 = master_data['51'].find{|s| s.refpos_nr == shd.positions_nr}
|
916
|
+
raise "Sorry - SA51 fehlt fuer pos_nr={shd.positions_nr}" unless s51
|
917
|
+
@msg.add_nad( :d3035=>'DP', :d3036_1=> s51.name_warenempfaenger,
|
918
|
+
:d3164=> s51.ort,
|
919
|
+
:d3042_1=> s51.strasse_postfach,
|
920
|
+
:d3251=> s51.plz_1==0 ? s51.plz_2.strip : s51.plz_1 )
|
921
|
+
# @msg.add_rff( :d1153=>'IA', :d1154=> shd.interne_nr )
|
922
|
+
when 3
|
923
|
+
bbn = shd.bbn_warenempfaenger
|
924
|
+
@msg.add_nad( :d3035=>'DP', :d3039=> bbn )
|
925
|
+
else
|
926
|
+
raise "Warenempfaenger-bbs: 'Kennzeichen' ungueltig: '#{kz}'"
|
927
|
+
end
|
928
|
+
|
929
|
+
# TAX-MOA SG6
|
930
|
+
#
|
931
|
+
all_str.each {|s| @msg.add_tax( :ust_kz=> s.ust_kz, :pos_nr=> s.positions_nr ) }
|
932
|
+
|
933
|
+
# ALC-MOA SG16
|
934
|
+
#
|
935
|
+
all_str.each do |s|
|
936
|
+
kz, betrag = s.fracht_verpackung_kz, s.frachtbelastung
|
937
|
+
next if kz == 0
|
938
|
+
params = {}
|
939
|
+
params[:d5463] = betrag > 0 ? 'C' : 'A'
|
940
|
+
params[:d7161] = case kz
|
941
|
+
when 1: 'FC'
|
942
|
+
when 2: 'PC'
|
943
|
+
when 3: 'IN'
|
944
|
+
when 4,5,6,7: 'SH'
|
945
|
+
else raise "'Fracht/Verpackungs-Kennzeichen' ungueltig: '#{kz}'"
|
946
|
+
end
|
947
|
+
@msg.add_alc( params )
|
948
|
+
@msg.add_moa( :d5025=> 8, :d5004=> betrag.abs/100.0 )
|
949
|
+
end
|
950
|
+
|
951
|
+
all_str.each do |s|
|
952
|
+
betrag = s.skonto
|
953
|
+
next if betrag == 0
|
954
|
+
@msg.add_alc( :d5463=> 'A', :d1227=> 1, :d7161=> 'EAB' )
|
955
|
+
@msg.add_moa( :d5025=> 8, :d5004=> betrag.abs/100.0 )
|
956
|
+
summe_131 += betrag
|
957
|
+
warn "Skonto positiv: #{betrag}, pos_nr=#{s.positions_nr}" if vz*betrag>0
|
958
|
+
end
|
959
|
+
|
960
|
+
all_str.each do |s| # Also see code at item level, SG39
|
961
|
+
[[s.rabatt_kz_1, s.rechnungsrabatt_1, 1],
|
962
|
+
[s.rabatt_kz_2, s.rechnungsrabatt_2, 2],
|
963
|
+
[s.rabatt_kz_3, s.rechnungsrabatt_3, 3],
|
964
|
+
[s.rabatt_kz_4, s.rechnungsrabatt_4, 4]].each do |a|
|
965
|
+
kz, betrag, no = a
|
966
|
+
next if kz == 0
|
967
|
+
|
968
|
+
params = {
|
969
|
+
:d5463=> betrag < 0 ? 'A' : 'C',
|
970
|
+
:d7161=> 'DI', :d1227=> kz%10 - 1
|
971
|
+
}
|
972
|
+
params[:d1227] = nil unless params[:d1227].between?(1,4)
|
973
|
+
@msg.add_alc( params )
|
974
|
+
|
975
|
+
case (kz - kz%10)/10
|
976
|
+
when 1..4, 6
|
977
|
+
@msg.add_moa( :d5025=> 8, :d5004=> betrag.abs/100.0 )
|
978
|
+
when 5
|
979
|
+
@msg.add_moa( :d5025=> 8, :d5004=> betrag.abs/100.0 )
|
980
|
+
pri_aab.d5125 = 'AAA' if pri_aab # Why?
|
981
|
+
when 7
|
982
|
+
@msg.add_pcd( :d5245=> 3, :d5482=> betrag.abs/10000.0 )
|
983
|
+
when 8
|
984
|
+
@msg.add_rte( :d5419=> 1, :d5420=> betrag.abs/10000.0 )
|
985
|
+
else
|
986
|
+
raise "ALC: Unbekanntes 'Rabatt-Kennzeichen: '#{kz}'"
|
987
|
+
end
|
988
|
+
end
|
989
|
+
end
|
990
|
+
|
991
|
+
# Items: Map elsewhere
|
992
|
+
#
|
993
|
+
s_msg[/[12][36]00/].each do |s|
|
994
|
+
map_16_to_38x_item( s.descendants_and_self, item_counter,
|
995
|
+
master_data, vz )
|
996
|
+
item_counter += 2
|
997
|
+
end
|
998
|
+
|
999
|
+
# Trailer
|
1000
|
+
#
|
1001
|
+
uns = @msg.new_segment("UNS")
|
1002
|
+
uns.d0081 = 'S'
|
1003
|
+
@msg.add(uns)
|
1004
|
+
|
1005
|
+
# MOA SG50
|
1006
|
+
#
|
1007
|
+
summe_402, summe_124, summe_79 = 0, 0, 0
|
1008
|
+
# summe_77, summe_131: siehe oben
|
1009
|
+
all_str.each do |s|
|
1010
|
+
if s.b_vereinbarung_kz_1 == 2 # Nr. 27
|
1011
|
+
summe_402 += s.b_vereinbarung_1
|
1012
|
+
end
|
1013
|
+
# FIXME: Really try to add both occurrences?
|
1014
|
+
if s.b_vereinbarung_kz_2 == 2 # Nr. 27
|
1015
|
+
summe_402 += s.b_vereinbarung_2
|
1016
|
+
end
|
1017
|
+
summe_124 += s.umsatzsteuer
|
1018
|
+
summe_131 += s.rechnungsrabatt_gesamt
|
1019
|
+
summe_79 += s.warenbetrag
|
1020
|
+
# summe_77 += s.endbetrag # See beginning
|
1021
|
+
end
|
1022
|
+
@msg.add_moa( :d5025=> 402, :d5004=> vz*summe_402/100.0 ) if summe_402 != 0
|
1023
|
+
@msg.add_moa( :d5025=> 131, :d5004=> vz*summe_131/100.0 ) if summe_131 != 0
|
1024
|
+
@msg.add_moa( :d5025=> 125, :d5004=> vz*(summe_77 - summe_124)/100.0 )
|
1025
|
+
@msg.add_moa( :d5025=> 124, :d5004=> vz*summe_124/100.0 ) if summe_124 != 0
|
1026
|
+
@msg.add_moa( :d5025=> 79, :d5004=> vz*summe_79 /100.0 ) if summe_79 != 0
|
1027
|
+
@msg.add_moa( :d5025=> 77, :d5004=> vz*summe_77 /100.0 ) if summe_77 != 0
|
1028
|
+
|
1029
|
+
# TAX-MOA SG52, only if more than 1 trailer record found
|
1030
|
+
#
|
1031
|
+
all_str.each do |s|
|
1032
|
+
if s.ust_kz != 0 # Nr. 9
|
1033
|
+
@msg.add_tax( :ust_kz=> s.ust_kz, :pos_nr=> s.positions_nr )
|
1034
|
+
@msg.add_moa( :d5025=> 79, :d5004=> vz*s.warenbetrag/100.0 )
|
1035
|
+
@msg.add_moa( :d5025=> 124, :d5004=> vz*s.umsatzsteuer/100.0 )
|
1036
|
+
betrag = s.rechnungsrabatt_gesamt + s.skonto
|
1037
|
+
@msg.add_moa( :d5025=> 131, :d5004=> vz*betrag/100.0 ) if betrag != 0
|
1038
|
+
end
|
1039
|
+
end if all_str.size > 1
|
1040
|
+
|
1041
|
+
@p.add @msg, false
|
1042
|
+
end
|
1043
|
+
|
1044
|
+
|
1045
|
+
def map_16_to_38x_item( segments, item_counter, master_data, vz )
|
1046
|
+
# Lookahead / out-of-sequence segments first:
|
1047
|
+
ftx_in_item = []
|
1048
|
+
segments.find_all{|seg| seg.name=~/[12][36]08/}.each do |seg|
|
1049
|
+
ftx = @msg.new_segment("FTX")
|
1050
|
+
ftx.d4451 = 'ZZZ'
|
1051
|
+
ftx.cC108.a4440[0].value = seg.freitext.strip
|
1052
|
+
ftx.d3453 = 'DE'
|
1053
|
+
ftx_in_item << ftx
|
1054
|
+
end
|
1055
|
+
|
1056
|
+
s02 = Verkettung02_Felder.new
|
1057
|
+
if seg=segments.find{|s| s.name=~/[12][36]02/} # just 0..1 expected
|
1058
|
+
s02.ust_prozentsatz = seg.ust_prozentsatz
|
1059
|
+
s02.preisschluessel = seg.preisschluessel
|
1060
|
+
s02.komma_kz_p = seg.komma_kz_p
|
1061
|
+
s02.grundpreis = seg.grundpreis
|
1062
|
+
s02.mengenschluessel = seg.mengenschluessel
|
1063
|
+
s02.komma_kz_m = seg.komma_kz_m
|
1064
|
+
s02.menge = seg.menge
|
1065
|
+
s02.empty = false
|
1066
|
+
else
|
1067
|
+
s02.empty = true
|
1068
|
+
end
|
1069
|
+
|
1070
|
+
# Now do the serial mapping
|
1071
|
+
segments.each do |seg|
|
1072
|
+
|
1073
|
+
seg_id = seg.name
|
1074
|
+
seg_id += ' ' + seg.sg_name if seg.sg_name
|
1075
|
+
case seg_id
|
1076
|
+
when /[12][36]00 SG1/
|
1077
|
+
# FIXME: Linear search - consider a hash for fast lookup via ean.
|
1078
|
+
s5000 = master_data.find{|s| s.name=='5000' && s.ean==seg.ean}
|
1079
|
+
raise "SA 50 fehlt fuer EAN #{seg.ean}, pos_nr=#{seg.positions_nr}" unless s5000
|
1080
|
+
|
1081
|
+
@msg.add_lin( :d1082=> item_counter, :d7140=> seg.ean)
|
1082
|
+
|
1083
|
+
# PIA
|
1084
|
+
#
|
1085
|
+
@msg.add_pia( :d4347=> 1, :d7140=> s5000.artikel_nr, :d7143=> 'SA')
|
1086
|
+
|
1087
|
+
# IMD
|
1088
|
+
#
|
1089
|
+
@msg.add_imd( :d7077=> 'C', :d7009=> 'IN', :d7009_3055=> 9)
|
1090
|
+
@msg.add_imd( :d7077=> 'A', :d7008_1=> s5000.langtext)
|
1091
|
+
|
1092
|
+
# QTY
|
1093
|
+
#
|
1094
|
+
if s02.empty || s02.mengenschluessel == 0 || s02.komma_kz_m == 0
|
1095
|
+
mengenschluessel, komma_kz_m, menge =
|
1096
|
+
seg.mengenschluessel, seg.komma_kz_m, seg.menge
|
1097
|
+
else
|
1098
|
+
mengenschluessel, komma_kz_m, menge =
|
1099
|
+
s02.mengenschluessel, s02.komma_kz_m, s02.menge
|
1100
|
+
end
|
1101
|
+
if s02.empty || s02.preisschluessel == 0 || s02.komma_kz_p == 0
|
1102
|
+
preisschluessel, komma_kz_p, grundpreis =
|
1103
|
+
seg.preisschluessel, seg.komma_kz_p, seg.grundpreis
|
1104
|
+
else
|
1105
|
+
preisschluessel, komma_kz_p, grundpreis =
|
1106
|
+
s02.preisschluessel, s02.komma_kz_p, s02.grundpreis
|
1107
|
+
end
|
1108
|
+
@msg.add_qty( :d6063=> preisschluessel == 9 ? 192 : 47, # w/o charge?
|
1109
|
+
:d6060=> to_value( komma_kz_m, vz*menge ),
|
1110
|
+
:qkey=> mengenschluessel )
|
1111
|
+
|
1112
|
+
# All FTX
|
1113
|
+
#
|
1114
|
+
ftx_in_item.each {|obj| @msg.add(obj)}
|
1115
|
+
|
1116
|
+
# MOA
|
1117
|
+
#
|
1118
|
+
betrag = seg.artikelrabatt_gesamt
|
1119
|
+
@msg.add_moa( :d5025=> 131, :d5004=> vz*betrag/100.0 ) if betrag != 0
|
1120
|
+
betrag = seg.warenwert
|
1121
|
+
@msg.add_moa( :d5025=> 203, :d5004=> vz*betrag/100.0 ) if betrag != 0
|
1122
|
+
if seg.b_vereinbarung_kz_2 == 3
|
1123
|
+
@msg.add_moa( :d5025=> 204, :d5004=> vz*seg.b_vereinbarung_2/10.0 )
|
1124
|
+
end
|
1125
|
+
|
1126
|
+
# PRI
|
1127
|
+
#
|
1128
|
+
pri_aab =
|
1129
|
+
@msg.add_pri(:d5125=>'AAB', :d5118=>to_value( komma_kz_p,grundpreis),
|
1130
|
+
:pkey=>preisschluessel, :qkey=>mengenschluessel )
|
1131
|
+
if seg.schluessel_kz == 1
|
1132
|
+
@msg.add_pri( :d5125=>'AAE',
|
1133
|
+
:d5118=>to_value( seg.komma_kz, seg.sondereintrag ) )
|
1134
|
+
# :pkey=>preisschluessel, :qkey=>mengenschluessel)
|
1135
|
+
elsif seg.schluessel_kz == 3
|
1136
|
+
@msg.add_pri( :d5125=>'AAA',
|
1137
|
+
:d5118=>to_value( seg.komma_kz, seg.sondereintrag ) )
|
1138
|
+
end
|
1139
|
+
|
1140
|
+
# RFF-DTM SG30
|
1141
|
+
#
|
1142
|
+
if seg.b_vereinbarung_kz_2 == 5
|
1143
|
+
@msg.add_rff( :d1153=>'AAK', :d1154=> seg.b_vereinbarung_2 )
|
1144
|
+
end
|
1145
|
+
|
1146
|
+
# TAX-MOA
|
1147
|
+
#
|
1148
|
+
@msg.add_tax( :ust_kz=> seg.umsatzsteuer_kz, :pos_nr=> seg.positions_nr )
|
1149
|
+
|
1150
|
+
|
1151
|
+
# ALC SG39
|
1152
|
+
#
|
1153
|
+
[[seg.rabatt_kz_1, seg.artikelrabatt_1, 1],
|
1154
|
+
[seg.rabatt_kz_2, seg.artikelrabatt_2, 2],
|
1155
|
+
[seg.rabatt_kz_3, seg.artikelrabatt_3, 3],
|
1156
|
+
[seg.rabatt_kz_4, seg.artikelrabatt_4, 4]].each do |a|
|
1157
|
+
kz, betrag, no = a
|
1158
|
+
next if kz == 0
|
1159
|
+
|
1160
|
+
params = {
|
1161
|
+
:d5463=> betrag < 0 ? 'A' : 'C',
|
1162
|
+
:d7161=> 'DI', :d1227=> kz%10 - 1
|
1163
|
+
}
|
1164
|
+
params[:d1227] = nil unless params[:d1227].between?(1,4)
|
1165
|
+
@msg.add_alc( params )
|
1166
|
+
|
1167
|
+
case (kz - kz%10)/10
|
1168
|
+
when 1..4, 6
|
1169
|
+
@msg.add_moa( :d5025=> 8, :d5004=> betrag.abs/100.0 )
|
1170
|
+
when 5
|
1171
|
+
@msg.add_moa( :d5025=> 8, :d5004=> betrag.abs/100.0 )
|
1172
|
+
pri_aab.d5125 = 'AAA' if pri_aab # Why?
|
1173
|
+
when 7
|
1174
|
+
@msg.add_pcd( :d5245=> 3, :d5482=> betrag.abs/10000.0 )
|
1175
|
+
when 8
|
1176
|
+
@msg.add_rte( :d5419=> 1, :d5420=> betrag.abs/10000.0 )
|
1177
|
+
else
|
1178
|
+
raise "ALC: Unbekanntes 'Rabatt-Kennzeichen: '#{kz}'"
|
1179
|
+
end
|
1180
|
+
end
|
1181
|
+
|
1182
|
+
# Sub-line info
|
1183
|
+
#
|
1184
|
+
@msg.add_lin( :d1082=> item_counter+1,
|
1185
|
+
:d7140=> s5000.kleinste_ean,
|
1186
|
+
:c829_d1082 => item_counter )
|
1187
|
+
|
1188
|
+
@msg.add_pia( :d4347=> 1, :d7140=> "%04d" % s5000.klassifikation,
|
1189
|
+
:d7143=> 'GN')
|
1190
|
+
@msg.add_imd( :d7077=> 'C', :d7009=> 'CU', :d7009_3055=> 9)
|
1191
|
+
@msg.add_qty( :d6063=> 59, :d6060=> s5000.menge_ean )
|
1192
|
+
|
1193
|
+
|
1194
|
+
when /[12][36]0[2468] SG1/
|
1195
|
+
# ignored here - handled by lookahead section
|
1196
|
+
|
1197
|
+
else
|
1198
|
+
raise "Segment-Id #{seg_id} hier nicht erwartet!"
|
1199
|
+
end
|
1200
|
+
end
|
1201
|
+
end
|
1202
|
+
|
1203
|
+
|
1204
|
+
def map_29_to_393( s_msg )
|
1205
|
+
@msg = @p.new_message( @msg_params )
|
1206
|
+
|
1207
|
+
raise "Verkettung 01 zu SA29 nicht unterstuetzt - sorry" unless s_msg['2901'].empty?
|
1208
|
+
raise "Verkettung 02 zu SA29 nicht unterstuetzt - sorry" unless s_msg['2902'].empty?
|
1209
|
+
|
1210
|
+
all_s29 = s_msg['2900']
|
1211
|
+
s29 = all_s29.first # Must exist due to SEDAS msg definition!
|
1212
|
+
|
1213
|
+
bgm = @msg.new_segment("BGM")
|
1214
|
+
bgm.cC002.d1001 = 393
|
1215
|
+
raise "Erste SA29 muss eine 'Rechnungslistennummer' enthalten!" unless s29.reli_kz == 2
|
1216
|
+
bgm.cC106.d1004 = s29.nummer
|
1217
|
+
bgm.d1225 = 9
|
1218
|
+
@msg.add(bgm)
|
1219
|
+
|
1220
|
+
@msg.add_dtm(:d2005=> 137, :digits=> 5, :d2380=>s29.datum_reli)
|
1221
|
+
|
1222
|
+
# SG1: RFF-DTM
|
1223
|
+
#
|
1224
|
+
if (nr=s29.abkommen_nr) != 0
|
1225
|
+
@msg.add_rff( :d1153=>'CT', :d1154=> nr )
|
1226
|
+
end
|
1227
|
+
|
1228
|
+
# SG2: NAD group
|
1229
|
+
#
|
1230
|
+
@msg.add_nad( :d3035=>'SU', :d3039=> s29.bbn_lieferant )
|
1231
|
+
@msg.add_nad( :d3035=>'BY', :d3039=> s29.bbn_rechnungslistenempfaenger )
|
1232
|
+
@msg.add_nad( :d3035=>'PE', :d3039=> s29.bbn_zahlungsempfaenger )
|
1233
|
+
@msg.add_nad( :d3035=>'PR', :d3039=> s29.bbn_zahlungsleistender )
|
1234
|
+
|
1235
|
+
|
1236
|
+
# TAX-MOA SG6
|
1237
|
+
#
|
1238
|
+
@msg.add_tax( :ust_kz=> s29.ust_kz, :pos_nr=> s29.positions_nr )
|
1239
|
+
# Just first occurrence of SA29 ok?
|
1240
|
+
|
1241
|
+
# PAT-DTM SG8
|
1242
|
+
#
|
1243
|
+
if (vdat=s29.valutadatum) != 0
|
1244
|
+
@msg.add_pat( :d4279=> 3 )
|
1245
|
+
@msg.add_dtm( :d2005=> 209, :d2380=> vdat )
|
1246
|
+
end
|
1247
|
+
|
1248
|
+
|
1249
|
+
# Trailer
|
1250
|
+
#
|
1251
|
+
uns = @msg.new_segment("UNS")
|
1252
|
+
uns.d0081 = 'S'
|
1253
|
+
@msg.add(uns)
|
1254
|
+
|
1255
|
+
# MOA SG50
|
1256
|
+
#
|
1257
|
+
|
1258
|
+
summe_124, summe_125, summe_86 = summe_9 = 0, 0, 0, 0
|
1259
|
+
all_s29.each do |s|
|
1260
|
+
summe_124 += s.umsatzsteuer
|
1261
|
+
summe_86 += s.endbetrag
|
1262
|
+
summe_9 += s.zahlbetrag
|
1263
|
+
end
|
1264
|
+
@msg.add_moa( :d5025=> 86, :d5004=> summe_86 /100.0 )
|
1265
|
+
@msg.add_moa( :d5025=> 9, :d5004=> summe_9 /100.0 )
|
1266
|
+
@msg.add_moa( :d5025=> 124, :d5004=> summe_124/100.0 )
|
1267
|
+
@msg.add_moa( :d5025=> 125, :d5004=> (summe_86 - summe_124)/100.0 )
|
1268
|
+
|
1269
|
+
|
1270
|
+
# TAX-MOA SG52, only if more than 1 S29 record found
|
1271
|
+
#
|
1272
|
+
all_s29.each do |s|
|
1273
|
+
@msg.add_tax( :ust_kz=> s.ust_kz, :pos_nr=> s.positions_nr )
|
1274
|
+
@msg.add_moa( :d5025=> 124, :d5004=> s.umsatzsteuer/100.0 )
|
1275
|
+
@msg.add_moa( :d5025=> 125, :d5004=> (s.zahlbetrag - s.umsatzsteuer)/100.0 )
|
1276
|
+
@msg.add_moa( :d5025=> 86, :d5004=> s.endbetrag/100.0 )
|
1277
|
+
end if all_s29.size > 1
|
1278
|
+
|
1279
|
+
@p.add @msg
|
1280
|
+
end
|
1281
|
+
|
1282
|
+
|
1283
|
+
def initialize(src, dest)
|
1284
|
+
@msg = nil
|
1285
|
+
@with_ung = false
|
1286
|
+
@s = src
|
1287
|
+
@ic = dest
|
1288
|
+
@p = @ic # Current parent of a message - either the interchange or a group
|
1289
|
+
@msg_params = {
|
1290
|
+
:msg_type => 'INVOIC',
|
1291
|
+
:version => 'D',
|
1292
|
+
:release => '01B',
|
1293
|
+
:resp_agency => 'UN',
|
1294
|
+
:assigned_code => 'EAN010'
|
1295
|
+
}
|
1296
|
+
@curr_year = Time.now.year.to_s
|
1297
|
+
end
|
1298
|
+
|
1299
|
+
|
1300
|
+
def go
|
1301
|
+
map_00_to_unb(@s.header)
|
1302
|
+
@s.each do |grp|
|
1303
|
+
map_01_to_ung(grp.header) if self.with_ung
|
1304
|
+
master_data = grp.find {|msg| msg.name=='50'}
|
1305
|
+
grp.each do |msg|
|
1306
|
+
case msg.name
|
1307
|
+
when '12', '22'
|
1308
|
+
map_12_to_325( msg, master_data )
|
1309
|
+
when '15', '25'
|
1310
|
+
map_15_to_38x( msg, master_data )
|
1311
|
+
when '29'
|
1312
|
+
map_29_to_393( msg )
|
1313
|
+
when '50'
|
1314
|
+
# Skip master data
|
1315
|
+
else
|
1316
|
+
raise "SA#{msg.name} nicht unterstuetzt - sorry"
|
1317
|
+
end
|
1318
|
+
end
|
1319
|
+
end
|
1320
|
+
end
|
1321
|
+
|
1322
|
+
|
1323
|
+
def validate
|
1324
|
+
@ic.validate
|
1325
|
+
end
|
1326
|
+
|
1327
|
+
def write(hnd)
|
1328
|
+
@ic.write(hnd)
|
1329
|
+
end
|
1330
|
+
end
|
1331
|
+
|
1332
|
+
|
1333
|
+
#
|
1334
|
+
# MAIN
|
1335
|
+
#
|
1336
|
+
|
1337
|
+
$log = Logger.new(STDERR)
|
1338
|
+
$log.level = Logger::INFO
|
1339
|
+
$log.datetime_format = "%H:%M:%S"
|
1340
|
+
|
1341
|
+
params = {
|
1342
|
+
:show_una => true,
|
1343
|
+
:charset => 'UNOC',
|
1344
|
+
:version => 3,
|
1345
|
+
:interchange_control_reference => Time.now.to_f.to_s[0...14] ,
|
1346
|
+
# :application_reference => 'EANCOM' ,
|
1347
|
+
# :output_mode => :verbatim,
|
1348
|
+
# :acknowledgment_request => true,
|
1349
|
+
:interchange_agreement_id => 'EANCOM'+'' , # your ref here!
|
1350
|
+
:test_indicator => 1,
|
1351
|
+
}
|
1352
|
+
ic = EDI::E::Interchange.new( params )
|
1353
|
+
|
1354
|
+
|
1355
|
+
with_ung = false
|
1356
|
+
|
1357
|
+
while ARGV[0] =~ /^-(\w)/
|
1358
|
+
opt = ARGV.shift
|
1359
|
+
case $1
|
1360
|
+
when 'v' # verbose mode - here: use formatted output
|
1361
|
+
ic.output_mode = :indented
|
1362
|
+
when 'g'
|
1363
|
+
with_ung = true
|
1364
|
+
else
|
1365
|
+
raise "Option nicht zulaessig: #{opt}"
|
1366
|
+
end
|
1367
|
+
end
|
1368
|
+
|
1369
|
+
$log.info "Input einlesen..."
|
1370
|
+
sedas_ic = EDI::S::Interchange.parse(File.open(ARGV[0], 'r'), false)
|
1371
|
+
$log.info "Input validieren..."
|
1372
|
+
sedas_ic.validate
|
1373
|
+
$log.info "Zuordnen..."
|
1374
|
+
map = SEDAS_to_EANCOM02_Map_INVOIC.new( sedas_ic, ic )
|
1375
|
+
#
|
1376
|
+
# Add UNG/UNE if there is more than one group per file
|
1377
|
+
#
|
1378
|
+
map.with_ung = (sedas_ic.size > 1) # with_ung
|
1379
|
+
map.go
|
1380
|
+
$log.info "Output validieren..."
|
1381
|
+
ic.validate
|
1382
|
+
$log.info "Ergebnis schreiben..."
|
1383
|
+
$stdout.write ic
|
1384
|
+
$log.info "Fertig."
|
1385
|
+
# ic.inspect
|